provider_test.go 55 KB

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