CF Access Service Token Rotation
CF Access Service Token Rotation (docs.alai.no / BookStack)
MC: #99235 (cleanup) — follow-up to Proveo audit #99027 (2026-05-05), deferred from kelsey-hightower subtask 3 on #99027.
Background
docs.alai.no (BookStack, Azure VM 4.223.110.181) sits behind Cloudflare Access. All
programmatic API calls (BookStack REST API, sync tooling) need two credential pairs:
- BookStack API token —
Authorization: Token <token_id>:<token_secret>(BookStack user token) - CF Access service token —
CF-Access-Client-Id+CF-Access-Client-Secretheaders (bypasses the CF Access login redirect for non-interactive clients)
Both live in ~/system/config/bookstack.json (local cache) and, for the BookStack token,
in Vaultwarden item "BookStack API" (fe418612-0d17-4e80-9b2e-39ef7c213b61).
Finding: CF_ACCESS_CLIENT_SECRET leaked in git history
~/system/config/bookstack.json was git-tracked with the CF Access client secret in
plaintext from 2026-02-12 through ~1775 auto-backup commits (repo ~/system, private,
external exposure minimal per CEO risk assessment 2026-05-05).
CEO decision (2026-05-05): document, do NOT rotate the token immediately.
Status as of 2026-07-29 (MC #99235 cleanup pass):
config/bookstack.jsonHEAD content had already been redacted in commite3e6fe36bd(2026-07-28 21:00 auto-backup) —cf_access_client_id/cf_access_client_secretreplaced with[REDACTED — see vault item b42cb5c2].- ⚠️ That vault pointer is wrong. Vaultwarden item
b42cb5c2-dc9b-4a43-bcc7-4adcfde992b2is named "ligthrag monitor deamon service token" and holds a CF Access pair for a different service (client_idstarting4248b2c1...), not thed9c7d65a...client_id that was actually inbookstack.json's history. The real BookStack CF Access service-token credential does not currently have a confirmed Vaultwarden home — treat as not yet rotated, not yet safely stored, and flag to CEO before relying on that note. config/bookstack.jsonandconfig/.bookstack-cred-cache.jsonwere still git-tracked (gitignore had no entry) as of this pass, meaning any future edit — including someone restoring a real secret into the file to fix the tool — would re-leak it. Fixed in commits97552323df(.gitignore) +4c69de88f8(untrack both files; local copies preserved on disk,bookstack-sync.jsstill reads/caches them exactly as before).- The BookStack API token itself (
token_secretfield, used forAuthorization: Token) is still plaintext in the current file and in every historical commit. Same exposure class as the CF secret; not in scope of the original #99027 finding but should be rotated together if/when the CF token is rotated. - Git history purge (removing the secret from all ~1775+ past commits) was NOT done —
coordinate with the
~/systemgit-history cleanup lineage (MC #105751, filter-repo based) before attempting; do not run filter-repo ad hoc without that runbook's safety steps.
Rotation procedure (when CEO approves)
- Generate new service token in Cloudflare Zero Trust dashboard → Access → Service Auth
→ Service Tokens → create/rotate the token scoped to
docs.alai.no(and any other*.alai.nohost sharing the same Access policy). - Store in Vaultwarden as a dedicated item (do not reuse an unrelated item like
b42cb5c2). Recommended: new item "BookStack CF Access" with fieldscf-access-client-id/cf-access-client-secret, matching the field-name patternbookstack-sync.jsalready expects when a vault item does carry these fields (loadConfigFromVault()readsfields.cf_access_client_id/fields.cf_access_client_secretfrom the "BookStack API" item — either add the fields there, or update~/system/tools/bookstack-sync.js:118-130to also check the new item name). - Update
~/system/config/bookstack.jsonwith the new pair (file is now gitignored — editing it will NOT create a new leak). - Revoke the old token in Cloudflare Zero Trust once the new one is verified working:
curl -I -H "CF-Access-Client-Id: <new>" -H "CF-Access-Client-Secret: <new>" https://docs.alai.no/api/docs→ expect200. - Verify sync still works:
node ~/system/tools/bookstack-sync.js statusshould list pages withoutVault unreachableorHTTP 401/403errors. - Update this runbook with the new Vaultwarden item ID once done.
Prevention (already applied, MC #99235)
config/bookstack.jsonandconfig/.bookstack-cred-cache.jsonadded to~/system/.gitignoreand untracked from git (commits97552323df,4c69de88f8).- Local files remain in place at
~/system/config/—bookstack-sync.jsbehavior unchanged. - History purge is a separate, deliberately-deferred step (CEO 2026-05-05 decision) — do not schedule without explicit CEO go-ahead, and do it as part of the git-history cleanup lineage (MC #105751), not standalone.