Files
homelab/terraform/keycloak/main.tf
T
Ultradesu 2778f6582c
Check with kubeconform / lint (push) Successful in 6s
Update Kubernetes Services Wiki / Generate and Update K8s Wiki (push) Successful in 12s
Auto-update README / Generate README and Create MR (push) Successful in 9s
Added grafana to keycloak. clean up prom-stak
2026-05-05 19:06:01 +01:00

198 lines
5.5 KiB
Terraform

# =============================================================================
# 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]
}
}
})
}
}