plugin/source/secretsmanager/secretsmanager.go (99 lines of code) (raw):

package secretsmanager /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved */ import ( "os" "path/filepath" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/facebookincubator/go2chef" "github.com/mitchellh/mapstructure" ) // TypeName is the name of this source plugin const TypeName = "go2chef.source.secretsmanager" // Source implements an AWS secretsmananger source plugin that // copies data stored in AWS secrets mananger into a file. type Source struct { logger go2chef.Logger SourceName string `mapstructure:"name"` Region string `mapstructure:"region"` SecretId string `mapstructure:"secret_id"` FileName string `mapstructure:"filename"` Credentials struct { AccessKeyID string `mapstructure:"access_key_id"` SecretAccessKey string `mapstructure:"secret_access_key"` Token string `mapstructure:"token"` } } func (s *Source) String() string { return "<" + TypeName + ":" + s.SourceName + ">" } // Name returns the name of this source instance func (s *Source) Name() string { return s.SourceName } // Type returns the type of this source func (s *Source) Type() string { return TypeName } // SetName sets the name of this source instance func (s *Source) SetName(name string) { s.SourceName = name } // DownloadToPath reads the SecretString from secretsmanager and // delivers it to the specified file at the download path. func (s *Source) DownloadToPath(dlPath string) error { s.logger.Debugf(0, "dlPath is: %s", dlPath) if err := os.MkdirAll(dlPath, 0755); err != nil { return err } s.logger.Debugf(0, "copy directory %s is ready", dlPath) cfg := aws.NewConfig().WithRegion(s.Region) if s.Credentials.AccessKeyID != "" && s.Credentials.SecretAccessKey != "" { cfg = cfg.WithCredentials( credentials.NewStaticCredentials(s.Credentials.AccessKeyID, s.Credentials.SecretAccessKey, ""), ) } sess, err := session.NewSession(cfg) if err != nil { s.logger.Debugf(0, "failed to create AWS session: %s", err) return err } svc := secretsmanager.New(sess) input := &secretsmanager.GetSecretValueInput{ SecretId: aws.String(s.SecretId), } outpath := filepath.Join(dlPath, s.FileName) result, err := svc.GetSecretValue(input) if err != nil { s.logger.Debugf(0, "failed to retrieve secret %s: %s", s.SecretId, err) return err } // Create the output file if it doesn't exist fh, err := os.OpenFile(outpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0400) if err != nil { s.logger.Debugf(0, "failed to create target (%s): %s", outpath, err) return err } defer fh.Close() _, err = fh.WriteString(*result.SecretString) if err != nil { s.logger.Debugf(0, "failed to write secret data: %s", err) return err } fh.Close() s.logger.Debugf(0, "Wrote secret (%s) to: %s", s.SecretId, outpath) return nil } // Loader provides an instantiation function for this source func Loader(config map[string]interface{}) (go2chef.Source, error) { s := &Source{ logger: go2chef.GetGlobalLogger(), SourceName: "", } if err := mapstructure.Decode(config, s); err != nil { return nil, err } if s.SourceName == "" { s.SourceName = TypeName } // default to using the secret id as the filename if one wasn't provided if s.FileName == "" { s.FileName = s.SecretId } return s, nil } var _ go2chef.Source = &Source{} var _ go2chef.SourceLoader = Loader func init() { go2chef.RegisterSource(TypeName, Loader) }