client_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package grpc
  13. import (
  14. "context"
  15. "net"
  16. "testing"
  17. "google.golang.org/grpc"
  18. "google.golang.org/grpc/credentials/insecure"
  19. "google.golang.org/grpc/test/bufconn"
  20. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  21. pb "github.com/external-secrets/external-secrets/proto/provider"
  22. )
  23. const bufSize = 1024 * 1024
  24. // mockServer is a simple mock implementation of the SecretStoreProvider service
  25. type mockServer struct {
  26. pb.UnimplementedSecretStoreProviderServer
  27. getSecretResponse *pb.GetSecretResponse
  28. getSecretMap map[string][]byte
  29. validateResponse *pb.ValidateResponse
  30. }
  31. func (m *mockServer) GetSecret(ctx context.Context, req *pb.GetSecretRequest) (*pb.GetSecretResponse, error) {
  32. if m.getSecretResponse != nil {
  33. return m.getSecretResponse, nil
  34. }
  35. return &pb.GetSecretResponse{
  36. Value: []byte("test-secret-value"),
  37. }, nil
  38. }
  39. func (m *mockServer) GetSecretMap(ctx context.Context, req *pb.GetSecretMapRequest) (*pb.GetSecretMapResponse, error) {
  40. if m.getSecretMap != nil {
  41. return &pb.GetSecretMapResponse{Secrets: m.getSecretMap}, nil
  42. }
  43. return &pb.GetSecretMapResponse{
  44. Secrets: map[string][]byte{
  45. "foo": []byte("bar"),
  46. },
  47. }, nil
  48. }
  49. func (m *mockServer) Validate(ctx context.Context, req *pb.ValidateRequest) (*pb.ValidateResponse, error) {
  50. if m.validateResponse != nil {
  51. return m.validateResponse, nil
  52. }
  53. return &pb.ValidateResponse{
  54. Valid: true,
  55. }, nil
  56. }
  57. // setupTestServer creates an in-memory gRPC server for testing
  58. func setupTestServer(t *testing.T, mock *mockServer) (*grpc.ClientConn, func()) {
  59. lis := bufconn.Listen(bufSize)
  60. baseServer := grpc.NewServer()
  61. pb.RegisterSecretStoreProviderServer(baseServer, mock)
  62. go func() {
  63. if err := baseServer.Serve(lis); err != nil {
  64. t.Logf("Server exited with error: %v", err)
  65. }
  66. }()
  67. conn, err := grpc.DialContext(context.Background(), "",
  68. grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
  69. return lis.Dial()
  70. }),
  71. grpc.WithTransportCredentials(insecure.NewCredentials()))
  72. if err != nil {
  73. t.Fatalf("Failed to dial bufnet: %v", err)
  74. }
  75. cleanup := func() {
  76. conn.Close()
  77. baseServer.Stop()
  78. lis.Close()
  79. }
  80. return conn, cleanup
  81. }
  82. func TestClient_GetSecret(t *testing.T) {
  83. mock := &mockServer{}
  84. conn, cleanup := setupTestServer(t, mock)
  85. defer cleanup()
  86. client := NewClientWithConn(conn)
  87. ref := esv1.ExternalSecretDataRemoteRef{
  88. Key: "test-key",
  89. Version: "v1",
  90. Property: "password",
  91. }
  92. value, err := client.GetSecret(context.Background(), ref, &pb.ProviderReference{Name: "provider"}, "default")
  93. if err != nil {
  94. t.Fatalf("GetSecret failed: %v", err)
  95. }
  96. if string(value) != "test-secret-value" {
  97. t.Errorf("Expected 'test-secret-value', got '%s'", string(value))
  98. }
  99. }
  100. func TestClient_Validate(t *testing.T) {
  101. t.Run("success", func(t *testing.T) {
  102. mock := &mockServer{}
  103. conn, cleanup := setupTestServer(t, mock)
  104. defer cleanup()
  105. client := NewClientWithConn(conn)
  106. err := client.Validate(context.Background(), &pb.ProviderReference{Name: "provider"}, "default")
  107. if err != nil {
  108. t.Fatalf("Validate failed: %v", err)
  109. }
  110. })
  111. t.Run("validation_error", func(t *testing.T) {
  112. mock := &mockServer{
  113. validateResponse: &pb.ValidateResponse{
  114. Valid: false,
  115. Error: "invalid credentials",
  116. },
  117. }
  118. conn, cleanup := setupTestServer(t, mock)
  119. defer cleanup()
  120. client := NewClientWithConn(conn)
  121. err := client.Validate(context.Background(), &pb.ProviderReference{Name: "provider"}, "default")
  122. if err == nil {
  123. t.Fatal("Expected validation to fail, but it succeeded")
  124. }
  125. if err.Error() != "provider validation failed: invalid credentials" {
  126. t.Errorf("Unexpected error message: %v", err)
  127. }
  128. })
  129. }
  130. func TestClient_GetSecretMap(t *testing.T) {
  131. mock := &mockServer{
  132. getSecretMap: map[string][]byte{
  133. "a": []byte("b"),
  134. },
  135. }
  136. conn, cleanup := setupTestServer(t, mock)
  137. defer cleanup()
  138. client := NewClientWithConn(conn)
  139. value, err := client.GetSecretMap(
  140. context.Background(),
  141. esv1.ExternalSecretDataRemoteRef{Key: "test-key"},
  142. &pb.ProviderReference{Name: "provider"},
  143. "default",
  144. )
  145. if err != nil {
  146. t.Fatalf("GetSecretMap failed: %v", err)
  147. }
  148. if string(value["a"]) != "b" {
  149. t.Fatalf("Expected map[a]=b, got %#v", value)
  150. }
  151. }
  152. func TestClient_Close(t *testing.T) {
  153. mock := &mockServer{}
  154. conn, cleanup := setupTestServer(t, mock)
  155. defer cleanup()
  156. client := NewClientWithConn(conn)
  157. err := client.Close(context.Background())
  158. if err != nil {
  159. t.Fatalf("Close failed: %v", err)
  160. }
  161. }
  162. func TestNewClient_InvalidAddress(t *testing.T) {
  163. _, err := NewClient("", nil)
  164. if err == nil {
  165. t.Fatal("Expected error for empty address, got nil")
  166. }
  167. }