Access Policies
An identity proves who is connecting. A policy decides what they may reach.
Policies are namespace-scoped and evaluated on every connection. Evaluation is default deny: until a policy grants access, nothing is reachable, and a namespace with no policies refuses everything.
Manage them under Access Policies in the console.
Anatomy
Name — how you will recognize it. It appears verbatim in the denial when a deny refuses
somebody, so a descriptive name is what makes a refusal diagnosable. Operators to prod beats
policy-2.
Effect — allow grants the access described; deny blocks it. A matching deny wins over any
allow, however specific.
Subject — who it applies to:
| Subject | Applies to |
|---|---|
| All members | Every member of the namespace |
| Role | Everyone holding that role, so the grant follows the role rather than the person |
| User | One person |
| API key | An automation connecting on its own identity |
Devices — which devices are covered:
| Selector | Behavior |
|---|---|
| All devices | Every device in the namespace, including ones enrolled later |
| Tags | Devices carrying the selected tags |
Logins — which unix logins are allowed on those devices: a specific list like deploy and
root, or any. This is the difference between reaching a device and reaching it as root.
Source IP — optionally, only accept connections from these addresses or ranges. Empty matches any address. It only ever narrows — it never grants.
Re-authentication — optionally, require the identity to confirm in the browser before connecting. Either every login, or once per window. See Login Approvals.
How policies combine
Every deny is evaluated first. If one matches, the connection is refused and no allow overrides it.
If no deny matches, the allows are evaluated, and one match is enough.
If nothing matches, refused.
A deny whose selector cannot be evaluated fails closed. An allow that cannot be evaluated is treated as a non-match.
That order makes a working policy set predictable in shape: broad allows for what people normally need, then narrow denies to carve out exceptions. Fighting a deny by adding more allows does not work.
A worked example
A team where operators handle the fleet, one contractor touches only lab devices, and a pipeline deploys.
| Name | Effect | Subject | Devices | Logins |
|---|---|---|---|---|
| Operators to fleet | allow | Role: operator | tag production |
deploy |
| Contractor to lab | allow | User: contractor | tag lab |
any |
| No root anywhere | deny | All members | All devices | root |
| Pipeline deploys | allow | API key ci-deploy |
tag production |
deploy |
What this buys you:
- The deny spans the namespace and needs no exception list. It beats all three allows without any of them being rewritten.
- Tagging a new device
productiongrants operators and the pipeline at once. No policy is edited. - Adding somebody to the operator role grants them the fleet. No policy is edited.
ci-botneeds its own allow — theall-membersdeny still applies to it, but noall-membersallow would have covered it.
Starting from scratch
A new namespace has one policy: Owner access, granting the owner every login on every device. Everybody else has nothing.
A reasonable second and third policy:
- An allow for the role your team mostly holds, scoped to a tag, with the logins they actually
need — not
*. - A namespace-wide deny for
root, if root is not something people should be reaching for routinely.
Then add narrower allows as real needs appear, rather than trying to model the whole organization up front.
Where to go next
- Policy Reference — Every field, and what empty means.
- Tags — Selecting devices well.
- User Roles — What a role subject resolves to.