Taxonomy¶
The grammar of a grant name. What a name is checked against is policy vocabulary.
Grammar¶
A grant is <scope>:<thing>:<role>: three lowercase segments, read as role, on thing, in scope.
| Segment | Is | Examples |
|---|---|---|
scope |
an environment, a tenant id, or all |
core, prod, devel, C0north, all |
thing |
a subsystem, project or application | k8s, argocd, grafana, shop, sluis |
role |
a role from that thing's ladder | viewer, operator, admin, deployer, editor |
Two families of two segments are not grants and are exempt from this page: rung:<name> carries a session lifetime, and emp:<slug> is a person.
Any other shape loads, and the start logs the WARN some group names are neither a grant nor an identity.
Rules¶
| Rule | Behaviour |
|---|---|
all |
Use it for a thing that exists once per installation, such as all:grafana:viewer. A per-environment thing is devel:k8s:viewer and prod:k8s:viewer, never all:k8s:viewer. |
| Sensitive scope | A declared vocabulary marks a scope sensitive, typically core and prod. A mapping wildcard never expands into it. A concrete name such as core:k8s:admin is unaffected. |
| Coverage | A role may not cover more scopes than a role it implies. admin on every scope implying user on devel is refused at load. |
Inheritance¶
A ladder is explicit implies: admin: [operator]. Holding S:T:admin holds every role it implies, transitively, on the same S:T.
The expansion happens once at evaluation.
There is no scope inheritance: all:x:admin never implies devel:x:admin.
Per-role scopes¶
A role value user: { scopes: [devel] } narrows the role inside its thing's scopes.
core:ssh:user is refused when user excludes core. Syntax: per-role scopes.
Mapping wildcards¶
* is allowed in the scope or thing position of a groups key only.
It is refused in requires, GitHub bindings, a Slack channel's from, claims, lifetimes and the role position.
*:k8s:admin and devel:*:viewer are valid. devel:k8s:* and *:*:* are not.
Without a declared vocabulary, * is refused.
A wildcard key stands for every concrete (scope, thing) that declares the scope and the role, where the role allows the scope. Sensitive scopes are excluded.
Whoever matches the key is in all those groups, unioned with matching concrete keys, and then inheritance applies.
Later stages see only concrete names.
A wildcard that expands to nothing fails the load:
| Key | Reason |
|---|---|
prod:*:viewer, prod sensitive |
names a sensitive scope directly; write the concrete group |
devel:*:admins, no thing has admins |
expands to no group |
*:k8s:viewer, every k8s scope sensitive |
expands to no group |
core:*:user, every user role excludes core |
expands to no group |
Examples¶
| Name | Reads as |
|---|---|
prod:k8s:admin |
admin of prod's Kubernetes |
all:sluis:operator |
operator of sluis, installation-wide |
C0north:sluis:viewer |
viewer of one directory only |
C0north:sluis:operator |
operator of one directory and the GitHub organisations and Slack workspaces it owns |
*:k8s:admin (groups key only) |
admin of every non-sensitive environment's Kubernetes |
devel:*:viewer (groups key only) |
viewer of everything devel has with a viewer role |
devel:ssh:user |
user of devel's ssh, a role scoped to devel |
rung:sre |
a session lifetime, not a grant |
emp:alice |
a person, not a grant |
Anti-patterns¶
| Anti-pattern | Fix |
|---|---|
A name that is not <scope>:<thing>:<role>, rung: or emp: |
Use the grammar. |
A provider's vocabulary in the name, such as cluster-prod:cluster:admin |
Name the thing: prod:k8s:admin. See naming. |
An application role under a tier scope, such as cluster-prod:roster:operator |
Give the application its own thing. |
A per-environment thing named with all, or a role on all expected to reach an environment |
Name the environment. |
A wildcard outside a groups key |
Write one concrete name. |
A role wildcard, S:T:* or *:*:* |
State the role. |