# ============================================================================= # Realm # ============================================================================= resource "keycloak_realm" "hexor" { realm = "hexor" enabled = true display_name = "Hexor" login_theme = "keycloak" account_theme = "keycloak.v3" registration_allowed = false reset_password_allowed = true remember_me = true verify_email = false login_with_email_allowed = true duplicate_emails_allowed = false ssl_required = "external" } # ============================================================================= # Google Identity Provider # ============================================================================= resource "keycloak_oidc_google_identity_provider" "google" { realm = keycloak_realm.hexor.id client_id = var.google_client_id client_secret = var.google_client_secret trust_email = true sync_mode = "IMPORT" } # ============================================================================= # Standalone groups # ============================================================================= resource "keycloak_group" "standalone" { for_each = toset(var.groups) realm_id = keycloak_realm.hexor.id name = each.value } resource "keycloak_default_groups" "default" { realm_id = keycloak_realm.hexor.id group_ids = [for g in keycloak_group.standalone : g.id if g.name == "users"] } # ============================================================================= # rsauth2-proxy client (production) # ============================================================================= resource "keycloak_openid_client" "rsauth2_proxy" { realm_id = keycloak_realm.hexor.id client_id = "rsauth2-proxy" name = "rsauth2-proxy" enabled = true access_type = "CONFIDENTIAL" standard_flow_enabled = true direct_access_grants_enabled = false valid_redirect_uris = [ "https://oauth.hexor.cy/callback", ] web_origins = [ "https://oauth.hexor.cy", ] } resource "keycloak_openid_group_membership_protocol_mapper" "rsauth2_proxy_groups" { realm_id = keycloak_realm.hexor.id client_id = keycloak_openid_client.rsauth2_proxy.id name = "groups" claim_name = "groups" full_path = false } resource "keycloak_openid_client_default_scopes" "rsauth2_proxy" { realm_id = keycloak_realm.hexor.id client_id = keycloak_openid_client.rsauth2_proxy.id default_scopes = [ "openid", "profile", "email", ] } # ============================================================================= # Proxy applications — auto-created groups + routes ConfigMap # ============================================================================= resource "keycloak_group" "app" { for_each = var.proxy_applications realm_id = keycloak_realm.hexor.id name = "app-${each.key}" } locals { app_allowed_groups = { for k, v in var.proxy_applications : k => concat( ["app-${k}"], v.allowed_groups ) } } # ============================================================================= # OAuth2 applications — full OIDC clients for apps that handle auth themselves # ============================================================================= resource "keycloak_openid_client" "oauth2_app" { for_each = var.oauth2_applications realm_id = keycloak_realm.hexor.id client_id = each.key name = each.key enabled = true access_type = "CONFIDENTIAL" standard_flow_enabled = true direct_access_grants_enabled = false valid_redirect_uris = each.value.redirect_uris valid_post_logout_redirect_uris = each.value.post_logout_redirect_uris web_origins = each.value.web_origins } resource "keycloak_openid_group_membership_protocol_mapper" "oauth2_app_groups" { for_each = var.oauth2_applications realm_id = keycloak_realm.hexor.id client_id = keycloak_openid_client.oauth2_app[each.key].id name = "groups" claim_name = "groups" full_path = false } resource "keycloak_openid_client_default_scopes" "oauth2_app" { for_each = var.oauth2_applications realm_id = keycloak_realm.hexor.id client_id = keycloak_openid_client.oauth2_app[each.key].id default_scopes = concat( ["openid", "profile", "email"], each.value.extra_default_scopes ) } resource "keycloak_openid_client_optional_scopes" "oauth2_app" { for_each = { for k, v in var.oauth2_applications : k => v if length(v.extra_optional_scopes) > 0 } realm_id = keycloak_realm.hexor.id client_id = keycloak_openid_client.oauth2_app[each.key].id optional_scopes = each.value.extra_optional_scopes } resource "keycloak_group" "oauth2_app" { for_each = { for k, v in var.oauth2_applications : k => v if length(v.allowed_groups) > 0 } realm_id = keycloak_realm.hexor.id name = "app-${each.key}" } # ============================================================================= # Proxy applications — routes ConfigMap # ============================================================================= resource "kubernetes_config_map_v1" "auth_proxy_routes" { metadata { name = "auth-proxy-routes" namespace = "auth-proxy" } data = { "routes.yaml" = yamlencode({ routes = { for k, v in var.proxy_applications : v.domain => { allowed_groups = local.app_allowed_groups[k] } } }) } }