diff options
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 190 |
1 files changed, 190 insertions, 0 deletions
@@ -0,0 +1,190 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + "regexp" + "strings" + + "riedstra.dev/go/dpw-ssm/store" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ssm" +) + +const SSM_MAX_SIZE = 4096 + +// ((16^4)*4096)/1024/1024 +// If we ever need more than 256 MB in parameter store, we've done something +// very wrong. +const SSM_KEY_FORMAT = "%s-%04X" // + +var ( + KMS_KEY_ID *string = nil + VersionString = "development" + svc *ssm.SSM + Logger = log.New(os.Stderr, "", 0) + trimRegex = regexp.MustCompile("-[0-9A-E][0-9A-E][0-9A-E][0-9A-E]$") + keyPrefix = os.Getenv("DPW_SSM_PREFIX") +) + +func listParams(params []string) { + info, err := store.GetInfo(svc) + if err != nil { + Logger.Fatal(err) + } + + for key, _ := range info.ByKey { + // Skip over things that aren't prefixed... + if keyPrefix != "" && !strings.HasPrefix(key, keyPrefix) { + continue + } + fmt.Println(strings.TrimPrefix(key, keyPrefix)) + } + + os.Exit(0) +} + +func insertParam(params []string) { + if len(params) != 1 { + Logger.Printf("Params provided: '%s'", params) + Logger.Fatal("Expected exactly one parameter, the path") + } + path := keyPrefix + params[0] + + err := store.InsertParam(svc, os.Stdin, path) + if err != nil { + Logger.Fatalf("While inserting: '%s': %s", path, err) + } + + os.Exit(0) +} + +func showParam(params []string) { + if len(params) != 1 { + Logger.Printf("Params provided: '%s'", params) + Logger.Fatal("Expected exactly one parameter, the path") + } + path := keyPrefix + params[0] + + err := store.GetParam(svc, os.Stdout, path) + if err != nil { + Logger.Fatalf("Encountered: %s\n", err) + } + + os.Exit(0) +} + +func removeParam(params []string) { + if len(params) != 1 { + Logger.Printf("Params provided: '%s'", params) + Logger.Fatal("Expected exactly one parameter, the path") + } + path := keyPrefix + params[0] + + err := store.RemoveParam(svc, path) + if err != nil { + Logger.Fatalf("Encountered: %s\n", err) + } + + os.Exit(0) +} + +func help() { + fmt.Printf(` +dpw-ssm: An AWS SSM backend for the dynamic password manager. +https://git.riedstra.dev/mitch/dpw/about/ + +This can be used directly, but for interactive use 'dpw' is encouraged. + +Available commands: + +list +insert <key-name> +show <key-name> +rm <key-name> + +Debugging environment variables: + +DPW_SSM_DEBUG=YES # Enable extended logging + +Environment variables: + +DPW_SSM_PREFIX=<prefix for all keys> +DPW_SSM_KMS_KEY_ID=<KMS KEY ID> # Optional +DPW_SSM_TAGS='{"json":"encoded","set":"of","key":"value","pairs":"..."}' + +version: %s +`, VersionString) + os.Exit(0) +} + +func setRegion() { + if os.Getenv("AWS_REGION") == "" { + // Default to us-east-2 + os.Setenv("AWS_REGION", "us-east-2") + + // But if a default is set, respect that, since the AWS SDK for Go + // doesn't, normally. + if os.Getenv("AWS_DEFAULT_REGION") != "" { + os.Setenv("AWS_REGION", os.Getenv("AWS_DEFAULT_REGION")) + } + } +} + +func main() { + if os.Getenv("DPW_SSM_DEBUG") != "" { + Logger = log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile) + } + + if os.Getenv("DPW_SSM_KMS_KEY_ID") != "" { + store.KMS_KEY_ID = aws.String(os.Getenv("DPW_SSM_KMS_KEY_ID")) + } + + ssm_tags_json := os.Getenv("DPW_SSM_TAGS") + if ssm_tags_json != "" { + tags := map[string]string{} + err := json.Unmarshal([]byte(ssm_tags_json), &tags) + if err != nil { + Logger.Println("Warning, failed to decode DPW_SSM_TAGS: %s\n", err) + } else { + for k, v := range tags { + store.Tags = append(store.Tags, &ssm.Tag{ + Key: aws.String(k), + Value: aws.String(v), + }) + } + } + } + + setRegion() + + ses := session.Must(session.NewSession()) + svc = ssm.New(ses) + + for n, arg := range os.Args[1:] { + switch arg { + case "list": + listParams(os.Args[n+2:]) + break + case "insert": + insertParam(os.Args[n+2:]) + break + case "show": + showParam(os.Args[n+2:]) + break + case "rm": + removeParam(os.Args[n+2:]) + break + case "init": + fmt.Fprintln(os.Stderr, "No init process is necessary") + break + default: + fmt.Fprintf(os.Stderr, "Unknown argument: '%s'\n", arg) + help() + } + } +} |
