feat(iam): declare Zitadel identity objects in Terraform
Adds terraform/zitadel: the provisioning half the ArgoCD wiring left open. It declares 1 project, 19 project roles, 12 OIDC applications, 5 machine users plus keys, one API application for the gateway, project grants, per-agent claim metadata, and a disabled groups-claim action. Facts established while writing it: - Client IDs cannot be preserved. ZITADEL v4.19.2 CreateOIDCApplicationRequest has no client_id field, and provider 3.8.7 rejects a settable application id (terraform validate reports "Invalid or unknown key"). Plan §3.2 assumed a client_id-preserving re-point; every consumer now also changes client ID. - Role keys equal the existing group names, so the groups claim can be byte-identical and no RBAC file changes. v4.19.2 allows role keys of 1-200 characters with no character-set restriction. - Machine users get JWT profile keys, not passwords. Per-agent claims move to user metadata and reach tokens only through the groups-claim action. - The action stays gated: enable_groups_claim_action defaults to false because the action runtime API is unverified. Two validations stop a null script from reaching file(). Checks: terraform fmt -check -recursive clean, terraform validate 0 errors, plan reaches only the expected missing-credentials error, structural gate 0 error / 0 warning, and one reviewer round: BLOCK on a plan-time fileexists(null) and on the missing api-gw machine path, both fixed, re-reviewed to SIGN-OFF. State is local and git-ignored; it carries generated client secrets and machine keys. Move it to MinIO before a second operator applies. Not applied: no Zitadel instance is running yet.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# Project, roles and default-org lookup.
|
||||
#
|
||||
# ZITADEL has no group object. The plan §1.3 maps every Authentik group to a
|
||||
# project role, and the groups-claim action (actions.tf) reconstructs the
|
||||
# `groups` claim from those role keys. Role keys therefore EQUAL the existing
|
||||
# Authentik group names, including the hyphens, so that the resulting claim is
|
||||
# byte-identical and no consumer or RBAC file changes. The v4.19.2 API allows
|
||||
# role keys of 1-200 characters with no character-set restriction (proto
|
||||
# zitadel/project/v2/project_service.proto, AddProjectRole.role_key).
|
||||
|
||||
data "zitadel_org" "default" {
|
||||
id = var.org_id
|
||||
}
|
||||
|
||||
locals {
|
||||
# Single source: the 19 groups of scripts/iam/provision-rbac.py GROUPS.
|
||||
# Descriptions are carried over so the console reads the same as before.
|
||||
roles = {
|
||||
"homelab-admins" = "Cluster administrators with full access"
|
||||
"minio-admins" = "MinIO administrators"
|
||||
"minio-photos" = "Photos bucket (Immich) access"
|
||||
"minio-documents" = "Documents bucket (Paperless) access"
|
||||
"minio-backups" = "Backups bucket read-only access"
|
||||
"poimen-admins" = "Poimen memory administrators"
|
||||
"poimen-devs" = "Dev and staging projects access"
|
||||
"poimen-prod-readonly" = "Production projects read-only access"
|
||||
"paperless-admins" = "Paperless administrators"
|
||||
"paperless-finance" = "Finance documents"
|
||||
"paperless-legal" = "Legal documents"
|
||||
"paperless-hr" = "HR documents"
|
||||
"grafana-admins" = "Grafana administrators"
|
||||
"grafana-editors" = "Grafana dashboard editors"
|
||||
"grafana-viewers" = "Grafana dashboard viewers"
|
||||
"sqs-users" = "SQS/Temporal queue read access"
|
||||
"sqs-writers" = "SQS/Temporal queue read/write access"
|
||||
"s3-users" = "S3 read access"
|
||||
"s3-writers" = "S3 read/write access"
|
||||
}
|
||||
}
|
||||
|
||||
resource "zitadel_project_v2" "homelab" {
|
||||
org_id = data.zitadel_org.default.id
|
||||
name = var.project_name
|
||||
project_id = var.project_id
|
||||
project_role_check = false
|
||||
|
||||
# Roles must reach the tokens. Every consumer authorizes on them:
|
||||
# kube-apiserver RBAC reads `groups`, MinIO reads bucket policies, Grafana
|
||||
# reads grafana_org_role. Role assertion on the ID token is what most OIDC
|
||||
# clients inspect.
|
||||
project_role_assertion = true
|
||||
}
|
||||
|
||||
resource "zitadel_project_role" "groups" {
|
||||
for_each = local.roles
|
||||
|
||||
org_id = data.zitadel_org.default.id
|
||||
project_id = zitadel_project_v2.homelab.id
|
||||
role_key = each.key
|
||||
display_name = each.key
|
||||
group = "homelab"
|
||||
}
|
||||
Reference in New Issue
Block a user