Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions docs/fleet-manager/make-a-credential-request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: "🙋 Make a credential request"
---

# 🙋 Make a credential request

:::info[In flight]
This page is new in the web UI. Your admin needs a Fleet Manager that serves operator credential requests to file the CSR you make here.
:::

This page covers one task: making your own Fleet Manager operator key and certificate signing request (CSR), then building your `.p12` file once your admin sends back the signed certificate. It is for someone who doesn't have an operator certificate yet.

The **Make a credential request** page runs entirely in your browser. It needs no login and sends nothing anywhere: the key, its backup and the passphrase stay on your machine. Only the CSR goes to your admin, who files it as described in [Adding operators in the web UI](./web-operator-credentials.md).

:::caution[Before you start]
You need the Fleet Manager's address, and the access level your admin agreed to give you: `viewer`, `operator` or `admin`.
:::

## Make your key and CSR

1. Open the Fleet Manager's address. Under **Log in**, select **No operator certificate yet? Make a credential request**. The page is at `/request-credential`.
2. Enter your **Full name**, your **Email** and the **Access level**. Your email becomes your certificate's common name.
3. Select **Make my key and CSR**. The browser makes a P-384 key and a CSR, then shows a generated passphrase and **Download key backup**.

:::danger[The passphrase is shown once]
The passphrase appears only on this screen. Download the key backup (`fleetos-<level>-<email>.key.pem`, your private key encrypted with that passphrase) and store the passphrase in a password manager before you go on. Without both, your key is lost and you have to start again. **Continue** stays disabled until you have downloaded the backup and ticked **I have saved the passphrase**.
:::

4. Select **Continue**. The page shows your **CSR**. Copy it, or download it as `fleetos-<level>-<email>.csr`.
5. Send the CSR to your admin with your name and the level you need. Never send the key backup or the passphrase.

:::tip[Expected output]
The CSR is a PEM block that begins `-----BEGIN CERTIFICATE REQUEST-----`. Its subject is `CN=<your email>`, and it asks for your level's profile.
:::

## Build your PKCS#12

Your admin gets the CSR signed at the operator CA, records it, and sends you the signed certificate. You can build the `.p12` file on the same page, in any browser:

1. Open `/request-credential` again and go to **2. Build your PKCS#12**.
2. Choose **Your key backup file**.
3. Paste **Your signed certificate (PEM)**. Optionally paste the **Operator CA certificate** your admin sent, to include it as the chain.
4. Enter the **Key backup passphrase** and select **Build my PKCS#12**.

:::tip[Expected output]
The browser downloads `<email>.p12`. It opens with the same passphrase as the key backup.
:::

If the page says `The certificate does not match the key in this backup`, the certificate was signed from a different CSR. Check with your admin. If it says `The passphrase is wrong or the key file is damaged`, check the passphrase.

You can build the same file with OpenSSL instead. It asks for the key backup passphrase, then for a passphrase for the `.p12` file:

```bash
openssl pkcs12 -export -inkey fleetos-<level>-<email>.key.pem -in <certificate>.crt -certfile operator-ca.crt -name "FleetOS <level> (<email>)" -out <email>.p12
```

## Install it

Install the `.p12` file in your browser's certificate store and log in, as in [Logging in](./web-ui.md#logging-in). Then keep the key backup somewhere safe, or delete it once the certificate is installed.

## Where to go next

- [The web UI](./web-ui.md): logging in and every page.
- [Adding operators in the web UI](./web-operator-credentials.md): what your admin does with your CSR.
108 changes: 108 additions & 0 deletions docs/fleet-manager/web-operator-credentials.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: "🪪 Adding operators in the web UI"
---

# 🪪 Adding operators in the web UI

:::info[In flight]
These screens are new in the web UI and need a Fleet Manager that serves operator credential requests. An older manager refuses them.
:::

This page covers one task: giving someone an operator certificate, and taking it away, from the web UI's **Operators** page. The Fleet Manager never signs operator certificates. Your external operator CA does (see [The operator CA and revocation](./operator-ca.md)). The web UI files a **credential request**, you get the request signed at the CA, and the web UI records the signed certificate.

If the person who needs the certificate can make their own key, have them use [Make a credential request](./make-a-credential-request.md) and send you the CSR. Their key then never leaves their machine.

:::caution[Before you start]
You need an `admin` operator certificate and a working login (see [Logging in](./web-ui.md#logging-in)). The manager needs an operator CA and `database_url`. You need someone who can sign at the operator CA, with the CA's OpenSSL config.
:::

## What the Operators page shows

The **Credentials** tab lists every operator certificate the manager knows:

| Column | What it shows |
|---|---|
| **Holder** | The certificate's common name (the holder's email) and, when recorded, their name. |
| **Level** | `viewer`, `operator` or `admin`. |
| **Kind** | How the manager learned of it: `first_admin`, `requested`, `recorded`, `observed` (seen logging in, never recorded) or `legacy_node` (from a CryptOS node before operator CAs became external; it can't log in). |
| **Issuer** | The start of the operator CA's SHA-256 fingerprint. |
| **Denylisted** | `denylisted` when it is on the manager's denylist. |
| **CRL** | `CRL-revoked` when the operator CA's CRL lists it. |
| **Last seen** | When it last logged in, for credentials the manager has seen in use. |

The **Pending requests** tab lists the requests waiting for a signed certificate, with who filed each one and when it expires. A request expires after 30 days.

## Request a credential

1. On **Operators**, select **Request credential…**.
2. Enter the holder's **Full name**, their **Email** and the **Access level**. The email becomes the certificate's common name.
3. Choose where the key is made, then select **Next**:
- **Make the key here**: this browser makes a P-384 key and a CSR.
- **Upload a CSR from the holder**: paste the holder's CSR or choose its file. Its subject must be exactly `CN=<the holder's email>`. The web UI refuses a CSR for anyone else.
4. With **Make the key here**, the next screen shows a generated passphrase and **Download key backup**. The key backup is the private key, encrypted with that passphrase, saved as `fleetos-<level>-<email>.key.pem`.

:::danger[The passphrase is shown once]
The passphrase appears only on this screen, and the manager never sees it or the key. Download the key backup and store the passphrase in a password manager before you go on. Without both the key is lost, and the request has to start again. **Continue** stays disabled until you have downloaded the backup and ticked **I have saved the passphrase**.
:::

Hand the key backup and the passphrase to the holder over separate channels, or keep them until you complete the request.

5. The request is filed. The screen shows the **CSR** (copy it, or download it as `fleetos-<level>-<email>.csr`, the name the signing command reads), the **OpenSSL extension section** for the level, and the **Signing command**.

:::tip[Expected output]
`Request filed for <email> (<level>). It expires <time>.` The request is listed on **Pending requests**.
:::

{/* screenshot: fleet-manager/operators-request-filed.png: the filed request with the CSR, extension section and signing command */}

## Sign the request at the CA

Give the CSR to whoever runs your operator CA. They sign it with the extension section and command from the previous step (see [The operator CA and revocation](./operator-ca.md) for the CA setup), and send back the certificate.

:::warning[The level extension must be non-critical]
The extension section the manager returns marks nothing critical except key usage and basic constraints. Sign with it as given, and never copy extensions from the CSR. A certificate with a critical level extension can't log in, and the manager refuses to record it (`LEVEL_EXT_CRITICAL`).
:::

## Complete the request

1. On **Pending requests**, select **Complete…** on the request.
2. Paste the **Signed certificate (PEM)**, or choose its file.
3. Choose where the private key is:
- **Key backup held in this browser**: offered only in the browser tab that made the key, until you leave or reload the page.
- **From the key backup file**: choose the `fleetos-<level>-<email>.key.pem` file.
- **The holder has the key**: the manager records the certificate, and the holder builds their PKCS#12 themselves.
4. For the first two, enter the **Key backup passphrase**. Optionally paste the **Operator CA certificate** to include it in the PKCS#12 as the chain.
5. Select **Record and build PKCS#12** (or **Record**).

The web UI first checks that the passphrase opens the backup and that the certificate carries that key, and stops there if either is wrong. Then the manager checks the certificate and records it, and the browser builds the PKCS#12.

:::tip[Expected output]
`Recorded <email> (<level>), serial <serial>.` With a key, the browser downloads `<email>.p12`, protected with the key backup's passphrase. The credential appears on **Credentials** with kind `requested`.
:::

If the manager refuses the certificate, the dialog says why and quotes the code, for example `Certificate refused: The level extension is marked critical. It must be non-critical, or browsers can't sign in with it. (error 1610 LEVEL_EXT_CRITICAL)`. The certificate must chain to the active operator CA and must not be recorded already.

Give the holder the `.p12` file and its passphrase. They install it as in [Logging in](./web-ui.md#logging-in), then keep the key backup somewhere safe or delete it.

To record a certificate made entirely at the CA, with no request, select **Record certificate…** on **Operators**, enter the **Holder's full name** and paste the certificate.

**Cancel** on a pending request withdraws it. The manager then refuses to record a certificate against it.

## Deny a credential

1. On **Credentials**, select **Deny…** on the credential. Credentials already denylisted, and `legacy_node` ones, have no **Deny…**.
2. Choose the **Reason**: an RFC 5280 reason code from 0 to 10 (there is no 7).
3. Optionally add a **Note**. The manager keeps it with the denylist entry.
4. Select **Deny at the Fleet Manager**.

:::warning[Denying here doesn't revoke at your CA]
The manager refuses the certificate from its next request, on every manager instance within about 5 seconds. Anything else that trusts the operator CA still accepts it. Revoke it at your CA as well and publish a new CRL. The dialog repeats this, with any warning the manager returns.
:::

Denying needs `database_url`. Without it the dialog shows `Not available here` with error 1603 `DATABASE_REQUIRED`.

## Where to go next

- [Make a credential request](./make-a-credential-request.md): the page a future operator uses to make their own key and CSR.
- [The operator CA and revocation](./operator-ca.md): the CA, the CRL and the denylist.
- [The web UI](./web-ui.md): every other page.
11 changes: 7 additions & 4 deletions docs/fleet-manager/web-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This page walks through the Fleet Manager's web UI: how you log in, what each pa

## Logging in

You log in with an operator certificate, not a password. Your fleet admin gives it to you as a `.p12` file with a passphrase.
You log in with an operator certificate, not a password. Your fleet admin gives it to you as a `.p12` file with a passphrase. If you don't have one yet, [make a credential request](./make-a-credential-request.md).

1. Install the `.p12` file in your browser's certificate store. The page shows the same commands when it can't find a certificate.

Expand Down Expand Up @@ -192,18 +192,20 @@ This page records intent only. ACME (RFC 8555) and EST (RFC 7030) are served by

## Operators

The operator certificates the manager knows about, with level, serial, expiry and status. It needs an operator CA (see [The operator CA and revocation](./operator-ca.md)). Without one the page says no operator CA is configured.
The operator certificates the manager knows about: recorded ones and ones it has only seen logging in, with their holder, level, kind, operator CA, serial, expiry, whether they are denylisted or CRL-revoked, and when they were last seen. A **Pending requests** tab lists the credential requests waiting for a signed certificate. The page needs an operator CA (see [The operator CA and revocation](./operator-ca.md)). Without one it says no operator CA is configured.

**Revoke…** (`admin`) puts a certificate on the manager's denylist: the manager refuses it from its next request. It needs `database_url`.
`admin` gets **Request credential…**, **Record certificate…**, **Complete…** and **Cancel** on a request, and **Deny…** on a credential. Each is a step in [Adding operators in the web UI](./web-operator-credentials.md). **Deny…** puts a certificate on the manager's denylist: the manager refuses it from its next request. It needs `database_url`.

:::warning[Revoking here doesn't revoke at your CA]
:::warning[Denying here doesn't revoke at your CA]
The denylist stops the certificate at the Fleet Manager only. Revoke it at your operator CA as well and publish a new CRL.
:::

The manager doesn't issue operator certificates: your operator CA signs them. Certificates the manager recorded before operator CAs became external are listed as `legacy_node` and can't log in.

{/* screenshot: fleet-manager/operators-not-configured.png: the Operators page with no operator CA configured */}

Someone with no operator certificate yet can make their own key and CSR from the start page: **No operator certificate yet? Make a credential request** opens [Make a credential request](./make-a-credential-request.md), which runs entirely in the browser.

## Agent keys and MCP sign-in

When the manager's MCP endpoint is on, AI agents use **agent keys**. Each key is bound to the operator certificate that made it, and does no more than that certificate's level or its own ceiling, whichever is lower. It stops working when the certificate is revoked or renewed.
Expand Down Expand Up @@ -238,3 +240,4 @@ Some screens still read the web app's built-in demo data instead of the manager:
- [Fleet Manager overview](./overview.md): what the manager holds and how nodes join.
- [Deploy with Helm](./helm.md): where each install path stands.
- [Approving agent requests](./approvals.md): deciding an agent's step-up request.
- [Adding operators in the web UI](./web-operator-credentials.md): requesting, completing and denying operator certificates.
2 changes: 2 additions & 0 deletions sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ const sidebars: SidebarsConfig = {
'fleet-manager/migrating-from-operator-ca-node',
'fleet-manager/helm',
'fleet-manager/web-ui',
'fleet-manager/web-operator-credentials',
'fleet-manager/make-a-credential-request',
'fleet-manager/approvals',
],
},
Expand Down
Loading