Skip to content

Commit

Permalink
Merge pull request #18 from tickup-se/aws-secret-key-value
Browse files Browse the repository at this point in the history
Decode AWS Secret manager Key/Value
  • Loading branch information
alexei-led authored Oct 20, 2021
2 parents 45f8b9f + fab4288 commit 2fa078e
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Summary:

User can put AWS secret ARN as environment variable value. The `secrets-init` will resolve any environment value, using specified ARN, to referenced secret value.

If the secret is saved as a Key/Value pair, all the keys are applied to as environment variables and passed. The environment variable passed is ignored unless it is inside the key/value pair.
```sh
# environment variable passed to `secrets-init`
MY_DB_PASSWORD=arn:aws:secretsmanager:$AWS_REGION:$AWS_ACCOUNT_ID:secret:mydbpassword-cdma3
Expand Down
24 changes: 23 additions & 1 deletion pkg/secrets/aws/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package aws

import (
"context"
"encoding/json"
"secrets-init/pkg/secrets"
"strings"

Expand Down Expand Up @@ -50,7 +51,20 @@ func (sp *SecretsProvider) ResolveSecrets(ctx context.Context, vars []string) ([
if err != nil {
return vars, errors.Wrap(err, "failed to get secret from AWS Secrets Manager")
}
env = key + "=" + *secret.SecretString
if IsJSON(secret.SecretString) {
var keyValueSecret map[string]string
err = json.Unmarshal([]byte(*secret.SecretString), &keyValueSecret)
if err != nil {
return vars, errors.Wrap(err, "failed to decode key/value secret")
}
for key, value := range keyValueSecret {
e := key + "=" + value
envs = append(envs, e)
}
continue // We continue to not add this ENV variable but only the environment variables that exists in the JSON
} else {
env = key + "=" + *secret.SecretString
}
} else if strings.HasPrefix(value, "arn:aws:ssm") && strings.Contains(value, ":parameter/") {
tokens := strings.Split(value, ":")
// valid parameter ARN arn:aws:ssm:REGION:ACCOUNT:parameter/PATH
Expand Down Expand Up @@ -80,3 +94,11 @@ func (sp *SecretsProvider) ResolveSecrets(ctx context.Context, vars []string) ([

return envs, nil
}

func IsJSON(str *string) bool {
if str == nil {
return false
}
var js json.RawMessage
return json.Unmarshal([]byte(*str), &js) == nil
}
24 changes: 24 additions & 0 deletions pkg/secrets/aws/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,30 @@ func TestSecretsProvider_ResolveSecrets(t *testing.T) {
return &sp
},
},
{
name: "get all secrets from from Secrets Manager json",
vars: []string{
"test-secret-1=arn:aws:secretsmanager:12345678-json",
},
want: []string{
"TEST_1=test-secret-value-1",
"TEST_2=test-secret-value-2",
},
mockServiceProvider: func(mockSM *mocks.SecretsManagerAPI, mockSSM *mocks.SSMAPI) secrets.Provider {
sp := SecretsProvider{sm: mockSM, ssm: mockSSM}
vars := map[string]string{
"arn:aws:secretsmanager:12345678-json": "{\n \"TEST_1\": \"test-secret-value-1\",\n \"TEST_2\": \"test-secret-value-2\"\n}",
}
for n, v := range vars {
name := n
value := v
valueInput := secretsmanager.GetSecretValueInput{SecretId: &name}
valueOutput := secretsmanager.GetSecretValueOutput{SecretString: &value}
mockSM.On("GetSecretValue", &valueInput).Return(&valueOutput, nil)
}
return &sp
},
},
{
name: "no secrets",
vars: []string{
Expand Down

0 comments on commit 2fa078e

Please sign in to comment.