Browse Source

:sparkles: Support template for webhook jsonpath (#1939)

* Support template for webhook jsonpath

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>
Thibault Cohen 3 years ago
parent
commit
6862c9c637
2 changed files with 44 additions and 5 deletions
  1. 11 3
      pkg/provider/webhook/webhook.go
  2. 33 2
      pkg/provider/webhook/webhook_test.go

+ 11 - 3
pkg/provider/webhook/webhook.go

@@ -141,14 +141,22 @@ func (w *WebHook) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDat
 		return nil, err
 		return nil, err
 	}
 	}
 	// Only parse as json if we have a jsonpath set
 	// Only parse as json if we have a jsonpath set
-	if provider.Result.JSONPath != "" {
+	data, err := w.getTemplateData(ctx, ref, provider.Secrets)
+	if err != nil {
+		return nil, err
+	}
+	resultJSONPath, err := executeTemplateString(provider.Result.JSONPath, data)
+	if err != nil {
+		return nil, err
+	}
+	if resultJSONPath != "" {
 		jsondata := interface{}(nil)
 		jsondata := interface{}(nil)
 		if err := yaml.Unmarshal(result, &jsondata); err != nil {
 		if err := yaml.Unmarshal(result, &jsondata); err != nil {
 			return nil, fmt.Errorf("failed to parse response json: %w", err)
 			return nil, fmt.Errorf("failed to parse response json: %w", err)
 		}
 		}
-		jsondata, err = jsonpath.Get(provider.Result.JSONPath, jsondata)
+		jsondata, err = jsonpath.Get(resultJSONPath, jsondata)
 		if err != nil {
 		if err != nil {
-			return nil, fmt.Errorf("failed to get response path %s: %w", provider.Result.JSONPath, err)
+			return nil, fmt.Errorf("failed to get response path %s: %w", resultJSONPath, err)
 		}
 		}
 		jsonvalue, ok := jsondata.(string)
 		jsonvalue, ok := jsondata.(string)
 		if !ok {
 		if !ok {

+ 33 - 2
pkg/provider/webhook/webhook_test.go

@@ -41,6 +41,7 @@ type args struct {
 	Body       string `json:"body,omitempty"`
 	Body       string `json:"body,omitempty"`
 	Timeout    string `json:"timeout,omitempty"`
 	Timeout    string `json:"timeout,omitempty"`
 	Key        string `json:"key,omitempty"`
 	Key        string `json:"key,omitempty"`
+	Property   string `json:"property,omitempty"`
 	Version    string `json:"version,omitempty"`
 	Version    string `json:"version,omitempty"`
 	JSONPath   string `json:"jsonpath,omitempty"`
 	JSONPath   string `json:"jsonpath,omitempty"`
 	Response   string `json:"response,omitempty"`
 	Response   string `json:"response,omitempty"`
@@ -137,6 +138,7 @@ args:
   response: secret-value
   response: secret-value
 want:
 want:
   path: /api/getsecret?id=testkey&version=1
   path: /api/getsecret?id=testkey&version=1
+  err: ''
   result: secret-value
   result: secret-value
 ---
 ---
 case: good json
 case: good json
@@ -148,6 +150,7 @@ args:
   response: '{"result":{"thesecret":"secret-value"}}'
   response: '{"result":{"thesecret":"secret-value"}}'
 want:
 want:
   path: /api/getsecret?id=testkey&version=1
   path: /api/getsecret?id=testkey&version=1
+  err: ''
   result: secret-value
   result: secret-value
 ---
 ---
 case: good json map
 case: good json map
@@ -159,6 +162,7 @@ args:
   response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value"}}'
   response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value"}}'
 want:
 want:
   path: /api/getsecret?id=testkey&version=1
   path: /api/getsecret?id=testkey&version=1
+  err: ''
   resultmap:
   resultmap:
     thesecret: secret-value
     thesecret: secret-value
     alsosecret: another-value
     alsosecret: another-value
@@ -171,6 +175,7 @@ args:
   response: '{"thesecret":"secret-value","alsosecret":"another-value"}'
   response: '{"thesecret":"secret-value","alsosecret":"another-value"}'
 want:
 want:
   path: /api/getsecret?id=testkey&version=1
   path: /api/getsecret?id=testkey&version=1
+  err: ''
   resultmap:
   resultmap:
     thesecret: secret-value
     thesecret: secret-value
     alsosecret: another-value
     alsosecret: another-value
@@ -201,6 +206,31 @@ want:
   resultmap:
   resultmap:
     thesecret: secret-value
     thesecret: secret-value
     alsosecret: another-value
     alsosecret: another-value
+---
+case: good json with good templated jsonpath
+args:
+  url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
+  key: testkey
+  property: thesecret
+  version: 1
+  jsonpath: $.result.{{ .remoteRef.property }}
+  response: '{"result":{"thesecret":"secret-value"}}'
+want:
+  path: /api/getsecret?id=testkey&version=1
+  err: ''
+  result: secret-value
+---
+case: good json with bad temlated jsonpath
+args:
+  url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
+  key: testkey
+  property: thesecret
+  version: 1
+  jsonpath: $.result.{{ .remoteRef.property }
+  response: '{"result":{"thesecret":"secret-value"}}'
+want:
+  path: /api/getsecret?id=testkey&version=1
+  err: 'template: webhooktemplate:1: unexpected "}" in operand'
 `
 `
 
 
 func TestWebhookGetSecret(t *testing.T) {
 func TestWebhookGetSecret(t *testing.T) {
@@ -294,8 +324,9 @@ func testGetSecretMap(tc testCase, t *testing.T, client esv1beta1.SecretsClient)
 
 
 func testGetSecret(tc testCase, t *testing.T, client esv1beta1.SecretsClient) {
 func testGetSecret(tc testCase, t *testing.T, client esv1beta1.SecretsClient) {
 	testRef := esv1beta1.ExternalSecretDataRemoteRef{
 	testRef := esv1beta1.ExternalSecretDataRemoteRef{
-		Key:     tc.Args.Key,
-		Version: tc.Args.Version,
+		Key:      tc.Args.Key,
+		Property: tc.Args.Property,
+		Version:  tc.Args.Version,
 	}
 	}
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	defer cancel()
 	defer cancel()