diff --git a/adapters/secrets/service.go b/adapters/secrets/service.go index 5344c38..7452ff2 100644 --- a/adapters/secrets/service.go +++ b/adapters/secrets/service.go @@ -6,16 +6,17 @@ import ( "errors" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/secretsmanager" ) type Service struct { - sm *secretsmanager.SecretsManager - secretName string + sm *secretsmanager.SecretsManager + secretPrefix string } -func NewService(secretName string) (*Service, error) { +func NewService(secretPrefix string) (*Service, error) { sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-east-2"), }) @@ -26,18 +27,27 @@ func NewService(secretName string) (*Service, error) { // Create a Secrets Manager client svc := secretsmanager.New(sess) - return &Service{sm: svc, secretName: secretName}, nil + return &Service{sm: svc, secretPrefix: secretPrefix}, nil } var ErrMissingSecret = errors.New("missing secret for builder") +func (s *Service) secretName(builderName string) string { + return s.secretPrefix + "/" + builderName +} + func (s *Service) GetSecretValues(builderName string) (json.RawMessage, error) { input := &secretsmanager.GetSecretValueInput{ - SecretId: aws.String(s.secretName), + SecretId: aws.String(s.secretName(builderName)), } result, err := s.sm.GetSecretValue(input) if err != nil { + // If the secret doesn't exist, return empty JSON for new builders + var awsErr awserr.Error + if errors.As(err, &awsErr) && awsErr.Code() == secretsmanager.ErrCodeResourceNotFoundException { + return json.RawMessage("{}"), nil + } return nil, err } secretData := make(map[string]json.RawMessage) @@ -55,15 +65,37 @@ func (s *Service) GetSecretValues(builderName string) (json.RawMessage, error) { } func (s *Service) SetSecretValues(builderName string, values json.RawMessage) error { + secretName := s.secretName(builderName) input := &secretsmanager.GetSecretValueInput{ - SecretId: aws.String(s.secretName), + SecretId: aws.String(secretName), } result, err := s.sm.GetSecretValue(input) + var secretData map[string]json.RawMessage + if err != nil { + // If the secret doesn't exist, create it + var awsErr awserr.Error + if errors.As(err, &awsErr) && awsErr.Code() == secretsmanager.ErrCodeResourceNotFoundException { + // Create a new secret with the builder's values + secretData = map[string]json.RawMessage{builderName: values} + newSecretString, marshalErr := json.Marshal(secretData) + if marshalErr != nil { + return marshalErr + } + + createInput := &secretsmanager.CreateSecretInput{ + Name: aws.String(secretName), + SecretString: aws.String(string(newSecretString)), + } + _, createErr := s.sm.CreateSecret(createInput) + return createErr + } return err } - secretData := make(map[string]json.RawMessage) + + // Secret exists, update it + secretData = make(map[string]json.RawMessage) err = json.Unmarshal([]byte(*result.SecretString), &secretData) if err != nil { return err @@ -76,7 +108,7 @@ func (s *Service) SetSecretValues(builderName string, values json.RawMessage) er } sv := &secretsmanager.PutSecretValueInput{ - SecretId: aws.String(s.secretName), + SecretId: aws.String(secretName), SecretString: aws.String(string(newSecretString)), } _, err = s.sm.PutSecretValue(sv) diff --git a/cmd/httpserver/main.go b/cmd/httpserver/main.go index 454ab79..4abc69e 100644 --- a/cmd/httpserver/main.go +++ b/cmd/httpserver/main.go @@ -85,10 +85,10 @@ var flags = []cli.Flag{ EnvVars: []string{"POSTGRES_DSN"}, }, &cli.StringFlag{ - Name: "secret-name", + Name: "secret-prefix", Value: "", Usage: "AWS Secret name", - EnvVars: []string{"AWS_BUILDER_CONFIGS_SECRET_NAME"}, + EnvVars: []string{"AWS_BUILDER_CONFIGS_SECRET_NAME", "AWS_BUILDER_CONFIGS_SECRET_PREFIX"}, }, &cli.BoolFlag{ Name: "mock-secrets", @@ -156,7 +156,7 @@ func runCli(cCtx *cli.Context) error { log.Info("using mock secrets storage") sm = domain.NewMockSecretService() } else { - sm, err = secrets.NewService(cCtx.String("secret-name")) + sm, err = secrets.NewService(cCtx.String("secret-prefix")) if err != nil { log.Error("failed to create secrets manager", "err", err) return err