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.use on 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 is link_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 with Action::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