Permissions checked at every gate
link-iam is the one check of who may do what: a principal does an
action on a resource, and it's allowed when the principal's policy says
so and, for another account's resource, that resource's [access] does
too. Every service that decides calls it; none decides for itself.
Policy reference
The Policy Spec describes each principal's grants and limits. Decisions explains why the shared check and policy model work this way.
The check
allows(principal, action, resource, now) answers with a Decision:
allowed, by which grant and whether by the resource's [access], or
refused, and why. It's pure: what it checks is what it's given, the
time included, so it reads no file and calls no service.
Refusal reasons
The decision distinguishes an expired principal, an action outside the resource's kind, a missing grant and another account's resource that does not let the principal in.
- Expired: the principal's end has passed.
- Not of the kind: the action belongs to another resource kind, such as
cloud.useon a box. - Not granted: no grant in the principal's policy allows it.
- Not let in: the policy allows it, but the other account's resource does not name the principal, its account or
*in[access].
Inputs to the check
What a service gives it:
- A
Principal: its id, its account, its end, its policy and its roles, as the service proved and holds them. Its id islink_principal::Principal, the one type every side names a principal with. One whose kind always expires (an API key, a guest) is refused without an end. - An
Action: read from its name,cloud.use, or made withAction::of. - A
Resource: its name and its[access], refused when the[access]names a verb its kind hasn't.
All of a pattern
allows_all(principal, action, on, now) asks whether a grant reaches
every resource of the principal's own account a pattern reaches, all
of a team's folder (bucket:team-r7/*) say. It's held to the pattern,
never to one name of it: a grant of the folder's top, bucket:team-r7/,
or of one folder of it, isn't all of it.
Roles
Roles keeps every role, a Policy Spec by its name, and who holds
each: define keeps or replaces one, give and take hand it to a
principal and back, remove ends it for every holder, and of gives
the policies a principal holds, for Principal::with_roles. allows
reads a principal's own policy first, then each of its roles, and its
decision names the role that allowed it. It's kept as TOML by the
service that holds it.
Limits
allows never reads a policy's [limits]: how much is kept by the
service that meters it. Before it makes a box, a host gives
Limits::admits a Usage (the boxes the principal would then have,
and the new box's CPUs, memory, disk and hours) and refuses the box
when it answers with the limit it would pass.
A child ends with its maker
Made keeps what each principal made, under its one maker: another
principal (a guest, a key, a subagent) or a resource (a box). A service
records each when it's made, and when it removes a principal, removes
what Made::end returns: everything it made and what that made, each
listed before its maker, so none is ever left without one. It's kept
as TOML by the service that holds it.
Docs
- Decisions: Why IAM works the way it does