diff --git a/core/src/main/java/io/kestra/core/models/triggers/types/Webhook.java b/core/src/main/java/io/kestra/core/models/triggers/types/Webhook.java index 026d18d7ec6..a0e57ede211 100644 --- a/core/src/main/java/io/kestra/core/models/triggers/types/Webhook.java +++ b/core/src/main/java/io/kestra/core/models/triggers/types/Webhook.java @@ -31,7 +31,7 @@ @NoArgsConstructor @Schema( title = "Trigger a flow from a webhook", - description = "Webbook trigger allow you to trigger a flow from a webhook url. " + + description = "Webhook trigger allow you to trigger a flow from a webhook url. " + "The trigger will generate a `key` that must be used on url : `/api/v1/executions/webhook/{namespace}/[flowId]/{key}`. " + "Kestra accept `GET`, `POST` & `PUT` request on this url. " + "The whole body & headers will be available as variable:\n " + @@ -41,7 +41,7 @@ @Plugin( examples = { @Example( - title = "Add a trigger to the current flow", + title = "Add a webhook trigger to the current flow with a generated key, the webhook will be available at the URI `/api/v1/executions/webhook/{namespace}/{flowId}/{generated-key}`.", code = { "triggers:", " - id: webhook", @@ -50,8 +50,7 @@ full = true ), @Example( - title = "After the trigger is created, a key will be created that will be use in the webhook url, now, you can launch " + - "the flow on the url `/api/v1/executions/webhook/{namespace}/[flowId]/4wjtkzwVGBM9yKnjm3yv8r`", + title = "Add a webhook trigger to the current flow with the key `4wjtkzwVGBM9yKnjm3yv8r`, the webhook will be available at the URI `/api/v1/executions/webhook/{namespace}/{flowId}/4wjtkzwVGBM9yKnjm3yv8r`.", code = { "triggers:", " - id: webhook", @@ -64,17 +63,17 @@ ) public class Webhook extends AbstractTrigger implements TriggerOutput { @Builder.Default - @Size(min = 16, max = 256) + @Size(max = 256) @Schema( title = "The unique key that will be part of the url", - description = "If you don't provide a key, a random one will be generated. Is used as key for generating the url of the webhook.\n" + + description = "If you don't provide a key, a random one will be generated. The key is used for generating the url of the webhook.\n" + "\n" + "::alert{type=\"warning\"}\n" + "Take care when using manual key, the key is the only security to protect your webhook and must be considered as a secret !\n" + "::\n", defaultValue = "" ) - @PluginProperty + @PluginProperty(dynamic = true) private final String key = IdUtils.create(); public Optional evaluate(HttpRequest request, io.kestra.core.models.flows.Flow flow) { diff --git a/core/src/test/resources/flows/valids/webhook-dynamic-key.yaml b/core/src/test/resources/flows/valids/webhook-dynamic-key.yaml new file mode 100644 index 00000000000..5274285ed1c --- /dev/null +++ b/core/src/test/resources/flows/valids/webhook-dynamic-key.yaml @@ -0,0 +1,16 @@ +id: webhook-dynamic-key +namespace: io.kestra.tests +labels: + flow-label-1: flow-label-1 + flow-label-2: flow-label-2 + +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: "{{ flow.id }}" 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 50944e13964..c86fcb2eaec 100644 --- a/webserver/src/main/java/io/kestra/webserver/controllers/ExecutionController.java +++ b/webserver/src/main/java/io/kestra/webserver/controllers/ExecutionController.java @@ -417,7 +417,16 @@ private Execution webhook( .stream() .filter(o -> o instanceof Webhook) .map(o -> (Webhook) o) - .filter(w -> w.getKey().equals(key)) + .filter(w -> { + RunContext runContext = runContextFactory.of(flow, w); + try { + String webhookKey = runContext.render(w.getKey()); + return webhookKey.equals(key); + } catch (IllegalVariableEvaluationException e) { + // be conservative, don't crash but filter the webhook + return false; + } + }) .findFirst(); if (webhook.isEmpty()) { 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 7a5b5ff8687..bc0fa649144 100644 --- a/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java +++ b/webserver/src/test/java/io/kestra/webserver/controllers/ExecutionControllerTest.java @@ -512,6 +512,20 @@ void webhook() { } + @Test + void webhookDynamicKey() { + Execution execution = client.toBlocking().retrieve( + HttpRequest + .GET( + "/api/v1/executions/webhook/" + TESTS_FLOW_NS + "/webhook-dynamic-key/webhook-dynamic-key" + ), + Execution.class + ); + + assertThat(execution, notNullValue()); + assertThat(execution.getId(), notNullValue()); + } + @Test void resumePaused() throws TimeoutException, InterruptedException { // Run execution until it is paused