# ssh (/docs/reference/api/ssh)

> The SSH certificate authority makes Better IAM the authority your servers trust.



The SSH certificate authority makes Better IAM the authority your servers trust. People, service accounts and agents
get short-lived OpenSSH user certificates for exactly the hosts and local accounts their policies allow. Hosts get
certificates their clients verify. Revoked certificates are refused through a key revocation list (KRL) that hosts
fetch every few minutes. The group exists when the deployment sets the `ssh` option; otherwise every method fails with
`FEATURE_DISABLED`.

## How access is decided [#how-access-is-decided]

Each enrolled host lists the local accounts people may use. Every pair of host and login is a resource,
`ssh-login/{host}/{login}`, whose attributes are the host's labels plus `host` and `login`. Getting a certificate is
the `ssh:login` decision on those resources, so conditions, boundaries, just-in-time roles and delegation scopes all
apply. Forwarding is decided on `ssh-host/{host}` (`ssh:port-forward`, `ssh:agent-forward`, `ssh:x11-forward`). A
certificate allows a kind of forwarding only when every host it names allows it.

A certificate carries one principal per allowed pair, `{login}@{host}`. Each login's principals file on a host holds
only that host's own principal, so a certificate never opens a host or login it was not issued for.

Administration uses `iam:ssh:manage` and `iam:ssh:read` on `iam/ssh/...`. Hosts call the public methods with their join
token or renewal token. The guide is
[SSH access](https://github.com/Better-IAM/better-iam/blob/main/docs/ssh-access.md).

| Method                                            | What it does                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | Access     |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| [`activateAuthority`](#activateauthority)         | Makes a pending authority the signing key. The key it replaces stays trusted as `previous`, so certificates it issued keep working until they expire.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Credential |
| [`clientTrust`](#clienttrust)                     | What a member's SSH client needs: known\_hosts lines trusting the host authority for the organization's enrolled names (or its patterns), `@revoked` lines for host keys to refuse, and the host revocation list (base64 KRL) for `RevokedHostKeys`. Needs a session of the organization.                                                                                                                                                                                                                                                                                                                                                                                              | Credential |
| [`createHost`](#createhost)                       | Registers a server: its `name` (unique, lowercase letters, digits, `.` and `-`, never changes), `addresses` for the host certificate, `logins` people may be granted, and `labels` that policies read as `resource.{label}`. Returns a one-time join token (shown once) for `enrollHost`. The name and every address must be unused by other hosts, inside the caller's own `iam:ssh:manage` scope (decided on `iam/ssh/hosts/{address}` for each), and names the organization can vouch for: single labels, private addresses, names under its verified domains, and within `hostPatterns` when set. Needs the authorities from `setup`.                                              | Credential |
| [`deleteHost`](#deletehost)                       | Deletes a host and revokes its certificate. Certificates naming it open nothing afterwards.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Credential |
| [`disableHost`](#disablehost)                     | Takes a host out of service. Its certificate is revoked, its key is published as `@revoked` to clients and in the revocation list, its renewal token stops working, and no user certificate names it any more.                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Credential |
| [`enrollHost`](#enrollhost)                       | A server enrolls with its join token and public host key (not a security key). It gets a host certificate for its name and addresses, the trusted user authority keys, one principals file per login, the revocation list, suggested file paths and an sshd\_config drop-in, and the renewal token (once) for `syncHost`. Public: the join token is the credential. It works once and expires after `ssh.joinTokenMs`.                                                                                                                                                                                                                                                                 | Public     |
| [`getCertificate`](#getcertificate)               | One certificate record: kind, serial, key ID, principals, hosts and logins, extensions, key fingerprint, validity, and revocation details.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | Credential |
| [`getHost`](#gethost)                             | One host: status, addresses, logins, labels, host key fingerprint, certificate expiry and when it last synced. Token hashes never appear.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | Credential |
| [`getSettings`](#getsettings)                     | The tenant's settings (MFA, security keys, source-address binding, default and maximum lifetimes, host patterns), the revocation list version, and the deployment's ceiling for `maxCertificateMs`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | Credential |
| [`issueCertificate`](#issuecertificate)           | Certifies the caller's public key (Ed25519, ECDSA, RSA of 2048+ bits, or a FIDO security key) for every requested host and login policies allow (default: every enrolled host). Forwarding extensions are included only where every named host allows them. The lifetime is the requested `ttlMs` (default from the settings), capped by the tenant maximum, the caller's session and the account's expiry. Returns the certificate line, its principals and validity, the hosts, and known\_hosts lines. Works with user sessions, API keys, and temporary and delegated sessions, but never with an impersonation session or a platform root override from outside the organization. | Credential |
| [`listAuthorities`](#listauthorities)             | Every authority key of the tenant, retired ones included: kind (`user` or `host`), status (`pending`, `active`, `previous`, `retired`), public key and fingerprint. Private keys never appear.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Credential |
| [`listCertificates`](#listcertificates)           | Issued certificates, newest first, filtered by `kind`, `identityId`, `hostId` or `status` (`active`, `revoked`, `expired`), paged with `limit` (at most 500) and `offset`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | Credential |
| [`listHosts`](#listhosts)                         | The tenant's hosts by name, filtered by `status`, exact `labels`, or a `query` over names, addresses and descriptions.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | Credential |
| [`myAccess`](#myaccess)                           | The enrolled hosts the caller may open, with the logins and forwarding policies allow, and the settings that affect a request (MFA, security keys, lifetimes). No permission needed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | Credential |
| [`myCertificates`](#mycertificates)               | The caller's own certificates in the tenant, newest first (the last 100), with their status.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | Credential |
| [`resetJoinToken`](#resetjointoken)               | Returns a fresh one-time join token, for a rebuilt server or to bring a disabled host back. The host's renewal token stops working; re-enrolling revokes its previous certificates as `superseded`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | Credential |
| [`retireAuthority`](#retireauthority)             | Stops trusting a previous (or pending) authority.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Credential |
| [`revocationList`](#revocationlist)               | A key revocation list, base64. `kind: 'user'` (the default) is for sshd `RevokedKeys`: revoked user certificates, certificates of holders who are no longer active or whose session is gone, and every user certificate while the organization is suspended. `kind: 'host'` is for ssh `RevokedHostKeys`: revoked host certificates and host keys no enrolled host uses any more. The version increases with every revocation. Public, like an X.509 CRL; read outside any transaction and cached for 10 seconds per tenant, kind and version.                                                                                                                                         | Public     |
| [`revokeAllCertificates`](#revokeallcertificates) | Revokes every live user certificate of the tenant, after a suspected compromise.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Credential |
| [`revokeCertificate`](#revokecertificate)         | Revokes one certificate. Anyone may revoke their own user certificate; revoking someone else's needs the permission. Hosts refuse it from their next revocation list.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Credential |
| [`revokeIdentity`](#revokeidentity)               | Revokes every live user certificate of one identity, for incident response.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Credential |
| [`rotateAuthority`](#rotateauthority)             | Starts rotating the user or host authority. A new `pending` key is published and trusted by hosts and clients from their next sync, and it signs from `activateAuthority`. With `activate: true` the new key signs at once (after a compromise); certificates then work only on hosts that have synced since.                                                                                                                                                                                                                                                                                                                                                                          | Credential |
| [`setup`](#setup)                                 | Creates the tenant's user authority and host authority when they are missing, and returns every authority and the trust material to distribute. Calling it again changes nothing (`created` is empty).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | Credential |
| [`status`](#status)                               | The tenant's SSH configuration at a glance: whether it is set up, the settings, the authorities that are not retired, hosts by status, counts of live user and host certificates and of revoked ones, and hosts whose certificate ends within 14 days.                                                                                                                                                                                                                                                                                                                                                                                                                                 | Credential |
| [`sweep`](#sweep)                                 | Runs the continuous-authorization sweep for this tenant now. It revokes live certificates whose holder is no longer active, whose temporary session ended, or whose hosts and logins policies no longer allow. The deployment job `iam.ssh.sweep()` covers every tenant.                                                                                                                                                                                                                                                                                                                                                                                                               | Credential |
| [`syncHost`](#synchost)                           | A host's periodic check-in with its renewal token. It returns the current trust, principals files and revocation list, and a new host certificate when the host's addresses or the host authority changed or the current certificate is past two thirds of its lifetime (`renew: true` forces one). A `publicKey` other than the enrolled one is refused, so a stolen renewal token cannot certify an attacker's key. Public: the renewal token is the credential.                                                                                                                                                                                                                     | Public     |
| [`trust`](#trust)                                 | The tenant's public trust: user authority keys for hosts (`trustedUserCaKeys` for `TrustedUserCAKeys`), host authority keys, and the `@cert-authority` known\_hosts line only when `hostPatterns` is set. Pending, active and previous keys are all trusted. Public (and bound to the organization's own address): public keys and patterns only, never host names.                                                                                                                                                                                                                                                                                                                    | Public     |
| [`updateHost`](#updatehost)                       | Changes a host's addresses, logins, labels or description (`null` clears it). New addresses reach the host certificate, and new logins the principals files, at the host's next `syncHost` (`syncRequired` says so).                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | Credential |
| [`updateSettings`](#updatesettings)               | Changes the tenant's settings; fields left out keep their values. `hostPatterns` are known\_hosts patterns (`*` and `?` globs, `!` negation). When set, every host name and address must match them, and the host authority is trusted only for them. Empty patterns trust it for exactly the enrolled names.                                                                                                                                                                                                                                                                                                                                                                          | Credential |
| [`whoCanLogin`](#whocanlogin)                     | Access review: which active identities may log in to a host, and as which logins. Each identity is decided in a synthetic session (with MFA when `assumeMfa`), optionally for one `login` or `kind`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | Credential |

## activateAuthority [#activateauthority]

Makes a pending authority the signing key. The key it replaces stays trusted as `previous`, so certificates it issued keep working until they expire.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/authorities/{kind}`.
* **Errors:** `INVALID_TRANSITION` unless the authority is pending.

```ts title="Signature"
iam.api.ssh.activateAuthority(
  credential: CredentialInput,
  input: { tenantId: string; authorityId: string },
): Promise<SshAuthorityView>
```

## clientTrust [#clienttrust]

What a member's SSH client needs: known\_hosts lines trusting the host authority for the organization's enrolled names (or its patterns), `@revoked` lines for host keys to refuse, and the host revocation list (base64 KRL) for `RevokedHostKeys`. Needs a session of the organization.

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

```ts title="Signature"
iam.api.ssh.clientTrust(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<{ knownHosts: string; revokedHostKeys: string; hostPatterns: string[] }>
```

## createHost [#createhost]

Registers a server: its `name` (unique, lowercase letters, digits, `.` and `-`, never changes), `addresses` for the host certificate, `logins` people may be granted, and `labels` that policies read as `resource.{label}`. Returns a one-time join token (shown once) for `enrollHost`. The name and every address must be unused by other hosts, inside the caller's own `iam:ssh:manage` scope (decided on `iam/ssh/hosts/{address}` for each), and names the organization can vouch for: single labels, private addresses, names under its verified domains, and within `hostPatterns` when set. Needs the authorities from `setup`.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/hosts/{name}`.
* **Errors:** `CONFLICT` for a name in use; `HOST_NAME_TAKEN` for an address another host uses;
  `HOST_OUTSIDE_PATTERNS` for a name or address the organization cannot vouch for; `ACCESS_DENIED` for an address
  outside the caller's scope; `SSH_NOT_CONFIGURED`; `INVALID_INPUT` for invalid names, logins, addresses or labels.
* **Audited as:** `iam:ssh:manage`; refusals by name as a denied `iam:ssh:manage` with `metadata.reason`.

```ts title="Signature"
iam.api.ssh.createHost(
  credential: CredentialInput,
  input: SshHostInput,
): Promise<{ host: SshHostView; joinToken: string; joinTokenExpiresAt: number }>
```

## deleteHost [#deletehost]

Deletes a host and revokes its certificate. Certificates naming it open nothing afterwards.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/hosts/{name}`.

```ts title="Signature"
iam.api.ssh.deleteHost(
  credential: CredentialInput,
  input: { tenantId: string; hostId: string },
): Promise<{ deleted: boolean }>
```

## disableHost [#disablehost]

Takes a host out of service. Its certificate is revoked, its key is published as `@revoked` to clients and in the revocation list, its renewal token stops working, and no user certificate names it any more.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/hosts/{name}`.

```ts title="Signature"
iam.api.ssh.disableHost(
  credential: CredentialInput,
  input: { tenantId: string; hostId: string },
): Promise<SshHostView>
```

## enrollHost [#enrollhost]

A server enrolls with its join token and public host key (not a security key). It gets a host certificate for its name and addresses, the trusted user authority keys, one principals file per login, the revocation list, suggested file paths and an sshd\_config drop-in, and the renewal token (once) for `syncHost`. Public: the join token is the credential. It works once and expires after `ssh.joinTokenMs`.

**HTTP:** `POST /api/iam/ssh/enrollHost` (no credential) · **Browser client:** `client.ssh.enrollHost()`

* **Audited as:** `ssh:host:enroll` (actor `ssh-host:{hostId}`).
* **Errors:** `INVALID_TOKEN` for an unknown, used or expired token or a disabled host (audited as a denied
  `ssh:host:enroll` when the host exists); `HOST_KEY_IN_USE` for another host's key; `INVALID_INPUT` for an authority
  key or a security key; `TENANT_INACTIVE`; `RATE_LIMITED`.

```ts title="Signature"
iam.api.ssh.enrollHost(
  input: { joinToken: string; publicKey: string },
): Promise<SshHostSetup>
```

## getCertificate [#getcertificate]

One certificate record: kind, serial, key ID, principals, hosts and logins, extensions, key fingerprint, validity, and revocation details.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/certificates/{id}`.

```ts title="Signature"
iam.api.ssh.getCertificate(
  credential: CredentialInput,
  input: { tenantId: string; certificateId: string },
): Promise<SshCertificateView>
```

## getHost [#gethost]

One host: status, addresses, logins, labels, host key fingerprint, certificate expiry and when it last synced. Token hashes never appear.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/hosts/{name}`.

```ts title="Signature"
iam.api.ssh.getHost(
  credential: CredentialInput,
  input: { tenantId: string; hostId: string },
): Promise<SshHostView>
```

## getSettings [#getsettings]

The tenant's settings (MFA, security keys, source-address binding, default and maximum lifetimes, host patterns), the revocation list version, and the deployment's ceiling for `maxCertificateMs`.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/settings`.

```ts title="Signature"
iam.api.ssh.getSettings(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<SshSettingsView>
```

## issueCertificate [#issuecertificate]

Certifies the caller's public key (Ed25519, ECDSA, RSA of 2048+ bits, or a FIDO security key) for every requested host and login policies allow (default: every enrolled host). Forwarding extensions are included only where every named host allows them. The lifetime is the requested `ttlMs` (default from the settings), capped by the tenant maximum, the caller's session and the account's expiry. Returns the certificate line, its principals and validity, the hosts, and known\_hosts lines. Works with user sessions, API keys, and temporary and delegated sessions, but never with an impersonation session or a platform root override from outside the organization.

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

* **Permission:** a session; `ssh:login` on each `ssh-login/{host}/{login}` decides.
* **Audited as:** `ssh:certificate:issue` with the serial, key ID, hosts, fingerprint and reason; a refusal is a denied
  `ssh:login` event with `metadata.reason`.
* **Errors:** `ACCESS_DENIED`; `NOT_FOUND` for a named host that is not enrolled; `MFA_REQUIRED`;
  `SECURITY_KEY_REQUIRED`; `SOURCE_ADDRESS_UNKNOWN`; `TOO_MANY_HOSTS`; `SESSION_EXPIRING`; `IMPERSONATION_RESTRICTED`;
  `ROOT_SSH_RESTRICTED`; `SSH_NOT_CONFIGURED`.

```ts
const cert = await iam.api.ssh.issueCertificate(session, {
  tenantId,
  publicKey: 'ssh-ed25519 AAAA... alice@laptop',
  hosts: ['web-01'],
  ttlMs: 30 * 60_000,
  reason: 'hotfix 42',
});
// Save cert.certificate as ~/.ssh/id_ed25519-cert.pub
```

```ts title="Signature"
iam.api.ssh.issueCertificate(
  credential: CredentialInput,
  input: SshCertificateRequest,
): Promise<SshIssuedCertificate>
```

## listAuthorities [#listauthorities]

Every authority key of the tenant, retired ones included: kind (`user` or `host`), status (`pending`, `active`, `previous`, `retired`), public key and fingerprint. Private keys never appear.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/authorities`.

```ts title="Signature"
iam.api.ssh.listAuthorities(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<SshAuthorityView[]>
```

## listCertificates [#listcertificates]

Issued certificates, newest first, filtered by `kind`, `identityId`, `hostId` or `status` (`active`, `revoked`, `expired`), paged with `limit` (at most 500) and `offset`.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/certificates`.

```ts title="Signature"
iam.api.ssh.listCertificates(
  credential: CredentialInput,
  input: {
    tenantId: string;
    kind?: 'user' | 'host';
    identityId?: string;
    hostId?: string;
    status?: 'active' | 'revoked' | 'expired';
    limit?: number;
    offset?: number;
  },
): Promise<{ certificates: SshCertificateView[]; total: number }>
```

## listHosts [#listhosts]

The tenant's hosts by name, filtered by `status`, exact `labels`, or a `query` over names, addresses and descriptions.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/hosts`.

```ts title="Signature"
iam.api.ssh.listHosts(
  credential: CredentialInput,
  input: {
    tenantId: string;
    status?: SshHost['status'];
    labels?: Record<string, string>;
    query?: string;
  },
): Promise<SshHostView[]>
```

## myAccess [#myaccess]

The enrolled hosts the caller may open, with the logins and forwarding policies allow, and the settings that affect a request (MFA, security keys, lifetimes). No permission needed.

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

```ts title="Signature"
iam.api.ssh.myAccess(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<{
  hosts: SshAccessEntry[];
  requireMfa: boolean;
  requireSecurityKey: boolean;
  defaultCertificateMs: number;
  maxCertificateMs: number;
}>
```

## myCertificates [#mycertificates]

The caller's own certificates in the tenant, newest first (the last 100), with their status.

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

```ts title="Signature"
iam.api.ssh.myCertificates(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<SshCertificateView[]>
```

## resetJoinToken [#resetjointoken]

Returns a fresh one-time join token, for a rebuilt server or to bring a disabled host back. The host's renewal token stops working; re-enrolling revokes its previous certificates as `superseded`.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/hosts/{name}`.

```ts title="Signature"
iam.api.ssh.resetJoinToken(
  credential: CredentialInput,
  input: { tenantId: string; hostId: string },
): Promise<{ host: SshHostView; joinToken: string; joinTokenExpiresAt: number }>
```

## retireAuthority [#retireauthority]

Stops trusting a previous (or pending) authority.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/authorities/{kind}`.
* **Errors:** `RESOURCE_IN_USE` while certificates it signed are still valid, unless `force: true`, which revokes them;
  `INVALID_TRANSITION` for the active authority.

```ts title="Signature"
iam.api.ssh.retireAuthority(
  credential: CredentialInput,
  input: { tenantId: string; authorityId: string; force?: boolean },
): Promise<SshAuthorityView>
```

## revocationList [#revocationlist]

A key revocation list, base64. `kind: 'user'` (the default) is for sshd `RevokedKeys`: revoked user certificates, certificates of holders who are no longer active or whose session is gone, and every user certificate while the organization is suspended. `kind: 'host'` is for ssh `RevokedHostKeys`: revoked host certificates and host keys no enrolled host uses any more. The version increases with every revocation. Public, like an X.509 CRL; read outside any transaction and cached for 10 seconds per tenant, kind and version.

**HTTP:** `POST /api/iam/ssh/revocationList` (no credential) · **Browser client:** `client.ssh.revocationList()`

```ts title="Signature"
iam.api.ssh.revocationList(
  input: { tenantId: string; kind?: 'user' | 'host' },
): Promise<{
  tenantId: string;
  kind: 'user' | 'host';
  version: number;
  generatedAt: number;
  tenantActive: boolean;
  revokedCertificates: number;
  revokedHostKeys: number;
  krl: string;
}>
```

## revokeAllCertificates [#revokeallcertificates]

Revokes every live user certificate of the tenant, after a suspected compromise.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/certificates`.

```ts title="Signature"
iam.api.ssh.revokeAllCertificates(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<{ revoked: number }>
```

## revokeCertificate [#revokecertificate]

Revokes one certificate. Anyone may revoke their own user certificate; revoking someone else's needs the permission. Hosts refuse it from their next revocation list.

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

* **Permission:** none for your own; otherwise `iam:ssh:manage` on `iam/ssh/certificates/{id}`.
* **Audited as:** `ssh:certificate:revoke` (own) or `iam:ssh:manage`.

```ts title="Signature"
iam.api.ssh.revokeCertificate(
  credential: CredentialInput,
  input: { tenantId: string; certificateId: string },
): Promise<SshCertificateView>
```

## revokeIdentity [#revokeidentity]

Revokes every live user certificate of one identity, for incident response.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/identities/{identityId}`.

```ts title="Signature"
iam.api.ssh.revokeIdentity(
  credential: CredentialInput,
  input: { tenantId: string; identityId: string },
): Promise<{ revoked: number }>
```

## rotateAuthority [#rotateauthority]

Starts rotating the user or host authority. A new `pending` key is published and trusted by hosts and clients from their next sync, and it signs from `activateAuthority`. With `activate: true` the new key signs at once (after a compromise); certificates then work only on hosts that have synced since.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/authorities/{kind}`.
* **Errors:** `CONFLICT` while a rotation is already pending.

```ts title="Signature"
iam.api.ssh.rotateAuthority(
  credential: CredentialInput,
  input: { tenantId: string; kind: SshAuthorityKind; activate?: boolean },
): Promise<SshAuthorityView>
```

## setup [#setup]

Creates the tenant's user authority and host authority when they are missing, and returns every authority and the trust material to distribute. Calling it again changes nothing (`created` is empty).

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/authorities`.
* **Audited as:** `iam:ssh:manage`.

```ts title="Signature"
iam.api.ssh.setup(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<{
  created: SshAuthorityKind[];
  authorities: SshAuthorityView[];
  trust: {
    tenantId: string;
    userAuthorities: {
      id: string;
      status: SshAuthorityStatus;
      publicKey: string;
      fingerprint: string;
    }[];
    hostAuthorities: {
      id: string;
      status: SshAuthorityStatus;
      publicKey: string;
      fingerprint: string;
    }[];
    hostPatterns: string[];
    trustedUserCaKeys: string;
    knownHosts: string;
  };
}>
```

## status [#status]

The tenant's SSH configuration at a glance: whether it is set up, the settings, the authorities that are not retired, hosts by status, counts of live user and host certificates and of revoked ones, and hosts whose certificate ends within 14 days.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/settings`.

```ts title="Signature"
iam.api.ssh.status(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<{
  configured: boolean;
  settings: SshSettingsView;
  authorities: SshAuthorityView[];
  hosts: { pending: number; enrolled: number; disabled: number };
  certificates: { activeUser: number; activeHost: number; revoked: number };
  hostsExpiringSoon: number;
}>
```

## sweep [#sweep]

Runs the continuous-authorization sweep for this tenant now. It revokes live certificates whose holder is no longer active, whose temporary session ended, or whose hosts and logins policies no longer allow. The deployment job `iam.ssh.sweep()` covers every tenant.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/certificates`.
* **Audited as:** `ssh:certificate:revoke` per revoked certificate (actor `deployment-operator`).

```ts title="Signature"
iam.api.ssh.sweep(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<SshSweepResult>
```

## syncHost [#synchost]

A host's periodic check-in with its renewal token. It returns the current trust, principals files and revocation list, and a new host certificate when the host's addresses or the host authority changed or the current certificate is past two thirds of its lifetime (`renew: true` forces one). A `publicKey` other than the enrolled one is refused, so a stolen renewal token cannot certify an attacker's key. Public: the renewal token is the credential.

**HTTP:** `POST /api/iam/ssh/syncHost` (no credential) · **Browser client:** `client.ssh.syncHost()`

* **Audited as:** `ssh:host:renew` when a certificate is issued.
  A renewed certificate comes with a new `renewalToken`; the one presented keeps working until the new one is used.
  `renew: true` is honoured at most hourly. While the organization is suspended the host still syncs, without a new
  certificate.

* **Errors:** `INVALID_TOKEN`; `HOST_KEY_CHANGED` (re-enroll with a new join token; audited as a denied
  `ssh:host:sync`); `RATE_LIMITED`.

```ts title="Signature"
iam.api.ssh.syncHost(
  input: { renewalToken: string; publicKey?: string; renew?: boolean },
): Promise<SshHostSetup>
```

## trust [#trust]

The tenant's public trust: user authority keys for hosts (`trustedUserCaKeys` for `TrustedUserCAKeys`), host authority keys, and the `@cert-authority` known\_hosts line only when `hostPatterns` is set. Pending, active and previous keys are all trusted. Public (and bound to the organization's own address): public keys and patterns only, never host names.

**HTTP:** `POST /api/iam/ssh/trust` (no credential) · **Browser client:** `client.ssh.trust()`

```ts title="Signature"
iam.api.ssh.trust(
  input: { tenantId: string },
): Promise<{
  tenantId: string;
  userAuthorities: {
    id: string;
    status: SshAuthorityStatus;
    publicKey: string;
    fingerprint: string;
  }[];
  hostAuthorities: {
    id: string;
    status: SshAuthorityStatus;
    publicKey: string;
    fingerprint: string;
  }[];
  hostPatterns: string[];
  trustedUserCaKeys: string;
  knownHosts: string;
}>
```

## updateHost [#updatehost]

Changes a host's addresses, logins, labels or description (`null` clears it). New addresses reach the host certificate, and new logins the principals files, at the host's next `syncHost` (`syncRequired` says so).

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/hosts/{name}`.
* **Errors:** `HOST_OUTSIDE_PATTERNS`.

```ts title="Signature"
iam.api.ssh.updateHost(
  credential: CredentialInput,
  input: SshHostUpdate,
): Promise<{ host: SshHostView; syncRequired: boolean }>
```

## updateSettings [#updatesettings]

Changes the tenant's settings; fields left out keep their values. `hostPatterns` are known\_hosts patterns (`*` and `?` globs, `!` negation). When set, every host name and address must match them, and the host authority is trusted only for them. Empty patterns trust it for exactly the enrolled names.

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

* **Permission:** `iam:ssh:manage` on `iam/ssh/settings`.
* **Errors:** `INVALID_INPUT` for lifetimes outside one minute to the deployment maximum, a default above the maximum,
  or malformed patterns; `HOST_OUTSIDE_PATTERNS` when the new patterns leave an existing host uncovered.

```ts title="Signature"
iam.api.ssh.updateSettings(
  credential: CredentialInput,
  input: {
    tenantId: string;
    requireMfa?: boolean;
    requireSecurityKey?: boolean;
    requireUserVerification?: boolean;
    bindSourceAddress?: boolean;
    defaultCertificateMs?: number;
    maxCertificateMs?: number;
    hostPatterns?: string[];
  },
): Promise<SshSettingsView>
```

## whoCanLogin [#whocanlogin]

Access review: which active identities may log in to a host, and as which logins. Each identity is decided in a synthetic session (with MFA when `assumeMfa`), optionally for one `login` or `kind`.

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

* **Permission:** `iam:ssh:read` on `iam/ssh/hosts/{name}`.

```ts title="Signature"
iam.api.ssh.whoCanLogin(
  credential: CredentialInput,
  input: {
    tenantId: string;
    hostId: string;
    login?: string;
    assumeMfa?: boolean;
    kind?: 'user' | 'service' | 'agent';
  },
): Promise<{
  host: string;
  identities: {
    identityId: string;
    name?: string;
    email?: string;
    kind: string;
    logins: string[];
  }[];
}>
```
