Authenticate scripts and CI with API tokens
When a script, a CI job or an external agent needs to call the Ring API, don't hand it a human's login session, which is unscoped and opens the whole cluster. Issue a scoped API token instead: it's limited to the scopes and namespaces you grant, it can expire, and you can revoke it the moment it leaks.
Create a token with the least privilege it needs
Pick the narrowest scope set for the job. A pipeline that only reads deployment status needs deployments:read; one that deploys needs deployments:write, ideally pinned to a single namespace.
# Read-only status checks, all namespaces, expires in 90 days ring token create ci-status --scope deployments:read --expires 90d # Deploy to production only ring token create deployer \ --scope deployments:write \ --namespace production
The clear token is printed on stdout; the summary and the "won't be shown again" notice go to stderr. That makes it safe to capture:
TOKEN=$(ring token create ci-status --scope deployments:read --expires 90d)
The clear
ring_pat_…value is shown once. Ring stores only a hash, so if you lose it, rotate the token, don't try to recover it.
Available scopes: deployments:read, deployments:write, secrets:read, secrets:write, configs:read, configs:write, namespaces:read, namespaces:write, users:read, users:write, and admin (everything).
Use the token
Send it as a Bearer credential, exactly like a session token:
curl -H "Authorization: Bearer $TOKEN" https://ring.example.com/deployments
If the token lacks the scope an endpoint requires, or the request targets a namespace outside its boundary, the API returns 403 Forbidden. An expired or revoked token returns 401 Unauthorized.
In a CI pipeline
Store the token as a masked secret (e.g. a GitHub Actions secret RING_TOKEN) and read it from the environment:
- name: Trigger deploy env: RING_TOKEN: ${{ secrets.RING_TOKEN }} run: | curl -fsS -X POST https://ring.example.com/deployments \ -H "Authorization: Bearer $RING_TOKEN" \ -H 'Content-Type: application/json' \ -d @manifest.json
List, revoke and rotate
Token management (list, get, create, revoke, rotate) is an administrative action: it needs a full-access login session or an admin-scoped token. A data-plane token scoped to, say, deployments:write cannot manage tokens (including its own), so a leaked low-privilege token can't mint or rotate itself into a stronger one.
ring token list
shows each token's prefix, scopes, namespaces, status (active / revoked / expired), last-used and expiry, but never the secret.
When a token is no longer needed, or you suspect it leaked, revoke it:
ring token revoke <ID> # prompts for confirmation on a terminal ring token revoke <ID> --yes # non-interactive (CI)
To replace a token without changing what it grants (for scheduled rotation, or right after a leak), rotate it. The old value stops working immediately and a new one is printed:
NEW=$(ring token rotate <ID>)
<ID> comes from ring token list.
Good practices
- One token per consumer. A token per pipeline/agent means revoking one doesn't break the others, and
last_used_attells you who's still active. - Scope to a namespace whenever the consumer only touches one, so a leaked production-only token can't reach staging or other tenants.
- Set an expiry. A token that never expires is a liability;
--expires 90dand a rotation reminder cost nothing. - Read-only by default. Only grant
:writescopes to consumers that actually mutate state.
Every create, revoke and rotate is recorded in Ring's audit log, so the token lifecycle is auditable after the fact.