Skip to content

Commit

Permalink
Usage of AWS SSM for keyfile
Browse files Browse the repository at this point in the history
  • Loading branch information
kompotkot committed Jan 29, 2024
1 parent 16f67a6 commit b992386
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 194 deletions.
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,24 +279,30 @@ With configuration file you can specify list of signers and sign drops with chos
"access_resource_id": "<access_brood_resource_uuid>",
"signers": [
{
"keyfile_path": "dev.json",
"password": "password.txt",
"password_type": "text_file"
"keyfile": "<path_to_account_keystore_JSON_file>",
"keyfile_type": "file",
"password": "KEYFILE_PASSWORD_ENVIRONMENT_VARIABLE",
"password_type": "env_var"
}
]
}
```

Config also could be generated with command:
Supported keyfile types:

```bash
waggle server configure --keyfile dev.json --outfile config.json --password-type text_file
```
- aws_secret (base64)
- env_var
- file

Supported password types:

- aws_secret
- env_var
- plaintext
- file

Run server:

```bash
waggle server run --host 0.0.0.0 --config config.json
```

Fetch
96 changes: 6 additions & 90 deletions cmd.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"bytes"
"encoding/csv"
"encoding/hex"
"encoding/json"
Expand All @@ -14,7 +13,6 @@ import (

bugout "github.com/bugout-dev/bugout-go/pkg"
"github.com/spf13/cobra"
"golang.org/x/term"
)

func CreateRootCommand() *cobra.Command {
Expand Down Expand Up @@ -532,17 +530,17 @@ func CreateServerCommand() *cobra.Command {
Use: "run",
Short: "Run API server.",
RunE: func(cmd *cobra.Command, args []string) error {
config, configsErr := ReadServerConfig(config)
configParsed, accessResourceId, configsErr := ReadConfig(config)
if configsErr != nil {
return configsErr
}
if len(config.Signers) == 0 {
if len(configParsed) == 0 {
return fmt.Errorf("no signers available")
}

availableSigners := make(map[string]AvailableSigner)
for _, c := range config.Signers {
key, keyErr := KeyFromFile(c.KeyfilePath, c.Password)
for _, c := range configParsed {
key, keyErr := OpenKeystore(c.Keyfile, c.Password)
if keyErr != nil {
return keyErr
}
Expand All @@ -567,7 +565,7 @@ func CreateServerCommand() *cobra.Command {
server := Server{
Host: host,
Port: port,
AccessResourceId: config.AccessResourceId,
AccessResourceId: accessResourceId,
AvailableSigners: availableSigners,
CORSWhitelist: corsWhitelist,
BugoutAPIClient: bugoutClient,
Expand All @@ -583,89 +581,7 @@ func CreateServerCommand() *cobra.Command {
runSubcommand.Flags().StringVar(&config, "config", "./config.json", "Path to server configuration file")
runSubcommand.Flags().IntVar(&logLevel, "log-level", 1, "Log verbosity level")

var keyfile, passwordFlag, passwordTypeFlag, outfile string

configureCommand := &cobra.Command{
Use: "configure",
Short: "Prepare configuration for waggle API server.",
PreRunE: func(cmd *cobra.Command, args []string) error {
var passwordType string
var flagsGetStringErr error
passwordType, flagsGetStringErr = cmd.Flags().GetString("password-type")
if flagsGetStringErr != nil {
return flagsGetStringErr
}

switch passwordType {
case string(PlainText), string(TextFile), string(AwsSecret):
return nil
}
return errors.New("invalid value: allowed values are 'plaintext', 'text_file' and 'aws_secret'")
},
RunE: func(cmd *cobra.Command, args []string) error {
serverSignerConfigs := []ServerSignerConfig{}
var password string
var err error
if passwordFlag == "" {
fmt.Print("Enter password (or path to text file, or aws secret manager variable name) for keyfile (it will not be displayed on screen)\nInput: ")
passwordRaw, err := term.ReadPassword(int(os.Stdin.Fd()))
fmt.Print("\n")
if err != nil {
return fmt.Errorf("error reading password from input: %s", err.Error())
}
password = string(passwordRaw)
} else {
password = passwordFlag
}

var passValidErr error
pt := PasswordType(passwordTypeFlag)
password, passValidErr = pt.PasswordValidation(password)
if passValidErr != nil {
return passValidErr
}

keyfilePath := strings.TrimSuffix(keyfile, "/")
_, err = os.Stat(keyfilePath)
if err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("file %s not found, err: %v", keyfilePath, err)
}
return fmt.Errorf("error due checking keyfile path %s, err: %v", keyfilePath, err)
}

// TODO(kompotkot): Provide functionality to generate config with multiple keyfiles
serverSignerConfigs = append(serverSignerConfigs, ServerSignerConfig{
KeyfilePath: keyfile,
Password: password,
PasswordType: passwordTypeFlag,
})

// Using manual encoding to prevent HTML escaping
buffer := &bytes.Buffer{}
encoder := json.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
if encodeErr := encoder.Encode(serverSignerConfigs); encodeErr != nil {
return encodeErr
}
resultJSON := buffer.Bytes()

if outfile != "" {
os.WriteFile(outfile, resultJSON, 0644)
} else {
os.Stdout.Write(resultJSON)
}

return nil
},
}

configureCommand.PersistentFlags().StringVarP(&keyfile, "keystore", "k", "", "Path to keystore file (this should be a JSON file)")
configureCommand.PersistentFlags().StringVarP(&passwordFlag, "password", "p", "", "Password for keystore file. If not provided, you will be prompted for it when you sign with the key.")
configureCommand.PersistentFlags().StringVarP(&passwordTypeFlag, "password-type", "t", "plaintext", fmt.Sprintf("Format of password, available options: %s, %s, %s", string(PlainText), string(TextFile), string(AwsSecret)))
configureCommand.PersistentFlags().StringVarP(&outfile, "outfile", "o", "config.json", "Config file output path")

serverCommand.AddCommand(runSubcommand, configureCommand)
serverCommand.AddCommand(runSubcommand)

return serverCommand
}
Loading

0 comments on commit b992386

Please sign in to comment.