Configuring Interceptors
- Overview
- Specifying an
Interceptor
- Webhook
Interceptors
- GitHub
Interceptors
- GitLab
Interceptors
- Bitbucket
Interceptors
- slack
Interceptors
- CEL
Interceptors
- Implementing custom
Interceptors
Overview
An Interceptor
is a “catch-all” event processor for a specific platform that runs before the TriggerBinding.
It allows you to perform payload filtering, verification (using a secret),
transformation, define and test trigger conditions, and implement other useful processing. Once the event data passes through an Interceptor
, it then goes to the Trigger
before you pass
the payload data to the TriggerBinding
. You can also use an Interceptor
to modify the behavior of the associated Trigger
.
Tekton Triggers currently supports two distinct Interceptor
implementations:
- Standalone
Interceptors
, which are instances of theInterceptor
or theClusterInterceptor
Custom Resource Definition (CRD). You specify theseInterceptors
by referencing them, along with the desired parameters, within yourEventListener
. You can use theClusterInterceptor
CRD to implement your own customInterceptors
. - Legacy
Interceptors
, which you define entirely as part of theEventListener
definition. This implementation will eventually be deprecated, so please consider transitioning to standaloneInterceptors
as soon as possible. See TEP-0026 for more context on this change.
Tekton Triggers ships with the following Interceptors
to help you get started:
- Webhook
Interceptors
- GitHub
Interceptors
- GitLab
Interceptors
- Bitbucket
Interceptors
- CEL
Interceptors
Specifying an Interceptor
To specify an Interceptor
within your EventListener
, create an interceptors:
field with the following sub-fields:
name
- (optional) a name that uniquely identifies thisInterceptor
definitionref
- a reference to aClusterInterceptor
orInterceptor
object with the following fields:name
- the name of the referencedClusterInterceptor
kind
- (optional) specifies that whether the referenced Kubernetes object is aClusterInterceptor
object orNamespacedInterceptor
. Default value isClusterInterceptor
apiVersion
- (optional) specifies the target API version, for exampletriggers.tekton.dev/v1alpha1
params
-name
/value
pairs that specify the parameters you want to pass to theClusterInterceptor
params
- (optional)name
/value
pairs that specify the desired parameters for theInterceptor
; thename
field takes a string, while thevalue
field takes a valid JSON object
Below is an example standalone Interceptor
reference within an EventListener
definition:
interceptors:
- name: "validate GitHub payload and filter on eventType"
ref:
name: "github"
params:
- name: "secretRef"
value:
secretName: github-secret
secretKey: secretToken
- name: "eventTypes"
value: ["pull_request"]
- name: "CEL filter: only when PRs are opened"
ref:
name: "cel"
params:
- name: "filter"
value: "body.action in ['opened', 'reopened']"
Webhook Interceptors
Note: Tekton Triggers ships with only a legacy Webhook Interceptor
. If you want to implement it using
the standalone model, see Implementing custom Interceptors
.
A Webhook Interceptor
allows you to process your event payload by an external Kubernetes object containing
custom business logic. The Kubernetes object, exposed via a Kubernetes Service, receives event payload
data from your EventListener
via HTTP, applies its business logic to it, and returns the processed payload
(both headers plus body) via a HTTP 200 response to the EventListener
.
This payload can then continue on to the TriggerBinding
specified in the EventListener
. If processing
is not successful, the Interceptor
recognizes that the returned HTTP response code is not 200 and halts
further processing of the event payload.
You can optionally specify additional data to merge with the event payload before sending out for processing
by adding the data as canonical key/value pairs
in the Interceptor's
header
field.
Your external Kubernetes object must meet the following criteria:
- Fronted by a regular Kubernetes v1 Service running on HTTP port 80,
- Accepts JSON payloads over HTTP,
- Accepts HTTP POST requests with JSON payloads,
- Returns an HTTP 200 OK response when you want the
EventListener
to continue processing the event, - Returns a JSON object in the HTTP response body.
- Returns headers expected by subsequently chained
Interceptors
and the associatedTriggerBinding
.
Note: If your business logic does not modify either the HTTP payload’s header or body, simply return the same HTTP header or body that you received.
Below is an example Webhook Interceptor
definition:
---
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
name: listener-interceptor
spec:
serviceAccountName: tekton-triggers-example-sa
triggers:
- name: foo-trig
interceptors:
- webhook:
header:
- name: Foo-Trig-Header1
value: string-value
- name: Foo-Trig-Header2
value:
- array-val1
- array-val2
objectRef:
kind: Service
name: gh-validate
apiVersion: v1
namespace: default
bindings:
- ref: pipeline-binding
template:
ref: pipeline-template
GitHub Interceptors
A GitHub Interceptor
contains logic that validates and filters GitHub webhooks.
It can validate the webhook’s origin as described in Securing your webhooks
as well as filter incoming events by the criteria you specify. The GitHub Interceptor
always preserves the payload data (both header and body) in its responses.
To use a GitHub Interceptor
as a GitHub webhook validator, do the following:
- Create a secret string value.
- Configure the
GitHub
webhook with that value. - Create a Kubernetes secret containing your secret value.
- Pass the Kubernetes secret as a reference to your GitHub
Interceptor
.
To use a GitHub Interceptor
as a filter for event data, specify the event types
you want the Interceptor
to accept in the eventTypes
field. The Interceptor
accepts data event types listed in Event types and payloads.
Below is an example GitHub Interceptor
reference:
triggers:
- name: github-listener
interceptors:
- ref:
name: "github"
kind: ClusterInterceptor
apiVersion: triggers.tekton.dev
params:
- name: "secretRef"
value:
secretName: github-secret
secretKey: secretToken
- name: "eventTypes"
value: ["pull_request"]
For reference, below is an example legacy GitHub Interceptor
definition:
triggers:
- name: github-listener
interceptors:
- github:
secretRef:
secretName: github-secret
secretKey: secretToken
eventTypes:
For more information, see our example of using this Interceptor
.
Adding Changed Files
The GitHub Interceptor
also has the ability to add a comma delimited list of all files that have changed (added, modified or deleted) for the push
and pull_request
events. The list of changed files are added to the changed_files
property of the event payload in the top-level extensions
field
Below is an example GitHub Interceptor
that enables the addChangedFiles
feature and uses the CEL Interceptor
to filter incoming events by the files changed
triggers:
- name: github-listener
interceptors:
- ref:
name: "github"
kind: ClusterInterceptor
apiVersion: triggers.tekton.dev
params:
- name: "secretRef"
value:
secretName: github-secret
secretKey: secretToken
- name: "eventTypes"
value: ["pull_request", "push"]
- name: "addChangedFiles"
value:
enabled: true
- ref:
name: cel
params:
- name: filter
# execute only when a file within the controllers directory has changed
value: extensions.changed_files.matches('controllers/')
Adding Changed Files - Private Repository
The ability to add changed files can also work with private repositories by supplying a GitHub personal access token in the personalAccessToken
field. In the example below, the personalAccessToken
uses the github-pat
secret to get the GitHub personal access token used to make the API calls to get the list of changed files.
triggers:
- name: github-listener
interceptors:
- ref:
name: "github"
kind: ClusterInterceptor
apiVersion: triggers.tekton.dev
params:
- name: "secretRef"
value:
secretName: github-secret
secretKey: secretToken
- name: "eventTypes"
value: ["pull_request", "push"]
- name: "addChangedFiles"
value:
enabled: true
personalAccessToken:
secretName: github-pat
secretKey: token
- ref:
name: cel
params:
- name: filter
# execute only when a file within the controllers directory has changed
value: extensions.changed_files.matches('controllers/')
For more information around adding changed files, see the following examples
Owners validation for pull requests
The GitHub Interceptor
supports the ability to halt processing on a pull request if the user is not listed in the owners file or is not a repository/organization member/owner. This feature can be used to prevent unnecessary execution of a PipelineRun or TaskRun. The GitHub Interceptor
also supports the ability to trigger a PipelineRun/TaskRun through a comment that contains /ok-to-test
on a pull request by an owner.
This feature will also work against private GitHub repositories by supplying a GitHub personal access token in the personalAccessToken
field.
NOTE: Owners validation requires (at a minimum) the
pull_request
andissue_comment
GitHub event types.
To use the GitHub Interceptor
as a GitHub owners validator, do the following:
- Create a secret string value.
- Configure the
GitHub
webhook with that value. - Create a Kubernetes secret containing your secret value called
SecretRef
. - Pass the Kubernetes secret as a reference to your GitHub
Interceptor
. - Create an owners file and add the list of approvers into the approvers section.
Below is an example GitHub Interceptor
using owners validation:
triggers:
- name: github-listener
interceptors:
- ref:
name: "github"
kind: ClusterInterceptor
apiVersion: triggers.tekton.dev
params:
- name: "secretRef"
value:
secretName: github-secret
secretKey: secretToken
- name: "eventTypes"
# Owners validation requires (at a minimum) the `pull_request` and `issue_comment` GitHub event types
value: ["pull_request", "issue_comment"]
- name: "githubOwners"
value:
enabled: true
# This value is needed for private repos or when checkType is set to orgMembers or repoMembers or all
# personalAccessToken:
# secretName: github-token
# secretKey: secretToken
checkType: none
For more information around owners file validation, see the following example
GitLab Interceptors
A GitLab Interceptor
contains logic that validates and filters GitLab webhooks.
It can validate the webhook’s origin as described in Webhooks
as well as filter incoming events by the criteria you specify. The GitLab Interceptor
always preserves the payload data (both header and body) in its responses.
To use a GitLab Interceptor
as a GitLab webhook validator, do the following:
- Create a secret string value.
- Configure the GitLab webhook with that value.
- Create a Kubernetes secret containing your secret value.
- Pass the Kubernetes secret as a reference to your GitLab
Interceptor
.
To use a GitLab Interceptor
as a filter for event data, specify the event types
you want the Interceptor
to accept in the eventTypes
field. The Interceptor
accepts data event types listed in Events.
Below is an example GitLab Interceptor
reference:
interceptors:
- ref:
name: "gitlab"
params:
- name: "secretRef"
value:
secretName: foo
secretKey: bar
- name: "eventTypes"
value: ["Push Hook"]
For reference, below is an example legacy GitLab Interceptor
definition:
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
name: gitlab-listener-interceptor
spec:
serviceAccountName: tekton-triggers-example-sa
triggers:
- name: foo-trig
interceptors:
- gitlab:
secretRef:
secretName: foo
secretKey: bar
eventTypes:
- Push Hook
bindings:
- ref: pipeline-binding
template:
ref: pipeline-template
Bitbucket Interceptors
Bitbucket Interceptors
has support for both Bitbucket server (which does secret validation and event filtering) and Bitbucket cloud (which does event filtering).
Bitbucket Server
A Bitbucket server contains logic that validates and filters Bitbucket server webhooks.
It can validate the webhook’s origin as described in Webhooks. The Bitbucket Interceptor
always preserves the payload
data (both header and body) in its responses.
To use a Bitbucket Interceptor
as a Bitbucket server webhook validator, do the following:
- Create a secret string value.
- Configure the Bitbucket server webhook with that value.
- Create a Kubernetes secret containing your secret value.
- Pass the Kubernetes secret as a reference to your Bitbucket
Interceptor
.
To use a Bitbucket Interceptor
as a filter for event data, specify the event types
you want the Interceptor
to accept in the eventTypes
field. The Interceptor
accepts data event types listed in Event payload.
Below is an example Bitbucket Interceptor
reference for server:
interceptors:
- ref:
name: "bitbucket"
params:
- name: secretRef
value:
secretName: bitbucket-server-secret
secretKey: secretToken
- name: eventTypes
value:
- repo:refs_changed
For reference, below is an example legacy Bitbucket Interceptor
definition:
---
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
name: bitbucket-server-listener
spec:
serviceAccountName: tekton-triggers-example-sa
triggers:
- name: bitbucket-server-triggers
interceptors:
- ref:
name: "bitbucket"
params:
- name: secretRef
value:
secretName: bitbucket-server-secret
secretKey: secretToken
- name: eventTypes
value:
- repo:refs_changed
bindings:
- ref: bitbucket-server-binding
template:
ref: bitbucket-server-template
Bitbucket Cloud
At the moment, Bitbucket cloud does not support validating webhook payloads using shared secrets. See the Secure Webhooks section of Bitbucket cloud docs for more information on securing your Bitbucket webhooks.
To use a Bitbucket Interceptor
as a filter for event data, specify the event types
you want the Interceptor
to accept in the eventTypes
field. The Interceptor
accepts data event types listed in Event payload.
Below is an example Bitbucket Interceptor
reference for cloud:
interceptors:
- ref:
name: "bitbucket"
params:
- name: eventTypes
value:
- repo:push
For reference, below is an example legacy Bitbucket Interceptor
definition:
---
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: bitbucket-cloud-listener
spec:
serviceAccountName: tekton-triggers-example-sa
triggers:
- name: bitbucket-cloud-triggers
interceptors:
- ref:
name: "bitbucket"
params:
- name: eventTypes
value:
- repo:push
bindings:
- ref: bitbucket-cloud-binding
template:
ref: bitbucket-cloud-template
Slack Interceptors
A Slack Interceptor
allows you to extract fields from a slack slash command payload which are sent in the http form-data section.
the Interceptor
requests fields extracts the requested fields and appends them to the extensions
.
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: slack-listener
annotations:
tekton.dev/payload-validation: "false"
spec:
triggers:
- name: slack-trigger
interceptors:
- ref:
name: "slack"
kind: ClusterInterceptor
params:
- name: requestedFields
value:
- text
Note: payload-validation must be disabled by add adding the following annotation
annotations:
tekton.dev/payload-validation: "false"
CEL Interceptors
A CEL Interceptor
allows you to filter and modify the payloads of incoming events using
the CEL expression language.
CEL Interceptors
support overlays
, which are CEL expressions that Tekton Triggers adds
to the event payload in the top-level extensions
field. overlays
are accessible from
TriggerBindings
.
In the example overlays
definition below, the Interceptor
adds two new fields to the
event payload that the corresponding TriggerBinding
will receive in addition to the standard
header
and body fields
: extensions.truncated_sha
and extensions.branch_name
:
triggers:
- name: cel-trig
interceptors:
- ref:
name: cel
params:
- name: "overlays"
value:
- key: truncated_sha
expression: "body.pull_request.head.sha.truncate(7)"
- key: branch_name
expression: "body.ref.split('/')[2]"
Below is the same example as a legacy Interceptor
:
triggers:
- name: cel-trig
interceptors:
- cel:
overlays:
- key: truncated_sha
expression: "body.pull_request.head.sha.truncate(7)"
- key: branch_name
expression: "body.ref.split('/')[2]"
You can use the key
element within the overlays
definition to create new or replace existing
elements within the extensions
field. This does not modify the body of the event payload, but instead
adds the extra fields to the top-level extensions
field.
For example, the following expression:
- key: short_sha
expression: "truncate(body.pull_request.head.sha, 7)"
can access the short_sha
field and its value that have been created in extensions
field:
{
"body": {
"ref": "refs/heads/master",
"pull_request": {
"head": {
"sha": "6113728f27ae82c7b1a177c8d03f9e96e0adf246"
}
}
},
"extensions": {
"short_sha": "6113728"
}
}
Note: You can also replace existing fields by specifying a key that matches the path to an existing field/value pair.
You can access the extra fields added by a CEL Interceptor
from your TriggerBinding
as follows:
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
name: pipeline-binding-with-cel-extensions
spec:
params:
- name: gitrevision
value: $(extensions.short_sha)
- name: branch
value: $(extensions.branch_name)
In the example CEL Interceptor
definition below, the cel-trig-with-matches
Trigger
filters events that don’t have an 'X-GitHub-Event'
header matching 'pull_request'
and
adds an extra key to the JSON body of the payload with a truncated string derived from the hook
body:
triggers:
- name: cel-trig-with-matches
interceptors:
- ref:
name: "cel"
params:
- name: "filter"
value: "header.match('X-GitHub-Event', 'pull_request')"
- name: "overlays"
value:
- key: truncated_sha
expression: "body.pull_request.head.sha.truncate(7)"
bindings:
- name: sha
value: $(extensions.truncated_sha)
Below is the same example as a legacy Interceptor
:
triggers:
- name: cel-trig-with-matches
interceptors:
- cel:
filter: "header.match('X-GitHub-Event', 'pull_request')"
overlays:
- key: truncated_sha
expression: "body.pull_request.head.sha.truncate(7)"
bindings:
- name: sha
value: $(extensions.truncated_sha)
In the example CEL Interceptor
definition below, the filter
expression must
return a true
value for this Trigger
to execute and apply the specified overlays
:
You also have the option to omit the filter
expression entirely, in which case the Interceptor
applies the specified overlays
to the payload’s body:
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
name: cel-eventlistener-no-filter
spec:
serviceAccountName: tekton-triggers-example-sa
triggers:
- name: cel-trig
interceptors:
- ref:
name: "cel"
params:
- name: "overlays"
value:
- key: extensions.truncated_sha
expression: "body.pull_request.head.sha.truncate(7)"
bindings:
- ref: pipeline-binding
template:
ref: pipeline-template
Chaining Interceptors
You can chain Interceptors
with the following constraints:
-
ClusterInterceptors
do not modify the body of the event payload; instead, they add extra fields to the top-levelextensions
field. -
Webhook
Interceptors
can modify the body of the event payload, but cannot access the top-levelextensions
field.
Chaining ClusterInterceptors
Each ClusterInterceptor can return values in the InterceptorResponse within the extensions
field. These values are then added to the extensions
field of the InterceptorRequest that is sent to the next interceptor in the chain.
If two interceptors return an extensions field with the same name, the latter one will overwrite the one from the previous one i.e. if interceptors A and B both return foo
in the Extensions field of the InterceptorResponse, the values written by B will overwrite the ones written by A. To prevent this, it is recommended that each cluster interceptor write to its own top level field i.e A returns A.foo
and B return B.foo
in the InterceptorResponse.
Chaining Webhook Interceptors
Note: We are working on changing the behavior of Webhook Interceptors
to match that of CEL Interceptors
so that both Interceptor
types can share data via the top-level extensions
field.
Since Webhook Interceptors
cannot access the extensions
field, the EventListener
adds the extensions
field to the body of the event payload before passing it to any Webhook Interceptor
.
In the example Interceptor
chain shown below, the first CEL Interceptor
adds the truncated_sha
field to the extensions
field and the EventListener
adds it to the body of the payload so that
the Webhook Interceptor
can access that data:
interceptors:
- cel:
overlays:
- key: "truncated_sha"
expression: "body.sha.truncate(5)"
- webhook:
objectRef:
kind: Service
name: some-interceptor
apiVersion: v1
- cel:
filter: "body.extensions.truncated_sha == \"abcde\"" # Can also be extensions.truncated_sha == \"abcde\"
As a result, the body of the payload sent to the Webhook Interceptor
is as follows:
{
"sha": "abcdefghi", // Original field
"extensions": {
"truncated_sha": "abcde"
}
}
As long as the Webhook Interceptor
does not modify the body of the payload, the last CEL interceptor in the chain and the target TriggerBinding
can access the truncated_sha
field both in the body of the payload as well as via the extra fields added to the top-level extension
field, namely $(body.extensions.truncated_sha)
as well as $(extensions.truncated_sha)
.
Implementing custom Interceptors
Tekton Triggers ships with the ClusterInterceptor
and Interceptor
Custom Resource Definition (CRD), which you can use to implement custom Interceptors
. See ClusterInterceptors
and NamespacedInterceptors
for more information.
Feedback
Was this page helpful?