provider_test.go 47 KB

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