Repository: external-secrets/external-secrets (go)

Issue:
Using "dataFrom"  webhook "ClusterSecretStore"'s templated "result.jsonPath" does not work
**Describe the bug**

I have a `webhook` `ClusterSecretStore` in which I declared a templated `result.jsonPath` expression, that looks like this:

```yaml
jsonPath: "$.data.attributes.{{ or .remoteRef.property \"password\" }}"
```

Using this construct, I can use different properties of the returned result in my `ExternalSecret` (and when no `property` is provided, `password` is used by default). This works fine when I source a value in my `ExternalSecret` using `data`. However, when I use `dataFrom`, I get this strange error:

```
Type     Reason        Age                     From              Message
----     ------        ----                    ----              -------
Warning  UpdateFailed  3m58s (x17 over 9m35s)  external-secrets  failed to get response path $.data.attributes.{{ or .remoteRef.property "password" }}: parsing error: $.data.attributes.{{ or .remoteRef.property "password" }}  :1:19 - 1:20 unexpected "{" while scanning JSON select expected Ident, "." or "*"
```

In the API reference, I see that `spec.data[*].remoteRef` and `spec.dataFrom[*].extract` reference the same data types (not sure if that's the correct term?). And since I am using `remoteRef` in the `jsonPath` template, that seems off because there is no `remoteRef` reference for `dataFrom` sources.

I *do* notice that at the HTTP endpoint, a request is made with the correct `name` GET parameter, so the retrieval part works (so at least `remoteRef.key` seems to exist).


**To Reproduce**

My `webhook` `ClusterSecretStore`, where I use the `result.jsonPath`:

```yaml
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: webhook-test
spec:
  provider:
    webhook:
      url: https://example.com/secret?name={{ .remoteRef.key }}
      timeout: 1s
      result:
        jsonPath: "$.data.attributes.{{ or .remoteRef.property \"password\" }}"
```

And the `ExternalSecret` with the failing `dataFrom` extraction:

```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: datafrom-test
spec:
  refreshInterval: 24h

  secretStoreRef:
    kind: ClusterSecretStore
    name: webhook-test

  dataFrom:
  - extract:
      key: users-test
      conversionStrategy: Default
      decodingStrategy: None
      metadataPolicy: None

  target:
    template:
      engineVersion: v2
      data:
        users: |
          {{- range $username, $password := . }}
          {{ htpasswd $username $password }}
          {{- end }}
```

The contents of `users-test` at `example.com` is simply:

```json
{
  "user-1": "password-1",
  "user-2": "password-2"
}
```

**Expected behavior**

I expect that a `datafrom-test` secret would contain some `htpasswd` lines.

**Additional context**

As mentioned, regular `data` sourced values work as expected, so there is a way we can work around it:

```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: data-test
spec:
  refreshInterval: 24h

  secretStoreRef:
    kind: ClusterSecretStore
    name: webhook-test

  data:
    - secretKey: credentials
      remoteRef:
        key: users-test
        conversionStrategy: Default
        decodingStrategy: None
        metadataPolicy: None

  target:
    template:
      engineVersion: v2
      data:
        users: |
          {{- range $username, $password := mustFromJson .credentials }}
          {{ htpasswd $username $password }}
          {{- end }}

```

Pull request:
fix: allows result.jsonpath to be templated on datafrom calls
## Problem Statement

Webhook provider does not allow `result.JsonPath` to be templated when calls come from `dataFrom` - even though it is stated in the docs it should be possible.

This PR fixes this by, well, templating the jsonPath :)

## Related Issue

Fixes #4801

## Checklist

- [x] I have read the [contribution guidelines](https://external-secrets.io/latest/contributing/process/#submitting-a-pull-request)
- [x] All commits are signed with `git commit --signoff`
- [x] My changes have reasonable test coverage
- [x] All tests pass with `make test`
- [x] I ensured my PR is ready for review with `make reviewable`


Patch:
diff --git a/pkg/provider/webhook/webhook.go b/pkg/provider/webhook/webhook.go
index 6234828bb..4e72587fc 100644
--- a/pkg/provider/webhook/webhook.go
+++ b/pkg/provider/webhook/webhook.go
@@ -217,6 +217,15 @@ func (w *WebHook) GetSecretMap(ctx context.Context, ref esv1.ExternalSecretDataR
 	if err != nil {
 		return nil, fmt.Errorf(errFailedToGetStore, err)
 	}
+	data, err := w.wh.GetTemplateData(ctx, &ref, provider.Secrets, false)
+	if err != nil {
+		return nil, fmt.Errorf("cannot get template data: %w", err)
+	}
+	resultJSONPath, err := webhook.ExecuteTemplateString(provider.Result.JSONPath, data)
+	if err != nil {
+		return nil, fmt.Errorf("cannot get templated json path: %w", err)
+	}
+	provider.Result.JSONPath = resultJSONPath
 	return w.wh.GetSecretMap(ctx, provider, &ref)
 }
 


Test patch:
diff --git a/pkg/provider/webhook/webhook_test.go b/pkg/provider/webhook/webhook_test.go
index 0982bfbb3..ad085ee97 100644
--- a/pkg/provider/webhook/webhook_test.go
+++ b/pkg/provider/webhook/webhook_test.go
@@ -191,6 +191,34 @@ want:
     thesecret: secret-value
     alsosecret: another-value
 ---
+case: templated jsonpath good json map
+args:
+  url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
+  key: testkey
+  version: 1
+  jsonpath: $.{{printf "result" }}
+  response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value"}}'
+want:
+  path: /api/getsecret?id=testkey&version=1
+  err: ''
+  resultmap:
+    thesecret: secret-value
+    alsosecret: another-value
+---
+case: templated jsonpath invalid template
+args:
+  url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}
+  key: testkey
+  version: 1
+  jsonpath: $.{{printf 'result' }}
+  response: '{"result":{"thesecret":"secret-value","alsosecret":"another-value"}}'
+want:
+  path: /api/getsecret?id=testkey&version=1
+  err: "cannot get templated json path"
+  resultmap:
+    thesecret: secret-value
+    alsosecret: another-value
+---
 case: good json map string
 args:
   url: /api/getsecret?id={{ .remoteRef.key }}&version={{ .remoteRef.version }}