Repository: kestra-io/kestra (java)

Issue:
Dynamically generated webhook key doesn't work as expected
In the last 0.11.0 release, we added the feature to fetch the webhook key from secrets. However, it didn't work for me. See in the video that when using the webhook key from the Secret, no Execution was triggered. After hardcoding the key, the event from EventBridge got passed to the webhook without any issues:

https://share.descript.com/view/kytVX5bnfp5 

### Environment Information

- Kestra Version: 0.12.0


Pull request description:
fix(webserver): trim the rendered webhook key
As the secret function adds a new line at the end of the rendered value.

close #2138


Patch:
diff --git a/build.gradle b/build.gradle
index a42b73e3f..2fae5071c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -188,6 +188,7 @@ subprojects {
         systemProperty 'user.country', 'US'
 
         environment 'SECRET_MY_SECRET', "{\"secretKey\":\"secretValue\"}".bytes.encodeBase64().toString()
+        environment 'SECRET_WEBHOOK_KEY', "secretKey".bytes.encodeBase64().toString()
         environment 'SECRET_NON_B64_SECRET', "some secret value"
     }
 
diff --git a/webserver/src/main/java/io/kestra/webserver/controllers/ExecutionController.java b/webserver/src/main/java/io/kestra/webserver/controllers/ExecutionController.java
index c592e753b..48e276ab4 100644
--- a/webserver/src/main/java/io/kestra/webserver/controllers/ExecutionController.java
+++ b/webserver/src/main/java/io/kestra/webserver/controllers/ExecutionController.java
@@ -391,7 +391,7 @@ public class ExecutionController {
             .filter(w -> {
                 RunContext runContext = runContextFactory.of(flow, w);
                 try {
-                    String webhookKey = runContext.render(w.getKey());
+                    String webhookKey = runContext.render(w.getKey()).trim();
                     return webhookKey.equals(key);
                 } catch (IllegalVariableEvaluationException e) {
                     // be conservative, don't crash but filter the webhook


Test patch:
diff --git a/core/src/test/resources/flows/valids/webhook-secret-key.yaml b/core/src/test/resources/flows/valids/webhook-secret-key.yaml
new file mode 100644
index 000000000..30329b26b
--- /dev/null
+++ b/core/src/test/resources/flows/valids/webhook-secret-key.yaml
@@ -0,0 +1,13 @@
+id: webhook-secret-key
+namespace: io.kestra.tests
+
+tasks:
+  - id: out
+    type: io.kestra.core.tasks.debugs.Return
+    format: "{{trigger | json }}"
+
+
+triggers:
+  - id: webhook
+    type: io.kestra.core.models.triggers.types.Webhook
+    key: "{{ secret('WEBHOOK_KEY') }}"
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java
index 59c23bc4a..0e99e747b 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java
@@ -33,6 +33,7 @@ import io.micronaut.rxjava2.http.client.sse.RxSseClient;
 import jakarta.inject.Inject;
 import jakarta.inject.Named;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
 
 import java.io.File;
 import java.time.Duration;
@@ -528,6 +529,21 @@ class ExecutionControllerTest extends JdbcH2ControllerTest {
         assertThat(execution.getId(), notNullValue());
     }
 
+    @Test
+    @EnabledIfEnvironmentVariable(named = "SECRET_WEBHOOK_KEY", matches = ".*")
+    void webhookDynamicKeyFromASecret() {
+        Execution execution = client.toBlocking().retrieve(
+            HttpRequest
+                .GET(
+                    "/api/v1/executions/webhook/" + TESTS_FLOW_NS + "/webhook-secret-key/secretKey"
+                ),
+            Execution.class
+        );
+
+        assertThat(execution, notNullValue());
+        assertThat(execution.getId(), notNullValue());
+    }
+
     @Test
     void resumePaused() throws TimeoutException, InterruptedException {
         // Run execution until it is paused