Added authentik terraform

This commit is contained in:
AB
2025-09-15 21:42:01 +03:00
parent 9b7f953bd3
commit 00cbd8830b
13 changed files with 971 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
{
"permissions": {
"allow": [
"WebSearch",
"WebFetch(domain:registry.terraform.io)",
"Bash(C:UsersabAppDataLocalMicrosoftWinGetPackagesHashicorp.Terraform_Microsoft.Winget.Source_8wekyb3d8bbweterraform.exe apply -auto-approve)",
"Bash(\"C:\\Users\\ab\\AppData\\Local\\Microsoft\\WinGet\\Packages\\Hashicorp.Terraform_Microsoft.Winget.Source_8wekyb3d8bbwe\\terraform.exe\" apply -auto-approve)",
"Bash(\"C:\\Users\\ab\\AppData\\Local\\Microsoft\\WinGet\\Packages\\Hashicorp.Terraform_Microsoft.Winget.Source_8wekyb3d8bbwe\\terraform.exe\" apply -auto-approve -lock=false)",
"Bash(\"C:\\Users\\ab\\AppData\\Local\\Microsoft\\WinGet\\Packages\\Hashicorp.Terraform_Microsoft.Winget.Source_8wekyb3d8bbwe\\terraform.exe\" plan -lock=false)",
"Bash(\"C:\\Users\\ab\\AppData\\Local\\Microsoft\\WinGet\\Packages\\Hashicorp.Terraform_Microsoft.Winget.Source_8wekyb3d8bbwe\\terraform.exe\" apply -replace=\"authentik_outpost.outposts[\"\"kubernetes-outpost\"\"]\" -auto-approve -lock=false)"
],
"deny": [],
"ask": []
}
}

44
terraform/authentik/.terraform.lock.hcl generated Normal file
View File

@@ -0,0 +1,44 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/goauthentik/authentik" {
version = "2025.8.1"
constraints = ">= 2023.10.0"
hashes = [
"h1:L3Fh0LyQ066laexCAeqLd+AVuSPDemwCmYgq1Bges6c=",
"zh:0c3f1083fd48f20ed06959401ff1459fbb5d454d81c8175b5b6d321b308c0be3",
"zh:21c6d93f8d26e688da38a660d121b5624e3597c426c671289f31a17a9771abbf",
"zh:301b5763ffc4c5fe47aa7e851ce0b19f71bab4fae5c81003ad81b38775e85f78",
"zh:4f7ee6473f6a687340538ddac0ec4a0453664186b15fdb0bb2fb5fcd8fb3ad30",
"zh:7927f4f634c9e072d4aa6620d09e97dc83eeb1dbd0667102086779cd5fc495c1",
"zh:84e7c2a3f3de721a54abe4c971d9a163127f5e4af91d023260fea305ac74bcf4",
"zh:92af52aaac518c426164eb731d282f51a5825e64e6a02b0695952177a7af7d9c",
"zh:a6920a54d5df69342f4ea2d903676145b00e7375d2f2eecc0840858d83b3b4a8",
"zh:ac8a60801fc55fd05b3471778f908ed43072e046997c0082644c9602b84dafec",
"zh:b1cc29e2878aa94a3827fd5e1dd8cffb98397aa4093d6a4852c6e53157e9b35f",
"zh:c2d78f308c4d70a16ef4f6d1f4822a64f8f160d0a207f2121904cdd6f4942db4",
"zh:ca970e5776f408059a84b4e17f6ac257ec92afae956be74f3807c548e4567eaa",
"zh:eb2e3650ee0eec033207b6d72fcb938dc5846c6feb8a61ae30d61981ea411269",
"zh:fcb93e51c84ba592bc2b075d7342e475126e5029620959666999b5b1bd11cb98",
]
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.7.2"
constraints = ">= 3.5.0"
hashes = [
"h1:0hcNr59VEJbhZYwuDE/ysmyTS0evkfcLarlni+zATPM=",
"zh:14829603a32e4bc4d05062f059e545a91e27ff033756b48afbae6b3c835f508f",
"zh:1527fb07d9fea400d70e9e6eb4a2b918d5060d604749b6f1c361518e7da546dc",
"zh:1e86bcd7ebec85ba336b423ba1db046aeaa3c0e5f921039b3f1a6fc2f978feab",
"zh:24536dec8bde66753f4b4030b8f3ef43c196d69cccbea1c382d01b222478c7a3",
"zh:29f1786486759fad9b0ce4fdfbbfece9343ad47cd50119045075e05afe49d212",
"zh:4d701e978c2dd8604ba1ce962b047607701e65c078cb22e97171513e9e57491f",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:7b8434212eef0f8c83f5a90c6d76feaf850f6502b61b53c329e85b3b281cba34",
"zh:ac8a23c212258b7976e1621275e3af7099e7e4a3d4478cf8d5d2a27f3bc3e967",
"zh:b516ca74431f3df4c6cf90ddcdb4042c626e026317a33c53f0b445a3d93b720d",
"zh:dc76e4326aec2490c1600d6871a95e78f9050f9ce427c71707ea412a2f2f1a62",
"zh:eac7b63e86c749c7d48f527671c7aee5b4e26c10be6ad7232d6860167f99dbb0",
]
}

View File

@@ -0,0 +1,55 @@
# Authentik Terraform Module
Terraform module for managing Authentik applications with OAuth2/OpenID and Proxy providers, including automatic Outpost assignment.
## Usage
```hcl
module "authentik" {
source = "./authentik"
authentik_url = "https://auth.example.com"
authentik_token = var.authentik_token
oauth_applications = {
"gitlab" = {
name = "GitLab OAuth"
slug = "gitlab"
redirect_uris = ["https://gitlab.example.com/users/auth/openid_connect/callback"]
}
}
proxy_applications = {
"portainer" = {
name = "Portainer"
slug = "portainer"
external_host = "https://portainer.example.com"
internal_host = "http://portainer:9000"
outpost = "k8s-outpost"
}
}
outposts = {
"k8s-outpost" = {
name = "Kubernetes Outpost"
type = "proxy"
service_connection = "k8s-local"
}
}
}
```
## Structure
- `main.tf` - Main configuration
- `variables.tf` - Input variables
- `outputs.tf` - Output values
- `modules/oauth-provider/` - OAuth2/OIDC provider module
- `modules/proxy-provider/` - Proxy provider module
- `terraform.tfvars.example` - Configuration example
## Requirements
- Terraform >= 1.0
- Authentik provider >= 2023.10.0
- Authentik API token with admin permissions

181
terraform/authentik/main.tf Normal file
View File

@@ -0,0 +1,181 @@
data "authentik_flow" "default_authorization_flow" {
slug = var.default_authorization_flow
}
data "authentik_flow" "default_authentication_flow" {
slug = var.default_authentication_flow
}
data "authentik_flow" "default_invalidation_flow" {
slug = var.default_invalidation_flow
}
resource "authentik_group" "groups" {
for_each = var.groups
name = each.value.name
is_superuser = each.value.is_superuser
parent = each.value.parent
attributes = jsonencode(each.value.attributes)
}
resource "authentik_certificate_key_pair" "certificates" {
for_each = var.certificates
name = each.value.name
certificate_data = each.value.certificate_data
key_data = each.value.key_data
}
data "authentik_service_connection_kubernetes" "local_k8s" {
name = "Local Kubernetes Cluster"
}
resource "authentik_flow" "flows" {
for_each = var.flows
name = each.value.name
title = each.value.title
slug = each.value.slug
designation = each.value.designation
policy_engine_mode = each.value.policy_engine_mode
compatibility_mode = each.value.compatibility_mode
layout = each.value.layout
denied_action = each.value.denied_action
}
resource "authentik_property_mapping_provider_scope" "oidc_mappings" {
for_each = {
for k, v in var.property_mappings : k => v
if v.oidc_scope != null
}
name = each.value.name
scope_name = each.value.oidc_scope
expression = each.value.expression
}
resource "authentik_property_mapping_provider_saml" "saml_mappings" {
for_each = {
for k, v in var.property_mappings : k => v
if v.saml_name != null
}
name = each.value.name
saml_name = each.value.saml_name
expression = each.value.expression
}
module "oauth_applications" {
source = "./modules/oauth-provider"
for_each = var.oauth_applications
name = each.value.name
app_name = each.value.name
app_slug = each.value.slug
app_group = each.value.group
client_id = each.value.client_id
authorization_flow = try(authentik_flow.flows[each.value.authorization_flow].id, data.authentik_flow.default_authorization_flow.id)
invalidation_flow = data.authentik_flow.default_invalidation_flow.id
redirect_uris = each.value.redirect_uris
client_type = each.value.client_type
include_claims_in_id_token = each.value.include_claims_in_id_token
access_code_validity = each.value.access_code_validity
access_token_validity = each.value.access_token_validity
refresh_token_validity = each.value.refresh_token_validity
property_mappings = each.value.property_mappings
signing_key = each.value.signing_key
policy_engine_mode = each.value.policy_engine_mode
meta_description = each.value.meta_description
meta_launch_url = each.value.meta_launch_url
meta_icon = each.value.meta_icon
}
module "proxy_applications" {
source = "./modules/proxy-provider"
for_each = var.proxy_applications
name = each.value.name
app_name = each.value.name
app_slug = each.value.slug
app_group = each.value.group
external_host = each.value.external_host
internal_host = each.value.internal_host
internal_host_ssl_validation = each.value.internal_host_ssl_validation
authorization_flow = try(authentik_flow.flows[each.value.authorization_flow].id, data.authentik_flow.default_authorization_flow.id)
invalidation_flow = data.authentik_flow.default_invalidation_flow.id
mode = each.value.mode
intercept_header_auth = each.value.intercept_header_auth
basic_auth_enabled = each.value.basic_auth_enabled
basic_auth_user_attribute = each.value.basic_auth_username_attribute
basic_auth_password_attribute = each.value.basic_auth_password_attribute
cookie_domain = each.value.cookie_domain
skip_path_regex = each.value.skip_path_regex
policy_engine_mode = each.value.policy_engine_mode
meta_description = each.value.meta_description
meta_launch_url = each.value.meta_launch_url
meta_icon = each.value.meta_icon
}
locals {
oauth_outpost_assignments = {
for app_key, app in var.oauth_applications : app_key => app.outpost
if app.outpost != null
}
proxy_outpost_assignments = {
for app_key, app in var.proxy_applications : app_key => app.outpost
if app.outpost != null
}
outpost_providers = {
for outpost_key, outpost in var.outposts : outpost_key => concat(
[for app_key, app_outpost in local.oauth_outpost_assignments :
module.oauth_applications[app_key].provider_id if app_outpost == outpost_key],
[for app_key, app_outpost in local.proxy_outpost_assignments :
module.proxy_applications[app_key].provider_id if app_outpost == outpost_key]
)
}
}
resource "authentik_outpost" "outposts" {
for_each = {
for k, v in var.outposts : k => v
if length(lookup(local.outpost_providers, k, [])) > 0
}
name = each.value.name
type = "proxy"
protocol_providers = local.outpost_providers[each.key]
service_connection = data.authentik_service_connection_kubernetes.local_k8s.id
config = jsonencode({
log_level = "info"
docker_labels = null
authentik_host = var.authentik_url
docker_network = null
container_image = null
docker_map_ports = true
refresh_interval = "minutes=5"
kubernetes_replicas = 1
kubernetes_namespace = "authentik"
authentik_host_browser = ""
object_naming_template = "ak-outpost-%(name)s"
authentik_host_insecure = false
kubernetes_json_patches = null
kubernetes_service_type = "ClusterIP"
kubernetes_image_pull_secrets = []
kubernetes_ingress_class_name = null
kubernetes_disabled_components = []
kubernetes_ingress_annotations = {}
kubernetes_ingress_secret_name = "authentik-outpost-tls"
})
depends_on = [
module.oauth_applications,
module.proxy_applications
]
}

View File

@@ -0,0 +1,59 @@
terraform {
required_providers {
authentik = {
source = "goauthentik/authentik"
version = ">= 2023.10.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.5.0"
}
}
}
resource "random_password" "client_secret" {
count = var.client_secret == null ? 1 : 0
length = 40
special = true
}
resource "authentik_provider_oauth2" "provider" {
name = var.name
client_id = var.client_id != null ? var.client_id : random_id.client_id[0].hex
client_secret = var.client_secret != null ? var.client_secret : random_password.client_secret[0].result
client_type = var.client_type
authorization_flow = var.authorization_flow
invalidation_flow = var.invalidation_flow
include_claims_in_id_token = var.include_claims_in_id_token
property_mappings = var.property_mappings
}
resource "random_id" "client_id" {
count = var.client_id == null ? 1 : 0
byte_length = 20
}
resource "authentik_application" "app" {
name = var.app_name
slug = var.app_slug
protocol_provider = authentik_provider_oauth2.provider.id
group = var.app_group
policy_engine_mode = var.policy_engine_mode
meta_description = var.meta_description
meta_launch_url = var.meta_launch_url
meta_icon = var.meta_icon
}
resource "authentik_policy_binding" "app_access" {
for_each = var.access_policies
target = authentik_application.app.id
policy = each.value.policy_id
order = each.value.order
enabled = lookup(each.value, "enabled", true)
timeout = lookup(each.value, "timeout", 30)
negate = lookup(each.value, "negate", false)
failure_result = lookup(each.value, "failure_result", true)
}

View File

@@ -0,0 +1,30 @@
output "provider_id" {
description = "ID of the OAuth2 provider"
value = authentik_provider_oauth2.provider.id
}
output "application_id" {
description = "ID of the application"
value = authentik_application.app.id
}
output "application_uuid" {
description = "UUID of the application"
value = authentik_application.app.id
}
output "client_id" {
description = "OAuth2 Client ID"
value = authentik_provider_oauth2.provider.client_id
}
output "client_secret" {
description = "OAuth2 Client Secret"
value = authentik_provider_oauth2.provider.client_secret
sensitive = true
}
output "application_slug" {
description = "Application slug"
value = authentik_application.app.slug
}

View File

@@ -0,0 +1,138 @@
variable "name" {
description = "Name of the OAuth2 provider"
type = string
}
variable "app_name" {
description = "Name of the application"
type = string
}
variable "app_slug" {
description = "Slug of the application"
type = string
}
variable "app_group" {
description = "Group for the application"
type = string
default = ""
}
variable "client_id" {
description = "OAuth2 Client ID"
type = string
default = null
}
variable "client_secret" {
description = "OAuth2 Client Secret"
type = string
default = null
sensitive = true
}
variable "client_type" {
description = "OAuth2 Client type (confidential or public)"
type = string
default = "confidential"
validation {
condition = contains(["confidential", "public"], var.client_type)
error_message = "Client type must be either 'confidential' or 'public'."
}
}
variable "authorization_flow" {
description = "Authorization flow UUID"
type = string
}
variable "invalidation_flow" {
description = "Invalidation flow UUID"
type = string
}
variable "redirect_uris" {
description = "List of allowed redirect URIs"
type = list(string)
default = []
}
variable "access_code_validity" {
description = "Access code validity duration"
type = string
default = "minutes=1"
}
variable "access_token_validity" {
description = "Access token validity duration"
type = string
default = "minutes=5"
}
variable "refresh_token_validity" {
description = "Refresh token validity duration"
type = string
default = "days=30"
}
variable "include_claims_in_id_token" {
description = "Include claims in ID token"
type = bool
default = true
}
variable "signing_key" {
description = "Signing key UUID"
type = string
default = null
}
variable "property_mappings" {
description = "List of property mapping UUIDs"
type = list(string)
default = []
}
variable "policy_engine_mode" {
description = "Policy engine mode"
type = string
default = "all"
validation {
condition = contains(["all", "any"], var.policy_engine_mode)
error_message = "Policy engine mode must be either 'all' or 'any'."
}
}
variable "meta_description" {
description = "Application meta description"
type = string
default = ""
}
variable "meta_launch_url" {
description = "Application launch URL"
type = string
default = ""
}
variable "meta_icon" {
description = "Application icon URL"
type = string
default = ""
}
variable "access_policies" {
description = "Access policies for the application"
type = map(object({
policy_id = string
order = number
enabled = optional(bool, true)
timeout = optional(number, 30)
negate = optional(bool, false)
failure_result = optional(bool, true)
}))
default = {}
}

View File

@@ -0,0 +1,49 @@
terraform {
required_providers {
authentik = {
source = "goauthentik/authentik"
version = ">= 2023.10.0"
}
}
}
resource "authentik_provider_proxy" "provider" {
name = var.name
external_host = var.external_host
internal_host = var.internal_host
internal_host_ssl_validation = var.internal_host_ssl_validation
authorization_flow = var.authorization_flow
invalidation_flow = var.invalidation_flow
mode = var.mode
cookie_domain = var.cookie_domain
skip_path_regex = var.skip_path_regex
intercept_header_auth = var.intercept_header_auth
basic_auth_enabled = var.basic_auth_enabled
basic_auth_password_attribute = var.basic_auth_password_attribute
property_mappings = var.property_mappings
}
resource "authentik_application" "app" {
name = var.app_name
slug = var.app_slug
protocol_provider = authentik_provider_proxy.provider.id
group = var.app_group
policy_engine_mode = var.policy_engine_mode
meta_description = var.meta_description
meta_launch_url = var.meta_launch_url
meta_icon = var.meta_icon
}
resource "authentik_policy_binding" "app_access" {
for_each = var.access_policies
target = authentik_application.app.id
policy = each.value.policy_id
order = each.value.order
enabled = lookup(each.value, "enabled", true)
timeout = lookup(each.value, "timeout", 30)
negate = lookup(each.value, "negate", false)
failure_result = lookup(each.value, "failure_result", true)
}

View File

@@ -0,0 +1,35 @@
output "provider_id" {
description = "ID of the Proxy provider"
value = authentik_provider_proxy.provider.id
}
output "application_id" {
description = "ID of the application"
value = authentik_application.app.id
}
output "application_uuid" {
description = "UUID of the application"
value = authentik_application.app.id
}
output "application_slug" {
description = "Application slug"
value = authentik_application.app.slug
}
output "launch_url" {
description = "Application launch URL"
value = authentik_application.app.meta_launch_url
}
output "external_host" {
description = "External host URL"
value = authentik_provider_proxy.provider.external_host
}
output "internal_host" {
description = "Internal host URL"
value = authentik_provider_proxy.provider.internal_host
}

View File

@@ -0,0 +1,145 @@
variable "name" {
description = "Name of the Proxy provider"
type = string
}
variable "app_name" {
description = "Name of the application"
type = string
}
variable "app_slug" {
description = "Slug of the application"
type = string
}
variable "app_group" {
description = "Group for the application"
type = string
default = ""
}
variable "external_host" {
description = "External hostname for the proxy"
type = string
}
variable "internal_host" {
description = "Internal hostname for the proxy"
type = string
default = ""
}
variable "internal_host_ssl_validation" {
description = "Enable SSL validation for internal host"
type = bool
default = true
}
variable "authorization_flow" {
description = "Authorization flow UUID"
type = string
}
variable "invalidation_flow" {
description = "Invalidation flow UUID"
type = string
}
variable "mode" {
description = "Proxy mode (proxy, forward_single, forward_domain)"
type = string
default = "proxy"
validation {
condition = contains(["proxy", "forward_single", "forward_domain"], var.mode)
error_message = "Mode must be one of: proxy, forward_single, forward_domain."
}
}
variable "cookie_domain" {
description = "Cookie domain for the proxy"
type = string
default = ""
}
variable "skip_path_regex" {
description = "Regular expression for paths to skip authentication"
type = string
default = ""
}
variable "intercept_header_auth" {
description = "Intercept header authentication"
type = bool
default = false
}
variable "basic_auth_enabled" {
description = "Enable basic authentication"
type = bool
default = false
}
variable "basic_auth_password_attribute" {
description = "Attribute for basic auth password"
type = string
default = ""
}
variable "basic_auth_user_attribute" {
description = "Attribute for basic auth username"
type = string
default = ""
}
variable "property_mappings" {
description = "List of property mapping UUIDs"
type = list(string)
default = []
}
variable "policy_engine_mode" {
description = "Policy engine mode"
type = string
default = "all"
validation {
condition = contains(["all", "any"], var.policy_engine_mode)
error_message = "Policy engine mode must be either 'all' or 'any'."
}
}
variable "meta_description" {
description = "Application meta description"
type = string
default = ""
}
variable "meta_launch_url" {
description = "Application launch URL"
type = string
default = ""
}
variable "meta_icon" {
description = "Application icon URL"
type = string
default = ""
}
variable "access_policies" {
description = "Access policies for the application"
type = map(object({
policy_id = string
order = number
enabled = optional(bool, true)
timeout = optional(number, 30)
negate = optional(bool, false)
failure_result = optional(bool, true)
}))
default = {}
}

View File

@@ -0,0 +1,70 @@
output "oauth_applications" {
description = "OAuth2/OpenID applications details"
value = {
for k, v in module.oauth_applications : k => {
application_id = v.application_id
application_uuid = v.application_uuid
client_id = v.client_id
client_secret = v.client_secret
slug = v.application_slug
}
}
sensitive = true
}
output "proxy_applications" {
description = "Proxy applications details"
value = {
for k, v in module.proxy_applications : k => {
application_id = v.application_id
application_uuid = v.application_uuid
external_host = v.external_host
internal_host = v.internal_host
slug = v.application_slug
}
}
}
output "outposts" {
description = "Outposts details"
value = {
for k, v in authentik_outpost.outposts : k => {
id = v.id
name = v.name
type = v.type
}
}
}
output "groups" {
description = "Groups details"
value = {
for k, v in authentik_group.groups : k => {
id = v.id
name = v.name
}
}
}
output "flows" {
description = "Custom flows details"
value = {
for k, v in authentik_flow.flows : k => {
id = v.id
slug = v.slug
name = v.name
}
}
}
output "certificates" {
description = "Certificates details"
value = {
for k, v in authentik_certificate_key_pair.certificates : k => {
id = v.id
name = v.name
fingerprint_sha256 = v.fingerprint_sha256
fingerprint_sha1 = v.fingerprint_sha1
}
}
}

View File

@@ -0,0 +1,13 @@
terraform {
required_providers {
authentik = {
source = "goauthentik/authentik"
version = "2025.8.1"
}
}
}
provider "authentik" {
url = "https://idm.hexor.cy"
token = "qXcuoCg77JaRgqnU6rqIIBa8MBJ4UNyLPTL89dZI8zeC2jfaWqQ7k56BJs8F"
}

View File

@@ -0,0 +1,137 @@
variable "oauth_applications" {
description = "Map of OAuth2/OpenID applications"
type = map(object({
name = string
slug = string
group = optional(string, "")
policy_engine_mode = optional(string, "all")
meta_description = optional(string, "")
meta_launch_url = optional(string, "")
meta_icon = optional(string, "")
redirect_uris = list(string)
client_type = optional(string, "confidential")
client_id = optional(string, null)
include_claims_in_id_token = optional(bool, true)
access_code_validity = optional(string, "minutes=1")
access_token_validity = optional(string, "minutes=5")
refresh_token_validity = optional(string, "days=30")
property_mappings = optional(list(string), [])
authorization_flow = optional(string, null)
signing_key = optional(string, null)
outpost = optional(string, null)
}))
default = {}
}
variable "proxy_applications" {
description = "Map of Proxy applications"
type = map(object({
name = string
slug = string
group = optional(string, "")
policy_engine_mode = optional(string, "all")
meta_description = optional(string, "")
meta_launch_url = optional(string, "")
meta_icon = optional(string, "")
external_host = string
internal_host = optional(string, "")
internal_host_ssl_validation = optional(bool, true)
mode = optional(string, "proxy")
intercept_header_auth = optional(bool, false)
basic_auth_enabled = optional(bool, false)
basic_auth_username_attribute = optional(string, "")
basic_auth_password_attribute = optional(string, "")
cookie_domain = optional(string, "")
authorization_flow = optional(string, null)
skip_path_regex = optional(string, "")
outpost = optional(string, null)
}))
default = {}
}
variable "outposts" {
description = "Map of Outposts (only proxy type supported)"
type = map(object({
name = string
config = optional(map(any), {})
}))
default = {}
}
variable "flows" {
description = "Map of authentication flows"
type = map(object({
name = string
title = string
slug = string
designation = string
policy_engine_mode = optional(string, "all")
compatibility_mode = optional(bool, false)
layout = optional(string, "stacked")
denied_action = optional(string, "message_continue")
}))
default = {}
}
variable "groups" {
description = "Map of user groups"
type = map(object({
name = string
is_superuser = optional(bool, false)
parent = optional(string, null)
attributes = optional(map(any), {})
}))
default = {}
}
variable "certificates" {
description = "Map of certificates for HTTPS"
type = map(object({
name = string
certificate_data = string
key_data = string
managed = optional(string, null)
}))
default = {}
}
variable "property_mappings" {
description = "Custom property mappings for SAML/OAuth"
type = map(object({
name = string
expression = string
saml_name = optional(string, null)
oidc_scope = optional(string, null)
}))
default = {}
}
variable "default_authorization_flow" {
description = "Default authorization flow slug"
type = string
default = "default-provider-authorization-implicit-consent"
}
variable "default_authentication_flow" {
description = "Default authentication flow slug"
type = string
default = "default-authentication-flow"
}
variable "default_invalidation_flow" {
description = "Default invalidation flow slug"
type = string
default = "default-provider-invalidation-flow"
}
variable "tags" {
description = "Tags to apply to all resources"
type = map(string)
default = {}
}
variable "authentik_url" {
description = "Authentik URL"
type = string
}