Add prefix option to AWS SSM Parameter Store secret store component (#2043)

Signed-off-by: Oliver Streek <ostreek@rosske.co.uk>

Signed-off-by: Oliver Streek <ostreek@rosske.co.uk>
This commit is contained in:
Oliver 2022-09-01 19:40:30 +01:00 committed by GitHub
parent 19341e5a0f
commit b18e73d028
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 5 deletions

View File

@ -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}
}
}

View File

@ -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{