Skip to content

Commit ea217b0

Browse files
lmicciniclaude
andcommitted
Add RestrictiveSecurityContext helper to pod package
Provides a centralized helper for building hardened container SecurityContext for unprivileged workloads: RunAsNonRoot, drops all capabilities, disables privilege escalation, and applies the RuntimeDefault seccomp profile. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 734fbfd commit ea217b0

2 files changed

Lines changed: 97 additions & 0 deletions

File tree

modules/common/pod/security.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright 2026 Red Hat
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package pod
18+
19+
import (
20+
corev1 "k8s.io/api/core/v1"
21+
"k8s.io/utils/ptr"
22+
)
23+
24+
// RestrictiveSecurityContext returns a hardened container SecurityContext
25+
// suitable for unprivileged workloads. It sets RunAsNonRoot, drops all
26+
// capabilities, disables privilege escalation, and applies the RuntimeDefault
27+
// seccomp profile. The provided uid is used for both RunAsUser and RunAsGroup.
28+
func RestrictiveSecurityContext(uid int64) *corev1.SecurityContext {
29+
return RestrictiveSecurityContextWithGID(uid, uid)
30+
}
31+
32+
// RestrictiveSecurityContextWithGID is like RestrictiveSecurityContext but
33+
// allows specifying a different GID.
34+
func RestrictiveSecurityContextWithGID(uid, gid int64) *corev1.SecurityContext {
35+
return &corev1.SecurityContext{
36+
RunAsUser: ptr.To(uid),
37+
RunAsGroup: ptr.To(gid),
38+
RunAsNonRoot: ptr.To(true),
39+
AllowPrivilegeEscalation: ptr.To(false),
40+
Capabilities: &corev1.Capabilities{
41+
Drop: []corev1.Capability{"ALL"},
42+
},
43+
SeccompProfile: &corev1.SeccompProfile{
44+
Type: corev1.SeccompProfileTypeRuntimeDefault,
45+
},
46+
}
47+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package pod
2+
3+
import (
4+
"testing"
5+
6+
corev1 "k8s.io/api/core/v1"
7+
)
8+
9+
func TestRestrictiveSecurityContext(t *testing.T) {
10+
var uid int64 = 42457
11+
sc := RestrictiveSecurityContext(uid)
12+
13+
if sc.RunAsUser == nil || *sc.RunAsUser != uid {
14+
t.Errorf("expected RunAsUser %d, got %v", uid, sc.RunAsUser)
15+
}
16+
if sc.RunAsGroup == nil || *sc.RunAsGroup != uid {
17+
t.Errorf("expected RunAsGroup %d, got %v", uid, sc.RunAsGroup)
18+
}
19+
if sc.RunAsNonRoot == nil || !*sc.RunAsNonRoot {
20+
t.Error("expected RunAsNonRoot true")
21+
}
22+
if sc.AllowPrivilegeEscalation == nil || *sc.AllowPrivilegeEscalation {
23+
t.Error("expected AllowPrivilegeEscalation false")
24+
}
25+
if sc.Capabilities == nil || len(sc.Capabilities.Drop) != 1 || sc.Capabilities.Drop[0] != "ALL" {
26+
t.Errorf("expected Capabilities.Drop [ALL], got %v", sc.Capabilities)
27+
}
28+
if sc.SeccompProfile == nil || sc.SeccompProfile.Type != corev1.SeccompProfileTypeRuntimeDefault {
29+
t.Errorf("expected SeccompProfile RuntimeDefault, got %v", sc.SeccompProfile)
30+
}
31+
}
32+
33+
func TestRestrictiveSecurityContextWithGID(t *testing.T) {
34+
var uid int64 = 42415
35+
var gid int64 = 42416
36+
sc := RestrictiveSecurityContextWithGID(uid, gid)
37+
38+
if sc.RunAsUser == nil || *sc.RunAsUser != uid {
39+
t.Errorf("expected RunAsUser %d, got %v", uid, sc.RunAsUser)
40+
}
41+
if sc.RunAsGroup == nil || *sc.RunAsGroup != gid {
42+
t.Errorf("expected RunAsGroup %d, got %v", gid, sc.RunAsGroup)
43+
}
44+
if sc.RunAsNonRoot == nil || !*sc.RunAsNonRoot {
45+
t.Error("expected RunAsNonRoot true")
46+
}
47+
if sc.AllowPrivilegeEscalation == nil || *sc.AllowPrivilegeEscalation {
48+
t.Error("expected AllowPrivilegeEscalation false")
49+
}
50+
}

0 commit comments

Comments
 (0)