|
|
@@ -366,7 +366,8 @@ func ErrorContains(out error, want string) bool {
|
|
|
}
|
|
|
|
|
|
type fakeRef struct {
|
|
|
- key string
|
|
|
+ key string
|
|
|
+ property string
|
|
|
}
|
|
|
|
|
|
func (f fakeRef) GetRemoteKey() string {
|
|
|
@@ -374,7 +375,7 @@ func (f fakeRef) GetRemoteKey() string {
|
|
|
}
|
|
|
|
|
|
func (f fakeRef) GetProperty() string {
|
|
|
- return ""
|
|
|
+ return f.property
|
|
|
}
|
|
|
|
|
|
func TestSetSecret(t *testing.T) {
|
|
|
@@ -416,24 +417,57 @@ func TestSetSecret(t *testing.T) {
|
|
|
Tags: externalSecretsTagFaulty,
|
|
|
}
|
|
|
|
|
|
+ initialVersion := "00000000-0000-0000-0000-000000000001"
|
|
|
+ defaultVersion := "00000000-0000-0000-0000-000000000002"
|
|
|
+ defaultUpdatedVersion := "00000000-0000-0000-0000-000000000003"
|
|
|
+ randomUUIDVersion := "c2812e8d-84ce-4858-abec-7163d8ab312b"
|
|
|
+ randomUUIDVersionIncremented := "c2812e8d-84ce-4858-abec-7163d8ab312c"
|
|
|
+ unparsableVersion := "IAM UNPARSABLE"
|
|
|
+
|
|
|
secretValueOutput := &awssm.GetSecretValueOutput{
|
|
|
- ARN: &arn,
|
|
|
+ ARN: &arn,
|
|
|
+ VersionId: &defaultVersion,
|
|
|
}
|
|
|
|
|
|
secretValueOutput2 := &awssm.GetSecretValueOutput{
|
|
|
ARN: &arn,
|
|
|
SecretBinary: secretValue,
|
|
|
+ VersionId: &defaultVersion,
|
|
|
+ }
|
|
|
+
|
|
|
+ type params struct {
|
|
|
+ s string
|
|
|
+ b []byte
|
|
|
+ version *string
|
|
|
}
|
|
|
+ secretValueOutputFrom := func(params params) *awssm.GetSecretValueOutput {
|
|
|
+ var version *string
|
|
|
+ if params.version == nil {
|
|
|
+ version = &defaultVersion
|
|
|
+ } else {
|
|
|
+ version = params.version
|
|
|
+ }
|
|
|
|
|
|
+ return &awssm.GetSecretValueOutput{
|
|
|
+ ARN: &arn,
|
|
|
+ SecretString: ¶ms.s,
|
|
|
+ SecretBinary: params.b,
|
|
|
+ VersionId: version,
|
|
|
+ }
|
|
|
+ }
|
|
|
blankSecretValueOutput := &awssm.GetSecretValueOutput{}
|
|
|
|
|
|
putSecretOutput := &awssm.PutSecretValueOutput{
|
|
|
ARN: &arn,
|
|
|
}
|
|
|
|
|
|
+ remoteRefWithoutProperty := fakeRef{key: "fake-key", property: ""}
|
|
|
+ remoteRefWithProperty := fakeRef{key: "fake-key", property: "other-fake-property"}
|
|
|
+
|
|
|
type args struct {
|
|
|
- store *esv1beta1.AWSProvider
|
|
|
- client fakesm.Client
|
|
|
+ store *esv1beta1.AWSProvider
|
|
|
+ client fakesm.Client
|
|
|
+ remoteRef fakeRef
|
|
|
}
|
|
|
|
|
|
type want struct {
|
|
|
@@ -454,6 +488,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(putSecretOutput, nil),
|
|
|
DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: nil,
|
|
|
@@ -467,11 +502,157 @@ func TestSetSecret(t *testing.T) {
|
|
|
GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(blankSecretValueOutput, &getSecretCorrectErr),
|
|
|
CreateSecretWithContextFn: fakesm.NewCreateSecretWithContextFn(secretOutput, nil),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: nil,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "SetSecretWithPropertySucceedsWithNewSecret": {
|
|
|
+ reason: "if a new secret is pushed to aws sm and a remoteRef property is specified, create a json secret with the remoteRef property as a key",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(blankSecretValueOutput, &getSecretCorrectErr),
|
|
|
+ CreateSecretWithContextFn: fakesm.NewCreateSecretWithContextFn(secretOutput, nil, []byte(`{"other-fake-property":"fake-value"}`)),
|
|
|
+ },
|
|
|
+ remoteRef: remoteRefWithProperty,
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: nil,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "SetSecretWithPropertySucceedsWithExistingSecretAndNewPropertyBinary": {
|
|
|
+ reason: "when a remoteRef property is specified, this property will be added to the sm secret if it is currently absent (sm secret is binary)",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutputFrom(params{b: []byte((`{"fake-property":"fake-value"}`))}), nil),
|
|
|
+ DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
+ PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(putSecretOutput, nil, fakesm.ExpectedPutSecretValueInput{
|
|
|
+ SecretBinary: []byte(`{"fake-property":"fake-value","other-fake-property":"fake-value"}`),
|
|
|
+ Version: &defaultUpdatedVersion,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ remoteRef: remoteRefWithProperty,
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: nil,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "SetSecretWithPropertySucceedsWithExistingSecretAndRandomUUIDVersion": {
|
|
|
+ reason: "When a secret version is not specified, the client sets a random uuid by default. We should treat a version that can't be parsed to an int as not having a version",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutputFrom(params{
|
|
|
+ b: []byte((`{"fake-property":"fake-value"}`)),
|
|
|
+ version: &randomUUIDVersion,
|
|
|
+ }), nil),
|
|
|
+ DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
+ PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(putSecretOutput, nil, fakesm.ExpectedPutSecretValueInput{
|
|
|
+ SecretBinary: []byte(`{"fake-property":"fake-value","other-fake-property":"fake-value"}`),
|
|
|
+ Version: &randomUUIDVersionIncremented,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ remoteRef: remoteRefWithProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: nil,
|
|
|
},
|
|
|
},
|
|
|
+ "SetSecretWithPropertySucceedsWithExistingSecretAndVersionThatCantBeParsed": {
|
|
|
+ reason: "A manually set secret version doesn't have to be a UUID, we only support UUID secret versions though",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutputFrom(params{
|
|
|
+ b: []byte((`{"fake-property":"fake-value"}`)),
|
|
|
+ version: &unparsableVersion,
|
|
|
+ }), nil),
|
|
|
+ DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
+ PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(putSecretOutput, nil, fakesm.ExpectedPutSecretValueInput{
|
|
|
+ SecretBinary: []byte(`{"fake-property":"fake-value","other-fake-property":"fake-value"}`),
|
|
|
+ Version: &initialVersion,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ remoteRef: remoteRefWithProperty,
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: fmt.Errorf("expected secret version in AWS SSM to be a UUID but got '%s'", unparsableVersion),
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "SetSecretWithPropertySucceedsWithExistingSecretAndAbsentVersion": {
|
|
|
+ reason: "When a secret version is not specified, set it to 1",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(&awssm.GetSecretValueOutput{
|
|
|
+ ARN: &arn,
|
|
|
+ SecretBinary: []byte((`{"fake-property":"fake-value"}`)),
|
|
|
+ }, nil),
|
|
|
+ DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
+ PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(putSecretOutput, nil, fakesm.ExpectedPutSecretValueInput{
|
|
|
+ SecretBinary: []byte(`{"fake-property":"fake-value","other-fake-property":"fake-value"}`),
|
|
|
+ Version: &initialVersion,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ remoteRef: remoteRefWithProperty,
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: nil,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "SetSecretWithPropertySucceedsWithExistingSecretAndNewPropertyString": {
|
|
|
+ reason: "when a remoteRef property is specified, this property will be added to the sm secret if it is currently absent (sm secret is a string)",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutputFrom(params{s: `{"fake-property":"fake-value"}`}), nil),
|
|
|
+ DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
+ PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(putSecretOutput, nil, fakesm.ExpectedPutSecretValueInput{
|
|
|
+ SecretBinary: []byte(`{"fake-property":"fake-value","other-fake-property":"fake-value"}`),
|
|
|
+ Version: &defaultUpdatedVersion,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ remoteRef: remoteRefWithProperty,
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: nil,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "SetSecretWithPropertySucceedsWithExistingSecretAndNewPropertyWithDot": {
|
|
|
+ reason: "when a remoteRef property is specified, this property will be added to the sm secret if it is currently absent (remoteRef property is a sub-object)",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutputFrom(params{s: `{"fake-property":{"fake-property":"fake-value"}}`}), nil),
|
|
|
+ DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
+ PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(putSecretOutput, nil, fakesm.ExpectedPutSecretValueInput{
|
|
|
+ SecretBinary: []byte(`{"fake-property":{"fake-property":"fake-value","other-fake-property":"fake-value"}}`),
|
|
|
+ Version: &defaultUpdatedVersion,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ remoteRef: fakeRef{key: "fake-key", property: "fake-property.other-fake-property"},
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: nil,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "SetSecretWithPropertyFailsExistingNonJsonSecret": {
|
|
|
+ reason: "setting a remoteRef property is only supported for json secrets",
|
|
|
+ args: args{
|
|
|
+ store: makeValidSecretStore().Spec.Provider.AWS,
|
|
|
+ client: fakesm.Client{
|
|
|
+ GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutputFrom(params{s: `non-json-secret`}), nil),
|
|
|
+ DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
+ },
|
|
|
+ remoteRef: remoteRefWithProperty,
|
|
|
+ },
|
|
|
+ want: want{
|
|
|
+ err: errors.New("PushSecret for aws secrets manager with a remoteRef property requires a json secret"),
|
|
|
+ },
|
|
|
+ },
|
|
|
"SetSecretCreateSecretFails": {
|
|
|
reason: "CreateSecretWithContext returns an error if it fails",
|
|
|
args: args{
|
|
|
@@ -480,6 +661,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(blankSecretValueOutput, &getSecretCorrectErr),
|
|
|
CreateSecretWithContextFn: fakesm.NewCreateSecretWithContextFn(nil, noPermission),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: noPermission,
|
|
|
@@ -492,6 +674,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
client: fakesm.Client{
|
|
|
GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(blankSecretValueOutput, noPermission),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: noPermission,
|
|
|
@@ -505,6 +688,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutput2, nil),
|
|
|
DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: nil,
|
|
|
@@ -519,6 +703,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
PutSecretValueWithContextFn: fakesm.NewPutSecretValueWithContextFn(nil, noPermission),
|
|
|
DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutput, nil),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: noPermission,
|
|
|
@@ -531,6 +716,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
client: fakesm.Client{
|
|
|
GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(blankSecretValueOutput, &getSecretWrongErr),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: &getSecretWrongErr,
|
|
|
@@ -544,6 +730,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutput, nil),
|
|
|
DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(nil, noPermission),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: noPermission,
|
|
|
@@ -557,6 +744,7 @@ func TestSetSecret(t *testing.T) {
|
|
|
GetSecretValueWithContextFn: fakesm.NewGetSecretValueWithContextFn(secretValueOutput, nil),
|
|
|
DescribeSecretWithContextFn: fakesm.NewDescribeSecretWithContextFn(tagSecretOutputFaulty, nil),
|
|
|
},
|
|
|
+ remoteRef: remoteRefWithoutProperty,
|
|
|
},
|
|
|
want: want{
|
|
|
err: fmt.Errorf("secret not managed by external-secrets"),
|
|
|
@@ -566,11 +754,10 @@ func TestSetSecret(t *testing.T) {
|
|
|
|
|
|
for name, tc := range tests {
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
- ref := fakeRef{key: "fake-key"}
|
|
|
sm := SecretsManager{
|
|
|
client: &tc.args.client,
|
|
|
}
|
|
|
- err := sm.PushSecret(context.Background(), []byte("fake-value"), nil, ref)
|
|
|
+ err := sm.PushSecret(context.Background(), []byte("fake-value"), nil, tc.args.remoteRef)
|
|
|
|
|
|
// Error nil XOR tc.want.err nil
|
|
|
if ((err == nil) || (tc.want.err == nil)) && !((err == nil) && (tc.want.err == nil)) {
|