Update docs for recent changes
- ARCHITECTURE.md: add gRPC listener, mciasgrpcctl, new roles, granular role endpoints, profile page, audit events, policy actions, trusted_proxy config, validate package, schema force command - PROGRESS.md: document role expansion and UI privilege escalation fix - PROJECT_PLAN.md: align mciasctl subcommands with implementation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
110
ARCHITECTURE.md
110
ARCHITECTURE.md
@@ -15,36 +15,46 @@ parties that delegate authentication decisions to it.
|
||||
### Components
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────┐
|
||||
│ MCIAS Server (mciassrv) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
|
||||
│ │ Auth │ │ Token │ │ Account / Role │ │
|
||||
│ │ Handler │ │ Manager │ │ Manager │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └─────────┬─────────┘ │
|
||||
│ └─────────────┴─────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────▼──────────┐ │
|
||||
│ │ SQLite Database │ │
|
||||
│ └────────────────────┘ │
|
||||
└────────────────────────────────────────────────────┘
|
||||
▲ ▲ ▲
|
||||
│ HTTPS/REST │ HTTPS/REST │ direct file I/O
|
||||
│ │ │
|
||||
┌──────┴──────┐ ┌────┴─────┐ ┌──────┴──────┐
|
||||
│ Personal │ │ mciasctl │ │ mciasdb │
|
||||
│ Apps │ │ (admin │ │ (DB tool) │
|
||||
└─────────────┘ │ CLI) │ └─────────────┘
|
||||
└──────────┘
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ MCIAS Server (mciassrv) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
|
||||
│ │ Auth │ │ Token │ │ Account / Role │ │
|
||||
│ │ Handler │ │ Manager │ │ Manager │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └─────────┬─────────┘ │
|
||||
│ └─────────────┴─────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────▼──────────┐ │
|
||||
│ │ SQLite Database │ │
|
||||
│ └────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────────┐ │
|
||||
│ │ REST listener │ │ gRPC listener │ │
|
||||
│ │ (net/http) │ │ (google.golang.org/ │ │
|
||||
│ │ :8443 │ │ grpc) :9443 │ │
|
||||
│ └──────────────────┘ └──────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
▲ ▲ ▲ ▲
|
||||
│ HTTPS/REST │ HTTPS/REST │ gRPC/TLS │ direct file I/O
|
||||
│ │ │ │
|
||||
┌────┴──────┐ ┌────┴─────┐ ┌─────┴────────┐ ┌───┴────────┐
|
||||
│ Personal │ │ mciasctl │ │ mciasgrpcctl │ │ mciasdb │
|
||||
│ Apps │ │ (admin │ │ (gRPC admin │ │ (DB tool) │
|
||||
└───────────┘ │ CLI) │ │ CLI) │ └────────────┘
|
||||
└──────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
**mciassrv** — The authentication server. Exposes a REST API over HTTPS/TLS.
|
||||
Handles login, token issuance, token validation, token renewal, and token
|
||||
revocation.
|
||||
**mciassrv** — The authentication server. Exposes a REST API and gRPC API over
|
||||
HTTPS/TLS (dual-stack; see §17). Handles login, token issuance, token
|
||||
validation, token renewal, and token revocation.
|
||||
|
||||
**mciasctl** — The administrator CLI. Communicates with mciassrv's REST API
|
||||
using an admin JWT. Creates/manages human accounts, system accounts, roles,
|
||||
and Postgres credential records.
|
||||
|
||||
**mciasgrpcctl** — The gRPC administrator CLI. Mirrors mciasctl's subcommands
|
||||
but communicates over gRPC/TLS instead of REST. Both CLIs can coexist; neither
|
||||
depends on the other.
|
||||
|
||||
**mciasdb** — The database maintenance tool. Operates directly on the SQLite
|
||||
file, bypassing the server API. Intended for break-glass recovery, offline
|
||||
inspection, schema verification, and maintenance tasks that cannot be
|
||||
@@ -127,13 +137,21 @@ mciassrv (passphrase or keyfile) to decrypt secrets at rest.
|
||||
|
||||
### Roles
|
||||
|
||||
Roles are simple string labels stored in the `account_roles` table.
|
||||
Roles are simple string labels stored in the `account_roles` table. Only
|
||||
compile-time allowlisted role names are accepted; attempting to grant an
|
||||
unknown role returns an error (prevents typos like "admim" from silently
|
||||
creating a useless role).
|
||||
|
||||
Reserved roles:
|
||||
Compile-time allowlisted roles:
|
||||
- `admin` — superuser; can manage all accounts, tokens, and credentials
|
||||
- `user` — standard user role
|
||||
- `guest` — limited read-only access
|
||||
- `viewer` — read-only access
|
||||
- `editor` — create/modify access
|
||||
- `commenter` — comment/annotate access
|
||||
- Any role named identically to a system account — grants that human account
|
||||
the ability to issue/revoke tokens and retrieve Postgres credentials for that
|
||||
system account
|
||||
system account (via policy rules, not the allowlist)
|
||||
|
||||
Role assignment requires admin privileges.
|
||||
|
||||
@@ -340,7 +358,6 @@ All endpoints use JSON request/response bodies. All responses include a
|
||||
| POST | `/v1/auth/login` | none | Username/password (+TOTP) login → JWT |
|
||||
| POST | `/v1/auth/logout` | bearer JWT | Revoke current token |
|
||||
| POST | `/v1/auth/renew` | bearer JWT | Exchange token for new token |
|
||||
| PUT | `/v1/auth/password` | bearer JWT | Self-service password change (requires current password) |
|
||||
|
||||
### Token Endpoints
|
||||
|
||||
@@ -372,7 +389,9 @@ All endpoints use JSON request/response bodies. All responses include a
|
||||
| Method | Path | Auth required | Description |
|
||||
|---|---|---|---|
|
||||
| GET | `/v1/accounts/{id}/roles` | admin JWT | List roles for account |
|
||||
| PUT | `/v1/accounts/{id}/roles` | admin JWT | Replace role set |
|
||||
| PUT | `/v1/accounts/{id}/roles` | admin JWT | Replace role set (atomic) |
|
||||
| POST | `/v1/accounts/{id}/roles` | admin JWT | Grant a single role |
|
||||
| DELETE | `/v1/accounts/{id}/roles/{role}` | admin JWT | Revoke a single role |
|
||||
|
||||
### TOTP Endpoints
|
||||
|
||||
@@ -446,6 +465,7 @@ cookie pattern (`mcias_csrf`).
|
||||
| `/pgcreds` | Postgres credentials list (owned + granted) with create form |
|
||||
| `/policies` | Policy rules management — create, enable/disable, delete |
|
||||
| `/audit` | Audit log viewer |
|
||||
| `/profile` | User profile — self-service password change (any authenticated user) |
|
||||
|
||||
**HTMX fragments:** Mutating operations (role updates, tag edits, credential
|
||||
saves, policy toggles, access grants) use HTMX partial-page updates for a
|
||||
@@ -490,6 +510,9 @@ CREATE TABLE accounts (
|
||||
-- AES-256-GCM encrypted TOTP secret; NULL if not enrolled
|
||||
totp_secret_enc BLOB,
|
||||
totp_secret_nonce BLOB,
|
||||
-- Last accepted TOTP counter value; prevents replay attacks within the
|
||||
-- ±1 time-step window (RFC 6238 §5.2). NULL = no code accepted yet.
|
||||
last_totp_counter INTEGER DEFAULT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
|
||||
deleted_at TEXT
|
||||
@@ -661,10 +684,13 @@ or a keyfile path — never inline in the config file.
|
||||
|
||||
```toml
|
||||
[server]
|
||||
listen_addr = "0.0.0.0:8443"
|
||||
grpc_addr = "0.0.0.0:9443" # optional; omit to disable gRPC
|
||||
tls_cert = "/etc/mcias/server.crt"
|
||||
tls_key = "/etc/mcias/server.key"
|
||||
listen_addr = "0.0.0.0:8443"
|
||||
grpc_addr = "0.0.0.0:9443" # optional; omit to disable gRPC
|
||||
tls_cert = "/etc/mcias/server.crt"
|
||||
tls_key = "/etc/mcias/server.key"
|
||||
# trusted_proxy = "127.0.0.1" # optional; IP of reverse proxy — when set,
|
||||
# X-Forwarded-For is trusted only from this IP
|
||||
# for rate limiting and audit log IP extraction
|
||||
|
||||
[database]
|
||||
path = "/var/lib/mcias/mcias.db"
|
||||
@@ -711,7 +737,8 @@ mcias/
|
||||
│ ├── policy/ # in-process authorization policy engine (§20)
|
||||
│ ├── server/ # HTTP handlers, router setup
|
||||
│ ├── token/ # JWT issuance, validation, revocation
|
||||
│ └── ui/ # web UI context, CSRF, session, template handlers
|
||||
│ ├── ui/ # web UI context, CSRF, session, template handlers
|
||||
│ └── validate/ # input validation helpers (username, password strength)
|
||||
├── web/
|
||||
│ ├── static/ # CSS and static assets
|
||||
│ └── templates/ # HTML templates (base layout, pages, HTMX fragments)
|
||||
@@ -761,6 +788,9 @@ The `cmd/` packages are thin wrappers that wire dependencies and call into
|
||||
| `totp_removed` | TOTP removed from account |
|
||||
| `pgcred_accessed` | Postgres credentials retrieved |
|
||||
| `pgcred_updated` | Postgres credentials stored/updated |
|
||||
| `pgcred_access_granted` | Read access to PG credentials granted to another account |
|
||||
| `pgcred_access_revoked` | Read access to PG credentials revoked from an account |
|
||||
| `password_changed` | Account password changed (self-service or admin reset) |
|
||||
| `tag_added` | Tag added to account |
|
||||
| `tag_removed` | Tag removed from account |
|
||||
| `policy_rule_created` | Policy rule created |
|
||||
@@ -838,6 +868,7 @@ mciasdb --config PATH <subcommand> [flags]
|
||||
|---|---|
|
||||
| `mciasdb schema verify` | Open DB, run migrations in dry-run mode, report version |
|
||||
| `mciasdb schema migrate` | Apply any pending migrations and exit |
|
||||
| `mciasdb schema force --version N` | Force schema version (clears dirty state); break-glass recovery |
|
||||
| `mciasdb prune tokens` | Delete expired rows from `token_revocation` and `system_tokens` |
|
||||
|
||||
**Account management (offline):**
|
||||
@@ -943,7 +974,7 @@ in `proto/generate.go` using `protoc-gen-go` and `protoc-gen-go-grpc`.
|
||||
|---|---|
|
||||
| `AuthService` | `Login`, `Logout`, `RenewToken`, `EnrollTOTP`, `ConfirmTOTP`, `RemoveTOTP` |
|
||||
| `TokenService` | `ValidateToken`, `IssueServiceToken`, `RevokeToken` |
|
||||
| `AccountService` | `ListAccounts`, `CreateAccount`, `GetAccount`, `UpdateAccount`, `DeleteAccount`, `GetRoles`, `SetRoles` |
|
||||
| `AccountService` | `ListAccounts`, `CreateAccount`, `GetAccount`, `UpdateAccount`, `DeleteAccount`, `GetRoles`, `SetRoles`, `GrantRole`, `RevokeRole` |
|
||||
| `CredentialService` | `GetPGCreds`, `SetPGCreds` |
|
||||
| `AdminService` | `Health`, `GetPublicKey` |
|
||||
|
||||
@@ -1374,9 +1405,10 @@ const (
|
||||
ActionReadAudit Action = "audit:read"
|
||||
ActionEnrollTOTP Action = "totp:enroll" // self-service
|
||||
ActionRemoveTOTP Action = "totp:remove" // admin
|
||||
ActionLogin Action = "auth:login" // public
|
||||
ActionLogout Action = "auth:logout" // self-service
|
||||
ActionListRules Action = "policy:list"
|
||||
ActionLogin Action = "auth:login" // public
|
||||
ActionLogout Action = "auth:logout" // self-service
|
||||
ActionChangePassword Action = "auth:change_password" // self-service
|
||||
ActionListRules Action = "policy:list"
|
||||
ActionManageRules Action = "policy:manage"
|
||||
|
||||
// Resource types
|
||||
@@ -1476,8 +1508,10 @@ at the same priority level.
|
||||
|
||||
```
|
||||
Priority 0, Allow: roles=[admin], actions=<all> — admin wildcard
|
||||
Priority 0, Allow: actions=[tokens:renew, auth:logout] — self-service logout/renew
|
||||
Priority 0, Allow: actions=[auth:logout, tokens:renew] — self-service logout/renew
|
||||
Priority 0, Allow: actions=[totp:enroll] — self-service TOTP enrollment
|
||||
Priority 0, Allow: accountTypes=[human], actions=[auth:change_password]
|
||||
— self-service password change
|
||||
Priority 0, Allow: accountTypes=[system], actions=[pgcreds:read],
|
||||
resourceType=pgcreds, ownerMatchesSubject=true
|
||||
— system account reads own creds
|
||||
|
||||
Reference in New Issue
Block a user