Skip to content

Commit

Permalink
fix(checks): respect PodSecurityContext for containers
Browse files Browse the repository at this point in the history
Signed-off-by: Nikita Pivkin <nikita.pivkin@smartforce.io>
  • Loading branch information
nikpivkin authored and simar7 committed Jan 16, 2025
1 parent e9f1c40 commit 07db85b
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 13 deletions.
23 changes: 23 additions & 0 deletions checks/kubernetes/general/runs_with_GID_le_10000_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,26 @@ test_low_gid_denied if {
count(r) == 1
r[_].msg == "Container 'hello' of Pod 'hello-gid' should set 'securityContext.runAsGroup' > 10000"
}

test_pod_sec_ctx_low_gid_denied if {
r := deny with input as {
"apiVersion": "v1",
"kind": "Pod",
"metadata": {"name": "hello-gid"},
"spec": {
"securityContext": {"runAsGroup": 100},
"containers": [{
"command": [
"sh",
"-c",
"echo 'Hello' && sleep 1h",
],
"image": "busybox",
"name": "hello",
}],
},
}

count(r) == 1
r[_].msg == "Container 'hello' of Pod 'hello-gid' should set 'securityContext.runAsGroup' > 10000"
}
23 changes: 23 additions & 0 deletions checks/kubernetes/general/runs_with_UID_le_10000_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,26 @@ test_zero_uid_denied if {
count(r) == 1
r[_].msg == "Container 'hello' of Pod 'hello-uid' should set 'securityContext.runAsUser' > 10000"
}

test_pod_sec_ctx_low_uid_denied if {
r := deny with input as {
"apiVersion": "v1",
"kind": "Pod",
"metadata": {"name": "hello-uid"},
"spec": {
"securityContext": {"runAsUser": 100},
"containers": [{
"command": [
"sh",
"-c",
"echo 'Hello' && sleep 1h",
],
"image": "busybox",
"name": "hello",
}],
},
}

count(r) == 1
r[_].msg == "Container 'hello' of Pod 'hello-uid' should set 'securityContext.runAsUser' > 10000"
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test_pod_context_custom_profile_denied if {
},
}

count(r) == 1
count(r) == 2
}

test_both_undefined_type_denied if {
Expand Down
17 changes: 14 additions & 3 deletions lib/kubernetes/kubernetes.rego
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ package lib.kubernetes

import rego.v1

import data.lib.k8s_sec_context

default is_gatekeeper := false

is_gatekeeper if {
Expand Down Expand Up @@ -39,8 +41,6 @@ default namespace := "default"

namespace := object.metadata.namespace

#annotations = object.metadata.annotations

kind := object.kind

is_pod if {
Expand Down Expand Up @@ -94,7 +94,18 @@ split_image(image) := [image_name, tag] if {

pod_containers(pod) := all_containers if {
keys = {"containers", "initContainers"}
all_containers = [c | keys[k]; c = pod.spec[k][_]]
all_containers = [c |
keys[k]
some container in pod.spec[k]
c := json.patch(
container,
[{
"op": "add",
"path": "securityContext",
"value": k8s_sec_context.resolve_container_sec_context(pod, container),
}],
)
]
}

containers contains container if {
Expand Down
35 changes: 26 additions & 9 deletions lib/kubernetes/kubernetes_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -229,18 +229,35 @@ test_containers if {
test_containers := containers with input as {
"apiVersion": "v1",
"kind": "Pod",
"spec": {"containers": [{
"command": [
"sh",
"-c",
"echo 'Hello !' && sleep 1h",
],
"image": "busybox",
"name": "hello-containers",
}]},
"spec": {
"securityContext": {
"runAsUser": 1000,
"runAsGroup": 1001,
"fsGroup": 2000,
"supplementalGroups": [4000],
},
"containers": [{
"command": [
"sh",
"-c",
"echo 'Hello !' && sleep 1h",
],
"image": "busybox",
"name": "hello-containers",
"securityContext": {
"runAsGroup": 3000,
"allowPrivilegeEscalation": false,
},
}],
},
}

test_containers[_].name == "hello-containers"
test_containers[_].securityContext == {
"runAsUser": 1000,
"runAsGroup": 3000,
"allowPrivilegeEscalation": false,
}
}

test_isapiserver_has_valid_container if {
Expand Down
33 changes: 33 additions & 0 deletions lib/kubernetes/security_context.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# METADATA
# custom:
# library: true
# input:
# selector:
# - type: kubernetes
# - type: rbac
package lib.k8s_sec_context

import rego.v1

# Some fields are present in both SecurityContext and PodSecurityContext.
# When both are set, the values in SecurityContext take precedence.
# See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#securitycontext-v1-core
resolve_container_sec_context(pod, container) := object.union(
_inherited_sec_ctx(pod),
object.get(container, "securityContext", {}),
)

_inherited_sec_ctx(pod) := {k: v |
ctx := object.get(pod, ["spec", "securityContext"], {})
some k, v in ctx
k in _inherited_sec_ctx_fields
}

_inherited_sec_ctx_fields := {
"runAsGroup",
"runAsNonRoot",
"runAsUser",
"seLinuxOptions",
"seccompProfile",
"windowsOptions",
}

0 comments on commit 07db85b

Please sign in to comment.