webhook_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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 webhook
  13. import (
  14. "bytes"
  15. "context"
  16. "errors"
  17. "io"
  18. "net/http"
  19. "net/http/httptest"
  20. "strings"
  21. "testing"
  22. "time"
  23. "gopkg.in/yaml.v3"
  24. corev1 "k8s.io/api/core/v1"
  25. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  26. "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  27. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  28. )
  29. type testCase struct {
  30. Case string `json:"case,omitempty"`
  31. Args args `json:"args"`
  32. Want want `json:"want"`
  33. }
  34. type secret struct {
  35. Name string `json:"name"`
  36. Data map[string]string `json:"data"`
  37. }
  38. type args struct {
  39. URL string `json:"url,omitempty"`
  40. Body string `json:"body,omitempty"`
  41. Timeout string `json:"timeout,omitempty"`
  42. Key string `json:"key,omitempty"`
  43. SecretKey string `json:"secretkey,omitempty"`
  44. Property string `json:"property,omitempty"`
  45. Version string `json:"version,omitempty"`
  46. JSONPath string `json:"jsonpath,omitempty"`
  47. Response string `json:"response,omitempty"`
  48. StatusCode int `json:"statuscode,omitempty"`
  49. PushSecret bool `json:"pushsecret,omitempty"`
  50. Secret secret `json:"secret,omitempty"`
  51. }
  52. type want struct {
  53. Path string `json:"path,omitempty"`
  54. Body *string `json:"body,omitempty"`
  55. Err string `json:"err,omitempty"`
  56. Result string `json:"result,omitempty"`
  57. ResultMap map[string]string `json:"resultmap,omitempty"`
  58. }
  59. var testCases = `
  60. case: error url
  61. args:
  62. url: /api/getsecret?id={{ .unclosed.template
  63. want:
  64. err: failed to parse url
  65. ---
  66. case: error body
  67. args:
  68. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  69. body: Body error {{ .unclosed.template
  70. want:
  71. err: failed to parse body
  72. ---
  73. case: error connection
  74. args:
  75. url: 1/api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  76. want:
  77. err: failed to call endpoint
  78. ---
  79. case: error no secret err
  80. args:
  81. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  82. key: testkey
  83. version: 1
  84. statuscode: 404
  85. response: not found
  86. want:
  87. path: /api/getsecret?id=testkey&version=1
  88. err: ` + esv1beta1.NoSecretErr.Error() + `
  89. ---
  90. case: error server error
  91. args:
  92. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  93. key: testkey
  94. version: 1
  95. statuscode: 500
  96. response: server error
  97. want:
  98. path: /api/getsecret?id=testkey&version=1
  99. err: endpoint gave error 500
  100. ---
  101. case: error bad json
  102. args:
  103. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  104. key: testkey
  105. version: 1
  106. jsonpath: $.result.thesecret
  107. response: '{"result":{"thesecret":"secret-value"}'
  108. want:
  109. path: /api/getsecret?id=testkey&version=1
  110. err: failed to parse response json
  111. ---
  112. case: error bad jsonpath
  113. args:
  114. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  115. key: testkey
  116. version: 1
  117. jsonpath: $.result.thesecret
  118. response: '{"result":{"nosecret":"secret-value"}}'
  119. want:
  120. path: /api/getsecret?id=testkey&version=1
  121. err: failed to get response path
  122. ---
  123. case: pull data out of map
  124. args:
  125. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  126. key: testkey
  127. version: 1
  128. jsonpath: $.result.thesecret
  129. response: '{"result":{"thesecret":{"one":"secret-value"}}}'
  130. want:
  131. path: /api/getsecret?id=testkey&version=1
  132. err: ''
  133. result: '{"one":"secret-value"}'
  134. ---
  135. case: error timeout
  136. args:
  137. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  138. key: testkey
  139. version: 1
  140. response: secret-value
  141. timeout: 0.01ms
  142. want:
  143. path: /api/getsecret?id=testkey&version=1
  144. err: context deadline exceeded
  145. ---
  146. case: good plaintext
  147. args:
  148. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  149. key: testkey
  150. version: 1
  151. response: secret-value
  152. want:
  153. path: /api/getsecret?id=testkey&version=1
  154. err: ''
  155. result: secret-value
  156. ---
  157. case: good json
  158. args:
  159. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  160. key: testkey
  161. version: 1
  162. jsonpath: $.result.thesecret
  163. response: '{"result":{"thesecret":"secret-value"}}'
  164. want:
  165. path: /api/getsecret?id=testkey&version=1
  166. err: ''
  167. result: secret-value
  168. ---
  169. case: good json map
  170. args:
  171. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  172. key: testkey
  173. version: 1
  174. jsonpath: $.result
  175. response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value"}}'
  176. want:
  177. path: /api/getsecret?id=testkey&version=1
  178. err: ''
  179. resultmap:
  180. thesecret: secret-value
  181. alsosecret: another-value
  182. ---
  183. case: good json map string
  184. args:
  185. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  186. key: testkey
  187. version: 1
  188. response: '{"thesecret":"secret-value","alsosecret":"another-value"}'
  189. want:
  190. path: /api/getsecret?id=testkey&version=1
  191. err: ''
  192. resultmap:
  193. thesecret: secret-value
  194. alsosecret: another-value
  195. ---
  196. case: error json map string
  197. args:
  198. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  199. key: testkey
  200. version: 1
  201. response: 'some simple string'
  202. want:
  203. path: /api/getsecret?id=testkey&version=1
  204. err: "failed to parse response json: invalid character"
  205. resultmap: {}
  206. ---
  207. case: error json map
  208. args:
  209. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  210. key: testkey
  211. version: 1
  212. jsonpath: $.result.thesecret
  213. response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value"}}'
  214. want:
  215. path: /api/getsecret?id=testkey&version=1
  216. err: "failed to parse response json from jsonpath"
  217. resultmap: {}
  218. ---
  219. case: good json with good templated jsonpath
  220. args:
  221. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  222. key: testkey
  223. property: thesecret
  224. version: 1
  225. jsonpath: $.result.{{ .remoteRef.property }}
  226. response: '{"result":{"thesecret":"secret-value"}}'
  227. want:
  228. path: /api/getsecret?id=testkey&version=1
  229. err: ''
  230. result: secret-value
  231. ---
  232. case: good json with jsonpath filter
  233. args:
  234. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  235. key: testkey
  236. version: 1
  237. jsonpath: $.secrets[?@.name=="thesecret"].value
  238. response: '{"secrets": [{"name": "thesecret", "value": "secret-value"}, {"name": "alsosecret", "value": "another-value"}]}'
  239. want:
  240. path: /api/getsecret?id=testkey&version=1
  241. err: ''
  242. result: secret-value
  243. ---
  244. case: good json with bad templated jsonpath
  245. args:
  246. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  247. key: testkey
  248. property: thesecret
  249. version: 1
  250. jsonpath: $.result.{{ .remoteRef.property }
  251. response: '{"result":{"thesecret":"secret-value"}}'
  252. want:
  253. path: /api/getsecret?id=testkey&version=1
  254. err: 'template: webhooktemplate:1: unexpected "}" in operand'
  255. ---
  256. case: error with jsonpath filter empty results
  257. args:
  258. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  259. key: testkey
  260. version: 1
  261. jsonpath: $.secrets[?@.name=="thebadsecret"].value
  262. response: '{"secrets": [{"name": "thesecret", "value": "secret-value"}, {"name": "alsosecret", "value": "another-value"}]}'
  263. want:
  264. path: /api/getsecret?id=testkey&version=1
  265. err: "filter worked but didn't get any result"
  266. ---
  267. case: success with jsonpath filter and result array
  268. args:
  269. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  270. key: testkey
  271. version: 1
  272. jsonpath: $..name
  273. response: '{"secrets": [{"name": "thesecret", "value": "secret-value"}, {"name": "alsosecret", "value": "another-value"}]}'
  274. want:
  275. path: /api/getsecret?id=testkey&version=1
  276. err: ''
  277. result: 'thesecret'
  278. ---
  279. case: success with jsonpath filter and result array of ints
  280. args:
  281. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  282. key: testkey
  283. version: 1
  284. jsonpath: $..name
  285. response: '{"secrets": [{"name": 123, "value": "secret-value"}, {"name": 456, "value": "another-value"}]}'
  286. want:
  287. path: /api/getsecret?id=testkey&version=1
  288. err: ''
  289. result: 123
  290. ---
  291. case: support backslash
  292. args:
  293. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  294. key: testkey
  295. version: 1
  296. jsonpath: $.refresh_token
  297. response: '{"access_token":"REDACTED","refresh_token":"RE\/DACTED=="}'
  298. want:
  299. path: /api/getsecret?id=testkey&version=1
  300. err: ''
  301. result: "RE/DACTED=="
  302. ---
  303. case: good json with mixed fields and jsonpath filter
  304. args:
  305. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  306. key: testkey
  307. version: 1
  308. jsonpath: $.result.thesecret
  309. response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value", "id": 1234, "weight": 1.5}}'
  310. want:
  311. path: /api/getsecret?id=testkey&version=1
  312. err: ''
  313. result: secret-value
  314. ---
  315. case: good json with mixed fields to map
  316. args:
  317. url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
  318. key: testkey
  319. version: 1
  320. jsonpath: $.result
  321. response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value", "id": 1234, "weight": 1.5}}'
  322. want:
  323. path: /api/getsecret?id=testkey&version=1
  324. err: ''
  325. resultmap:
  326. thesecret: secret-value
  327. alsosecret: another-value
  328. id: 1234
  329. weight: 1.5
  330. ---
  331. case: only url encoding for url templates
  332. args:
  333. url: /api/getsecrets?folder={{ .remoteRef.key }}
  334. body: '{"folder": "{{ .remoteRef.key }}"}'
  335. key: /myapp/secrets
  336. want:
  337. path: /api/getsecrets?folder=%2Fmyapp%2Fsecrets
  338. body: '{"folder": "/myapp/secrets"}'
  339. `
  340. func TestWebhookGetSecret(t *testing.T) {
  341. ydec := yaml.NewDecoder(bytes.NewReader([]byte(testCases)))
  342. for {
  343. var tc testCase
  344. if err := ydec.Decode(&tc); err != nil {
  345. if !errors.Is(err, io.EOF) {
  346. t.Errorf("testcase decode error %v", err)
  347. }
  348. break
  349. }
  350. runTestCase(tc, t)
  351. }
  352. }
  353. var testCasesPushSecret = `
  354. ---
  355. case: secret key not found
  356. args:
  357. url: /api/pushsecret?id={{ .remoteRef.remoteKey }}&secret={{ .remoteRef.secretKey }}
  358. key: testkey
  359. secretkey: not-found
  360. pushsecret: true
  361. secret:
  362. name: test-secret
  363. data:
  364. secretkey: value
  365. want:
  366. path: /api/pushsecret?id=testkey&secret=not-found
  367. err: 'failed to find secret key in secret with key: not-found'
  368. ---
  369. case: default body good json
  370. args:
  371. url: /api/pushsecret?id={{ .remoteRef.remoteKey }}&secret={{ .remoteRef.secretKey }}
  372. key: testkey
  373. secretkey: secretkey
  374. pushsecret: true
  375. secret:
  376. name: test-secret
  377. data:
  378. secretkey: value
  379. want:
  380. path: /api/pushsecret?id=testkey&secret=secretkey
  381. body: 'value'
  382. err: ''
  383. ---
  384. case: good json
  385. args:
  386. url: /api/pushsecret?id={{ .remoteRef.remoteKey }}&secret={{ .remoteRef.secretKey }}
  387. key: testkey
  388. body: 'pre {{ .remoteRef.remoteKey }} {{ .remoteRef.testkey }} post'
  389. secretkey: secretkey
  390. pushsecret: true
  391. secret:
  392. name: test-secret
  393. data:
  394. secretkey: value
  395. want:
  396. path: /api/pushsecret?id=testkey&secret=secretkey
  397. body: 'pre testkey value post'
  398. err: ''
  399. ---
  400. case: empty body
  401. args:
  402. url: /api/pushsecret?id={{ .remoteRef.remoteKey }}
  403. key: testkey
  404. body: '{{ "" }}'
  405. pushsecret: true
  406. secret:
  407. name: test-secret
  408. data:
  409. secretkey: value
  410. want:
  411. path: /api/pushsecret?id=testkey
  412. body: ''
  413. err: ''
  414. ---
  415. case: default body pushing without secret key
  416. args:
  417. url: /api/pushsecret?id={{ .remoteRef.remoteKey }}
  418. key: testkey
  419. pushsecret: true
  420. secret:
  421. name: test-secret
  422. data:
  423. secretkey: value
  424. want:
  425. path: /api/pushsecret?id=testkey
  426. body: '{"secretkey":"value"}'
  427. err: ''
  428. ---
  429. case: pushing without secret key
  430. args:
  431. url: /api/pushsecret?id={{ .remoteRef.remoteKey }}
  432. key: testkey
  433. body: 'pre {{ .remoteRef.remoteKey }} {{ index (.remoteRef.testkey | fromJson) "secretkey" }} post'
  434. pushsecret: true
  435. secret:
  436. name: test-secret
  437. data:
  438. secretkey: value
  439. want:
  440. path: /api/pushsecret?id=testkey
  441. body: 'pre testkey value post'
  442. err: ''
  443. ---
  444. case: pushing without secret key with dynamic resolution
  445. args:
  446. url: /api/pushsecret?id={{ .remoteRef.remoteKey }}
  447. key: testkey
  448. body: 'pre {{ .remoteRef.remoteKey }} {{ index (index .remoteRef .remoteRef.remoteKey | fromJson) "secretkey" }} post'
  449. pushsecret: true
  450. secret:
  451. name: test-secret
  452. data:
  453. secretkey: value
  454. want:
  455. path: /api/pushsecret?id=testkey
  456. body: 'pre testkey value post'
  457. err: ''
  458. `
  459. func TestWebhookPushSecret(t *testing.T) {
  460. ydec := yaml.NewDecoder(bytes.NewReader([]byte(testCasesPushSecret)))
  461. for {
  462. var tc testCase
  463. if err := ydec.Decode(&tc); err != nil {
  464. if !errors.Is(err, io.EOF) {
  465. t.Errorf("testcase decode error %v", err)
  466. }
  467. break
  468. }
  469. runTestCase(tc, t)
  470. }
  471. }
  472. func testCaseServer(tc testCase, t *testing.T) *httptest.Server {
  473. // Start a new server for every test case because the server wants to check the expected api path
  474. return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
  475. if tc.Want.Path != "" && req.URL.String() != tc.Want.Path {
  476. t.Errorf("%s: unexpected api path: %s, expected %s", tc.Case, req.URL.String(), tc.Want.Path)
  477. }
  478. if tc.Want.Body != nil {
  479. b, _ := io.ReadAll(req.Body)
  480. if tc.Want.Body != nil && string(b) != *tc.Want.Body {
  481. t.Errorf("%s: unexpected body: %s, expected %s", tc.Case, string(b), *tc.Want.Body)
  482. }
  483. }
  484. if tc.Args.StatusCode != 0 {
  485. rw.WriteHeader(tc.Args.StatusCode)
  486. }
  487. rw.Write([]byte(tc.Args.Response))
  488. }))
  489. }
  490. func parseTimeout(timeout string) (*metav1.Duration, error) {
  491. if timeout == "" {
  492. return nil, nil
  493. }
  494. dur, err := time.ParseDuration(timeout)
  495. if err != nil {
  496. return nil, err
  497. }
  498. return &metav1.Duration{Duration: dur}, nil
  499. }
  500. func runTestCase(tc testCase, t *testing.T) {
  501. ts := testCaseServer(tc, t)
  502. defer ts.Close()
  503. testStore := makeClusterSecretStore(ts.URL, tc.Args)
  504. var err error
  505. timeout, err := parseTimeout(tc.Args.Timeout)
  506. if err != nil {
  507. t.Errorf("%s: error parsing timeout '%s': %s", tc.Case, tc.Args.Timeout, err.Error())
  508. return
  509. }
  510. testStore.Spec.Provider.Webhook.Timeout = timeout
  511. testProv := &Provider{}
  512. client, err := testProv.NewClient(context.Background(), testStore, nil, "testnamespace")
  513. if err != nil {
  514. t.Errorf("%s: error creating client: %s", tc.Case, err.Error())
  515. return
  516. }
  517. if tc.Want.ResultMap != nil && !tc.Args.PushSecret {
  518. testGetSecretMap(tc, t, client)
  519. } else if !tc.Args.PushSecret {
  520. testGetSecret(tc, t, client)
  521. } else {
  522. testPushSecret(tc, t, client)
  523. }
  524. }
  525. func testGetSecretMap(tc testCase, t *testing.T, client esv1beta1.SecretsClient) {
  526. testRef := esv1beta1.ExternalSecretDataRemoteRef{
  527. Key: tc.Args.Key,
  528. Version: tc.Args.Version,
  529. }
  530. secretmap, err := client.GetSecretMap(context.Background(), testRef)
  531. errStr := ""
  532. if err != nil {
  533. errStr = err.Error()
  534. }
  535. if (tc.Want.Err == "") != (errStr == "") || !strings.Contains(errStr, tc.Want.Err) {
  536. t.Errorf("%s: unexpected error: '%s' (expected '%s')", tc.Case, errStr, tc.Want.Err)
  537. }
  538. if err == nil {
  539. for wantkey, wantval := range tc.Want.ResultMap {
  540. gotval, ok := secretmap[wantkey]
  541. if !ok {
  542. t.Errorf("%s: unexpected response: wanted key '%s' not found", tc.Case, wantkey)
  543. } else if string(gotval) != wantval {
  544. t.Errorf("%s: unexpected response: key '%s' = '%s' (expected '%s')", tc.Case, wantkey, wantval, gotval)
  545. }
  546. }
  547. }
  548. }
  549. func testGetSecret(tc testCase, t *testing.T, client esv1beta1.SecretsClient) {
  550. testRef := esv1beta1.ExternalSecretDataRemoteRef{
  551. Key: tc.Args.Key,
  552. Property: tc.Args.Property,
  553. Version: tc.Args.Version,
  554. }
  555. ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  556. defer cancel()
  557. secret, err := client.GetSecret(ctx, testRef)
  558. errStr := ""
  559. if err != nil {
  560. errStr = err.Error()
  561. }
  562. if !strings.Contains(errStr, tc.Want.Err) {
  563. t.Errorf("%s: unexpected error: '%s' (expected '%s')", tc.Case, errStr, tc.Want.Err)
  564. }
  565. if err == nil && string(secret) != tc.Want.Result {
  566. t.Errorf("%s: unexpected response: '%s' (expected '%s')", tc.Case, secret, tc.Want.Result)
  567. }
  568. }
  569. func testPushSecret(tc testCase, t *testing.T, client esv1beta1.SecretsClient) {
  570. testRef := v1alpha1.PushSecretData{
  571. Match: v1alpha1.PushSecretMatch{
  572. SecretKey: tc.Args.SecretKey,
  573. RemoteRef: v1alpha1.PushSecretRemoteRef{
  574. RemoteKey: tc.Args.Key,
  575. },
  576. },
  577. }
  578. data := map[string][]byte{}
  579. for k, v := range tc.Args.Secret.Data {
  580. data[k] = []byte(v)
  581. }
  582. sec := &corev1.Secret{
  583. ObjectMeta: metav1.ObjectMeta{
  584. Name: tc.Args.Secret.Name,
  585. },
  586. Data: data,
  587. }
  588. ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  589. defer cancel()
  590. err := client.PushSecret(ctx, sec, testRef)
  591. errStr := ""
  592. if err != nil {
  593. errStr = err.Error()
  594. }
  595. if tc.Want.Err == "" && errStr != "" {
  596. t.Errorf("%s: unexpected error: '%s' (expected '%s')", tc.Case, errStr, tc.Want.Err)
  597. }
  598. if !strings.Contains(errStr, tc.Want.Err) {
  599. t.Errorf("%s: unexpected error: '%s' (expected '%s')", tc.Case, errStr, tc.Want.Err)
  600. }
  601. }
  602. func makeClusterSecretStore(url string, args args) *esv1beta1.ClusterSecretStore {
  603. store := &esv1beta1.ClusterSecretStore{
  604. TypeMeta: metav1.TypeMeta{
  605. Kind: "ClusterSecretStore",
  606. },
  607. ObjectMeta: metav1.ObjectMeta{
  608. Name: "wehbook-store",
  609. Namespace: "default",
  610. },
  611. Spec: esv1beta1.SecretStoreSpec{
  612. Provider: &esv1beta1.SecretStoreProvider{
  613. Webhook: &esv1beta1.WebhookProvider{
  614. URL: url + args.URL,
  615. Body: args.Body,
  616. Headers: map[string]string{
  617. "Content-Type": "application.json",
  618. "X-SecretKey": "{{ .remoteRef.key }}",
  619. },
  620. Result: esv1beta1.WebhookResult{
  621. JSONPath: args.JSONPath,
  622. },
  623. },
  624. },
  625. },
  626. }
  627. return store
  628. }