provider_test.go 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  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 ibm
  13. import (
  14. "context"
  15. "encoding/json"
  16. "fmt"
  17. "reflect"
  18. "strconv"
  19. "strings"
  20. "testing"
  21. "time"
  22. "github.com/IBM/go-sdk-core/v5/core"
  23. sm "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2"
  24. "github.com/go-openapi/strfmt"
  25. corev1 "k8s.io/api/core/v1"
  26. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  27. utilpointer "k8s.io/utils/ptr"
  28. clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
  29. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  30. v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
  31. fakesm "github.com/external-secrets/external-secrets/pkg/provider/ibm/fake"
  32. )
  33. const (
  34. errExpectedErr = "wanted error got nil"
  35. secretKey = "test-secret"
  36. secretUUID = "d5deb37a-7883-4fe2-a5e7-3c15420adc76"
  37. iamCredentialsSecret = "iam_credentials/"
  38. )
  39. type secretManagerTestCase struct {
  40. name string
  41. mockClient *fakesm.IBMMockClient
  42. apiInput *sm.GetSecretOptions
  43. apiOutput sm.SecretIntf
  44. listInput *sm.ListSecretsOptions
  45. listOutput *sm.SecretMetadataPaginatedCollection
  46. listError error
  47. ref *esv1beta1.ExternalSecretDataRemoteRef
  48. serviceURL *string
  49. apiErr error
  50. expectError string
  51. expectedSecret string
  52. // for testing secretmap
  53. expectedData map[string][]byte
  54. }
  55. func makeValidSecretManagerTestCase() *secretManagerTestCase {
  56. smtc := secretManagerTestCase{
  57. mockClient: &fakesm.IBMMockClient{},
  58. apiInput: makeValidAPIInput(),
  59. ref: makeValidRef(),
  60. apiOutput: makeValidAPIOutput(),
  61. listInput: makeValidListInput(),
  62. listOutput: makeValidListSecretsOutput(),
  63. listError: nil,
  64. serviceURL: nil,
  65. apiErr: nil,
  66. expectError: "",
  67. expectedSecret: "",
  68. expectedData: map[string][]byte{},
  69. }
  70. mcParams := fakesm.IBMMockClientParams{
  71. GetSecretOptions: smtc.apiInput,
  72. GetSecretOutput: smtc.apiOutput,
  73. GetSecretErr: smtc.apiErr,
  74. ListSecretsOptions: smtc.listInput,
  75. ListSecretsOutput: smtc.listOutput,
  76. ListSecretsErr: smtc.listError,
  77. }
  78. smtc.mockClient.WithValue(mcParams)
  79. return &smtc
  80. }
  81. func makeValidRef() *esv1beta1.ExternalSecretDataRemoteRef {
  82. return &esv1beta1.ExternalSecretDataRemoteRef{
  83. Key: secretUUID,
  84. Version: "default",
  85. }
  86. }
  87. func makeValidAPIInput() *sm.GetSecretOptions {
  88. return &sm.GetSecretOptions{
  89. ID: utilpointer.To(secretUUID),
  90. }
  91. }
  92. func makeValidAPIOutput() sm.SecretIntf {
  93. secret := &sm.Secret{
  94. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  95. Name: utilpointer.To("testyname"),
  96. ID: utilpointer.To(secretUUID),
  97. }
  98. var i sm.SecretIntf = secret
  99. return i
  100. }
  101. func makeValidListSecretsOutput() *sm.SecretMetadataPaginatedCollection {
  102. list := sm.SecretMetadataPaginatedCollection{}
  103. return &list
  104. }
  105. func makeValidListInput() *sm.ListSecretsOptions {
  106. listOpt := sm.ListSecretsOptions{}
  107. return &listOpt
  108. }
  109. func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTestCase)) *secretManagerTestCase {
  110. smtc := makeValidSecretManagerTestCase()
  111. for _, fn := range tweaks {
  112. fn(smtc)
  113. }
  114. mcParams := fakesm.IBMMockClientParams{
  115. GetSecretOptions: smtc.apiInput,
  116. GetSecretOutput: smtc.apiOutput,
  117. GetSecretErr: smtc.apiErr,
  118. ListSecretsOptions: smtc.listInput,
  119. ListSecretsOutput: smtc.listOutput,
  120. ListSecretsErr: smtc.listError,
  121. }
  122. smtc.mockClient.WithValue(mcParams)
  123. return smtc
  124. }
  125. // This case can be shared by both GetSecret and GetSecretMap tests.
  126. // bad case: set apiErr.
  127. var setAPIErr = func(smtc *secretManagerTestCase) {
  128. smtc.apiErr = fmt.Errorf("oh no")
  129. smtc.expectError = "oh no"
  130. }
  131. var setNilMockClient = func(smtc *secretManagerTestCase) {
  132. smtc.mockClient = nil
  133. smtc.expectError = errUninitalizedIBMProvider
  134. }
  135. // simple tests for Validate Store.
  136. func TestValidateStore(t *testing.T) {
  137. p := providerIBM{}
  138. store := &esv1beta1.SecretStore{
  139. Spec: esv1beta1.SecretStoreSpec{
  140. Provider: &esv1beta1.SecretStoreProvider{
  141. IBM: &esv1beta1.IBMProvider{},
  142. },
  143. },
  144. }
  145. err := p.ValidateStore(store)
  146. if err == nil {
  147. t.Errorf(errExpectedErr)
  148. } else if err.Error() != "serviceURL is required" {
  149. t.Errorf("service URL test failed")
  150. }
  151. url := "my-url"
  152. store.Spec.Provider.IBM.ServiceURL = &url
  153. var nilProfile esv1beta1.IBMAuthContainerAuth
  154. store.Spec.Provider.IBM.Auth.ContainerAuth = nilProfile
  155. err = p.ValidateStore(store)
  156. if err == nil {
  157. t.Errorf(errExpectedErr)
  158. } else if err.Error() != "secretAPIKey.name cannot be empty" {
  159. t.Errorf("KeySelector test failed: expected secret name is required, got %v", err)
  160. }
  161. store.Spec.Provider.IBM.Auth.SecretRef.SecretAPIKey.Name = "foo"
  162. store.Spec.Provider.IBM.Auth.SecretRef.SecretAPIKey.Key = "bar"
  163. ns := "ns-one"
  164. store.Spec.Provider.IBM.Auth.SecretRef.SecretAPIKey.Namespace = &ns
  165. err = p.ValidateStore(store)
  166. if err == nil {
  167. t.Errorf(errExpectedErr)
  168. } else if err.Error() != "namespace not allowed with namespaced SecretStore" {
  169. t.Errorf("KeySelector test failed: expected namespace not allowed, got %v", err)
  170. }
  171. // add container auth test
  172. store.Spec.Provider.IBM = &esv1beta1.IBMProvider{}
  173. store.Spec.Provider.IBM.ServiceURL = &url
  174. store.Spec.Provider.IBM.Auth.ContainerAuth.Profile = "Trusted IAM Profile"
  175. store.Spec.Provider.IBM.Auth.ContainerAuth.TokenLocation = "/a/path/to/nowhere/that/should/exist"
  176. err = p.ValidateStore(store)
  177. expected := "cannot read container auth token"
  178. if !ErrorContains(err, expected) {
  179. t.Errorf("ProfileSelector test failed: %s, expected: '%s'", err.Error(), expected)
  180. }
  181. }
  182. // test the sm<->gcp interface
  183. // make sure correct values are passed and errors are handled accordingly.
  184. func TestIBMSecretManagerGetSecret(t *testing.T) {
  185. secretString := "changedvalue"
  186. secretUsername := "userName"
  187. secretPassword := "P@ssw0rd"
  188. secretAPIKey := "01234567890"
  189. secretCertificate := "certificate_value"
  190. // good case: default version is set
  191. // key is passed in, output is sent back
  192. setSecretString := func(smtc *secretManagerTestCase) {
  193. secret := &sm.ArbitrarySecret{
  194. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  195. Name: utilpointer.To("testyname"),
  196. ID: utilpointer.To(secretUUID),
  197. Payload: &secretString,
  198. }
  199. smtc.name = "good case: default version is set"
  200. smtc.apiOutput = secret
  201. smtc.apiInput.ID = utilpointer.To(secretUUID)
  202. smtc.expectedSecret = secretString
  203. }
  204. // good case: custom version set
  205. setCustomKey := func(smtc *secretManagerTestCase) {
  206. secret := &sm.ArbitrarySecret{
  207. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  208. Name: utilpointer.To("testyname"),
  209. ID: utilpointer.To(secretUUID),
  210. Payload: &secretString,
  211. }
  212. smtc.name = "good case: custom version set"
  213. smtc.ref.Key = "arbitrary/" + secretUUID
  214. smtc.apiInput.ID = utilpointer.To(secretUUID)
  215. smtc.apiOutput = secret
  216. smtc.expectedSecret = secretString
  217. }
  218. // bad case: arbitrary type secret which is destroyed
  219. badArbitSecret := func(smtc *secretManagerTestCase) {
  220. secret := &sm.UsernamePasswordSecret{
  221. SecretType: utilpointer.To(sm.Secret_SecretType_UsernamePassword),
  222. Name: utilpointer.To("testyname"),
  223. ID: utilpointer.To(secretUUID),
  224. }
  225. smtc.name = "bad case: username_password type without property"
  226. smtc.apiInput.ID = utilpointer.To(secretUUID)
  227. smtc.apiOutput = secret
  228. smtc.ref.Key = secretUUID
  229. smtc.expectError = "key payload does not exist in secret " + secretUUID
  230. }
  231. // bad case: username_password type without property
  232. secretUserPass := "username_password/" + secretUUID
  233. badSecretUserPass := func(smtc *secretManagerTestCase) {
  234. secret := &sm.UsernamePasswordSecret{
  235. SecretType: utilpointer.To(sm.Secret_SecretType_UsernamePassword),
  236. Name: utilpointer.To("testyname"),
  237. ID: utilpointer.To(secretUUID),
  238. Username: &secretUsername,
  239. Password: &secretPassword,
  240. }
  241. smtc.name = "bad case: username_password type without property"
  242. smtc.apiInput.ID = utilpointer.To(secretUUID)
  243. smtc.apiOutput = secret
  244. smtc.ref.Key = secretUserPass
  245. smtc.expectError = "remoteRef.property required for secret type username_password"
  246. }
  247. // good case: username_password type with property
  248. funcSetUserPass := func(secretName, property, name string) func(smtc *secretManagerTestCase) {
  249. return func(smtc *secretManagerTestCase) {
  250. secret := &sm.UsernamePasswordSecret{
  251. SecretType: utilpointer.To(sm.Secret_SecretType_UsernamePassword),
  252. Name: utilpointer.To("testyname"),
  253. ID: utilpointer.To(secretUUID),
  254. Username: &secretUsername,
  255. Password: &secretPassword,
  256. }
  257. secretMetadata := &sm.UsernamePasswordSecretMetadata{
  258. Name: utilpointer.To("testyname"),
  259. ID: utilpointer.To(secretUUID),
  260. }
  261. smtc.name = name
  262. smtc.apiInput.ID = utilpointer.To(secretUUID)
  263. smtc.apiOutput = secret
  264. smtc.listInput.Search = utilpointer.To("testyname")
  265. smtc.listOutput.Secrets = make([]sm.SecretMetadataIntf, 1)
  266. smtc.listOutput.Secrets[0] = secretMetadata
  267. smtc.ref.Key = "username_password/" + secretName
  268. smtc.ref.Property = property
  269. if property == "username" {
  270. smtc.expectedSecret = secretUsername
  271. } else {
  272. smtc.expectedSecret = secretPassword
  273. }
  274. }
  275. }
  276. setSecretUserPassByID := funcSetUserPass(secretUUID, "username", "good case: username_password type - get username by ID")
  277. setSecretUserPassUsername := funcSetUserPass("testyname", "username", "good case: username_password type - get username by secret name")
  278. setSecretUserPassPassword := funcSetUserPass("testyname", "password", "good case: username_password type - get password by secret name")
  279. // good case: iam_credentials type
  280. funcSetSecretIam := func(secretName, name string) func(*secretManagerTestCase) {
  281. return func(smtc *secretManagerTestCase) {
  282. secret := &sm.IAMCredentialsSecret{
  283. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  284. Name: utilpointer.To("testyname"),
  285. ID: utilpointer.To(secretUUID),
  286. ApiKey: utilpointer.To(secretAPIKey),
  287. }
  288. secretMetadata := &sm.IAMCredentialsSecretMetadata{
  289. Name: utilpointer.To("testyname"),
  290. ID: utilpointer.To(secretUUID),
  291. }
  292. smtc.apiInput.ID = utilpointer.To(secretUUID)
  293. smtc.name = name
  294. smtc.apiOutput = secret
  295. smtc.listInput.Search = utilpointer.To("testyname")
  296. smtc.listOutput.Secrets = make([]sm.SecretMetadataIntf, 1)
  297. smtc.listOutput.Secrets[0] = secretMetadata
  298. smtc.ref.Key = iamCredentialsSecret + secretName
  299. smtc.expectedSecret = secretAPIKey
  300. }
  301. }
  302. setSecretIamByID := funcSetSecretIam(secretUUID, "good case: iam_credenatials type - get API Key by ID")
  303. setSecretIamByName := funcSetSecretIam("testyname", "good case: iam_credenatials type - get API Key by name")
  304. funcSetCertSecretTest := func(secret sm.SecretIntf, name, certType string, good bool) func(*secretManagerTestCase) {
  305. return func(smtc *secretManagerTestCase) {
  306. smtc.name = name
  307. smtc.apiInput.ID = utilpointer.To(secretUUID)
  308. smtc.apiOutput = secret
  309. smtc.ref.Key = certType + "/" + secretUUID
  310. if good {
  311. smtc.ref.Property = "certificate"
  312. smtc.expectedSecret = secretCertificate
  313. } else {
  314. smtc.expectError = "remoteRef.property required for secret type " + certType
  315. }
  316. }
  317. }
  318. // good case: imported_cert type with property
  319. importedCert := &sm.ImportedCertificate{
  320. SecretType: utilpointer.To(sm.Secret_SecretType_ImportedCert),
  321. Name: utilpointer.To("testyname"),
  322. ID: utilpointer.To(secretUUID),
  323. Certificate: utilpointer.To(secretCertificate),
  324. Intermediate: utilpointer.To("intermediate"),
  325. PrivateKey: utilpointer.To("private_key"),
  326. }
  327. setSecretCert := funcSetCertSecretTest(importedCert, "good case: imported_cert type with property", sm.Secret_SecretType_ImportedCert, true)
  328. // good case: imported_cert type without a private_key
  329. importedCertNoPvtKey := func(smtc *secretManagerTestCase) {
  330. secret := &sm.ImportedCertificate{
  331. SecretType: utilpointer.To(sm.Secret_SecretType_ImportedCert),
  332. Name: utilpointer.To("testyname"),
  333. ID: utilpointer.To(secretUUID),
  334. Certificate: utilpointer.To(secretCertificate),
  335. }
  336. smtc.name = "good case: imported cert without private key"
  337. smtc.apiInput.ID = utilpointer.To(secretUUID)
  338. smtc.apiOutput = secret
  339. smtc.ref.Key = "imported_cert/" + secretUUID
  340. smtc.ref.Property = "private_key"
  341. smtc.expectedSecret = ""
  342. }
  343. // bad case: imported_cert type without property
  344. badSecretCert := funcSetCertSecretTest(importedCert, "bad case: imported_cert type without property", sm.Secret_SecretType_ImportedCert, false)
  345. // good case: public_cert type with property
  346. publicCert := &sm.PublicCertificate{
  347. SecretType: utilpointer.To(sm.Secret_SecretType_PublicCert),
  348. Name: utilpointer.To("testyname"),
  349. ID: utilpointer.To(secretUUID),
  350. Certificate: utilpointer.To(secretCertificate),
  351. Intermediate: utilpointer.To("intermediate"),
  352. PrivateKey: utilpointer.To("private_key"),
  353. }
  354. setSecretPublicCert := funcSetCertSecretTest(publicCert, "good case: public_cert type with property", sm.Secret_SecretType_PublicCert, true)
  355. // bad case: public_cert type without property
  356. badSecretPublicCert := funcSetCertSecretTest(publicCert, "bad case: public_cert type without property", sm.Secret_SecretType_PublicCert, false)
  357. // good case: private_cert type with property
  358. privateCert := &sm.PrivateCertificate{
  359. SecretType: utilpointer.To(sm.Secret_SecretType_PublicCert),
  360. Name: utilpointer.To("testyname"),
  361. ID: utilpointer.To(secretUUID),
  362. Certificate: utilpointer.To(secretCertificate),
  363. PrivateKey: utilpointer.To("private_key"),
  364. }
  365. setSecretPrivateCert := funcSetCertSecretTest(privateCert, "good case: private_cert type with property", sm.Secret_SecretType_PrivateCert, true)
  366. // bad case: private_cert type without property
  367. badSecretPrivateCert := funcSetCertSecretTest(privateCert, "bad case: private_cert type without property", sm.Secret_SecretType_PrivateCert, false)
  368. secretDataKV := make(map[string]interface{})
  369. secretDataKV["key1"] = "val1"
  370. secretDataKVComplex := make(map[string]interface{})
  371. secretKVComplex := `{"key1":"val1","key2":"val2","key3":"val3","keyC":{"keyC1":"valC1","keyC2":"valC2"},"special.log":"file-content"}`
  372. json.Unmarshal([]byte(secretKVComplex), &secretDataKVComplex)
  373. secretKV := "kv/" + secretUUID
  374. // bad case: kv type with key which is not in payload
  375. badSecretKV := func(smtc *secretManagerTestCase) {
  376. secret := &sm.KVSecret{
  377. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  378. Name: utilpointer.To("testyname"),
  379. ID: utilpointer.To(secretUUID),
  380. Data: secretDataKV,
  381. }
  382. smtc.name = "bad case: kv type with key which is not in payload"
  383. smtc.apiInput.ID = utilpointer.To(secretUUID)
  384. smtc.apiOutput = secret
  385. smtc.ref.Key = secretKV
  386. smtc.ref.Property = "other-key"
  387. smtc.expectError = "key other-key does not exist in secret kv/" + secretUUID
  388. }
  389. // good case: kv type with property
  390. setSecretKV := func(smtc *secretManagerTestCase) {
  391. secret := &sm.KVSecret{
  392. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  393. Name: utilpointer.To("testyname"),
  394. ID: utilpointer.To(secretUUID),
  395. Data: secretDataKV,
  396. }
  397. smtc.name = "good case: kv type with property"
  398. smtc.apiInput.ID = utilpointer.To(secretUUID)
  399. smtc.apiOutput = secret
  400. smtc.ref.Key = secretKV
  401. smtc.ref.Property = "key1"
  402. smtc.expectedSecret = "val1"
  403. }
  404. // good case: kv type with property, returns specific value
  405. setSecretKVWithKey := func(smtc *secretManagerTestCase) {
  406. secret := &sm.KVSecret{
  407. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  408. Name: utilpointer.To("testyname"),
  409. ID: utilpointer.To(secretUUID),
  410. Data: secretDataKVComplex,
  411. }
  412. smtc.name = "good case: kv type with property, returns specific value"
  413. smtc.apiInput.ID = utilpointer.To(secretUUID)
  414. smtc.apiOutput = secret
  415. smtc.ref.Key = secretKV
  416. smtc.ref.Property = "key2"
  417. smtc.expectedSecret = "val2"
  418. }
  419. // good case: kv type with property and path, returns specific value
  420. setSecretKVWithKeyPath := func(smtc *secretManagerTestCase) {
  421. secret := &sm.KVSecret{
  422. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  423. Name: utilpointer.To("testyname"),
  424. ID: utilpointer.To(secretUUID),
  425. Data: secretDataKVComplex,
  426. }
  427. smtc.name = "good case: kv type with property and path, returns specific value"
  428. smtc.apiInput.ID = utilpointer.To(secretUUID)
  429. smtc.apiOutput = secret
  430. smtc.ref.Key = secretKV
  431. smtc.ref.Property = "keyC.keyC2"
  432. smtc.expectedSecret = "valC2"
  433. }
  434. // good case: kv type with property and dot, returns specific value
  435. setSecretKVWithKeyDot := func(smtc *secretManagerTestCase) {
  436. secret := &sm.KVSecret{
  437. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  438. Name: utilpointer.To("testyname"),
  439. ID: utilpointer.To(secretUUID),
  440. Data: secretDataKVComplex,
  441. }
  442. smtc.name = "good case: kv type with property and dot, returns specific value"
  443. smtc.apiInput.ID = utilpointer.To(secretUUID)
  444. smtc.apiOutput = secret
  445. smtc.ref.Key = secretKV
  446. smtc.ref.Property = "special.log"
  447. smtc.expectedSecret = "file-content"
  448. }
  449. // good case: kv type without property, returns all
  450. setSecretKVWithOutKey := func(smtc *secretManagerTestCase) {
  451. secret := &sm.KVSecret{
  452. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  453. Name: utilpointer.To("testyname"),
  454. ID: utilpointer.To(secretUUID),
  455. Data: secretDataKVComplex,
  456. }
  457. smtc.name = "good case: kv type without property, returns all"
  458. smtc.apiInput.ID = utilpointer.To(secretUUID)
  459. smtc.apiOutput = secret
  460. smtc.ref.Key = secretKV
  461. smtc.expectedSecret = secretKVComplex
  462. }
  463. successCases := []*secretManagerTestCase{
  464. makeValidSecretManagerTestCaseCustom(setSecretString),
  465. makeValidSecretManagerTestCaseCustom(setCustomKey),
  466. makeValidSecretManagerTestCaseCustom(badArbitSecret),
  467. makeValidSecretManagerTestCaseCustom(setAPIErr),
  468. makeValidSecretManagerTestCaseCustom(setNilMockClient),
  469. makeValidSecretManagerTestCaseCustom(badSecretUserPass),
  470. makeValidSecretManagerTestCaseCustom(setSecretUserPassByID),
  471. makeValidSecretManagerTestCaseCustom(setSecretUserPassUsername),
  472. makeValidSecretManagerTestCaseCustom(setSecretUserPassPassword),
  473. makeValidSecretManagerTestCaseCustom(setSecretIamByID),
  474. makeValidSecretManagerTestCaseCustom(setSecretIamByName),
  475. makeValidSecretManagerTestCaseCustom(setSecretCert),
  476. makeValidSecretManagerTestCaseCustom(setSecretKV),
  477. makeValidSecretManagerTestCaseCustom(setSecretKVWithKey),
  478. makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyPath),
  479. makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyDot),
  480. makeValidSecretManagerTestCaseCustom(setSecretKVWithOutKey),
  481. makeValidSecretManagerTestCaseCustom(badSecretKV),
  482. makeValidSecretManagerTestCaseCustom(badSecretCert),
  483. makeValidSecretManagerTestCaseCustom(importedCertNoPvtKey),
  484. makeValidSecretManagerTestCaseCustom(setSecretPublicCert),
  485. makeValidSecretManagerTestCaseCustom(badSecretPublicCert),
  486. makeValidSecretManagerTestCaseCustom(setSecretPrivateCert),
  487. makeValidSecretManagerTestCaseCustom(badSecretPrivateCert),
  488. }
  489. sm := providerIBM{}
  490. for _, v := range successCases {
  491. t.Run(v.name, func(t *testing.T) {
  492. sm.IBMClient = v.mockClient
  493. sm.cache = NewCache(10, 1*time.Minute)
  494. out, err := sm.GetSecret(context.Background(), *v.ref)
  495. if !ErrorContains(err, v.expectError) {
  496. t.Errorf("unexpected error:\n%s, expected:\n'%s'", err.Error(), v.expectError)
  497. }
  498. if string(out) != v.expectedSecret {
  499. t.Errorf("unexpected secret: expected:\n%s\ngot:\n%s", v.expectedSecret, string(out))
  500. }
  501. })
  502. }
  503. }
  504. func TestGetSecretMap(t *testing.T) {
  505. secretUsername := "user1"
  506. secretPassword := "P@ssw0rd"
  507. secretAPIKey := "01234567890"
  508. nilValue := "<nil>"
  509. secretCertificate := "certificate_value"
  510. secretPrivateKey := "private_key_value"
  511. secretIntermediate := "intermediate_value"
  512. timeValue := "0001-01-01T00:00:00.000Z"
  513. secretComplex := map[string]interface{}{
  514. "key1": "val1",
  515. "key2": "val2",
  516. "keyC": map[string]interface{}{
  517. "keyC1": map[string]string{
  518. "keyA": "valA",
  519. "keyB": "valB",
  520. },
  521. },
  522. }
  523. // good case: arbitrary
  524. setArbitrary := func(smtc *secretManagerTestCase) {
  525. payload := `{"foo":"bar"}`
  526. secret := &sm.ArbitrarySecret{
  527. Name: utilpointer.To("testyname"),
  528. ID: utilpointer.To(secretUUID),
  529. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  530. Payload: &payload,
  531. }
  532. smtc.name = "good case: arbitrary"
  533. smtc.apiInput.ID = utilpointer.To(secretUUID)
  534. smtc.apiOutput = secret
  535. smtc.ref.Key = secretUUID
  536. smtc.expectedData["arbitrary"] = []byte(payload)
  537. }
  538. // good case: username_password
  539. setSecretUserPass := func(smtc *secretManagerTestCase) {
  540. secret := &sm.UsernamePasswordSecret{
  541. Name: utilpointer.To("testyname"),
  542. ID: utilpointer.To(secretUUID),
  543. SecretType: utilpointer.To(sm.Secret_SecretType_UsernamePassword),
  544. Username: &secretUsername,
  545. Password: &secretPassword,
  546. }
  547. smtc.name = "good case: username_password"
  548. smtc.apiInput.ID = utilpointer.To(secretUUID)
  549. smtc.apiOutput = secret
  550. smtc.ref.Key = "username_password/" + secretUUID
  551. smtc.expectedData["username"] = []byte(secretUsername)
  552. smtc.expectedData["password"] = []byte(secretPassword)
  553. }
  554. // good case: iam_credentials
  555. setSecretIam := func(smtc *secretManagerTestCase) {
  556. secret := &sm.IAMCredentialsSecret{
  557. Name: utilpointer.To("testyname"),
  558. ID: utilpointer.To(secretUUID),
  559. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  560. ApiKey: utilpointer.To(secretAPIKey),
  561. }
  562. smtc.name = "good case: iam_credentials"
  563. smtc.apiInput.ID = utilpointer.To(secretUUID)
  564. smtc.apiOutput = secret
  565. smtc.ref.Key = iamCredentialsSecret + secretUUID
  566. smtc.expectedData["apikey"] = []byte(secretAPIKey)
  567. }
  568. // bad case: iam_credentials of a destroyed secret
  569. badSecretIam := func(smtc *secretManagerTestCase) {
  570. secret := &sm.IAMCredentialsSecret{
  571. Name: utilpointer.To("testyname"),
  572. ID: utilpointer.To(secretUUID),
  573. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  574. }
  575. smtc.name = "good case: iam_credentials"
  576. smtc.apiInput.ID = utilpointer.To(secretUUID)
  577. smtc.apiOutput = secret
  578. smtc.ref.Key = iamCredentialsSecret + secretUUID
  579. smtc.expectError = "key api_key does not exist in secret " + secretUUID
  580. }
  581. funcCertTest := func(secret sm.SecretIntf, name, certType string) func(*secretManagerTestCase) {
  582. return func(smtc *secretManagerTestCase) {
  583. smtc.name = name
  584. smtc.apiInput.ID = utilpointer.To(secretUUID)
  585. smtc.apiOutput = secret
  586. smtc.ref.Key = certType + "/" + secretUUID
  587. smtc.expectedData["certificate"] = []byte(secretCertificate)
  588. smtc.expectedData["private_key"] = []byte(secretPrivateKey)
  589. smtc.expectedData["intermediate"] = []byte(secretIntermediate)
  590. }
  591. }
  592. // good case: imported_cert
  593. importedCert := &sm.ImportedCertificate{
  594. SecretType: utilpointer.To(sm.Secret_SecretType_ImportedCert),
  595. Name: utilpointer.To("testyname"),
  596. ID: utilpointer.To(secretUUID),
  597. Certificate: utilpointer.To(secretCertificate),
  598. Intermediate: utilpointer.To(secretIntermediate),
  599. PrivateKey: utilpointer.To(secretPrivateKey),
  600. }
  601. setSecretCert := funcCertTest(importedCert, "good case: imported_cert", sm.Secret_SecretType_ImportedCert)
  602. // good case: public_cert
  603. publicCert := &sm.PublicCertificate{
  604. SecretType: utilpointer.To(sm.Secret_SecretType_PublicCert),
  605. Name: utilpointer.To("testyname"),
  606. ID: utilpointer.To(secretUUID),
  607. Certificate: utilpointer.To(secretCertificate),
  608. Intermediate: utilpointer.To(secretIntermediate),
  609. PrivateKey: utilpointer.To(secretPrivateKey),
  610. }
  611. setSecretPublicCert := funcCertTest(publicCert, "good case: public_cert", sm.Secret_SecretType_PublicCert)
  612. // good case: private_cert
  613. setSecretPrivateCert := func(smtc *secretManagerTestCase) {
  614. secret := &sm.PrivateCertificate{
  615. Name: utilpointer.To("testyname"),
  616. ID: utilpointer.To(secretUUID),
  617. SecretType: utilpointer.To(sm.Secret_SecretType_PrivateCert),
  618. Certificate: &secretCertificate,
  619. PrivateKey: &secretPrivateKey,
  620. }
  621. smtc.name = "good case: private_cert"
  622. smtc.apiInput.ID = utilpointer.To(secretUUID)
  623. smtc.apiOutput = secret
  624. smtc.ref.Key = "private_cert/" + secretUUID
  625. smtc.expectedData["certificate"] = []byte(secretCertificate)
  626. smtc.expectedData["private_key"] = []byte(secretPrivateKey)
  627. }
  628. // good case: arbitrary with metadata
  629. setArbitraryWithMetadata := func(smtc *secretManagerTestCase) {
  630. payload := `{"foo":"bar"}`
  631. secret := &sm.ArbitrarySecret{
  632. CreatedBy: utilpointer.To("testCreatedBy"),
  633. CreatedAt: &strfmt.DateTime{},
  634. Downloaded: utilpointer.To(false),
  635. Labels: []string{"abc", "def", "xyz"},
  636. LocksTotal: utilpointer.To(int64(20)),
  637. Payload: &payload,
  638. }
  639. smtc.name = "good case: arbitrary with metadata"
  640. smtc.apiInput.ID = utilpointer.To(secretUUID)
  641. smtc.apiOutput = secret
  642. smtc.ref.Key = secretUUID
  643. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch
  644. smtc.expectedData = map[string][]byte{"arbitrary": []byte(payload),
  645. "created_at": []byte(timeValue),
  646. "created_by": []byte(*secret.CreatedBy),
  647. "crn": []byte(nilValue),
  648. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  649. "id": []byte(nilValue),
  650. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  651. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  652. "payload": []byte(payload),
  653. "secret_group_id": []byte(nilValue),
  654. "secret_type": []byte(nilValue),
  655. "updated_at": []byte(nilValue),
  656. "versions_total": []byte(nilValue),
  657. }
  658. }
  659. // good case: iam_credentials with metadata
  660. setSecretIamWithMetadata := func(smtc *secretManagerTestCase) {
  661. secret := &sm.IAMCredentialsSecret{
  662. CreatedBy: utilpointer.To("testCreatedBy"),
  663. CreatedAt: &strfmt.DateTime{},
  664. Downloaded: utilpointer.To(false),
  665. Labels: []string{"abc", "def", "xyz"},
  666. LocksTotal: utilpointer.To(int64(20)),
  667. ApiKey: utilpointer.To(secretAPIKey),
  668. }
  669. smtc.name = "good case: iam_credentials with metadata"
  670. smtc.apiInput.ID = utilpointer.To(secretUUID)
  671. smtc.apiOutput = secret
  672. smtc.ref.Key = iamCredentialsSecret + secretUUID
  673. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch
  674. smtc.expectedData = map[string][]byte{"api_key": []byte(secretAPIKey),
  675. "apikey": []byte(secretAPIKey),
  676. "created_at": []byte(timeValue),
  677. "created_by": []byte(*secret.CreatedBy),
  678. "crn": []byte(nilValue),
  679. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  680. "id": []byte(nilValue),
  681. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  682. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  683. "reuse_api_key": []byte(nilValue),
  684. "secret_group_id": []byte(nilValue),
  685. "secret_type": []byte(nilValue),
  686. "ttl": []byte(nilValue),
  687. "updated_at": []byte(nilValue),
  688. "versions_total": []byte(nilValue),
  689. }
  690. }
  691. // "good case: username_password with metadata
  692. setSecretUserPassWithMetadata := func(smtc *secretManagerTestCase) {
  693. secret := &sm.UsernamePasswordSecret{
  694. CreatedBy: utilpointer.To("testCreatedBy"),
  695. CreatedAt: &strfmt.DateTime{},
  696. Downloaded: utilpointer.To(false),
  697. Labels: []string{"abc", "def", "xyz"},
  698. LocksTotal: utilpointer.To(int64(20)),
  699. Username: &secretUsername,
  700. Password: &secretPassword,
  701. }
  702. smtc.name = "good case: username_password with metadata"
  703. smtc.apiInput.ID = utilpointer.To(secretUUID)
  704. smtc.apiOutput = secret
  705. smtc.ref.Key = "username_password/" + secretUUID
  706. smtc.expectedData["username"] = []byte(secretUsername)
  707. smtc.expectedData["password"] = []byte(secretPassword)
  708. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch
  709. smtc.expectedData = map[string][]byte{
  710. "created_at": []byte(timeValue),
  711. "created_by": []byte(*secret.CreatedBy),
  712. "crn": []byte(nilValue),
  713. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  714. "id": []byte(nilValue),
  715. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  716. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  717. "password": []byte(secretPassword),
  718. "rotation": []byte(nilValue),
  719. "secret_group_id": []byte(nilValue),
  720. "secret_type": []byte(nilValue),
  721. "updated_at": []byte(nilValue),
  722. "username": []byte(secretUsername),
  723. "versions_total": []byte(nilValue),
  724. }
  725. }
  726. // good case: imported_cert with metadata
  727. setimportedCertWithMetadata := func(smtc *secretManagerTestCase) {
  728. secret := &sm.ImportedCertificate{
  729. CreatedBy: utilpointer.To("testCreatedBy"),
  730. CreatedAt: &strfmt.DateTime{},
  731. Downloaded: utilpointer.To(false),
  732. Labels: []string{"abc", "def", "xyz"},
  733. LocksTotal: utilpointer.To(int64(20)),
  734. Certificate: utilpointer.To(secretCertificate),
  735. Intermediate: utilpointer.To(secretIntermediate),
  736. PrivateKey: utilpointer.To(secretPrivateKey),
  737. }
  738. smtc.name = "good case: imported_cert with metadata"
  739. smtc.apiInput.ID = utilpointer.To(secretUUID)
  740. smtc.apiOutput = secret
  741. smtc.ref.Key = "imported_cert" + "/" + secretUUID
  742. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch
  743. smtc.expectedData = map[string][]byte{
  744. "certificate": []byte(secretCertificate),
  745. "created_at": []byte(timeValue),
  746. "created_by": []byte(*secret.CreatedBy),
  747. "crn": []byte(nilValue),
  748. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  749. "expiration_date": []byte(nilValue),
  750. "id": []byte(nilValue),
  751. "intermediate": []byte(secretIntermediate),
  752. "intermediate_included": []byte(nilValue),
  753. "issuer": []byte(nilValue),
  754. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  755. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  756. "private_key": []byte(secretPrivateKey),
  757. "private_key_included": []byte(nilValue),
  758. "secret_group_id": []byte(nilValue),
  759. "secret_type": []byte(nilValue),
  760. "serial_number": []byte(nilValue),
  761. "signing_algorithm": []byte(nilValue),
  762. "updated_at": []byte(nilValue),
  763. "validity": []byte(nilValue),
  764. "versions_total": []byte(nilValue),
  765. }
  766. }
  767. // good case: imported_cert without a private_key
  768. setimportedCertWithNoPvtKey := func(smtc *secretManagerTestCase) {
  769. secret := &sm.ImportedCertificate{
  770. CreatedBy: utilpointer.To("testCreatedBy"),
  771. CreatedAt: &strfmt.DateTime{},
  772. Downloaded: utilpointer.To(false),
  773. Labels: []string{"abc", "def", "xyz"},
  774. LocksTotal: utilpointer.To(int64(20)),
  775. Certificate: utilpointer.To(secretCertificate),
  776. Intermediate: utilpointer.To(secretIntermediate),
  777. }
  778. smtc.name = "good case: imported_cert without private key"
  779. smtc.apiInput.ID = utilpointer.To(secretUUID)
  780. smtc.apiOutput = secret
  781. smtc.ref.Key = "imported_cert/" + secretUUID
  782. smtc.expectedData = map[string][]byte{
  783. "certificate": []byte(secretCertificate),
  784. "intermediate": []byte(secretIntermediate),
  785. "private_key": []byte(""),
  786. }
  787. }
  788. // good case: public_cert with metadata
  789. setPublicCertWithMetadata := func(smtc *secretManagerTestCase) {
  790. secret := &sm.PublicCertificate{
  791. CreatedBy: utilpointer.To("testCreatedBy"),
  792. CreatedAt: &strfmt.DateTime{},
  793. Downloaded: utilpointer.To(false),
  794. Labels: []string{"abc", "def", "xyz"},
  795. LocksTotal: utilpointer.To(int64(20)),
  796. Certificate: utilpointer.To(secretCertificate),
  797. Intermediate: utilpointer.To(secretIntermediate),
  798. PrivateKey: utilpointer.To(secretPrivateKey),
  799. }
  800. smtc.name = "good case: public_cert with metadata"
  801. smtc.apiInput.ID = utilpointer.To(secretUUID)
  802. smtc.apiOutput = secret
  803. smtc.ref.Key = "public_cert" + "/" + secretUUID
  804. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch
  805. smtc.expectedData = map[string][]byte{
  806. "certificate": []byte(secretCertificate),
  807. "common_name": []byte(nilValue),
  808. "created_at": []byte(timeValue),
  809. "created_by": []byte(*secret.CreatedBy),
  810. "crn": []byte(nilValue),
  811. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  812. "id": []byte(nilValue),
  813. "intermediate": []byte(secretIntermediate),
  814. "key_algorithm": []byte(nilValue),
  815. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  816. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  817. "private_key": []byte(secretPrivateKey),
  818. "rotation": []byte(nilValue),
  819. "secret_group_id": []byte(nilValue),
  820. "secret_type": []byte(nilValue),
  821. "updated_at": []byte(nilValue),
  822. "versions_total": []byte(nilValue),
  823. }
  824. }
  825. // good case: private_cert with metadata
  826. setPrivateCertWithMetadata := func(smtc *secretManagerTestCase) {
  827. secret := &sm.PrivateCertificate{
  828. CreatedBy: utilpointer.To("testCreatedBy"),
  829. CreatedAt: &strfmt.DateTime{},
  830. Downloaded: utilpointer.To(false),
  831. Labels: []string{"abc", "def", "xyz"},
  832. LocksTotal: utilpointer.To(int64(20)),
  833. Certificate: utilpointer.To(secretCertificate),
  834. PrivateKey: utilpointer.To(secretPrivateKey),
  835. }
  836. smtc.name = "good case: private_cert with metadata"
  837. smtc.apiInput.ID = utilpointer.To(secretUUID)
  838. smtc.apiOutput = secret
  839. smtc.ref.Key = "private_cert" + "/" + secretUUID
  840. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch
  841. smtc.expectedData = map[string][]byte{
  842. "certificate": []byte(secretCertificate),
  843. "certificate_template": []byte(nilValue),
  844. "common_name": []byte(nilValue),
  845. "created_at": []byte(timeValue),
  846. "created_by": []byte(*secret.CreatedBy),
  847. "crn": []byte(nilValue),
  848. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  849. "expiration_date": []byte(nilValue),
  850. "id": []byte(nilValue),
  851. "issuer": []byte(nilValue),
  852. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  853. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  854. "private_key": []byte(secretPrivateKey),
  855. "secret_group_id": []byte(nilValue),
  856. "secret_type": []byte(nilValue),
  857. "serial_number": []byte(nilValue),
  858. "signing_algorithm": []byte(nilValue),
  859. "updated_at": []byte(nilValue),
  860. "validity": []byte(nilValue),
  861. "versions_total": []byte(nilValue),
  862. }
  863. }
  864. // good case: kv with property and metadata
  865. setSecretKVWithMetadata := func(smtc *secretManagerTestCase) {
  866. secret := &sm.KVSecret{
  867. CreatedBy: utilpointer.To("testCreatedBy"),
  868. CreatedAt: &strfmt.DateTime{},
  869. Downloaded: utilpointer.To(false),
  870. Labels: []string{"abc", "def", "xyz"},
  871. LocksTotal: utilpointer.To(int64(20)),
  872. Data: secretComplex,
  873. }
  874. smtc.name = "good case: kv, with property and with metadata"
  875. smtc.apiInput.ID = core.StringPtr(secretUUID)
  876. smtc.apiOutput = secret
  877. smtc.ref.Key = "kv/" + secretUUID
  878. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyFetch
  879. smtc.expectedData = map[string][]byte{
  880. "created_at": []byte(timeValue),
  881. "created_by": []byte(*secret.CreatedBy),
  882. "crn": []byte(nilValue),
  883. "data": []byte("map[key1:val1 key2:val2 keyC:map[keyC1:map[keyA:valA keyB:valB]]]"),
  884. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  885. "id": []byte(nilValue),
  886. "key1": []byte("val1"),
  887. "key2": []byte("val2"),
  888. "keyC": []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`),
  889. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  890. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  891. "secret_group_id": []byte(nilValue),
  892. "secret_type": []byte(nilValue),
  893. "updated_at": []byte(nilValue),
  894. "versions_total": []byte(nilValue),
  895. }
  896. }
  897. // good case: iam_credentials without metadata
  898. setSecretIamWithoutMetadata := func(smtc *secretManagerTestCase) {
  899. secret := &sm.IAMCredentialsSecret{
  900. CreatedBy: utilpointer.To("testCreatedBy"),
  901. CreatedAt: &strfmt.DateTime{},
  902. Downloaded: utilpointer.To(false),
  903. Labels: []string{"abc", "def", "xyz"},
  904. LocksTotal: utilpointer.To(int64(20)),
  905. ApiKey: utilpointer.To(secretAPIKey),
  906. }
  907. smtc.name = "good case: iam_credentials without metadata"
  908. smtc.apiInput.ID = utilpointer.To(secretUUID)
  909. smtc.apiOutput = secret
  910. smtc.ref.Key = iamCredentialsSecret + secretUUID
  911. smtc.ref.MetadataPolicy = esv1beta1.ExternalSecretMetadataPolicyNone
  912. smtc.expectedData = map[string][]byte{
  913. "apikey": []byte(secretAPIKey),
  914. }
  915. }
  916. secretKeyKV := "kv/" + secretUUID
  917. // good case: kv, no property, return entire payload as key:value pairs
  918. setSecretKV := func(smtc *secretManagerTestCase) {
  919. secret := &sm.KVSecret{
  920. Name: utilpointer.To("testyname"),
  921. ID: utilpointer.To(secretUUID),
  922. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  923. Data: secretComplex,
  924. }
  925. smtc.name = "good case: kv, no property, return entire payload as key:value pairs"
  926. smtc.apiInput.ID = core.StringPtr(secretUUID)
  927. smtc.apiOutput = secret
  928. smtc.ref.Key = secretKeyKV
  929. smtc.expectedData["key1"] = []byte("val1")
  930. smtc.expectedData["key2"] = []byte("val2")
  931. smtc.expectedData["keyC"] = []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`)
  932. }
  933. // good case: kv, with property
  934. setSecretKVWithProperty := func(smtc *secretManagerTestCase) {
  935. secret := &sm.KVSecret{
  936. Name: utilpointer.To("d5deb37a-7883-4fe2-a5e7-3c15420adc76"),
  937. ID: utilpointer.To(secretUUID),
  938. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  939. Data: secretComplex,
  940. }
  941. smtc.name = "good case: kv, with property"
  942. smtc.apiInput.ID = core.StringPtr(secretUUID)
  943. smtc.ref.Property = "keyC"
  944. smtc.apiOutput = secret
  945. smtc.ref.Key = secretKeyKV
  946. smtc.expectedData["keyC1"] = []byte(`{"keyA":"valA","keyB":"valB"}`)
  947. }
  948. // good case: kv, with property and path
  949. setSecretKVWithPathAndProperty := func(smtc *secretManagerTestCase) {
  950. secret := &sm.KVSecret{
  951. Name: utilpointer.To(secretUUID),
  952. ID: utilpointer.To(secretUUID),
  953. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  954. Data: secretComplex,
  955. }
  956. smtc.name = "good case: kv, with property and path"
  957. smtc.apiInput.ID = core.StringPtr(secretUUID)
  958. smtc.ref.Property = "keyC.keyC1"
  959. smtc.apiOutput = secret
  960. smtc.ref.Key = secretKeyKV
  961. smtc.expectedData["keyA"] = []byte("valA")
  962. smtc.expectedData["keyB"] = []byte("valB")
  963. }
  964. // bad case: kv, with property and path
  965. badSecretKVWithUnknownProperty := func(smtc *secretManagerTestCase) {
  966. secret := &sm.KVSecret{
  967. Name: utilpointer.To("testyname"),
  968. ID: utilpointer.To(secretUUID),
  969. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  970. Data: secretComplex,
  971. }
  972. smtc.name = "bad case: kv, with property and path"
  973. smtc.apiInput.ID = core.StringPtr(secretUUID)
  974. smtc.ref.Property = "unknown.property"
  975. smtc.apiOutput = secret
  976. smtc.ref.Key = secretKeyKV
  977. smtc.expectError = "key unknown.property does not exist in secret " + secretKeyKV
  978. }
  979. successCases := []*secretManagerTestCase{
  980. makeValidSecretManagerTestCaseCustom(badSecretIam),
  981. makeValidSecretManagerTestCaseCustom(setArbitrary),
  982. makeValidSecretManagerTestCaseCustom(setNilMockClient),
  983. makeValidSecretManagerTestCaseCustom(setAPIErr),
  984. makeValidSecretManagerTestCaseCustom(setSecretUserPass),
  985. makeValidSecretManagerTestCaseCustom(setSecretIam),
  986. makeValidSecretManagerTestCaseCustom(setSecretCert),
  987. makeValidSecretManagerTestCaseCustom(setSecretKV),
  988. makeValidSecretManagerTestCaseCustom(setSecretKVWithProperty),
  989. makeValidSecretManagerTestCaseCustom(setSecretKVWithPathAndProperty),
  990. makeValidSecretManagerTestCaseCustom(badSecretKVWithUnknownProperty),
  991. makeValidSecretManagerTestCaseCustom(setSecretPublicCert),
  992. makeValidSecretManagerTestCaseCustom(setSecretPrivateCert),
  993. makeValidSecretManagerTestCaseCustom(setimportedCertWithNoPvtKey),
  994. makeValidSecretManagerTestCaseCustom(setSecretIamWithMetadata),
  995. makeValidSecretManagerTestCaseCustom(setArbitraryWithMetadata),
  996. makeValidSecretManagerTestCaseCustom(setSecretUserPassWithMetadata),
  997. makeValidSecretManagerTestCaseCustom(setimportedCertWithMetadata),
  998. makeValidSecretManagerTestCaseCustom(setPublicCertWithMetadata),
  999. makeValidSecretManagerTestCaseCustom(setPrivateCertWithMetadata),
  1000. makeValidSecretManagerTestCaseCustom(setSecretKVWithMetadata),
  1001. makeValidSecretManagerTestCaseCustom(setSecretIamWithoutMetadata),
  1002. }
  1003. sm := providerIBM{}
  1004. for _, v := range successCases {
  1005. t.Run(v.name, func(t *testing.T) {
  1006. sm.IBMClient = v.mockClient
  1007. out, err := sm.GetSecretMap(context.Background(), *v.ref)
  1008. if !ErrorContains(err, v.expectError) {
  1009. t.Errorf("unexpected error: %s, expected: '%s'", err.Error(), v.expectError)
  1010. }
  1011. if err == nil && !reflect.DeepEqual(out, v.expectedData) {
  1012. t.Errorf("unexpected secret data: expected:\n%+v\ngot:\n%+v", v.expectedData, out)
  1013. }
  1014. })
  1015. }
  1016. }
  1017. func TestValidRetryInput(t *testing.T) {
  1018. sm := providerIBM{}
  1019. invalid := "Invalid"
  1020. serviceURL := "http://fake-service-url.cool"
  1021. spec := &esv1beta1.SecretStore{
  1022. Spec: esv1beta1.SecretStoreSpec{
  1023. Provider: &esv1beta1.SecretStoreProvider{
  1024. IBM: &esv1beta1.IBMProvider{
  1025. Auth: esv1beta1.IBMAuth{
  1026. SecretRef: esv1beta1.IBMAuthSecretRef{
  1027. SecretAPIKey: v1.SecretKeySelector{
  1028. Name: "fake-secret",
  1029. Key: "fake-key",
  1030. },
  1031. },
  1032. },
  1033. ServiceURL: &serviceURL,
  1034. },
  1035. },
  1036. RetrySettings: &esv1beta1.SecretStoreRetrySettings{
  1037. RetryInterval: &invalid,
  1038. },
  1039. },
  1040. }
  1041. expected := fmt.Sprintf("cannot setup new ibm client: time: invalid duration %q", invalid)
  1042. ctx := context.TODO()
  1043. kube := clientfake.NewClientBuilder().WithObjects(&corev1.Secret{
  1044. ObjectMeta: metav1.ObjectMeta{
  1045. Name: "fake-secret",
  1046. Namespace: "default",
  1047. },
  1048. Data: map[string][]byte{
  1049. "fake-key": []byte("ImAFakeApiKey"),
  1050. },
  1051. }).Build()
  1052. _, err := sm.NewClient(ctx, spec, kube, "default")
  1053. if !ErrorContains(err, expected) {
  1054. t.Errorf("CheckValidRetryInput unexpected error: %s, expected: '%s'", err.Error(), expected)
  1055. }
  1056. }
  1057. func ErrorContains(out error, want string) bool {
  1058. if out == nil {
  1059. return want == ""
  1060. }
  1061. if want == "" {
  1062. return false
  1063. }
  1064. return strings.Contains(out.Error(), want)
  1065. }