|
@@ -186,6 +186,24 @@ func newVaultResponseWithData(data map[string]interface{}) *vault.Response {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func newVaultResponseWithMetadata(content map[string]interface{}) map[string]fake.VaultListResponse {
|
|
|
|
|
+ ans := make(map[string]fake.VaultListResponse)
|
|
|
|
|
+ for k, v := range content {
|
|
|
|
|
+ t := v.(map[string]interface{})
|
|
|
|
|
+ m := t["metadata"].(map[string]interface{})
|
|
|
|
|
+ listResponse := fake.VaultListResponse{
|
|
|
|
|
+ Data: newVaultResponse(&vault.Secret{
|
|
|
|
|
+ Data: t,
|
|
|
|
|
+ }),
|
|
|
|
|
+ Metadata: newVaultResponse(&vault.Secret{
|
|
|
|
|
+ Data: m,
|
|
|
|
|
+ }),
|
|
|
|
|
+ }
|
|
|
|
|
+ ans[k] = listResponse
|
|
|
|
|
+ }
|
|
|
|
|
+ return ans
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func newVaultTokenIDResponse(token string) *vault.Response {
|
|
func newVaultTokenIDResponse(token string) *vault.Response {
|
|
|
return newVaultResponseWithData(map[string]interface{}{
|
|
return newVaultResponseWithData(map[string]interface{}{
|
|
|
"id": token,
|
|
"id": token,
|
|
@@ -984,23 +1002,91 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func TestGetAllSecrets(t *testing.T) {
|
|
func TestGetAllSecrets(t *testing.T) {
|
|
|
- errBoom := errors.New("boom")
|
|
|
|
|
|
|
+ secret1Bytes := []byte("{\"access_key\":\"access_key\",\"access_secret\":\"access_secret\"}")
|
|
|
|
|
+ secret2Bytes := []byte("{\"access_key\":\"access_key2\",\"access_secret\":\"access_secret2\"}")
|
|
|
|
|
+ path1Bytes := []byte("{\"access_key\":\"path1\",\"access_secret\":\"path1\"}")
|
|
|
|
|
+ path2Bytes := []byte("{\"access_key\":\"path2\",\"access_secret\":\"path2\"}")
|
|
|
|
|
+ tagBytes := []byte("{\"access_key\":\"unfetched\",\"access_secret\":\"unfetched\"}")
|
|
|
|
|
+ path := "path"
|
|
|
secret := map[string]interface{}{
|
|
secret := map[string]interface{}{
|
|
|
- "access_key": "access_key",
|
|
|
|
|
- "access_secret": "access_secret",
|
|
|
|
|
- }
|
|
|
|
|
- secondSecret := map[string]interface{}{
|
|
|
|
|
- "access_key": "access_key2",
|
|
|
|
|
- "access_secret": "access_secret2",
|
|
|
|
|
- "token": nil,
|
|
|
|
|
|
|
+ "secret1": map[string]interface{}{
|
|
|
|
|
+ "data": map[string]interface{}{
|
|
|
|
|
+ "access_key": "access_key",
|
|
|
|
|
+ "access_secret": "access_secret",
|
|
|
|
|
+ },
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "custom_metadata": map[string]interface{}{
|
|
|
|
|
+ "foo": "bar",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ "secret2": map[string]interface{}{
|
|
|
|
|
+ "data": map[string]interface{}{
|
|
|
|
|
+ "access_key": "access_key2",
|
|
|
|
|
+ "access_secret": "access_secret2",
|
|
|
|
|
+ },
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "custom_metadata": map[string]interface{}{
|
|
|
|
|
+ "foo": "baz",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ "tag": map[string]interface{}{
|
|
|
|
|
+ "data": map[string]interface{}{
|
|
|
|
|
+ "access_key": "unfetched",
|
|
|
|
|
+ "access_secret": "unfetched",
|
|
|
|
|
+ },
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "custom_metadata": map[string]interface{}{
|
|
|
|
|
+ "foo": "baz",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ "path/1": map[string]interface{}{
|
|
|
|
|
+ "data": map[string]interface{}{
|
|
|
|
|
+ "access_key": "path1",
|
|
|
|
|
+ "access_secret": "path1",
|
|
|
|
|
+ },
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "custom_metadata": map[string]interface{}{
|
|
|
|
|
+ "foo": "path",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ "path/2": map[string]interface{}{
|
|
|
|
|
+ "data": map[string]interface{}{
|
|
|
|
|
+ "access_key": "path2",
|
|
|
|
|
+ "access_secret": "path2",
|
|
|
|
|
+ },
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "custom_metadata": map[string]interface{}{
|
|
|
|
|
+ "foo": "path",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ "default": map[string]interface{}{
|
|
|
|
|
+ "data": map[string]interface{}{
|
|
|
|
|
+ "empty": "true",
|
|
|
|
|
+ },
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "keys": []string{"secret1", "secret2", "tag", "path/"},
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ "path/": map[string]interface{}{
|
|
|
|
|
+ "data": map[string]interface{}{
|
|
|
|
|
+ "empty": "true",
|
|
|
|
|
+ },
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "keys": []string{"1", "2"},
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
type args struct {
|
|
type args struct {
|
|
|
store *esv1beta1.VaultProvider
|
|
store *esv1beta1.VaultProvider
|
|
|
kube kclient.Client
|
|
kube kclient.Client
|
|
|
vClient Client
|
|
vClient Client
|
|
|
ns string
|
|
ns string
|
|
|
- data esv1beta1.ExternalSecretDataRemoteRef
|
|
|
|
|
|
|
+ data esv1beta1.ExternalSecretFind
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type want struct {
|
|
type want struct {
|
|
@@ -1013,181 +1099,97 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
args args
|
|
args args
|
|
|
want want
|
|
want want
|
|
|
}{
|
|
}{
|
|
|
- "ReadSecretKV2": {
|
|
|
|
|
- reason: "Should Map the Secret with DataFrom.Find.Name",
|
|
|
|
|
- args: args{
|
|
|
|
|
- store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- want: want{
|
|
|
|
|
- err: nil,
|
|
|
|
|
- val: map[string][]byte{
|
|
|
|
|
- "access_key": []byte("access_key"),
|
|
|
|
|
- "access_secret": []byte("access_secret"),
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- "ReadSecretKV2": {
|
|
|
|
|
- reason: "Should map the secret even if it has a nil value",
|
|
|
|
|
|
|
+ "FindByName": {
|
|
|
|
|
+ reason: "should map multiple secrets matching name",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
|
vClient: &fake.VaultClient{
|
|
vClient: &fake.VaultClient{
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secret,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
|
|
+ MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
+ MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
+ newVaultResponseWithMetadata(secret), nil,
|
|
|
),
|
|
),
|
|
|
},
|
|
},
|
|
|
- },
|
|
|
|
|
- want: want{
|
|
|
|
|
- err: nil,
|
|
|
|
|
- val: map[string][]byte{
|
|
|
|
|
- "access_key": []byte("access_key"),
|
|
|
|
|
- "access_secret": []byte("access_secret"),
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- "ReadSecretWithNilValueKV1": {
|
|
|
|
|
- reason: "Should map the secret even if it has a nil value",
|
|
|
|
|
- args: args{
|
|
|
|
|
- store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secretWithNilVal), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ data: esv1beta1.ExternalSecretFind{
|
|
|
|
|
+ Name: &esv1beta1.FindName{
|
|
|
|
|
+ RegExp: "secret.*",
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
|
err: nil,
|
|
err: nil,
|
|
|
val: map[string][]byte{
|
|
val: map[string][]byte{
|
|
|
- "access_key": []byte("access_key"),
|
|
|
|
|
- "access_secret": []byte("access_secret"),
|
|
|
|
|
- "token": []byte(nil),
|
|
|
|
|
|
|
+ "secret1": secret1Bytes,
|
|
|
|
|
+ "secret2": secret2Bytes,
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- "ReadSecretWithNilValueKV2": {
|
|
|
|
|
- reason: "Should map the secret even if it has a nil value",
|
|
|
|
|
|
|
+ "FindByTag": {
|
|
|
|
|
+ reason: "should map multiple secrets matching tags",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
|
vClient: &fake.VaultClient{
|
|
vClient: &fake.VaultClient{
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secretWithNilVal,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
|
|
+ MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
+ MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
+ newVaultResponseWithMetadata(secret), nil,
|
|
|
),
|
|
),
|
|
|
},
|
|
},
|
|
|
- },
|
|
|
|
|
- want: want{
|
|
|
|
|
- err: nil,
|
|
|
|
|
- val: map[string][]byte{
|
|
|
|
|
- "access_key": []byte("access_key"),
|
|
|
|
|
- "access_secret": []byte("access_secret"),
|
|
|
|
|
- "token": []byte(nil),
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- "ReadSecretWithTypesKV2": {
|
|
|
|
|
- reason: "Should map the secret even if it has other types",
|
|
|
|
|
- args: args{
|
|
|
|
|
- store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secretWithTypes,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ data: esv1beta1.ExternalSecretFind{
|
|
|
|
|
+ Tags: map[string]string{
|
|
|
|
|
+ "foo": "baz",
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
|
err: nil,
|
|
err: nil,
|
|
|
val: map[string][]byte{
|
|
val: map[string][]byte{
|
|
|
- "access_secret": []byte("access_secret"),
|
|
|
|
|
- "f32": []byte("2.12"),
|
|
|
|
|
- "f64": []byte("2.1234534153423423"),
|
|
|
|
|
- "int": []byte("42"),
|
|
|
|
|
- "bool": []byte("true"),
|
|
|
|
|
- "bt": []byte("Zm9vYmFy"), // base64
|
|
|
|
|
|
|
+ "tag": tagBytes,
|
|
|
|
|
+ "secret2": secret2Bytes,
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- "ReadNestedSecret": {
|
|
|
|
|
- reason: "Should map the secret for deeply nested property",
|
|
|
|
|
|
|
+ "FilterByPath": {
|
|
|
|
|
+ reason: "should filter secrets based on path",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
|
- data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
|
|
- Property: "nested",
|
|
|
|
|
- },
|
|
|
|
|
vClient: &fake.VaultClient{
|
|
vClient: &fake.VaultClient{
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secretWithNestedVal,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
|
|
+ MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
+ MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
+ newVaultResponseWithMetadata(secret), nil,
|
|
|
),
|
|
),
|
|
|
},
|
|
},
|
|
|
|
|
+ data: esv1beta1.ExternalSecretFind{
|
|
|
|
|
+ Path: &path,
|
|
|
|
|
+ Tags: map[string]string{
|
|
|
|
|
+ "foo": "path",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
|
err: nil,
|
|
err: nil,
|
|
|
val: map[string][]byte{
|
|
val: map[string][]byte{
|
|
|
- "foo": []byte(`{"mhkeih":"yada yada","oke":"yup"}`),
|
|
|
|
|
|
|
+ "1": path1Bytes,
|
|
|
|
|
+ "2": path2Bytes,
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- "ReadDeeplyNestedSecret": {
|
|
|
|
|
- reason: "Should map the secret for deeply nested property",
|
|
|
|
|
|
|
+ "FailIfKv1": {
|
|
|
|
|
+ reason: "should not work if using kv1 store",
|
|
|
args: args{
|
|
args: args{
|
|
|
- store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
|
|
|
- data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
|
|
- Property: "nested.foo",
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
|
vClient: &fake.VaultClient{
|
|
vClient: &fake.VaultClient{
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secretWithNestedVal,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
|
|
+ MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
+ MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
+ newVaultResponseWithMetadata(secret), nil,
|
|
|
),
|
|
),
|
|
|
},
|
|
},
|
|
|
- },
|
|
|
|
|
- want: want{
|
|
|
|
|
- err: nil,
|
|
|
|
|
- val: map[string][]byte{
|
|
|
|
|
- "oke": []byte("yup"),
|
|
|
|
|
- "mhkeih": []byte("yada yada"),
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- "ReadSecretError": {
|
|
|
|
|
- reason: "Should return error if vault client fails to read secret.",
|
|
|
|
|
- args: args{
|
|
|
|
|
- store: makeSecretStore().Spec.Provider.Vault,
|
|
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(nil, errBoom),
|
|
|
|
|
|
|
+ data: esv1beta1.ExternalSecretFind{
|
|
|
|
|
+ Tags: map[string]string{
|
|
|
|
|
+ "foo": "baz",
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
|
- err: fmt.Errorf(errReadSecret, errBoom),
|
|
|
|
|
|
|
+ err: errors.New(errUnsupportedKvVersion),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
@@ -1200,7 +1202,7 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
store: tc.args.store,
|
|
store: tc.args.store,
|
|
|
namespace: tc.args.ns,
|
|
namespace: tc.args.ns,
|
|
|
}
|
|
}
|
|
|
- val, err := vStore.GetSecretMap(context.Background(), tc.args.data)
|
|
|
|
|
|
|
+ val, err := vStore.GetAllSecrets(context.Background(), tc.args.data)
|
|
|
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
|
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
|
|
|
t.Errorf("\n%s\nvault.GetSecretMap(...): -want error, +got error:\n%s", tc.reason, diff)
|
|
t.Errorf("\n%s\nvault.GetSecretMap(...): -want error, +got error:\n%s", tc.reason, diff)
|
|
|
}
|
|
}
|