provider_test.go 43 KB

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