Skip to content

Commit 56f6a65

Browse files
committed
add pod security
1 parent 8824136 commit 56f6a65

File tree

3 files changed

+103
-1
lines changed

3 files changed

+103
-1
lines changed

internal/controller/postgrescluster/pgbouncer.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/crunchydata/postgres-operator/internal/pgbouncer"
2626
"github.com/crunchydata/postgres-operator/internal/pki"
2727
"github.com/crunchydata/postgres-operator/internal/postgres"
28+
"github.com/crunchydata/postgres-operator/internal/util"
2829
"github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1"
2930
)
3031

@@ -477,7 +478,7 @@ func (r *Reconciler) generatePGBouncerDeployment(
477478
// Do not add environment variables describing services in this namespace.
478479
deploy.Spec.Template.Spec.EnableServiceLinks = initialize.Bool(false)
479480

480-
deploy.Spec.Template.Spec.SecurityContext = initialize.PodSecurityContext()
481+
deploy.Spec.Template.Spec.SecurityContext = util.PodSecurityContext(ctx, 2, cluster.Spec.SupplementalGroups)
481482

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

internal/util/pod_security.go

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

internal/util/pod_security_test.go

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

0 commit comments

Comments
 (0)