Skip to main content
A denial tells you almost nothing on its own, deliberately: an error that explained which statement refused would tell an attacker what your policies look like. So diagnosis is a process of elimination, and there is an order that finds the answer faster than reading policies top to bottom.

Check scope before adding permissions

1

Check the credential's account

Service account and role tokens belong to an account. Confirm that it matches the requested account. Changing X-Account-Id does not move the identity; use an explicit AssumeRole exchange for another account.A non-owner human must choose an assigned account role. Their personal Workspace policies do not grant ordinary account operations.
2

Check the policy domain

Organization actions (workspace:*, billing:*, quota:*, and audit:*) need organization policies. Account service actions need account policies. A wildcard in the wrong domain is ineffective.A role session uses the role’s own account policies and organization grants, not the source principal’s permissions.
3

Check explicit deny and allow

A matching explicit deny wins in the evaluated domain. Without a matching allow, access is denied. For a user, organization policies include group policies. Service accounts never inherit group policies.
4

Check the resource CRN

Account IAM resources contain the account handle. Workspace resources contain the organization UUID in the path. Global means an empty region slot; it does not mean an empty account slot.Resource CRNs use immutable names for roles, service accounts, and policies. Trust principals bind concrete machine identities to immutable UUIDs. Copy the appropriate returned identity instead of guessing its shape.
5

Check conditions, boundaries, and session policy

A session policy can only narrow permissions. Account boundaries cap account permissions, while Workspace user boundaries cap organization permissions. Neither policy domain can be used to widen the other.Check condition keys, values, and whether a requested resource has the tags the policy expects. A missing value can make an otherwise matching allow ineffective.

An assigned role cannot be assumed

Check both gates. The user needs a direct or group assignment for the target role, and the role’s trust must accept their Workspace user principal CRN. For a machine source, replace the assignment check with iam:AssumeRole on the target role in the source account policy. For cross-account assumption, use the target account’s full role CRN. Trust must identify the source account and immutable source principal correctly. Cross-organization role assumption is not supported.

Organization delegation is denied

Attaching an organization policy requires Workspace permission on the policy and IAM permission to update the target role or service account. Both must be held by the same caller. An account administrator with no organization grants cannot grant those to itself. The same protection applies to sensitive changes to an identity that already carries organization grants. See organization delegation.

Errors that can be misleading

A resource outside your organization or selected account can return 404 to avoid confirming its existence. Check scope as well as the UUID.
The session revoke endpoint checks iam:RevokeSession, then reads the session for its response with iam:GetSTSSession. Grant both. With only the first permission, revocation can succeed before the read is denied.
Managed policy attachment requires both policy and target resource permission. A grant on only policy CRNs or only identity CRNs is incomplete. See IAM attachments and Workspace permissions.
Unknown operators do not match allow statements. For a deny with matching action and resource, an unknown operator fails closed. Check operator spelling when a deny is broader than expected.
A 503 SERVICE_UNAVAILABLE during a credential exchange can indicate a temporary platform dependency failure. Retry with backoff; rotating a valid key does not fix an unavailable exchange.

Collection access and membership reads

A top-level list authorizes a collection CRN, not individual rows. A policy on one role does not grant ListRoles. Relationship lists instead authorize their parent. See listing. The region catalog is public. Token exchange verifies credentials. Humans can read organizations they belong to through membership; machines need workspace:GetOrganization. These checks differ from ordinary account resource permissions.

What the audit log does and does not show

The audit log records successful IAM and Workspace mutations — who attached which policy to whom, who created a role, who removed a user. That is what you want for an access review, and it is queryable through GET /v1/audit-logs.
Authorization denials are not in it. A refused request is recorded in the service’s own logs, with the action and the resource CRN the service actually asked about, but nothing surfaces that back to you through the API.So “what CRN did my policy have to match?” cannot be answered from the audit log. Derive it instead: the shapes are listed under resources, and each service’s permissions page gives its own.
Sign-in events are the exception that does record failures — a failed two-factor enrolment or a removed security key is audited either way, because the failure is the interesting half.

Read event identities

Audit logs have no console page. Use the API to inspect the event identities and retained labels. The event’s crn identifies the audit record itself, in the authenticated organization. Its final segment is the event’s id. actor_crn and resource_crn identify the actor and target as they were at event time. These snapshots do not change when a name changes or a resource is deleted. actor_name, actor_email and resource_name are optional retained labels. Use them for display, not to construct an identity. They can remain available after the actor or target has been deleted; handle absent or null labels. For example, an API response can contain this audit record:
Historical events without identity snapshots return null CRNs. A target that could not be resolved from event-time data also has a null resource_crn, such as a password reset for an unknown email address. When a target UUID is known, it is retained in details.resource_id; do not substitute that UUID or a display label for a missing CRN. An API record without snapshots or retained labels can look like this:
These examples show API JSON. CLI JSON output omits null CRN fields. For an assumed-role actor, actor_crn identifies the role, such as crn:iam::production:role/deployer. The optional details.actor_session_crn, shaped as crn:iam::production:sts-session/<id>, correlates the event with its AssumeRole call.

Next

Permissions

Every action, and the resource each is checked against.

Writing policies

Conditions, operators, and what a missing key does.