version is always 2024-01-01. Anything else is rejected.
Choose the policy scope
Account policies belong to one account and attach to its roles and service accounts. They grant account service actions. Organization policies belong to Workspace and grantworkspace:*, billing:*, quota:*, and audit:*.
Attach them to users or groups, or explicitly delegate them to an account role
or service account.
The document format is shared, but the permission domains are separate.
actions: ["*"] and action exclusions apply only within the policy’s domain.
An account administrator policy cannot grant organization access. An
organization policy cannot grant ordinary account resource access.
The console’s visual editor offers services appropriate to the selected scope.
JSON editing uses the same rules; writing an action from the other scope does
not make it effective.
Statements
string, optional
A label for your own use. It has no effect on evaluation.
allow | deny
required
Lowercase. An explicit
deny beats every allow in the policy domain being evaluated.array
required
Exactly one of the pair. Setting both, or neither, is rejected when the
document is saved.
array
required
Exactly one of the pair, same rule.
array, optional
All of them must hold for the statement to apply.
Actions
Actions areservice:Action, and * is the only wildcard.
Resources
Resources are CRNs, with* as the only wildcard. The
colon and slash layout is compared literally, so the shape has to be right:
Naming by exclusion
not_actions and not_resources cover everything except what they list.
Conditions
A condition compares a context key against values using an operator. Every condition on a statement must hold for it to apply.Operators
What happens when the key is missing
This is the part that decides whether a guardrail works, so it is worth being precise about. The reason is that a deny needs to fire on the request it is guarding against. “Deny unless the request comes from these addresses” has to catch a request with no address — treating the missing key as no match would make the guardrail fail open exactly when it matters.Multi-valued keys
Some context keys are sets rather than single values —basalt:TagKeys is
the set of tag keys a request carries. To compare against one, add a
set_operator:
for_all_valuesholds when every member of the request set satisfies the operator. An absent or empty set holds vacuously — a request carrying no tags is not fenced by a tag-key restriction.for_any_valueholds when at least one member does. An absent or empty set does not hold.
Context keys
The two tag prefixes answer different questions.
ResourceTag fences access to
things already labelled a certain way; RequestTag fences what a caller is
allowed to label something as.
Worked examples
Read-only across a service
Read-only across a service
Confine a team to one environment by tag
Confine a team to one environment by tag
Reaches only resources already tagged
env=staging:This grants nothing on an untagged resource:
equals on a missing
key fails. That is usually what you want — an unlabelled resource is not
quietly in scope.Force new resources to be labelled correctly
Force new resources to be labelled correctly
A caller may create instances only while tagging them
env=staging:Fence an office network, and mean it
Fence an office network, and mean it
ip_address matches — leaves the fence off whenever the key is absent.A guardrail that survives broad grants
A guardrail that survives broad grants
Let a data-plane agent read one certificate's key
Let a data-plane agent read one certificate's key
GetCertificateMaterial is a separate action from reading a certificate,
precisely so this can be granted narrowly. See
certificates.Managed and inline policies
Managed policy
A standalone object with its own CRN. Account policies attach to roles and
service accounts; organization policies also attach to users and groups.
Edit once, and every attachment uses the updated document.
Inline policy
Written directly onto one principal, named rather than identified, and
deleted with it. For a one-off grant that should never be reused or
accidentally attached elsewhere.
iam.basaltic.sh. Organization
policies use the same collection path on workspace.basaltic.sh:
- Console
- API
- CLI
- Go
Open Identity & access → Policies and choose Create Policy
for an account policy. Use Organization → Organization policies
for an organization policy. Policy Document supports visual and JSON
editing. Attach the saved policy from the appropriate identity page.
- Console
- API
- CLI
- Go
Every user, group, service account and role has an Inline Policies
card with Add Inline Policy — a Name and a Policy Document
JSON editor. The name identifies the policy, so it is fixed once saved and
editing one changes only the document.
is_system. They are
maintained by the platform, shared across organizations, and cannot be edited —
attach them or don’t. The console badges them System rather than Custom
and opens them as View Policy, with no save.
Validation
A document is rejected on save, not silently ignored, when:versionis missing or is not2024-01-01statementsis emptyeffectis notallowordeny- a statement sets both
actionsandnot_actions, or neither - a statement sets both
resourcesandnot_resources, or neither - a condition has no
key, or an unrecognisedoperatororset_operator
An unrecognised operator in a stored document — one saved before an
operator was renamed, say — never matches. On an allow statement it is
skipped; on a deny it is treated as a hard deny when the action and resource
match, so a broken guardrail fails closed rather than open.
Next
Permission boundaries
Capping what these policies can ever grant.
Roles and credentials
Session policies scope credentials down the same way.
Resource references
Policy, role and group names are immutable. Relationship fields such aspolicy, role, group and groups[] accept a UUID, a name or a CRN.
The syntax selects the lookup; a missing resource never triggers a second
lookup using another interpretation.
Account policies use crn:iam::<account-handle>:policy/<name>. System account
policies use crn:iam:::policy/<Name>. A bare name prefers a policy in the
selected account, then a system policy. A fully qualified system CRN selects
that namespace even when a custom policy has the same name.
Organization policies use
crn:workspace:::policy/<name>;
system organization policies use crn:workspace:::system-policy/<Name>.
An organization policy lookup does not search account policies, or vice versa.
Roles use crn:iam::<account-handle>:role/<name>. Groups use
crn:workspace:::group/<name>.
Delegated organization policy attachment requests use the policy UUID in
policy_id; see Workspace permissions.
Lists with name and crn filters apply both before pagination. An empty
value is still a filter. A foreign or mismatched CRN returns an empty page.
See resource references for each list’s filters.
