provider_test.go 45 KB

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