-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathapprove_csrs.rego
116 lines (100 loc) · 3.88 KB
/
approve_csrs.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
package policy
import data.police_builtins as pb
import future.keywords.in
describe[{"desc": desc, "severity": severity}] {
desc := "Identities that can create and approve certificatesigningrequests can issue arbitrary certificates with cluster admin privileges"
severity := "Critical"
}
targets := {"serviceAccounts", "nodes", "combined", "users", "groups"}
# https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/
# To create a CSR
# 1. Verbs: create, get, list, watch, group: certificates.k8s.io, resource: certificatesigningrequests
# To approve a CSR
# 2. Verbs: get, list, watch, group: certificates.k8s.io, resource: certificatesigningrequests
# 3. Verbs: update, group: certificates.k8s.io, resource: certificatesigningrequests/approval
# 4. Verbs: approve, group: certificates.k8s.io, resource: signers, resourceName: <signerNameDomain>/<signerNamePath> or <signerNameDomain>/*
# Nodes already have the 1 & 2: https://github.com/kubernetes/kubernetes/blob/e847b849c4d170b872d6020bfc2263d02c05e369/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go#L150
evaluateRoles(roles, owner) {
rolesCanUpdateCsrsApproval(roles)
rolesCanApproveSigners(roles)
rolesCanCreateAndRetrieveCsrs(roles, owner)
}
rolesCanCreateAndRetrieveCsrs(roles, owner) {
owner == "node"
} {
rolesCanRetrieveCsrs(roles)
rolesCanCreateCsrs(roles)
}
evaluateCombined = combinedViolations {
combinedViolations := { combinedViolation |
some node in input.nodes
sasOnNode := pb.sasOnNode(node)
# Can the node or one of its SAs update CSR approvals?
sasCanUpdateCsrApproval := { saFullName |
some sa in sasOnNode
saEffectiveRoles := pb.effectiveRoles(sa.roles)
rolesCanUpdateCsrsApproval(saEffectiveRoles)
saFullName := pb.saFullName(sa)
}
nodeCanUpdateCsrsApproval(node.roles, sasCanUpdateCsrApproval)
# Can the node or one of its SAs approve signers?
sasCanApproveSigners := { saFullName |
some sa in sasOnNode
saEffectiveRoles := pb.effectiveRoles(sa.roles)
rolesCanApproveSigners(saEffectiveRoles)
saFullName := pb.saFullName(sa)
}
nodeCanApproveSigners(node.roles, sasCanApproveSigners)
combinedViolation := {
"node": node.name,
"serviceAccounts": sasCanUpdateCsrApproval | sasCanApproveSigners
}
}
}
nodeCanUpdateCsrsApproval(nodeRoles, sasCanUpdateCsrApproval) {
count(sasCanUpdateCsrApproval) > 0
} {
nodeEffectiveRoles := pb.effectiveRoles(nodeRoles)
rolesCanUpdateCsrsApproval(nodeEffectiveRoles)
}
nodeCanApproveSigners(nodeRoles, sasCanApproveSigners) {
count(sasCanApproveSigners) > 0
} {
nodeEffectiveRoles := pb.effectiveRoles(nodeRoles)
rolesCanApproveSigners(nodeEffectiveRoles)
}
rolesCanUpdateCsrsApproval(roles) {
some role in roles
pb.notNamespaced(role)
some rule in role.rules
pb.valueOrWildcard(rule.apiGroups, "certificates.k8s.io")
pb.updateOrPatchOrWildcard(rule.verbs) # https://github.com/kubernetes/kubernetes/blob/442a69c3bdf6fe8e525b05887e57d89db1e2f3a5/plugin/pkg/admission/certificates/approval/admission.go#L77
pb.subresourceOrWildcard(rule.resources, "certificatesigningrequests/approval")
}
rolesCanApproveSigners(roles) {
some role in roles
pb.notNamespaced(role)
some rule in role.rules
pb.valueOrWildcard(rule.apiGroups, "certificates.k8s.io")
pb.valueOrWildcard(rule.verbs, "approve")
pb.valueOrWildcard(rule.resources, "signers")
}
rolesCanCreateCsrs(roles) {
some role in roles
pb.notNamespaced(role)
some rule in role.rules
pb.valueOrWildcard(rule.apiGroups, "certificates.k8s.io")
pb.valueOrWildcard(rule.verbs, "create")
}
rolesCanRetrieveCsrs(roles) {
some role in roles
pb.notNamespaced(role)
some rule in role.rules
pb.valueOrWildcard(rule.apiGroups, "certificates.k8s.io")
getListWatchOrWildcard(rule.verbs)
}
getListWatchOrWildcard(verbs) {
pb.getOrListOrWildcard(verbs)
} {
"watch" in verbs
}