Browse Source

Merge pull request #966 from external-secrets/fix/aws-keys-with-dot

Fixes gjson behavior for aws SecretsManager and ParameterStore
paul-the-alien[bot] 4 years ago
parent
commit
0c8851c541

+ 9 - 0
pkg/provider/aws/parameterstore/parameterstore.go

@@ -18,6 +18,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"strings"
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/session"
@@ -187,6 +188,14 @@ func (pm *ParameterStore) GetSecret(ctx context.Context, ref esv1beta1.ExternalS
 		}
 		return nil, fmt.Errorf("invalid secret received. parameter value is nil for key: %s", ref.Key)
 	}
+	idx := strings.Index(ref.Property, ".")
+	if idx > 0 {
+		refProperty := strings.ReplaceAll(ref.Property, ".", "\\.")
+		val := gjson.Get(*out.Parameter.Value, refProperty)
+		if val.Exists() {
+			return []byte(val.String()), nil
+		}
+	}
 	val := gjson.Get(*out.Parameter.Value, ref.Property)
 	if !val.Exists() {
 		return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)

+ 7 - 0
pkg/provider/aws/parameterstore/parameterstore_test.go

@@ -96,6 +96,12 @@ func TestGetSecret(t *testing.T) {
 		pstc.expectedSecret = "bang"
 		pstc.remoteRef.Property = "/shmoo"
 	}
+	// good case: extract property with `.`
+	setExtractPropertyWithDot := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String(`{"/shmoo.boom": "bang"}`)
+		pstc.expectedSecret = "bang"
+		pstc.remoteRef.Property = "/shmoo.boom"
+	}
 
 	// bad case: missing property
 	setMissingProperty := func(pstc *parameterstoreTestCase) {
@@ -131,6 +137,7 @@ func TestGetSecret(t *testing.T) {
 		makeValidParameterStoreTestCaseCustom(setPropertyFail),
 		makeValidParameterStoreTestCaseCustom(setParameterValueNil),
 		makeValidParameterStoreTestCaseCustom(setAPIError),
+		makeValidParameterStoreTestCaseCustom(setExtractPropertyWithDot),
 	}
 
 	ps := ParameterStore{}

+ 10 - 1
pkg/provider/aws/secretsmanager/secretsmanager.go

@@ -19,6 +19,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"strings"
 
 	"github.com/aws/aws-sdk-go/aws/session"
 	awssm "github.com/aws/aws-sdk-go/service/secretsmanager"
@@ -241,7 +242,15 @@ func (sm *SecretsManager) GetSecret(ctx context.Context, ref esv1beta1.ExternalS
 	if secretOut.SecretBinary != nil {
 		payload = string(secretOut.SecretBinary)
 	}
-
+	// We need to search if a given key with a . exists before using gjson operations.
+	idx := strings.Index(ref.Property, ".")
+	if idx > 0 {
+		refProperty := strings.ReplaceAll(ref.Property, ".", "\\.")
+		val := gjson.Get(payload, refProperty)
+		if val.Exists() {
+			return []byte(val.String()), nil
+		}
+	}
 	val := gjson.Get(payload, ref.Property)
 	if !val.Exists() {
 		return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)

+ 8 - 0
pkg/provider/aws/secretsmanager/secretsmanager_test.go

@@ -147,6 +147,13 @@ func TestSecretsManagerGetSecret(t *testing.T) {
 		smtc.remoteRef.Property = "foobar.baz"
 		smtc.expectedSecret = "nestedval"
 	}
+	// good case: secretOut.SecretBinary no JSON parsing if name on key
+	setSecretValueWithDot := func(smtc *secretsManagerTestCase) {
+		smtc.apiOutput.SecretString = nil
+		smtc.apiOutput.SecretBinary = []byte(`{"foobar.baz":"nestedval"}`)
+		smtc.remoteRef.Property = "foobar.baz"
+		smtc.expectedSecret = "nestedval"
+	}
 
 	// good case: custom version set
 	setCustomVersion := func(smtc *secretsManagerTestCase) {
@@ -165,6 +172,7 @@ func TestSecretsManagerGetSecret(t *testing.T) {
 		makeValidSecretsManagerTestCaseCustom(setSecretBinaryNotSecretString),
 		makeValidSecretsManagerTestCaseCustom(setSecretBinaryAndSecretStringToNil),
 		makeValidSecretsManagerTestCaseCustom(setNestedSecretValueJSONParsing),
+		makeValidSecretsManagerTestCaseCustom(setSecretValueWithDot),
 		makeValidSecretsManagerTestCaseCustom(setCustomVersion),
 		makeValidSecretsManagerTestCaseCustom(setAPIErr),
 	}