Skip to content

Commit 8d73c0f

Browse files
authored
Set fsGroup on pgBouncer pods (#4277)
When we looked into logging validation, we found that pgBouncer wasn't being created with an fsGroup setting. This PR updates that.
1 parent fe4aa54 commit 8d73c0f

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

internal/controller/postgrescluster/pgbouncer.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,13 @@ func (r *Reconciler) generatePGBouncerDeployment(
462462
// Do not add environment variables describing services in this namespace.
463463
deploy.Spec.Template.Spec.EnableServiceLinks = initialize.Bool(false)
464464

465-
deploy.Spec.Template.Spec.SecurityContext = initialize.PodSecurityContext()
465+
fsGroup := 2
466+
if initialize.FromPointer(cluster.Spec.OpenShift) {
467+
fsGroup = 0
468+
}
469+
deploy.Spec.Template.Spec.SecurityContext = util.PodSecurityContext(int64(fsGroup),
470+
cluster.Spec.SupplementalGroups,
471+
)
466472

467473
// set the image pull secrets, if any exist
468474
deploy.Spec.Template.Spec.ImagePullSecrets = cluster.Spec.ImagePullSecrets

internal/controller/postgrescluster/pgbouncer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ containers: null
478478
enableServiceLinks: false
479479
restartPolicy: Always
480480
securityContext:
481+
fsGroup: 2
481482
fsGroupChangePolicy: OnRootMismatch
482483
shareProcessNamespace: true
483484
topologySpreadConstraints:

internal/util/pod_security.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2017 - 2025 Crunchy Data Solutions, Inc.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package util
6+
7+
import (
8+
corev1 "k8s.io/api/core/v1"
9+
10+
"github.com/crunchydata/postgres-operator/internal/initialize"
11+
)
12+
13+
// PodSecurityContext returns a v1.PodSecurityContext for cluster that can write
14+
// to PersistentVolumes.
15+
// This func sets the supplmental groups and fsGgroup if present.
16+
// fsGroup should not be present in OpenShift environments
17+
func PodSecurityContext(fsgroup int64, supplementalGroups []int64) *corev1.PodSecurityContext {
18+
psc := initialize.PodSecurityContext()
19+
20+
// Use the specified supplementary groups except for root. The CRD has
21+
// similar validation, but we should never emit a PodSpec with that group.
22+
// - https://docs.k8s.io/concepts/security/pod-security-standards/
23+
for i := range supplementalGroups {
24+
if gid := supplementalGroups[i]; gid > 0 {
25+
psc.SupplementalGroups = append(psc.SupplementalGroups, gid)
26+
}
27+
}
28+
29+
// OpenShift assigns a filesystem group based on a SecurityContextConstraint.
30+
// Otherwise, set a filesystem group so PostgreSQL can write to files
31+
// regardless of the UID or GID of a container.
32+
// - https://cloud.redhat.com/blog/a-guide-to-openshift-and-uids
33+
// - https://docs.k8s.io/tasks/configure-pod-container/security-context/
34+
// - https://docs.openshift.com/container-platform/4.8/authentication/managing-security-context-constraints.html
35+
if fsgroup > 0 {
36+
psc.FSGroup = initialize.Int64(fsgroup)
37+
}
38+
39+
return psc
40+
}

internal/util/pod_security_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2017 - 2025 Crunchy Data Solutions, Inc.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package util
6+
7+
import (
8+
"testing"
9+
10+
"gotest.tools/v3/assert"
11+
12+
"github.com/crunchydata/postgres-operator/internal/testing/cmp"
13+
)
14+
15+
func TestPodSecurityContext(t *testing.T) {
16+
t.Run("Non-Openshift", func(t *testing.T) {
17+
assert.Assert(t, cmp.MarshalMatches(PodSecurityContext(2, []int64{}), `
18+
fsGroup: 2
19+
fsGroupChangePolicy: OnRootMismatch
20+
`))
21+
22+
supplementalGroups := []int64{3, 4}
23+
assert.Assert(t, cmp.MarshalMatches(PodSecurityContext(26, supplementalGroups), `
24+
fsGroup: 26
25+
fsGroupChangePolicy: OnRootMismatch
26+
supplementalGroups:
27+
- 3
28+
- 4
29+
`))
30+
})
31+
32+
t.Run("OpenShift", func(t *testing.T) {
33+
assert.Assert(t, cmp.MarshalMatches(PodSecurityContext(0, []int64{}),
34+
`fsGroupChangePolicy: OnRootMismatch`))
35+
36+
supplementalGroups := []int64{3, 4}
37+
assert.Assert(t, cmp.MarshalMatches(PodSecurityContext(0, supplementalGroups), `
38+
fsGroupChangePolicy: OnRootMismatch
39+
supplementalGroups:
40+
- 3
41+
- 4
42+
`))
43+
})
44+
45+
t.Run("NoRootGID", func(t *testing.T) {
46+
supplementalGroups := []int64{999, 0, 100, 0}
47+
assert.DeepEqual(t, []int64{999, 100}, PodSecurityContext(2, supplementalGroups).SupplementalGroups)
48+
49+
supplementalGroups = []int64{0}
50+
assert.Assert(t, PodSecurityContext(2, supplementalGroups).SupplementalGroups == nil)
51+
})
52+
}

0 commit comments

Comments
 (0)