Skip to content

Commit

Permalink
Update eventlistener podSeurityContext to adhere to restricted pod se…
Browse files Browse the repository at this point in the history
…curity standards

Alter podSecurityContext to include seccompProfile, runAsUser, runAsGroup and fsGroup
when set-security-context is set.

As podSecurityContext only included runAsNonRoot, which could cause injected sidecars
to miss some required restricted pod security standards securityContext
fields.
  • Loading branch information
kristofferchr committed Aug 6, 2024
1 parent 2474af6 commit 10b5ec4
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 44 deletions.
8 changes: 4 additions & 4 deletions pkg/apis/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import (

const (
defaultServiceAccountKey = "default-service-account"
defaultRunAsUserKey = "default-run-as-user"
defaultRunAsGroupKey = "default-run-as-group"
DefaultRunAsUserKey = "default-run-as-user"
DefaultRunAsGroupKey = "default-run-as-group"
defaultRunAsNonRootKey = "default-run-as-non-root"
DefaultServiceAccountValue = "default"
defaultRunAsUserValue = 65532
Expand Down Expand Up @@ -86,7 +86,7 @@ func NewDefaultsFromMap(cfgMap map[string]string) (*Defaults, error) {
tc.DefaultServiceAccount = defaultServiceAccount
}

if defaultRunAsUser, ok := cfgMap[defaultRunAsUserKey]; ok {
if defaultRunAsUser, ok := cfgMap[DefaultRunAsUserKey]; ok {
if defaultRunAsUser != "" {
runAsUser, err := strconv.ParseInt(defaultRunAsUser, 10, 0)
if err != nil {
Expand All @@ -99,7 +99,7 @@ func NewDefaultsFromMap(cfgMap map[string]string) (*Defaults, error) {
}
}

if defaultRunAsGroup, ok := cfgMap[defaultRunAsGroupKey]; ok {
if defaultRunAsGroup, ok := cfgMap[DefaultRunAsGroupKey]; ok {
if defaultRunAsGroup != "" {
runAsGroup, err := strconv.ParseInt(defaultRunAsGroup, 10, 0)
if err != nil {
Expand Down
18 changes: 18 additions & 0 deletions pkg/reconciler/eventlistener/eventlistener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ func makeDeployment(ops ...func(d *appsv1.Deployment)) *appsv1.Deployment {
}},
SecurityContext: &corev1.PodSecurityContext{
RunAsNonRoot: ptr.Bool(true),
RunAsUser: ptr.Int64(65532),
RunAsGroup: ptr.Int64(65532),
FSGroup: ptr.Int64(65532),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
},
},
Expand Down Expand Up @@ -900,6 +906,12 @@ func TestReconcile(t *testing.T) {
deploymentMissingReadOnlyRootFilesystem := makeDeployment(func(d *appsv1.Deployment) {
d.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{
RunAsNonRoot: ptr.Bool(true),
RunAsUser: ptr.Int64(65532),
RunAsGroup: ptr.Int64(65532),
FSGroup: ptr.Int64(65532),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
}
d.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
AllowPrivilegeEscalation: ptr.Bool(false),
Expand All @@ -926,6 +938,12 @@ func TestReconcile(t *testing.T) {
deploymentWithSecurityContext := makeDeployment(func(d *appsv1.Deployment) {
d.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{
RunAsNonRoot: ptr.Bool(true),
RunAsUser: ptr.Int64(65532),
RunAsGroup: ptr.Int64(65532),
FSGroup: ptr.Int64(65532),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
}
d.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
AllowPrivilegeEscalation: ptr.Bool(false),
Expand Down
21 changes: 19 additions & 2 deletions pkg/reconciler/eventlistener/resources/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,28 @@ const (
)

var (
strongerSecurityPolicy = corev1.PodSecurityContext{
baseSecurityPolicy = corev1.PodSecurityContext{
RunAsNonRoot: ptr.Bool(true),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
}
)

func getStrongerSecurityPolicy(cfg *config.Config) corev1.PodSecurityContext {
securityContext := baseSecurityPolicy
if !cfg.Defaults.IsDefaultRunAsUserEmpty {
securityContext.RunAsUser = ptr.Int64(cfg.Defaults.DefaultRunAsUser)
}

if !cfg.Defaults.IsDefaultRunAsGroupEmpty {
securityContext.RunAsGroup = ptr.Int64(cfg.Defaults.DefaultRunAsGroup)
securityContext.FSGroup = ptr.Int64(cfg.Defaults.DefaultRunAsGroup)
}

return securityContext
}

func MakeDeployment(ctx context.Context, el *v1beta1.EventListener, configAcc reconcilersource.ConfigAccessor, c Config, cfg *config.Config) (*appsv1.Deployment, error) {
opt, err := addDeploymentBits(el, c)
if err != nil {
Expand Down Expand Up @@ -101,7 +118,7 @@ func MakeDeployment(ctx context.Context, el *v1beta1.EventListener, configAcc re

var securityContext corev1.PodSecurityContext
if *c.SetSecurityContext {
securityContext = strongerSecurityPolicy
securityContext = getStrongerSecurityPolicy(cfg)
}

return &appsv1.Deployment{
Expand Down
164 changes: 126 additions & 38 deletions pkg/reconciler/eventlistener/resources/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,19 @@ func TestDeployment(t *testing.T) {
t.Setenv("METRICS_PROMETHEUS_PORT", "9000")
t.Setenv("SYSTEM_NAMESPACE", "tekton-pipelines")

config := *MakeConfig()
resourcesConfig := *MakeConfig()
labels := map[string]string{
"app.kubernetes.io/managed-by": "EventListener",
"app.kubernetes.io/part-of": "Triggers",
"eventlistener": eventListenerName,
}
expectedSecurityContext := getStrongerSecurityPolicy(cfg.FromContextOrDefaults(context.Background()))

tests := []struct {
name string
el *v1beta1.EventListener
want *appsv1.Deployment
name string
el *v1beta1.EventListener
config *cfg.Config
want *appsv1.Deployment
}{{
name: "vanilla",
el: makeEL(),
Expand All @@ -68,11 +70,11 @@ func TestDeployment(t *testing.T) {
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
},
},
},
Expand Down Expand Up @@ -103,11 +105,11 @@ func TestDeployment(t *testing.T) {
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
},
},
},
Expand Down Expand Up @@ -146,11 +148,11 @@ func TestDeployment(t *testing.T) {
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
Tolerations: []corev1.Toleration{{
Key: "foo",
Value: "bar",
Expand Down Expand Up @@ -192,11 +194,11 @@ func TestDeployment(t *testing.T) {
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
NodeSelector: map[string]string{
"foo": "bar",
},
Expand Down Expand Up @@ -235,11 +237,11 @@ func TestDeployment(t *testing.T) {
Spec: corev1.PodSpec{
ServiceAccountName: "bob",
Containers: []corev1.Container{
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
},
},
},
Expand All @@ -265,9 +267,9 @@ func TestDeployment(t *testing.T) {
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(withTLSEnvFrom("Bill")), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(withTLSEnvFrom("Bill")), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(withTLSEnvFrom("Bill")), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(withTLSEnvFrom("Bill")), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
Volumes: []corev1.Volume{{
Name: "https-connection",
Expand All @@ -277,7 +279,7 @@ func TestDeployment(t *testing.T) {
},
},
}},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
},
},
},
Expand Down Expand Up @@ -319,11 +321,11 @@ func TestDeployment(t *testing.T) {
MaxSkew: 1,
}},
Containers: []corev1.Container{
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
},
},
},
Expand All @@ -349,11 +351,73 @@ func TestDeployment(t *testing.T) {
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(setProbes()), &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(setProbes()), config),
addCertsForSecureConnection(config)),
MakeContainer(makeEL(setProbes()), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
cfg.FromContextOrDefaults(context.Background()), mustAddDeployBits(t, makeEL(setProbes()), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: &strongerSecurityPolicy,
SecurityContext: &expectedSecurityContext,
},
},
},
},
}, {
name: "with overridden runAsGroup, runAsUser, fsGroup",
el: makeEL(setProbes()),
config: getConfigWithoverriddenRunAsGroupAndRunAsUser("0"),
want: &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "",
Namespace: namespace,
Labels: labels,
OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(makeEL())},
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: labels,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: labels,
},
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(setProbes()), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
getConfigWithoverriddenRunAsGroupAndRunAsUser("0"), mustAddDeployBits(t, makeEL(setProbes()), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: getSecurityContextWithoverriddenRunAsGroupAndRunAsUser(expectedSecurityContext, ptr.Int64(0)),
},
},
},
},
}, {
name: "support empty defaults runAsGroup, runAsUser, fsGroup for distributions such as OpenShift",
el: makeEL(setProbes()),
config: getConfigWithoverriddenRunAsGroupAndRunAsUser(""),
want: &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "",
Namespace: namespace,
Labels: labels,
OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(makeEL())},
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: labels,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: labels,
},
Spec: corev1.PodSpec{
ServiceAccountName: "sa",
Containers: []corev1.Container{
MakeContainer(makeEL(setProbes()), &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
getConfigWithoverriddenRunAsGroupAndRunAsUser(""), mustAddDeployBits(t, makeEL(setProbes()), resourcesConfig),
addCertsForSecureConnection(resourcesConfig)),
},
SecurityContext: getSecurityContextWithoverriddenRunAsGroupAndRunAsUser(expectedSecurityContext, nil),
},
},
},
Expand All @@ -362,8 +426,12 @@ func TestDeployment(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := MakeDeployment(context.Background(), tt.el, &reconcilersource.EmptyVarsGenerator{}, config,
cfg.FromContextOrDefaults(context.Background()))
config := tt.config
if config == nil {
config = cfg.FromContextOrDefaults(context.Background())
}
got, err := MakeDeployment(context.Background(), tt.el, &reconcilersource.EmptyVarsGenerator{}, resourcesConfig,
config)
if err != nil {
t.Fatalf("MakeDeployment() = %v", err)
}
Expand All @@ -374,6 +442,26 @@ func TestDeployment(t *testing.T) {
}
}

func getSecurityContextWithoverriddenRunAsGroupAndRunAsUser(securityContext corev1.PodSecurityContext, overriddenValue *int64) *corev1.PodSecurityContext {
securityContextCopy := securityContext.DeepCopy()

securityContextCopy.RunAsUser = overriddenValue
securityContextCopy.RunAsGroup = overriddenValue
securityContextCopy.FSGroup = overriddenValue
return securityContextCopy
}

func getConfigWithoverriddenRunAsGroupAndRunAsUser(value string) *cfg.Config {
config := cfg.FromContextOrDefaults(context.Background())
defaults, err := cfg.NewDefaultsFromMap(map[string]string{cfg.DefaultRunAsGroupKey: value, cfg.DefaultRunAsUserKey: value})
if err != nil {
panic(err)
}

config.Defaults = defaults
return config
}

func TestDeploymentError(t *testing.T) {
t.Setenv("METRICS_PROMETHEUS_PORT", "bad")
got, err := MakeDeployment(context.Background(), makeEL(), &reconcilersource.EmptyVarsGenerator{}, *MakeConfig(),
Expand Down

0 comments on commit 10b5ec4

Please sign in to comment.