Wire Forge-native release infrastructure
Some checks failed
Cache: Publish Nix / Publish Nix Cache (push) Waiting to run
Build Rust / Cargo Test (push) Successful in 4m14s
Build Site / Next.js Build (push) Failing after 6s
Infra: OpenTofu / OpenTofu (grafana) (push) Successful in 5s
Lint Governance / BEP Metadata (push) Successful in 0s
Build: Android / Android Rust Core Stub (push) Failing after 23s
Some checks failed
Cache: Publish Nix / Publish Nix Cache (push) Waiting to run
Build Rust / Cargo Test (push) Successful in 4m14s
Build Site / Next.js Build (push) Failing after 6s
Infra: OpenTofu / OpenTofu (grafana) (push) Successful in 5s
Lint Governance / BEP Metadata (push) Successful in 0s
Build: Android / Android Rust Core Stub (push) Failing after 23s
This commit is contained in:
parent
97c569fb35
commit
002bd382e9
199 changed files with 14268 additions and 185 deletions
5
infra/openbao/.gitignore
vendored
Normal file
5
infra/openbao/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.terraform/
|
||||
backend.hcl
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
*.tfplan
|
||||
43
infra/openbao/.terraform.lock.hcl
generated
Normal file
43
infra/openbao/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# This file is maintained automatically by "tofu init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/google" {
|
||||
version = "6.50.0"
|
||||
constraints = ">= 5.40.0, < 7.0.0"
|
||||
hashes = [
|
||||
"h1:MAAe4zFFdqS9M5rpmJK/vKgdb6ZMD/s/0Xd97yTDipA=",
|
||||
"zh:1d4695f807d998f11fcdcfa174766287b82a8093513af857bcdad2d81c642480",
|
||||
"zh:3173ac5df0294624d113812e49e2a55714aff7db617488168cecdf4168df9e29",
|
||||
"zh:34d2b3d44c23bd6354fc4ab5917b302872ea1ab8de107034567f955b1717fa5b",
|
||||
"zh:3a77f3cc2f3664cd5aaeeef4d044e6ec1695a079588fffec3ca03953664e5f04",
|
||||
"zh:6b444e4b629ea8dc8cb112a39dde098dc5584d26d6de4177558f556a9a226696",
|
||||
"zh:96545c8cd4d3a57069c5d1799eab5aedd887e16d98b5559a195f6d2c2d9bc674",
|
||||
"zh:ba464caafde95ee16671d6b5ec90f053ed77a9d06c567456db6efd9160fa3165",
|
||||
"zh:d876938e5b0d3f57a984d9be72467995f87fef6569968623415dc51d9f54d30b",
|
||||
"zh:dfd908d873e314ab807d0abc9cfd42d2611cd06dc1b9ec719ebdbb738e8e68d6",
|
||||
"zh:f9f16819a7738d564afd45fd169ba61004ec4e4e7089d2a4950cb8895be1fe1f",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/vault" {
|
||||
version = "5.9.0"
|
||||
constraints = ">= 4.5.0, < 6.0.0"
|
||||
hashes = [
|
||||
"h1:9U4AT36IqNYXfQMR7nf+oywulVKYua473W4NmuwVb7M=",
|
||||
"zh:03cb46fab606872e3fc06e27f8d14b911b7a9781d0f32af335c7287a9dbe4f4f",
|
||||
"zh:1e69677b09329b009a8791f9cbb556790fb4dbddc1360f953345259892dc6c5b",
|
||||
"zh:4e5a3dc82e70d88f5671968b7f2217163815be259d0b26dfcc9a897409c491fa",
|
||||
"zh:51b82b358fe52099ef29cae62e2040ae0224ceea40a7dfdf0b69de90fb0233a8",
|
||||
"zh:60ec3477fbe712b3269eec2e4d9d5921e2e68d0861d77e11e91bea088aab27bf",
|
||||
"zh:64e58a3e3fd61005b54d71eee792b8576ab42ea4cd711515043a3ac0d8bc7919",
|
||||
"zh:69142fb83aff31e27f5b3d9e7afb7594013b63e490cfcef8678fd0d724609359",
|
||||
"zh:6f2e58ba6bd41c4d9e0e752e55eb7d86104f9d786cf57fa8dc960c61b574f9ce",
|
||||
"zh:73390b7cb186310e5aaf4a1baaa639ab0302a8da4db130b4e28ebced3ba103fe",
|
||||
"zh:a2214b3fda93cfed89ba1a7d714fe8b015176927605b215365978efdaae1c6db",
|
||||
"zh:b275ee0f0a63765364d2e6979e3a11464d2c2ce6d3ce9bd15b3f503aea6f12b0",
|
||||
"zh:bb2cd553b1c589a0f6f5b0575e1b176a9d91c1b20c6375d1afd63bb2a47fd014",
|
||||
"zh:bc38e48ae5cdb8219fef326366f46e6a25e7f77f9bbcd9bdc80c7cb960de81ed",
|
||||
"zh:e54af55cf667759a400af07b927b5034f1733e6527f9352b84001205561dcf9e",
|
||||
"zh:f617688ef4568c0de8a28d5e1fa3714fb2eeab9f8cf7bcf20af42a1a511844be",
|
||||
]
|
||||
}
|
||||
36
infra/openbao/README.md
Normal file
36
infra/openbao/README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Burrow OpenBao Control Plane
|
||||
|
||||
This OpenTofu stack manages non-secret infrastructure around
|
||||
`vault.burrow.net`.
|
||||
|
||||
It may manage:
|
||||
|
||||
- Google KMS seal-wrapping keys for OpenBao
|
||||
- the OpenBao `age/` KV v2 mount used for migrated runtime secrets
|
||||
- OpenBao policies and Authentik OIDC roles
|
||||
- AppRole auth scaffolding for machine consumers
|
||||
|
||||
It must not manage:
|
||||
|
||||
- secret values
|
||||
- root tokens
|
||||
- AppRole SecretIDs
|
||||
- release-signing key material
|
||||
|
||||
## Run
|
||||
|
||||
```sh
|
||||
Scripts/openbao-tofu.sh init -backend-config=backend.hcl
|
||||
Scripts/openbao-tofu.sh plan -var-file=terraform.tfvars
|
||||
```
|
||||
|
||||
For local syntax work:
|
||||
|
||||
```sh
|
||||
Scripts/openbao-tofu.sh init -backend=false
|
||||
Scripts/openbao-tofu.sh validate
|
||||
```
|
||||
|
||||
The Vault/OpenBao provider reads `VAULT_TOKEN` from the environment. Keep
|
||||
`manage_openbao_config = false` until `vault.burrow.net` is initialized and an
|
||||
operator token is available out of band.
|
||||
4
infra/openbao/backend.hcl.example
Normal file
4
infra/openbao/backend.hcl.example
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
bucket = "burrow-opentofu-state"
|
||||
key = "openbao/openbao.tfstate"
|
||||
region = "us-west-2"
|
||||
encrypt = true
|
||||
65
infra/openbao/google.tf
Normal file
65
infra/openbao/google.tf
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
locals {
|
||||
google_required_services = toset([
|
||||
"cloudkms.googleapis.com",
|
||||
"cloudresourcemanager.googleapis.com",
|
||||
"iam.googleapis.com",
|
||||
])
|
||||
|
||||
google_existing_kms_key_ring_id = var.google_kms_key_ring_id != "" ? var.google_kms_key_ring_id : "projects/${var.google_project_id}/locations/${var.google_kms_key_ring_location}/keyRings/${var.google_kms_key_ring_name}"
|
||||
|
||||
google_kms_key_ring_id = var.manage_google_kms_key_ring ? (
|
||||
google_kms_key_ring.openbao[0].id
|
||||
) : local.google_existing_kms_key_ring_id
|
||||
}
|
||||
|
||||
resource "google_project_service" "openbao" {
|
||||
for_each = var.manage_google ? local.google_required_services : toset([])
|
||||
|
||||
project = var.google_project_id
|
||||
service = each.value
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
resource "google_kms_key_ring" "openbao" {
|
||||
count = var.manage_google && var.manage_google_kms_key_ring ? 1 : 0
|
||||
|
||||
project = var.google_project_id
|
||||
location = var.google_kms_key_ring_location
|
||||
name = var.google_kms_key_ring_name
|
||||
|
||||
depends_on = [google_project_service.openbao]
|
||||
}
|
||||
|
||||
resource "google_kms_crypto_key" "openbao_seal" {
|
||||
count = var.manage_google && local.google_kms_key_ring_id != "" ? 1 : 0
|
||||
|
||||
name = var.google_openbao_seal_key_name
|
||||
key_ring = local.google_kms_key_ring_id
|
||||
purpose = "ENCRYPT_DECRYPT"
|
||||
labels = merge(
|
||||
{
|
||||
project = "burrow"
|
||||
component = "openbao"
|
||||
managed_by = "opentofu"
|
||||
key_target = "seal"
|
||||
},
|
||||
var.tags,
|
||||
)
|
||||
|
||||
version_template {
|
||||
algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION"
|
||||
protection_level = "HSM"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
prevent_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_kms_crypto_key_iam_member" "openbao_seal" {
|
||||
for_each = var.manage_google && local.google_kms_key_ring_id != "" ? var.google_openbao_seal_members : toset([])
|
||||
|
||||
crypto_key_id = google_kms_crypto_key.openbao_seal[0].id
|
||||
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
|
||||
member = each.value
|
||||
}
|
||||
125
infra/openbao/openbao.tf
Normal file
125
infra/openbao/openbao.tf
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
resource "vault_mount" "age" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
path = var.age_mount_path
|
||||
type = "kv-v2"
|
||||
description = "Migrated Burrow age-managed runtime secrets."
|
||||
|
||||
options = {
|
||||
version = "2"
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_policy" "admin" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
name = "burrow-openbao-admin"
|
||||
|
||||
policy = <<-EOT
|
||||
path "*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_policy" "runtime_read" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
name = "burrow-runtime-read"
|
||||
|
||||
policy = <<-EOT
|
||||
path "${var.age_mount_path}/data/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
path "${var.age_mount_path}/metadata/*" {
|
||||
capabilities = ["list", "read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_auth_backend" "approle" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
path = var.approle_auth_path
|
||||
type = "approle"
|
||||
description = "Machine auth for Burrow runtime secret consumers."
|
||||
|
||||
tune {
|
||||
token_type = "default-service"
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role" "runtime" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
backend = vault_auth_backend.approle[0].path
|
||||
role_name = var.runtime_approle_role_name
|
||||
bind_secret_id = true
|
||||
|
||||
token_policies = [vault_policy.runtime_read[0].name]
|
||||
token_ttl = var.runtime_approle_token_ttl_seconds
|
||||
token_max_ttl = var.runtime_approle_token_max_ttl_seconds
|
||||
token_num_uses = 0
|
||||
|
||||
secret_id_ttl = var.runtime_approle_secret_id_ttl_seconds
|
||||
secret_id_num_uses = var.runtime_approle_secret_id_num_uses
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend" "authentik" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
path = "oidc"
|
||||
type = "oidc"
|
||||
oidc_discovery_url = var.authentik_issuer
|
||||
bound_issuer = var.authentik_issuer
|
||||
oidc_client_id = var.authentik_client_id
|
||||
default_role = "burrow-admin"
|
||||
|
||||
tune {
|
||||
listing_visibility = "unauth"
|
||||
token_type = "default-service"
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend_role" "admin" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
backend = vault_jwt_auth_backend.authentik[0].path
|
||||
role_name = "burrow-admin"
|
||||
role_type = "oidc"
|
||||
user_claim = "email"
|
||||
|
||||
allowed_redirect_uris = [
|
||||
"https://vault.burrow.net/ui/vault/auth/oidc/oidc/callback",
|
||||
"http://localhost:8250/oidc/callback",
|
||||
]
|
||||
|
||||
bound_audiences = [var.authentik_client_id]
|
||||
bound_claims = {
|
||||
groups = var.authentik_admin_group
|
||||
}
|
||||
oidc_scopes = ["openid", "profile", "email", "groups"]
|
||||
token_policies = [vault_policy.admin[0].name]
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend_role" "runtime" {
|
||||
count = var.manage_openbao_config ? 1 : 0
|
||||
|
||||
backend = vault_jwt_auth_backend.authentik[0].path
|
||||
role_name = "burrow-runtime-read"
|
||||
role_type = "oidc"
|
||||
user_claim = "email"
|
||||
|
||||
allowed_redirect_uris = [
|
||||
"https://vault.burrow.net/ui/vault/auth/oidc/oidc/callback",
|
||||
"http://localhost:8250/oidc/callback",
|
||||
]
|
||||
|
||||
bound_audiences = [var.authentik_client_id]
|
||||
bound_claims = {
|
||||
groups = var.authentik_runtime_group
|
||||
}
|
||||
oidc_scopes = ["openid", "profile", "email", "groups"]
|
||||
token_policies = [vault_policy.runtime_read[0].name]
|
||||
}
|
||||
14
infra/openbao/outputs.tf
Normal file
14
infra/openbao/outputs.tf
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
output "google_kms_key_ring_id" {
|
||||
description = "Google KMS key ring id used by the OpenBao stack."
|
||||
value = local.google_kms_key_ring_id
|
||||
}
|
||||
|
||||
output "google_openbao_seal_key_id" {
|
||||
description = "Google KMS seal key id when managed."
|
||||
value = try(google_kms_crypto_key.openbao_seal[0].id, null)
|
||||
}
|
||||
|
||||
output "openbao_age_mount_path" {
|
||||
description = "OpenBao KV v2 mount path for migrated age secrets."
|
||||
value = var.age_mount_path
|
||||
}
|
||||
8
infra/openbao/providers.tf
Normal file
8
infra/openbao/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
provider "google" {
|
||||
project = var.google_project_id
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
address = var.openbao_address
|
||||
skip_tls_verify = var.openbao_skip_tls_verify
|
||||
}
|
||||
8
infra/openbao/terraform.tfvars.example
Normal file
8
infra/openbao/terraform.tfvars.example
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
manage_google = false
|
||||
manage_openbao_config = false
|
||||
google_project_id = "project-88c23ce9-918a-470a-b33"
|
||||
openbao_address = "https://vault.burrow.net"
|
||||
authentik_issuer = "https://auth.burrow.net/application/o/openbao/"
|
||||
authentik_client_id = "vault.burrow.net"
|
||||
authentik_admin_group = "burrow-admins"
|
||||
authentik_runtime_group = "burrow-automation"
|
||||
137
infra/openbao/variables.tf
Normal file
137
infra/openbao/variables.tf
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
variable "openbao_address" {
|
||||
description = "OpenBao API address. The Vault provider reads the token from VAULT_TOKEN."
|
||||
type = string
|
||||
default = "https://vault.burrow.net"
|
||||
}
|
||||
|
||||
variable "openbao_skip_tls_verify" {
|
||||
description = "Skip TLS verification for local bootstrap only."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "age_mount_path" {
|
||||
description = "KV v2 mount path for migrated age-managed runtime secrets."
|
||||
type = string
|
||||
default = "age"
|
||||
}
|
||||
|
||||
variable "manage_openbao_config" {
|
||||
description = "Manage OpenBao mounts, policies, and Authentik OIDC auth. Requires VAULT_TOKEN."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "authentik_issuer" {
|
||||
description = "Authentik OpenBao OIDC issuer."
|
||||
type = string
|
||||
default = "https://auth.burrow.net/application/o/openbao/"
|
||||
}
|
||||
|
||||
variable "authentik_client_id" {
|
||||
description = "Public Authentik OpenBao OIDC client id."
|
||||
type = string
|
||||
default = "vault.burrow.net"
|
||||
}
|
||||
|
||||
variable "authentik_admin_group" {
|
||||
description = "Authentik group allowed to administer OpenBao."
|
||||
type = string
|
||||
default = "burrow-admins"
|
||||
}
|
||||
|
||||
variable "authentik_runtime_group" {
|
||||
description = "Authentik group allowed to read runtime secrets."
|
||||
type = string
|
||||
default = "burrow-automation"
|
||||
}
|
||||
|
||||
variable "approle_auth_path" {
|
||||
description = "OpenBao AppRole auth mount path for machine consumers."
|
||||
type = string
|
||||
default = "approle"
|
||||
}
|
||||
|
||||
variable "runtime_approle_role_name" {
|
||||
description = "AppRole role name used by Burrow runtime secret consumers."
|
||||
type = string
|
||||
default = "burrow-runtime"
|
||||
}
|
||||
|
||||
variable "runtime_approle_token_ttl_seconds" {
|
||||
description = "Token TTL for runtime AppRole login."
|
||||
type = number
|
||||
default = 3600
|
||||
}
|
||||
|
||||
variable "runtime_approle_token_max_ttl_seconds" {
|
||||
description = "Maximum token TTL for runtime AppRole login."
|
||||
type = number
|
||||
default = 7200
|
||||
}
|
||||
|
||||
variable "runtime_approle_secret_id_ttl_seconds" {
|
||||
description = "SecretID TTL for runtime AppRole. Zero means no expiry; rotate manually."
|
||||
type = number
|
||||
default = 0
|
||||
}
|
||||
|
||||
variable "runtime_approle_secret_id_num_uses" {
|
||||
description = "SecretID use limit for runtime AppRole. Zero means unlimited uses; rotate manually."
|
||||
type = number
|
||||
default = 0
|
||||
}
|
||||
|
||||
variable "manage_google" {
|
||||
description = "Manage Google Cloud KMS resources for OpenBao seal wrapping."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "google_project_id" {
|
||||
description = "Google Cloud project id for OpenBao seal wrapping."
|
||||
type = string
|
||||
default = "project-88c23ce9-918a-470a-b33"
|
||||
}
|
||||
|
||||
variable "manage_google_kms_key_ring" {
|
||||
description = "Create/manage the Google KMS key ring. Existing rings should be imported before enabling this."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "google_kms_key_ring_name" {
|
||||
description = "Google KMS key ring for OpenBao seal wrapping."
|
||||
type = string
|
||||
default = "burrow-identity"
|
||||
}
|
||||
|
||||
variable "google_kms_key_ring_location" {
|
||||
description = "Google KMS key ring location."
|
||||
type = string
|
||||
default = "global"
|
||||
}
|
||||
|
||||
variable "google_kms_key_ring_id" {
|
||||
description = "Existing Google KMS key ring id."
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "google_openbao_seal_key_name" {
|
||||
description = "Google KMS symmetric key used for OpenBao seal wrapping."
|
||||
type = string
|
||||
default = "openbao-seal"
|
||||
}
|
||||
|
||||
variable "google_openbao_seal_members" {
|
||||
description = "IAM members allowed to encrypt/decrypt with the OpenBao seal key."
|
||||
type = set(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "Additional labels applied to supported Google resources."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
16
infra/openbao/versions.tf
Normal file
16
infra/openbao/versions.tf
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
terraform {
|
||||
required_version = ">= 1.8.0"
|
||||
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = ">= 5.40.0, < 7.0"
|
||||
}
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = ">= 4.5.0, < 6.0"
|
||||
}
|
||||
}
|
||||
|
||||
backend "s3" {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue