diff --git a/secretstores/aws/parameterstore/parameterstore.go b/secretstores/aws/parameterstore/parameterstore.go index 4af967b7f..185577b55 100644 --- a/secretstores/aws/parameterstore/parameterstore.go +++ b/secretstores/aws/parameterstore/parameterstore.go @@ -41,10 +41,12 @@ type parameterStoreMetaData struct { AccessKey string `json:"accessKey"` SecretKey string `json:"secretKey"` SessionToken string `json:"sessionToken"` + Prefix string `json:"prefix"` } type ssmSecretStore struct { client ssmiface.SSMAPI + prefix string logger logger.Logger } @@ -60,6 +62,7 @@ func (s *ssmSecretStore) Init(metadata secretstores.Metadata) error { return err } s.client = client + s.prefix = meta.Prefix return nil } @@ -75,7 +78,7 @@ func (s *ssmSecretStore) GetSecret(req secretstores.GetSecretRequest) (secretsto } output, err := s.client.GetParameter(&ssm.GetParameterInput{ - Name: aws.String(name), + Name: aws.String(s.prefix + name), WithDecryption: aws.Bool(true), }) if err != nil { @@ -86,7 +89,8 @@ func (s *ssmSecretStore) GetSecret(req secretstores.GetSecretRequest) (secretsto Data: map[string]string{}, } if output.Parameter.Name != nil && output.Parameter.Value != nil { - resp.Data[*output.Parameter.Name] = *output.Parameter.Value + secretName := (*output.Parameter.Name)[len(s.prefix):] + resp.Data[secretName] = *output.Parameter.Value } return resp, nil @@ -101,10 +105,22 @@ func (s *ssmSecretStore) BulkGetSecret(req secretstores.BulkGetSecretRequest) (s search := true var nextToken *string = nil + var filters []*ssm.ParameterStringFilter + if s.prefix != "" { + filters = []*ssm.ParameterStringFilter{ + { + Key: aws.String(ssm.ParametersFilterKeyName), + Option: aws.String("BeginsWith"), + Values: aws.StringSlice([]string{s.prefix}), + }, + } + } + for search { output, err := s.client.DescribeParameters(&ssm.DescribeParametersInput{ - MaxResults: nil, - NextToken: nextToken, + MaxResults: nil, + NextToken: nextToken, + ParameterFilters: filters, }) if err != nil { return secretstores.BulkGetSecretResponse{Data: nil}, fmt.Errorf("couldn't list secrets: %s", err) @@ -120,7 +136,8 @@ func (s *ssmSecretStore) BulkGetSecret(req secretstores.BulkGetSecretRequest) (s } if entry.Name != nil && params.Parameter.Value != nil { - resp.Data[*entry.Name] = map[string]string{*entry.Name: *params.Parameter.Value} + secretName := (*entry.Name)[len(s.prefix):] + resp.Data[secretName] = map[string]string{secretName: *params.Parameter.Value} } } diff --git a/secretstores/aws/parameterstore/parameterstore_test.go b/secretstores/aws/parameterstore/parameterstore_test.go index 1d781d11d..204f25dcd 100644 --- a/secretstores/aws/parameterstore/parameterstore_test.go +++ b/secretstores/aws/parameterstore/parameterstore_test.go @@ -117,6 +117,33 @@ func TestGetSecret(t *testing.T) { assert.Nil(t, e) assert.Equal(t, secretValue, output.Data[req.Name]) }) + + t.Run("with prefix", func(t *testing.T) { + s := ssmSecretStore{ + client: &mockedSSM{ + GetParameterFn: func(input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) { + assert.Equal(t, "/prefix/aws/dev/secret", *input.Name) + secret := secretValue + + return &ssm.GetParameterOutput{ + Parameter: &ssm.Parameter{ + Name: input.Name, + Value: &secret, + }, + }, nil + }, + }, + prefix: "/prefix", + } + + req := secretstores.GetSecretRequest{ + Name: "/aws/dev/secret", + Metadata: map[string]string{}, + } + output, e := s.GetSecret(req) + assert.Nil(t, e) + assert.Equal(t, "secret", output.Data[req.Name]) + }) }) t.Run("unsuccessfully retrieve secret", func(t *testing.T) { @@ -172,6 +199,42 @@ func TestGetBulkSecrets(t *testing.T) { assert.Contains(t, output.Data, "/aws/dev/secret2") }) + t.Run("successfully retrieve bulk secrets with prefix", func(t *testing.T) { + s := ssmSecretStore{ + client: &mockedSSM{ + DescribeParametersFn: func(*ssm.DescribeParametersInput) (*ssm.DescribeParametersOutput, error) { + return &ssm.DescribeParametersOutput{NextToken: nil, Parameters: []*ssm.ParameterMetadata{ + { + Name: aws.String("/prefix/aws/dev/secret1"), + }, + { + Name: aws.String("/prefix/aws/dev/secret2"), + }, + }}, nil + }, + GetParameterFn: func(input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) { + secret := fmt.Sprintf("%s-%s", *input.Name, secretValue) + + return &ssm.GetParameterOutput{ + Parameter: &ssm.Parameter{ + Name: input.Name, + Value: &secret, + }, + }, nil + }, + }, + prefix: "/prefix", + } + + req := secretstores.BulkGetSecretRequest{ + Metadata: map[string]string{}, + } + output, e := s.BulkGetSecret(req) + assert.Nil(t, e) + assert.Equal(t, "map[/aws/dev/secret1:/prefix/aws/dev/secret1-secret]", fmt.Sprint(output.Data["/aws/dev/secret1"])) + assert.Equal(t, "map[/aws/dev/secret2:/prefix/aws/dev/secret2-secret]", fmt.Sprint(output.Data["/aws/dev/secret2"])) + }) + t.Run("unsuccessfully retrieve bulk secrets on get parameter", func(t *testing.T) { s := ssmSecretStore{ client: &mockedSSM{