diff --git a/README.md b/README.md index 61c1dff..b6b757f 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,19 @@ selleo aws ecs deploy --cluster CLUSTER_ID --service SERVICE_NAME --docker-image Get all the secrets and export them in shell: ``` -$(selleo aws secrets export --region REGION --id SECRET_ID) +$(selleo aws secrets kv export --region REGION --id SECRET_ID) ``` And new secret (KEY/VALUE are positional arguments): ``` -aws secrets set --region REGION --id SECRET_ID KEY VALUE +aws secrets kv set --region REGION --id SECRET_ID KEY VALUE ``` +Get binary secret: +``` +aws secrets bin get --region REGION --id SECRET_ID +``` ## About Selleo diff --git a/awscmd/secrets_binary.go b/awscmd/secrets_binary.go new file mode 100644 index 0000000..18627a9 --- /dev/null +++ b/awscmd/secrets_binary.go @@ -0,0 +1,45 @@ +package awscmd + +import ( + "context" + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/secretsmanager" +) + +type InputSecretsBinaryGet struct { + Region string + ID string +} + +type OutputSecretsBinaryGet struct { + Bytes []byte +} + +func SecretsBinaryGet(ctx context.Context, input *InputSecretsBinaryGet) (*OutputSecretsBinaryGet, error) { + sess, err := NewSession(input.Region) + if err != nil { + return nil, err + } + + svc := secretsmanager.New(sess, aws.NewConfig().WithRegion(input.Region)) + secretsInput := &secretsmanager.GetSecretValueInput{ + SecretId: aws.String(input.ID), + VersionStage: aws.String("AWSCURRENT"), + } + result, err := svc.GetSecretValueWithContext(ctx, secretsInput) + if err != nil { + return nil, fmt.Errorf("Failed to get secret value: %w", err) + } + + var out OutputSecretsBinaryGet + if result.SecretBinary != nil { + out.Bytes = make([]byte, len(result.SecretBinary)) + copy(out.Bytes, result.SecretBinary) + } else { + return nil, fmt.Errorf("Failed to fetch secret value (SecretBinary is empty): %w", err) + } + + return &out, nil +} diff --git a/main.go b/main.go index 8b87f6d..f719783 100644 --- a/main.go +++ b/main.go @@ -32,52 +32,86 @@ func main() { Usage: "Secrets manager", Subcommands: []*cli.Command{ { - Name: "export", - Usage: "Export secrets for shell", - Flags: []cli.Flag{ - &cli.StringFlag{Name: "region", Usage: "AWS region", Required: true}, - &cli.StringFlag{Name: "id", Usage: "Secrets ID", Required: true}, - }, - Action: func(c *cli.Context) error { - input := &awscmd.InputSecretsAll{ - Region: c.String("region"), - ID: c.String("id"), - } - out, err := awscmd.SecretsAll(context.TODO(), input) - if err != nil { - return err - } + Name: "kv", + Usage: "Key-value secrets", + Subcommands: []*cli.Command{ + { + Name: "export", + Usage: "Export secrets for shell", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "region", Usage: "AWS region", Required: true}, + &cli.StringFlag{Name: "id", Usage: "Secrets ID", Required: true}, + }, + Action: func(c *cli.Context) error { + input := &awscmd.InputSecretsAll{ + Region: c.String("region"), + ID: c.String("id"), + } + out, err := awscmd.SecretsAll(context.TODO(), input) + if err != nil { + return err + } - shellcmd.KeyValueToExports(c.App.Writer, out.Secrets) + shellcmd.KeyValueToExports(c.App.Writer, out.Secrets) - return nil + return nil + }, + }, + { + Name: "set", + Usage: "Sets key value secret", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "region", Usage: "AWS region", Required: true}, + &cli.StringFlag{Name: "id", Usage: "Secrets ID", Required: true}, + }, + ArgsUsage: "KEY VALUE", + Action: func(c *cli.Context) error { + if c.NArg() != 2 { + return fmt.Errorf("Invalid number of arguments. Missing KEY and VALUE.") + } + k, v := c.Args().Get(0), c.Args().Get(1) + + input := &awscmd.InputSecretsPut{ + Region: c.String("region"), + ID: c.String("id"), + NewSecrets: map[string]string{k: v}, + } + _, err := awscmd.SecretsPut(context.TODO(), input) + if err != nil { + return err + } + + return nil + }, + }, }, }, { - Name: "set", - Usage: "Sets key value secret", - Flags: []cli.Flag{ - &cli.StringFlag{Name: "region", Usage: "AWS region", Required: true}, - &cli.StringFlag{Name: "id", Usage: "Secrets ID", Required: true}, - }, - ArgsUsage: "KEY VALUE", - Action: func(c *cli.Context) error { - if c.NArg() != 2 { - return fmt.Errorf("Invalid number of arguments. Missing KEY and VALUE.") - } - k, v := c.Args().Get(0), c.Args().Get(1) + Name: "bin", + Usage: "binary secrets", + Subcommands: []*cli.Command{ + { + Name: "get", + Usage: "Get binary secret", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "region", Usage: "AWS region", Required: true}, + &cli.StringFlag{Name: "id", Usage: "Secrets ID", Required: true}, + }, + Action: func(c *cli.Context) error { + input := &awscmd.InputSecretsBinaryGet{ + Region: c.String("region"), + ID: c.String("id"), + } + out, err := awscmd.SecretsBinaryGet(context.TODO(), input) + if err != nil { + return err + } - input := &awscmd.InputSecretsPut{ - Region: c.String("region"), - ID: c.String("id"), - NewSecrets: map[string]string{k: v}, - } - _, err := awscmd.SecretsPut(context.TODO(), input) - if err != nil { - return err - } + c.App.Writer.Write(out.Bytes) - return nil + return nil + }, + }, }, }, },