Skip to content

Commit

Permalink
feat(core): make the webhook key dynamic (#1857)
Browse files Browse the repository at this point in the history
  • Loading branch information
loicmathieu authored Aug 4, 2023
1 parent c5ea0ba commit f222d87
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 " +
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -64,17 +63,17 @@
)
public class Webhook extends AbstractTrigger implements TriggerOutput<Webhook.Output> {
@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 = "<generated-hash>"
)
@PluginProperty
@PluginProperty(dynamic = true)
private final String key = IdUtils.create();

public Optional<Execution> evaluate(HttpRequest<String> request, io.kestra.core.models.flows.Flow flow) {
Expand Down
16 changes: 16 additions & 0 deletions core/src/test/resources/flows/valids/webhook-dynamic-key.yaml
Original file line number Diff line number Diff line change
@@ -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 }}"
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit f222d87

Please sign in to comment.