Skip to content

Commit 43e16bb

Browse files
authored
Allow SecurityContext and PodSecurityContext to be reset to default (rabbitmq#749)
* Allow SecurityContext and PodSecurityContext to be reset to default * Review markups * Add documented example for overriding securityContext
1 parent 3490cfb commit 43e16bb

File tree

6 files changed

+120
-0
lines changed

6 files changed

+120
-0
lines changed

controllers/rabbitmqcluster_controller_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
. "github.com/onsi/ginkgo"
2323

2424
. "github.com/onsi/gomega"
25+
. "github.com/onsi/gomega/gstruct"
2526
rabbitmqv1beta1 "github.com/rabbitmq/cluster-operator/api/v1beta1"
2627
"github.com/rabbitmq/cluster-operator/internal/status"
2728
appsv1 "k8s.io/api/apps/v1"
@@ -957,6 +958,28 @@ var _ = Describe("RabbitmqClusterController", func() {
957958
return c.Image
958959
}, 3).Should(Equal("my-great-image-2"))
959960
})
961+
962+
It("can reset the securityContext of the RabbitMQ container and initContainer to default", func() {
963+
Expect(updateWithRetry(cluster, func(r *rabbitmqv1beta1.RabbitmqCluster) {
964+
cluster.Spec.Override.StatefulSet.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{}
965+
cluster.Spec.Override.StatefulSet.Spec.Template.Spec.InitContainers = []corev1.Container{
966+
{
967+
Name: "setup-container",
968+
SecurityContext: &corev1.SecurityContext{},
969+
},
970+
}
971+
})).To(Succeed())
972+
973+
Eventually(func() corev1.PodSecurityContext {
974+
sts := statefulSet(ctx, cluster)
975+
return *sts.Spec.Template.Spec.SecurityContext
976+
}, 3).Should(MatchFields(IgnoreExtras, Fields{
977+
"RunAsUser": BeNil(),
978+
"FSGroup": BeNil(),
979+
}))
980+
Expect(statefulSet(ctx, cluster).Spec.Template.Spec.InitContainers[0].SecurityContext).To(BeNil())
981+
})
982+
960983
})
961984

962985
Context("Service Override", func() {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Setting Pod Security Context to Container Runtime default
2+
3+
By default, the RabbitMQ Cluster Operator applies a [securityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) in order to run the RabbitMQ container
4+
and initContainer as a specific non-root user.
5+
6+
In some deployments, you may wish to remove this securityContext so that the containers are run with the default securityContext of the container runtime. For example, in Openshift, in order
7+
to [run the RabbitMQ containers as an arbitrary user](https://www.openshift.com/blog/a-guide-to-openshift-and-uids), you will need to remove the operator-configured securityContext.
8+
9+
Note that unless your Kubernetes distribution applies a default securityContext to pods, your containers will run as root.
10+
11+
## Example
12+
13+
The example `rabbitmq.yaml` contains an override which will set the securityContext to the default, by specifying it as an empty struct (`{}`).
14+
15+
```shell
16+
kubectl apply -f rabbitmq.yaml
17+
```
18+
19+
You can then inspect the container to check that it is running with the default securityContext:
20+
```shell
21+
kubectl exec default-security-context-server-0 -- id
22+
uid=0(root) gid=0(root) groups=0(root)
23+
```
24+
25+
Or, in an environment where the runtime provides a default securityContext, like Openshift:
26+
```shell
27+
kubectl exec default-security-context-server-0 -- id
28+
uid=1000620000(1000620000) gid=0(root) groups=0(root),1000620000
29+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: rabbitmq.com/v1beta1
2+
kind: RabbitmqCluster
3+
metadata:
4+
name: default-security-context
5+
spec:
6+
override:
7+
statefulSet:
8+
spec:
9+
template:
10+
spec:
11+
securityContext: {}
12+
containers: []
13+
initContainers:
14+
- name: setup-container
15+
securityContext: {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
set -x
3+
4+
uid="$(kubectl exec default-security-context-server-0 -- \
5+
id -u 2> /dev/null)"
6+
groups="$(kubectl exec default-security-context-server-0 -- \
7+
id -G 2> /dev/null)"
8+
## kubectl std. error is redirectd to null because the error output of jsonpath
9+
## is not very helpful to troubleshoot
10+
11+
[[ "$uid" == "0" && "$groups" == "0" ]] || exit 1
12+

internal/resource/statefulset.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ package resource
1212
import (
1313
"encoding/json"
1414
"fmt"
15+
"reflect"
1516

1617
"sigs.k8s.io/controller-runtime/pkg/client"
1718

@@ -258,6 +259,18 @@ func patchPodSpec(podSpec, podSpecOverride *corev1.PodSpec) (corev1.PodSpec, err
258259
sortVolumeMounts(patchedPodSpec.Containers[0].VolumeMounts)
259260
}
260261

262+
// A user may wish to override the controller-set securityContext for the RabbitMQ & init containers so that the
263+
// container runtime can override them. If the securityContext has been set to an empty struct, `strategicpatch.StrategicMergePatch`
264+
// won't pick this up, so manually override it here.
265+
if podSpecOverride.SecurityContext != nil && reflect.DeepEqual(*podSpecOverride.SecurityContext, corev1.PodSecurityContext{}) {
266+
patchedPodSpec.SecurityContext = nil
267+
}
268+
for i := range podSpecOverride.InitContainers {
269+
if podSpecOverride.InitContainers[i].SecurityContext != nil && reflect.DeepEqual(*podSpecOverride.InitContainers[i].SecurityContext, corev1.SecurityContext{}) {
270+
patchedPodSpec.InitContainers[i].SecurityContext = nil
271+
}
272+
}
273+
261274
return patchedPodSpec, nil
262275
}
263276

internal/resource/statefulset_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,34 @@ var _ = Describe("StatefulSet", func() {
16931693
},
16941694
}))
16951695
})
1696+
It("can reset securityContext to default", func() {
1697+
instance.Spec.Override.StatefulSet = &rabbitmqv1beta1.StatefulSet{
1698+
Spec: &rabbitmqv1beta1.StatefulSetSpec{
1699+
Template: &rabbitmqv1beta1.PodTemplateSpec{
1700+
Spec: &corev1.PodSpec{
1701+
SecurityContext: &corev1.PodSecurityContext{},
1702+
InitContainers: []corev1.Container{
1703+
{
1704+
Name: "setup-container",
1705+
SecurityContext: &corev1.SecurityContext{},
1706+
},
1707+
},
1708+
},
1709+
},
1710+
},
1711+
}
1712+
1713+
builder = &resource.RabbitmqResourceBuilder{
1714+
Instance: &instance,
1715+
Scheme: scheme,
1716+
}
1717+
stsBuilder := builder.StatefulSet()
1718+
Expect(stsBuilder.Update(statefulSet)).To(Succeed())
1719+
1720+
Expect(statefulSet.Spec.Template.Spec.SecurityContext).To(BeNil())
1721+
Expect(statefulSet.Spec.Template.Spec.InitContainers[0].SecurityContext).To(BeNil())
1722+
1723+
})
16961724

16971725
Context("Rabbitmq Container volume mounts", func() {
16981726
It("Overrides the volume mounts list while making sure that '/var/lib/rabbitmq/' mounts before '/var/lib/rabbitmq/mnesia/' ", func() {

0 commit comments

Comments
 (0)