-
Notifications
You must be signed in to change notification settings - Fork 316
/
src.rego
127 lines (103 loc) · 4.21 KB
/
src.rego
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package k8spspallowedusers
import data.lib.exclude_update.is_update
import data.lib.exempt_container.is_exempt
violation[{"msg": msg}] {
# runAsUser, runAsGroup, supplementalGroups, fsGroup fields are immutable.
not is_update(input.review)
fields := ["runAsUser", "runAsGroup", "supplementalGroups", "fsGroup"]
field := fields[_]
container := input_containers[_]
not is_exempt(container)
msg := get_type_violation(field, container)
}
get_type_violation(field, container) = msg {
field == "runAsUser"
params := input.parameters[field]
msg := get_user_violation(params, container)
}
get_type_violation(field, container) = msg {
field != "runAsUser"
params := input.parameters[field]
msg := get_violation(field, params, container)
}
# RunAsUser (separate due to "MustRunAsNonRoot")
get_user_violation(params, container) = msg {
rule := params.rule
provided_user := get_field_value("runAsUser", container, input.review)
not accept_users(rule, provided_user)
msg := sprintf("Container %v is attempting to run as disallowed user %v. Allowed runAsUser: %v", [container.name, provided_user, params])
}
get_user_violation(params, container) = msg {
not get_field_value("runAsUser", container, input.review)
params.rule = "MustRunAs"
msg := sprintf("Container %v is attempting to run without a required securityContext/runAsUser", [container.name])
}
get_user_violation(params, container) = msg {
params.rule = "MustRunAsNonRoot"
not get_field_value("runAsUser", container, input.review)
not get_field_value("runAsNonRoot", container, input.review)
msg := sprintf("Container %v is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0", [container.name])
}
accept_users("RunAsAny", _)
accept_users("MustRunAsNonRoot", provided_user) := provided_user != 0
accept_users("MustRunAs", provided_user) := res {
ranges := input.parameters.runAsUser.ranges
res := is_in_range(provided_user, ranges)
}
# Group Options
get_violation(field, params, container) = msg {
rule := params.rule
provided_value := get_field_value(field, container, input.review)
not is_array(provided_value)
not accept_value(rule, provided_value, params.ranges)
msg := sprintf("Container %v is attempting to run as disallowed group %v. Allowed %v: %v", [container.name, provided_value, field, params])
}
# SupplementalGroups is array value
get_violation(field, params, container) = msg {
rule := params.rule
array_value := get_field_value(field, container, input.review)
is_array(array_value)
provided_value := array_value[_]
not accept_value(rule, provided_value, params.ranges)
msg := sprintf("Container %v is attempting to run with disallowed supplementalGroups %v. Allowed %v: %v", [container.name, array_value, field, params])
}
get_violation(field, params, container) = msg {
not get_field_value(field, container, input.review)
params.rule == "MustRunAs"
msg := sprintf("Container %v is attempting to run without a required securityContext/%v. Allowed %v: %v", [container.name, field, field, params])
}
accept_value("RunAsAny", _, _)
accept_value("MayRunAs", provided_value, ranges) := is_in_range(provided_value, ranges)
accept_value("MustRunAs", provided_value, ranges) := is_in_range(provided_value, ranges)
# If container level is provided, that takes precedence
get_field_value(field, container, _) := get_seccontext_field(field, container)
# If no container level exists, use pod level
get_field_value(field, container, review) = out {
not has_seccontext_field(field, container)
review.kind.kind == "Pod"
pod_value := get_seccontext_field(field, review.object.spec)
out := pod_value
}
# Helper Functions
is_in_range(val, ranges) = res {
matching := {1 | val >= ranges[j].min; val <= ranges[j].max}
res := count(matching) > 0
}
has_seccontext_field(field, obj) {
get_seccontext_field(field, obj)
}
has_seccontext_field(field, obj) {
get_seccontext_field(field, obj) == false
}
get_seccontext_field(field, obj) = out {
out = obj.securityContext[field]
}
input_containers[c] {
c := input.review.object.spec.containers[_]
}
input_containers[c] {
c := input.review.object.spec.initContainers[_]
}
input_containers[c] {
c := input.review.object.spec.ephemeralContainers[_]
}