2026-05-05 14:56:56 +01:00
|
|
|
# =============================================================================
|
|
|
|
|
# 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"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
2026-05-05 15:21:27 +01:00
|
|
|
# Standalone groups
|
2026-05-05 14:56:56 +01:00
|
|
|
# =============================================================================
|
|
|
|
|
|
2026-05-05 15:21:27 +01:00
|
|
|
resource "keycloak_group" "standalone" {
|
|
|
|
|
for_each = toset(var.groups)
|
|
|
|
|
|
2026-05-05 14:56:56 +01:00
|
|
|
realm_id = keycloak_realm.hexor.id
|
2026-05-05 15:21:27 +01:00
|
|
|
name = each.value
|
2026-05-05 14:56:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resource "keycloak_default_groups" "default" {
|
|
|
|
|
realm_id = keycloak_realm.hexor.id
|
2026-05-05 15:21:27 +01:00
|
|
|
group_ids = [for g in keycloak_group.standalone : g.id if g.name == "users"]
|
2026-05-05 14:56:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
|
|
|
# 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",
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# =============================================================================
|
2026-05-05 18:57:05 +01:00
|
|
|
# Proxy applications — auto-created groups + routes ConfigMap
|
2026-05-05 14:56:56 +01:00
|
|
|
# =============================================================================
|
|
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
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
|
|
|
|
|
|
2026-05-05 14:56:56 +01:00
|
|
|
realm_id = keycloak_realm.hexor.id
|
2026-05-05 18:57:05 +01:00
|
|
|
client_id = each.key
|
2026-05-05 14:56:56 +01:00
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
name = each.key
|
2026-05-05 14:56:56 +01:00
|
|
|
enabled = true
|
|
|
|
|
access_type = "CONFIDENTIAL"
|
|
|
|
|
standard_flow_enabled = true
|
|
|
|
|
direct_access_grants_enabled = false
|
|
|
|
|
|
2026-05-05 19:06:01 +01:00
|
|
|
valid_redirect_uris = each.value.redirect_uris
|
2026-05-05 18:57:05 +01:00
|
|
|
valid_post_logout_redirect_uris = each.value.post_logout_redirect_uris
|
2026-05-05 19:06:01 +01:00
|
|
|
web_origins = each.value.web_origins
|
2026-05-05 14:56:56 +01:00
|
|
|
}
|
|
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
resource "keycloak_openid_group_membership_protocol_mapper" "oauth2_app_groups" {
|
|
|
|
|
for_each = var.oauth2_applications
|
|
|
|
|
|
2026-05-05 14:56:56 +01:00
|
|
|
realm_id = keycloak_realm.hexor.id
|
2026-05-05 18:57:05 +01:00
|
|
|
client_id = keycloak_openid_client.oauth2_app[each.key].id
|
2026-05-05 14:56:56 +01:00
|
|
|
name = "groups"
|
|
|
|
|
claim_name = "groups"
|
|
|
|
|
full_path = false
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
resource "keycloak_openid_client_default_scopes" "oauth2_app" {
|
|
|
|
|
for_each = var.oauth2_applications
|
|
|
|
|
|
2026-05-05 14:56:56 +01:00
|
|
|
realm_id = keycloak_realm.hexor.id
|
2026-05-05 18:57:05 +01:00
|
|
|
client_id = keycloak_openid_client.oauth2_app[each.key].id
|
2026-05-05 14:56:56 +01:00
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
default_scopes = concat(
|
|
|
|
|
["openid", "profile", "email"],
|
|
|
|
|
each.value.extra_default_scopes
|
|
|
|
|
)
|
2026-05-05 14:56:56 +01:00
|
|
|
}
|
2026-05-05 15:21:27 +01:00
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
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
|
|
|
|
|
}
|
2026-05-05 15:21:27 +01:00
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
realm_id = keycloak_realm.hexor.id
|
|
|
|
|
client_id = keycloak_openid_client.oauth2_app[each.key].id
|
2026-05-05 15:21:27 +01:00
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
optional_scopes = each.value.extra_optional_scopes
|
2026-05-05 15:21:27 +01:00
|
|
|
}
|
|
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
resource "keycloak_group" "oauth2_app" {
|
|
|
|
|
for_each = {
|
|
|
|
|
for k, v in var.oauth2_applications : k => v if length(v.allowed_groups) > 0
|
2026-05-05 15:21:27 +01:00
|
|
|
}
|
2026-05-05 18:57:05 +01:00
|
|
|
|
|
|
|
|
realm_id = keycloak_realm.hexor.id
|
|
|
|
|
name = "app-${each.key}"
|
2026-05-05 15:21:27 +01:00
|
|
|
}
|
|
|
|
|
|
2026-05-05 18:57:05 +01:00
|
|
|
# =============================================================================
|
|
|
|
|
# Proxy applications — routes ConfigMap
|
|
|
|
|
# =============================================================================
|
|
|
|
|
|
|
|
|
|
resource "kubernetes_config_map_v1" "auth_proxy_routes" {
|
2026-05-05 15:21:27 +01:00
|
|
|
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]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|