provider_test.go 40 KB

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