# Authentication

> How ZopNight authenticates to AWS, GCP, and Azure. IAM roles, service principals, workload identity, and PATs for the API.

Source: https://zop.dev/docs/zopnight/authentication

---

## Overview

ZopNight authenticates in two directions:

1. **To your cloud**: using the cloud's native identity primitive (IAM role, service principal, workload identity). Credentials are AES-256-GCM encrypted at rest with per-account envelope keys and decrypted only at the call site.
2. **From your tools to ZopNight**: using personal access tokens (PATs) for the REST API and the MCP server.

ZopNight is **read-only by default**. Write permissions are opt-in, per rule category, and can be scoped to a single resource group.

## Authenticating to AWS

ZopNight supports several AWS connect modes: **WIF-Assume Role** (recommended; a keyless cross-account IAM role), **IAM User / Static Keys**, and **Temporary Credentials (STS)**. See [Cloud accounts](https://zop.dev/docs/zopnight/cloud-setup/cloud-accounts) for how to pick and switch between them.

### WIF-Assume Role (recommended)

The wizard generates a trust policy that allows ZopNight's audit account to call `sts:AssumeRole` with an external ID. The external ID is unique per workspace and is shown only once in the wizard.

The read-only policy attaches the AWS-managed `ReadOnlyAccess` policy plus a small inline policy for resource discovery on services that aren't covered by the managed policy. The full document is shown in the wizard and can be downloaded as JSON. This is the broad, simplest grant; for the exact policy and the least-privilege alternative, see [Cloud permissions](https://zop.dev/docs/zopnight/cloud-setup/permissions).

**Rotation cadence**: the external ID rotates only on user request. The trust policy itself does not expire; if you remove the role on your side, the connection moves to *unreachable* and the account is flagged in **Settings → Cloud accounts**. Recheck the role and external ID, then re-verify, or contact support.

### IAM User / Static Keys

Supported for organisations that haven't adopted WIF-Assume Role. Keys are encrypted at rest. We strongly recommend rotating these every 90 days and migrating to WIF-Assume Role when possible.

## Authenticating to GCP

ZopNight supports two GCP connect modes: **One-Click Connect** (recommended) and **Service Account Key**.

### One-Click Connect (recommended)

Sign in with Google and grant consent; ZopNight provisions and manages a dedicated read-only service account in your project. **No long-lived keys are created or stored on your side.**

### Service Account Key

Supported for accounts where One-Click Connect isn't possible. You provide a service-account JSON key; it is encrypted at rest and never logged.

The simplest grant is `roles/viewer` on the project (or organisation, for org-scope connects). For the exact least-privilege roles (`roles/monitoring.viewer` plus `roles/cloudasset.viewer`), see [Cloud permissions](https://zop.dev/docs/zopnight/cloud-setup/permissions). For billing you also need:

- `roles/billing.viewer` if billing exports are not yet wired to BigQuery
- `roles/bigquery.dataViewer` on the billing export dataset

## Authenticating to Azure

ZopNight supports two Azure connect modes: **Service Principal** (recommended; app registration plus client secret) and **Workload Identity Federation** (OIDC, no secret).

### Service Principal (recommended)

The wizard generates a service principal (an app registration plus client secret) that ZopNight uses to authenticate to your subscription. The client secret is encrypted at rest and never logged.

### Workload Identity Federation

Supported for subscriptions that can issue federated credentials. ZopNight's tenant acts as a configured app registration through a federated credential, so **no client secret is stored.**

The simplest grant is the built-in **Reader** role on the subscription (or management group, for tenant-scope connects). For the least-privilege role (**Monitoring Reader**), see [Cloud permissions](https://zop.dev/docs/zopnight/cloud-setup/permissions). For billing you also need:

- **Cost Management Reader** for cost queries
- **Storage Blob Data Reader** on the storage account that hosts the billing export (Azure-EA / MCA exports)

## Personal access tokens (PATs)

Use PATs to authenticate to the REST API and the MCP server from your own tools. Mint a PAT from **Settings → Access tokens**.

- Scope tokens to the **read-only** scope unless you specifically need write.
- Tokens are shown **once** at creation. Store them in your secret manager.
- Tokens are tied to your user; rotate or revoke them when your role changes.
- The MCP server rejects every write request at the protocol layer regardless of token scope.

### API request example

```bash
curl https://api.zop.dev/v1/recommendations \
  -H "Authorization: Bearer $ZOPNIGHT_PAT" \
  -H "Content-Type: application/json"
```

### Token rotation

PATs do not expire by default. Enable **Token rotation policy** on the Enterprise tier to enforce 90-day rotation. Expired tokens move to a 7-day grace state with a banner in the UI; revoked tokens fail immediately.

## Audit trail

Every authentication event (connect, role assumption, PAT issuance, PAT use) is captured in the audit log with actor, action, timestamp, and request body. The trail is append-only and can be forwarded to your SIEM on the Enterprise tier.
