gitea: add the gitea token secrets engine (mount, config, teabot roles) #101

Open
unkinben wants to merge 2 commits from benvin/gitea-secret-engine into master
Owner

Why

teabot's implementer and reviewer bot users should mint ephemeral, scoped Gitea tokens on demand rather than holding standing personal access tokens — Gitea tokens never expire on their own, so a leak lasts until someone notices. This registers and mounts the new vault-plugin-secrets-gitea engine (released v0.1.0) and declares its roles, mirroring the rancher engine wiring.

Change

  • Register the plugin in the catalog (config/plugins/vault-plugin-secrets-gitea.yaml), pinned to the released v0.1.0 binary sha256 8f67fbc216effada5fd7399888a710b62fad83be0b31761a439e7dec3d56509b (sha256 of /opt/openbao-plugins/vault-plugin-secrets-gitea from the released openbao-plugin-secrets-gitea-0.1.0 RPM).
  • Add gitea_secret_backend + gitea_secret_backend_role modules and wire them through config.hcl, environments/au/syd1/terragrunt.hcl, and modules/vault_cluster variables/main, using the giteavaultsecret provider from the terraform-unkin registry (v0.1.0).
  • Mount the engine at gitea/ against https://git.unkin.net; seeded site-admin credentials are read from KV (service/vault/au/syd1/secret_backend/gitea/config, keys admin_username/admin_password) — not stored in git.
  • The seed is consumed create-only: lifecycle ignore_changes on admin_username/admin_password means the engine reads the KV seed only when first creating gitea/config. After rotate-root diverges the live password from the seed, a later apply never pushes the stale seed back.
  • Add roles with conservative, minimal scopes (write: implies read:):
    • teabot-implementerwrite:repository, write:issue (clone/push, open PRs, comment).
    • teabot-reviewerread:repository, write:issue (read diffs, post PR reviews/comments).
  • TTLs: ttl 1h / max_ttl 4h on both roles.

The site-admin bot + KV seed are now provisioned by Terraform (no manual gap)

Per Ben's review, creating the site-admin bot and seeding its credential is no longer a manual step:

  • terraform-git #46 creates the gitea-vault-admin site-admin bot and writes its generated password once to kv/service/vault/au/syd1/secret_backend/gitea/config (create-only KV write; never updated).
  • terraform-vault #102 grants terraform-git write access to that KV path.

Ordering (merge + apply)

  1. puppet-prod #498 — installs the plugin binary on the vault nodes (Puppet must run).
  2. terraform-vault #100 (benvin/gitea-deployer-access) — deployer access to the gitea mount.
  3. terraform-vault #102 (benvin/gitea-kv-writer) — terraform-git KV write grant.
  4. terraform-git #46 (benvin/gitea-vault-admin) — creates the bot + seeds KV.
  5. This PR — mounts the engine (reads the seed) and declares roles.

Files here are disjoint from #100 and #102 (no conflict).

CI note: the plan for this PR may hard-fail in CI if the plugin isn't yet registered/installed or the KV seed isn't present in the plan's target. If CI plan fails for that ordering reason, that is expected — do not force; apply only once steps 1–4 are live.

Remaining manual step (one, ordered)

After this PR's first apply, run vault write -f gitea/config/rotate-root so the standing seed password is replaced by one only Vault holds. (On future binary upgrades, bump the RPM version in puppet-prod and the catalog sha256 here together, then vault write sys/plugins/reload/backend plugin=vault-plugin-secrets-gitea.)

https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv

## Why teabot's implementer and reviewer bot users should mint **ephemeral, scoped Gitea tokens** on demand rather than holding standing personal access tokens — Gitea tokens never expire on their own, so a leak lasts until someone notices. This registers and mounts the new `vault-plugin-secrets-gitea` engine (released v0.1.0) and declares its roles, mirroring the rancher engine wiring. ## Change - Register the plugin in the catalog (`config/plugins/vault-plugin-secrets-gitea.yaml`), pinned to the released v0.1.0 binary `sha256 8f67fbc216effada5fd7399888a710b62fad83be0b31761a439e7dec3d56509b` (sha256 of `/opt/openbao-plugins/vault-plugin-secrets-gitea` from the released `openbao-plugin-secrets-gitea-0.1.0` RPM). - Add `gitea_secret_backend` + `gitea_secret_backend_role` modules and wire them through `config.hcl`, `environments/au/syd1/terragrunt.hcl`, and `modules/vault_cluster` variables/main, using the `giteavaultsecret` provider from the `terraform-unkin` registry (v0.1.0). - Mount the engine at `gitea/` against `https://git.unkin.net`; seeded site-admin credentials are read from KV (`service/vault/au/syd1/secret_backend/gitea/config`, keys `admin_username`/`admin_password`) — not stored in git. - **The seed is consumed create-only**: `lifecycle ignore_changes` on `admin_username`/`admin_password` means the engine reads the KV seed only when first creating `gitea/config`. After `rotate-root` diverges the live password from the seed, a later apply never pushes the stale seed back. - Add roles with conservative, minimal scopes (write: implies read:): - `teabot-implementer` — `write:repository`, `write:issue` (clone/push, open PRs, comment). - `teabot-reviewer` — `read:repository`, `write:issue` (read diffs, post PR reviews/comments). - TTLs: `ttl` 1h / `max_ttl` 4h on both roles. ## The site-admin bot + KV seed are now provisioned by Terraform (no manual gap) Per Ben's review, creating the site-admin bot and seeding its credential is no longer a manual step: - **terraform-git #46** creates the `gitea-vault-admin` site-admin bot and writes its generated password **once** to `kv/service/vault/au/syd1/secret_backend/gitea/config` (create-only KV write; never updated). - **terraform-vault #102** grants terraform-git write access to that KV path. ## Ordering (merge + apply) 1. **puppet-prod #498** — installs the plugin binary on the vault nodes (Puppet must run). 2. **terraform-vault #100** (`benvin/gitea-deployer-access`) — deployer access to the gitea mount. 3. **terraform-vault #102** (`benvin/gitea-kv-writer`) — terraform-git KV write grant. 4. **terraform-git #46** (`benvin/gitea-vault-admin`) — creates the bot + seeds KV. 5. **This PR** — mounts the engine (reads the seed) and declares roles. Files here are disjoint from #100 and #102 (no conflict). **CI note:** the plan for this PR may hard-fail in CI if the plugin isn't yet registered/installed or the KV seed isn't present in the plan's target. If CI plan fails for that ordering reason, that is expected — do not force; apply only once steps 1–4 are live. ## Remaining manual step (one, ordered) After this PR's first apply, run `vault write -f gitea/config/rotate-root` so the standing seed password is replaced by one only Vault holds. (On future binary upgrades, bump the RPM version in puppet-prod and the catalog `sha256` here together, then `vault write sys/plugins/reload/backend plugin=vault-plugin-secrets-gitea`.) https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
unkinben added 1 commit 2026-07-27 19:05:51 +10:00
gitea: add the gitea token secrets engine (mount, config, teabot roles)
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
a960757ab2
Why: teabot's implementer and reviewer bot users should mint ephemeral,
scoped Gitea tokens on demand instead of holding standing personal access
tokens (Gitea tokens never expire on their own). This registers and mounts
the new vault-plugin-secrets-gitea engine and declares its roles, mirroring
the rancher engine wiring.

Change:
- Register the plugin in the catalog (config/plugins/vault-plugin-secrets-gitea.yaml)
  pinned to the released v0.1.0 binary sha256.
- Add gitea_secret_backend + gitea_secret_backend_role modules and wire them
  through config.hcl, terragrunt.hcl, and vault_cluster variables/main, using
  the giteavaultsecret provider (terraform-unkin registry, v0.1.0).
- Mount the engine at gitea/ against https://git.unkin.net; seeded site-admin
  credentials are read from KV (service/vault/au/syd1/secret_backend/gitea/config).
- Add teabot-implementer (write:repository, write:issue) and teabot-reviewer
  (read:repository, write:issue) roles, ttl 1h / max_ttl 4h.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
Owner

Seed the KV admin credential BEFORE apply: write admin_username + admin_password to kv/service/vault/au/syd1/secret_backend/gitea/config for a purpose-built Gitea site-admin bot with 2FA disabled (local user). GAP for a human: creating that site-admin bot account in Gitea is out of scope for this PR chain and does not exist yet — it must be provisioned before this applies.

Can this not be done by terraform-git? It should be able to write git user passwords to vault. The vault gitea module in the vault repo should only use the password/user kv when initially creating the secret engine. After that it’s ignored. In terraform git, we should be able to write a random password once and not update it after that

`Seed the KV admin credential BEFORE apply: write admin_username + admin_password to kv/service/vault/au/syd1/secret_backend/gitea/config for a purpose-built Gitea site-admin bot with 2FA disabled (local user). GAP for a human: creating that site-admin bot account in Gitea is out of scope for this PR chain and does not exist yet — it must be provisioned before this applies. ` Can this not be done by terraform-git? It should be able to write git user passwords to vault. The vault gitea module in the vault repo should only use the password/user kv when initially creating the secret engine. After that it’s ignored. In terraform git, we should be able to write a random password once and not update it after that
unkinben added 1 commit 2026-07-27 19:31:20 +10:00
gitea: consume the KV admin seed only at engine-config creation
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
13c1f5c1ba
Why: after the engine is first configured, rotate-root changes the live admin
password so it diverges from the KV seed. Re-reading the (possibly stale) seed
on a later apply must not push it back and clobber the rotated password. Ben
asked that the seed be used only when initially creating the config.

Change:
- Add lifecycle ignore_changes on admin_username/admin_password to the
  gitea_secret_backend resource, making the module create-only for the seeded
  credential. Noted inline that the rancher/litellm seed modules lack this.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
Author
Owner

Yes — done in Terraform, no manual gap:

  • terraform-git #46 creates the gitea-vault-admin site-admin bot and writes its generated password to kv/service/vault/au/syd1/secret_backend/gitea/config. The write is create-only (random_password never regenerates, and lifecycle ignore_changes = [data_json] on the vault_kv_secret_v2), so the password is seeded once and never updated after.
  • terraform-vault #102 grants terraform-git write access to that KV path.
  • This PR's gitea module now uses the seed only at creation: ignore_changes on admin_username/admin_password, so once gitea/config exists, a later apply won't push the (post-rotate-root stale) seed back over the live password.

Apply order: #100#102 → terraform-git #46 → this. vault write -f gitea/config/rotate-root after first apply is the only remaining manual step.

Yes — done in Terraform, no manual gap: - terraform-git #46 creates the `gitea-vault-admin` site-admin bot and writes its generated password to `kv/service/vault/au/syd1/secret_backend/gitea/config`. The write is create-only (`random_password` never regenerates, and `lifecycle ignore_changes = [data_json]` on the `vault_kv_secret_v2`), so the password is seeded once and never updated after. - terraform-vault #102 grants terraform-git write access to that KV path. - This PR's gitea module now uses the seed only at creation: `ignore_changes` on `admin_username`/`admin_password`, so once `gitea/config` exists, a later apply won't push the (post-rotate-root stale) seed back over the live password. Apply order: #100 → #102 → terraform-git #46 → this. `vault write -f gitea/config/rotate-root` after first apply is the only remaining manual step.
All checks were successful
ci/woodpecker/pr/plan Pipeline was successful
Required
Details
ci/woodpecker/pr/pre-commit Pipeline was successful
Required
Details
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin benvin/gitea-secret-engine:benvin/gitea-secret-engine
git checkout benvin/gitea-secret-engine
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/terraform-vault#101