vault_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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 vault
  13. import (
  14. "bytes"
  15. "context"
  16. "encoding/json"
  17. "errors"
  18. "fmt"
  19. "io/ioutil"
  20. "net/http"
  21. "testing"
  22. "github.com/crossplane/crossplane-runtime/pkg/test"
  23. "github.com/google/go-cmp/cmp"
  24. vault "github.com/hashicorp/vault/api"
  25. corev1 "k8s.io/api/core/v1"
  26. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  27. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  28. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  29. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  30. "github.com/external-secrets/external-secrets/pkg/provider/vault/fake"
  31. )
  32. const (
  33. tokenSecretName = "example-secret-token"
  34. secretDataString = "some-creds"
  35. )
  36. func makeValidSecretStore() *esv1alpha1.SecretStore {
  37. return &esv1alpha1.SecretStore{
  38. ObjectMeta: metav1.ObjectMeta{
  39. Name: "vault-store",
  40. Namespace: "default",
  41. },
  42. Spec: esv1alpha1.SecretStoreSpec{
  43. Provider: &esv1alpha1.SecretStoreProvider{
  44. Vault: &esv1alpha1.VaultProvider{
  45. Server: "vault.example.com",
  46. Path: "secret",
  47. Version: esv1alpha1.VaultKVStoreV2,
  48. Auth: esv1alpha1.VaultAuth{
  49. Kubernetes: &esv1alpha1.VaultKubernetesAuth{
  50. Path: "kubernetes",
  51. Role: "kubernetes-auth-role",
  52. ServiceAccountRef: &esmeta.ServiceAccountSelector{
  53. Name: "example-sa",
  54. },
  55. },
  56. },
  57. },
  58. },
  59. },
  60. }
  61. }
  62. func makeValidSecretStoreWithCerts() *esv1alpha1.SecretStore {
  63. return &esv1alpha1.SecretStore{
  64. ObjectMeta: metav1.ObjectMeta{
  65. Name: "vault-store",
  66. Namespace: "default",
  67. },
  68. Spec: esv1alpha1.SecretStoreSpec{
  69. Provider: &esv1alpha1.SecretStoreProvider{
  70. Vault: &esv1alpha1.VaultProvider{
  71. Server: "vault.example.com",
  72. Path: "secret",
  73. Version: esv1alpha1.VaultKVStoreV2,
  74. Auth: esv1alpha1.VaultAuth{
  75. Cert: &esv1alpha1.VaultCertAuth{
  76. ClientCert: esmeta.SecretKeySelector{
  77. Name: "tls-auth-certs",
  78. Key: "tls.crt",
  79. },
  80. SecretRef: esmeta.SecretKeySelector{
  81. Name: "tls-auth-certs",
  82. Key: "tls.key",
  83. },
  84. },
  85. },
  86. },
  87. },
  88. },
  89. }
  90. }
  91. func makeValidSecretStoreWithK8sCerts(isSecret bool) *esv1alpha1.SecretStore {
  92. store := makeSecretStore()
  93. caProvider := &esv1alpha1.CAProvider{
  94. Name: "vault-cert",
  95. Key: "cert",
  96. }
  97. if isSecret {
  98. caProvider.Type = "Secret"
  99. } else {
  100. caProvider.Type = "ConfigMap"
  101. }
  102. store.Spec.Provider.Vault.CAProvider = caProvider
  103. return store
  104. }
  105. type secretStoreTweakFn func(s *esv1alpha1.SecretStore)
  106. func makeSecretStore(tweaks ...secretStoreTweakFn) *esv1alpha1.SecretStore {
  107. store := makeValidSecretStore()
  108. for _, fn := range tweaks {
  109. fn(store)
  110. }
  111. return store
  112. }
  113. func newVaultResponse(data *vault.Secret) *vault.Response {
  114. jsonData, _ := json.Marshal(data)
  115. return &vault.Response{
  116. Response: &http.Response{
  117. Body: ioutil.NopCloser(bytes.NewReader(jsonData)),
  118. },
  119. }
  120. }
  121. func newVaultTokenIDResponse(token string) *vault.Response {
  122. return newVaultResponse(&vault.Secret{
  123. Data: map[string]interface{}{
  124. "id": token,
  125. },
  126. })
  127. }
  128. func clientWithLoginMock(c *vault.Config) (Client, error) {
  129. return &fake.VaultClient{
  130. MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
  131. MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
  132. newVaultTokenIDResponse("test-token"), nil, func(got *vault.Request) error { return nil }),
  133. MockSetToken: fake.NewSetTokenFn(),
  134. }, nil
  135. }
  136. func kubeMockWithSecretTokenAndServiceAcc(obj kclient.Object) error {
  137. if o, ok := obj.(*corev1.ServiceAccount); ok {
  138. o.Secrets = []corev1.ObjectReference{
  139. {
  140. Name: tokenSecretName,
  141. },
  142. }
  143. return nil
  144. }
  145. if o, ok := obj.(*corev1.Secret); ok {
  146. o.Data = map[string][]byte{
  147. "token": []byte(secretDataString),
  148. }
  149. return nil
  150. }
  151. return nil
  152. }
  153. func TestNewVault(t *testing.T) {
  154. errBoom := errors.New("boom")
  155. secretClientKey := []byte(`-----BEGIN RSA PRIVATE KEY-----
  156. MIIEpAIBAAKCAQEArfZ4HV1obFVlVNiA24tX/UOakqRnEtWXpIvaOsMaPGvvODgGe4XnyJGO32idPv85sIr7vDH9p+OhactVlJV1fu5SZoZ7pg4jTCLqVDCb3IRD++yik2Sw58YayNe3HiaCTsJQWeMXLzfaqOeyk6bEpBCJo09+3QxUWxijgJ7YZCb+Gi8pf3ZWeSZG+rGNNvXHmTs1Yu1H849SYXu+uJOd/R3ZSTw8CxFe4eTLgbCnPf6tgA8Sg2hc+CAZxunPP2JLZWbiJXxjNRoypso6MAJ1FRkx5sTJiLg6UoLvd95/S/lCVOR2PDlM1hg7ox8VEd4QHky7tLx7gji/5hHQKJQSTwIDAQABAoIBAQCYPICQ8hVX+MNcpLrfZenycR7sBYNOMC0silbH5cUn6yzFfgHuRxi3pOnrCJnTb3cE0BvMbdMVAVdYReD2znSsR9NEdZvvjZ/GGSgH1SIQsI7t//+mDQ/jRLJb4KsXb4vJcLLwdpLrd22bMmhMXjzndrF8gSz8NLX9omozPM8RlLxjzPzYOdlX/Zw8V68qQH2Ic04KbtnCwyAUIgAJxYtn/uYB8lzILBkyzQqwhQKkDDZQ0wbZT0hP6z+HgsdifwQvHG1GZAgCuzzyXrL/4TgDaDhYdMVoBA4+HPmzqm5MkBvjH4oqroxjRofUroVix0OGXZJMI1OJ0z/ubzmwCq5BAoGBANqbwzAydUJs0P+GFL94K/Y6tXULKA2c9N0crbxoxheobRpuJvhpW1ZE/9UGpaYX1Rw3nW4x+Jwvt83YkgHAlR4LgEwDvdJPZobybfqifQDiraUO0t62Crn8mSxOsFCugtRIFniwnX67w3uKxiSdCZYbJGs9JEDTpxRG/PSWq3QlAoGBAMu3zOv1PJAhOky7VcxFxWQPEMY+t2PA/sneD01/qgGuhlTwL4QlpywmBqXcI070dcvcBkP0flnWI7y5cnuE1+55twmsrvfaS8s1+AYje0b35DsaF2vtKuJrXC0AGKP+/eiycd9cbvVW2GWOxE7Ui76Mj95MARK8ZNjt0wJagQhjAoGASm9dD80uhhadN1RFPkjB1054OMk6sx/tdFhug8e9I5MSyzwUguME2aQW5EcmIh7dToVVUo8rUqsgz7NdS8FyRM+vuLJRcQneJDbp4bxwCdwlOh2JCZI8psVutlp4yJATNgrxs9iXV+7BChDflNnvyK+nP+iKrpQiwNHHEdU3vg0CgYEAvEpwD4+loJn1psJn9NxwK6F5IaMKIhtZ4/9pKXpcCh3jb1JouL2MnFOxRVAJGor87aW57Mlol2RDt8W4OM56PqMlOL3xIokUEQka66GT6e5pdu8QwuJ9BrWwhq9WFw4yZQe6FHb836qbbJLegvYVC9QjjZW2UDjtBUwcAkrghH0CgYBUMmMOCwIfMEtMaWxZRGdxRabazLhn7TXhBpVTuv7WouPaXYd7ZGjCTMKAuVa/E4afBlxgemnqBuX90gHpK/dDmn9l+lp8GZey0grJ7G0x5HEMiKziaX5PrgAcKbQ70m9ZNZ1deYhsC05X8rHNexZB6ns7Yms9L7qnlAy51ZH2zw==
  157. -----END RSA PRIVATE KEY-----`)
  158. clientCrt := []byte(`-----BEGIN CERTIFICATE-----
  159. MIICsTCCAZkCFEJJ4daz5sxkFlzq9n1djLEuG7bmMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCHZhdWx0LWNhMB4XDTIxMDcyMDA4MTQxM1oXDTIyMDcyMDA4MTQxM1owFzEVMBMGA1UEAwwMdmF1bHQtY2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArfZ4HV1obFVlVNiA24tX/UOakqRnEtWXpIvaOsMaPGvvODgGe4XnyJGO32idPv85sIr7vDH9p+OhactVlJV1fu5SZoZ7pg4jTCLqVDCb3IRD++yik2Sw58YayNe3HiaCTsJQWeMXLzfaqOeyk6bEpBCJo09+3QxUWxijgJ7YZCb+Gi8pf3ZWeSZG+rGNNvXHmTs1Yu1H849SYXu+uJOd/R3ZSTw8CxFe4eTLgbCnPf6tgA8Sg2hc+CAZxunPP2JLZWbiJXxjNRoypso6MAJ1FRkx5sTJiLg6UoLvd95/S/lCVOR2PDlM1hg7ox8VEd4QHky7tLx7gji/5hHQKJQSTwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAsDYKtzScIA7bqIOmqF8rr+oLSjRhPt5OfT+KGNdXk8G3VAy1ED2tyCHaRNC7dPLq4EvcxbIXQnXPy1iZMofriGbFPAcQ2fyWUesAD6bYSpI+bYxwz6Ebb93hU5nc/FyXg8yh0kgiGbY3MrACPjxqP2+z5kcOC3u3hx3SZylgW7TeOXDTdqSbNfH1b+1rR/bVNgQQshjhU9d+c4Yv/t0u07uykBhHLWZDSnYiAeOZ8+mWuOSDkcZHE1zznx74fWgtN0zRDtr0L0w9evT9R2CnNSZGxXcEQxAlQ7SL/Jyw82TFCGEw0L4jj7jjvx0N5J8KX/DulUDE9vuVyQEJ88Epe
  160. -----END CERTIFICATE-----
  161. `)
  162. secretData := []byte(secretDataString)
  163. type args struct {
  164. newClientFunc func(c *vault.Config) (Client, error)
  165. store esv1alpha1.GenericStore
  166. kube kclient.Client
  167. ns string
  168. }
  169. type want struct {
  170. err error
  171. }
  172. cases := map[string]struct {
  173. reason string
  174. args args
  175. want want
  176. }{
  177. "InvalidVaultStore": {
  178. reason: "Should return error if given an invalid vault store.",
  179. args: args{
  180. store: &esv1alpha1.SecretStore{},
  181. },
  182. want: want{
  183. err: errors.New(errVaultStore),
  184. },
  185. },
  186. "AddVaultStoreCertsError": {
  187. reason: "Should return error if given an invalid CA certificate.",
  188. args: args{
  189. store: makeSecretStore(func(s *esv1alpha1.SecretStore) {
  190. s.Spec.Provider.Vault.CABundle = []byte("badcertdata")
  191. }),
  192. },
  193. want: want{
  194. err: errors.New(errVaultCert),
  195. },
  196. },
  197. "VaultAuthFormatError": {
  198. reason: "Should return error if no valid authentication method is given.",
  199. args: args{
  200. store: makeSecretStore(func(s *esv1alpha1.SecretStore) {
  201. s.Spec.Provider.Vault.Auth = esv1alpha1.VaultAuth{}
  202. }),
  203. },
  204. want: want{
  205. err: errors.New(errAuthFormat),
  206. },
  207. },
  208. "GetKubeServiceAccountError": {
  209. reason: "Should return error if fetching kubernetes secret fails.",
  210. args: args{
  211. store: makeSecretStore(),
  212. kube: &test.MockClient{
  213. MockGet: test.NewMockGetFn(errBoom),
  214. },
  215. },
  216. want: want{
  217. err: fmt.Errorf(errGetKubeSA, "example-sa", errBoom),
  218. },
  219. },
  220. "GetKubeSecretError": {
  221. reason: "Should return error if fetching kubernetes secret fails.",
  222. args: args{
  223. store: makeSecretStore(func(s *esv1alpha1.SecretStore) {
  224. s.Spec.Provider.Vault.Auth.Kubernetes.ServiceAccountRef = nil
  225. s.Spec.Provider.Vault.Auth.Kubernetes.SecretRef = &esmeta.SecretKeySelector{
  226. Name: "vault-secret",
  227. Key: "key",
  228. }
  229. }),
  230. kube: &test.MockClient{
  231. MockGet: test.NewMockGetFn(errBoom),
  232. },
  233. },
  234. want: want{
  235. err: fmt.Errorf(errGetKubeSecret, "vault-secret", errBoom),
  236. },
  237. },
  238. "SuccessfulVaultStore": {
  239. reason: "Should return a Vault provider successfully",
  240. args: args{
  241. store: makeSecretStore(),
  242. kube: &test.MockClient{
  243. MockGet: test.NewMockGetFn(nil, kubeMockWithSecretTokenAndServiceAcc),
  244. },
  245. newClientFunc: func(c *vault.Config) (Client, error) {
  246. return &fake.VaultClient{
  247. MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
  248. MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(
  249. newVaultTokenIDResponse("test-token"), nil, func(got *vault.Request) error {
  250. kubeRole := makeValidSecretStore().Spec.Provider.Vault.Auth.Kubernetes.Role
  251. want := kubeParameters(kubeRole, string(secretData))
  252. if diff := cmp.Diff(want, got.Obj); diff != "" {
  253. t.Errorf("RawRequestWithContext(...): -want, +got:\n%s", diff)
  254. }
  255. return nil
  256. }),
  257. MockSetToken: fake.NewSetTokenFn(),
  258. MockToken: fake.NewTokenFn(""),
  259. MockClearToken: fake.NewClearTokenFn(),
  260. }, nil
  261. },
  262. },
  263. want: want{
  264. err: nil,
  265. },
  266. },
  267. "SuccessfulVaultStoreWithCertAuth": {
  268. reason: "Should return a Vault provider successfully",
  269. args: args{
  270. store: makeValidSecretStoreWithCerts(),
  271. kube: &test.MockClient{
  272. MockGet: test.NewMockGetFn(nil, func(obj kclient.Object) error {
  273. if o, ok := obj.(*corev1.Secret); ok {
  274. o.Data = map[string][]byte{
  275. "tls.key": secretClientKey,
  276. "tls.crt": clientCrt,
  277. }
  278. return nil
  279. }
  280. return nil
  281. }),
  282. },
  283. newClientFunc: clientWithLoginMock,
  284. },
  285. want: want{
  286. err: nil,
  287. },
  288. },
  289. "SuccessfulVaultStoreWithK8sCertSecret": {
  290. reason: "Should return a Vault prodvider with the cert from k8s",
  291. args: args{
  292. store: makeValidSecretStoreWithK8sCerts(true),
  293. kube: &test.MockClient{
  294. MockGet: test.NewMockGetFn(nil, func(obj kclient.Object) error {
  295. if o, ok := obj.(*corev1.Secret); ok {
  296. o.Data = map[string][]byte{
  297. "cert": clientCrt,
  298. "token": secretData,
  299. }
  300. return nil
  301. }
  302. if o, ok := obj.(*corev1.ServiceAccount); ok {
  303. o.Secrets = []corev1.ObjectReference{
  304. {
  305. Name: tokenSecretName,
  306. },
  307. }
  308. return nil
  309. }
  310. return nil
  311. }),
  312. },
  313. newClientFunc: clientWithLoginMock,
  314. },
  315. want: want{
  316. err: nil,
  317. },
  318. },
  319. "GetCertSecretKeyMissingError": {
  320. reason: "Should return an error if the secret key is missing",
  321. args: args{
  322. store: makeValidSecretStoreWithK8sCerts(true),
  323. kube: &test.MockClient{
  324. MockGet: test.NewMockGetFn(nil, kubeMockWithSecretTokenAndServiceAcc),
  325. },
  326. newClientFunc: clientWithLoginMock,
  327. },
  328. want: want{
  329. err: fmt.Errorf(errVaultCert, errors.New(`cannot find secret data for key: "cert"`)),
  330. },
  331. },
  332. "SuccessfulVaultStoreWithK8sCertConfigMap": {
  333. reason: "Should return a Vault prodvider with the cert from k8s",
  334. args: args{
  335. store: makeValidSecretStoreWithK8sCerts(false),
  336. kube: &test.MockClient{
  337. MockGet: test.NewMockGetFn(nil, func(obj kclient.Object) error {
  338. if o, ok := obj.(*corev1.ConfigMap); ok {
  339. o.Data = map[string]string{
  340. "cert": string(clientCrt),
  341. }
  342. return nil
  343. }
  344. if o, ok := obj.(*corev1.ServiceAccount); ok {
  345. o.Secrets = []corev1.ObjectReference{
  346. {
  347. Name: tokenSecretName,
  348. },
  349. }
  350. return nil
  351. }
  352. if o, ok := obj.(*corev1.Secret); ok {
  353. o.Data = map[string][]byte{
  354. "token": secretData,
  355. }
  356. return nil
  357. }
  358. return nil
  359. }),
  360. },
  361. newClientFunc: clientWithLoginMock,
  362. },
  363. want: want{
  364. err: nil,
  365. },
  366. },
  367. "GetCertConfigMapMissingError": {
  368. reason: "Should return an error if the config map key is missing",
  369. args: args{
  370. store: makeValidSecretStoreWithK8sCerts(false),
  371. kube: &test.MockClient{
  372. MockGet: test.NewMockGetFn(nil, func(obj kclient.Object) error {
  373. if o, ok := obj.(*corev1.ServiceAccount); ok {
  374. o.Secrets = []corev1.ObjectReference{
  375. {
  376. Name: tokenSecretName,
  377. },
  378. }
  379. return nil
  380. }
  381. if o, ok := obj.(*corev1.Secret); ok {
  382. o.Data = map[string][]byte{
  383. "token": secretData,
  384. }
  385. return nil
  386. }
  387. return nil
  388. }),
  389. },
  390. newClientFunc: clientWithLoginMock,
  391. },
  392. want: want{
  393. err: fmt.Errorf(errConfigMapFmt, "cert"),
  394. },
  395. },
  396. "GetCertificateFormatError": {
  397. reason: "Should return error if client certificate is in wrong format.",
  398. args: args{
  399. store: makeValidSecretStoreWithCerts(),
  400. kube: &test.MockClient{
  401. MockGet: test.NewMockGetFn(nil, func(obj kclient.Object) error {
  402. if o, ok := obj.(*corev1.Secret); ok {
  403. o.Data = map[string][]byte{
  404. "tls.key": secretClientKey,
  405. "tls.crt": []byte("cert with mistak"),
  406. }
  407. return nil
  408. }
  409. return nil
  410. }),
  411. },
  412. newClientFunc: clientWithLoginMock,
  413. },
  414. want: want{
  415. err: fmt.Errorf(errClientTLSAuth, "tls: failed to find any PEM data in certificate input"),
  416. },
  417. },
  418. "GetKeyFormatError": {
  419. reason: "Should return error if client key is in wrong format.",
  420. args: args{
  421. store: makeValidSecretStoreWithCerts(),
  422. kube: &test.MockClient{
  423. MockGet: test.NewMockGetFn(nil, func(obj kclient.Object) error {
  424. if o, ok := obj.(*corev1.Secret); ok {
  425. o.Data = map[string][]byte{
  426. "tls.key": []byte("key with mistake"),
  427. "tls.crt": clientCrt,
  428. }
  429. return nil
  430. }
  431. return nil
  432. }),
  433. },
  434. newClientFunc: clientWithLoginMock,
  435. },
  436. want: want{
  437. err: fmt.Errorf(errClientTLSAuth, "tls: failed to find any PEM data in key input"),
  438. },
  439. },
  440. }
  441. for name, tc := range cases {
  442. t.Run(name, func(t *testing.T) {
  443. conn := &connector{
  444. newVaultClient: tc.args.newClientFunc,
  445. }
  446. if tc.args.newClientFunc == nil {
  447. conn.newVaultClient = newVaultClient
  448. }
  449. _, err := conn.NewClient(context.Background(), tc.args.store, tc.args.kube, tc.args.ns)
  450. if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
  451. t.Errorf("\n%s\nvault.New(...): -want error, +got error:\n%s", tc.reason, diff)
  452. }
  453. })
  454. }
  455. }
  456. func TestGetSecretMap(t *testing.T) {
  457. errBoom := errors.New("boom")
  458. type args struct {
  459. store *esv1alpha1.VaultProvider
  460. kube kclient.Client
  461. vClient Client
  462. ns string
  463. data esv1alpha1.ExternalSecretDataRemoteRef
  464. }
  465. type want struct {
  466. err error
  467. }
  468. cases := map[string]struct {
  469. reason string
  470. args args
  471. want want
  472. }{
  473. "ReadSecretError": {
  474. reason: "Should return error if vault client fails to read secret.",
  475. args: args{
  476. store: makeSecretStore().Spec.Provider.Vault,
  477. vClient: &fake.VaultClient{
  478. MockNewRequest: fake.NewMockNewRequestFn(&vault.Request{}),
  479. MockRawRequestWithContext: fake.NewMockRawRequestWithContextFn(nil, errBoom),
  480. },
  481. },
  482. want: want{
  483. err: fmt.Errorf(errReadSecret, errBoom),
  484. },
  485. },
  486. }
  487. for name, tc := range cases {
  488. t.Run(name, func(t *testing.T) {
  489. vStore := &client{
  490. kube: tc.args.kube,
  491. client: tc.args.vClient,
  492. store: tc.args.store,
  493. namespace: tc.args.ns,
  494. }
  495. _, err := vStore.GetSecretMap(context.Background(), tc.args.data)
  496. if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
  497. t.Errorf("\n%s\nvault.GetSecretMap(...): -want error, +got error:\n%s", tc.reason, diff)
  498. }
  499. })
  500. }
  501. }