kms_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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 alibaba
  13. import (
  14. "context"
  15. "fmt"
  16. "reflect"
  17. "strings"
  18. "testing"
  19. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
  20. kmssdk "github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
  21. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  22. fakesm "github.com/external-secrets/external-secrets/pkg/provider/alibaba/fake"
  23. )
  24. const (
  25. secretName = "test-example"
  26. secretValue = "value"
  27. )
  28. type keyManagementServiceTestCase struct {
  29. mockClient *fakesm.AlibabaMockClient
  30. apiInput *kmssdk.GetSecretValueRequest
  31. apiOutput *kmssdk.GetSecretValueResponse
  32. ref *esv1beta1.ExternalSecretDataRemoteRef
  33. apiErr error
  34. expectError string
  35. expectedSecret string
  36. // for testing secretmap
  37. expectedData map[string][]byte
  38. }
  39. func makeValidKMSTestCase() *keyManagementServiceTestCase {
  40. kmstc := keyManagementServiceTestCase{
  41. mockClient: &fakesm.AlibabaMockClient{},
  42. apiInput: makeValidAPIInput(),
  43. ref: makeValidRef(),
  44. apiOutput: makeValidAPIOutput(),
  45. apiErr: nil,
  46. expectError: "",
  47. expectedSecret: "",
  48. expectedData: make(map[string][]byte),
  49. }
  50. kmstc.mockClient.WithValue(kmstc.apiInput, kmstc.apiOutput, kmstc.apiErr)
  51. return &kmstc
  52. }
  53. func makeValidRef() *esv1beta1.ExternalSecretDataRemoteRef {
  54. return &esv1beta1.ExternalSecretDataRemoteRef{
  55. Key: secretName,
  56. }
  57. }
  58. func makeValidAPIInput() *kmssdk.GetSecretValueRequest {
  59. return &kmssdk.GetSecretValueRequest{
  60. SecretName: secretName,
  61. }
  62. }
  63. func makeValidAPIOutput() *kmssdk.GetSecretValueResponse {
  64. kmsresponse := &kmssdk.GetSecretValueResponse{
  65. BaseResponse: &responses.BaseResponse{},
  66. RequestId: "",
  67. SecretName: secretName,
  68. VersionId: "",
  69. CreateTime: "",
  70. SecretData: secretValue,
  71. SecretDataType: "",
  72. AutomaticRotation: "",
  73. RotationInterval: "",
  74. NextRotationDate: "",
  75. ExtendedConfig: "",
  76. LastRotationDate: "",
  77. SecretType: "",
  78. VersionStages: kmssdk.VersionStagesInGetSecretValue{},
  79. }
  80. return kmsresponse
  81. }
  82. func makeValidKMSTestCaseCustom(tweaks ...func(kmstc *keyManagementServiceTestCase)) *keyManagementServiceTestCase {
  83. kmstc := makeValidKMSTestCase()
  84. for _, fn := range tweaks {
  85. fn(kmstc)
  86. }
  87. kmstc.mockClient.WithValue(kmstc.apiInput, kmstc.apiOutput, kmstc.apiErr)
  88. return kmstc
  89. }
  90. var setAPIErr = func(kmstc *keyManagementServiceTestCase) {
  91. kmstc.apiErr = fmt.Errorf("oh no")
  92. kmstc.expectError = "oh no"
  93. }
  94. var setNilMockClient = func(kmstc *keyManagementServiceTestCase) {
  95. kmstc.mockClient = nil
  96. kmstc.expectError = errUninitalizedAlibabaProvider
  97. }
  98. func TestAlibabaKMSGetSecret(t *testing.T) {
  99. secretData := make(map[string]interface{})
  100. secretValue := "changedvalue"
  101. secretData["payload"] = secretValue
  102. // good case: default version is set
  103. // key is passed in, output is sent back
  104. setSecretString := func(kmstc *keyManagementServiceTestCase) {
  105. kmstc.apiOutput.SecretName = secretName
  106. kmstc.apiOutput.SecretData = secretValue
  107. kmstc.expectedSecret = secretValue
  108. }
  109. // good case: custom version set
  110. setCustomKey := func(kmstc *keyManagementServiceTestCase) {
  111. kmstc.apiOutput.SecretName = "test-example-other"
  112. kmstc.ref.Key = "test-example-other"
  113. kmstc.apiOutput.SecretData = secretValue
  114. kmstc.expectedSecret = secretValue
  115. }
  116. successCases := []*keyManagementServiceTestCase{
  117. makeValidKMSTestCaseCustom(setSecretString),
  118. makeValidKMSTestCaseCustom(setCustomKey),
  119. makeValidKMSTestCaseCustom(setAPIErr),
  120. makeValidKMSTestCaseCustom(setNilMockClient),
  121. }
  122. sm := KeyManagementService{}
  123. for k, v := range successCases {
  124. sm.Client = v.mockClient
  125. out, err := sm.GetSecret(context.Background(), *v.ref)
  126. if !ErrorContains(err, v.expectError) {
  127. t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
  128. }
  129. if string(out) != v.expectedSecret {
  130. t.Errorf("[%d] unexpected secret: expected %s, got %s", k, v.expectedSecret, string(out))
  131. }
  132. }
  133. }
  134. func TestGetSecretMap(t *testing.T) {
  135. // good case: default version & deserialization
  136. setDeserialization := func(kmstc *keyManagementServiceTestCase) {
  137. kmstc.apiOutput.SecretName = "foo"
  138. kmstc.expectedData["foo"] = []byte("bar")
  139. kmstc.apiOutput.SecretData = `{"foo":"bar"}`
  140. }
  141. // bad case: invalid json
  142. setInvalidJSON := func(kmstc *keyManagementServiceTestCase) {
  143. kmstc.apiOutput.SecretData = "-----------------"
  144. kmstc.expectError = "unable to unmarshal secret"
  145. }
  146. successCases := []*keyManagementServiceTestCase{
  147. makeValidKMSTestCaseCustom(setDeserialization),
  148. makeValidKMSTestCaseCustom(setInvalidJSON),
  149. makeValidKMSTestCaseCustom(setNilMockClient),
  150. makeValidKMSTestCaseCustom(setAPIErr),
  151. }
  152. sm := KeyManagementService{}
  153. for k, v := range successCases {
  154. sm.Client = v.mockClient
  155. out, err := sm.GetSecretMap(context.Background(), *v.ref)
  156. if !ErrorContains(err, v.expectError) {
  157. t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
  158. }
  159. if err == nil && !reflect.DeepEqual(out, v.expectedData) {
  160. t.Errorf("[%d] unexpected secret data: expected %#v, got %#v", k, v.expectedData, out)
  161. }
  162. }
  163. }
  164. func ErrorContains(out error, want string) bool {
  165. if out == nil {
  166. return want == ""
  167. }
  168. if want == "" {
  169. return false
  170. }
  171. return strings.Contains(out.Error(), want)
  172. }