# trust (/docs/reference/api/trust)

> A trust lets one named identity, usually from another tenant, temporarily assume a role in this tenant.



A trust lets one named identity, usually from another tenant, temporarily assume a role in this tenant. Identities
belong to one tenant and parent membership grants nothing in child tenants, so a support engineer or an automation
that must act inside a customer's tenant needs a controlled way in. A trust gives exactly that person short-lived,
audited access to one role, instead of a second account or standing access. It works like a role trust policy in
cloud IAM.

## How role assumption works [#how-role-assumption-works]

1. A root administrator creates a trust that names the source tenant and identity, the target role, and optional
   safeguards.
2. The source identity calls [`roles.assume`](/docs/reference/api/roles#assume) with the trust's ID (and the
   external ID, when the trust requires one). The source also needs `iam:roles:assume` on the role's ID in its own
   tenant, so its own administrators decide who may use trusts at all.
3. The call returns a short-lived role session token. Requests made with it act in the target tenant with the
   role's permissions, never more than the trust's `ceiling`.

The safeguards are checked on every assumption:

* **`requireMfa`** (default `true`): the source session must be MFA-verified.
* **`externalId`**: a shared value the caller must present, which protects against a confused deputy (someone
  tricking a trusted service into assuming the role on their behalf). Only its SHA-256 hash is stored.
* **`ceiling`**: a policy document that caps what role sessions may do, whatever the role grants. Without one, the
  role's own permissions are the limit.

A role session cannot assume another role, and a "view as" (impersonation) session cannot assume roles at all.
Role sessions stop working at their next use once the trust is revoked. The protected Owner role can never be the
target of a trust.

## Trust options and session attributes [#trust-options-and-session-attributes]

Identity trusts also carry typed knobs, set at creation or later with [`update`](#update) (root only):

* **`maxSessionSeconds`**: the longest role session the trust issues, from 60 up to the deployment's
  `sts.maxRoleSessionSeconds`; 3600 when unset.
* **`passSourceAttributes`**: whether the source identity's attributes reach policies as `principal.{attribute}` in
  role sessions. New cross-tenant trusts default to `false`, so another tenant's attribute values cannot satisfy
  this tenant's conditions; same-tenant trusts default to `true`, and trusts created before the option existed keep
  passing attributes until you change them. [`analysis.findings`](/docs/reference/api/analysis#findings) reports
  cross-tenant trusts that still pass them.
* **`allowedTagKeys`**: the session tag keys a caller may set on `roles.assume` (at most 50, or `['*']` for any);
  none by default. Tags reach policies as `principal.sessionTags.{key}`.
* **`sourceIdentityMode`**: whether a caller may (`optional`), must (`required`), or may not (`forbidden`, the
  default) name a source identity, which policies read as `principal.sourceIdentity`.
* **`description`**: up to 512 characters for the people reviewing the trust.

Tags and a source identity are closed by default because a caller chooses their values, and both can satisfy policy
conditions. Revocation is covered by [`revokeSessions`](#revokesessions), which ends sessions issued before a point in
time without revoking the trust.

## Web-identity trusts [#web-identity-trusts]

A trust of kind `web-identity` admits tokens from an external OpenID Connect provider (see
[`oidcProviders`](/docs/reference/api/oidc-providers)) instead of a named identity, for CI jobs and workloads that
exchange their platform token through
[`sts.assumeRoleWithWebIdentity`](/docs/reference/api/sts#assumerolewithwebidentity). Unlike identity trusts, they are
tenant-managed: an administrator with `iam:trust:create` on the role creates one, and only that administrator's grant
authority (or root) may change or revoke it. Each one names:

* the provider (`providerId`) and an active service account of the tenant (`serviceAccountId`) that sessions act as;
* `conditions` on the verified token's claims, written in the policy condition grammar over `token.{claim}` keys
  (nested claims are joined with dots, such as `token.kubernetes.io.namespace`). They must pin `token.sub` with
  `StringEquals` or `StringLike` without a leading wildcard, or creation fails with `WEAK_TRUST_CONDITIONS`;
* optionally `tagClaims` (session tag key to claim name, at most 10), `sourceIdentityClaim`, `maxSessionSeconds`,
  `ceiling`, `passSourceAttributes` (default `true`), and `description`.

Sessions are bounded by the role, the trust's ceiling, and the grant authorities of the trust's and the provider's
creators; revoking either authority, disabling the provider or the service account, or revoking the trust ends them.
Web identity must be enabled on the deployment (`sts.webIdentity.enabled`) to create, change, or revoke one.

| Method                                        | What it does                                                                                                                                                                                                | Access     |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| [`create`](#create)                           | Creates a trust that lets one source identity assume one role of this tenant.                                                                                                                               | Credential |
| [`evaluateWebIdentity`](#evaluatewebidentity) | Checks what a web-identity trust would conclude about an external token, without issuing anything.                                                                                                          | Credential |
| [`list`](#list)                               | Lists the trusts that target this tenant's roles.                                                                                                                                                           | Credential |
| [`revoke`](#revoke)                           | Revokes a trust so its source can no longer assume the role, and ends the role sessions already issued under it.                                                                                            | Credential |
| [`revokeSessions`](#revokesessions)           | Ends the role sessions issued under one trust before a point in time, without revoking the trust.                                                                                                           | Credential |
| [`update`](#update)                           | Changes a trust's safeguards and options, such as its MFA requirement, ceiling, session length, attribute passing, tag keys, source identity mode, or a web-identity trust's conditions and claim mappings. | Credential |

## create [#create]

Creates a trust that lets one source identity assume one role of this tenant.

**HTTP:** `POST /api/iam/trust/create` (requires a credential) · **Browser client:** `client.trust.create()`

* **Permission:** `iam:trust:create` on the role (`iam/{roleId}`); root administrators only, with recent
  authentication.
* **Audited as:** `iam:trust:create`.
* **Errors:** `ACCESS_DENIED` for anyone but a root administrator; `RECENT_AUTH_REQUIRED` without recent
  authentication; `PROTECTED_RESOURCE` when the role is the Owner role; `NOT_FOUND` when the role is not in this
  tenant or the source identity is not in `sourceTenantId`; `INVALID_POLICY`, `INVALID_ACTION`, or
  `INVALID_RESOURCE_TYPE` for a `ceiling` storage would reject; `INVARIANT_VIOLATION` when the trust would newly
  break an enforced access invariant.

Trusts are platform-controlled because they cross tenant boundaries: a tenant administrator cannot open their
tenant to an outside identity on their own. Keep `requireMfa` on; [`analysis.findings`](/docs/reference/api/analysis#findings)
reports trusts without it. Give each trust the narrowest ceiling the task needs.

With `kind: 'web-identity'` the call creates a [web-identity trust](#web-identity-trusts) instead: `iam:trust:create`
on the role without root, recent authentication, and `sts.webIdentity.enabled` (else `FEATURE_DISABLED`). It fails
with `WEAK_TRUST_CONDITIONS` when the conditions do not pin `token.sub`, `INVALID_IDENTITY` when the service account
is not an active service account, and `INVALID_INPUT` for identity-trust fields such as `sourceTenantId` or
`requireMfa`. Both kinds return the public trust, which reports `requiresExternalId` instead of the stored hash.

```ts
const trust = await iam.api.trust.create(rootCredential, {
  tenantId: customerTenantId,
  sourceTenantId: rootTenantId,
  sourceIdentityId: supportEngineerId,
  roleId: supportRoleId,
  externalId: 'ticket-routing-7f3a',
  ceiling: {
    version: 1,
    statements: [{ effect: 'allow', actions: ['iam:identities:read', 'iam:audit:read'], resources: ['*'] }],
  },
});
```

```ts title="Signature"
iam.api.trust.create(
  credential: CredentialInput,
  input: TrustCreateInput,
): Promise<PublicTrust>
```

## evaluateWebIdentity [#evaluatewebidentity]

Checks what a web-identity trust would conclude about an external token, without issuing anything.

**HTTP:** `POST /api/iam/trust/evaluateWebIdentity` (requires a credential) · **Browser client:** `client.trust.evaluateWebIdentity()`

* **Permission:** `iam:trust:read` on the trust, and `sts.webIdentity.enabled`.
* **Audited as:** `iam:trust:read`.
* **Errors:** `FEATURE_DISABLED` when web identity is off; `INVALID_INPUT` for a trust that is not a web-identity
  trust; `NOT_FOUND`.

The public exchange answers every refusal with the same `WEB_IDENTITY_REJECTED`, so callers cannot probe which
trusts exist. This dry run is how administrators find out why a token is refused: it returns `verified`, the
`reason` the exchange would give (a verification failure such as `audience`, `expired`, or `unknown-key`, or
`conditions` or `source-identity`), the verified registered claims, each failing condition as `Operator:key`, and
the session tags and source identity the claim mappings would produce. No replay record is written, so the token
stays redeemable.

```ts
const result = await iam.api.trust.evaluateWebIdentity(credential, { tenantId, trustId, webIdentityToken });
if (result.conditions && !result.conditions.matched) console.log(result.conditions.failed); // ['StringLike:token.sub']
```

```ts title="Signature"
iam.api.trust.evaluateWebIdentity(
  credential: CredentialInput,
  input: { tenantId: string; trustId: string; webIdentityToken: string },
): Promise<WebIdentityEvaluation>
```

## list [#list]

Lists the trusts that target this tenant's roles.

**HTTP:** `POST /api/iam/trust/list` (requires a credential) · **Browser client:** `client.trust.list()`

* **Permission:** `iam:trust:read` on the tenant.
* **Audited as:** `iam:trust:read`.

Revoked trusts are left out unless `includeRevoked` is `true`. External ID hashes are never returned; instead,
`requiresExternalId` tells you whether callers must present one. Tenant administrators can use this to see who
outside the tenant may assume which role. Trusts of kind `web-identity`, which admit tokens from an external OpenID
Connect provider, appear here too.

```ts title="Signature"
iam.api.trust.list(
  credential: CredentialInput,
  input: { tenantId: string; includeRevoked?: boolean },
): Promise<PublicTrust[]>
```

## revoke [#revoke]

Revokes a trust so its source can no longer assume the role, and ends the role sessions already issued under it.

**HTTP:** `POST /api/iam/trust/revoke` (requires a credential) · **Browser client:** `client.trust.revoke()`

* **Permission:** `iam:trust:revoke` on the trust (`iam/{trustId}`); root administrators only, with recent
  authentication.
* **Audited as:** `iam:trust:revoke`.
* **Errors:** `ACCESS_DENIED` for anyone but a root administrator; `RECENT_AUTH_REQUIRED` without recent
  authentication; `NOT_FOUND` when the trust is not in this tenant.

Existing role sessions under the trust are refused at their next use. The record is kept with `revoked: true`, so
it still appears with `includeRevoked` and in the audit history. Revoking an already revoked trust succeeds.

The trust's live role sessions are also deleted in the same transaction, so they disappear from
[`roles.listSessions`](/docs/reference/api/roles#listsessions) at once. A web-identity trust is revoked by the
administrator whose authority created it (or root) rather than root only, and needs `sts.webIdentity.enabled`
(`FEATURE_DISABLED` otherwise).

```ts title="Signature"
iam.api.trust.revoke(
  credential: CredentialInput,
  input: { tenantId: string; trustId: string },
): Promise<PublicTrust>
```

## revokeSessions [#revokesessions]

Ends the role sessions issued under one trust before a point in time, without revoking the trust.

**HTTP:** `POST /api/iam/trust/revokeSessions` (requires a credential) · **Browser client:** `client.trust.revokeSessions()`

* **Permission:** `iam:roles:revoke-sessions` on the trust's role (`iam/{roleId}`), with recent authentication. It
  is not root-only, so the target tenant's administrators can end sessions under a platform-controlled trust.
* **Audited as:** `iam:roles:revoke-sessions` and `role:sessions-revoked` (with the watermark and the number of
  sessions deleted).
* **Errors:** `INVALID_INPUT` when `before` is not a whole number of milliseconds, is negative, or lies in the future;
  `NOT_FOUND` when the trust is not in this tenant; `RECENT_AUTH_REQUIRED`; `ACCESS_DENIED`.

`before` defaults to now, which ends every session issued so far. The trust's `sessionsRevokedBefore` watermark only
moves forward, so older sessions are refused at their next use and the matching rows are deleted at once, while new
assumptions keep working. Session JWTs that other services verify offline stay valid there until they expire; those
services can check [`sts.getCallerIdentity`](/docs/reference/api/sts#getcalleridentity) for an online answer.

```ts
const { revoked } = await iam.api.trust.revokeSessions(credential, { tenantId, trustId });
```

```ts title="Signature"
iam.api.trust.revokeSessions(
  credential: CredentialInput,
  input: TrustRevokeSessionsInput,
): Promise<{ trustId: string; sessionsRevokedBefore: number; revoked: number }>
```

## update [#update]

Changes a trust's safeguards and options, such as its MFA requirement, ceiling, session length, attribute passing, tag keys, source identity mode, or a web-identity trust's conditions and claim mappings.

**HTTP:** `POST /api/iam/trust/update` (requires a credential) · **Browser client:** `client.trust.update()`

* **Permission:** `iam:trust:update` on the trust, with recent authentication. Identity trusts need a root
  administrator; web-identity trusts need the grant authority that created them (or root).
* **Audited as:** `iam:trust:update`.
* **Errors:** `ACCESS_DENIED` for anyone else; `CONFLICT` (409) for a revoked trust; `INVALID_INPUT` when nothing
  changes or a field belongs to the other kind of trust (`conditions`, `tagClaims`, or `sourceIdentityClaim` on an
  identity trust; `requireMfa`, `allowedTagKeys`, or `sourceIdentityMode` on a web-identity trust);
  `WEAK_TRUST_CONDITIONS` for conditions that do not pin `token.sub`; `FEATURE_DISABLED` for a web-identity trust
  while web identity is off; `RECENT_AUTH_REQUIRED`; `NOT_FOUND`.

Only the fields you pass change, and `null` returns `ceiling`, `maxSessionSeconds`, `allowedTagKeys`,
`description`, `tagClaims`, or `sourceIdentityClaim` to its default. Tightening what the trust admits (its tag keys,
source identity mode, conditions, claim mappings, or a shorter `maxSessionSeconds`) also moves the trust's
`sessionsRevokedBefore` watermark to now, so sessions issued under the looser rules end at their next use. Use it
to turn off `passSourceAttributes` on older cross-tenant trusts.

```ts
await iam.api.trust.update(rootCredential, { tenantId, trustId, passSourceAttributes: false, maxSessionSeconds: 900 });
```

```ts title="Signature"
iam.api.trust.update(
  credential: CredentialInput,
  input: TrustUpdateInput,
): Promise<PublicTrust>
```
