| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835 |
- /*
- Copyright © The ESO Authors
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- https://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package grpc
- import (
- "bytes"
- "context"
- "net"
- "testing"
- "time"
- "google.golang.org/grpc"
- "google.golang.org/grpc/credentials/insecure"
- "google.golang.org/grpc/test/bufconn"
- "google.golang.org/protobuf/reflect/protoreflect"
- corev1 "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
- pb "github.com/external-secrets/external-secrets/proto/provider"
- v2 "github.com/external-secrets/external-secrets/providers/v2/common"
- )
- const (
- bufSize = 1024 * 1024
- testCompatibilityStoreName = "compat-store"
- testSourceNamespace = "tenant-a"
- )
- type mockServer struct {
- pb.UnimplementedSecretStoreProviderServer
- getSecretResponse *pb.GetSecretResponse
- getSecretRequest *pb.GetSecretRequest
- getSecretMapResponse *pb.GetSecretMapResponse
- getSecretMapRequest *pb.GetSecretMapRequest
- getAllSecretsResponse *pb.GetAllSecretsResponse
- getAllSecretsRequest *pb.GetAllSecretsRequest
- pushSecretRequest *pb.PushSecretRequest
- deleteRequest *pb.DeleteSecretRequest
- existsRequest *pb.SecretExistsRequest
- existsResponse *pb.SecretExistsResponse
- validateResponse *pb.ValidateResponse
- validateRequest *pb.ValidateRequest
- capabilitiesResponse *pb.CapabilitiesResponse
- capabilitiesRequest *pb.CapabilitiesRequest
- getAllSecretsDeadline time.Duration
- }
- func (m *mockServer) GetSecret(_ context.Context, req *pb.GetSecretRequest) (*pb.GetSecretResponse, error) {
- m.getSecretRequest = req
- if m.getSecretResponse != nil {
- return m.getSecretResponse, nil
- }
- return &pb.GetSecretResponse{Value: []byte("test-secret-value")}, nil
- }
- func (m *mockServer) GetSecretMap(_ context.Context, req *pb.GetSecretMapRequest) (*pb.GetSecretMapResponse, error) {
- m.getSecretMapRequest = req
- if m.getSecretMapResponse != nil {
- return m.getSecretMapResponse, nil
- }
- return &pb.GetSecretMapResponse{
- Secrets: map[string][]byte{"foo": []byte("bar")},
- }, nil
- }
- func (m *mockServer) GetAllSecrets(ctx context.Context, req *pb.GetAllSecretsRequest) (*pb.GetAllSecretsResponse, error) {
- m.getAllSecretsRequest = req
- if deadline, ok := ctx.Deadline(); ok {
- m.getAllSecretsDeadline = time.Until(deadline)
- }
- if m.getAllSecretsResponse != nil {
- return m.getAllSecretsResponse, nil
- }
- return &pb.GetAllSecretsResponse{
- Secrets: map[string][]byte{"db-password": []byte("value")},
- }, nil
- }
- func (m *mockServer) PushSecret(_ context.Context, req *pb.PushSecretRequest) (*pb.PushSecretResponse, error) {
- m.pushSecretRequest = req
- return &pb.PushSecretResponse{}, nil
- }
- func (m *mockServer) DeleteSecret(_ context.Context, req *pb.DeleteSecretRequest) (*pb.DeleteSecretResponse, error) {
- m.deleteRequest = req
- return &pb.DeleteSecretResponse{}, nil
- }
- func (m *mockServer) SecretExists(_ context.Context, req *pb.SecretExistsRequest) (*pb.SecretExistsResponse, error) {
- m.existsRequest = req
- if m.existsResponse != nil {
- return m.existsResponse, nil
- }
- return &pb.SecretExistsResponse{Exists: true}, nil
- }
- func (m *mockServer) Validate(_ context.Context, req *pb.ValidateRequest) (*pb.ValidateResponse, error) {
- m.validateRequest = req
- if m.validateResponse != nil {
- return m.validateResponse, nil
- }
- return &pb.ValidateResponse{Valid: true}, nil
- }
- func (m *mockServer) Capabilities(_ context.Context, req *pb.CapabilitiesRequest) (*pb.CapabilitiesResponse, error) {
- m.capabilitiesRequest = req
- if m.capabilitiesResponse != nil {
- return m.capabilitiesResponse, nil
- }
- return &pb.CapabilitiesResponse{Capabilities: pb.SecretStoreCapabilities_READ_WRITE}, nil
- }
- func setupTestServer(t *testing.T, mock *mockServer) (*grpc.ClientConn, func()) {
- t.Helper()
- lis := bufconn.Listen(bufSize)
- baseServer := grpc.NewServer()
- pb.RegisterSecretStoreProviderServer(baseServer, mock)
- go func() {
- if err := baseServer.Serve(lis); err != nil {
- t.Logf("Server exited with error: %v", err)
- }
- }()
- conn, err := grpc.DialContext(context.Background(), "",
- grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
- return lis.Dial()
- }),
- grpc.WithTransportCredentials(insecure.NewCredentials()))
- if err != nil {
- t.Fatalf("Failed to dial bufnet: %v", err)
- }
- cleanup := func() {
- _ = conn.Close()
- baseServer.Stop()
- _ = lis.Close()
- }
- return conn, cleanup
- }
- func TestClientGetSecretSendsProviderReferenceAndNamespace(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderStoreKindStr}
- ref := esv1.ExternalSecretDataRemoteRef{
- Key: "test-key",
- Version: "v1",
- Property: "password",
- DecodingStrategy: esv1.ExternalSecretDecodeBase64,
- MetadataPolicy: esv1.ExternalSecretMetadataPolicyFetch,
- }
- value, err := client.GetSecret(context.Background(), ref, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("GetSecret failed: %v", err)
- }
- if string(value) != "test-secret-value" {
- t.Fatalf("expected test-secret-value, got %q", string(value))
- }
- if mock.getSecretRequest == nil {
- t.Fatal("expected get secret request to be recorded")
- }
- assertProviderRefEqual(t, mock.getSecretRequest.ProviderRef, providerRef)
- if mock.getSecretRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected source namespace: %q", mock.getSecretRequest.SourceNamespace)
- }
- if mock.getSecretRequest.RemoteRef.Key != "test-key" || mock.getSecretRequest.RemoteRef.Version != "v1" || mock.getSecretRequest.RemoteRef.Property != "password" {
- t.Fatalf("unexpected remote ref: %#v", mock.getSecretRequest.RemoteRef)
- }
- if mock.getSecretRequest.RemoteRef.DecodingStrategy != string(esv1.ExternalSecretDecodeBase64) {
- t.Fatalf("unexpected decoding strategy: %q", mock.getSecretRequest.RemoteRef.DecodingStrategy)
- }
- if mock.getSecretRequest.RemoteRef.MetadataPolicy != string(esv1.ExternalSecretMetadataPolicyFetch) {
- t.Fatalf("unexpected metadata policy: %q", mock.getSecretRequest.RemoteRef.MetadataPolicy)
- }
- }
- func TestClientGetSecretMapSendsProviderReferenceAndNamespace(t *testing.T) {
- mock := &mockServer{
- getSecretMapResponse: &pb.GetSecretMapResponse{
- Secrets: map[string][]byte{"a": []byte("b")},
- },
- }
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderStoreKindStr}
- value, err := client.GetSecretMap(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "test-key"}, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("GetSecretMap failed: %v", err)
- }
- if string(value["a"]) != "b" {
- t.Fatalf("expected map[a]=b, got %#v", value)
- }
- if mock.getSecretMapRequest == nil {
- t.Fatal("expected get secret map request to be recorded")
- }
- if mock.getSecretMapRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected request: %#v", mock.getSecretMapRequest)
- }
- assertProviderRefEqual(t, mock.getSecretMapRequest.ProviderRef, providerRef)
- }
- func TestClientGetAllSecretsSendsFindCriteria(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderStoreKindStr}
- path := "/team-a"
- secrets, err := client.GetAllSecrets(context.Background(), esv1.ExternalSecretFind{
- Tags: map[string]string{"team": "a"},
- Path: &path,
- Name: &esv1.FindName{RegExp: "db-.*"},
- }, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("GetAllSecrets failed: %v", err)
- }
- if string(secrets["db-password"]) != "value" {
- t.Fatalf("unexpected secrets: %#v", secrets)
- }
- if mock.getAllSecretsRequest == nil {
- t.Fatal("expected get all secrets request to be recorded")
- }
- if mock.getAllSecretsRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected request: %#v", mock.getAllSecretsRequest)
- }
- assertProviderRefEqual(t, mock.getAllSecretsRequest.ProviderRef, providerRef)
- if mock.getAllSecretsRequest.Find.Path != "/team-a" {
- t.Fatalf("unexpected path: %q", mock.getAllSecretsRequest.Find.Path)
- }
- if mock.getAllSecretsRequest.Find.Name == nil || mock.getAllSecretsRequest.Find.Name.Regexp != "db-.*" {
- t.Fatalf("unexpected name matcher: %#v", mock.getAllSecretsRequest.Find.Name)
- }
- }
- func TestClientGetAllSecretsUsesExtendedTimeout(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderStoreKindStr}
- _, err := client.GetAllSecrets(context.Background(), esv1.ExternalSecretFind{
- Name: &esv1.FindName{RegExp: "db-.*"},
- }, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("GetAllSecrets failed: %v", err)
- }
- if mock.getAllSecretsDeadline <= defaultTimeout {
- t.Fatalf("expected GetAllSecrets timeout to exceed default timeout %s, got %s", defaultTimeout, mock.getAllSecretsDeadline)
- }
- }
- func TestClientGetSecretSendsCompatibilityStore(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- compatibilityStore := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "config-ns",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: []byte(`{"provider":{"fake":{"data":[{"key":"test-key","value":"test-secret-value"}]}}}`),
- }
- value, err := client.GetSecret(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "test-key"}, nil, compatibilityStore, testSourceNamespace)
- if err != nil {
- t.Fatalf("GetSecret failed: %v", err)
- }
- if string(value) != "test-secret-value" {
- t.Fatalf("expected test-secret-value, got %q", string(value))
- }
- if mock.getSecretRequest == nil {
- t.Fatal("expected get secret request to be recorded")
- }
- if mock.getSecretRequest.ProviderRef != nil {
- t.Fatalf("expected provider ref to be omitted, got %#v", mock.getSecretRequest.ProviderRef)
- }
- if mock.getSecretRequest.CompatibilityStore == nil {
- t.Fatal("expected compatibility store to be recorded")
- }
- if mock.getSecretRequest.CompatibilityStore.StoreName != testCompatibilityStoreName {
- t.Fatalf("unexpected compatibility store: %#v", mock.getSecretRequest.CompatibilityStore)
- }
- }
- func TestClientGetSecretMapSendsCompatibilityStore(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- compatibilityStore := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "config-ns",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: []byte(`{"provider":{"fake":{"data":[{"key":"test-key","value":"test-secret-value"}]}}}`),
- }
- _, err := client.GetSecretMap(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "test-key"}, nil, compatibilityStore, testSourceNamespace)
- if err != nil {
- t.Fatalf("GetSecretMap failed: %v", err)
- }
- if mock.getSecretMapRequest == nil {
- t.Fatal("expected get secret map request to be recorded")
- }
- if mock.getSecretMapRequest.ProviderRef != nil {
- t.Fatalf("expected provider ref to be omitted, got %#v", mock.getSecretMapRequest.ProviderRef)
- }
- if mock.getSecretMapRequest.CompatibilityStore == nil {
- t.Fatal("expected compatibility store to be recorded")
- }
- if mock.getSecretMapRequest.CompatibilityStore.StoreName != testCompatibilityStoreName {
- t.Fatalf("unexpected compatibility store: %#v", mock.getSecretMapRequest.CompatibilityStore)
- }
- }
- func TestClientGetAllSecretsSendsCompatibilityStore(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- compatibilityStore := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "config-ns",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: []byte(`{"provider":{"fake":{"data":[{"key":"test-key","value":"test-secret-value"}]}}}`),
- }
- _, err := client.GetAllSecrets(context.Background(), esv1.ExternalSecretFind{}, nil, compatibilityStore, testSourceNamespace)
- if err != nil {
- t.Fatalf("GetAllSecrets failed: %v", err)
- }
- if mock.getAllSecretsRequest == nil {
- t.Fatal("expected get all secrets request to be recorded")
- }
- if mock.getAllSecretsRequest.ProviderRef != nil {
- t.Fatalf("expected provider ref to be omitted, got %#v", mock.getAllSecretsRequest.ProviderRef)
- }
- if mock.getAllSecretsRequest.CompatibilityStore == nil {
- t.Fatal("expected compatibility store to be recorded")
- }
- if mock.getAllSecretsRequest.CompatibilityStore.StoreName != testCompatibilityStoreName {
- t.Fatalf("unexpected compatibility store: %#v", mock.getAllSecretsRequest.CompatibilityStore)
- }
- }
- func TestClientValidateSendsCompatibilityStore(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- compatibilityStore := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "config-ns",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: []byte(`{"provider":{"fake":{"data":[{"key":"test-key","value":"test-secret-value"}]}}}`),
- }
- err := client.Validate(context.Background(), nil, compatibilityStore, testSourceNamespace)
- if err != nil {
- t.Fatalf("Validate failed: %v", err)
- }
- if mock.validateRequest == nil {
- t.Fatal("expected validate request to be recorded")
- }
- if mock.validateRequest.ProviderRef != nil {
- t.Fatalf("expected provider ref to be omitted, got %#v", mock.validateRequest.ProviderRef)
- }
- if mock.validateRequest.CompatibilityStore == nil {
- t.Fatal("expected compatibility store to be recorded")
- }
- }
- func TestClientPushSecretSendsCompatibilityStore(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- compatibilityStore := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "config-ns",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: []byte(`{"provider":{"fake":{"data":[{"key":"test-key","value":"test-secret-value"}]}}}`),
- }
- err := client.PushSecret(context.Background(), &corev1.Secret{
- Data: map[string][]byte{"token": []byte("value")},
- }, &pb.PushSecretData{RemoteKey: "remote", SecretKey: "token"}, nil, compatibilityStore, testSourceNamespace)
- if err != nil {
- t.Fatalf("PushSecret failed: %v", err)
- }
- if mock.pushSecretRequest == nil {
- t.Fatal("expected push secret request to be recorded")
- }
- if mock.pushSecretRequest.ProviderRef != nil {
- t.Fatalf("expected provider ref to be omitted, got %#v", mock.pushSecretRequest.ProviderRef)
- }
- if mock.pushSecretRequest.CompatibilityStore == nil {
- t.Fatal("expected compatibility store to be recorded")
- }
- }
- func TestClientDeleteSecretSendsCompatibilityStore(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- compatibilityStore := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "config-ns",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: []byte(`{"provider":{"fake":{"data":[{"key":"test-key","value":"test-secret-value"}]}}}`),
- }
- err := client.DeleteSecret(context.Background(), &pb.PushSecretRemoteRef{RemoteKey: "remote"}, nil, compatibilityStore, testSourceNamespace)
- if err != nil {
- t.Fatalf("DeleteSecret failed: %v", err)
- }
- if mock.deleteRequest == nil {
- t.Fatal("expected delete secret request to be recorded")
- }
- if mock.deleteRequest.ProviderRef != nil {
- t.Fatalf("expected provider ref to be omitted, got %#v", mock.deleteRequest.ProviderRef)
- }
- if mock.deleteRequest.CompatibilityStore == nil {
- t.Fatal("expected compatibility store to be recorded")
- }
- }
- func TestClientSecretExistsSendsCompatibilityStore(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- compatibilityStore := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "config-ns",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: []byte(`{"provider":{"fake":{"data":[{"key":"test-key","value":"test-secret-value"}]}}}`),
- }
- exists, err := client.SecretExists(context.Background(), &pb.PushSecretRemoteRef{RemoteKey: "remote"}, nil, compatibilityStore, testSourceNamespace)
- if err != nil {
- t.Fatalf("SecretExists failed: %v", err)
- }
- if !exists {
- t.Fatal("expected secret to exist")
- }
- if mock.existsRequest == nil {
- t.Fatal("expected secret exists request to be recorded")
- }
- if mock.existsRequest.ProviderRef != nil {
- t.Fatalf("expected provider ref to be omitted, got %#v", mock.existsRequest.ProviderRef)
- }
- if mock.existsRequest.CompatibilityStore == nil {
- t.Fatal("expected compatibility store to be recorded")
- }
- }
- func TestReadRequestIdentityValidationRejectsMissingReadIdentity(t *testing.T) {
- testCases := []struct {
- name string
- call func(client v2.Provider) error
- }{
- {
- name: "get secret",
- call: func(client v2.Provider) error {
- _, err := client.GetSecret(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "sample"}, nil, nil, testSourceNamespace)
- return err
- },
- },
- {
- name: "get secret map",
- call: func(client v2.Provider) error {
- _, err := client.GetSecretMap(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "sample"}, nil, nil, testSourceNamespace)
- return err
- },
- },
- {
- name: "get all secrets",
- call: func(client v2.Provider) error {
- _, err := client.GetAllSecrets(context.Background(), esv1.ExternalSecretFind{}, nil, nil, testSourceNamespace)
- return err
- },
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- err := tc.call(NewClientWithConn(conn))
- if err == nil || err.Error() != "provider reference or compatibility store is required for read operations" {
- t.Fatalf("unexpected error: %v", err)
- }
- })
- }
- }
- func TestCompatibilityStoreLogFieldsRedactSpecPayload(t *testing.T) {
- specPayload := []byte(`{"provider":{"fake":{"data":[{"key":"db","value":"secret-value"}]}}}`)
- store := &pb.CompatibilityStore{
- StoreName: testCompatibilityStoreName,
- StoreNamespace: "team-a",
- StoreKind: esv1.SecretStoreKind,
- StoreUid: "uid-1",
- StoreGeneration: 7,
- StoreSpecJson: specPayload,
- }
- fields := compatibilityStoreLogFields(store)
- if len(fields) == 0 {
- t.Fatal("expected compatibility store log fields")
- }
- found := map[string]bool{}
- for i := 0; i < len(fields); i += 2 {
- key, ok := fields[i].(string)
- if !ok {
- t.Fatalf("expected string log key, got %T", fields[i])
- }
- found[key] = true
- if bytes.Equal([]byte(key), specPayload) {
- t.Fatalf("unexpected spec payload key: %q", key)
- }
- value := fields[i+1]
- if value == store {
- t.Fatalf("unexpected raw compatibility store in log fields")
- }
- if payload, ok := value.([]byte); ok && bytes.Equal(payload, specPayload) {
- t.Fatalf("unexpected raw spec payload in log fields")
- }
- if text, ok := value.(string); ok && text == string(specPayload) {
- t.Fatalf("unexpected raw spec payload string in log fields")
- }
- }
- for _, key := range []string{
- "compatibilityStoreKind",
- "compatibilityStoreName",
- "compatibilityStoreNamespace",
- "compatibilityStoreUID",
- "compatibilityStoreGeneration",
- "compatibilityStoreSpecBytes",
- } {
- if !found[key] {
- t.Fatalf("expected log field %q, got %#v", key, fields)
- }
- }
- }
- func TestClientPushDeleteExistsAndCapabilitiesSendProviderReferenceAndNamespace(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderStoreKindStr}
- err := client.PushSecret(context.Background(), &corev1.Secret{
- Data: map[string][]byte{"token": []byte("value")},
- }, &pb.PushSecretData{
- RemoteKey: "remote/path",
- SecretKey: "token",
- Property: "property",
- Metadata: []byte(`{"mergePolicy":"replace"}`),
- }, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("PushSecret failed: %v", err)
- }
- if mock.pushSecretRequest == nil {
- t.Fatal("expected push secret request to be recorded")
- }
- if mock.pushSecretRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected push request: %#v", mock.pushSecretRequest)
- }
- assertProviderRefEqual(t, mock.pushSecretRequest.ProviderRef, providerRef)
- if string(mock.pushSecretRequest.SecretData["token"]) != "value" {
- t.Fatalf("unexpected pushed secret data: %#v", mock.pushSecretRequest.SecretData)
- }
- err = client.DeleteSecret(context.Background(), &pb.PushSecretRemoteRef{
- RemoteKey: "remote/path",
- Property: "property",
- }, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("DeleteSecret failed: %v", err)
- }
- if mock.deleteRequest == nil || mock.deleteRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected delete request: %#v", mock.deleteRequest)
- }
- assertProviderRefEqual(t, mock.deleteRequest.ProviderRef, providerRef)
- exists, err := client.SecretExists(context.Background(), &pb.PushSecretRemoteRef{
- RemoteKey: "remote/path",
- Property: "property",
- }, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("SecretExists failed: %v", err)
- }
- if !exists {
- t.Fatal("expected exists to be true")
- }
- if mock.existsRequest == nil || mock.existsRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected exists request: %#v", mock.existsRequest)
- }
- assertProviderRefEqual(t, mock.existsRequest.ProviderRef, providerRef)
- caps, err := client.Capabilities(context.Background(), providerRef, testSourceNamespace)
- if err != nil {
- t.Fatalf("Capabilities failed: %v", err)
- }
- if caps != pb.SecretStoreCapabilities_READ_WRITE {
- t.Fatalf("expected READ_WRITE, got %v", caps)
- }
- if mock.capabilitiesRequest == nil || mock.capabilitiesRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected capabilities request: %#v", mock.capabilitiesRequest)
- }
- assertProviderRefEqual(t, mock.capabilitiesRequest.ProviderRef, providerRef)
- }
- func TestClientPushSecretSendsExpandedKubernetesSecretFields(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ClusterProviderStoreKindStr}
- err := client.PushSecret(context.Background(), &corev1.Secret{
- Type: corev1.SecretTypeDockerConfigJson,
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{"team": "platform"},
- Annotations: map[string]string{"owner": "app-team"},
- },
- Data: map[string][]byte{
- ".dockerconfigjson": []byte("payload"),
- },
- }, &pb.PushSecretData{
- RemoteKey: "remote/path",
- SecretKey: ".dockerconfigjson",
- Property: "property",
- Metadata: []byte(`{"mergePolicy":"replace"}`),
- }, providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("PushSecret failed: %v", err)
- }
- if mock.pushSecretRequest == nil {
- t.Fatal("expected push secret request to be recorded")
- }
- if got, want := string(mock.pushSecretRequest.SecretData[".dockerconfigjson"]), "payload"; got != want {
- t.Errorf("expected request secret data %q, got %q", want, got)
- }
- assertProviderRefEqual(t, mock.pushSecretRequest.ProviderRef, providerRef)
- if got, want := mock.pushSecretRequest.SourceNamespace, testSourceNamespace; got != want {
- t.Errorf("expected source namespace %q, got %q", want, got)
- }
- if got, want := mock.pushSecretRequest.SecretType, string(corev1.SecretTypeDockerConfigJson); got != want {
- t.Errorf("expected secret_type=%q, got %q", want, got)
- }
- if got, want := mock.pushSecretRequest.SecretLabels["team"], "platform"; got != want {
- t.Errorf("expected secret_labels.team=%q, got %q", want, got)
- }
- if got, want := mock.pushSecretRequest.SecretAnnotations["owner"], "app-team"; got != want {
- t.Errorf("expected secret_annotations.owner=%q, got %q", want, got)
- }
- if got, want := string(mock.pushSecretRequest.PushSecretData.Metadata), `{"mergePolicy":"replace"}`; got != want {
- t.Errorf("expected metadata=%q, got %q", want, got)
- }
- }
- func TestClientValidate(t *testing.T) {
- t.Run("success", func(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- providerRef := &pb.ProviderReference{Name: "provider", Namespace: "config-ns", StoreRefKind: esv1.ProviderStoreKindStr}
- err := client.Validate(context.Background(), providerRef, nil, testSourceNamespace)
- if err != nil {
- t.Fatalf("Validate failed: %v", err)
- }
- if mock.validateRequest == nil {
- t.Fatal("expected validate request to be recorded")
- }
- if mock.validateRequest.SourceNamespace != testSourceNamespace {
- t.Fatalf("unexpected validate request: %#v", mock.validateRequest)
- }
- assertProviderRefEqual(t, mock.validateRequest.ProviderRef, providerRef)
- })
- t.Run("validation_error", func(t *testing.T) {
- mock := &mockServer{
- validateResponse: &pb.ValidateResponse{
- Valid: false,
- Error: "invalid credentials",
- },
- }
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- err := client.Validate(context.Background(), &pb.ProviderReference{Name: "provider"}, nil, testSourceNamespace)
- if err == nil {
- t.Fatal("Expected validation to fail, but it succeeded")
- }
- if err.Error() != "provider validation failed: invalid credentials" {
- t.Fatalf("unexpected error message: %v", err)
- }
- })
- }
- func TestClientClose(t *testing.T) {
- mock := &mockServer{}
- conn, cleanup := setupTestServer(t, mock)
- defer cleanup()
- client := NewClientWithConn(conn)
- if err := client.Close(context.Background()); err != nil {
- t.Fatalf("Close failed: %v", err)
- }
- }
- func TestNewClientInvalidAddress(t *testing.T) {
- _, err := NewClient("", nil)
- if err == nil {
- t.Fatal("expected error for empty address, got nil")
- }
- }
- func assertProviderRefEqual(t *testing.T, got, want *pb.ProviderReference) {
- t.Helper()
- if got == nil || want == nil {
- t.Fatalf("provider refs must not be nil: got=%#v want=%#v", got, want)
- }
- if got.ApiVersion != want.ApiVersion || got.Kind != want.Kind || got.Name != want.Name || got.Namespace != want.Namespace || got.StoreRefKind != want.StoreRefKind {
- t.Fatalf("unexpected provider ref: got=%#v want=%#v", got, want)
- }
- }
- func TestProtoCompatibilityRequestsExposeCompatibilityStoreField(t *testing.T) {
- cases := []struct {
- name string
- msg protoreflect.ProtoMessage
- }{
- {name: "GetSecretRequest", msg: &pb.GetSecretRequest{}},
- {name: "GetSecretMapRequest", msg: &pb.GetSecretMapRequest{}},
- {name: "GetAllSecretsRequest", msg: &pb.GetAllSecretsRequest{}},
- {name: "ValidateRequest", msg: &pb.ValidateRequest{}},
- {name: "PushSecretRequest", msg: &pb.PushSecretRequest{}},
- {name: "DeleteSecretRequest", msg: &pb.DeleteSecretRequest{}},
- {name: "SecretExistsRequest", msg: &pb.SecretExistsRequest{}},
- }
- for _, tc := range cases {
- t.Run(tc.name, func(t *testing.T) {
- fields := tc.msg.ProtoReflect().Descriptor().Fields()
- if fields.ByName("compatibility_store") == nil {
- t.Fatalf("expected %s to have field compatibility_store", tc.name)
- }
- })
- }
- }
|