-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathsteal_pods.rego
125 lines (110 loc) · 4.08 KB
/
steal_pods.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
package policy
import data.police_builtins as pb
import future.keywords.in
describe[{"desc": desc, "severity": severity}] {
desc := sprintf("Identities that can delete or evict pods in privileged namespaces (%v) and also make other nodes unschedulable can steal powerful pods from other nodes onto a compromised one", [concat(", ", pb.privileged_namespaces)])
severity := "High"
}
targets := {"serviceAccounts", "nodes", "combined", "users", "groups"}
evaluateRoles(roles, owner) {
rolesCanRemovePodsInPrivNS(roles, owner)
rolesCanMakeNodesUnschedulable(roles, owner)
}
evaluateCombined = combinedViolations {
combinedViolations := { combinedViolation |
some node in input.nodes
sasOnNode := pb.sasOnNode(node)
# Can the node or one of its SAs remove pods?
sasCanRemovePods := { saFullName |
some sa in sasOnNode
saEffectiveRoles := pb.effectiveRoles(sa.roles)
rolesCanRemovePodsInPrivNS(saEffectiveRoles, "serviceAccount")
saFullName := pb.saFullName(sa)
}
nodeCanRemovePods(node.roles, sasCanRemovePods)
# Can the node or one of its SAs make other nodes unschedulable?
sasCanMakeNodesUnschedulable := { saFullName |
some sa in sasOnNode
saEffectiveRoles := pb.effectiveRoles(sa.roles)
rolesCanMakeNodesUnschedulable(saEffectiveRoles, "serviceAccount")
saFullName := pb.saFullName(sa)
}
nodeCanMakeNodesUnschedulable(node.roles, sasCanMakeNodesUnschedulable)
combinedViolation := {
"node": node.name,
"serviceAccounts": sasCanRemovePods | sasCanMakeNodesUnschedulable
}
}
}
nodeCanRemovePods(nodeRoles, sasCanRemovePods) {
count(sasCanRemovePods) > 0
} {
nodeEffectiveRoles := pb.effectiveRoles(nodeRoles)
rolesCanRemovePodsInPrivNS(nodeEffectiveRoles, "node")
}
nodeCanMakeNodesUnschedulable(nodeRoles, sasCanMakeNodesUnschedulable) {
count(sasCanMakeNodesUnschedulable) > 0
} {
nodeEffectiveRoles := pb.effectiveRoles(nodeRoles)
rolesCanMakeNodesUnschedulable(nodeEffectiveRoles, "node")
}
rolesCanRemovePodsInPrivNS(roles, owner) {
some role in roles
pb.affectsPrivNS(role)
roleCanRemovePods(role, owner)
}
rolesCanMakeNodesUnschedulable(roles, owner) {
not pb.nodeRestrictionEnabledAndIsNode(owner)
rule := roles[_].rules[_]
nodeOrNodeStatus(rule.resources)
pb.updateOrPatchOrWildcard(rule.verbs)
pb.valueOrWildcard(rule.apiGroups, "")
not pb.hasKey(rule, "resourceNames")
}
roleCanRemovePods(role, roleOwner) {
some rule in role.rules
pb.valueOrWildcard(rule.apiGroups, "")
ruleCanRemovePods(rule, roleOwner)
}
# Permissions that would allow one to remove a pod
ruleCanRemovePods(rule, ruleOwner) {
# Check perms that allow removal but may be blocked by NodeRestriction
not pb.nodeRestrictionEnabledAndIsNode(ruleOwner)
ruleCanRemovePodsInner(rule)
} {
# Check perms that allow removal but may be blocked by NodeRestriction from v1.17
not pb.nodeRestrictionV117EnabledAndIsNode(ruleOwner)
pb.subresourceOrWildcard(rule.resources, "pods/status")
pb.updateOrPatchOrWildcard(rule.verbs)
}
# update / patch pods: set a pod's labels to match a pod controller, triggering the removal of a real replica
# delete pods: simply delete a pod
# create pods/eviction: evict a pod
# delete nodes: delete a node to evict all its pods
# update nodes: taint a node with the NoExecute taint to evict its pods
ruleCanRemovePodsInner(rule) {
pb.valueOrWildcard(rule.resources, "pods")
pb.updateOrPatchOrWildcard(rule.verbs)
} {
not pb.hasKey(rule, "resourceNames")
ruleCanRemovePodsInner2(rule)
}
# These are most likely benign with resourceNames
ruleCanRemovePodsInner2(rule) {
pb.valueOrWildcard(rule.resources, "pods")
pb.valueOrWildcard(rule.verbs, "delete")
} {
pb.subresourceOrWildcard(rule.resources, "pods/eviction")
pb.valueOrWildcard(rule.verbs, "create")
} {
pb.valueOrWildcard(rule.resources, "nodes")
pb.valueOrWildcard(rule.verbs, "delete")
} {
pb.valueOrWildcard(rule.resources, "nodes")
pb.updateOrPatchOrWildcard(rule.verbs)
}
nodeOrNodeStatus(resources) {
pb.valueOrWildcard(resources, "nodes")
} {
pb.subresourceOrWildcard(resources, "nodes/status")
}