API keys for server scope: edges, server alerts and orgs can be scripted
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
39659f0144
commit
1c2a5b71bd
6 files changed
+232
-9
No files matched your search
@@ -0,0 +1,36 @@
|
||||
# Scripting Hammerhead: API audit
|
||||
|
||||
Everything the dashboard does goes through the JSON API (`server.go` lists the routes). Callers
|
||||
authenticate with the `hh_session` cookie or `Authorization: Bearer hhk_<id>_<secret>`.
|
||||
|
||||
## Credentials
|
||||
|
||||
| Credential | Reaches | Made at |
|
||||
|---|---|---|
|
||||
| Organization key | that organization's `/api/orgs/{org}/...` routes (admin rights), `GET /api/orgs`, `GET /api/edges` (edges the org may use) | `POST /api/orgs/{org}/apikeys` |
|
||||
| Server key | every organization, plus the server-admin routes: edges, `/api/admin/alerts`, users, settings, `POST /api/orgs` | `POST /api/admin/apikeys` (signed-in server admin only) |
|
||||
|
||||
The secret is shown once, in the `key` field of the create response. A key cannot mint keys at server
|
||||
level, and a server key has no user, so `/api/me` and other per-user routes refuse it.
|
||||
|
||||
## Gaps found, and what was done
|
||||
|
||||
| Gap | Resolution |
|
||||
|---|---|
|
||||
| Edges, server alerts, `POST /api/orgs` required a browser session (`withServerAdmin` refused keys) | server keys, accepted by `withServerAdmin` |
|
||||
| No way to mint an unattended server credential | `GET/POST/DELETE /api/admin/apikeys` |
|
||||
| `GET /api/edges` was session-only | accepts keys; an org key sees the edges its org may use |
|
||||
| No way to list orgs with a key | `GET /api/orgs` |
|
||||
| Key creation did not return the key's ID | create response now has `id` as well as `key` |
|
||||
| `createOrg` added the caller as a member | skipped for server keys (they have no user) |
|
||||
|
||||
## Known remaining gaps (not blocking scripting)
|
||||
|
||||
- No per-resource `GET`: sites, domains, ports and alert channels are read from `GET /api/orgs/{org}/state` and
|
||||
`GET /api/orgs/{org}/alerts`. Clients filter by ID.
|
||||
- Alert channel secrets (webhook URL, Sandbar key) are never returned, so a client can't detect drift in them; a
|
||||
blank value on `PUT` keeps the stored one.
|
||||
- Keys are all-powerful within their scope (no read-only or per-resource scopes), and have no expiry.
|
||||
- `PUT` on ports replaces the whole object; omitted fields reset.
|
||||
- Site tokens are returned on create and, for admins, in `state`.
|
||||
- Deleting an edge/site does not check for ports that use it (the server cleans up or refuses; clients should order deletes).
|
||||
Reference in new issue
Block a user