docs(federation): M2 Step-CA setup guide + admin CLI reference (FED-M2-12) (#502)
This commit was merged in pull request #502.
This commit is contained in:
106
docs/federation/ADMIN-CLI.md
Normal file
106
docs/federation/ADMIN-CLI.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# Mosaic Federation — Admin CLI Reference
|
||||||
|
|
||||||
|
Available since: FED-M2
|
||||||
|
|
||||||
|
## Grant Management
|
||||||
|
|
||||||
|
### Create a grant
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic federation grant create --user <userId> --peer <peerId> --scope <scope-file.json>
|
||||||
|
```
|
||||||
|
|
||||||
|
The scope file defines what resources and rows the peer may access:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"resources": ["tasks", "notes"],
|
||||||
|
"excluded_resources": ["credentials"],
|
||||||
|
"max_rows_per_query": 100
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Valid resource values: `tasks`, `notes`, `credentials`, `teams`, `users`
|
||||||
|
|
||||||
|
### List grants
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic federation grant list [--peer <peerId>] [--status pending|active|revoked|expired]
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all federation grants, optionally filtered by peer or status.
|
||||||
|
|
||||||
|
### Show a grant
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic federation grant show <grantId>
|
||||||
|
```
|
||||||
|
|
||||||
|
Display details of a single grant, including its scope, activation timestamp, and status.
|
||||||
|
|
||||||
|
### Revoke a grant
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic federation grant revoke <grantId> [--reason "Reason text"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Revoke an active grant immediately. Revoked grants cannot be reactivated. The optional reason is stored in the audit log.
|
||||||
|
|
||||||
|
### Generate enrollment token
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic federation grant token <grantId> [--ttl <seconds>]
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate a single-use enrollment token for the grant. The default TTL is 900 seconds (15 minutes); maximum 15 minutes.
|
||||||
|
|
||||||
|
Output includes the token and the full enrollment URL for the peer to use.
|
||||||
|
|
||||||
|
## Peer Management
|
||||||
|
|
||||||
|
### Add a peer (remote enrollment)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic federation peer add <enrollment-url>
|
||||||
|
```
|
||||||
|
|
||||||
|
Enroll a remote peer using the enrollment URL obtained from a grant token. The command:
|
||||||
|
|
||||||
|
1. Generates a P-256 ECDSA keypair locally
|
||||||
|
2. Creates a certificate signing request (CSR)
|
||||||
|
3. Submits the CSR to the enrollment URL
|
||||||
|
4. Verifies the returned certificate includes the correct custom OIDs (grant ID and subject user ID)
|
||||||
|
5. Seals the private key at rest using `BETTER_AUTH_SECRET`
|
||||||
|
6. Stores the peer record and sealed key in the local gateway database
|
||||||
|
|
||||||
|
Once enrollment completes, the peer can authenticate using the certificate and private key.
|
||||||
|
|
||||||
|
### List peers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mosaic federation peer list
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all enrolled peers, including their certificate fingerprints and activation status.
|
||||||
|
|
||||||
|
## REST API Reference
|
||||||
|
|
||||||
|
All CLI commands call the local gateway admin API. Equivalent REST endpoints:
|
||||||
|
|
||||||
|
| CLI Command | REST Endpoint | Method |
|
||||||
|
| ------------ | ------------------------------------------------------------------------------------------- | ----------------- |
|
||||||
|
| grant create | `/api/admin/federation/grants` | POST |
|
||||||
|
| grant list | `/api/admin/federation/grants` | GET |
|
||||||
|
| grant show | `/api/admin/federation/grants/:id` | GET |
|
||||||
|
| grant revoke | `/api/admin/federation/grants/:id/revoke` | PATCH |
|
||||||
|
| grant token | `/api/admin/federation/grants/:id/tokens` | POST |
|
||||||
|
| peer list | `/api/admin/federation/peers` | GET |
|
||||||
|
| peer add | `/api/admin/federation/peers/keypair` + enrollment + `/api/admin/federation/peers/:id/cert` | POST, POST, PATCH |
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- **Enrollment tokens** are single-use and expire in 15 minutes (not configurable beyond 15 minutes)
|
||||||
|
- **Peer private keys** are encrypted at rest using AES-256-GCM, keyed from `BETTER_AUTH_SECRET`
|
||||||
|
- **Custom OIDs** in issued certificates are verified post-issuance: the grant ID and subject user ID must match the certificate extensions
|
||||||
|
- **Grant activation** is atomic — concurrent enrollment attempts for the same grant are rejected
|
||||||
|
- **Revoked grants** cannot be activated; peers attempting to use a revoked grant's token will be rejected
|
||||||
@@ -70,6 +70,96 @@ For JSON output (useful in CI/automation):
|
|||||||
mosaic gateway doctor --json
|
mosaic gateway doctor --json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Step 2: Step-CA Bootstrap
|
||||||
|
|
||||||
|
Step-CA is a certificate authority that issues X.509 certificates for federation peers. In Mosaic federation, it signs peer certificates with custom OIDs that embed grant and user identities, enforcing authorization at the certificate level.
|
||||||
|
|
||||||
|
### Prerequisites for Step-CA
|
||||||
|
|
||||||
|
Before starting the CA, you must set up the dev password:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp infra/step-ca/dev-password.example infra/step-ca/dev-password
|
||||||
|
# Edit dev-password and set your CA password (minimum 16 characters)
|
||||||
|
```
|
||||||
|
|
||||||
|
The password is required for the CA to boot and derive the provisioner key used by the gateway.
|
||||||
|
|
||||||
|
### Start the Step-CA service
|
||||||
|
|
||||||
|
Add the step-ca service to your federated stack:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.federated.yml --profile federated up -d step-ca
|
||||||
|
```
|
||||||
|
|
||||||
|
On first boot, the init script (`infra/step-ca/init.sh`) runs automatically. It:
|
||||||
|
|
||||||
|
- Generates the CA root key and certificate in the Docker volume
|
||||||
|
- Creates the `mosaic-fed` JWK provisioner
|
||||||
|
- Applies the X.509 template from `infra/step-ca/templates/federation.tpl`
|
||||||
|
|
||||||
|
The volume is persistent, so subsequent boots reuse the existing CA keys.
|
||||||
|
|
||||||
|
Verify the CA is healthy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl https://localhost:9000/health --cacert /tmp/step-ca-root.crt
|
||||||
|
```
|
||||||
|
|
||||||
|
(If the root cert file doesn't exist yet, see the extraction steps below.)
|
||||||
|
|
||||||
|
### Extract credentials for the gateway
|
||||||
|
|
||||||
|
The gateway requires two credentials from the running CA:
|
||||||
|
|
||||||
|
**1. Provisioner key (for `STEP_CA_PROVISIONER_KEY_JSON`)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec $(docker ps -qf name=step-ca) cat /home/step/secrets/mosaic-fed.json > /tmp/step-ca-provisioner.json
|
||||||
|
```
|
||||||
|
|
||||||
|
This JSON file contains the JWK public and private keys for the `mosaic-fed` provisioner. Store it securely and pass its contents to the gateway via the `STEP_CA_PROVISIONER_KEY_JSON` environment variable.
|
||||||
|
|
||||||
|
**2. Root certificate (for `STEP_CA_ROOT_CERT_PATH`)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker cp $(docker ps -qf name=step-ca):/home/step/certs/root_ca.crt /tmp/step-ca-root.crt
|
||||||
|
```
|
||||||
|
|
||||||
|
This PEM file is the CA's root certificate, used to verify peer certificates issued by step-ca. Pass its path to the gateway via `STEP_CA_ROOT_CERT_PATH`.
|
||||||
|
|
||||||
|
### Custom OID Registry
|
||||||
|
|
||||||
|
Federation certificates include custom OIDs in the certificate extension. These encode authorization metadata:
|
||||||
|
|
||||||
|
| OID | Name | Description |
|
||||||
|
| ------------------- | ---------------------- | --------------------- |
|
||||||
|
| 1.3.6.1.4.1.99999.1 | mosaic_grant_id | Federation grant UUID |
|
||||||
|
| 1.3.6.1.4.1.99999.2 | mosaic_subject_user_id | Subject user UUID |
|
||||||
|
|
||||||
|
These OIDs are verified by the gateway after the CSR is signed, ensuring the certificate was issued with the correct grant and user context.
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Configure the gateway with the following environment variables before startup:
|
||||||
|
|
||||||
|
| Variable | Required | Description |
|
||||||
|
| ------------------------------ | -------- | --------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `STEP_CA_URL` | Yes | Base URL of the step-ca instance, e.g. `https://step-ca:9000` (use `https://localhost:9000` in local dev) |
|
||||||
|
| `STEP_CA_PROVISIONER_KEY_JSON` | Yes | JSON-encoded JWK from `/home/step/secrets/mosaic-fed.json` |
|
||||||
|
| `STEP_CA_ROOT_CERT_PATH` | Yes | Absolute path to the root CA certificate (e.g. `/tmp/step-ca-root.crt`) |
|
||||||
|
| `BETTER_AUTH_SECRET` | Yes | Secret used to seal peer private keys at rest; already required for M1 |
|
||||||
|
|
||||||
|
Example environment setup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export STEP_CA_URL="https://localhost:9000"
|
||||||
|
export STEP_CA_PROVISIONER_KEY_JSON="$(cat /tmp/step-ca-provisioner.json)"
|
||||||
|
export STEP_CA_ROOT_CERT_PATH="/tmp/step-ca-root.crt"
|
||||||
|
export BETTER_AUTH_SECRET="<your-secret>"
|
||||||
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Port conflicts
|
### Port conflicts
|
||||||
|
|||||||
Reference in New Issue
Block a user