diff --git a/k8s/core/auth-proxy/kustomization.yaml b/k8s/core/auth-proxy/kustomization.yaml index d529dd5..9dd7852 100644 --- a/k8s/core/auth-proxy/kustomization.yaml +++ b/k8s/core/auth-proxy/kustomization.yaml @@ -4,7 +4,7 @@ kind: Kustomization resources: - app.yaml - external-secrets.yaml - - routes.yaml - deployment.yaml - service.yaml - ingress.yaml +# routes.yaml ConfigMap is managed by Terraform (kubernetes_config_map) diff --git a/k8s/core/auth-proxy/routes.yaml b/k8s/core/auth-proxy/routes.yaml deleted file mode 100644 index a0a27ec..0000000 --- a/k8s/core/auth-proxy/routes.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: auth-proxy-routes -data: - routes.yaml: | - routes: - secret-reader.hexor.cy: - allowed_groups: [] diff --git a/terraform/keycloak/.terraform.lock.hcl b/terraform/keycloak/.terraform.lock.hcl index 89a224d..987ce07 100644 --- a/terraform/keycloak/.terraform.lock.hcl +++ b/terraform/keycloak/.terraform.lock.hcl @@ -1,6 +1,26 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. +provider "registry.terraform.io/hashicorp/kubernetes" { + version = "3.1.0" + constraints = ">= 2.0.0" + hashes = [ + "h1:G9QqKNpcztBRqrywtlNylFJSpGzDfRFtO8hcWLdkvRY=", + "zh:0215c5c60be62028c09a2f22458e89cda3ef5830a632299f1d401eb3538874b0", + "zh:09ebb9f442431e278a310a9423f32caf467cb4b3cad3fe59573ca71fa7b14e20", + "zh:0c4e5912f83bb35846ae0a9ae54fc320706ee61894cd21cc6b4181b1c5a2fa5c", + "zh:1678c982853ad461e65ccb5e79d585e13ed109dd47dab2a66d3a7a304faeef65", + "zh:1c050a5c15e330457a9c18caacf61a923c59d663e13f2962e4b32f04fef523a0", + "zh:2c55bcec83be58ec132c7cb0a1ac644758b800d794fdc636d53a0eada0358a3a", + "zh:a062bb0aa316c08d8460c66a5d68da71da40de5d3bc3b31abcf3a1a9a19650f1", + "zh:a26fdea0afaa9b247c73c0b42843ca51ba7db0ac2571f9d3d50dcabd20ca1b98", + "zh:c872c9385a78d502bf5823d61cd3bb0f9a0585030e025eb12585c83451beeaa1", + "zh:f180879af931182beee4c8c0d9dab62b81d86f17ddcbe3786ef4c7cec9163a4e", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f70f5789264069e0eef06f9b5d5fde955ef7206f7d446d1ce51a4c37a3f3e02f", + ] +} + provider "registry.terraform.io/keycloak/keycloak" { version = "5.7.0" constraints = ">= 5.0.0" diff --git a/terraform/keycloak/main.tf b/terraform/keycloak/main.tf index 7cb9655..a25f499 100644 --- a/terraform/keycloak/main.tf +++ b/terraform/keycloak/main.tf @@ -35,17 +35,19 @@ resource "keycloak_oidc_google_identity_provider" "google" { } # ============================================================================= -# Default groups +# Standalone groups # ============================================================================= -resource "keycloak_group" "users" { +resource "keycloak_group" "standalone" { + for_each = toset(var.groups) + realm_id = keycloak_realm.hexor.id - name = "users" + name = each.value } resource "keycloak_default_groups" "default" { realm_id = keycloak_realm.hexor.id - group_ids = [keycloak_group.users.id] + group_ids = [for g in keycloak_group.standalone : g.id if g.name == "users"] } # ============================================================================= @@ -131,3 +133,40 @@ resource "keycloak_openid_client_default_scopes" "rsauth2_proxy_dev" { "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 + ) + } +} + +resource "kubernetes_config_map" "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] + } + } + }) + } +} diff --git a/terraform/keycloak/outputs.tf b/terraform/keycloak/outputs.tf index 381d622..5378e6d 100644 --- a/terraform/keycloak/outputs.tf +++ b/terraform/keycloak/outputs.tf @@ -23,3 +23,15 @@ output "rsauth2_proxy_dev_client_secret" { value = keycloak_openid_client.rsauth2_proxy_dev.client_secret sensitive = true } + +output "standalone_groups" { + value = [for g in keycloak_group.standalone : g.name] +} + +output "app_groups" { + value = { for k, g in keycloak_group.app : k => g.name } +} + +output "app_allowed_groups" { + value = local.app_allowed_groups +} diff --git a/terraform/keycloak/providers.tf b/terraform/keycloak/providers.tf index 14c28ac..aba70b7 100644 --- a/terraform/keycloak/providers.tf +++ b/terraform/keycloak/providers.tf @@ -4,6 +4,10 @@ terraform { source = "keycloak/keycloak" version = ">= 5.0.0" } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.0.0" + } } } @@ -13,3 +17,7 @@ provider "keycloak" { client_id = var.keycloak_client_id client_secret = var.keycloak_client_secret } + +provider "kubernetes" { + config_path = var.kubeconfig_path +} diff --git a/terraform/keycloak/variables.tf b/terraform/keycloak/variables.tf index 1debe6f..9a0030d 100644 --- a/terraform/keycloak/variables.tf +++ b/terraform/keycloak/variables.tf @@ -16,6 +16,12 @@ variable "keycloak_client_secret" { sensitive = true } +variable "kubeconfig_path" { + description = "Path to kubeconfig (set via TF_VAR_kubeconfig_path or KUBE_CONFIG_PATH)" + type = string + default = "~/.kube/config" +} + variable "google_client_id" { description = "Google OAuth client ID (set via TF_VAR_google_client_id)" type = string @@ -26,3 +32,18 @@ variable "google_client_secret" { type = string sensitive = true } + +variable "groups" { + description = "Standalone Keycloak groups" + type = list(string) + default = [] +} + +variable "proxy_applications" { + description = "Proxy applications protected by rsauth2-proxy" + type = map(object({ + domain = string + allowed_groups = optional(list(string), []) + })) + default = {} +}