provider_test.go 45 KB

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