Skip to content

Commit

Permalink
Custom security contexts implementation
Browse files Browse the repository at this point in the history
Allow setting custom security contexts for both contour deployments and
envoy daemonsets. The default value is unpriviledged and is equivalent
to the following:

contourSecurityContext:
  runAsUser: 65534
  runAsGroup: 65534
  runAsNonRoot: true

Fixes projectcontour#112
Updates projectcontour#378

Signed-off-by: David Morgan <[email protected]>
  • Loading branch information
dmorgan81 committed Sep 30, 2021
1 parent 623f0d2 commit 1994c04
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 2 deletions.
8 changes: 8 additions & 0 deletions api/v1alpha1/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,11 @@ func (c *Contour) EnvoyTolerationsExist() bool {

return false
}

func (c *Contour) ContourSecurityContextExists() bool {
return c.Spec.ContourSecurityContext != nil
}

func (c *Contour) EnvoySecurityContextExists() bool {
return c.Spec.EnvoySecurityContext != nil
}
7 changes: 6 additions & 1 deletion internal/objects/daemonset/daemonset.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ func DesiredDaemonSet(contour *operatorv1alpha1.Contour, contourImage, envoyImag
DeprecatedServiceAccount: EnvoyContainerName,
AutomountServiceAccountToken: pointer.BoolPtr(false),
TerminationGracePeriodSeconds: pointer.Int64Ptr(int64(300)),
SecurityContext: &corev1.PodSecurityContext{},
DNSPolicy: corev1.DNSClusterFirst,
RestartPolicy: corev1.RestartPolicyAlways,
SchedulerName: "default-scheduler",
Expand All @@ -378,6 +377,12 @@ func DesiredDaemonSet(contour *operatorv1alpha1.Contour, contourImage, envoyImag
ds.Spec.Template.Spec.Tolerations = contour.Spec.NodePlacement.Envoy.Tolerations
}

if contour.EnvoySecurityContextExists() {
ds.Spec.Template.Spec.SecurityContext = contour.Spec.EnvoySecurityContext
} else {
ds.Spec.Template.Spec.SecurityContext = objutil.NewUnprivilegedPodSecurity()
}

return ds
}

Expand Down
34 changes: 34 additions & 0 deletions internal/objects/daemonset/daemonset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import (

operatorv1alpha1 "github.com/projectcontour/contour-operator/api/v1alpha1"
"github.com/projectcontour/contour-operator/internal/config"
objutil "github.com/projectcontour/contour-operator/internal/objects"
objcontour "github.com/projectcontour/contour-operator/internal/objects/contour"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/utils/pointer"
)

func checkDaemonSetHasEnvVar(t *testing.T, ds *appsv1.DaemonSet, container, name string) {
Expand Down Expand Up @@ -136,6 +138,16 @@ func checkDaemonSetHasTolerations(t *testing.T, ds *appsv1.DaemonSet, expected [
t.Errorf("deployment has unexpected tolerations %v", expected)
}

func checkDaemonSetHasSecurityContext(t *testing.T, ds *appsv1.DaemonSet, expected *corev1.PodSecurityContext) {
t.Helper()

if apiequality.Semantic.DeepEqual(ds.Spec.Template.Spec.SecurityContext, expected) {
return
}

t.Errorf("deployment has unexpected security context %v", expected)
}

func TestDesiredDaemonSet(t *testing.T) {
name := "ds-test"
cfg := objcontour.Config{
Expand Down Expand Up @@ -164,6 +176,7 @@ func TestDesiredDaemonSet(t *testing.T) {
}
checkDaemonSetHasNodeSelector(t, ds, nil)
checkDaemonSetHasTolerations(t, ds, nil)
checkDaemonSetHasSecurityContext(t, ds, objutil.NewUnprivilegedPodSecurity())
}

func TestNodePlacementDaemonSet(t *testing.T) {
Expand Down Expand Up @@ -198,3 +211,24 @@ func TestNodePlacementDaemonSet(t *testing.T) {
checkDaemonSetHasNodeSelector(t, ds, selectors)
checkDaemonSetHasTolerations(t, ds, tolerations)
}

func TestSecurityContextDaemonSet(t *testing.T) {
name := "security-context-test"
sc := &corev1.PodSecurityContext{
RunAsUser: pointer.Int64(int64(0)),
}
cfg := objcontour.Config{
Name: name,
Namespace: fmt.Sprintf("%s-ns", name),
SpecNs: "projectcontour",
RemoveNs: false,
NetworkType: operatorv1alpha1.LoadBalancerServicePublishingType,
}
cntr := objcontour.New(cfg)
cntr.Spec.EnvoySecurityContext = sc

testContourImage := config.DefaultContourImage
testEnvoyImage := config.DefaultEnvoyImage
ds := DesiredDaemonSet(cntr, testContourImage, testEnvoyImage)
checkDaemonSetHasSecurityContext(t, ds, sc)
}
7 changes: 6 additions & 1 deletion internal/objects/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,6 @@ func DesiredDeployment(contour *operatorv1alpha1.Contour, image string) *appsv1.
ServiceAccountName: objutil.ContourRbacName,
RestartPolicy: corev1.RestartPolicyAlways,
SchedulerName: "default-scheduler",
SecurityContext: objutil.NewUnprivilegedPodSecurity(),
TerminationGracePeriodSeconds: pointer.Int64Ptr(int64(30)),
},
},
Expand All @@ -319,6 +318,12 @@ func DesiredDeployment(contour *operatorv1alpha1.Contour, image string) *appsv1.
deploy.Spec.Template.Spec.Tolerations = contour.Spec.NodePlacement.Contour.Tolerations
}

if contour.ContourSecurityContextExists() {
deploy.Spec.Template.Spec.SecurityContext = contour.Spec.ContourSecurityContext
} else {
deploy.Spec.Template.Spec.SecurityContext = objutil.NewUnprivilegedPodSecurity()
}

return deploy
}

Expand Down
33 changes: 33 additions & 0 deletions internal/objects/deployment/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ import (

operatorv1alpha1 "github.com/projectcontour/contour-operator/api/v1alpha1"
"github.com/projectcontour/contour-operator/internal/config"
objutil "github.com/projectcontour/contour-operator/internal/objects"
objcontour "github.com/projectcontour/contour-operator/internal/objects/contour"
objcfg "github.com/projectcontour/contour-operator/internal/objects/sharedconfig"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/utils/pointer"
)

func checkDeploymentHasEnvVar(t *testing.T, deploy *appsv1.Deployment, name string) {
Expand Down Expand Up @@ -107,6 +109,16 @@ func checkDeploymentHasTolerations(t *testing.T, deploy *appsv1.Deployment, expe
t.Errorf("deployment has unexpected tolerations %v", expected)
}

func checkDeploymentHasSecurityContext(t *testing.T, deploy *appsv1.Deployment, expected *corev1.PodSecurityContext) {
t.Helper()

if apiequality.Semantic.DeepEqual(deploy.Spec.Template.Spec.SecurityContext, expected) {
return
}

t.Errorf("deployment has unexpected security context %v", expected)
}

func TestDesiredDeployment(t *testing.T) {
name := "deploy-test"
cfg := objcontour.Config{
Expand Down Expand Up @@ -155,6 +167,7 @@ func TestDesiredDeployment(t *testing.T) {
checkContainerHasArg(t, container, arg)
checkDeploymentHasNodeSelector(t, deploy, nil)
checkDeploymentHasTolerations(t, deploy, nil)
checkDeploymentHasSecurityContext(t, deploy, objutil.NewUnprivilegedPodSecurity())
}

func TestNodePlacementDeployment(t *testing.T) {
Expand Down Expand Up @@ -189,3 +202,23 @@ func TestNodePlacementDeployment(t *testing.T) {
checkDeploymentHasNodeSelector(t, deploy, selectors)
checkDeploymentHasTolerations(t, deploy, tolerations)
}

func TestSecurityContextDeployment(t *testing.T) {
name := "security-context-test"
sc := &corev1.PodSecurityContext{
RunAsUser: pointer.Int64(int64(0)),
}
cfg := objcontour.Config{
Name: name,
Namespace: fmt.Sprintf("%s-ns", name),
SpecNs: "projectcontour",
RemoveNs: false,
NetworkType: operatorv1alpha1.LoadBalancerServicePublishingType,
}
cntr := objcontour.New(cfg)
cntr.Spec.ContourSecurityContext = sc

testContourImage := config.DefaultContourImage
ds := DesiredDeployment(cntr, testContourImage)
checkDeploymentHasSecurityContext(t, ds, sc)
}

0 comments on commit 1994c04

Please sign in to comment.