# Read the OAuth client secret from Vault so nothing sensitive is committed. data "vault_kv_secret_v2" "keycloakoidc" { count = var.keycloakoidc != null && var.keycloakoidc.client_secret_vault != null ? 1 : 0 mount = var.keycloakoidc.client_secret_vault.mount name = var.keycloakoidc.client_secret_vault.path } # Read the internal PKI CA chain (intermediate + root) from Vault. Rancher makes # its OIDC discovery call to https://identity.unkin.net server-side; without the # internal CA it fails with x509 "certificate signed by unknown authority". The # ca_chain field is public/non-sensitive. Sourced from Vault (not hardcoded) so # the trust never goes stale on rotation. data "vault_generic_secret" "internal_ca" { count = var.keycloakoidc != null ? 1 : 0 path = "pki_int/cert/ca_chain" } # Rancher's Keycloak(OIDC) auth provider, pointed at Authentik. access_mode # "unrestricted" means any authenticated Authentik user can log in; Rancher # roles are granted to users/groups separately (avoids admin lockout on enable). resource "rancher2_auth_config_keycloak_oidc" "this" { count = var.keycloakoidc != null ? 1 : 0 rancher_url = var.keycloakoidc.rancher_url client_id = var.keycloakoidc.client_id client_secret = data.vault_kv_secret_v2.keycloakoidc[0].data["client_secret"] issuer = var.keycloakoidc.issuer auth_endpoint = var.keycloakoidc.auth_endpoint scopes = var.keycloakoidc.scopes groups_field = var.keycloakoidc.groups_field access_mode = var.keycloakoidc.access_mode enabled = var.keycloakoidc.enabled # CA cert Rancher uses to trust the IdP's TLS during OIDC discovery. Defaults # to the internal PKI chain from Vault; an explicit config value overrides it. certificate = coalesce(var.keycloakoidc.certificate, data.vault_generic_secret.internal_ca[0].data["ca_chain"]) } # Grant Rancher global roles to Authentik permission groups. The keycloak_oidc # group principal id is keycloakoidc_group://. Members of a role # group (e.g. akR-global-admin) inherit the permission group, so they receive # the bound global role. resource "rancher2_global_role_binding" "group" { for_each = var.global_role_bindings # Binding name must be an RFC 1123 label (lowercase); the group name may be # mixed-case (akP-*), so lowercase it here. The principal id keeps the original # case to match the group. name = "akgroup-${lower(each.key)}" global_role_id = each.value.global_role_id group_principal_id = "keycloakoidc_group://${each.key}" depends_on = [rancher2_auth_config_keycloak_oidc.this] }