74 lines
2.7 KiB
Markdown
74 lines
2.7 KiB
Markdown
# Token rotation
|
|
|
|
Monlet uses split Bearer-token auth (ADR-0007):
|
|
|
|
- **UI token** — `MONLET_AUTH_TOKEN` env. Accepted by every UI/operator endpoint. The variable holds one or more space/comma-separated tokens; the server accepts any of them, so rotation is zero-loss.
|
|
- **Agent key** — generated locally by each agent and stored in `state_dir/agent.key`. It is not configured on the server; operators accept, block, remove, or blacklist keys through the Agents UI/API.
|
|
|
|
Rotate UI tokens independently from agent admission. Changing `MONLET_AUTH_TOKEN` does not affect accepted agents.
|
|
|
|
## How multi-token overlap works
|
|
|
|
`MONLET_AUTH_TOKEN` is a list: tokens separated by spaces and/or commas. Examples:
|
|
|
|
```sh
|
|
MONLET_AUTH_TOKEN="single-token"
|
|
MONLET_AUTH_TOKEN="old-token new-token"
|
|
MONLET_AUTH_TOKEN="old-token,new-token"
|
|
```
|
|
|
|
All listed tokens are accepted. The middleware compares in constant time across the full list, so timing-side-channels do not leak which token matched.
|
|
|
|
Logs and metrics never include token values.
|
|
|
|
## When to rotate
|
|
|
|
- Suspected UI token leak.
|
|
- Operator turnover.
|
|
- Routine schedule (e.g., quarterly).
|
|
|
|
## Zero-loss procedure
|
|
|
|
1. **Generate a new token**:
|
|
|
|
```sh
|
|
openssl rand -hex 32
|
|
```
|
|
|
|
2. **Add the new token alongside the old one** in the server environment:
|
|
|
|
```sh
|
|
MONLET_AUTH_TOKEN="$OLD $NEW"
|
|
```
|
|
|
|
Restart (or reload) the server. The old token still works, the new one is now accepted as well.
|
|
|
|
3. **Move clients to the new token**:
|
|
- Update Web UI `MONLET_API_TOKEN` and restart.
|
|
- Update any operator scripts or curl examples to use the new value.
|
|
|
|
4. **Verify everything uses the new token**:
|
|
|
|
```sh
|
|
curl -sf -H "Authorization: Bearer $NEW" http://server:8000/api/v1/agents | jq .
|
|
# Optional: tail server logs for unauthorized attempts during the window.
|
|
```
|
|
|
|
5. **Remove the old token** from the server environment:
|
|
|
|
```sh
|
|
MONLET_AUTH_TOKEN="$NEW"
|
|
```
|
|
|
|
Restart the server. From this point the old token is revoked.
|
|
|
|
6. **Scrub the old value** from secret stores, CI variables, and operator notes.
|
|
|
|
## Notes
|
|
|
|
- Tokens are the only auth in v1; protect them like a database password.
|
|
- Tokens never appear in metrics labels, incident keys, or notification labels (ADR-0007, redaction policy).
|
|
- The server redacts `Authorization`/`Cookie`-style headers before logging (`monlet_server/redaction.py`).
|
|
- The middleware uses `hmac.compare_digest` against every accepted token; rotation does not introduce a timing oracle.
|
|
- To rotate an individual agent key, delete `state_dir/agent.key` on that host and restart the agent. The server will show a pending replacement for the same hostname; accept it after verifying the host.
|