provider_test.go 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451
  1. /*
  2. Copyright © 2025 ESO Maintainer Team
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. https://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package ibm
  14. import (
  15. "bytes"
  16. "context"
  17. "encoding/json"
  18. "errors"
  19. "fmt"
  20. "reflect"
  21. "strconv"
  22. "strings"
  23. "testing"
  24. "github.com/IBM/go-sdk-core/v5/core"
  25. sm "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2"
  26. "github.com/go-openapi/strfmt"
  27. corev1 "k8s.io/api/core/v1"
  28. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  29. utilpointer "k8s.io/utils/ptr"
  30. clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
  31. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  32. v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
  33. fakesm "github.com/external-secrets/external-secrets/providers/v1/ibm/fake"
  34. )
  35. const (
  36. errExpectedErr = "wanted error got nil"
  37. secretKey = "test-secret"
  38. secretUUID = "d5deb37a-7883-4fe2-a5e7-3c15420adc76"
  39. iamCredentialsSecret = "iam_credentials/"
  40. )
  41. type secretManagerTestCase struct {
  42. name string
  43. mockClient *fakesm.IBMMockClient
  44. apiInput *sm.GetSecretOptions
  45. apiOutput sm.SecretIntf
  46. getByNameInput *sm.GetSecretByNameTypeOptions
  47. getByNameOutput sm.SecretIntf
  48. getByNameError error
  49. ref *esv1.ExternalSecretDataRemoteRef
  50. serviceURL *string
  51. apiErr error
  52. expectError string
  53. expectedSecret string
  54. // for testing secretmap
  55. expectedData map[string][]byte
  56. }
  57. func makeValidSecretManagerTestCase() *secretManagerTestCase {
  58. smtc := secretManagerTestCase{
  59. mockClient: &fakesm.IBMMockClient{},
  60. apiInput: makeValidAPIInput(),
  61. ref: makeValidRef(),
  62. apiOutput: makeValidAPIOutput(),
  63. getByNameInput: makeValidGetByNameInput(),
  64. getByNameOutput: makeValidAPIOutput(),
  65. getByNameError: nil,
  66. serviceURL: nil,
  67. apiErr: nil,
  68. expectError: "",
  69. expectedSecret: "",
  70. expectedData: map[string][]byte{},
  71. }
  72. mcParams := fakesm.IBMMockClientParams{
  73. GetSecretOptions: smtc.apiInput,
  74. GetSecretOutput: smtc.apiOutput,
  75. GetSecretErr: smtc.apiErr,
  76. GetSecretByNameOptions: smtc.getByNameInput,
  77. GetSecretByNameOutput: smtc.getByNameOutput,
  78. GetSecretByNameErr: smtc.getByNameError,
  79. }
  80. smtc.mockClient.WithValue(mcParams)
  81. return &smtc
  82. }
  83. func makeValidRef() *esv1.ExternalSecretDataRemoteRef {
  84. return &esv1.ExternalSecretDataRemoteRef{
  85. Key: secretUUID,
  86. Version: "default",
  87. }
  88. }
  89. func makeValidAPIInput() *sm.GetSecretOptions {
  90. return &sm.GetSecretOptions{
  91. ID: utilpointer.To(secretUUID),
  92. }
  93. }
  94. func makeValidAPIOutput() sm.SecretIntf {
  95. secret := &sm.Secret{
  96. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  97. Name: utilpointer.To("testyname"),
  98. ID: utilpointer.To(secretUUID),
  99. }
  100. var i sm.SecretIntf = secret
  101. return i
  102. }
  103. func makeValidGetByNameInput() *sm.GetSecretByNameTypeOptions {
  104. return &sm.GetSecretByNameTypeOptions{}
  105. }
  106. func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTestCase)) *secretManagerTestCase {
  107. smtc := makeValidSecretManagerTestCase()
  108. for _, fn := range tweaks {
  109. fn(smtc)
  110. }
  111. mcParams := fakesm.IBMMockClientParams{
  112. GetSecretOptions: smtc.apiInput,
  113. GetSecretOutput: smtc.apiOutput,
  114. GetSecretErr: smtc.apiErr,
  115. GetSecretByNameOptions: smtc.getByNameInput,
  116. GetSecretByNameOutput: smtc.getByNameOutput,
  117. GetSecretByNameErr: smtc.apiErr,
  118. }
  119. smtc.mockClient.WithValue(mcParams)
  120. return smtc
  121. }
  122. // This case can be shared by both GetSecret and GetSecretMap tests.
  123. // bad case: set apiErr.
  124. var setAPIErr = func(smtc *secretManagerTestCase) {
  125. smtc.apiErr = errors.New("oh no")
  126. smtc.expectError = "oh no"
  127. }
  128. var setNilMockClient = func(smtc *secretManagerTestCase) {
  129. smtc.mockClient = nil
  130. smtc.expectError = errUninitializedIBMProvider
  131. }
  132. // simple tests for Validate Store.
  133. func TestValidateStore(t *testing.T) {
  134. p := providerIBM{}
  135. store := &esv1.SecretStore{
  136. Spec: esv1.SecretStoreSpec{
  137. Provider: &esv1.SecretStoreProvider{
  138. IBM: &esv1.IBMProvider{},
  139. },
  140. },
  141. }
  142. _, err := p.ValidateStore(store)
  143. if err == nil {
  144. t.Error(errExpectedErr)
  145. } else if err.Error() != "serviceURL is required" {
  146. t.Errorf("service URL test failed")
  147. }
  148. url := "my-url"
  149. store.Spec.Provider.IBM.ServiceURL = &url
  150. _, err = p.ValidateStore(store)
  151. if err == nil {
  152. t.Error(errExpectedErr)
  153. } else if err.Error() != "missing auth method" {
  154. t.Errorf("KeySelector test failed: expected missing auth method, got %v", err)
  155. }
  156. ns := "ns-one"
  157. store.Spec.Provider.IBM.Auth.SecretRef = &esv1.IBMAuthSecretRef{
  158. SecretAPIKey: v1.SecretKeySelector{
  159. Name: "foo",
  160. Key: "bar",
  161. Namespace: &ns,
  162. },
  163. IAMEndpoint: "https://iam.cloud.ibm.com",
  164. }
  165. _, err = p.ValidateStore(store)
  166. if err == nil {
  167. t.Error(errExpectedErr)
  168. } else if err.Error() != "namespace should either be empty or match the namespace of the SecretStore for a namespaced SecretStore" {
  169. t.Errorf("KeySelector test failed: expected namespace not allowed, got %v", err)
  170. }
  171. // add container auth test
  172. store = &esv1.SecretStore{
  173. Spec: esv1.SecretStoreSpec{
  174. Provider: &esv1.SecretStoreProvider{
  175. IBM: &esv1.IBMProvider{
  176. ServiceURL: &url,
  177. Auth: esv1.IBMAuth{
  178. ContainerAuth: &esv1.IBMAuthContainerAuth{
  179. Profile: "Trusted IAM Profile",
  180. TokenLocation: "/a/path/to/nowhere/that/should/exist",
  181. },
  182. },
  183. },
  184. },
  185. },
  186. }
  187. _, err = p.ValidateStore(store)
  188. expected := "cannot read container auth token"
  189. if !ErrorContains(err, expected) {
  190. t.Errorf("ProfileSelector test failed: %s, expected: '%s'", err.Error(), expected)
  191. }
  192. }
  193. // test the sm<->gcp interface
  194. // make sure correct values are passed and errors are handled accordingly.
  195. func TestIBMSecretManagerGetSecret(t *testing.T) {
  196. secretString := "changedvalue"
  197. secretUsername := "userName"
  198. secretPassword := "P@ssw0rd"
  199. secretAPIKey := "01234567890"
  200. secretCertificate := "certificate_value"
  201. firstValue := "val1"
  202. // good case: default version is set
  203. // key is passed in, output is sent back
  204. setSecretString := func(smtc *secretManagerTestCase) {
  205. secret := &sm.ArbitrarySecret{
  206. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  207. Name: utilpointer.To("testyname"),
  208. ID: utilpointer.To(secretUUID),
  209. Payload: &secretString,
  210. }
  211. smtc.name = "good case: default version is set"
  212. smtc.apiOutput = secret
  213. smtc.apiInput.ID = utilpointer.To(secretUUID)
  214. smtc.expectedSecret = secretString
  215. }
  216. // good case: custom version set
  217. setCustomKey := func(smtc *secretManagerTestCase) {
  218. secret := &sm.ArbitrarySecret{
  219. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  220. Name: utilpointer.To("testyname"),
  221. ID: utilpointer.To(secretUUID),
  222. Payload: &secretString,
  223. }
  224. smtc.name = "good case: custom version set"
  225. smtc.ref.Key = "arbitrary/" + secretUUID
  226. smtc.apiInput.ID = utilpointer.To(secretUUID)
  227. smtc.apiOutput = secret
  228. smtc.expectedSecret = secretString
  229. }
  230. // bad case: arbitrary type secret which is destroyed
  231. badArbitSecret := func(smtc *secretManagerTestCase) {
  232. secret := &sm.ArbitrarySecret{
  233. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  234. Name: utilpointer.To("testyname"),
  235. ID: utilpointer.To(secretUUID),
  236. }
  237. smtc.name = "bad case: arbitrary type without property"
  238. smtc.apiInput.ID = utilpointer.To(secretUUID)
  239. smtc.apiOutput = secret
  240. smtc.ref.Key = secretUUID
  241. smtc.expectError = "key payload does not exist in secret " + secretUUID
  242. }
  243. // bad case: username_password type without property
  244. secretUserPass := "username_password/" + secretUUID
  245. badSecretUserPass := func(smtc *secretManagerTestCase) {
  246. secret := &sm.UsernamePasswordSecret{
  247. SecretType: utilpointer.To(sm.Secret_SecretType_UsernamePassword),
  248. Name: utilpointer.To("testyname"),
  249. ID: utilpointer.To(secretUUID),
  250. Username: &secretUsername,
  251. Password: &secretPassword,
  252. }
  253. smtc.name = "bad case: username_password type without property"
  254. smtc.apiInput.ID = utilpointer.To(secretUUID)
  255. smtc.apiOutput = secret
  256. smtc.ref.Key = secretUserPass
  257. smtc.expectError = "remoteRef.property required for secret type username_password"
  258. }
  259. // good case: username_password type with property
  260. funcSetUserPass := func(secretName, property, name string) func(smtc *secretManagerTestCase) {
  261. return func(smtc *secretManagerTestCase) {
  262. secret := &sm.UsernamePasswordSecret{
  263. SecretType: utilpointer.To(sm.Secret_SecretType_UsernamePassword),
  264. Name: utilpointer.To("testyname"),
  265. ID: utilpointer.To(secretUUID),
  266. Username: &secretUsername,
  267. Password: &secretPassword,
  268. }
  269. smtc.name = name
  270. smtc.apiInput.ID = utilpointer.To(secretUUID)
  271. smtc.apiOutput = secret
  272. smtc.ref.Key = "username_password/" + secretName
  273. smtc.ref.Property = property
  274. if property == "username" {
  275. smtc.expectedSecret = secretUsername
  276. } else {
  277. smtc.expectedSecret = secretPassword
  278. }
  279. }
  280. }
  281. setSecretUserPassByID := funcSetUserPass(secretUUID, "username", "good case: username_password type - get username by ID")
  282. // good case: iam_credentials type
  283. funcSetSecretIam := func(secretName, name string) func(*secretManagerTestCase) {
  284. return func(smtc *secretManagerTestCase) {
  285. secret := &sm.IAMCredentialsSecret{
  286. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  287. Name: utilpointer.To("testyname"),
  288. ID: utilpointer.To(secretUUID),
  289. ApiKey: utilpointer.To(secretAPIKey),
  290. }
  291. smtc.apiInput.ID = utilpointer.To(secretUUID)
  292. smtc.name = name
  293. smtc.apiOutput = secret
  294. smtc.ref.Key = iamCredentialsSecret + secretName
  295. smtc.expectedSecret = secretAPIKey
  296. }
  297. }
  298. setSecretIamByID := funcSetSecretIam(secretUUID, "good case: iam_credenatials type - get API Key by ID")
  299. // good case: iam_credentials type - get API Key by name, providing the secret group ID
  300. funcSetSecretIamNew := func(secretName, groupName, name string) func(*secretManagerTestCase) {
  301. return func(smtc *secretManagerTestCase) {
  302. secret := &sm.IAMCredentialsSecret{
  303. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  304. Name: utilpointer.To("testyname"),
  305. ID: utilpointer.To(secretUUID),
  306. ApiKey: utilpointer.To(secretAPIKey),
  307. }
  308. smtc.getByNameInput.Name = &secretName
  309. smtc.getByNameInput.SecretGroupName = &groupName
  310. smtc.getByNameInput.SecretType = utilpointer.To(sm.Secret_SecretType_IamCredentials)
  311. smtc.name = name
  312. smtc.getByNameOutput = secret
  313. smtc.ref.Key = groupName + "/" + iamCredentialsSecret + secretName
  314. smtc.expectedSecret = secretAPIKey
  315. }
  316. }
  317. setSecretIamByNameNew := funcSetSecretIamNew("testyname", "testGroup", "good case: iam_credenatials type - get API Key by name - new mechanism")
  318. // good case: service_credentials type
  319. dummySrvCreds := &sm.ServiceCredentialsSecretCredentials{
  320. Apikey: &secretAPIKey,
  321. }
  322. funcSetSecretSrvCred := func(secretName, name string) func(*secretManagerTestCase) {
  323. return func(smtc *secretManagerTestCase) {
  324. secret := &sm.ServiceCredentialsSecret{
  325. SecretType: utilpointer.To(sm.Secret_SecretType_ServiceCredentials),
  326. Name: utilpointer.To("testyname"),
  327. ID: utilpointer.To(secretUUID),
  328. Credentials: dummySrvCreds,
  329. }
  330. smtc.apiInput.ID = utilpointer.To(secretUUID)
  331. smtc.name = name
  332. smtc.apiOutput = secret
  333. smtc.ref.Key = "service_credentials/" + secretName
  334. smtc.expectedSecret = "{\"apikey\":\"01234567890\"}"
  335. }
  336. }
  337. setSecretSrvCredByID := funcSetSecretSrvCred(secretUUID, "good case: service_credentials type - get creds by ID")
  338. funcSetCertSecretTest := func(secret sm.SecretIntf, name, certType string, good bool) func(*secretManagerTestCase) {
  339. return func(smtc *secretManagerTestCase) {
  340. smtc.name = name
  341. smtc.apiInput.ID = utilpointer.To(secretUUID)
  342. smtc.apiOutput = secret
  343. smtc.ref.Key = certType + "/" + secretUUID
  344. if good {
  345. smtc.ref.Property = "certificate"
  346. smtc.expectedSecret = secretCertificate
  347. } else {
  348. smtc.expectError = "remoteRef.property required for secret type " + certType
  349. }
  350. }
  351. }
  352. // good case: imported_cert type with property
  353. importedCert := &sm.ImportedCertificate{
  354. SecretType: utilpointer.To(sm.Secret_SecretType_ImportedCert),
  355. Name: utilpointer.To("testyname"),
  356. ID: utilpointer.To(secretUUID),
  357. Certificate: utilpointer.To(secretCertificate),
  358. Intermediate: utilpointer.To("intermediate"),
  359. PrivateKey: utilpointer.To("private_key"),
  360. }
  361. setSecretCert := funcSetCertSecretTest(importedCert, "good case: imported_cert type with property", sm.Secret_SecretType_ImportedCert, true)
  362. // good case: imported_cert type without a private_key
  363. importedCertNoPvtKey := func(smtc *secretManagerTestCase) {
  364. secret := &sm.ImportedCertificate{
  365. SecretType: utilpointer.To(sm.Secret_SecretType_ImportedCert),
  366. Name: utilpointer.To("testyname"),
  367. ID: utilpointer.To(secretUUID),
  368. Certificate: utilpointer.To(secretCertificate),
  369. }
  370. smtc.name = "good case: imported cert without private key"
  371. smtc.apiInput.ID = utilpointer.To(secretUUID)
  372. smtc.apiOutput = secret
  373. smtc.ref.Key = "imported_cert/" + secretUUID
  374. smtc.ref.Property = "private_key"
  375. smtc.expectedSecret = ""
  376. }
  377. // bad case: imported_cert type without property
  378. badSecretCert := funcSetCertSecretTest(importedCert, "bad case: imported_cert type without property", sm.Secret_SecretType_ImportedCert, false)
  379. // good case: public_cert type with property
  380. publicCert := &sm.PublicCertificate{
  381. SecretType: utilpointer.To(sm.Secret_SecretType_PublicCert),
  382. Name: utilpointer.To("testyname"),
  383. ID: utilpointer.To(secretUUID),
  384. Certificate: utilpointer.To(secretCertificate),
  385. Intermediate: utilpointer.To("intermediate"),
  386. PrivateKey: utilpointer.To("private_key"),
  387. }
  388. setSecretPublicCert := funcSetCertSecretTest(publicCert, "good case: public_cert type with property", sm.Secret_SecretType_PublicCert, true)
  389. // bad case: public_cert type without property
  390. badSecretPublicCert := funcSetCertSecretTest(publicCert, "bad case: public_cert type without property", sm.Secret_SecretType_PublicCert, false)
  391. // good case: private_cert type with property
  392. privateCert := &sm.PrivateCertificate{
  393. SecretType: utilpointer.To(sm.Secret_SecretType_PublicCert),
  394. Name: utilpointer.To("testyname"),
  395. ID: utilpointer.To(secretUUID),
  396. Certificate: utilpointer.To(secretCertificate),
  397. PrivateKey: utilpointer.To("private_key"),
  398. }
  399. setSecretPrivateCert := funcSetCertSecretTest(privateCert, "good case: private_cert type with property", sm.Secret_SecretType_PrivateCert, true)
  400. // bad case: private_cert type without property
  401. badSecretPrivateCert := funcSetCertSecretTest(privateCert, "bad case: private_cert type without property", sm.Secret_SecretType_PrivateCert, false)
  402. secretDataKV := make(map[string]any)
  403. secretDataKV["key1"] = firstValue
  404. secretDataKVComplex := make(map[string]any)
  405. secretKVComplex := `{"key1":"val1","key2":"val2","key3":"val3","keyC":{"keyC1":"valC1","keyC2":"valC2"},"special.log":"file-content"}`
  406. json.Unmarshal([]byte(secretKVComplex), &secretDataKVComplex)
  407. secretKV := "kv/" + secretUUID
  408. // bad case: kv type with key which is not in payload
  409. badSecretKV := func(smtc *secretManagerTestCase) {
  410. secret := &sm.KVSecret{
  411. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  412. Name: utilpointer.To("testyname"),
  413. ID: utilpointer.To(secretUUID),
  414. Data: secretDataKV,
  415. }
  416. smtc.name = "bad case: kv type with key which is not in payload"
  417. smtc.apiInput.ID = utilpointer.To(secretUUID)
  418. smtc.apiOutput = secret
  419. smtc.ref.Key = secretKV
  420. smtc.ref.Property = "other-key"
  421. smtc.expectError = "key other-key does not exist in secret kv/" + secretUUID
  422. }
  423. // good case: kv type with property
  424. setSecretKV := func(smtc *secretManagerTestCase) {
  425. secret := &sm.KVSecret{
  426. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  427. Name: utilpointer.To("testyname"),
  428. ID: utilpointer.To(secretUUID),
  429. Data: secretDataKV,
  430. }
  431. smtc.name = "good case: kv type with property"
  432. smtc.apiInput.ID = utilpointer.To(secretUUID)
  433. smtc.apiOutput = secret
  434. smtc.ref.Key = secretKV
  435. smtc.ref.Property = "key1"
  436. smtc.expectedSecret = firstValue
  437. }
  438. // good case: kv type with property, returns specific value
  439. setSecretKVWithKey := func(smtc *secretManagerTestCase) {
  440. secret := &sm.KVSecret{
  441. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  442. Name: utilpointer.To("testyname"),
  443. ID: utilpointer.To(secretUUID),
  444. Data: secretDataKVComplex,
  445. }
  446. smtc.name = "good case: kv type with property, returns specific value"
  447. smtc.apiInput.ID = utilpointer.To(secretUUID)
  448. smtc.apiOutput = secret
  449. smtc.ref.Key = secretKV
  450. smtc.ref.Property = "key2"
  451. smtc.expectedSecret = "val2"
  452. }
  453. // good case: kv type with property and path, returns specific value
  454. setSecretKVWithKeyPath := func(smtc *secretManagerTestCase) {
  455. secret := &sm.KVSecret{
  456. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  457. Name: utilpointer.To("testyname"),
  458. ID: utilpointer.To(secretUUID),
  459. Data: secretDataKVComplex,
  460. }
  461. smtc.name = "good case: kv type with property and path, returns specific value"
  462. smtc.apiInput.ID = utilpointer.To(secretUUID)
  463. smtc.apiOutput = secret
  464. smtc.ref.Key = secretKV
  465. smtc.ref.Property = "keyC.keyC2"
  466. smtc.expectedSecret = "valC2"
  467. }
  468. // good case: kv type with property and dot, returns specific value
  469. setSecretKVWithKeyDot := func(smtc *secretManagerTestCase) {
  470. secret := &sm.KVSecret{
  471. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  472. Name: utilpointer.To("testyname"),
  473. ID: utilpointer.To(secretUUID),
  474. Data: secretDataKVComplex,
  475. }
  476. smtc.name = "good case: kv type with property and dot, returns specific value"
  477. smtc.apiInput.ID = utilpointer.To(secretUUID)
  478. smtc.apiOutput = secret
  479. smtc.ref.Key = secretKV
  480. smtc.ref.Property = "special.log"
  481. smtc.expectedSecret = "file-content"
  482. }
  483. // good case: kv type without property, returns all
  484. setSecretKVWithOutKey := func(smtc *secretManagerTestCase) {
  485. secret := &sm.KVSecret{
  486. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  487. Name: utilpointer.To("testyname"),
  488. ID: utilpointer.To(secretUUID),
  489. Data: secretDataKVComplex,
  490. }
  491. smtc.name = "good case: kv type without property, returns all"
  492. smtc.apiInput.ID = utilpointer.To(secretUUID)
  493. smtc.apiOutput = secret
  494. smtc.ref.Key = secretKV
  495. smtc.expectedSecret = secretKVComplex
  496. }
  497. customCredentialsSecretCredentialsContent := make(map[string]any)
  498. customCredentialsSecretCredentialsContent["key1"] = firstValue
  499. customCredentialsSecretCredentialsContentComplex := make(map[string]any)
  500. customCredentialsSecretComplex := `{"key1":"val1","key2":"val2","key3":"val3","keyC":{"keyC1":"valC1","keyC2":"valC2"},"special.log":"file-content"}`
  501. json.Unmarshal([]byte(customCredentialsSecretComplex), &customCredentialsSecretCredentialsContentComplex)
  502. secretCustomCredentials := "custom_credentials/" + secretUUID
  503. // bad case: custom credentials type with key which is not in payload
  504. badSecretCustomCredentials := func(smtc *secretManagerTestCase) {
  505. secret := &sm.CustomCredentialsSecret{
  506. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  507. Name: utilpointer.To("testyname"),
  508. ID: utilpointer.To(secretUUID),
  509. CredentialsContent: customCredentialsSecretCredentialsContent,
  510. }
  511. smtc.name = "bad case: custom credentials type with key which is not in payload"
  512. smtc.apiInput.ID = utilpointer.To(secretUUID)
  513. smtc.apiOutput = secret
  514. smtc.ref.Key = secretCustomCredentials
  515. smtc.ref.Property = "other-key"
  516. smtc.expectError = "key other-key does not exist in secret custom_credentials/" + secretUUID
  517. }
  518. // good case: custom credentials type with property
  519. setSecretCustomCredentials := func(smtc *secretManagerTestCase) {
  520. secret := &sm.CustomCredentialsSecret{
  521. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  522. Name: utilpointer.To("testyname"),
  523. ID: utilpointer.To(secretUUID),
  524. CredentialsContent: customCredentialsSecretCredentialsContent,
  525. }
  526. smtc.name = "good case: custom_credentials type with property"
  527. smtc.apiInput.ID = utilpointer.To(secretUUID)
  528. smtc.apiOutput = secret
  529. smtc.ref.Key = secretCustomCredentials
  530. smtc.ref.Property = "key1"
  531. smtc.expectedSecret = firstValue
  532. }
  533. // good case: custom_credentials type with property, returns specific value
  534. setSecretCustomCredentialsWithKey := func(smtc *secretManagerTestCase) {
  535. secret := &sm.CustomCredentialsSecret{
  536. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  537. Name: utilpointer.To("testyname"),
  538. ID: utilpointer.To(secretUUID),
  539. CredentialsContent: customCredentialsSecretCredentialsContentComplex,
  540. }
  541. smtc.name = "good case: custom_credentials type with property, returns specific value"
  542. smtc.apiInput.ID = utilpointer.To(secretUUID)
  543. smtc.apiOutput = secret
  544. smtc.ref.Key = secretCustomCredentials
  545. smtc.ref.Property = "key2"
  546. smtc.expectedSecret = "val2"
  547. }
  548. // good case: custom_credentials type with property and path, returns specific value
  549. setSecretCustomCredentialsWithKeyPath := func(smtc *secretManagerTestCase) {
  550. secret := &sm.CustomCredentialsSecret{
  551. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  552. Name: utilpointer.To("testyname"),
  553. ID: utilpointer.To(secretUUID),
  554. CredentialsContent: customCredentialsSecretCredentialsContentComplex,
  555. }
  556. smtc.name = "good case: custom_credentials type with property and path, returns specific value"
  557. smtc.apiInput.ID = utilpointer.To(secretUUID)
  558. smtc.apiOutput = secret
  559. smtc.ref.Key = secretCustomCredentials
  560. smtc.ref.Property = "keyC.keyC2"
  561. smtc.expectedSecret = "valC2"
  562. }
  563. // good case: custom_credentials type with property and dot, returns specific value
  564. setSecretCustomCredentialsWithKeyDot := func(smtc *secretManagerTestCase) {
  565. secret := &sm.CustomCredentialsSecret{
  566. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  567. Name: utilpointer.To("testyname"),
  568. ID: utilpointer.To(secretUUID),
  569. CredentialsContent: customCredentialsSecretCredentialsContentComplex,
  570. }
  571. smtc.name = "good case: custom_credentials type with property and dot, returns specific value"
  572. smtc.apiInput.ID = utilpointer.To(secretUUID)
  573. smtc.apiOutput = secret
  574. smtc.ref.Key = secretCustomCredentials
  575. smtc.ref.Property = "special.log"
  576. smtc.expectedSecret = "file-content"
  577. }
  578. // good case: custom_credentials type without property, returns all
  579. setSecretCustomCredentialsWithOutKey := func(smtc *secretManagerTestCase) {
  580. secret := &sm.CustomCredentialsSecret{
  581. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  582. Name: utilpointer.To("testyname"),
  583. ID: utilpointer.To(secretUUID),
  584. CredentialsContent: customCredentialsSecretCredentialsContentComplex,
  585. }
  586. smtc.name = "good case: custom_credentials type without property, returns all"
  587. smtc.apiInput.ID = utilpointer.To(secretUUID)
  588. smtc.apiOutput = secret
  589. smtc.ref.Key = secretCustomCredentials
  590. smtc.expectedSecret = customCredentialsSecretComplex
  591. }
  592. successCases := []*secretManagerTestCase{
  593. makeValidSecretManagerTestCaseCustom(setSecretString),
  594. makeValidSecretManagerTestCaseCustom(setCustomKey),
  595. makeValidSecretManagerTestCaseCustom(badArbitSecret),
  596. makeValidSecretManagerTestCaseCustom(setAPIErr),
  597. makeValidSecretManagerTestCaseCustom(setNilMockClient),
  598. makeValidSecretManagerTestCaseCustom(badSecretUserPass),
  599. makeValidSecretManagerTestCaseCustom(setSecretUserPassByID),
  600. makeValidSecretManagerTestCaseCustom(setSecretIamByID),
  601. makeValidSecretManagerTestCaseCustom(setSecretCert),
  602. makeValidSecretManagerTestCaseCustom(setSecretKV),
  603. makeValidSecretManagerTestCaseCustom(setSecretKVWithKey),
  604. makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyPath),
  605. makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyDot),
  606. makeValidSecretManagerTestCaseCustom(setSecretKVWithOutKey),
  607. makeValidSecretManagerTestCaseCustom(badSecretKV),
  608. makeValidSecretManagerTestCaseCustom(badSecretCert),
  609. makeValidSecretManagerTestCaseCustom(importedCertNoPvtKey),
  610. makeValidSecretManagerTestCaseCustom(setSecretPublicCert),
  611. makeValidSecretManagerTestCaseCustom(badSecretPublicCert),
  612. makeValidSecretManagerTestCaseCustom(setSecretPrivateCert),
  613. makeValidSecretManagerTestCaseCustom(badSecretPrivateCert),
  614. makeValidSecretManagerTestCaseCustom(setSecretIamByNameNew),
  615. makeValidSecretManagerTestCaseCustom(setSecretSrvCredByID),
  616. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentials),
  617. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentialsWithKey),
  618. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentialsWithKeyPath),
  619. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentialsWithKeyDot),
  620. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentialsWithOutKey),
  621. makeValidSecretManagerTestCaseCustom(badSecretCustomCredentials),
  622. }
  623. sm := providerIBM{}
  624. for _, v := range successCases {
  625. t.Run(v.name, func(t *testing.T) {
  626. sm.IBMClient = v.mockClient
  627. out, err := sm.GetSecret(context.Background(), *v.ref)
  628. if !ErrorContains(err, v.expectError) {
  629. t.Errorf("unexpected error:\n%s, expected:\n'%s'", err.Error(), v.expectError)
  630. }
  631. if string(out) != v.expectedSecret {
  632. t.Errorf("unexpected secret: expected:\n%s\ngot:\n%s", v.expectedSecret, string(out))
  633. }
  634. })
  635. }
  636. }
  637. func TestGetSecretMap(t *testing.T) {
  638. secretUsername := "user1"
  639. secretPassword := "P@ssw0rd"
  640. secretAPIKey := "01234567890"
  641. nilValue := "<nil>"
  642. secretCertificate := "certificate_value"
  643. secretPrivateKey := "private_key_value"
  644. secretIntermediate := "intermediate_value"
  645. timeValue := "0001-01-01T00:00:00.000Z"
  646. secretComplex := map[string]any{
  647. "key1": "val1",
  648. "key2": "val2",
  649. "keyC": map[string]any{
  650. "keyC1": map[string]string{
  651. "keyA": "valA",
  652. "keyB": "valB",
  653. },
  654. },
  655. }
  656. dummySrvCreds := &sm.ServiceCredentialsSecretCredentials{
  657. Apikey: &secretAPIKey,
  658. }
  659. // good case: arbitrary
  660. setArbitrary := func(smtc *secretManagerTestCase) {
  661. payload := `{"foo":"bar"}`
  662. secret := &sm.ArbitrarySecret{
  663. Name: utilpointer.To("testyname"),
  664. ID: utilpointer.To(secretUUID),
  665. SecretType: utilpointer.To(sm.Secret_SecretType_Arbitrary),
  666. Payload: &payload,
  667. }
  668. smtc.name = "good case: arbitrary"
  669. smtc.apiInput.ID = utilpointer.To(secretUUID)
  670. smtc.apiOutput = secret
  671. smtc.ref.Key = secretUUID
  672. smtc.expectedData["arbitrary"] = []byte(payload)
  673. }
  674. // good case: username_password
  675. setSecretUserPass := func(smtc *secretManagerTestCase) {
  676. secret := &sm.UsernamePasswordSecret{
  677. Name: utilpointer.To("testyname"),
  678. ID: utilpointer.To(secretUUID),
  679. SecretType: utilpointer.To(sm.Secret_SecretType_UsernamePassword),
  680. Username: &secretUsername,
  681. Password: &secretPassword,
  682. }
  683. smtc.name = "good case: username_password"
  684. smtc.apiInput.ID = utilpointer.To(secretUUID)
  685. smtc.apiOutput = secret
  686. smtc.ref.Key = "username_password/" + secretUUID
  687. smtc.expectedData["username"] = []byte(secretUsername)
  688. smtc.expectedData["password"] = []byte(secretPassword)
  689. }
  690. // good case: iam_credentials
  691. setSecretIam := func(smtc *secretManagerTestCase) {
  692. secret := &sm.IAMCredentialsSecret{
  693. Name: utilpointer.To("testyname"),
  694. ID: utilpointer.To(secretUUID),
  695. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  696. ApiKey: utilpointer.To(secretAPIKey),
  697. }
  698. smtc.name = "good case: iam_credentials"
  699. smtc.apiInput.ID = utilpointer.To(secretUUID)
  700. smtc.apiOutput = secret
  701. smtc.ref.Key = iamCredentialsSecret + secretUUID
  702. smtc.expectedData["apikey"] = []byte(secretAPIKey)
  703. }
  704. // good case: iam_credentials by name using new mechanism
  705. setSecretIamByName := func(smtc *secretManagerTestCase) {
  706. secret := &sm.IAMCredentialsSecret{
  707. Name: utilpointer.To("testyname"),
  708. ID: utilpointer.To(secretUUID),
  709. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  710. ApiKey: utilpointer.To(secretAPIKey),
  711. }
  712. smtc.name = "good case: iam_credentials by name using new mechanism"
  713. smtc.getByNameInput.Name = utilpointer.To("testyname")
  714. smtc.getByNameInput.SecretGroupName = utilpointer.To("groupName")
  715. smtc.getByNameInput.SecretType = utilpointer.To(sm.Secret_SecretType_IamCredentials)
  716. smtc.getByNameOutput = secret
  717. smtc.apiOutput = secret
  718. smtc.ref.Key = "groupName/" + iamCredentialsSecret + "testyname"
  719. smtc.expectedData["apikey"] = []byte(secretAPIKey)
  720. }
  721. // bad case: iam_credentials of a destroyed secret
  722. badSecretIam := func(smtc *secretManagerTestCase) {
  723. secret := &sm.IAMCredentialsSecret{
  724. Name: utilpointer.To("testyname"),
  725. ID: utilpointer.To(secretUUID),
  726. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  727. }
  728. smtc.name = "bad case: iam_credentials of a destroyed secret"
  729. smtc.apiInput.ID = utilpointer.To(secretUUID)
  730. smtc.apiOutput = secret
  731. smtc.ref.Key = iamCredentialsSecret + secretUUID
  732. smtc.expectError = "key api_key does not exist in secret " + secretUUID
  733. }
  734. funcCertTest := func(secret sm.SecretIntf, name, certType string) func(*secretManagerTestCase) {
  735. return func(smtc *secretManagerTestCase) {
  736. smtc.name = name
  737. smtc.apiInput.ID = utilpointer.To(secretUUID)
  738. smtc.apiOutput = secret
  739. smtc.ref.Key = certType + "/" + secretUUID
  740. smtc.expectedData["certificate"] = []byte(secretCertificate)
  741. smtc.expectedData["private_key"] = []byte(secretPrivateKey)
  742. smtc.expectedData["intermediate"] = []byte(secretIntermediate)
  743. }
  744. }
  745. // good case: service_credentials
  746. setSecretSrvCreds := func(smtc *secretManagerTestCase) {
  747. secret := &sm.ServiceCredentialsSecret{
  748. Name: utilpointer.To("testyname"),
  749. ID: utilpointer.To(secretUUID),
  750. SecretType: utilpointer.To(sm.Secret_SecretType_IamCredentials),
  751. Credentials: dummySrvCreds,
  752. }
  753. smtc.name = "good case: service_credentials"
  754. smtc.apiInput.ID = utilpointer.To(secretUUID)
  755. smtc.apiOutput = secret
  756. smtc.ref.Key = "service_credentials/" + secretUUID
  757. smtc.expectedData["credentials"] = []byte(fmt.Sprintf("%+v", map[string]string{"apikey": secretAPIKey}))
  758. }
  759. // good case: imported_cert
  760. importedCert := &sm.ImportedCertificate{
  761. SecretType: utilpointer.To(sm.Secret_SecretType_ImportedCert),
  762. Name: utilpointer.To("testyname"),
  763. ID: utilpointer.To(secretUUID),
  764. Certificate: utilpointer.To(secretCertificate),
  765. Intermediate: utilpointer.To(secretIntermediate),
  766. PrivateKey: utilpointer.To(secretPrivateKey),
  767. }
  768. setSecretCert := funcCertTest(importedCert, "good case: imported_cert", sm.Secret_SecretType_ImportedCert)
  769. // good case: public_cert
  770. publicCert := &sm.PublicCertificate{
  771. SecretType: utilpointer.To(sm.Secret_SecretType_PublicCert),
  772. Name: utilpointer.To("testyname"),
  773. ID: utilpointer.To(secretUUID),
  774. Certificate: utilpointer.To(secretCertificate),
  775. Intermediate: utilpointer.To(secretIntermediate),
  776. PrivateKey: utilpointer.To(secretPrivateKey),
  777. }
  778. setSecretPublicCert := funcCertTest(publicCert, "good case: public_cert", sm.Secret_SecretType_PublicCert)
  779. // good case: private_cert
  780. setSecretPrivateCert := func(smtc *secretManagerTestCase) {
  781. secret := &sm.PrivateCertificate{
  782. Name: utilpointer.To("testyname"),
  783. ID: utilpointer.To(secretUUID),
  784. SecretType: utilpointer.To(sm.Secret_SecretType_PrivateCert),
  785. Certificate: &secretCertificate,
  786. PrivateKey: &secretPrivateKey,
  787. }
  788. smtc.name = "good case: private_cert"
  789. smtc.apiInput.ID = utilpointer.To(secretUUID)
  790. smtc.apiOutput = secret
  791. smtc.ref.Key = "private_cert/" + secretUUID
  792. smtc.expectedData["certificate"] = []byte(secretCertificate)
  793. smtc.expectedData["private_key"] = []byte(secretPrivateKey)
  794. }
  795. // good case: arbitrary with metadata
  796. setArbitraryWithMetadata := func(smtc *secretManagerTestCase) {
  797. payload := `{"foo":"bar"}`
  798. secret := &sm.ArbitrarySecret{
  799. CreatedBy: utilpointer.To("testCreatedBy"),
  800. CreatedAt: &strfmt.DateTime{},
  801. Downloaded: utilpointer.To(false),
  802. Labels: []string{"abc", "def", "xyz"},
  803. LocksTotal: utilpointer.To(int64(20)),
  804. Payload: &payload,
  805. }
  806. smtc.name = "good case: arbitrary with metadata"
  807. smtc.apiInput.ID = utilpointer.To(secretUUID)
  808. smtc.apiOutput = secret
  809. smtc.ref.Key = secretUUID
  810. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  811. smtc.expectedData = map[string][]byte{
  812. "arbitrary": []byte(payload),
  813. "created_at": []byte(timeValue),
  814. "created_by": []byte(*secret.CreatedBy),
  815. "crn": []byte(nilValue),
  816. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  817. "id": []byte(nilValue),
  818. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  819. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  820. "payload": []byte(payload),
  821. "secret_group_id": []byte(nilValue),
  822. "secret_type": []byte(nilValue),
  823. "updated_at": []byte(nilValue),
  824. "versions_total": []byte(nilValue),
  825. }
  826. }
  827. // good case: iam_credentials with metadata
  828. setSecretIamWithMetadata := func(smtc *secretManagerTestCase) {
  829. secret := &sm.IAMCredentialsSecret{
  830. CreatedBy: utilpointer.To("testCreatedBy"),
  831. CreatedAt: &strfmt.DateTime{},
  832. Downloaded: utilpointer.To(false),
  833. Labels: []string{"abc", "def", "xyz"},
  834. LocksTotal: utilpointer.To(int64(20)),
  835. ApiKey: utilpointer.To(secretAPIKey),
  836. }
  837. smtc.name = "good case: iam_credentials with metadata"
  838. smtc.apiInput.ID = utilpointer.To(secretUUID)
  839. smtc.apiOutput = secret
  840. smtc.ref.Key = iamCredentialsSecret + secretUUID
  841. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  842. smtc.expectedData = map[string][]byte{
  843. "api_key": []byte(secretAPIKey),
  844. "apikey": []byte(secretAPIKey),
  845. "created_at": []byte(timeValue),
  846. "created_by": []byte(*secret.CreatedBy),
  847. "crn": []byte(nilValue),
  848. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  849. "id": []byte(nilValue),
  850. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  851. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  852. "reuse_api_key": []byte(nilValue),
  853. "secret_group_id": []byte(nilValue),
  854. "secret_type": []byte(nilValue),
  855. "ttl": []byte(nilValue),
  856. "updated_at": []byte(nilValue),
  857. "versions_total": []byte(nilValue),
  858. }
  859. }
  860. // "good case: username_password with metadata
  861. setSecretUserPassWithMetadata := func(smtc *secretManagerTestCase) {
  862. secret := &sm.UsernamePasswordSecret{
  863. CreatedBy: utilpointer.To("testCreatedBy"),
  864. CreatedAt: &strfmt.DateTime{},
  865. Downloaded: utilpointer.To(false),
  866. Labels: []string{"abc", "def", "xyz"},
  867. LocksTotal: utilpointer.To(int64(20)),
  868. Username: &secretUsername,
  869. Password: &secretPassword,
  870. }
  871. smtc.name = "good case: username_password with metadata"
  872. smtc.apiInput.ID = utilpointer.To(secretUUID)
  873. smtc.apiOutput = secret
  874. smtc.ref.Key = "username_password/" + secretUUID
  875. smtc.expectedData["username"] = []byte(secretUsername)
  876. smtc.expectedData["password"] = []byte(secretPassword)
  877. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  878. smtc.expectedData = map[string][]byte{
  879. "created_at": []byte(timeValue),
  880. "created_by": []byte(*secret.CreatedBy),
  881. "crn": []byte(nilValue),
  882. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  883. "id": []byte(nilValue),
  884. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  885. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  886. "password": []byte(secretPassword),
  887. "rotation": []byte(nilValue),
  888. "secret_group_id": []byte(nilValue),
  889. "secret_type": []byte(nilValue),
  890. "updated_at": []byte(nilValue),
  891. "username": []byte(secretUsername),
  892. "versions_total": []byte(nilValue),
  893. }
  894. }
  895. // good case: imported_cert with metadata
  896. setimportedCertWithMetadata := func(smtc *secretManagerTestCase) {
  897. secret := &sm.ImportedCertificate{
  898. CreatedBy: utilpointer.To("testCreatedBy"),
  899. CreatedAt: &strfmt.DateTime{},
  900. Downloaded: utilpointer.To(false),
  901. Labels: []string{"abc", "def", "xyz"},
  902. LocksTotal: utilpointer.To(int64(20)),
  903. Certificate: utilpointer.To(secretCertificate),
  904. Intermediate: utilpointer.To(secretIntermediate),
  905. PrivateKey: utilpointer.To(secretPrivateKey),
  906. }
  907. smtc.name = "good case: imported_cert with metadata"
  908. smtc.apiInput.ID = utilpointer.To(secretUUID)
  909. smtc.apiOutput = secret
  910. smtc.ref.Key = "imported_cert" + "/" + secretUUID
  911. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  912. smtc.expectedData = map[string][]byte{
  913. "certificate": []byte(secretCertificate),
  914. "created_at": []byte(timeValue),
  915. "created_by": []byte(*secret.CreatedBy),
  916. "crn": []byte(nilValue),
  917. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  918. "id": []byte(nilValue),
  919. "intermediate": []byte(secretIntermediate),
  920. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  921. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  922. "private_key": []byte(secretPrivateKey),
  923. "secret_group_id": []byte(nilValue),
  924. "secret_type": []byte(nilValue),
  925. "updated_at": []byte(nilValue),
  926. "versions_total": []byte(nilValue),
  927. }
  928. }
  929. // good case: imported_cert without a private_key
  930. setimportedCertWithNoPvtKey := func(smtc *secretManagerTestCase) {
  931. secret := &sm.ImportedCertificate{
  932. CreatedBy: utilpointer.To("testCreatedBy"),
  933. CreatedAt: &strfmt.DateTime{},
  934. Downloaded: utilpointer.To(false),
  935. Labels: []string{"abc", "def", "xyz"},
  936. LocksTotal: utilpointer.To(int64(20)),
  937. Certificate: utilpointer.To(secretCertificate),
  938. Intermediate: utilpointer.To(secretIntermediate),
  939. }
  940. smtc.name = "good case: imported_cert without private key"
  941. smtc.apiInput.ID = utilpointer.To(secretUUID)
  942. smtc.apiOutput = secret
  943. smtc.ref.Key = "imported_cert/" + secretUUID
  944. smtc.expectedData = map[string][]byte{
  945. "certificate": []byte(secretCertificate),
  946. "intermediate": []byte(secretIntermediate),
  947. "private_key": []byte(""),
  948. }
  949. }
  950. // good case: public_cert with metadata
  951. setPublicCertWithMetadata := func(smtc *secretManagerTestCase) {
  952. secret := &sm.PublicCertificate{
  953. CreatedBy: utilpointer.To("testCreatedBy"),
  954. CreatedAt: &strfmt.DateTime{},
  955. Downloaded: utilpointer.To(false),
  956. Labels: []string{"abc", "def", "xyz"},
  957. LocksTotal: utilpointer.To(int64(20)),
  958. Certificate: utilpointer.To(secretCertificate),
  959. Intermediate: utilpointer.To(secretIntermediate),
  960. PrivateKey: utilpointer.To(secretPrivateKey),
  961. }
  962. smtc.name = "good case: public_cert with metadata"
  963. smtc.apiInput.ID = utilpointer.To(secretUUID)
  964. smtc.apiOutput = secret
  965. smtc.ref.Key = "public_cert" + "/" + secretUUID
  966. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  967. smtc.expectedData = map[string][]byte{
  968. "certificate": []byte(secretCertificate),
  969. "created_at": []byte(timeValue),
  970. "created_by": []byte(*secret.CreatedBy),
  971. "crn": []byte(nilValue),
  972. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  973. "id": []byte(nilValue),
  974. "intermediate": []byte(secretIntermediate),
  975. "key_algorithm": []byte(nilValue),
  976. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  977. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  978. "private_key": []byte(secretPrivateKey),
  979. "rotation": []byte(nilValue),
  980. "secret_group_id": []byte(nilValue),
  981. "secret_type": []byte(nilValue),
  982. "updated_at": []byte(nilValue),
  983. "versions_total": []byte(nilValue),
  984. }
  985. }
  986. // good case: private_cert with metadata
  987. setPrivateCertWithMetadata := func(smtc *secretManagerTestCase) {
  988. expirationDate := &strfmt.DateTime{}
  989. secret := &sm.PrivateCertificate{
  990. CreatedBy: utilpointer.To("testCreatedBy"),
  991. CreatedAt: &strfmt.DateTime{},
  992. Downloaded: utilpointer.To(false),
  993. Labels: []string{"abc", "def", "xyz"},
  994. LocksTotal: utilpointer.To(int64(20)),
  995. Certificate: utilpointer.To(secretCertificate),
  996. PrivateKey: utilpointer.To(secretPrivateKey),
  997. ExpirationDate: expirationDate,
  998. }
  999. smtc.name = "good case: private_cert with metadata"
  1000. smtc.apiInput.ID = utilpointer.To(secretUUID)
  1001. smtc.apiOutput = secret
  1002. smtc.ref.Key = "private_cert" + "/" + secretUUID
  1003. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  1004. smtc.expectedData = map[string][]byte{
  1005. "certificate": []byte(secretCertificate),
  1006. "certificate_template": []byte(nilValue),
  1007. "common_name": []byte(nilValue),
  1008. "created_at": []byte(timeValue),
  1009. "created_by": []byte(*secret.CreatedBy),
  1010. "crn": []byte(nilValue),
  1011. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  1012. "expiration_date": []byte(expirationDate.String()),
  1013. "id": []byte(nilValue),
  1014. "issuer": []byte(nilValue),
  1015. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  1016. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  1017. "private_key": []byte(secretPrivateKey),
  1018. "secret_group_id": []byte(nilValue),
  1019. "secret_type": []byte(nilValue),
  1020. "serial_number": []byte(nilValue),
  1021. "signing_algorithm": []byte(nilValue),
  1022. "updated_at": []byte(nilValue),
  1023. "validity": []byte(nilValue),
  1024. "versions_total": []byte(nilValue),
  1025. }
  1026. }
  1027. // good case: kv with property and metadata
  1028. setSecretKVWithMetadata := func(smtc *secretManagerTestCase) {
  1029. secret := &sm.KVSecret{
  1030. CreatedBy: utilpointer.To("testCreatedBy"),
  1031. CreatedAt: &strfmt.DateTime{},
  1032. Downloaded: utilpointer.To(false),
  1033. Labels: []string{"abc", "def", "xyz"},
  1034. LocksTotal: utilpointer.To(int64(20)),
  1035. Data: secretComplex,
  1036. }
  1037. smtc.name = "good case: kv, with property and with metadata"
  1038. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1039. smtc.apiOutput = secret
  1040. smtc.ref.Key = "kv/" + secretUUID
  1041. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  1042. smtc.expectedData = map[string][]byte{
  1043. "created_at": []byte(timeValue),
  1044. "created_by": []byte(*secret.CreatedBy),
  1045. "crn": []byte(nilValue),
  1046. "data": []byte("map[key1:val1 key2:val2 keyC:map[keyC1:map[keyA:valA keyB:valB]]]"),
  1047. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  1048. "id": []byte(nilValue),
  1049. "key1": []byte("val1"),
  1050. "key2": []byte("val2"),
  1051. "keyC": []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`),
  1052. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  1053. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  1054. "secret_group_id": []byte(nilValue),
  1055. "secret_type": []byte(nilValue),
  1056. "updated_at": []byte(nilValue),
  1057. "versions_total": []byte(nilValue),
  1058. }
  1059. }
  1060. // good case: custom_credentials with property and metadata
  1061. setSecretCustomCredentialsWithMetadata := func(smtc *secretManagerTestCase) {
  1062. secret := &sm.CustomCredentialsSecret{
  1063. CreatedBy: utilpointer.To("testCreatedBy"),
  1064. CreatedAt: &strfmt.DateTime{},
  1065. Downloaded: utilpointer.To(false),
  1066. Labels: []string{"abc", "def", "xyz"},
  1067. LocksTotal: utilpointer.To(int64(20)),
  1068. CredentialsContent: secretComplex,
  1069. }
  1070. smtc.name = "good case: custom_credentials, with property and with metadata"
  1071. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1072. smtc.apiOutput = secret
  1073. smtc.ref.Key = "custom_credentials/" + secretUUID
  1074. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyFetch
  1075. smtc.expectedData = map[string][]byte{
  1076. "created_at": []byte(timeValue),
  1077. "created_by": []byte(*secret.CreatedBy),
  1078. "crn": []byte(nilValue),
  1079. "credentials_content": []byte("map[key1:val1 key2:val2 keyC:map[keyC1:map[keyA:valA keyB:valB]]]"),
  1080. "downloaded": []byte(strconv.FormatBool(*secret.Downloaded)),
  1081. "id": []byte(nilValue),
  1082. "key1": []byte("val1"),
  1083. "key2": []byte("val2"),
  1084. "keyC": []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`),
  1085. "labels": []byte("[" + strings.Join(secret.Labels, " ") + "]"),
  1086. "locks_total": []byte(strconv.Itoa(int(*secret.LocksTotal))),
  1087. "secret_group_id": []byte(nilValue),
  1088. "secret_type": []byte(nilValue),
  1089. "updated_at": []byte(nilValue),
  1090. "versions_total": []byte(nilValue),
  1091. "configuration": []byte(nilValue),
  1092. }
  1093. }
  1094. // good case: iam_credentials without metadata
  1095. setSecretIamWithoutMetadata := func(smtc *secretManagerTestCase) {
  1096. secret := &sm.IAMCredentialsSecret{
  1097. CreatedBy: utilpointer.To("testCreatedBy"),
  1098. CreatedAt: &strfmt.DateTime{},
  1099. Downloaded: utilpointer.To(false),
  1100. Labels: []string{"abc", "def", "xyz"},
  1101. LocksTotal: utilpointer.To(int64(20)),
  1102. ApiKey: utilpointer.To(secretAPIKey),
  1103. }
  1104. smtc.name = "good case: iam_credentials without metadata"
  1105. smtc.apiInput.ID = utilpointer.To(secretUUID)
  1106. smtc.apiOutput = secret
  1107. smtc.ref.Key = iamCredentialsSecret + secretUUID
  1108. smtc.ref.MetadataPolicy = esv1.ExternalSecretMetadataPolicyNone
  1109. smtc.expectedData = map[string][]byte{
  1110. "apikey": []byte(secretAPIKey),
  1111. }
  1112. }
  1113. secretKeyKV := "kv/" + secretUUID
  1114. // good case: kv, no property, return entire payload as key:value pairs
  1115. setSecretKV := func(smtc *secretManagerTestCase) {
  1116. secret := &sm.KVSecret{
  1117. Name: utilpointer.To("testyname"),
  1118. ID: utilpointer.To(secretUUID),
  1119. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  1120. Data: secretComplex,
  1121. }
  1122. smtc.name = "good case: kv, no property, return entire payload as key:value pairs"
  1123. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1124. smtc.apiOutput = secret
  1125. smtc.ref.Key = secretKeyKV
  1126. smtc.expectedData["key1"] = []byte("val1")
  1127. smtc.expectedData["key2"] = []byte("val2")
  1128. smtc.expectedData["keyC"] = []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`)
  1129. }
  1130. // good case: kv, with property
  1131. setSecretKVWithProperty := func(smtc *secretManagerTestCase) {
  1132. secret := &sm.KVSecret{
  1133. Name: utilpointer.To("d5deb37a-7883-4fe2-a5e7-3c15420adc76"),
  1134. ID: utilpointer.To(secretUUID),
  1135. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  1136. Data: secretComplex,
  1137. }
  1138. smtc.name = "good case: kv, with property"
  1139. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1140. smtc.ref.Property = "keyC"
  1141. smtc.apiOutput = secret
  1142. smtc.ref.Key = secretKeyKV
  1143. smtc.expectedData["keyC1"] = []byte(`{"keyA":"valA","keyB":"valB"}`)
  1144. }
  1145. // good case: kv, with property and path
  1146. setSecretKVWithPathAndProperty := func(smtc *secretManagerTestCase) {
  1147. secret := &sm.KVSecret{
  1148. Name: utilpointer.To(secretUUID),
  1149. ID: utilpointer.To(secretUUID),
  1150. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  1151. Data: secretComplex,
  1152. }
  1153. smtc.name = "good case: kv, with property and path"
  1154. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1155. smtc.ref.Property = "keyC.keyC1"
  1156. smtc.apiOutput = secret
  1157. smtc.ref.Key = secretKeyKV
  1158. smtc.expectedData["keyA"] = []byte("valA")
  1159. smtc.expectedData["keyB"] = []byte("valB")
  1160. }
  1161. // bad case: kv, with property and path
  1162. badSecretKVWithUnknownProperty := func(smtc *secretManagerTestCase) {
  1163. secret := &sm.KVSecret{
  1164. Name: utilpointer.To("testyname"),
  1165. ID: utilpointer.To(secretUUID),
  1166. SecretType: utilpointer.To(sm.Secret_SecretType_Kv),
  1167. Data: secretComplex,
  1168. }
  1169. smtc.name = "bad case: kv, with property and path"
  1170. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1171. smtc.ref.Property = "unknown.property"
  1172. smtc.apiOutput = secret
  1173. smtc.ref.Key = secretKeyKV
  1174. smtc.expectError = "key unknown.property does not exist in secret " + secretKeyKV
  1175. }
  1176. secretKeyCustomCredentials := "custom_credentials/" + secretUUID
  1177. // good case: custom_credentials, no property, return entire payload as key:value pairs
  1178. setSecretCustomCredentials := func(smtc *secretManagerTestCase) {
  1179. secret := &sm.CustomCredentialsSecret{
  1180. Name: utilpointer.To("testyname"),
  1181. ID: utilpointer.To(secretUUID),
  1182. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  1183. CredentialsContent: secretComplex,
  1184. }
  1185. smtc.name = "good case: custom_credentials, no property, return entire payload as key:value pairs"
  1186. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1187. smtc.apiOutput = secret
  1188. smtc.ref.Key = secretKeyCustomCredentials
  1189. smtc.expectedData["key1"] = []byte("val1")
  1190. smtc.expectedData["key2"] = []byte("val2")
  1191. smtc.expectedData["keyC"] = []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`)
  1192. }
  1193. // good case: custom_credentials, with property
  1194. setSecretCustomCredentialsWithProperty := func(smtc *secretManagerTestCase) {
  1195. secret := &sm.CustomCredentialsSecret{
  1196. Name: utilpointer.To("d5deb37a-7883-4fe2-a5e7-3c15420adc76"),
  1197. ID: utilpointer.To(secretUUID),
  1198. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  1199. CredentialsContent: secretComplex,
  1200. }
  1201. smtc.name = "good case: custom_credentials, with property"
  1202. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1203. smtc.ref.Property = "keyC"
  1204. smtc.apiOutput = secret
  1205. smtc.ref.Key = secretKeyCustomCredentials
  1206. smtc.expectedData["keyC1"] = []byte(`{"keyA":"valA","keyB":"valB"}`)
  1207. }
  1208. // good case: custom_credentials, with property and path
  1209. setSecretCustomCredentialsWithPathAndProperty := func(smtc *secretManagerTestCase) {
  1210. secret := &sm.CustomCredentialsSecret{
  1211. Name: utilpointer.To(secretUUID),
  1212. ID: utilpointer.To(secretUUID),
  1213. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  1214. CredentialsContent: secretComplex,
  1215. }
  1216. smtc.name = "good case: custom_credentials, with property and path"
  1217. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1218. smtc.ref.Property = "keyC.keyC1"
  1219. smtc.apiOutput = secret
  1220. smtc.ref.Key = secretKeyCustomCredentials
  1221. smtc.expectedData["keyA"] = []byte("valA")
  1222. smtc.expectedData["keyB"] = []byte("valB")
  1223. }
  1224. // bad case: custom_credentials, with property and path
  1225. badSecretCustomCredentialsWithUnknownProperty := func(smtc *secretManagerTestCase) {
  1226. secret := &sm.CustomCredentialsSecret{
  1227. Name: utilpointer.To("testyname"),
  1228. ID: utilpointer.To(secretUUID),
  1229. SecretType: utilpointer.To(sm.Secret_SecretType_CustomCredentials),
  1230. CredentialsContent: secretComplex,
  1231. }
  1232. smtc.name = "bad case: custom_credentials, with property and path"
  1233. smtc.apiInput.ID = core.StringPtr(secretUUID)
  1234. smtc.ref.Property = "unknown.property"
  1235. smtc.apiOutput = secret
  1236. smtc.ref.Key = secretKeyCustomCredentials
  1237. smtc.expectError = "key unknown.property does not exist in secret " + secretKeyCustomCredentials
  1238. }
  1239. successCases := []*secretManagerTestCase{
  1240. makeValidSecretManagerTestCaseCustom(badSecretIam),
  1241. makeValidSecretManagerTestCaseCustom(setSecretSrvCreds),
  1242. makeValidSecretManagerTestCaseCustom(setArbitrary),
  1243. makeValidSecretManagerTestCaseCustom(setNilMockClient),
  1244. makeValidSecretManagerTestCaseCustom(setAPIErr),
  1245. makeValidSecretManagerTestCaseCustom(setSecretUserPass),
  1246. makeValidSecretManagerTestCaseCustom(setSecretIam),
  1247. makeValidSecretManagerTestCaseCustom(setSecretCert),
  1248. makeValidSecretManagerTestCaseCustom(setSecretKV),
  1249. makeValidSecretManagerTestCaseCustom(setSecretKVWithProperty),
  1250. makeValidSecretManagerTestCaseCustom(setSecretKVWithPathAndProperty),
  1251. makeValidSecretManagerTestCaseCustom(badSecretKVWithUnknownProperty),
  1252. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentials),
  1253. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentialsWithProperty),
  1254. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentialsWithPathAndProperty),
  1255. makeValidSecretManagerTestCaseCustom(badSecretCustomCredentialsWithUnknownProperty),
  1256. makeValidSecretManagerTestCaseCustom(setSecretPublicCert),
  1257. makeValidSecretManagerTestCaseCustom(setSecretPrivateCert),
  1258. makeValidSecretManagerTestCaseCustom(setimportedCertWithNoPvtKey),
  1259. makeValidSecretManagerTestCaseCustom(setSecretIamWithMetadata),
  1260. makeValidSecretManagerTestCaseCustom(setArbitraryWithMetadata),
  1261. makeValidSecretManagerTestCaseCustom(setSecretUserPassWithMetadata),
  1262. makeValidSecretManagerTestCaseCustom(setimportedCertWithMetadata),
  1263. makeValidSecretManagerTestCaseCustom(setPublicCertWithMetadata),
  1264. makeValidSecretManagerTestCaseCustom(setPrivateCertWithMetadata),
  1265. makeValidSecretManagerTestCaseCustom(setSecretKVWithMetadata),
  1266. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentialsWithMetadata),
  1267. makeValidSecretManagerTestCaseCustom(setSecretIamWithoutMetadata),
  1268. makeValidSecretManagerTestCaseCustom(setSecretIamByName),
  1269. makeValidSecretManagerTestCaseCustom(setSecretCustomCredentials),
  1270. }
  1271. sm := providerIBM{}
  1272. for _, v := range successCases {
  1273. t.Run(v.name, func(t *testing.T) {
  1274. sm.IBMClient = v.mockClient
  1275. out, err := sm.GetSecretMap(context.Background(), *v.ref)
  1276. if !ErrorContains(err, v.expectError) {
  1277. t.Errorf("unexpected error: %s, expected: '%s'", err.Error(), v.expectError)
  1278. }
  1279. if err == nil && !reflect.DeepEqual(out, v.expectedData) {
  1280. // Add some debug logs because t.Errorf is hard to debug at a glance.
  1281. for k, val := range out {
  1282. if val2, ok := v.expectedData[k]; !ok {
  1283. t.Logf("%s was not in expected data\n", k)
  1284. } else if !bytes.Equal(val2, val) {
  1285. fmt.Printf("%s did not equal expected value: %s\n", string(val), string(val2))
  1286. }
  1287. }
  1288. for k := range v.expectedData {
  1289. if _, ok := out[k]; !ok {
  1290. t.Logf("%s expected key was not in out\n", k)
  1291. }
  1292. }
  1293. t.Errorf("unexpected secret data: expected:\n%+v\ngot:\n%+v", v.expectedData, out)
  1294. }
  1295. })
  1296. }
  1297. }
  1298. func TestValidRetryInput(t *testing.T) {
  1299. sm := providerIBM{}
  1300. invalid := "Invalid"
  1301. serviceURL := "http://fake-service-url.cool"
  1302. spec := &esv1.SecretStore{
  1303. Spec: esv1.SecretStoreSpec{
  1304. Provider: &esv1.SecretStoreProvider{
  1305. IBM: &esv1.IBMProvider{
  1306. Auth: esv1.IBMAuth{
  1307. SecretRef: &esv1.IBMAuthSecretRef{
  1308. SecretAPIKey: v1.SecretKeySelector{
  1309. Name: "fake-secret",
  1310. Key: "fake-key",
  1311. },
  1312. },
  1313. },
  1314. ServiceURL: &serviceURL,
  1315. },
  1316. },
  1317. RetrySettings: &esv1.SecretStoreRetrySettings{
  1318. RetryInterval: &invalid,
  1319. },
  1320. },
  1321. }
  1322. expected := fmt.Sprintf("cannot setup new ibm client: time: invalid duration %q", invalid)
  1323. ctx := context.TODO()
  1324. kube := clientfake.NewClientBuilder().WithObjects(&corev1.Secret{
  1325. ObjectMeta: metav1.ObjectMeta{
  1326. Name: "fake-secret",
  1327. Namespace: "default",
  1328. },
  1329. Data: map[string][]byte{
  1330. "fake-key": []byte("ImAFakeApiKey"),
  1331. },
  1332. }).Build()
  1333. _, err := sm.NewClient(ctx, spec, kube, "default")
  1334. if !ErrorContains(err, expected) {
  1335. t.Errorf("CheckValidRetryInput unexpected error: %s, expected: '%s'", err.Error(), expected)
  1336. }
  1337. }
  1338. func ErrorContains(out error, want string) bool {
  1339. if out == nil {
  1340. return want == ""
  1341. }
  1342. if want == "" {
  1343. return false
  1344. }
  1345. return strings.Contains(out.Error(), want)
  1346. }