Files
kydah-modules/ldap/ldap.tf
2024-10-12 20:32:12 +02:00

158 lines
5.0 KiB
HCL

locals {
app_slug = "${var.instance}${var.component == "" ? "" : "-"}${var.component}"
ldap_labels = merge(var.labels, {
"app.kubernetes.io/component" = "authentik-ldap"
})
base_dn = format("dc=%s", join(",dc=", split(".", var.dns_name)))
base_group_dn = format("ou=groups,%s", local.base_dn)
base_user_dn = format("ou=users,%s", local.base_dn)
authentik_base_url = "http://authentik-authentik.${var.domain}-auth.svc"
ldap_outpost_providers = jsondecode(data.http.get_ldap_outpost.response_body).results[0].providers
ldap_outpost_pk = jsondecode(data.http.get_ldap_outpost.response_body).results[0].pk
app_name = var.component == var.instance ? var.instance : format("%s-%s", var.component, var.instance)
main_group = format("app-%s", local.app_name)
sorted_group_names = reverse(distinct(sort([
for grp in var.user_groups : grp.name
])))
sorted_groups = flatten([
for name in local.sorted_group_names : [
for grp in var.user_groups :
grp if grp.name == name
]
])
}
data "authentik_group" "vynil_admin" {
name = "vynil-ldap-admins"
}
resource "authentik_group" "groups" {
count = length(local.sorted_groups)
name = local.sorted_groups[count.index].name
attributes = jsonencode({ local.app_name = true })
}
data "authentik_group" "readed_groups" {
depends_on = [authentik_group.groups]
count = length(local.sorted_groups)
name = local.sorted_groups[count.index].name
}
resource "authentik_application" "application_ldap" {
name = local.app_slug
slug = "${local.app_slug}-ldap"
protocol_provider = authentik_provider_ldap.provider_ldap.id
meta_launch_url = "blank://blank"
}
resource "authentik_policy_expression" "policy" {
name = local.main_group
expression = <<-EOF
attr = request.user.group_attributes()
return attr['${local.app_name}'] if '${local.app_name}' in attr else False
EOF
}
resource "authentik_policy_binding" "ldap_access_users" {
target = authentik_application.application_ldap.uuid
policy = authentik_policy_expression.policy.id
order = 0
}
resource "authentik_policy_binding" "ldap_access_ldap" {
target = authentik_application.application_ldap.uuid
group = authentik_group.ldapsearch.id
order = 1
}
resource "authentik_policy_binding" "ldap_access_vynil" {
target = authentik_application.application_ldap.uuid
group = data.authentik_group.vynil_admin.id
order = 2
}
resource "kubectl_manifest" "ldap" {
ignore_fields = ["metadata.annotations"]
yaml_body = <<-EOF
apiVersion: "secretgenerator.mittwald.de/v1alpha1"
kind: "StringSecret"
metadata:
name: "${local.app_slug}-ldapsearch"
namespace: "${var.namespace}"
labels: ${jsonencode(local.ldap_labels)}
data:
LDAP_ADMIN_USR: "${local.app_slug}-ldapsearch"
spec:
forceRegenerate: false
fields:
- fieldName: "LDAP_ADMIN_PASS"
length: "32"
EOF
}
data "kubernetes_secret_v1" "ldap_password" {
depends_on = [kubectl_manifest.ldap]
metadata {
name = kubectl_manifest.ldap.name
namespace = var.namespace
}
}
resource "authentik_user" "ldapsearch" {
username = "${local.app_slug}-ldapsearch"
name = "${local.app_slug}-ldapsearch"
}
resource "authentik_group" "ldapsearch" {
name = "${local.app_slug}-ldapsearch"
users = [authentik_user.ldapsearch.id]
}
data "http" "ldapsearch_password" {
url = "${local.authentik_base_url}/api/v3/core/users/${authentik_user.ldapsearch.id}/set_password/"
method = "POST"
request_headers = var.request_headers
request_body = jsonencode({
password = data.kubernetes_secret_v1.ldap_password.data["LDAP_ADMIN_PASS"]
})
lifecycle {
postcondition {
condition = contains([201, 204], self.status_code)
error_message = "Status code invalid"
}
}
}
data "authentik_flow" "ldap_authentication_flow" {
slug = "ldap-authentication-flow"
}
resource "authentik_provider_ldap" "provider_ldap" {
name = "${local.app_slug}-ldap"
base_dn = local.base_dn
search_group = authentik_group.ldapsearch.id
bind_flow = data.authentik_flow.ldap_authentication_flow.id
}
data "http" "get_ldap_outpost" {
depends_on = [authentik_policy_binding.ldap_access_users] # fake dependency so it is not evaluated at plan stage
url = "${local.authentik_base_url}/api/v3/outposts/instances/?name__iexact=ldap"
method = "GET"
request_headers = var.request_headers
lifecycle {
postcondition {
condition = contains([200], self.status_code)
error_message = "Status code invalid"
}
}
}
resource "restapi_object" "ldap_outpost_binding" {
path = "/outposts/instances/${local.ldap_outpost_pk}/"
data = jsonencode({
name = "ldap"
providers = contains(local.ldap_outpost_providers, authentik_provider_ldap.provider_ldap.id) ? local.ldap_outpost_providers : concat(local.ldap_outpost_providers, [authentik_provider_ldap.provider_ldap.id])
})
}