refactor(iam): retire terraform/zitadel, provision through the API
The Terraform root module duplicated a writer that the provisioning script could be, and its state carried generated client secrets. Declare the objects in the script instead: project, 19 roles, 12 OIDC apps, applied through the management API with the iam-admin PAT. State is a 0600 JSON file under ~/.config/zitadel. Also add zitadel to the Cloudflare tunnel hostname list, with the import command and the note that the tunnel's Public Hostname entry is a separate dashboard step: DNS alone yields a 404 from the tunnel.
This commit is contained in:
@@ -1,103 +0,0 @@
|
||||
variable "zitadel_domain" {
|
||||
description = "External domain of the ZITADEL instance, without scheme."
|
||||
type = string
|
||||
default = "zitadel.riotpiao.com"
|
||||
}
|
||||
|
||||
variable "zitadel_port" {
|
||||
description = "Port for the ZITADEL API. 443 behind ingress, 8080 for a direct pod port-forward."
|
||||
type = string
|
||||
default = "443"
|
||||
}
|
||||
|
||||
variable "zitadel_insecure" {
|
||||
description = "Call the API over plain HTTP (set true only when port-forwarding the pod)."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "jwt_profile_file" {
|
||||
description = "Path to the iam-admin machine key JSON extracted from the iam-admin Secret."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "org_id" {
|
||||
description = <<-EOT
|
||||
ID of the ZITADEL organization that holds the project. Read it from the
|
||||
console: https://zitadel.riotpiao.com -> Organization settings -> Resource
|
||||
ID. The chart's setup job creates the default org; this module never creates
|
||||
one, because creating a second org would split the role and grant space.
|
||||
EOT
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
description = <<-EOT
|
||||
Stable project ID. ZITADEL puts the project ID in the access token `aud`
|
||||
claim, so pinning it keeps audience checks readable across a rebuild.
|
||||
Every consumer that validates `aud` against a client ID must be re-pointed
|
||||
to this value — see the plan §5.2.
|
||||
EOT
|
||||
type = string
|
||||
default = "homelab"
|
||||
}
|
||||
|
||||
variable "project_name" {
|
||||
description = "Display name of the project that carries every role and application."
|
||||
type = string
|
||||
default = "homelab"
|
||||
}
|
||||
|
||||
variable "machine_key_expiry" {
|
||||
description = "Expiry of every machine key, RFC3339. Matches the chart's default iam-admin key window; rotate by changing this value and re-applying."
|
||||
type = string
|
||||
default = "2029-01-01T00:00:00Z"
|
||||
}
|
||||
|
||||
variable "api_app_consumers" {
|
||||
description = <<-EOT
|
||||
Machine users that also need an API application (the client_credentials
|
||||
replacement). Only the gateway does: every other agent signs a JWT with its
|
||||
machine key and does not need a client_credentials grant.
|
||||
EOT
|
||||
type = map(string)
|
||||
default = { api-gw = "Go LLM gateway" }
|
||||
}
|
||||
|
||||
variable "enable_groups_claim_action" {
|
||||
description = <<-EOT
|
||||
Create the Actions v1 script and its trigger that synthesizes the `groups`
|
||||
claim. Keep this false until the live go/no-go gate passes: the claim is
|
||||
load-bearing for kube-apiserver RBAC, MinIO policies, Grafana role mapping
|
||||
and every service that reads `groups`. Turning it on with an unverified
|
||||
script can break every consumer at once.
|
||||
EOT
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "groups_claim_script" {
|
||||
description = <<-EOT
|
||||
Path to the JavaScript body for the groups-claim action, read only when
|
||||
enable_groups_claim_action is true. The body is deliberately not shipped
|
||||
blind: the ZITADEL v1 Actions runtime API must be confirmed against the live
|
||||
instance before a script is committed, because a wrong call silently emits
|
||||
no claim instead of failing loudly.
|
||||
EOT
|
||||
type = string
|
||||
default = null
|
||||
|
||||
validation {
|
||||
# try() is required: HCL does not short-circuit `||`, so fileexists(null)
|
||||
# would fail the whole plan even with the action disabled.
|
||||
condition = try(fileexists(var.groups_claim_script), true)
|
||||
error_message = "groups_claim_script must name an existing file when it is set."
|
||||
}
|
||||
|
||||
# Enabling the action without a script would reach file(null) inside actions.tf.
|
||||
validation {
|
||||
condition = !var.enable_groups_claim_action || var.groups_claim_script != null
|
||||
error_message = "enable_groups_claim_action requires groups_claim_script."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user