Files
Hammerhead/docs/api-automation.md

2.3 KiB

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
Creating an alert channel returned only {ok:true} response now includes the channel id
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 or site cascades silently (its ports and domains go with it, as do ports left with no target), so Terraform plans should not rely on dependent resources surviving.