|
@@ -15,13 +15,10 @@ limitations under the License.
|
|
|
package vault
|
|
package vault
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
- "bytes"
|
|
|
|
|
"context"
|
|
"context"
|
|
|
- "encoding/json"
|
|
|
|
|
"errors"
|
|
"errors"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
- "io"
|
|
|
|
|
- "net/http"
|
|
|
|
|
|
|
+ "strings"
|
|
|
"testing"
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/crossplane/crossplane-runtime/pkg/test"
|
|
"github.com/crossplane/crossplane-runtime/pkg/test"
|
|
@@ -171,45 +168,6 @@ func makeSecretStore(tweaks ...secretStoreTweakFn) *esv1beta1.SecretStore {
|
|
|
return store
|
|
return store
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func newVaultResponse(data *vault.Secret) *vault.Response {
|
|
|
|
|
- jsonData, _ := json.Marshal(data)
|
|
|
|
|
- return &vault.Response{
|
|
|
|
|
- Response: &http.Response{
|
|
|
|
|
- Body: io.NopCloser(bytes.NewReader(jsonData)),
|
|
|
|
|
- },
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func newVaultResponseWithData(data map[string]interface{}) *vault.Response {
|
|
|
|
|
- return newVaultResponse(&vault.Secret{
|
|
|
|
|
- Data: data,
|
|
|
|
|
- })
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-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 {
|
|
|
|
|
- return newVaultResponseWithData(map[string]interface{}{
|
|
|
|
|
- "id": token,
|
|
|
|
|
- })
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
type args struct {
|
|
type args struct {
|
|
|
newClientFunc func(c *vault.Config) (Client, error)
|
|
newClientFunc func(c *vault.Config) (Client, error)
|
|
|
store esv1beta1.GenericStore
|
|
store esv1beta1.GenericStore
|
|
@@ -228,12 +186,25 @@ type testCase struct {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func clientWithLoginMock(c *vault.Config) (Client, error) {
|
|
func clientWithLoginMock(c *vault.Config) (Client, error) {
|
|
|
- return &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultTokenIDResponse("test-token"), nil, func(got *vault.Request) error { return nil }),
|
|
|
|
|
|
|
+ cl := fake.VaultClient{
|
|
|
MockSetToken: fake.NewSetTokenFn(),
|
|
MockSetToken: fake.NewSetTokenFn(),
|
|
|
- }, nil
|
|
|
|
|
|
|
+ MockAuth: fake.NewVaultAuth(),
|
|
|
|
|
+ MockLogical: fake.NewVaultLogical(),
|
|
|
|
|
+ }
|
|
|
|
|
+ auth := cl.Auth()
|
|
|
|
|
+ token := cl.AuthToken()
|
|
|
|
|
+ logical := cl.Logical()
|
|
|
|
|
+ out := VClient{
|
|
|
|
|
+ setToken: cl.SetToken,
|
|
|
|
|
+ token: cl.Token,
|
|
|
|
|
+ clearToken: cl.ClearToken,
|
|
|
|
|
+ auth: auth,
|
|
|
|
|
+ authToken: token,
|
|
|
|
|
+ logical: logical,
|
|
|
|
|
+ setNamespace: cl.SetNamespace,
|
|
|
|
|
+ addHeader: cl.AddHeader,
|
|
|
|
|
+ }
|
|
|
|
|
+ return out, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func kubeMockWithSecretTokenAndServiceAcc(obj kclient.Object) error {
|
|
func kubeMockWithSecretTokenAndServiceAcc(obj kclient.Object) error {
|
|
@@ -327,36 +298,6 @@ MIICsTCCAZkCFEJJ4daz5sxkFlzq9n1djLEuG7bmMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHZh
|
|
|
err: fmt.Errorf(errGetKubeSecret, "vault-secret", errBoom),
|
|
err: fmt.Errorf(errGetKubeSecret, "vault-secret", errBoom),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- "SuccessfulVaultStore": {
|
|
|
|
|
- reason: "Should return a Vault provider successfully",
|
|
|
|
|
- args: args{
|
|
|
|
|
- store: makeSecretStore(),
|
|
|
|
|
- kube: &test.MockClient{
|
|
|
|
|
- MockGet: test.NewMockGetFn(nil, kubeMockWithSecretTokenAndServiceAcc),
|
|
|
|
|
- },
|
|
|
|
|
- newClientFunc: func(c *vault.Config) (Client, error) {
|
|
|
|
|
- return &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultTokenIDResponse("test-token"), nil, func(got *vault.Request) error {
|
|
|
|
|
- kubeRole := makeValidSecretStore().Spec.Provider.Vault.Auth.Kubernetes.Role
|
|
|
|
|
- want := kubeParameters(kubeRole, string(secretData))
|
|
|
|
|
- if diff := cmp.Diff(want, got.Obj); diff != "" {
|
|
|
|
|
- t.Errorf("RawRequestWithContext(...): -want, +got:\n%s", diff)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return nil
|
|
|
|
|
- }),
|
|
|
|
|
- MockSetToken: fake.NewSetTokenFn(),
|
|
|
|
|
- MockToken: fake.NewTokenFn(""),
|
|
|
|
|
- MockClearToken: fake.NewClearTokenFn(),
|
|
|
|
|
- }, nil
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- want: want{
|
|
|
|
|
- err: nil,
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
"SuccessfulVaultStoreWithCertAuth": {
|
|
"SuccessfulVaultStoreWithCertAuth": {
|
|
|
reason: "Should return a Vault provider successfully",
|
|
reason: "Should return a Vault provider successfully",
|
|
|
args: args{
|
|
args: args{
|
|
@@ -592,11 +533,11 @@ func TestGetSecret(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type args struct {
|
|
type args struct {
|
|
|
- store *esv1beta1.VaultProvider
|
|
|
|
|
- kube kclient.Client
|
|
|
|
|
- vClient Client
|
|
|
|
|
- ns string
|
|
|
|
|
- data esv1beta1.ExternalSecretDataRemoteRef
|
|
|
|
|
|
|
+ store *esv1beta1.VaultProvider
|
|
|
|
|
+ kube kclient.Client
|
|
|
|
|
+ vLogical Logical
|
|
|
|
|
+ ns string
|
|
|
|
|
+ data esv1beta1.ExternalSecretDataRemoteRef
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type want struct {
|
|
type want struct {
|
|
@@ -616,11 +557,8 @@ func TestGetSecret(t *testing.T) {
|
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
Property: "access_key",
|
|
Property: "access_key",
|
|
|
},
|
|
},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secret, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -635,11 +573,8 @@ func TestGetSecret(t *testing.T) {
|
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
Property: "access_key",
|
|
Property: "access_key",
|
|
|
},
|
|
},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secretWithNilVal), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secretWithNilVal, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -652,11 +587,8 @@ func TestGetSecret(t *testing.T) {
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{},
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secret, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -671,11 +603,8 @@ func TestGetSecret(t *testing.T) {
|
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
Property: "nested.foo",
|
|
Property: "nested.foo",
|
|
|
},
|
|
},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secretWithNestedVal), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secretWithNestedVal, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -691,11 +620,8 @@ func TestGetSecret(t *testing.T) {
|
|
|
//
|
|
//
|
|
|
Property: "nested.bar",
|
|
Property: "nested.bar",
|
|
|
},
|
|
},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secretWithNestedVal), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secretWithNestedVal, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -710,11 +636,8 @@ func TestGetSecret(t *testing.T) {
|
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
Property: "nop.doesnt.exist",
|
|
Property: "nop.doesnt.exist",
|
|
|
},
|
|
},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secretWithNestedVal), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secretWithNestedVal, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -725,9 +648,8 @@ func TestGetSecret(t *testing.T) {
|
|
|
reason: "Should return error if vault client fails to read secret.",
|
|
reason: "Should return error if vault client fails to read secret.",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeSecretStore().Spec.Provider.Vault,
|
|
store: makeSecretStore().Spec.Provider.Vault,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(nil, errBoom),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, errBoom),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -740,7 +662,7 @@ func TestGetSecret(t *testing.T) {
|
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Run(name, func(t *testing.T) {
|
|
|
vStore := &client{
|
|
vStore := &client{
|
|
|
kube: tc.args.kube,
|
|
kube: tc.args.kube,
|
|
|
- client: tc.args.vClient,
|
|
|
|
|
|
|
+ logical: tc.args.vLogical,
|
|
|
store: tc.args.store,
|
|
store: tc.args.store,
|
|
|
namespace: tc.args.ns,
|
|
namespace: tc.args.ns,
|
|
|
}
|
|
}
|
|
@@ -788,7 +710,7 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
type args struct {
|
|
type args struct {
|
|
|
store *esv1beta1.VaultProvider
|
|
store *esv1beta1.VaultProvider
|
|
|
kube kclient.Client
|
|
kube kclient.Client
|
|
|
- vClient Client
|
|
|
|
|
|
|
+ vClient Logical
|
|
|
ns string
|
|
ns string
|
|
|
data esv1beta1.ExternalSecretDataRemoteRef
|
|
data esv1beta1.ExternalSecretDataRemoteRef
|
|
|
}
|
|
}
|
|
@@ -807,11 +729,8 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
reason: "Should map the secret even if it has a nil value",
|
|
reason: "Should map the secret even if it has a nil value",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secret, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -826,15 +745,10 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
reason: "Should map the secret even if it has a nil value",
|
|
reason: "Should map the secret even if it has a nil value",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secret,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
|
|
|
|
|
+ "data": secret,
|
|
|
|
|
+ }, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -849,11 +763,8 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
reason: "Should map the secret even if it has a nil value",
|
|
reason: "Should map the secret even if it has a nil value",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(secretWithNilVal), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(secretWithNilVal, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -869,15 +780,9 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
reason: "Should map the secret even if it has a nil value",
|
|
reason: "Should map the secret even if it has a nil value",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secretWithNilVal,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
|
|
|
|
|
+ "data": secretWithNilVal}, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -893,15 +798,9 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
reason: "Should map the secret even if it has other types",
|
|
reason: "Should map the secret even if it has other types",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
|
|
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,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
|
|
|
|
|
+ "data": secretWithTypes}, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -923,15 +822,9 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
Property: "nested",
|
|
Property: "nested",
|
|
|
},
|
|
},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secretWithNestedVal,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
|
|
|
|
|
+ "data": secretWithNestedVal}, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -948,15 +841,9 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
data: esv1beta1.ExternalSecretDataRemoteRef{
|
|
|
Property: "nested.foo",
|
|
Property: "nested.foo",
|
|
|
},
|
|
},
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
|
|
|
|
|
- newVaultResponseWithData(
|
|
|
|
|
- map[string]interface{}{
|
|
|
|
|
- "data": secretWithNestedVal,
|
|
|
|
|
- },
|
|
|
|
|
- ), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
|
|
|
|
|
+ "data": secretWithNestedVal}, nil),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -971,9 +858,8 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
reason: "Should return error if vault client fails to read secret.",
|
|
reason: "Should return error if vault client fails to read secret.",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeSecretStore().Spec.Provider.Vault,
|
|
store: makeSecretStore().Spec.Provider.Vault,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(nil, errBoom),
|
|
|
|
|
|
|
+ vClient: &fake.Logical{
|
|
|
|
|
+ ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, errBoom),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
want: want{
|
|
want: want{
|
|
@@ -986,7 +872,7 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Run(name, func(t *testing.T) {
|
|
|
vStore := &client{
|
|
vStore := &client{
|
|
|
kube: tc.args.kube,
|
|
kube: tc.args.kube,
|
|
|
- client: tc.args.vClient,
|
|
|
|
|
|
|
+ logical: tc.args.vClient,
|
|
|
store: tc.args.store,
|
|
store: tc.args.store,
|
|
|
namespace: tc.args.ns,
|
|
namespace: tc.args.ns,
|
|
|
}
|
|
}
|
|
@@ -1001,6 +887,50 @@ func TestGetSecretMap(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func newListWithContextFn(secrets map[string]interface{}) func(ctx context.Context, path string) (*vault.Secret, error) {
|
|
|
|
|
+ return func(ctx context.Context, path string) (*vault.Secret, error) {
|
|
|
|
|
+ path = strings.TrimPrefix(path, "secret/metadata/")
|
|
|
|
|
+ if path == "" {
|
|
|
|
|
+ path = "default"
|
|
|
|
|
+ }
|
|
|
|
|
+ data, ok := secrets[path]
|
|
|
|
|
+ if !ok {
|
|
|
|
|
+ return nil, errors.New("Secret not found")
|
|
|
|
|
+ }
|
|
|
|
|
+ meta := data.(map[string]interface{})
|
|
|
|
|
+ ans := meta["metadata"].(map[string]interface{})
|
|
|
|
|
+ secret := &vault.Secret{
|
|
|
|
|
+ Data: map[string]interface{}{
|
|
|
|
|
+ "keys": ans["keys"],
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+ return secret, nil
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func newReadtWithContextFn(secrets map[string]interface{}) func(ctx context.Context, path string, data map[string][]string) (*vault.Secret, error) {
|
|
|
|
|
+ return func(ctx context.Context, path string, d map[string][]string) (*vault.Secret, error) {
|
|
|
|
|
+ path = strings.TrimPrefix(path, "secret/data/")
|
|
|
|
|
+ path = strings.TrimPrefix(path, "secret/metadata/")
|
|
|
|
|
+ if path == "" {
|
|
|
|
|
+ path = "default"
|
|
|
|
|
+ }
|
|
|
|
|
+ data, ok := secrets[path]
|
|
|
|
|
+ if !ok {
|
|
|
|
|
+ return nil, errors.New("Secret not found")
|
|
|
|
|
+ }
|
|
|
|
|
+ meta := data.(map[string]interface{})
|
|
|
|
|
+ metadata := meta["metadata"].(map[string]interface{})
|
|
|
|
|
+ content := map[string]interface{}{
|
|
|
|
|
+ "data": meta["data"],
|
|
|
|
|
+ "custom_metadata": metadata["custom_metadata"],
|
|
|
|
|
+ }
|
|
|
|
|
+ secret := &vault.Secret{
|
|
|
|
|
+ Data: content,
|
|
|
|
|
+ }
|
|
|
|
|
+ return secret, nil
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
func TestGetAllSecrets(t *testing.T) {
|
|
func TestGetAllSecrets(t *testing.T) {
|
|
|
secret1Bytes := []byte("{\"access_key\":\"access_key\",\"access_secret\":\"access_secret\"}")
|
|
secret1Bytes := []byte("{\"access_key\":\"access_key\",\"access_secret\":\"access_secret\"}")
|
|
|
secret2Bytes := []byte("{\"access_key\":\"access_key2\",\"access_secret\":\"access_secret2\"}")
|
|
secret2Bytes := []byte("{\"access_key\":\"access_key2\",\"access_secret\":\"access_secret2\"}")
|
|
@@ -1010,66 +940,66 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
path := "path"
|
|
path := "path"
|
|
|
secret := map[string]interface{}{
|
|
secret := map[string]interface{}{
|
|
|
"secret1": map[string]interface{}{
|
|
"secret1": map[string]interface{}{
|
|
|
|
|
+ "metadata": map[string]interface{}{
|
|
|
|
|
+ "custom_metadata": map[string]interface{}{
|
|
|
|
|
+ "foo": "bar",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
"data": map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
|
"access_key": "access_key",
|
|
"access_key": "access_key",
|
|
|
"access_secret": "access_secret",
|
|
"access_secret": "access_secret",
|
|
|
},
|
|
},
|
|
|
|
|
+ },
|
|
|
|
|
+ "secret2": map[string]interface{}{
|
|
|
"metadata": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
|
"custom_metadata": map[string]interface{}{
|
|
"custom_metadata": map[string]interface{}{
|
|
|
- "foo": "bar",
|
|
|
|
|
|
|
+ "foo": "baz",
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- },
|
|
|
|
|
- "secret2": map[string]interface{}{
|
|
|
|
|
"data": map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
|
"access_key": "access_key2",
|
|
"access_key": "access_key2",
|
|
|
"access_secret": "access_secret2",
|
|
"access_secret": "access_secret2",
|
|
|
},
|
|
},
|
|
|
|
|
+ },
|
|
|
|
|
+ "tag": map[string]interface{}{
|
|
|
"metadata": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
|
"custom_metadata": map[string]interface{}{
|
|
"custom_metadata": map[string]interface{}{
|
|
|
"foo": "baz",
|
|
"foo": "baz",
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- },
|
|
|
|
|
- "tag": map[string]interface{}{
|
|
|
|
|
"data": map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
|
"access_key": "unfetched",
|
|
"access_key": "unfetched",
|
|
|
"access_secret": "unfetched",
|
|
"access_secret": "unfetched",
|
|
|
},
|
|
},
|
|
|
|
|
+ },
|
|
|
|
|
+ "path/1": map[string]interface{}{
|
|
|
"metadata": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
|
"custom_metadata": map[string]interface{}{
|
|
"custom_metadata": map[string]interface{}{
|
|
|
- "foo": "baz",
|
|
|
|
|
|
|
+ "foo": "path",
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- },
|
|
|
|
|
- "path/1": map[string]interface{}{
|
|
|
|
|
"data": map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
|
"access_key": "path1",
|
|
"access_key": "path1",
|
|
|
"access_secret": "path1",
|
|
"access_secret": "path1",
|
|
|
},
|
|
},
|
|
|
|
|
+ },
|
|
|
|
|
+ "path/2": map[string]interface{}{
|
|
|
"metadata": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
|
"custom_metadata": map[string]interface{}{
|
|
"custom_metadata": map[string]interface{}{
|
|
|
"foo": "path",
|
|
"foo": "path",
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- },
|
|
|
|
|
- "path/2": map[string]interface{}{
|
|
|
|
|
"data": map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
|
"access_key": "path2",
|
|
"access_key": "path2",
|
|
|
"access_secret": "path2",
|
|
"access_secret": "path2",
|
|
|
},
|
|
},
|
|
|
- "metadata": map[string]interface{}{
|
|
|
|
|
- "custom_metadata": map[string]interface{}{
|
|
|
|
|
- "foo": "path",
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
},
|
|
},
|
|
|
"default": map[string]interface{}{
|
|
"default": map[string]interface{}{
|
|
|
"data": map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
|
"empty": "true",
|
|
"empty": "true",
|
|
|
},
|
|
},
|
|
|
"metadata": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
|
- "keys": []string{"secret1", "secret2", "tag", "path/"},
|
|
|
|
|
|
|
+ "keys": []interface{}{"secret1", "secret2", "tag", "path/"},
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
"path/": map[string]interface{}{
|
|
"path/": map[string]interface{}{
|
|
@@ -1077,16 +1007,16 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
"empty": "true",
|
|
"empty": "true",
|
|
|
},
|
|
},
|
|
|
"metadata": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
|
- "keys": []string{"1", "2"},
|
|
|
|
|
|
|
+ "keys": []interface{}{"1", "2"},
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
|
type args struct {
|
|
type args struct {
|
|
|
- store *esv1beta1.VaultProvider
|
|
|
|
|
- kube kclient.Client
|
|
|
|
|
- vClient Client
|
|
|
|
|
- ns string
|
|
|
|
|
- data esv1beta1.ExternalSecretFind
|
|
|
|
|
|
|
+ store *esv1beta1.VaultProvider
|
|
|
|
|
+ kube kclient.Client
|
|
|
|
|
+ vLogical Logical
|
|
|
|
|
+ ns string
|
|
|
|
|
+ data esv1beta1.ExternalSecretFind
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type want struct {
|
|
type want struct {
|
|
@@ -1103,11 +1033,9 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
reason: "should map multiple secrets matching name",
|
|
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{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
- newVaultResponseWithMetadata(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ListWithContextFn: newListWithContextFn(secret),
|
|
|
|
|
+ ReadWithDataWithContextFn: newReadtWithContextFn(secret),
|
|
|
},
|
|
},
|
|
|
data: esv1beta1.ExternalSecretFind{
|
|
data: esv1beta1.ExternalSecretFind{
|
|
|
Name: &esv1beta1.FindName{
|
|
Name: &esv1beta1.FindName{
|
|
@@ -1127,11 +1055,9 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
reason: "should map multiple secrets matching tags",
|
|
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{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
- newVaultResponseWithMetadata(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ListWithContextFn: newListWithContextFn(secret),
|
|
|
|
|
+ ReadWithDataWithContextFn: newReadtWithContextFn(secret),
|
|
|
},
|
|
},
|
|
|
data: esv1beta1.ExternalSecretFind{
|
|
data: esv1beta1.ExternalSecretFind{
|
|
|
Tags: map[string]string{
|
|
Tags: map[string]string{
|
|
@@ -1151,11 +1077,9 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
reason: "should filter secrets based on path",
|
|
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,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
- newVaultResponseWithMetadata(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ListWithContextFn: newListWithContextFn(secret),
|
|
|
|
|
+ ReadWithDataWithContextFn: newReadtWithContextFn(secret),
|
|
|
},
|
|
},
|
|
|
data: esv1beta1.ExternalSecretFind{
|
|
data: esv1beta1.ExternalSecretFind{
|
|
|
Path: &path,
|
|
Path: &path,
|
|
@@ -1176,11 +1100,9 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
reason: "should not work if using kv1 store",
|
|
reason: "should not work if using kv1 store",
|
|
|
args: args{
|
|
args: args{
|
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV1).Spec.Provider.Vault,
|
|
|
- vClient: &fake.VaultClient{
|
|
|
|
|
- MockNewRequest: fake.NewMockNewRequestListFn(&vault.Request{}),
|
|
|
|
|
- MockRawRequestWithContext: fake.NewMockRawRequestListWithContextFn(
|
|
|
|
|
- newVaultResponseWithMetadata(secret), nil,
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+ vLogical: &fake.Logical{
|
|
|
|
|
+ ListWithContextFn: newListWithContextFn(secret),
|
|
|
|
|
+ ReadWithDataWithContextFn: newReadtWithContextFn(secret),
|
|
|
},
|
|
},
|
|
|
data: esv1beta1.ExternalSecretFind{
|
|
data: esv1beta1.ExternalSecretFind{
|
|
|
Tags: map[string]string{
|
|
Tags: map[string]string{
|
|
@@ -1198,7 +1120,7 @@ func TestGetAllSecrets(t *testing.T) {
|
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Run(name, func(t *testing.T) {
|
|
|
vStore := &client{
|
|
vStore := &client{
|
|
|
kube: tc.args.kube,
|
|
kube: tc.args.kube,
|
|
|
- client: tc.args.vClient,
|
|
|
|
|
|
|
+ logical: tc.args.vLogical,
|
|
|
store: tc.args.store,
|
|
store: tc.args.store,
|
|
|
namespace: tc.args.ns,
|
|
namespace: tc.args.ns,
|
|
|
}
|
|
}
|