Skip to content

Commit

Permalink
[artemiscloud#799] Restrict security context of pods by default
Browse files Browse the repository at this point in the history
The operator pod and the broker pods can run with a safer and restricted
security context without issues. Restricting the security context of the pods
by default allows to deploy a cluster of brokers also in Kubernetes namespaces
with the restricted policy.
  • Loading branch information
brusdev committed Feb 20, 2024
1 parent ac670af commit 24c3268
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2728,8 +2728,15 @@ spec:
resources: {}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
serviceAccountName: activemq-artemis-controller-manager
terminationGracePeriodSeconds: 10
permissions:
Expand Down
7 changes: 7 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ spec:
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- command:
- /home/activemq-artemis-operator/bin/entrypoint
Expand Down Expand Up @@ -66,6 +68,11 @@ spec:
name: manager
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
seccompProfile:
type: RuntimeDefault
livenessProbe:
httpGet:
path: /healthz
Expand Down
26 changes: 24 additions & 2 deletions controllers/activemqartemis_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2334,7 +2334,12 @@ func (r *ActiveMQArtemisReconcilerImpl) configurePodSecurityContext(podSpec *cor
podSpec.SecurityContext = podSecurityContext
} else {
r.log.V(2).Info("Incoming podSecurityContext is nil, creating with default values")
podSpec.SecurityContext = &corev1.PodSecurityContext{}
runAsNonRoot := true
seccompProfile := corev1.SeccompProfile{Type: "RuntimeDefault"}
podSpec.SecurityContext = &corev1.PodSecurityContext{
RunAsNonRoot: &runAsNonRoot,
SeccompProfile: &seccompProfile,
}
}
}

Expand All @@ -2344,6 +2349,19 @@ func (r *ActiveMQArtemisReconcilerImpl) configureContianerSecurityContext(contai
if nil != containerSecurityContext {
r.log.V(2).Info("Incoming Container SecurityContext is NOT nil, assigning")
container.SecurityContext = containerSecurityContext
} else {
r.log.V(2).Info("Incoming Container SecurityContext is nil, creating with default values")
runAsNonRoot := true
allowPrivilegeEscalation := false
capabilities := corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}
seccompProfile := corev1.SeccompProfile{Type: "RuntimeDefault"}
securityContext := corev1.SecurityContext{
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
Capabilities: &capabilities,
SeccompProfile: &seccompProfile,
RunAsNonRoot: &runAsNonRoot,
}
container.SecurityContext = &securityContext
}
}

Expand Down Expand Up @@ -2374,8 +2392,12 @@ func (r *ActiveMQArtemisReconcilerImpl) configPodSecurity(podSpec *corev1.PodSpe
if podSecurity.RunAsUser != nil {
r.log.V(2).Info("Pod runAsUser specified", "runAsUser", *podSecurity.RunAsUser)
if podSpec.SecurityContext == nil {
runAsNonRoot := true
seccompProfile := corev1.SeccompProfile{Type: "RuntimeDefault"}
secCtxt := corev1.PodSecurityContext{
RunAsUser: podSecurity.RunAsUser,
RunAsUser: podSecurity.RunAsUser,
RunAsNonRoot: &runAsNonRoot,
SeccompProfile: &seccompProfile,
}
podSpec.SecurityContext = &secCtxt
} else {
Expand Down
49 changes: 44 additions & 5 deletions controllers/controllermanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,37 @@ var _ = Describe("tests regarding controller manager", func() {
})
})

It("test watching restricted namespace", func() {
testWatchNamespace("restricted", Default, func(g Gomega) {
By("deploying broker in to target namespace")
cr, createdCr := DeployCustomBroker(restrictedNamespace, nil)

By("check statefulset get created")
createdSs := &appsv1.StatefulSet{}
Eventually(func(g Gomega) {
key := types.NamespacedName{Name: namer.CrToSS(cr.Name), Namespace: restrictedNamespace}
err := k8sClient.Get(ctx, key, createdSs)
g.Expect(err).To(Succeed(), "expect to get ss for cr "+cr.Name)
}, timeout, interval).Should(Succeed())

if os.Getenv("USE_EXISTING_CLUSTER") == "true" {

// with kube, deleting while initialising leads to long delays on terminating the namespace..

By("verifying started")
deployedCrd := brokerv1beta1.ActiveMQArtemis{}
key := types.NamespacedName{Name: createdCr.Name, Namespace: createdCr.Namespace}

Eventually(func(g Gomega) {
g.Expect(k8sClient.Get(ctx, key, &deployedCrd)).Should(Succeed())
g.Expect(len(deployedCrd.Status.PodStatus.Ready)).Should(BeEquivalentTo(1))
}, existingClusterTimeout, existingClusterInterval).Should(Succeed())
}

CleanResource(createdCr, cr.Name, restrictedNamespace)
})
})

It("test watching all namespaces", func() {
testWatchNamespace("all", Default, func(g Gomega) {
By("deploying broker in to all namespaces")
Expand Down Expand Up @@ -274,14 +305,15 @@ var _ = Describe("tests regarding controller manager", func() {
})
})

func createNamespace(namespace string) error {
func createNamespace(namespace string, annotations map[string]string) error {
ns := corev1.Namespace{
TypeMeta: metav1.TypeMeta{
Kind: "Namespace",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
Name: namespace,
Annotations: annotations,
},
}

Expand Down Expand Up @@ -341,12 +373,18 @@ func testWatchNamespace(kind string, g Gomega, testFunc func(g Gomega)) {

shutdownControllerManager()

g.Expect(createNamespace(namespace1)).To(Succeed())
g.Expect(createNamespace(namespace2)).To(Succeed())
g.Expect(createNamespace(namespace3)).To(Succeed())
g.Expect(createNamespace(namespace1, map[string]string{})).To(Succeed())
g.Expect(createNamespace(namespace2, map[string]string{})).To(Succeed())
g.Expect(createNamespace(namespace3, map[string]string{})).To(Succeed())
g.Expect(createNamespace(restrictedNamespace, map[string]string{
"pod-security.kubernetes.io/enforce": "restricted",
"pod-security.kubernetes.io/enforce-version": "latest",
})).To(Succeed())

if kind == "single" {
createControllerManager(true, defaultNamespace)
} else if kind == "restricted" {
createControllerManager(true, restrictedNamespace)
} else if kind == "all" {
createControllerManager(true, "")
} else {
Expand All @@ -360,6 +398,7 @@ func testWatchNamespace(kind string, g Gomega, testFunc func(g Gomega)) {
deleteNamespace(namespace1, g)
deleteNamespace(namespace2, g)
deleteNamespace(namespace3, g)
deleteNamespace(restrictedNamespace, g)

createControllerManagerForSuite()
}
1 change: 1 addition & 0 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import (
const (
defaultNamespace = "default"
otherNamespace = "other"
restrictedNamespace = "restricted"
timeout = time.Second * 30
duration = time.Second * 10
interval = time.Millisecond * 500
Expand Down
7 changes: 7 additions & 0 deletions deploy/activemq-artemis-operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5201,7 +5201,14 @@ spec:
periodSeconds: 10
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
serviceAccountName: activemq-artemis-controller-manager
terminationGracePeriodSeconds: 10
7 changes: 7 additions & 0 deletions deploy/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,14 @@ spec:
periodSeconds: 10
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
serviceAccountName: activemq-artemis-controller-manager
terminationGracePeriodSeconds: 10

0 comments on commit 24c3268

Please sign in to comment.