1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-15 17:51:01 +00:00

Add tweaks for secretsManager GetSecret tests

For readability and scalability, create a struct with default
test case values, then use anonymous function "tweaks" with only the
changes from default to test on.
This commit is contained in:
Gabi 2021-05-04 12:08:03 +02:00
parent 8bd306cc01
commit 73fd040965

View file

@ -37,179 +37,147 @@ func TestConstructor(t *testing.T) {
assert.NotNil(t, c.client)
}
type secretsManagerTestCase struct {
fakeClient *fakesm.Client
apiInput *awssm.GetSecretValueInput
apiOutput *awssm.GetSecretValueOutput
ref *esv1alpha1.ExternalSecretDataRemoteRef
apiErr error
expectError string
expectedSecret string
}
func makeValidSecretsManagerTestCase() *secretsManagerTestCase {
smtc := secretsManagerTestCase{
fakeClient: &fakesm.Client{},
apiInput: makeValidAPIInput(),
ref: makeValidRef(),
apiOutput: makeValidAPIOutput(),
apiErr: nil,
expectError: "",
expectedSecret: "",
}
smtc.fakeClient.WithValue(smtc.apiInput, smtc.apiOutput, smtc.apiErr)
return &smtc
}
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Version: "AWSCURRENT",
}
}
func makeValidAPIInput() *awssm.GetSecretValueInput {
return &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
}
}
func makeValidAPIOutput() *awssm.GetSecretValueOutput {
return &awssm.GetSecretValueOutput{
SecretString: aws.String(""),
}
}
func makeValidSecretsManagerTestCaseCustom(tweaks ...func(smtc *secretsManagerTestCase)) *secretsManagerTestCase {
smtc := makeValidSecretsManagerTestCase()
for _, fn := range tweaks {
fn(smtc)
}
smtc.fakeClient.WithValue(smtc.apiInput, smtc.apiOutput, smtc.apiErr)
return smtc
}
// test the sm<->aws interface
// make sure correct values are passed and errors are handled accordingly.
func TestGetSecret(t *testing.T) {
fake := &fakesm.Client{}
p := &SecretsManager{
client: fake,
func TestSecretsManagerGetSecret(t *testing.T) {
// good case: default version is set
// key is passed in, output is sent back
setSecretString := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretString = aws.String("testtesttest")
smtc.expectedSecret = "testtesttest"
}
for i, row := range []struct {
apiInput *awssm.GetSecretValueInput
apiOutput *awssm.GetSecretValueOutput
rr esv1alpha1.ExternalSecretDataRemoteRef
apiErr error
expectError string
expectedSecret string
}{
{
// good case: default version is set
// key is passed in, output is sent back
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: aws.String("RRRRR"),
},
apiErr: nil,
expectError: "",
expectedSecret: "RRRRR",
},
{
// good case: extract property
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Property: "/shmoo",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: aws.String(`{"/shmoo": "bang"}`),
},
apiErr: nil,
expectError: "",
expectedSecret: "bang",
},
{
// bad case: missing property
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Property: "INVALPROP",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: aws.String(`{"/shmoo": "bang"}`),
},
apiErr: nil,
expectError: "key INVALPROP does not exist in secret",
expectedSecret: "",
},
{
// bad case: extract property failure due to invalid json
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Property: "INVALPROP",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: aws.String(`------`),
},
apiErr: nil,
expectError: "key INVALPROP does not exist in secret",
expectedSecret: "",
},
{
// case: ssm.SecretString may be nil but binary is set
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: nil,
SecretBinary: []byte("yesplease"),
},
apiErr: nil,
expectError: "",
expectedSecret: "yesplease",
},
{
// case: both .SecretString and .SecretBinary is nil
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: nil,
SecretBinary: nil,
},
apiErr: nil,
expectError: "no secret string nor binary for key",
expectedSecret: "",
},
{
// case: secretOut.SecretBinary JSON parsing
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/baz"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Property: "foobar.baz",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: nil,
SecretBinary: []byte(`{"foobar":{"baz":"nestedval"}}`),
},
apiErr: nil,
expectError: "",
expectedSecret: "nestedval",
},
{
// should pass version
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/foo/bar"),
VersionStage: aws.String("1234"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/foo/bar",
Version: "1234",
},
apiOutput: &awssm.GetSecretValueOutput{
SecretString: aws.String("FOOBA!"),
},
apiErr: nil,
expectError: "",
expectedSecret: "FOOBA!",
},
{
// should return err
apiInput: &awssm.GetSecretValueInput{
SecretId: aws.String("/foo/bar"),
VersionStage: aws.String("AWSCURRENT"),
},
rr: esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/foo/bar",
},
apiOutput: &awssm.GetSecretValueOutput{},
apiErr: fmt.Errorf("oh no"),
expectError: "oh no",
},
} {
fake.WithValue(row.apiInput, row.apiOutput, row.apiErr)
out, err := p.GetSecret(context.Background(), row.rr)
if !ErrorContains(err, row.expectError) {
t.Errorf("[%d] unexpected error: %s, expected: '%s'", i, err.Error(), row.expectError)
// good case: extract property
// Testing that the property exists in the SecretString
setRefPropertyExistsInKey := func(smtc *secretsManagerTestCase) {
smtc.ref.Property = "/shmoo"
smtc.apiOutput.SecretString = aws.String(`{"/shmoo": "bang"}`)
smtc.expectedSecret = "bang"
}
// bad case: missing property
setRefMissingProperty := func(smtc *secretsManagerTestCase) {
smtc.ref.Property = "INVALPROP"
smtc.expectError = "key INVALPROP does not exist in secret"
}
// bad case: extract property failure due to invalid json
setRefMissingPropertyInvalidJSON := func(smtc *secretsManagerTestCase) {
smtc.ref.Property = "INVALPROP"
smtc.apiOutput.SecretString = aws.String(`------`)
smtc.expectError = "key INVALPROP does not exist in secret"
}
// good case: set .SecretString to nil but set binary with value
setSecretBinaryNotSecretString := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretBinary = []byte("yesplease")
// needs to be set as nil, empty quotes ("") is considered existing
smtc.apiOutput.SecretString = nil
smtc.expectedSecret = "yesplease"
}
// bad case: both .SecretString and .SecretBinary are nil
setSecretBinaryAndSecretStringToNil := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretBinary = nil
smtc.apiOutput.SecretString = nil
smtc.expectError = "no secret string nor binary for key"
}
// good case: secretOut.SecretBinary JSON parsing
setNestedSecretValueJSONParsing := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretString = nil
smtc.apiOutput.SecretBinary = []byte(`{"foobar":{"baz":"nestedval"}}`)
smtc.ref.Property = "foobar.baz"
smtc.expectedSecret = "nestedval"
}
// good case: custom version set
setCustomVersion := func(smtc *secretsManagerTestCase) {
smtc.apiInput.VersionStage = aws.String("1234")
smtc.ref.Version = "1234"
smtc.apiOutput.SecretString = aws.String("FOOBA!")
smtc.expectedSecret = "FOOBA!"
}
// bad case: set apiErr
setAPIErr := func(smtc *secretsManagerTestCase) {
smtc.apiErr = fmt.Errorf("oh no")
smtc.expectError = "oh no"
}
successCases := []*secretsManagerTestCase{
makeValidSecretsManagerTestCase(),
makeValidSecretsManagerTestCaseCustom(setSecretString),
makeValidSecretsManagerTestCaseCustom(setRefPropertyExistsInKey),
makeValidSecretsManagerTestCaseCustom(setRefMissingProperty),
makeValidSecretsManagerTestCaseCustom(setRefMissingPropertyInvalidJSON),
makeValidSecretsManagerTestCaseCustom(setSecretBinaryNotSecretString),
makeValidSecretsManagerTestCaseCustom(setSecretBinaryAndSecretStringToNil),
makeValidSecretsManagerTestCaseCustom(setNestedSecretValueJSONParsing),
makeValidSecretsManagerTestCaseCustom(setCustomVersion),
makeValidSecretsManagerTestCaseCustom(setAPIErr),
}
sm := SecretsManager{}
for k, v := range successCases {
sm.client = v.fakeClient
out, err := sm.GetSecret(context.Background(), *v.ref)
if !ErrorContains(err, v.expectError) {
t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
}
if string(out) != row.expectedSecret {
t.Errorf("[%d] unexpected secret: expected %s, got %s", i, row.expectedSecret, string(out))
if string(out) != v.expectedSecret {
t.Errorf("[%d] unexpected secret: expected %s, got %s", k, v.expectedSecret, string(out))
}
}
}