Skip to content
Operate and secureProduct pagePricing

Identity and access

Identity and access decides who may do what in your organization: people, groups, service accounts and AI agents, with roles on the organization, a folder, a project or a single resource. Every API call from the console, the CLI, an MCP client or Terraform is checked the same way, at the latest version of your access rules, so a removed role stops working on the very next request. Agents can ask for changes but never approve them, and every action leaves an audit entry that says who acted and for whom.

Product overview: Identity and access.

One login works in many organizations: an engineer can belong to Acme and to Pellwyn with one account, and neither organization sees the other’s members. Inside an organization, resources form a tree, organization › folders › projects › resources, and a role granted on a node applies to everything below it.

Every call passes the same steps, in this order:

  1. Authenticate: who the principal is, the agent acting for it if any, and how strongly it signed in.
  2. Kill switch: the organization’s switch that suspends every agent, and suspended agents.
  3. Token scope: what the token allows, such as read-only.
  4. Deny policies: rules that refuse permissions to principals, with conditions.
  5. Principal boundaries, including an agent’s ceiling.
  6. Allow: role bindings on the resource or any parent. For an agent acting for a person, steps 4 to 6 run again for that person and both must allow.
  7. Approval: a rule may hold the call for a person’s approval, with a plan. This is not a denial.
  8. Organization policy, then quota.

Every IAM change increases your organization’s IAM revision in the same transaction, and every check runs at the latest revision; decisions are never cached. Every decision gets an ID, returned in the X-Frazer-Authz-Decision header, which you can explain later even after the rules changed.

  • Principal: a user, a group, a service account, an agent, or a federated identity such as a GitHub Actions job.
  • Role: a named set of permissions. Predefined roles are roles/<service>.<role>; basic roles are roles/owner, roles/admin, roles/developer and roles/viewer.
  • Permission: <service>.<collection>.<verb>, for example kubernetes.clusters.create or approvals.approvals.approve.
  • Binding: a role for a member on a node, with an optional CEL condition and an optional expiry.
  • Approval: a plan waiting for a person, pinned to the exact change and the target’s version.
  • Decision ID: the identifier of one allow or deny, for troubleshooting.
  1. Install the CLI and sign in. frazer login opens your browser; over SSH, frazer login --no-browser prints a code to confirm on another device. The CLI’s key stays in your operating system’s keychain.

    Terminal window
    curl -fsSL frazer.ai/install | sh
    frazer login
  2. Invite people in Organization › IAM › Members with Invite: an email address, a role, and optionally a project. An invitation is single-use, sends a reminder on day 5 and expires after 7 days. The person accepts it with the invited address, once it is verified.

  3. Create a group, such as engineering, in Organization › IAM › Groups and roles, and add the people to it.

  4. Grant the group a role on a project.

    Terminal window
    frazer projects add-iam-policy-binding acme-production \
    --member group:engineering --role roles/developer --dry-run

    The plan lists the bindings gained and lost. Run the command again without --dry-run to apply it.

  5. Require a second factor for everyone in Organization › IAM › Sign-in and SSO. The same page sets the allowed sign-in methods, the session length, token lifetimes and the default role for new members.

  6. Check the result:

    Terminal window
    frazer projects get-iam-policy acme-production
Role Name Can Cannot
Owner roles/owner Everything in the organization, billing included Read secret values
Admin roles/admin All resources, the sign-in policy and SSO; approve agent plans Change owners; read secret values
Developer (default) roles/developer Create, change and delete clusters, data, network and monitoring resources; write secret values; approve agent plans in their projects Members, roles and billing; delete protected resources
Responder roles/responder Read everything in scope; acknowledge and resolve incidents; silences and maintenance windows Change resources
Viewer roles/viewer Read everything in scope Any change
IAM admin roles/iam.admin Members, invitations, groups and roles; given with Owner to whoever creates the organization Grant a role it does not hold
Billing admin roles/billing.admin Invoices, payment methods, spend caps and usage Resources
Servers admin roles/servers.admin Sites, servers, pools, provider accounts and Frazer Link settings Members, billing
Audit viewer roles/audit.viewer Read the audit log, IAM, sessions, tokens and policies Any change

Basic roles never include IAM administration, impersonating a service account, minting tokens or reading secrets; those are always granted on their own. No role reads a secret value, owners included: people write new versions with a reason and see the metadata, and workloads read the values. Reading one in an emergency is a separate, recorded two-person procedure.

New members get Developer. An Owner can make Admin the default, and production projects can stay narrower with project bindings. Every organization keeps at least one owner; removing the last one is refused.

Predefined roles cover each service, such as roles/kubernetes.viewer or roles/dns.recordEditor; frazer iam roles list lists them with their permissions. Custom roles are your own permission sets on an organization (organizations/{organization}/roles/{role}) or a project. Deleting a custom role that is in use is refused unless you force it, and the error lists the bindings.

Method Notes
Email and password At least 15 characters (12 on a change once a second factor is enrolled, 128 at most); checked against known breaches; no composition rules and no forced rotation
Google and GitHub Linked to an existing account only after you sign in to it the usual way and confirm
Passkeys Discoverable credentials with user verification; a passkey counts as two factors
Authenticator app Time-based codes, plus 10 recovery codes; using one replaces the whole set
SSO and SCIM Per-organization OIDC or SAML, verified domains, groups mapped to roles, SCIM deprovisioning; see Single sign-on

Step-up. Sensitive actions need a passkey or second factor from the last 10 minutes: creating a personal access token, changing your factors, deleting an organization, project or cluster, clearing a resource’s protected flag, and approving a change. In the CLI, run frazer login --step-up first. A personal access token never satisfies step-up, so a token can never create a token.

Sessions and tokens.

Client Lifetime
Console session 7 days idle, 30 days at most; your organization can shorten it. The second-factor level lasts until 24 hours after the factor or 1 hour of inactivity, whichever comes first
CLI Access tokens 15 minutes; the refresh token is bound to a key on your machine, 30 days idle, 90 days at most
MCP clients and apps Access tokens 15 minutes; refresh 30 days at most
Personal access token 90 days by default, 5 minutes to 365 days
Workload identity 15 minutes

Protection. After 5 failed sign-ins to an account, every attempt solves a proof-of-work challenge; after 10, the account is locked for 15 minutes for passwords, while passkeys and browsers the account already knows still get in. A sign-in from a new device, country or network sends you an email with a This wasn’t me link, which signs out every session and pauses every token. Your sessions, connected apps and agents, and personal access tokens are listed under your avatar, in Account, where you can revoke each one.

Groups belong to the organization and nest up to 5 levels deep. A membership can carry an expiry, with reminders 7 days and 1 day before it ends. A membership’s source is manual, SCIM, or a claim from your identity provider; SCIM and claim memberships are changed only in the identity provider. To map an identity provider group to a role, bind the role to the group like any other member; there is no separate mapping table.

Adding a member to a group grants them the group’s roles, so it follows the same rule as any grant: you cannot grant what you do not hold yourself. Removing a member, or a nested group, takes effect on the next request.

Restrict access with conditions and deny policies

Section titled “Restrict access with conditions and deny policies”

A binding can carry a condition in CEL, evaluated on every request. Conditions read the request (request.time, request.auth.aal, request.auth.amr, request.auth.auth_age, request.origin.ip, request.origin.network), the resource (resource.name, resource.type, resource.service, resource.matchTag(), resource.hasTagKey()) and the principal (principal.kind). Conditions read tags, never labels. An error while evaluating a condition fails closed.

Deny policies sit on the organization, a folder or a project and win over any allow. They name denied principals and exceptions, denied permissions with wildcards such as kubernetes.* or *.delete, and a condition. Every permission can be denied.

Deny policy on the organization
denied permissions: *.delete
condition:
principal.kind == "agent"
&& resource.matchTag("frazer.ai/env", "production")

Principal boundaries cap what a principal can ever do, whatever it is granted; an agent’s ceiling is a boundary. A resource with protected set cannot be deleted by anyone until a person clears the flag with step-up.

Service accounts live in a project. Keys are off by default through an organization policy; where you allow them, they expire within 90 days. Instead, let CI sign in with its own identity: with workload identity federation, a GitHub Actions job exchanges its OIDC token for a 15-minute Frazer token, and a condition on the token’s claims decides which jobs may.

Workload identity condition
repository == "acme/platform-envs" && ref == "refs/heads/main"

Bind the role to the federated principal or principal set directly; no service-account impersonation is needed. Attaching a service account to a workload (actAs) and impersonating it to get a token are separate permissions, and an impersonation chain is at most 3 long. Frazer clusters use workload identity too: a cluster’s service-account token is trusted because Frazer registered the cluster’s issuer when it created the cluster.

Create a service account in Organization › IAM › Service accounts, with frazer iam service-accounts create, or as frazer_iam_service_account with the Frazer provider for Terraform and OpenTofu.

A personal access token starts with frz_pat_, is bound to one organization and to scopes (<service>:read, <service>:write or cloud-platform), and must expire: 90 days by default, at most 365 days, and your organization can cap it or turn tokens off. Create one in Account › Personal access tokens and CLI tokens, or with frazer identity personal-access-tokens create; both need a fresh step-up. A token can carry up to 20 allowed networks, and a call from anywhere else is refused before any other check. Frazer emails you 7 days and 1 day before a token expires, and a token found in a public GitHub repository is revoked at once. Prefer workload identity for CI.

An MCP client connects to https://mcp.frazer.ai with OAuth. On the consent page you pick one organization and see the client’s name and host, the scopes in words, and the refresh lifetime; read-only is on by default, and write scopes are opt-in per grant. The resulting token works only in that organization and only within your own rights.

  • A write tool does not write. It returns a plan, and an approval waits for a person; see Approve changes.
  • Organization › IAM › Agents and MCP lists every connected agent with its ceiling, toolsets and approval policy. Suspend all agents is a kill switch checked on every request, so every agent token stops working on its next call.
  • In the audit log an agent’s action names the agent, the person it acted for, the client and the approval.

One approvals engine handles every plan → approve → apply in Frazer: agent writes, IAM changes made over MCP, quota increases, production changes, and other actions that need a second person.

How a held call works. When a rule holds a call, Frazer runs it as a plan, creates an approval, and answers FAILED_PRECONDITION APPROVAL_REQUIRED with the approval’s name and its page, https://console.frazer.ai/approvals/<name>. Nothing has changed yet. As soon as enough people approve, Frazer applies exactly that plan, once, as the person or agent that asked, after checking their permissions again.

Who may vote. People only, from the console or the Frazer CLI, with a passkey or second factor from the last 10 minutes. Agents, service accounts, MCP and SDK tokens, Terraform and personal access tokens can ask, never vote. The requester never counts toward a four-eyes quorum, and neither does the person an agent acted for. Any eligible rejection ends the approval.

Two clocks. A pending approval expires after 24 hours by default (7 days for quota requests). Once approved, the change must start within 15 minutes of the last vote. If the target changes in between, the approval is invalidated and the change is requested again.

Terminal window
# Approve from the terminal
frazer login --step-up
frazer approvals list --can-decide
frazer approvals approve apr_01JA3KQ7
# The requester's side: follow it until it is applied
frazer approvals wait apr_01JA3KQ7

Built-in rules cannot be turned off: any write through MCP (four eyes in production; outside production the person the agent acts for may confirm it), IAM changes through MCP (always four eyes), and quota requests above the organization’s limit or the tier ceiling.

Your approval policy. Each organization and each project has one approval policy; a project inherits its organization’s:

Field Meaning Default
production Four eyes on every approval in the project Off
required_approvals Votes needed 1, or 2 in production
approvers People or groups admitted, narrowing who holds the approve permission Everyone with approvals.approvals.approve
hold_people Hold people’s own calls too: DESTRUCTIVE, IAM None
pending_lifetime How long a pending approval waits 24 hours
escalate_after, escalation_contacts When and to whom to escalate 1 hour; the organization’s owners

Strengthening a policy applies at once. Weakening it, for example turning off production or lowering required_approvals, is itself held for approval with four eyes. By default no direct call by a person is held, so Terraform and GitOps pipelines keep their pull-request review as the approval; opt in per project with hold_people.

Records. Every vote, decision, expiry and apply is in the audit log, and the record of the applied change names the requester and every approver. Each decided approval is also a signed record; check it with frazer approvals verify, against the keys from frazer approvals attestation-keys export.

Just-in-time access and break-glass. An entitlement lets named people request a role on a scope for at most 8 hours, with a justification and an approver who is never the requester and never an agent; the grant expires on its own. For an emergency, a person who holds approvals.approvals.breakGlass applies their own pending change at once with a justification and a hardware security key; owners are alerted immediately, and a second person must review it within 24 hours or it escalates.

A denied call returns PERMISSION_DENIED from iam.frazer.ai with the step that refused it (deniedBy: kill switch, token scope, deny, boundary, allow, condition or session assurance), the permission and resource, up to three of the smallest roles that would allow it (rolesGranting), and a decision ID. The message ends with “(or it might not exist)” because a missing and a forbidden resource look the same.

Explain it with frazer iam decisions troubleshoot-access, the MCP tool iam_troubleshoot_access, or the console page in the error’s help link, console.frazer.ai/iam/troubleshoot?decision=<id>. The answer replays the decision at the revision it was made, shows the outcome now, and lists what changed in between:

  • For yourself you see the outcome, the step and the roles that would grant access, and a Request access link, with nothing that names another member or a rule.
  • For an IAM viewer the answer adds the deny rule or binding that decided, the group path, and who could grant the role. Where you may grant it yourself, Grant is offered.

Decisions are kept 90 days. Every denial and approval reason, with its fix, is in the errors reference.

  1. Verify your domain in Organization › IAM › Sign-in and SSO by publishing the DNS TXT record _frazer-verify.<domain> it shows. The same verification lets the organization create DNS zones for the domain.

  2. Add an SSO connection: OIDC with the issuer, client ID and client secret, or SAML, which Frazer converts to OIDC so no XML signature code runs in the core.

  3. Enforce it. Sign-in is identity-first: people with an email in your domain are sent to your identity provider. They can no longer use a password for your organization, and keep their access to other organizations.

  4. Choose how accounts are created: just-in-time on first sign-in with groups mapped to roles, or SCIM, which is then the source of truth. SCIM deprovisioning removes the membership and revokes that organization’s sessions and tokens.

Keep a break-glass principal: break-glass accounts are exempt from SSO enforcement, use hardware-key MFA, and survive an outage of your identity provider.

Who can change access. Granting roles needs the right to change a node’s IAM policy, and you can never grant a role, or add a member to a group, with permissions you do not hold yourself. IAM writes through MCP are always held for approval. A change that would leave nobody able to change the organization’s IAM policy is refused.

Audit log. Every action records the actor, the person an agent acted for, the client, the authentication method, the approval and the result.

Log Records Kept
ADMIN_ACTIVITY Every change, always on 400 days
SYSTEM_EVENT Changes Frazer makes on its own, such as repairs and upgrades 400 days
DATA_ACCESS Secret metadata reads, kubeconfig and token mints, log queries, exports; opt-in per service 30 days, configurable
POLICY_DENIED Every refused call: IAM, deny, organization policy, quota, agent ceiling 30 days
STAFF_ACCESS Every time Frazer staff touch your data or resources, with a justification, in your own log within 1 minute 400 days

Every IAM change’s record carries the bindings and memberships added and removed. A write-once copy of the audit log is kept in object storage. Read it in Organization › Settings › Audit log or Project › Settings › Audit log, filtered by person, service account or agent, and export it.

Item Default
Role bindings per resource node 10,000
Role bindings per organization 1,000,000
Group nesting depth 5
Groups per organization 10,000
Direct members per group 100,000
Groups a principal belongs to, transitively 1,000
Condition size 2 KB, estimated cost 1,000
Conditional bindings with the same role and principal on one node 20
Deny rules per node 500
Boundaries per principal set 10
Custom roles per organization; permissions per custom role 1,000; 3,000
IAM writes per organization 20 per second sustained
Organizations you create 3 per 24 hours; 10 owned
Open invitations per organization 50
Invitations sent per day 20 for organizations younger than 7 days, then 100
Personal access tokens created per user 20 a day
Pending approvals per requester 50
Plan size held for approval 256 KiB

The IAM limits are soft limits per organization: a write that would pass one is refused, and the error names the limit.

Identity and access has no line of its own on the price list. Every line, with the estimator:

Identity and accessOn your serversOn the Frazer fleet
PriceIncluded: SSO (OIDC, SAML), SCIM, MFA, roles and audit logsIncluded in every organization

Every line, with the estimator: pricing.

Symptom Cause Fix
PERMISSION_DENIED right after someone granted you a role The grant went to another project, folder or principal, or a deny policy or boundary still refuses it Explain the decision ID; the replay shows which step refused
STEP_UP_REQUIRED in the CLI Your last second factor is older than 10 minutes, or you used a personal access token Run frazer login --step-up and retry
An MCP client lists no write tools The grant is read-only, or the token is for another organization Reconnect the client and turn on write scopes for this organization
An agent’s change returns APPROVAL_REQUIRED Writes through MCP are held for a person Approve it on the approval page or with frazer approvals approve
You cannot approve your own agent’s production change Production needs four eyes; the person an agent acts for does not count Ask another approver
An approval failed with PLAN_CHANGED The target changed after the plan was made Request the change again
You cannot remove someone from a group The membership comes from SCIM or your identity provider Remove them in the identity provider
A new member cannot accept an invitation The invitation expired after 7 days, or their address is not verified or does not match Resend the invitation, or have them verify the invited address
Someone you removed still appears in a project They hold a role there through another group or a direct binding Check the project’s policy with frazer projects get-iam-policy

CLI

CommandWhat it does
frazer loginSign the CLI in through your browser; with --no-browser, confirm a code on another device instead.
frazer login --step-upConfirm with a passkey or second factor, good for 10 minutes, before you approve or create a token.
frazer logoutRevoke the CLI's grant and delete its key.
frazer auth print-access-tokenPrint an access token for the active configuration.
frazer auth listList the CLI's configurations and their grants.
frazer identity personal-access-tokens createCreate a personal access token; needs a fresh step-up.
frazer projects get-iam-policyShow a project's role bindings.
frazer projects add-iam-policy-bindingGrant a role to a member on a project.
frazer projects remove-iam-policy-bindingRemove a member's role on a project.
frazer iam groups createCreate a group in the organization.
frazer iam memberships createAdd a person, a service account or a group to a group.
frazer iam service-accounts createCreate a service account in a project.
frazer iam roles listList predefined and custom roles with their permissions.
frazer iam decisions troubleshoot-accessExplain a decision by its ID, or a principal's access to a resource.
frazer approvals listList approvals; with --can-decide, only the ones you may decide.
frazer approvals getShow an approval with its plan, votes and state.
frazer approvals approveVote to approve; needs a fresh step-up.
frazer approvals rejectReject with a reason; one rejection ends the approval.
frazer approvals cancelCancel an approval you requested.
frazer approvals waitFollow an approval until it is applied or ends.
frazer approvals verifyCheck a decided approval's signed record.
frazer approvals attestation-keys exportExport the public keys that sign approval records.

All of them: CLI reference.

Terraform and OpenTofu

ResourceWhat it manages
frazer_iam_service_accountA service account in a project.

All of them: Terraform and OpenTofu reference.

MCP tools

ToolWhat it does
iam_troubleshoot_accessExplain a decision by its ID, or a principal's access to a resource.
approvals_listList approvals, such as the ones an agent's writes are waiting on.
approvals_getGet an approval and, once applied, the result of the change.
approvals_begin_batchStart a batch, so up to 100 held writes become one approval.
approvals_submit_batchSubmit a batch of held writes for one approval.

All of them: MCP tools reference.

Events

Event typeWhen it is sent
frazer.member.added.v1A person joined the organization or a project.
frazer.member.removed.v1A person was removed from the organization or a project.

All of them: Events reference.

Errors

ReasonWhat it meansHow to fix it
LAST_IAM_ADMINThe change would leave the organization with nobody who can change its IAM policy.Grant the role to another person first.
GROUP_CYCLEThe group would contain itself through its members.Remove the nesting that closes the loop.
GROUP_DEPTH_EXCEEDEDGroups would nest more than 5 levels deep.Flatten the group tree.
MEMBERSHIP_MANAGED_EXTERNALLYThe membership comes from your identity provider through SCIM or a sign-in claim.Change it in your identity provider.
ETAG_REQUIREDA full policy replace was sent without the policy's etag.Read the policy, edit it and send it back with its etag, or add and remove single bindings instead.
LIMIT_EXCEEDEDAn IAM limit, such as bindings per resource, would be passed.Use groups instead of many direct bindings, or ask for the limit to be raised.
APPROVER_NOT_ALLOWEDOnly people can vote, and the approval's approvers must include you.Ask an eligible approver; agents, service accounts and tokens never vote.
APPROVER_CLIENT_NOT_ALLOWEDVotes come only from the console or the Frazer CLI.Vote in the console or with frazer approvals approve.
SELF_APPROVALYou requested the change, or an agent asked for you, and the rule needs another person.Ask a colleague who is an approver.
APPLY_DEADLINE_EXCEEDEDThe approved change did not start within 15 minutes of the last vote.Request the change again.
PLAN_TOO_LARGEPlans over 256 KiB are not held for approval.Split the change into smaller ones.
BREAK_GLASS_NOT_ALLOWEDBreak-glass is only for a change you asked for directly, not through MCP, an agent or a workload.Make the request yourself from the console or the CLI.
HARDWARE_KEY_REQUIREDBreak-glass needs a step-up with a hardware security key.Step up with a device-bound security key.

All of them: Errors reference.