provider_test.go 45 KB

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