ZKAC/docs/CLI.md
2026-05-06 18:12:31 +02:00

255 lines
6.2 KiB
Markdown

# ZKAC CLI Guide
This guide documents the `zkac-node` CLI and the related `zkac-node-i2p-server` helper, with practical workflows for creating users, issuing credentials, and authenticating.
## Install
From the repository root:
```bash
# Build/install the zkac Python extension first.
maturin develop
# Install CLI entrypoints.
pip install -e ./cli
```
Check installed commands:
```bash
zkac-node --help
zkac-node-i2p-server --help
```
## Concepts
- `userid` is your local identity name; each user is stored under `~/.zkac/<userid>/`.
- `server` is always a network endpoint string in `host:port` form.
- Most management operations require pinning the server public key first.
- Credentials are granted directly over authenticated P2P delivery (`grant` -> `p2p-listen`).
## Command Groups
## `user`
Manage local identities.
```bash
zkac-node user create <userid>
zkac-node user list
zkac-node user show <userid> [--peer host:port]
```
- `create` generates issuance and transport keypairs.
- `show --peer host:port` embeds your receiving endpoint into a shareable contact bundle, used by admins when granting.
## `serve`
Run a ZKAC node server:
```bash
zkac-node serve <userid> [--data-dir DIR] [--host HOST] [--port PORT] \
[--max-connections N] [--idle-timeout SECONDS] [--listen-backlog N] \
[--allow-non-loopback]
```
Defaults: `--host 127.0.0.1`, `--port 9800`, data at `~/.zkac/<userid>/server/`.
By default non-loopback binds are blocked unless you explicitly pass `--allow-non-loopback`.
## `server pin`
Pin a server transport public key per user:
```bash
zkac-node server pin <userid> <host:port> --key <SERVER_PUBLIC_KEY_HEX>
```
Pins are exact string matches. If you connect with `example.b32.i2p:9800`, pin exactly that, not `localhost:9800`.
## `registry`
Manage registries you own:
```bash
zkac-node registry create <userid> <server> --roles role1,role2
zkac-node registry update <userid> <server> --registry <REGISTRY_ID> --add-roles role3,role4
zkac-node registry get <userid> <server> --registry <REGISTRY_ID>
zkac-node registry list <userid>
zkac-node registry revoke <userid> <server> --registry <REGISTRY_ID> --role <ROLE>
zkac-node registry revoke <userid> <server> --registry <REGISTRY_ID> --all
```
- `create` initializes a registry and stores local admin metadata.
- `update` adds new roles.
- `revoke` bumps role epoch(s), invalidating credentials for that role or all roles.
## `grant`
Grant one credential directly to a recipient:
```bash
zkac-node grant <admin_userid> --server <host:port> --registry <REGISTRY_ID> \
--role <ROLE> --to "<RECIPIENT_CONTACT_BUNDLE>"
```
The `--to` bundle must include both:
- recipient issuance key and transport key
- grant pairing token and `peer` endpoint (from `user show --peer`)
## `p2p-listen`
Receive exactly one direct grant and store it locally:
```bash
zkac-node p2p-listen <userid> [--host HOST] [--port PORT] [--timeout SECONDS] \
[--allow-non-loopback]
```
Default bind is `127.0.0.1:9810`.
## `credentials list`
Show locally stored credentials:
```bash
zkac-node credentials list <userid>
```
## `auth`
Authenticate using a credential:
```bash
zkac-node auth <userid> --registry <REGISTRY_ID> --role <ROLE> [--server host:port]
```
If `--server` is omitted, the CLI tries to use server info from local admin metadata for that registry.
## `net check`
Connectivity diagnostics:
```bash
zkac-node net check <host:port> [--timeout SECONDS] [--handshake] [--userid <id>] [--key <hex>]
```
- Without `--handshake`, this verifies TCP reachability.
- With `--handshake`, it additionally verifies anonymous ZKAC handshake.
- For handshake mode, provide either `--key` or `--userid` (not both).
## End-to-End Workflow: Create, Grant, Receive, Authenticate
Two users: `alice` (admin) and `bob` (recipient), one server on `localhost:9800`.
1) Create users
```bash
zkac-node user create alice
zkac-node user create bob
```
2) Start server (Alice host)
```bash
zkac-node serve alice --host 127.0.0.1 --port 9800
```
3) Pin server key for both users
```bash
zkac-node server pin alice localhost:9800 --key <SERVER_PK_HEX>
zkac-node server pin bob localhost:9800 --key <SERVER_PK_HEX>
```
4) Bob shares contact bundle with peer endpoint
```bash
zkac-node user show bob --peer 127.0.0.1:9810
```
Copy the emitted contact blob from Bob to Alice through an out-of-band channel.
5) Alice creates registry
```bash
zkac-node registry create alice localhost:9800 --roles analyst,operator
```
Save the `registry_id` from command output.
6) Bob starts one-shot receiver
```bash
zkac-node p2p-listen bob --host 127.0.0.1 --port 9810
```
7) Alice grants Bob `analyst`
```bash
zkac-node grant alice --server localhost:9800 --registry <REGISTRY_ID> \
--role analyst --to "<BOB_CONTACT_BUNDLE>"
```
8) Bob verifies local credential
```bash
zkac-node credentials list bob
```
9) Bob authenticates
```bash
zkac-node auth bob --registry <REGISTRY_ID> --role analyst --server localhost:9800
```
## Workflow: Revoke a Role
Revoke only one role:
```bash
zkac-node registry revoke alice localhost:9800 --registry <REGISTRY_ID> --role analyst
```
Revoke all roles:
```bash
zkac-node registry revoke alice localhost:9800 --registry <REGISTRY_ID> --all
```
After revocation, existing credentials for bumped epoch(s) no longer authenticate.
## Workflow: I2P Connectivity
Run server intended for I2P tunnel exposure:
```bash
zkac-node-i2p-server alice --host 127.0.0.1 --port 9800
```
For outbound client traffic to `.i2p` endpoints, configure SOCKS5:
```bash
export ZKAC_SOCKS5_PROXY=127.0.0.1:4447
```
Then use normal commands against `*.b32.i2p:port`:
```bash
zkac-node net check exampledestination.b32.i2p:9800
zkac-node net check exampledestination.b32.i2p:9800 --handshake --key <SERVER_PK_HEX>
zkac-node auth bob --registry <REGISTRY_ID> --role analyst --server exampledestination.b32.i2p:9800
```
## Local Storage Layout
Per user directory (`~/.zkac/<userid>/`):
```text
identity.json issuance + p2p transport identity data
admin/<registry_id>.json local admin material for owned registries
credentials/<rid>_<role>.json received credentials
servers/sha256_*.json pinned server public keys
server/ server state if `serve` is run for this userid
```