Merge pull request 'user: add gitea-vault-admin site-admin bot with one-time Vault KV seeding' (#46) from benvin/gitea-vault-admin into main
ci/woodpecker/push/apply Pipeline failed

Reviewed-on: #46
This commit was merged in pull request #46.
This commit is contained in:
2026-07-27 21:47:31 +10:00
8 changed files with 77 additions and 0 deletions
@@ -0,0 +1,21 @@
# Purpose-built Gitea site-admin bot for the vault-plugin-secrets-gitea engine.
# The engine seeds itself from this account's credentials (Basic Auth) to mint
# and delete per-user tokens for any user. Its randomly generated password is
# written ONCE to Vault KV (vault_seed_path below) and never updated after; the
# Vault gitea engine reads that seed only when first creating gitea/config and
# then rotates it (rotate-root) so only Vault holds the live password.
#
# A local (not external-auth) account with 2FA disabled is required so the
# engine can change the password via the admin API during rotate-root.
email: gitea-vault-admin@unkin.net
full_name: "Gitea Vault Admin"
description: "site-admin bot; credentials seeded to Vault for vault-plugin-secrets-gitea"
# Site admin so the engine may mint/delete tokens for any user. No org/repo
# creation; profile visible only to signed-in users.
visibility: limited
admin: true
allow_create_organization: false
max_repo_creation: 0
# Seed this account's generated password to Vault KV (mount "kv") at this path,
# where the Vault gitea secrets engine reads it at creation time. Written once.
vault_seed_path: "service/vault/au/syd1/secret_backend/gitea/config"
+5
View File
@@ -11,6 +11,11 @@ provider "woodpecker" {
server = "https://ci.k8s.syd1.au.unkin.net"
}
# Address + token come from VAULT_ADDR / VAULT_TOKEN in the environment (the
# Makefile authenticates via k8s auth before running terragrunt). Used to seed
# bot-account credentials into Vault KV (see modules/user vault_seed_path).
provider "vault" {}
terraform {
backend "consul" {
address = "https://consul.service.consul"
+2
View File
@@ -55,6 +55,8 @@ module "user" {
allow_create_organization = each.value.allow_create_organization
max_repo_creation = each.value.max_repo_creation
must_change_password = each.value.must_change_password
vault_seed_path = each.value.vault_seed_path
vault_seed_mount = each.value.vault_seed_mount
}
module "team" {
@@ -35,3 +35,24 @@ resource "gitea_user" "this" {
ignore_changes = [password]
}
}
# Optional one-time seed of the account's credentials to Vault KV, for the
# vault-plugin-secrets-gitea engine to consume when it first creates gitea/config.
# random_password never regenerates (no keepers), so the seed is stable; the
# ignore_changes below makes the write strictly create-only, so a later
# rotate-root on the Vault side (which diverges the live password from this seed)
# is never clobbered by a re-apply here.
resource "vault_kv_secret_v2" "seed" {
count = var.vault_seed_path != null ? 1 : 0
mount = var.vault_seed_mount
name = var.vault_seed_path
data_json = jsonencode({
admin_username = var.username
admin_password = random_password.this.result
})
lifecycle {
ignore_changes = [data_json]
}
}
@@ -9,5 +9,9 @@ terraform {
source = "hashicorp/random"
version = ">= 3.5"
}
vault = {
source = "hashicorp/vault"
version = ">= 4.3"
}
}
}
@@ -67,3 +67,21 @@ variable "must_change_password" {
type = bool
default = false
}
variable "vault_seed_path" {
description = <<-EOT
Optional. When set, the account's generated password is seeded ONCE to Vault
KV at this secret name (under vault_seed_mount) as admin_username +
admin_password, for the vault-plugin-secrets-gitea engine to consume at
creation time. The write is create-only; subsequent changes are ignored so
the seed never churns (and never overwrites a rotated password).
EOT
type = string
default = null
}
variable "vault_seed_mount" {
description = "KV v2 mount holding the seeded credential (used only when vault_seed_path is set)"
type = string
default = "kv"
}
+4
View File
@@ -13,5 +13,9 @@ terraform {
source = "hashicorp/random"
version = ">= 3.5"
}
vault = {
source = "hashicorp/vault"
version = ">= 4.3"
}
}
}
+2
View File
@@ -79,6 +79,8 @@ variable "user" {
allow_create_organization = optional(bool, false)
max_repo_creation = optional(number, 0)
must_change_password = optional(bool, false)
vault_seed_path = optional(string)
vault_seed_mount = optional(string, "kv")
}))
default = {}
}