Skip to content

Commit

Permalink
secret: create secret from local aws credentials
Browse files Browse the repository at this point in the history
closes #109
  • Loading branch information
Mate Ory committed Jul 23, 2019
1 parent 426934e commit e9c9088
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 11 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ require (
github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/sprig v2.18.0+incompatible
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6
github.com/aws/aws-sdk-go v1.21.2
github.com/coreos/go-oidc v2.0.0+incompatible
github.com/cpuguy83/go-md2man v1.0.10 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6 h1:uZuxRZCz65cG1o6K/xUqImNcYKtmk9ylqaH0itMSvzA=
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.21.2 h1:CqbWrQzi7s8J2F0TRRdLvTr0+bt5Zxo2IDoFNGsAiUg=
github.com/aws/aws-sdk-go v1.21.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
Expand Down Expand Up @@ -346,6 +348,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
Expand Down
72 changes: 61 additions & 11 deletions internal/cli/command/secret/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type createSecretOptions struct {
tags []string
validate string
format string
magic bool
}

// secretFieldQuestion contains all necessary field for a secret question (any type except generic)
Expand Down Expand Up @@ -117,6 +118,7 @@ func NewCreateCommand(banzaiCli cli.Cli) *cobra.Command {
flags.StringVarP(&options.secretType, "type", "t", "", "Type of the secret")
flags.StringArrayVarP(&options.tags, "tag", "", []string{}, "Tags to add to the secret")
flags.StringVarP(&options.validate, "validate", "v", "", "Secret validation (true|false)")
flags.BoolVar(&options.magic, "magic", false, "Try to import credentials from local environment (AWS only for now)")

return cmd
}
Expand Down Expand Up @@ -151,9 +153,24 @@ func runCreateSecret(banzaiCli cli.Cli, options *createSecretOptions) error {
}

func getCreateSecretRequest(banzaiCli cli.Cli, options *createSecretOptions, out *pipeline.CreateSecretRequest) error {
out.Name = options.secretName
out.Type = options.secretType
out.Tags = options.tags

if banzaiCli.Interactive() {
return buildInteractiveCreateSecretRequest(banzaiCli, options, out)
} else {

if values, err := importLocalCredential(banzaiCli, options); err != nil {
return err
} else if values != nil {
out.Values = values
}

if options.file == "" && options.magic {
return nil
}

return readFileAndValidate(options.file, out)
}
}
Expand Down Expand Up @@ -201,15 +218,8 @@ func validateCreateSecretRequest(val interface{}) error {

func buildInteractiveCreateSecretRequest(banzaiCli cli.Cli, options *createSecretOptions, out *pipeline.CreateSecretRequest) error {

if len(options.file) != 0 {
if err := readCreateSecretRequestFromFile(options.file, out); err != nil {
// failed to load file, we can ask the user via survey
cli.LogAPIError("create secret", err, out)
} else {
options.secretType = out.Type
options.secretName = out.Name
return nil
}
if options.file != "" {
return readCreateSecretRequestFromFile(options.file, out)
}

allowedTypes, _, err := banzaiCli.Client().SecretsApi.AllowedSecretsTypes(context.Background())
Expand All @@ -222,8 +232,15 @@ func buildInteractiveCreateSecretRequest(banzaiCli cli.Cli, options *createSecre

surveySecretType(options, allowedTypes)

if err := surveySecretFields(options, allowedTypes, out); err != nil {
log.Fatalf("could not get secret fields: %v", err)
out.Values, err = importLocalCredential(banzaiCli, options)
if err != nil {
return err
}

if out.Values == nil {
if err := surveySecretFields(options, allowedTypes, out); err != nil {
log.Fatalf("could not get secret fields: %v", err)
}
}

surveyTags(options)
Expand Down Expand Up @@ -421,3 +438,36 @@ func getValidationFlag(validation string) optional.Bool {
return optional.NewBool(true)
}
}

func importLocalCredential(banzaiCli cli.Cli, options *createSecretOptions) (map[string]interface{}, error) {
if !banzaiCli.Interactive() && !options.magic {
return nil, nil
}

var id string
var values map[string]interface{}
var err error

switch options.secretType {
case TypeAmazon:
id, values, err = input.GetAmazonCredentials()
default:
if options.magic {
return nil, errors.New("unsupported secret type for local credential import")
}
return nil, nil
}

if values != nil && !options.magic && banzaiCli.Interactive() {
prompt := &survey.Confirm{
Message: fmt.Sprintf("Do you want to create the secret from your local credential (%s)?", id),
Help: fmt.Sprintf("We can extract your local AWS credentials if you want."),
}
_ = survey.AskOne(prompt, &options.magic, nil)
}

if options.magic {
return values, err
}
return nil, nil
}
33 changes: 33 additions & 0 deletions internal/cli/input/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import (
"context"

"github.com/antihax/optional"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/goph/emperror"
"github.com/pkg/errors"
"gopkg.in/AlecAivazis/survey.v1"

"github.com/banzaicloud/banzai-cli/.gen/pipeline"
Expand Down Expand Up @@ -49,3 +52,33 @@ func AskSecret(banzaiCli cli.Cli, orgID int32, cloud string) (string, error) {

return secretIds[secretName], nil
}

// GetAmazonCredentials extracts the local credentials from env vars and user profile
func GetAmazonCredentials() (string, map[string]interface{}, error) {
/* create a new session, which is basically the same as the following, but may also contain a region
creds := credentials.NewChainCredentials(
[]credentials.Provider{
&credentials.EnvProvider{},
&credentials.SharedCredentialsProvider{},
}) */
session, err := session.NewSession(&aws.Config{})
if err != nil {
return "", nil, err

}

value, err := session.Config.Credentials.Get()
if err != nil {
return "", nil, err
}

if value.SessionToken != "" {
return "", nil, errors.New("AWS session tokens are not supported by Banzai Cloud Pipeline")
}

return value.AccessKeyID, map[string]interface{}{
"AWS_ACCESS_KEY_ID": value.AccessKeyID,
"AWS_SECRET_ACCESS_KEY": value.SecretAccessKey,
"AWS_REGION": session.Config.Region,
}, nil
}

0 comments on commit e9c9088

Please sign in to comment.