ce7cb702218693d08ea6d83464d2457c9250027c
This commit is contained in:
commit
34c5f8963c
32 changed files with 145336 additions and 0 deletions
64
terraform/internal/vault/.terraform.lock.hcl
generated
Normal file
64
terraform/internal/vault/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# This file is maintained automatically by "tofu init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/random" {
|
||||
version = "3.8.1"
|
||||
constraints = "~> 3.8"
|
||||
hashes = [
|
||||
"h1:4XzXwVRt9H0n4AZt0fpNc0AuBIsZH2MF6enFO0Tgm/E=",
|
||||
"h1:EHn3jsqOKhWjbg0X+psk0Ww96yz3N7ASqEKKuFvDFwo=",
|
||||
"h1:HTRqTUdrtlIPsvneQRTTGUfU46vHJ0uI7lf26SNVSoo=",
|
||||
"h1:K/OIbLGX0YNiuoDXlpkerSWyv+bjS97Z6YGUCGePPAw=",
|
||||
"h1:LsYuJLZcYl1RiH7Hd3w90Ra5+k5cNqfdRUQXItkTI8Y=",
|
||||
"h1:ZmWv79WB2oB8IuUyTylbl9zEeWyJVvjd0Uac+Lk6LVw=",
|
||||
"h1:bXd92D1e8ahgUbZNQPoOe+VK+WfNRMP8wU3meagUtB4=",
|
||||
"h1:nz02g0rqNAJ+KO1Lq5Krfp3qJCuhA4bJuV8jtUw99ss=",
|
||||
"h1:tZP70yQDl6mKnTsDtx6tS6GReVb1lgb7WnlIIneXsHY=",
|
||||
"zh:25c458c7c676f15705e872202dad7dcd0982e4a48e7ea1800afa5fc64e77f4c8",
|
||||
"zh:2edeaf6f1b20435b2f81855ad98a2e70956d473be9e52a5fdf57ccd0098ba476",
|
||||
"zh:44becb9d5f75d55e36dfed0c5beabaf4c92e0a2bc61a3814d698271c646d48e7",
|
||||
"zh:7699032612c3b16cc69928add8973de47b10ce81b1141f30644a0e8a895b5cd3",
|
||||
"zh:86d07aa98d17703de9fbf402c89590dc1e01dbe5671dd6bc5e487eb8fe87eee0",
|
||||
"zh:8c411c77b8390a49a8a1bc9f176529e6b32369dd33a723606c8533e5ca4d68c1",
|
||||
"zh:a5ecc8255a612652a56b28149994985e2c4dc046e5d34d416d47fa7767f5c28f",
|
||||
"zh:aea3fe1a5669b932eda9c5c72e5f327db8da707fe514aaca0d0ef60cb24892f9",
|
||||
"zh:f56e26e6977f755d7ae56fa6320af96ecf4bb09580d47cb481efbf27f1c5afff",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/vault" {
|
||||
version = "5.8.0"
|
||||
constraints = "~> 5.0"
|
||||
hashes = [
|
||||
"h1:/OZCcd0X7F9y846SOlVUMItMtLDBwasYe+Mv3HF2I1Q=",
|
||||
"h1:68t9TdU3ap9L+Ayewb478BIyv8rpEDIQxYq1xsq99fs=",
|
||||
"h1:6MmwOTMo0TpjoMs27LNKfxD+kZypRclB2WrV1OgbWD4=",
|
||||
"h1:8DpFTiNTio1Yal+kozfxkPabRvN8ucRyjVkRcKuCnCo=",
|
||||
"h1:B1DuZ215BVQbK/70wahsWR6Wy16LMicdRCuThNgeBOg=",
|
||||
"h1:EhuYG2XYdV7d3RuOB/r/KKv0k5XXtDoBMgrzPraH8yQ=",
|
||||
"h1:FIRP0mpZpyDppetTZxzmaH2kd2E0o8As9w2CANYsEhE=",
|
||||
"h1:KuT1QZ3kyjqZ/YENs5ABfhSHEBLr/01ZWzWbJrS+vDo=",
|
||||
"h1:SMqA7BA2Nv/R4O8oVi8arc1E2NXz56dcnp54vFG9sfg=",
|
||||
"h1:TO99KdU92KULAbT4D0CJSeGFLuEsOgR10d6qFnR3dDk=",
|
||||
"h1:Y3HaoTjTuH4UePPja1vDrRxrSTNhR7wq//qJsJA7/rQ=",
|
||||
"h1:bd5YeFG+ok71bEUWdvksBLPWBWVpeosSl0rbbDJAigE=",
|
||||
"h1:eSjvykpglWlaCF/77dluIgXQ/SbPlh7RSSuLjAYNZUs=",
|
||||
"h1:lUnHYFRPEO+C+DwumShhX7va0iY9ApkhoSSj/P7vCsk=",
|
||||
"h1:qFAesj3MEaAzGFL2tvV+uy/biNwGJUculuN5CFtTh1E=",
|
||||
"zh:1c9d0b740520a88a16ccc57c6bcb1a58e47b6ba19676428b2a0f5b9fe4004788",
|
||||
"zh:274ad5bad107a845927773a6a31a45cd0ed7916fa52b86d85c86c535b59fcea4",
|
||||
"zh:2b2eef2cb6840c3cf41134b1d1b6d3d50d6edbe3b2af2318bf7101843072c83b",
|
||||
"zh:42b607a2983e77a47099b5ac8550a25ecd5ba03760be19749a4ad63617ea6085",
|
||||
"zh:544877ac091e54b2954f5638edf06d76f344eb6833fb68db961c0edb5b0fdc83",
|
||||
"zh:812bd7730efb3781fcfc7442650551d30b015f931a132ae9acdffdd625526908",
|
||||
"zh:8798d164f8e25f3b211be45e79d3bd5272e9237e728942c0026300b25798e5fe",
|
||||
"zh:91201a2e5dbc88013977960f0d1139fb584cdcda1cfd27577980d8cf0a31ead3",
|
||||
"zh:a532662249b28e10a065bbab467d4ea9a12719638fe0f7e0add05d8d11142366",
|
||||
"zh:ab91b32cbcc71cd9e89cca7d88957d9410f54750f7ea60f1416d2d77b478006a",
|
||||
"zh:ae5658b04277318c8b91c0a9ed2ec05dd324a7501c1a057d53e79b0e1978a1f6",
|
||||
"zh:e02581fca392f46738a95999d5fbccca7d82500df3a88e16ae9668633eb16f9b",
|
||||
"zh:e89f59329ee939b59158c6173484ef4376da44296f6153d2fbafd3e28bd650c5",
|
||||
"zh:e9ac49b94293cb5c8b31eb6e5afddc6134ffff0481ec195b242e0175e1f6766f",
|
||||
"zh:ef60d5715c3b82ae64643dea9b4c1a82c10f72151c77af2749d3ceb060bb2adb",
|
||||
]
|
||||
}
|
||||
22
terraform/internal/vault/agentgateway.tf
Normal file
22
terraform/internal/vault/agentgateway.tf
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
resource "vault_policy" "agentgateway" {
|
||||
name = "agentgateway"
|
||||
|
||||
policy = <<-EOT
|
||||
path "secret/data/agentgateway/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/robots/cluster_pull" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "agentgateway" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "agentgateway"
|
||||
bound_service_account_names = ["agentgateway-vso"]
|
||||
bound_service_account_namespaces = ["agentgateway-system"]
|
||||
token_policies = [vault_policy.agentgateway.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
30
terraform/internal/vault/argo.tf
Normal file
30
terraform/internal/vault/argo.tf
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
resource "random_password" "versitygw_argo_secret_access_key" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "versitygw_argo_user" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/argo"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
secretAccessKey = random_password.versitygw_argo_secret_access_key.result
|
||||
})
|
||||
|
||||
# Vault is source of truth after first write. Re-runs do not rotate user credentials.
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "argo_artifacts" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "argo/artifacts"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
access_key_id = "********"
|
||||
secret_access_key = random_password.versitygw_argo_secret_access_key.result
|
||||
internal_ca_cert = vault_pki_secret_backend_root_cert.root.certificate
|
||||
})
|
||||
|
||||
# Keep in lockstep with versitygw/users/argo until rotation is designed.
|
||||
}
|
||||
27
terraform/internal/vault/auth.tf
Normal file
27
terraform/internal/vault/auth.tf
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Kubernetes auth method — workloads authenticate using their pod service account token.
|
||||
resource "vault_auth_backend" "kubernetes" {
|
||||
type = "kubernetes"
|
||||
path = "kubernetes"
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_config" "kubernetes" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
kubernetes_host = var.k8s_host
|
||||
# Vault reads the cluster CA and its own service account token from the pod
|
||||
# filesystem automatically when running inside the cluster. No explicit
|
||||
# token_reviewer_jwt or kubernetes_ca_cert needed.
|
||||
disable_iss_validation = true
|
||||
}
|
||||
|
||||
# cert-manager role
|
||||
# Bound to cert-manager's service account; grants the cert-manager policy
|
||||
# so it can sign certificates via pki_int.
|
||||
resource "vault_kubernetes_auth_backend_role" "cert_manager" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "cert-manager"
|
||||
bound_service_account_names = ["cert-manager"]
|
||||
bound_service_account_namespaces = ["cert-manager"]
|
||||
token_policies = [vault_policy.cert_manager.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
15
terraform/internal/vault/backups.tf
Normal file
15
terraform/internal/vault/backups.tf
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
resource "random_password" "backup_key" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "backup_writer" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/backup-writer"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
access_key_id = "backup-writer"
|
||||
secret_access_key = random_password.backup_key.result
|
||||
})
|
||||
}
|
||||
59
terraform/internal/vault/ca.tf
Normal file
59
terraform/internal/vault/ca.tf
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
locals {
|
||||
ca_roots = {
|
||||
internal = "pki"
|
||||
postgres = "pki_postgres"
|
||||
opnsense = "pki_opnsense"
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "ca" {
|
||||
for_each = local.ca_roots
|
||||
mount = vault_mount.secret.path
|
||||
name = "ca/${each.key}"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({ certificate = "PLACEHOLDER" })
|
||||
}
|
||||
|
||||
resource "vault_policy" "ca_sync" {
|
||||
name = "ca-sync"
|
||||
policy = join("\n", concat(
|
||||
[for mount in values(local.ca_roots) :
|
||||
"path \"${mount}/cert/ca\" { capabilities = [\"read\"] }"
|
||||
],
|
||||
[for name in keys(local.ca_roots) :
|
||||
"path \"secret/data/ca/${name}\" { capabilities = [\"read\", \"update\"] }"
|
||||
],
|
||||
))
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "ca_sync" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "ca-sync"
|
||||
bound_service_account_names = ["ca-sync"]
|
||||
bound_service_account_namespaces = ["vault"]
|
||||
token_policies = [vault_policy.ca_sync.name]
|
||||
token_ttl = 300
|
||||
token_max_ttl = 300
|
||||
}
|
||||
|
||||
resource "vault_policy" "ca_sync_pull" {
|
||||
name = "ca-sync-pull"
|
||||
policy = <<-EOT
|
||||
path "secret/data/quay/robots/cluster_pull" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "pki/cert/ca" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "ca_sync_pull" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "ca-sync-pull"
|
||||
bound_service_account_names = ["ca-sync-vso"]
|
||||
bound_service_account_namespaces = ["vault"]
|
||||
token_policies = [vault_policy.ca_sync_pull.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
18
terraform/internal/vault/cluster-health.tf
Normal file
18
terraform/internal/vault/cluster-health.tf
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
resource "vault_policy" "cluster_health" {
|
||||
name = "cluster-health"
|
||||
policy = <<-EOT
|
||||
path "secret/data/quay/robots/cluster_pull" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "cluster_health" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "cluster-health"
|
||||
bound_service_account_names = ["cluster-health-vso"]
|
||||
bound_service_account_namespaces = ["cluster-health"]
|
||||
token_policies = [vault_policy.cluster_health.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
100
terraform/internal/vault/database.tf
Normal file
100
terraform/internal/vault/database.tf
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
data "terraform_remote_state" "postgres" {
|
||||
backend = "pg"
|
||||
config = {
|
||||
conn_str = "postgres://10.234.158.153:5432/tf_state?sslmode=require"
|
||||
schema_name = "internal_postgres"
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_mount" "database" {
|
||||
path = "database"
|
||||
type = "database"
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_connection" "postgres" {
|
||||
backend = vault_mount.database.path
|
||||
name = "postgres"
|
||||
allowed_roles = ["zitadel", "forgejo", "forgejo-public", "grafana", "quay", "quay_clair", "argo", "stalwart", "tf-state", "hf-chat-ui"]
|
||||
|
||||
postgresql {
|
||||
connection_url = "postgresql://{{username}}:{{password}}@main-rw.postgres.svc.cluster.local:5432/postgres?sslmode=require"
|
||||
username = "********"
|
||||
password = data.terraform_remote_state.postgres.outputs.vault_db_admin_password
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
db_static_rotation_schedule = "0 19 * * 0"
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "zitadel" {
|
||||
backend = vault_mount.database.path
|
||||
name = "zitadel"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "forgejo" {
|
||||
backend = vault_mount.database.path
|
||||
name = "forgejo"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "forgejo_public" {
|
||||
backend = vault_mount.database.path
|
||||
name = "forgejo-public"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "grafana" {
|
||||
backend = vault_mount.database.path
|
||||
name = "grafana"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "quay" {
|
||||
backend = vault_mount.database.path
|
||||
name = "quay"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "quay_clair" {
|
||||
backend = vault_mount.database.path
|
||||
name = "quay_clair"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "argo" {
|
||||
backend = vault_mount.database.path
|
||||
name = "argo"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "stalwart" {
|
||||
backend = vault_mount.database.path
|
||||
name = "stalwart"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "tf_state" {
|
||||
backend = vault_mount.database.path
|
||||
name = "tf-state"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "********"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
14
terraform/internal/vault/dump.tf
Normal file
14
terraform/internal/vault/dump.tf
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
resource "random_password" "versitygw_hardware_qualification_writer_secret_access_key" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "versitygw_hardware_qualification_writer" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/hardware-qualification-writer"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
secretAccessKey = random_password.versitygw_hardware_qualification_writer_secret_access_key.result
|
||||
})
|
||||
}
|
||||
65
terraform/internal/vault/forgejo-public.tf
Normal file
65
terraform/internal/vault/forgejo-public.tf
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
resource "random_password" "versitygw_forgejo_public_secret_access_key" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "versitygw_forgejo_public_user" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/forgejo-public"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
secretAccessKey = random_password.versitygw_forgejo_public_secret_access_key.result
|
||||
})
|
||||
}
|
||||
|
||||
resource "random_password" "forgejo_public_dragonfly_password" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "dragonfly_forgejo_public_acl" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "dragonfly/forgejo-public/acl"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
acl = "user default on >${random_password.forgejo_public_dragonfly_password.result} ~* &* +@all\n"
|
||||
})
|
||||
}
|
||||
|
||||
resource "random_password" "forgejo_public_secret_key" {
|
||||
length = 64
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "random_password" "forgejo_public_internal_token" {
|
||||
length = 64
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "random_password" "forgejo_public_oauth2_jwt_secret" {
|
||||
length = 64
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "random_password" "forgejo_public_lfs_jwt_secret" {
|
||||
length = 64
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "forgejo_public_secrets" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "forgejo-public/secrets"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
secret_key = random_password.forgejo_public_secret_key.result
|
||||
internal_token = random_password.forgejo_public_internal_token.result
|
||||
oauth2_jwt_secret = random_password.forgejo_public_oauth2_jwt_secret.result
|
||||
lfs_jwt_secret = random_password.forgejo_public_lfs_jwt_secret.result
|
||||
redis_password = random_password.forgejo_public_dragonfly_password.result
|
||||
s3_secret_key = random_password.versitygw_forgejo_public_secret_access_key.result
|
||||
internal_ca_cert = vault_pki_secret_backend_root_cert.root.certificate
|
||||
})
|
||||
}
|
||||
51
terraform/internal/vault/forgejo.tf
Normal file
51
terraform/internal/vault/forgejo.tf
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
resource "random_password" "versitygw_forgejo_secret_access_key" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "versitygw_forgejo_user" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/forgejo"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
secretAccessKey = random_password.versitygw_forgejo_secret_access_key.result
|
||||
})
|
||||
|
||||
# Vault is source of truth after first write. Re-runs do not rotate user credentials.
|
||||
}
|
||||
|
||||
resource "random_password" "forgejo_dragonfly_password" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "dragonfly_forgejo_acl" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "dragonfly/forgejo/acl"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
acl = "user default on >${random_password.forgejo_dragonfly_password.result} ~* &* +@all\n"
|
||||
})
|
||||
|
||||
# Vault is source of truth after first write. Re-runs do not rotate the ACL.
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "forgejo_secrets" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "forgejo/secrets"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
secret_key = "REPLACE_AFTER_EXTRACTION"
|
||||
internal_token = "REPLACE_AFTER_EXTRACTION"
|
||||
oauth2_jwt_secret = "REPLACE_AFTER_EXTRACTION"
|
||||
lfs_jwt_secret = "REPLACE_AFTER_EXTRACTION"
|
||||
redis_password = random_password.forgejo_dragonfly_password.result
|
||||
s3_secret_key = random_password.versitygw_forgejo_secret_access_key.result
|
||||
internal_ca_cert = vault_pki_secret_backend_root_cert.root.certificate
|
||||
})
|
||||
|
||||
# Manual escrow patches the Forgejo runtime keys after the path exists.
|
||||
}
|
||||
63
terraform/internal/vault/frigate.tf
Normal file
63
terraform/internal/vault/frigate.tf
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
resource "random_password" "frigate_s3" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "frigate_s3" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/model-reader"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
accessKeyId = "model-reader"
|
||||
secretAccessKey = random_password.frigate_s3.result
|
||||
})
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "frigate_oauth2_proxy" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "frigate/oauth2-proxy"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({})
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "frigate_oauth2_proxy_cookie" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "frigate/oauth2-proxy-cookie"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({})
|
||||
}
|
||||
|
||||
resource "vault_policy" "frigate" {
|
||||
name = "frigate"
|
||||
|
||||
policy = <<-EOT
|
||||
path "secret/data/frigate/rtsp" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/frigate/oauth2-proxy" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/frigate/oauth2-proxy-cookie" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/robots/cluster_pull" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/versitygw/users/model-reader" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "pki/cert/ca" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "frigate" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "frigate"
|
||||
bound_service_account_names = ["frigate-vso"]
|
||||
bound_service_account_namespaces = ["frigate"]
|
||||
token_policies = [vault_policy.frigate.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
9
terraform/internal/vault/grafana.tf
Normal file
9
terraform/internal/vault/grafana.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
resource "vault_kv_secret_v2" "grafana_s3" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/grafana"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
secretAccessKey = "PLACEHOLDER"
|
||||
})
|
||||
}
|
||||
38
terraform/internal/vault/hf-chat-ui.tf
Normal file
38
terraform/internal/vault/hf-chat-ui.tf
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
resource "vault_database_secret_backend_static_role" "hf_chat_ui" {
|
||||
backend = vault_mount.database.path
|
||||
name = "hf-chat-ui"
|
||||
db_name = vault_database_secret_backend_connection.postgres.name
|
||||
username = "hf_chat_ui"
|
||||
rotation_schedule = local.db_static_rotation_schedule
|
||||
}
|
||||
|
||||
resource "vault_policy" "hf_chat_ui" {
|
||||
name = "hf-chat-ui"
|
||||
policy = <<-EOT
|
||||
path "secret/data/hf-chat-ui/oidc/zitadel" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "database/static-creds/hf-chat-ui" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/robots/cluster_pull" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/ca/internal" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/ca/postgres" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "hf_chat_ui" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "hf-chat-ui"
|
||||
bound_service_account_names = ["hf-chat-ui-vso"]
|
||||
bound_service_account_namespaces = ["hf-chat-ui"]
|
||||
token_policies = [vault_policy.hf_chat_ui.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
1049
terraform/internal/vault/kv.tf
Normal file
1049
terraform/internal/vault/kv.tf
Normal file
File diff suppressed because it is too large
Load diff
57
terraform/internal/vault/layshaft.tf
Normal file
57
terraform/internal/vault/layshaft.tf
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
resource "vault_mount" "layshaft" {
|
||||
path = "layshaft"
|
||||
type = "kv"
|
||||
options = { version = "2" }
|
||||
}
|
||||
|
||||
resource "vault_policy" "layshaft" {
|
||||
name = "layshaft"
|
||||
|
||||
policy = <<-EOT
|
||||
path "${vault_mount.layshaft.path}/data/server" {
|
||||
capabilities = ["create", "read", "update"]
|
||||
}
|
||||
path "${vault_mount.layshaft.path}/data/unlock/+" {
|
||||
capabilities = ["create", "read", "update"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "layshaft" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "layshaft"
|
||||
bound_service_account_names = ["layshaft"]
|
||||
bound_service_account_namespaces = ["layshaft"]
|
||||
audience = "layshaft-vault"
|
||||
token_policies = [vault_policy.layshaft.name]
|
||||
token_no_default_policy = true
|
||||
token_ttl = 300
|
||||
token_max_ttl = 300
|
||||
}
|
||||
|
||||
resource "vault_policy" "layshaft_vso" {
|
||||
name = "layshaft-vso"
|
||||
|
||||
policy = <<-EOT
|
||||
path "auth/token/renew-self" {
|
||||
capabilities = ["update"]
|
||||
}
|
||||
path "secret/data/quay/robots/cluster_pull" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "pki/cert/ca" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "layshaft_vso" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "layshaft-vso"
|
||||
bound_service_account_names = ["layshaft-vso"]
|
||||
bound_service_account_namespaces = ["layshaft"]
|
||||
token_policies = [vault_policy.layshaft_vso.name]
|
||||
token_no_default_policy = true
|
||||
token_ttl = 300
|
||||
token_max_ttl = 300
|
||||
}
|
||||
7
terraform/internal/vault/minecraft-boot.tf
Normal file
7
terraform/internal/vault/minecraft-boot.tf
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
resource "vault_kv_secret_v2" "boot_publisher" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/boot-publisher"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({ secretAccessKey = "PLACEHOLDER" })
|
||||
}
|
||||
|
||||
71
terraform/internal/vault/minecraft.tf
Normal file
71
terraform/internal/vault/minecraft.tf
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
resource "vault_kv_secret_v2" "minecraft" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "minecraft/server"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
EULA = "PLACEHOLDER"
|
||||
FTB_MODPACK_ID = "PLACEHOLDER"
|
||||
FTB_MODPACK_VERSION_ID = "PLACEHOLDER"
|
||||
MEMORY = "PLACEHOLDER"
|
||||
JVM_OPTS = "PLACEHOLDER"
|
||||
})
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "minecraft_files" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "minecraft/files"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
"server.properties" = "PLACEHOLDER"
|
||||
})
|
||||
}
|
||||
|
||||
resource "vault_policy" "minecraft" {
|
||||
name = "minecraft"
|
||||
policy = <<-EOT
|
||||
path "secret/data/minecraft/server" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/oauth/project-delivery-reader" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/minecraft/files" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/minecraft/rcon" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/versitygw/users/minecraft" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/ca/internal" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "minecraft_s3" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/minecraft"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({ secretAccessKey = "PLACEHOLDER" })
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "minecraft_rcon" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "minecraft/rcon"
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
password = "PLACEHOLDER"
|
||||
})
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "minecraft" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "minecraft"
|
||||
bound_service_account_names = ["minecraft-vso"]
|
||||
bound_service_account_namespaces = ["minecraft"]
|
||||
token_policies = [vault_policy.minecraft.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
125
terraform/internal/vault/mirrored-image.tf
Normal file
125
terraform/internal/vault/mirrored-image.tf
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
locals {
|
||||
mirror_personas = toset([
|
||||
"candidates-bot",
|
||||
"mirror-bot",
|
||||
])
|
||||
mirror_oauth = {
|
||||
candidates-reader = {
|
||||
service_account = "cand-read-vso"
|
||||
}
|
||||
candidates-writer = {
|
||||
service_account = "cand-write-vso"
|
||||
}
|
||||
mirror-reader = {
|
||||
service_account = "mirror-read-vso"
|
||||
}
|
||||
mirror-writer = {
|
||||
service_account = "mirror-write-vso"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "mirror_persona" {
|
||||
for_each = local.mirror_personas
|
||||
|
||||
mount = vault_mount.secret.path
|
||||
name = "quay/personas/${each.key}"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({ password = "PLACEHOLDER" })
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "mirror_oauth" {
|
||||
for_each = local.mirror_oauth
|
||||
|
||||
mount = vault_mount.secret.path
|
||||
name = "quay/oauth/${each.key}"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({ token = "PLACEHOLDER" })
|
||||
}
|
||||
|
||||
resource "vault_policy" "mirror_oauth" {
|
||||
for_each = local.mirror_oauth
|
||||
|
||||
name = each.key
|
||||
|
||||
policy = <<-EOT
|
||||
path "secret/data/quay/oauth/${each.key}" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "mirror_oauth" {
|
||||
for_each = local.mirror_oauth
|
||||
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = each.key
|
||||
bound_service_account_names = [each.value.service_account]
|
||||
bound_service_account_namespaces = ["mirrored-image"]
|
||||
token_policies = [vault_policy.mirror_oauth[each.key].name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
|
||||
resource "vault_policy" "mirror_support" {
|
||||
name = "mirror-support"
|
||||
|
||||
policy = <<-EOT
|
||||
path "secret/data/argo/artifacts" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/robots/cluster_pull" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "mirror_support" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "mirror-support"
|
||||
bound_service_account_names = ["mirror-sup-vso"]
|
||||
bound_service_account_namespaces = ["mirrored-image"]
|
||||
token_policies = [vault_policy.mirror_support.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
|
||||
resource "vault_policy" "mirror_bootstrap" {
|
||||
name = "mirror-bootstrap"
|
||||
|
||||
policy = <<-EOT
|
||||
path "secret/data/quay/bootstrap" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/personas/candidates-bot" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/personas/mirror-bot" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "secret/data/quay/oauth/candidates-reader" {
|
||||
capabilities = ["read", "update"]
|
||||
}
|
||||
path "secret/data/quay/oauth/candidates-writer" {
|
||||
capabilities = ["read", "update"]
|
||||
}
|
||||
path "secret/data/quay/oauth/mirror-reader" {
|
||||
capabilities = ["read", "update"]
|
||||
}
|
||||
path "secret/data/quay/oauth/mirror-writer" {
|
||||
capabilities = ["read", "update"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "mirror_bootstrap" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "mirror-bootstrap"
|
||||
bound_service_account_names = ["mirror-bootstrap"]
|
||||
bound_service_account_namespaces = ["mirrored-image"]
|
||||
token_policies = [vault_policy.mirror_bootstrap.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
36
terraform/internal/vault/pg-backup.tf
Normal file
36
terraform/internal/vault/pg-backup.tf
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
resource "random_password" "pg_backup_key" {
|
||||
length = 48
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "vault_kv_secret_v2" "pg_backup" {
|
||||
mount = vault_mount.secret.path
|
||||
name = "versitygw/users/pg-backup"
|
||||
|
||||
data_json_wo_version = 1
|
||||
data_json_wo = jsonencode({
|
||||
access_key_id = "********"
|
||||
secret_access_key = random_password.pg_backup_key.result
|
||||
internal_ca_cert = vault_pki_secret_backend_root_cert.root.certificate
|
||||
})
|
||||
}
|
||||
|
||||
resource "vault_policy" "pg_backup" {
|
||||
name = "pg-backup"
|
||||
|
||||
policy = <<-EOT
|
||||
path "secret/data/versitygw/users/pg-backup" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "pg_backup" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "pg-backup"
|
||||
bound_service_account_names = ["pg-vso"]
|
||||
bound_service_account_namespaces = ["postgres"]
|
||||
token_policies = [vault_policy.pg_backup.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 3600
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue