match_rules in config/rules.yaml select a Rule node by exact equality on resource and verb, so a role rule granting the RBAC wildcard is not matched by a risk rule naming a concrete value:
- a role granting
verbs: ['*'] on a resource is not matched by rules naming a verb (risky-create-daemonsets, risky-get-secrets, ...), even though * grants that verb
- a role granting
resources: ['*'] within an API group is not matched by rules naming a resource (risky-get-secrets, risky-any-verb-pods, ...), even though * covers that resource
This is the mirror image of #80: that issue was about a match rule being too broad (any API group satisfied it); this one is about it being too narrow.
Reproduction
Three ClusterRoles, each bound to a ServiceAccount:
# 1
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["get", "list", "delete"]
# 2
rules:
- apiGroups: ["apps"]
resources: ["daemonsets"]
verbs: ["*"]
# 3
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["*"]
Findings reported:
| ClusterRole |
grants |
reported by |
not reported by |
core-wildcard-reader (1) |
get/list/delete on every core resource, incl. secrets and pods |
nothing |
risky-get-secrets, risky-list-secrets, risky-any-resource-* |
wildcard-verb-daemonsets (2) |
every verb on daemonsets, incl. create and update |
risky-any-verb-daemonsets |
risky-create-daemonsets, risky-update-daemonsets |
wildcard-verb-secrets (3) |
every verb on secrets, incl. get and list |
risky-any-verb-secrets |
risky-get-secrets, risky-list-secrets |
For (2) and (3) the grant is at least reported under some title, so the gap costs precision rather than coverage. For (1) nothing is reported at all: get on * resources scoped to the core group is now invisible to the report, since the fix for #80 scopes the resources: ['*'] rules to apiGroups: ['*'] (before that fix it was reported, but as "get action on all resources", which was the inaccuracy #80 objected to).
Note this only affects the risky-role template's match_rules. The subject level templates (unrestricted-cluster-wide-subjects, unrestricted-ns-level-subjects, rbac-managing-subjects) already spell the wildcard out in their queries, e.g. (r.resource = '*' OR r.url = '*') AND r.verb = '*'.
Suggested fix
Match resource and verb as alternatives including the wildcard, the way apiGroups are handled after #80 - i.e. ru0.verb IN ['create', '*'] and ru0.resource IN ['secrets', '*'] instead of the equality in the node property map.
Two things to decide before doing that, since it widens the report noticeably:
- Double reporting. A role granting
verbs: ['*'] on secrets would then match risky-get-secrets, risky-list-secrets and risky-any-verb-secrets, so the same grant appears under three titles. The risky-any-* rules may want to become the only match for the wildcard case, or the specific rules may want to exclude a wildcard-only grant.
- Multi-match rules.
risky-exec-pods and the risky-create-rolebinding-* rules AND several selectors together; widening each one multiplies how easily the intersection is satisfied, which is the intent but worth eyeballing against a real cluster's report first.
Found while fixing #80.
match_rulesinconfig/rules.yamlselect aRulenode by exact equality onresourceandverb, so a role rule granting the RBAC wildcard is not matched by a risk rule naming a concrete value:verbs: ['*']on a resource is not matched by rules naming a verb (risky-create-daemonsets,risky-get-secrets, ...), even though*grants that verbresources: ['*']within an API group is not matched by rules naming a resource (risky-get-secrets,risky-any-verb-pods, ...), even though*covers that resourceThis is the mirror image of #80: that issue was about a match rule being too broad (any API group satisfied it); this one is about it being too narrow.
Reproduction
Three ClusterRoles, each bound to a ServiceAccount:
Findings reported:
core-wildcard-reader(1)risky-get-secrets,risky-list-secrets,risky-any-resource-*wildcard-verb-daemonsets(2)risky-any-verb-daemonsetsrisky-create-daemonsets,risky-update-daemonsetswildcard-verb-secrets(3)risky-any-verb-secretsrisky-get-secrets,risky-list-secretsFor (2) and (3) the grant is at least reported under some title, so the gap costs precision rather than coverage. For (1) nothing is reported at all:
geton*resources scoped to the core group is now invisible to the report, since the fix for #80 scopes theresources: ['*']rules toapiGroups: ['*'](before that fix it was reported, but as "get action on all resources", which was the inaccuracy #80 objected to).Note this only affects the
risky-roletemplate'smatch_rules. The subject level templates (unrestricted-cluster-wide-subjects,unrestricted-ns-level-subjects,rbac-managing-subjects) already spell the wildcard out in their queries, e.g.(r.resource = '*' OR r.url = '*') AND r.verb = '*'.Suggested fix
Match
resourceandverbas alternatives including the wildcard, the wayapiGroupsare handled after #80 - i.e.ru0.verb IN ['create', '*']andru0.resource IN ['secrets', '*']instead of the equality in the node property map.Two things to decide before doing that, since it widens the report noticeably:
verbs: ['*']on secrets would then matchrisky-get-secrets,risky-list-secretsandrisky-any-verb-secrets, so the same grant appears under three titles. Therisky-any-*rules may want to become the only match for the wildcard case, or the specific rules may want to exclude a wildcard-only grant.risky-exec-podsand therisky-create-rolebinding-*rules AND several selectors together; widening each one multiplies how easily the intersection is satisfied, which is the intent but worth eyeballing against a real cluster's report first.Found while fixing #80.