Skip to content

Commit

Permalink
Add an interceptor to that can filter based on CEL expressions.
Browse files Browse the repository at this point in the history
This adds a cel interceptor, that uses a a CEL expression to filter request bodies.

This addresses issue tektoncd#49.
  • Loading branch information
bigkevmcd committed Jan 6, 2020
1 parent 2ea5540 commit 08a2057
Show file tree
Hide file tree
Showing 165 changed files with 45,654 additions and 6 deletions.
49 changes: 46 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ required = [
"knative.dev/caching/pkg/apis/caching",
"github.com/tektoncd/plumbing/scripts",
"github.com/knative/test-infra/tools/dep-collector",
"github.com/google/go-github/github"
"github.com/google/go-github/github",
"github.com/google/cel-go/cel",
"github.com/google/cel-go/checker/decls",
"github.com/google/cel-go/common/types",
"github.com/google/cel-go/common/types/ref",
"github.com/google/cel-go/interpreter/functions",
"google.golang.org/genproto/googleapis/api/expr/v1alpha1",
]

[[constraint]]
Expand Down
29 changes: 29 additions & 0 deletions docs/eventlisteners.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,32 @@ spec:
template:
name: pipeline-template
```

### CEL Interceptors

CEL interceptors parse expressions to filter requests based on JSON bodies and request headers, using the
[CEL](https://github.com/google/cel-go) expression language.

Supported features include case-insensitive matching on request headers.

<!-- FILE: examples/eventlisteners/cel-eventlistener-interceptor.yaml -->
```YAML
apiVersion: tekton.dev/v1alpha1
kind: EventListener
metadata:
name: cel-listener-interceptor
spec:
serviceAccountName: tekton-triggers-example-sa
triggers:
- name: cel-trig
interceptor:
cel:
filter: "headers.match('X-GitHub-Event', 'push')"
bindings:
- name: pipeline-binding
template:
name: pipeline-template
```

The `expression` must return a `true` value, otherwise the request will be filtered
out.
15 changes: 15 additions & 0 deletions examples/eventlisteners/cel-eventlistener-interceptor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: tekton.dev/v1alpha1
kind: EventListener
metadata:
name: cel-listener-interceptor
spec:
serviceAccountName: tekton-triggers-example-sa
triggers:
- name: cel-trig
interceptor:
cel:
filter: "headers.match('X-GitHub-Event', 'push')"
bindings:
- name: pipeline-binding
template:
name: pipeline-template
6 changes: 6 additions & 0 deletions pkg/apis/triggers/v1alpha1/event_listener_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type EventInterceptor struct {
Webhook *WebhookInterceptor `json:"webhook,omitempty"`
GitHub *GitHubInterceptor `json:"github,omitempty"`
GitLab *GitLabInterceptor `json:"gitlab,omitempty"`
CEL *CELInterceptor `json:"cel,omitempty"`
}

// WebhookInterceptor provides a webhook to intercept and pre-process events
Expand All @@ -105,6 +106,11 @@ type GitLabInterceptor struct {
EventTypes []string `json:"eventTypes,omitempty"`
}

// CELInterceptor provides a webhook to intercept and pre-process events
type CELInterceptor struct {
Filter string `json:"filter,omitempty"`
}

// SecretRef contains the information required to reference a single secret string
// This is needed because the other secretRef types are not cross-namespace and do not
// actually contain the "SecretName" field, which allows us to access a single secret value.
Expand Down
9 changes: 7 additions & 2 deletions pkg/apis/triggers/v1alpha1/event_listener_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ func (s *EventListenerSpec) validate(ctx context.Context, el *EventListener) *ap
}

func (i *EventInterceptor) validate(ctx context.Context, namespace string) *apis.FieldError {
// Validate at least one
if i.Webhook == nil && i.GitHub == nil && i.GitLab == nil {
if i.Webhook == nil && i.GitHub == nil && i.GitLab == nil && i.CEL == nil {
return apis.ErrMissingField("interceptor")
}

Expand Down Expand Up @@ -126,5 +125,11 @@ func (i *EventInterceptor) validate(ctx context.Context, namespace string) *apis
// if i.GitLab != nil {
//
// }

if i.CEL != nil {
if i.CEL.Filter == "" {
return apis.ErrMissingField("interceptor.cel.filter")
}
}
return nil
}
17 changes: 17 additions & 0 deletions pkg/apis/triggers/v1alpha1/event_listener_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,23 @@ func TestEventListenerValidate_error(t *testing.T) {
}},
},
},
}, {
name: "CEL interceptor with no filter",
el: &v1alpha1.EventListener{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: v1alpha1.EventListenerSpec{
Triggers: []v1alpha1.EventListenerTrigger{{
Bindings: []*v1alpha1.EventListenerBinding{{Name: "tb"}},
Template: v1alpha1.EventListenerTemplate{Name: "tt"},
Interceptor: &v1alpha1.EventInterceptor{
CEL: &v1alpha1.CELInterceptor{},
},
}},
},
},
}}

for _, test := range tests {
Expand Down
21 changes: 21 additions & 0 deletions pkg/apis/triggers/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 08a2057

Please sign in to comment.