provider_test.go 53 KB

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