Skip to content

Commit f228ec3

Browse files
committed
Allow users to set custom securityContext in EventListener spec
1. Users can now define their own securityContext under the EventListener YAML. 2. When is true - If the user sets a custom securityContext, it is give priority and used same. - If not, a default securityContext is applied. Signed-off-by: savitaashture <sashture@redhat.com>
1 parent 7f33b43 commit f228ec3

File tree

9 files changed

+239
-23
lines changed

9 files changed

+239
-23
lines changed

docs/eventlisteners.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ Tolerations
272272
Containers
273273
Affinity
274274
TopologySpreadConstraints
275+
SecurityContext
275276
```
276277

277278
Legal values for the `Containers` sub-field for `kubernetesResource` and `CustomResource` are:
@@ -283,12 +284,14 @@ Env
283284
LivenessProbe
284285
ReadinessProbe
285286
StartupProbe
287+
SecurityContext
286288
```
287289
288290
**CustomResource:**
289291
```
290292
Resources
291293
Env
294+
SecurityContext
292295
```
293296
294297
### Specifying a `kubernetesResource` object
@@ -310,13 +313,18 @@ spec:
310313
key: "value"
311314
spec:
312315
serviceAccountName: tekton-triggers-github-sa
316+
securityContext:
317+
runAsNonRoot: true
313318
nodeSelector:
314319
app: test
315320
tolerations:
316321
- key: key
317322
value: value
318323
operator: Equal
319324
effect: NoSchedule
325+
containers:
326+
- securityContext:
327+
readOnlyRootFilesystem: true
320328
```
321329

322330
#### Specifying `Service` configuration
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
apiVersion: triggers.tekton.dev/v1beta1
3+
kind: EventListener
4+
metadata:
5+
name: listener-tolerations
6+
spec:
7+
serviceAccountName: tekton-triggers-example-sa
8+
resources:
9+
kubernetesResource:
10+
spec:
11+
template:
12+
spec:
13+
securityContext:
14+
runAsNonRoot: true
15+
containers:
16+
- resources:
17+
requests:
18+
memory: "64Mi"
19+
cpu: "250m"
20+
limits:
21+
memory: "128Mi"
22+
cpu: "500m"
23+
securityContext:
24+
readOnlyRootFilesystem: true
25+
triggers:
26+
- name: foo-trig
27+
bindings:
28+
- ref: pipeline-binding
29+
- ref: message-binding
30+
template:
31+
ref: pipeline-template

pkg/apis/triggers/v1beta1/event_listener_validation.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,15 @@ func containerFieldMaskForKubernetes(in *corev1.Container) *corev1.Container {
232232
out.LivenessProbe = in.LivenessProbe
233233
out.ReadinessProbe = in.ReadinessProbe
234234
out.StartupProbe = in.StartupProbe
235+
out.SecurityContext = in.SecurityContext
235236
return containerFieldMask(out)
236237
}
237238

238239
func containerFieldMaskForCustomResource(in *corev1.Container) *corev1.Container {
239240
out := new(corev1.Container)
240241
out.Resources = in.Resources
241242
out.Env = in.Env
243+
out.SecurityContext = in.SecurityContext
242244
return containerFieldMask(out)
243245
}
244246

@@ -278,6 +280,7 @@ func podSpecMask(in *corev1.PodSpec) *corev1.PodSpec {
278280
out.Affinity = in.Affinity
279281
out.TopologySpreadConstraints = in.TopologySpreadConstraints
280282
out.ImagePullSecrets = in.ImagePullSecrets
283+
out.SecurityContext = in.SecurityContext
281284

282285
// Disallowed fields
283286
// This list clarifies which all podspec fields are not allowed.
@@ -294,7 +297,6 @@ func podSpecMask(in *corev1.PodSpec) *corev1.PodSpec {
294297
out.HostPID = false
295298
out.HostIPC = false
296299
out.ShareProcessNamespace = nil
297-
out.SecurityContext = nil
298300
out.Hostname = ""
299301
out.Subdomain = ""
300302
out.SchedulerName = ""

pkg/apis/triggers/v1beta1/event_listener_validation_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,48 @@ func Test_EventListenerValidate(t *testing.T) {
587587
},
588588
},
589589
},
590+
}, {
591+
name: "Valid EventListener with kubernetes resources for securityContext",
592+
el: &triggersv1beta1.EventListener{
593+
ObjectMeta: myObjectMeta,
594+
Spec: triggersv1beta1.EventListenerSpec{
595+
Triggers: []triggersv1beta1.EventListenerTrigger{{
596+
Template: &triggersv1beta1.EventListenerTemplate{
597+
Ref: ptr.String("tt"),
598+
},
599+
}},
600+
Resources: triggersv1beta1.Resources{
601+
KubernetesResource: &triggersv1beta1.KubernetesResource{
602+
WithPodSpec: duckv1.WithPodSpec{
603+
Template: duckv1.PodSpecable{
604+
Spec: corev1.PodSpec{
605+
ServiceAccountName: "k8sresource",
606+
SecurityContext: &corev1.PodSecurityContext{
607+
RunAsNonRoot: ptr.Bool(true),
608+
},
609+
Containers: []corev1.Container{{
610+
Resources: corev1.ResourceRequirements{
611+
Limits: corev1.ResourceList{
612+
corev1.ResourceCPU: resource.Quantity{Format: resource.DecimalSI},
613+
corev1.ResourceMemory: resource.Quantity{Format: resource.BinarySI},
614+
},
615+
Requests: corev1.ResourceList{
616+
corev1.ResourceCPU: resource.Quantity{Format: resource.DecimalSI},
617+
corev1.ResourceMemory: resource.Quantity{Format: resource.BinarySI},
618+
},
619+
},
620+
SecurityContext: &corev1.SecurityContext{
621+
RunAsNonRoot: ptr.Bool(true),
622+
RunAsUser: ptr.Int64(65532),
623+
},
624+
}},
625+
},
626+
},
627+
},
628+
},
629+
},
630+
},
631+
},
590632
}}
591633

592634
for _, tc := range tests {

pkg/reconciler/eventlistener/eventlistener_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,8 +928,8 @@ func TestReconcile(t *testing.T) {
928928
})
929929

930930
deploymentMissingSecurityContext := makeDeployment(func(d *appsv1.Deployment) {
931-
d.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{}
932-
d.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{}
931+
d.Spec.Template.Spec.SecurityContext = nil
932+
d.Spec.Template.Spec.Containers[0].SecurityContext = nil
933933
})
934934

935935
deploymentWithSecurityContext := makeDeployment(func(d *appsv1.Deployment) {

pkg/reconciler/eventlistener/resources/container.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,16 @@ func MakeContainer(el *v1beta1.EventListener, configAcc reconcilersource.ConfigA
5050

5151
ev := configAcc.ToEnvVars()
5252

53-
containerSecurityContext := corev1.SecurityContext{}
54-
if *c.SetSecurityContext {
55-
containerSecurityContext = corev1.SecurityContext{
53+
var containerSecurityContext *corev1.SecurityContext
54+
if el.Spec.Resources.KubernetesResource != nil {
55+
if len(el.Spec.Resources.KubernetesResource.Template.Spec.Containers) != 0 {
56+
if *c.SetSecurityContext {
57+
containerSecurityContext = el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].SecurityContext
58+
}
59+
}
60+
}
61+
if *c.SetSecurityContext && containerSecurityContext == nil {
62+
containerSecurityContext = &corev1.SecurityContext{
5663
AllowPrivilegeEscalation: ptr.Bool(false),
5764
Capabilities: &corev1.Capabilities{
5865
Drop: []corev1.Capability{"ALL"},
@@ -111,7 +118,7 @@ func MakeContainer(el *v1beta1.EventListener, configAcc reconcilersource.ConfigA
111118
Name: "K_SINK_TIMEOUT",
112119
Value: strconv.FormatInt(*c.TimeOutHandler, 10),
113120
}}...),
114-
SecurityContext: &containerSecurityContext,
121+
SecurityContext: containerSecurityContext,
115122
}
116123

117124
for _, opt := range opts {

pkg/reconciler/eventlistener/resources/container_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
corev1 "k8s.io/api/core/v1"
2929
"k8s.io/apimachinery/pkg/api/resource"
3030
reconcilersource "knative.dev/eventing/pkg/reconciler/source"
31+
duckv1 "knative.dev/pkg/apis/duck/v1"
3132
"knative.dev/pkg/ptr"
3233
)
3334

@@ -486,6 +487,73 @@ func TestContainer(t *testing.T) {
486487
},
487488
},
488489
},
490+
}, {
491+
name: "passing securityContext from EL",
492+
el: makeEL(func(el *v1beta1.EventListener) {
493+
el.Spec.Resources.KubernetesResource = &v1beta1.KubernetesResource{
494+
WithPodSpec: duckv1.WithPodSpec{
495+
Template: duckv1.PodSpecable{
496+
Spec: corev1.PodSpec{
497+
Containers: []corev1.Container{{
498+
SecurityContext: &corev1.SecurityContext{
499+
RunAsNonRoot: ptr.Bool(true),
500+
},
501+
}},
502+
},
503+
},
504+
},
505+
}
506+
el.Annotations = map[string]string{
507+
triggers.PayloadValidationAnnotation: "false",
508+
}
509+
}),
510+
want: corev1.Container{
511+
Name: "event-listener",
512+
Image: DefaultImage,
513+
Ports: []corev1.ContainerPort{{
514+
ContainerPort: int32(eventListenerContainerPort),
515+
Protocol: corev1.ProtocolTCP,
516+
}},
517+
Args: []string{
518+
"--el-name=" + eventListenerName,
519+
"--el-namespace=" + namespace,
520+
"--port=" + strconv.Itoa(eventListenerContainerPort),
521+
"--readtimeout=" + strconv.FormatInt(DefaultReadTimeout, 10),
522+
"--writetimeout=" + strconv.FormatInt(DefaultWriteTimeout, 10),
523+
"--idletimeout=" + strconv.FormatInt(DefaultIdleTimeout, 10),
524+
"--timeouthandler=" + strconv.FormatInt(DefaultTimeOutHandler, 10),
525+
"--httpclient-readtimeout=" + strconv.FormatInt(DefaultHTTPClientReadTimeOut, 10),
526+
"--httpclient-keep-alive=" + strconv.FormatInt(DefaultHTTPClientKeepAlive, 10),
527+
"--httpclient-tlshandshaketimeout=" + strconv.FormatInt(DefaultHTTPClientTLSHandshakeTimeout, 10),
528+
"--httpclient-responseheadertimeout=" + strconv.FormatInt(DefaultHTTPClientResponseHeaderTimeout, 10),
529+
"--httpclient-expectcontinuetimeout=" + strconv.FormatInt(DefaultHTTPClientExpectContinueTimeout, 10),
530+
"--is-multi-ns=" + strconv.FormatBool(false),
531+
"--payload-validation=" + strconv.FormatBool(false),
532+
"--cloudevent-uri=",
533+
},
534+
Env: []corev1.EnvVar{{
535+
Name: "K_LOGGING_CONFIG",
536+
}, {
537+
Name: "K_METRICS_CONFIG",
538+
}, {
539+
Name: "K_TRACING_CONFIG",
540+
}, {
541+
Name: "NAMESPACE",
542+
Value: namespace,
543+
}, {
544+
Name: "NAME",
545+
Value: eventListenerName,
546+
}, {
547+
Name: "EL_EVENT",
548+
Value: "disable",
549+
}, {
550+
Name: "K_SINK_TIMEOUT",
551+
Value: strconv.FormatInt(DefaultTimeOutHandler, 10),
552+
}},
553+
SecurityContext: &corev1.SecurityContext{
554+
RunAsNonRoot: ptr.Bool(true),
555+
},
556+
},
489557
}}
490558

491559
for _, tt := range tests {

pkg/reconciler/eventlistener/resources/deployment.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ const (
3737
)
3838

3939
var (
40-
baseSecurityPolicy = corev1.PodSecurityContext{
40+
baseSecurityPolicy = &corev1.PodSecurityContext{
4141
RunAsNonRoot: ptr.Bool(true),
4242
SeccompProfile: &corev1.SeccompProfile{
4343
Type: corev1.SeccompProfileTypeRuntimeDefault,
4444
},
4545
}
4646
)
4747

48-
func getStrongerSecurityPolicy(cfg *config.Config) corev1.PodSecurityContext {
48+
func getStrongerSecurityPolicy(cfg *config.Config) *corev1.PodSecurityContext {
4949
securityContext := baseSecurityPolicy
5050
if !cfg.Defaults.IsDefaultRunAsUserEmpty {
5151
securityContext.RunAsUser = ptr.Int64(cfg.Defaults.DefaultRunAsUser)
@@ -97,6 +97,7 @@ func MakeDeployment(ctx context.Context, el *v1beta1.EventListener, configAcc re
9797
}
9898
}
9999

100+
var securityContext *corev1.PodSecurityContext
100101
if el.Spec.Resources.KubernetesResource != nil {
101102
if el.Spec.Resources.KubernetesResource.Replicas != nil {
102103
replicas = el.Spec.Resources.KubernetesResource.Replicas
@@ -121,10 +122,12 @@ func MakeDeployment(ctx context.Context, el *v1beta1.EventListener, configAcc re
121122
}
122123
annotations = el.Spec.Resources.KubernetesResource.Template.Annotations
123124
podlabels = kmeta.UnionMaps(podlabels, el.Spec.Resources.KubernetesResource.Template.Labels)
125+
if *c.SetSecurityContext {
126+
securityContext = el.Spec.Resources.KubernetesResource.Template.Spec.SecurityContext
127+
}
124128
}
125129

126-
var securityContext corev1.PodSecurityContext
127-
if *c.SetSecurityContext {
130+
if *c.SetSecurityContext && securityContext == nil {
128131
securityContext = getStrongerSecurityPolicy(cfg)
129132
}
130133

@@ -147,7 +150,7 @@ func MakeDeployment(ctx context.Context, el *v1beta1.EventListener, configAcc re
147150
ServiceAccountName: serviceAccountName,
148151
Containers: []corev1.Container{container},
149152
Volumes: vol,
150-
SecurityContext: &securityContext,
153+
SecurityContext: securityContext,
151154
Affinity: affinity,
152155
TopologySpreadConstraints: topologySpreadConstraints,
153156
},
@@ -176,7 +179,6 @@ func addDeploymentBits(el *v1beta1.EventListener, c Config) (ContainerOption, er
176179
container.StartupProbe = el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].StartupProbe
177180
}
178181
}
179-
180182
container.Ports = append(container.Ports, corev1.ContainerPort{
181183
ContainerPort: int32(metricsPort),
182184
Protocol: corev1.ProtocolTCP,

0 commit comments

Comments
 (0)