example(idp): build a example on how to use scim #23
20 changed files with 877 additions and 0 deletions
146
examples/iam-scim-integration/.terraform.lock.hcl
generated
Normal file
146
examples/iam-scim-integration/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/goauthentik/authentik" {
|
||||
version = "2026.2.0"
|
||||
constraints = "2026.2.0"
|
||||
hashes = [
|
||||
"h1:On3/Zzv3W72aGsJ4AhW/tnpi4hvq9cxwgf7tF6Tg+a4=",
|
||||
"zh:00c44e8ee842e75de9cc4fd6193b10258d1dc840e5be4aaaf118ffc180dceee0",
|
||||
"zh:13057f08bce3b63613e1be3997dd454ff9568c569dd983987b1550280fbe3d01",
|
||||
"zh:410a1ff2ae4647cc0ab37894f81e4d474b588a0a7f005d05d55e8c3a40978dd2",
|
||||
"zh:43830834d12b3c0eeabe397842f82ca3a6b58a5bc8dd837d55b821419b55ed61",
|
||||
"zh:56eaedd196ed7c4003cee0434b891b38242b4fde2031978d0ddcfdf6e16ee5ad",
|
||||
"zh:5b3c10bb63c3c215ed9e0918e5808b240e3f2ee8248d10cd4d824a4998a213c5",
|
||||
"zh:99c14891bcb92a6b21ef4c0e60f6c0df23e3452808f3eefd67cde78d132c80d9",
|
||||
"zh:9a32cdda9f939f8484e27d4200d004c44f016fe97579a111201083f4beea78e8",
|
||||
"zh:ae5086816144f68de9a0002e7696321169a71473f9d161793f4ae996388f56de",
|
||||
"zh:bd09409dd34608a4ef3ea80cfc5e397268e7872f2e84c1ccdc9b5698e36ddad5",
|
||||
"zh:be7af8b9eb61b0eb5053f14360e5a68caeb32c115efe8e1b583f2e7c91352a2a",
|
||||
"zh:e11726812a1b2caf6b6784a3d074d1f50e3d406e9629c02096a001e5a5979331",
|
||||
"zh:e39183d10d8158ccab51208f4f727c7419b1b1e596f4feb23dc42aebb36d01e3",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/helm" {
|
||||
version = "3.1.1"
|
||||
hashes = [
|
||||
"h1:47CqNwkxctJtL/N/JuEj+8QMg8mRNI/NWeKO5/ydfZU=",
|
||||
"zh:1a6d5ce931708aec29d1f3d9e360c2a0c35ba5a54d03eeaff0ce3ca597cd0275",
|
||||
"zh:3411919ba2a5941801e677f0fea08bdd0ae22ba3c9ce3309f55554699e06524a",
|
||||
"zh:81b36138b8f2320dc7f877b50f9e38f4bc614affe68de885d322629dd0d16a29",
|
||||
"zh:95a2a0a497a6082ee06f95b38bd0f0d6924a65722892a856cfd914c0d117f104",
|
||||
"zh:9d3e78c2d1bb46508b972210ad706dd8c8b106f8b206ecf096cd211c54f46990",
|
||||
"zh:a79139abf687387a6efdbbb04289a0a8e7eaca2bd91cdc0ce68ea4f3286c2c34",
|
||||
"zh:aaa8784be125fbd50c48d84d6e171d3fb6ef84a221dbc5165c067ce05faab4c8",
|
||||
"zh:afecd301f469975c9d8f350cc482fe656e082b6ab0f677d1a816c3c615837cc1",
|
||||
"zh:c54c22b18d48ff9053d899d178d9ffef7d9d19785d9bf310a07d648b7aac075b",
|
||||
"zh:db2eefd55aea48e73384a555c72bac3f7d428e24147bedb64e1a039398e5b903",
|
||||
"zh:ee61666a233533fd2be971091cecc01650561f1585783c381b6f6e8a390198a4",
|
||||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/kubernetes" {
|
||||
version = "3.1.0"
|
||||
constraints = "> 2.14.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/hashicorp/local" {
|
||||
version = "2.9.0"
|
||||
hashes = [
|
||||
"h1:m24fjcInWvTVZ1XSo2MaNuKPe+X/gfG8SIi09rA7a7M=",
|
||||
"zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0",
|
||||
"zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64",
|
||||
"zh:197c79015a10d1cce904a8ea722cbc750c42aeae2da53f44a6a0751d9fd1aa90",
|
||||
"zh:29d0b03e5343a80677ebfeb2e2c31cbe4b1f65e736e53417454a4277fec2544c",
|
||||
"zh:4896bfa6cf1d2fd562b47ef2e87f47862ae92a04f8ad5d764380f0c6653473b8",
|
||||
"zh:531f8529cbca49f681883e57761a05a8398afaef6d1ab0d205d26bf12f4428e8",
|
||||
"zh:6aaf5011d83161c86d2bfb80c0923ec934e578288758da2f37acb7aec129004b",
|
||||
"zh:7430275253d3d3c40aa6179e0ec0d63212874dbbc06c5a51b9d07ec590f9756c",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:be17dc611e95e26cdf6cad79dfccf1064f0e32032a2efeb939a9bbe7fb1cbfe9",
|
||||
"zh:f0e3b0aa644202e1d79d2000dca91f6019425da71e9800fa23f27e51c034f195",
|
||||
"zh:f62bae4519e4ead49182ddc8afe8cf61e2a4c3ba3973b0fbba967736a2696aa3",
|
||||
"zh:fcafa360a5b0b96244f26f4e3a6d642b716a376557142c2442ff2fb12d11da18",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.9.0"
|
||||
constraints = "3.9.0"
|
||||
hashes = [
|
||||
"h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=",
|
||||
"zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1",
|
||||
"zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea",
|
||||
"zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f",
|
||||
"zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0",
|
||||
"zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61",
|
||||
"zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc",
|
||||
"zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e",
|
||||
"zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef",
|
||||
"zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b",
|
||||
"zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257",
|
||||
"zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/time" {
|
||||
version = "0.14.0"
|
||||
constraints = ">= 0.9.1"
|
||||
hashes = [
|
||||
"h1:/hlxsUpuN/lvPTNL9+NyVGsOyRsK5NsxwFMsj5CdOp4=",
|
||||
"zh:12abfd6b800e4d7fa6db7310dec8ffd440b31993861ef188c7ed5260b3073937",
|
||||
"zh:23005521e800bb19e1597bf755c5f70d675d30b685d4255001ed5fa47d9df3f1",
|
||||
"zh:2fea249b582ae97cd1cc10385187ea50993bb47c28cc5df0305e57ceaabf0a10",
|
||||
"zh:322018d3b987b7aad08697178029a2bb667bed699e88328f0c89c52a2fd41341",
|
||||
"zh:32a08e98fce2d273cb9b2c89d6c54727cc9f0a32e15bfd896be4e02cc6b48f95",
|
||||
"zh:3db89aabd0e619616bd4b0f8b373a7586dfe60feffcea12a84a0bdbc445714b3",
|
||||
"zh:7488f56c81d742dc020f29063626c8f07ca188aa97be61e7307e8d62397020a2",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:7cb4067f2e7559b13f7562ef722f948950901eb37834873e98360ab28f66e9d7",
|
||||
"zh:9d552c8345f61e1b7db8e725144981345f18ac1014d58d6f5ddf0928a195fffb",
|
||||
"zh:a8e69fb6b97fc9d86fb19a9f4d42abe33c4a68e700b15387ce2e17d2b9934bed",
|
||||
"zh:aeeb900eb8dd0f790c60ea5c0e0c8d42bd6e4a54f391681d4decca15b544394b",
|
||||
"zh:c239c619101a8c95e1f14061eb973c57a8d15fa0e68878ced5bbd76858ee5b79",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/stackitcloud/stackit" {
|
||||
version = "0.96.0"
|
||||
constraints = ">= 0.87.0, >= 0.95.0"
|
||||
hashes = [
|
||||
"h1:NgwbVCV5pfBVMO3xUMop4l5AzvVv3BuBzXpJjgoZfSU=",
|
||||
"zh:04d309851424a53d3d014dde3b143fc1cdc19fbebf558eb4b927878103f78fb0",
|
||||
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
|
||||
"zh:0ebcdf98a47f301e12925803198320d637552ef57abc49e2a48a009f1ddbf39a",
|
||||
"zh:176238c057193c9c60c365b83463e758892186fcc2bd14bc9bbf69bf471f1d6b",
|
||||
"zh:1c514ec6d09ee210ebb813d49b7d3a71b5b9d0b173c743bce9ab937b1e3d303a",
|
||||
"zh:20433d0dc7e4aa2a806863fc289a2cecb19763624f199babfbe44f22d4d9150f",
|
||||
"zh:452ceacbe4a1f70c81320b9223f4958c9bc122508c79e86bc97cb9241682c053",
|
||||
"zh:5f893229f41f8dc2169b5b02785fb2988e8cad2141722a411711182bafefa015",
|
||||
"zh:69383e27067a6413300d3acbcdad8f890bd187e16630580c09900ba379659284",
|
||||
"zh:694de24bd05027c3c8b7a7c477973f76cd5a11d7fd38819026b5a0e588698fd9",
|
||||
"zh:7c7399e3223dd76efb56ca2e3c9435b41bcbaf549839cec36023f801ca5bdcd2",
|
||||
"zh:8a92b221694c59648d22e2e2a0059015872eff7034ae0ba9eb801fe399644a2c",
|
||||
"zh:90a8ae716c9bc6c8804a38f7a903c7af7114ce324d0126c64e1447b6d255cdba",
|
||||
"zh:d29eb17fde9460c5ce3c7a7975eef0ad7fea692eb17fad5e0421952e4d29dbd2",
|
||||
]
|
||||
}
|
||||
66
examples/iam-scim-integration/010-provider.tf
Normal file
66
examples/iam-scim-integration/010-provider.tf
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
stackit = {
|
||||
source = "stackitcloud/stackit"
|
||||
version = ">=0.95.0"
|
||||
}
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = ">2.14.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = ">= 3.0.0"
|
||||
}
|
||||
authentik = {
|
||||
source = "goauthentik/authentik"
|
||||
version = "2026.2.0"
|
||||
}
|
||||
time = {
|
||||
source = "hashicorp/time"
|
||||
version = ">= 0.9.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "authentik" {
|
||||
url = "https://${stackit_dns_record_set.authentik.name}.${stackit_dns_zone.this.dns_name}"
|
||||
token = random_password.authentik_bootstrap_token.result
|
||||
}
|
||||
|
||||
provider "stackit" {
|
||||
default_region = var.stackit_region
|
||||
service_account_key_path = var.stackit_service_account_key_path
|
||||
enable_beta_resources = true
|
||||
}
|
||||
|
||||
|
||||
provider "kubernetes" {
|
||||
host = yamldecode(module.ske.kubeconfig).clusters.0.cluster.server
|
||||
client_certificate = base64decode(yamldecode(module.ske.kubeconfig).users.0.user.client-certificate-data)
|
||||
client_key = base64decode(yamldecode(module.ske.kubeconfig).users.0.user.client-key-data)
|
||||
cluster_ca_certificate = base64decode(yamldecode(module.ske.kubeconfig).clusters.0.cluster.certificate-authority-data)
|
||||
}
|
||||
|
||||
provider "helm" {
|
||||
kubernetes = {
|
||||
host = yamldecode(module.ske.kubeconfig).clusters.0.cluster.server
|
||||
client_certificate = base64decode(yamldecode(module.ske.kubeconfig).users.0.user.client-certificate-data)
|
||||
client_key = base64decode(yamldecode(module.ske.kubeconfig).users.0.user.client-key-data)
|
||||
cluster_ca_certificate = base64decode(yamldecode(module.ske.kubeconfig).clusters.0.cluster.certificate-authority-data)
|
||||
}
|
||||
}
|
||||
47
examples/iam-scim-integration/020-variables.tf
Normal file
47
examples/iam-scim-integration/020-variables.tf
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
variable "stackit_project_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "stackit_region" {
|
||||
type = string
|
||||
default = "eu01"
|
||||
}
|
||||
|
||||
variable "stackit_service_account_key_path" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "acme_email" {
|
||||
description = "The email address used for ACME registration."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "authentik_scim_long_lived_token" {
|
||||
description = "The SCIM synchronization token provided by the IDP team. This configuration uses a long-lived static token due to Authentik Community Edition limitations. For production environments, dynamically generated, short-lived tokens are highly recommended."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "authentik_number_of_users" {
|
||||
description = "The number of test users to generate"
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "authentik_default_user_password" {
|
||||
description = "The default password assigned to all created test users"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
37
examples/iam-scim-integration/030-ske-cluster.tf
Normal file
37
examples/iam-scim-integration/030-ske-cluster.tf
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
module "ske" {
|
||||
source = "../../modules/test-ske"
|
||||
project_id = var.stackit_project_id
|
||||
cluster_name = "ske-test"
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace_v1" "cert_manager" {
|
||||
metadata {
|
||||
name = "cert-manager"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace_v1" "authentik" {
|
||||
metadata {
|
||||
name = "authentik"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace_v1" "nginx" {
|
||||
metadata {
|
||||
name = "nginx"
|
||||
}
|
||||
}
|
||||
46
examples/iam-scim-integration/040-dns.tf
Normal file
46
examples/iam-scim-integration/040-dns.tf
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
resource "stackit_public_ip" "ingress_floating_ip" {
|
||||
project_id = var.stackit_project_id
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [network_interface_id]
|
||||
}
|
||||
}
|
||||
|
||||
resource "random_string" "this" {
|
||||
length = 6
|
||||
special = false
|
||||
upper = false
|
||||
}
|
||||
|
||||
resource "stackit_dns_zone" "this" {
|
||||
project_id = var.stackit_project_id
|
||||
name = random_string.this.result
|
||||
dns_name = "${random_string.this.result}.runs.onstackit.cloud"
|
||||
type = "primary"
|
||||
default_ttl = 60
|
||||
contact_email = "hostmaster@stackit.cloud"
|
||||
}
|
||||
|
||||
resource "stackit_dns_record_set" "authentik" {
|
||||
project_id = var.stackit_project_id
|
||||
zone_id = stackit_dns_zone.this.zone_id
|
||||
name = "authentik"
|
||||
type = "A"
|
||||
ttl = 60
|
||||
comment = "a record"
|
||||
records = [stackit_public_ip.ingress_floating_ip.ip]
|
||||
}
|
||||
62
examples/iam-scim-integration/050-cert-manager.tf
Normal file
62
examples/iam-scim-integration/050-cert-manager.tf
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
resource "helm_release" "cert_manager" {
|
||||
name = "cert-manager"
|
||||
repository = "https://charts.jetstack.io"
|
||||
chart = "cert-manager"
|
||||
version = "v1.15.1"
|
||||
|
||||
timeout = 120
|
||||
cleanup_on_fail = true
|
||||
force_update = false
|
||||
namespace = kubernetes_namespace_v1.cert_manager.metadata.0.name
|
||||
|
||||
set = [
|
||||
{
|
||||
name = "crds.enabled"
|
||||
value = "true"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
resource "kubernetes_manifest" "cluster_issuer" {
|
||||
manifest = {
|
||||
apiVersion = "cert-manager.io/v1"
|
||||
kind = "ClusterIssuer"
|
||||
metadata = {
|
||||
name = "letsencrypt-prod-cluster"
|
||||
}
|
||||
spec = {
|
||||
acme = {
|
||||
email = var.acme_email
|
||||
server = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
privateKeySecretRef = {
|
||||
name = "letsencrypt-prod-cluster"
|
||||
}
|
||||
solvers = [
|
||||
{
|
||||
http01 = {
|
||||
ingress = {
|
||||
class = "nginx"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
depends_on = [helm_release.cert_manager]
|
||||
}
|
||||
36
examples/iam-scim-integration/060-nginx-ingress.tf
Normal file
36
examples/iam-scim-integration/060-nginx-ingress.tf
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
resource "helm_release" "nginx_ingress" {
|
||||
name = "nginx-ingress"
|
||||
repository = "https://kubernetes.github.io/ingress-nginx"
|
||||
chart = "ingress-nginx"
|
||||
version = "4.2.3"
|
||||
|
||||
namespace = kubernetes_namespace_v1.nginx.metadata.0.name
|
||||
|
||||
values = [
|
||||
<<EOF
|
||||
controller:
|
||||
replicaCount: 1
|
||||
service:
|
||||
type: LoadBalancer
|
||||
annotations:
|
||||
lb.stackit.cloud/ip-mode-proxy: "true"
|
||||
lb.stackit.cloud/external-address: ${stackit_public_ip.ingress_floating_ip.ip}
|
||||
EOF
|
||||
]
|
||||
|
||||
timeout = 600
|
||||
}
|
||||
98
examples/iam-scim-integration/070-authentik-chart.tf
Normal file
98
examples/iam-scim-integration/070-authentik-chart.tf
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
resource "random_password" "authentik_secret_key" {
|
||||
length = 50
|
||||
special = true
|
||||
}
|
||||
|
||||
resource "random_password" "authentik_bootstrap_password" {
|
||||
length = 24
|
||||
special = true
|
||||
}
|
||||
|
||||
resource "random_password" "authentik_bootstrap_token" {
|
||||
length = 40
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "random_password" "postgresql_password" {
|
||||
length = 24
|
||||
special = false
|
||||
}
|
||||
|
||||
locals {
|
||||
authentik_values = {
|
||||
authentik = {
|
||||
secret_key = random_password.authentik_secret_key.result
|
||||
bootstrap_password = random_password.authentik_bootstrap_password.result
|
||||
bootstrap_token = random_password.authentik_bootstrap_token.result
|
||||
postgresql = {
|
||||
user = "authentik"
|
||||
name = "authentik"
|
||||
password = random_password.postgresql_password.result
|
||||
}
|
||||
}
|
||||
postgresql = {
|
||||
enabled = true
|
||||
auth = {
|
||||
username = "authentik"
|
||||
database = "authentik"
|
||||
password = random_password.postgresql_password.result
|
||||
}
|
||||
}
|
||||
server = {
|
||||
ingress = {
|
||||
enabled = true
|
||||
ingressClassName = "nginx"
|
||||
annotations = {
|
||||
"cert-manager.io/cluster-issuer" = "letsencrypt-prod-cluster"
|
||||
}
|
||||
hosts = [
|
||||
"${stackit_dns_record_set.authentik.name}.${stackit_dns_zone.this.dns_name}"
|
||||
]
|
||||
paths = ["/"]
|
||||
tls = [
|
||||
{
|
||||
secretName = "authentik-tls"
|
||||
hosts = [
|
||||
"${stackit_dns_record_set.authentik.name}.${stackit_dns_zone.this.dns_name}"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "helm_release" "authentik" {
|
||||
name = "authentik"
|
||||
repository = "https://charts.goauthentik.io"
|
||||
chart = "authentik"
|
||||
version = "2026.2.3"
|
||||
|
||||
namespace = kubernetes_namespace_v1.authentik.metadata.0.name
|
||||
|
||||
values = [
|
||||
yamlencode(local.authentik_values)
|
||||
]
|
||||
|
||||
timeout = 600
|
||||
}
|
||||
|
||||
resource "time_sleep" "wait_60_seconds" {
|
||||
depends_on = [helm_release.authentik]
|
||||
|
||||
create_duration = "60s"
|
||||
}
|
||||
47
examples/iam-scim-integration/071-authentik-user-groups.tf
Normal file
47
examples/iam-scim-integration/071-authentik-user-groups.tf
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
resource "authentik_user" "test_users" {
|
||||
count = var.authentik_number_of_users
|
||||
|
||||
username = "testuser${count.index + 1}"
|
||||
name = "Test User ${count.index + 1}"
|
||||
email = "testuser${count.index + 1}@${stackit_dns_zone.this.dns_name}"
|
||||
|
||||
password = var.authentik_default_user_password
|
||||
|
||||
attributes = jsonencode({
|
||||
given_name = "Test${count.index + 1}"
|
||||
family_name = "User ${count.index + 1}"
|
||||
preferred_username = "testuser${count.index + 1}"
|
||||
})
|
||||
|
||||
depends_on = [time_sleep.wait_60_seconds]
|
||||
}
|
||||
|
||||
resource "authentik_group" "stackit_test_user" {
|
||||
name = "stackit-admins"
|
||||
users = authentik_user.test_users[*].id
|
||||
depends_on = [time_sleep.wait_60_seconds]
|
||||
}
|
||||
|
||||
data "authentik_property_mapping_provider_scope" "scopes" {
|
||||
managed_list = [
|
||||
"goauthentik.io/providers/oauth2/scope-openid",
|
||||
"goauthentik.io/providers/oauth2/scope-email",
|
||||
"goauthentik.io/providers/oauth2/scope-profile"
|
||||
]
|
||||
|
||||
depends_on = [time_sleep.wait_60_seconds]
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
resource "random_password" "authentik_client_secret" {
|
||||
length = 40
|
||||
special = true
|
||||
}
|
||||
|
||||
data "authentik_flow" "default_authorization_flow" {
|
||||
slug = "default-provider-authorization-implicit-consent"
|
||||
|
||||
depends_on = [time_sleep.wait_60_seconds]
|
||||
}
|
||||
|
||||
data "authentik_flow" "default_invalidation_flow" {
|
||||
slug = "default-provider-invalidation-flow"
|
||||
|
||||
depends_on = [time_sleep.wait_60_seconds]
|
||||
}
|
||||
|
||||
resource "authentik_property_mapping_provider_scope" "stackit_custom_claims" {
|
||||
name = "stackit-custom-claims"
|
||||
scope_name = "profile" # Attaches this data to the standard 'profile' scope
|
||||
expression = <<EOT
|
||||
return {
|
||||
"given_name": request.user.attributes.get("given_name", request.user.name),
|
||||
"family_name": request.user.attributes.get("family_name", request.user.name),
|
||||
"preferred_username": request.user.attributes.get("preferred_username", request.user.username)
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
data "authentik_certificate_key_pair" "this" {
|
||||
name = "authentik Self-signed Certificate"
|
||||
}
|
||||
|
||||
resource "authentik_provider_oauth2" "stackit" {
|
||||
name = "stackit"
|
||||
client_id = "stackit-client"
|
||||
client_secret = random_password.authentik_client_secret.result
|
||||
|
||||
authorization_flow = data.authentik_flow.default_authorization_flow.id
|
||||
invalidation_flow = data.authentik_flow.default_invalidation_flow.id
|
||||
|
||||
allowed_redirect_uris = [
|
||||
{
|
||||
matching_mode = "strict"
|
||||
url = "https://accounts.stackit.cloud/ui/login/login/externalidp/callback"
|
||||
},
|
||||
# debugging
|
||||
{
|
||||
matching_mode = "strict"
|
||||
url = "http://localhost:8080/ui/login/login/externalidp/callback"
|
||||
}
|
||||
]
|
||||
|
||||
signing_key = data.authentik_certificate_key_pair.this.id
|
||||
|
||||
property_mappings = concat(
|
||||
data.authentik_property_mapping_provider_scope.scopes.ids,
|
||||
[authentik_property_mapping_provider_scope.stackit_custom_claims.id]
|
||||
)
|
||||
|
||||
include_claims_in_id_token = true
|
||||
|
||||
depends_on = [time_sleep.wait_60_seconds]
|
||||
|
||||
lifecycle {
|
||||
prevent_destroy = true
|
||||
}
|
||||
}
|
||||
48
examples/iam-scim-integration/073-authentik-scim-sync.tf
Normal file
48
examples/iam-scim-integration/073-authentik-scim-sync.tf
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
data "authentik_property_mapping_provider_scim" "scim_user" {
|
||||
managed_list = [
|
||||
"goauthentik.io/providers/scim/user"
|
||||
]
|
||||
}
|
||||
|
||||
data "authentik_property_mapping_provider_scim" "scim_group" {
|
||||
managed_list = [
|
||||
"goauthentik.io/providers/scim/group"
|
||||
]
|
||||
}
|
||||
|
||||
resource "authentik_provider_scim" "stackit" {
|
||||
name = "stackit-scim"
|
||||
url = "https://accounts.stackit.cloud/scim/v2/"
|
||||
|
||||
token = var.authentik_scim_long_lived_token
|
||||
|
||||
property_mappings = data.authentik_property_mapping_provider_scim.scim_user.ids
|
||||
property_mappings_group = data.authentik_property_mapping_provider_scim.scim_group.ids
|
||||
|
||||
exclude_users_service_account = true
|
||||
}
|
||||
|
||||
resource "authentik_application" "stackit" {
|
||||
name = "STACKIT"
|
||||
slug = "stackit"
|
||||
protocol_provider = authentik_provider_oauth2.stackit.id
|
||||
|
||||
# Connects the SCIM provisioning pipeline to this application
|
||||
backchannel_providers = [
|
||||
authentik_provider_scim.stackit.id
|
||||
]
|
||||
}
|
||||
49
examples/iam-scim-integration/100-outputs.tf
Normal file
49
examples/iam-scim-integration/100-outputs.tf
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
output "authentik_url" {
|
||||
value = "https://${stackit_dns_record_set.authentik.name}.${stackit_dns_zone.this.dns_name}"
|
||||
}
|
||||
|
||||
output "authentik_oidc_issuer" {
|
||||
description = "Issuer identifier URL for your OIDC provider"
|
||||
value = "https://${stackit_dns_record_set.authentik.name}.${stackit_dns_zone.this.dns_name}/application/o/stackit/"
|
||||
}
|
||||
|
||||
output "authentik_oidc_client_id" {
|
||||
description = "ID assigned to our application"
|
||||
value = authentik_provider_oauth2.stackit.client_id
|
||||
}
|
||||
|
||||
output "authentik_oidc_client_secret" {
|
||||
description = "Secret key associated with the Client ID"
|
||||
value = random_password.authentik_client_secret.result
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "stackit_ticket_scopes" {
|
||||
description = "Required permissions to include in the STACKIT Support Ticket"
|
||||
value = "openid email profile"
|
||||
}
|
||||
|
||||
output "stackit_ticket_claims_mapping" {
|
||||
description = "Standard Authentik claims mapping to copy into the STACKIT Support Ticket"
|
||||
value = {
|
||||
unique_user_id = "sub"
|
||||
email_address = "email"
|
||||
preferred_name = "preferred_username" # Or "name"
|
||||
first_name = "given_name"
|
||||
last_name = "family_name"
|
||||
}
|
||||
}
|
||||
9
examples/iam-scim-integration/MAINTAINERS.md
Normal file
9
examples/iam-scim-integration/MAINTAINERS.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Maintainers
|
||||
|
||||
General maintainers:
|
||||
|
||||
- Mauritz Uphoff (mauritz.uphoff@digits.schwarz)
|
||||
|
||||
This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis.
|
||||
For questions, issues, or feature requests, please email general maintainers.
|
||||
Please include the BP name and version in your request. We will track your request as an issue.
|
||||
104
examples/iam-scim-integration/README.md
Normal file
104
examples/iam-scim-integration/README.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# STACKIT IAM-SCIM Integration with Authentik
|
||||
|
||||
This repository provides an automated setup for **Authentik** on STACKIT SKE, pre-configured as an Identity Provider (IdP) for STACKIT with both **OIDC** and **SCIM** support.
|
||||
|
||||
## Integration Details
|
||||
|
||||
### OAuth2 / OIDC
|
||||
|
||||
Authentik acts as the OIDC issuer. The provider is configured with the following:
|
||||
|
||||
- **Client ID**: `stackit-client`
|
||||
- **Scopes**: `openid`, `email`, `profile`
|
||||
- **Custom Claims**: Maps `given_name`, `family_name`, and `preferred_username` from Authentik user attributes.
|
||||
|
||||
### SCIM Provisioning
|
||||
|
||||
Automated user and group synchronization to STACKIT:
|
||||
|
||||
- **Endpoint**: `https://accounts.stackit.cloud/scim/v2/`
|
||||
- **Authentication**: Uses a long-lived token (required for Authentik Community Edition).
|
||||
- **Mapping**: Synchronizes both Users and Groups (e.g., `stackit-admins`).
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ STACKIT Integration Process
|
||||
|
||||
**Self-service provisioning for configuring external Identity Providers is currently a Work In Progress.** Until this is released, you must request the integration by opening a STACKIT support ticket.
|
||||
|
||||
### What to supply in your ticket:
|
||||
|
||||
Please open a support ticket with STACKIT containing the following details:
|
||||
|
||||
**General Information**
|
||||
|
||||
- **Federation type:** OpenID Connect (OIDC)
|
||||
- **Reason for integration:** Brief explanation (e.g., "Enable SSO and SCIM for enterprise users via Authentik")
|
||||
- **Email domains:** All email domains your employees use for login (e.g., `@example.com` and `@foobar.com`)
|
||||
|
||||
**OIDC-Specific Information**
|
||||
|
||||
- **Issuer:** The Issuer identifier URL for your Authentik instance (e.g., `https://authentik.example.com/`)
|
||||
- **Client ID:** The ID assigned to the application (`stackit-client`)
|
||||
- **Client Secret:** The secret key associated with your Client ID _(Note: Provide this securely!)_
|
||||
- **Scopes:** `openid`, `profile`, `email`
|
||||
- **Display name:** Internal name for this federation (e.g., `my_company_authentik`)
|
||||
- **Claims mapping:** \* Unique user ID -> `sub`
|
||||
- Email address -> `email`
|
||||
- Preferred name -> `preferred_username`
|
||||
- First name -> `given_name`
|
||||
- Last name -> `family_name`
|
||||
|
||||
### What you will receive in return:
|
||||
|
||||
Once STACKIT support processes your ticket, they will configure the trust relationship on their end. You will receive:
|
||||
|
||||
1. **Confirmation of Federation:** Your Authentik instance will officially be trusted by the STACKIT login portal.
|
||||
2. **SCIM Credentials:** You will be provided with the required OAuth credentials to generate the necessary Bearer tokens so Authentik can communicate with the STACKIT SCIM API.
|
||||
|
||||
---
|
||||
|
||||
## Testing the SCIM Integration
|
||||
|
||||
### Scenario 1: User Sync
|
||||
|
||||
1. **Create a User**: In the Authentik UI (_Directory -> Users_), create a new test user.
|
||||
2. **Assign to Application**: Ensure the user is assigned to the `STACKIT` application.
|
||||
3. **Verify**: Log in to the STACKIT Portal. If the user doesn't appear immediately, go to _Applications -> STACKIT -> Backchannel Providers_ and click **Sync Now**.
|
||||
|
||||
### Scenario 2: Group & Role Mapping (RBAC)
|
||||
|
||||
1. **Create/Assign Group**: Add your user to the `stackit-admins` group in Authentik.
|
||||
2. **Map to STACKIT Role**: In the STACKIT Org settings, map this group to the `Owner` or `Admin` role.
|
||||
3. **Verify Access**:
|
||||
- Log in to the STACKIT Portal. The user should have the assigned organization-level permissions.
|
||||
- **Remove Group**: Remove the user from the group in Authentik. After sync, the user's permissions in the STACKIT Org will be revoked.
|
||||
|
||||
---
|
||||
|
||||
## Visual Verification
|
||||
|
||||
### 1. Dashboard/Application Overview
|
||||
|
||||

|
||||

|
||||
|
||||
### 2. User & Group Management
|
||||
|
||||

|
||||

|
||||
|
||||
### 3. SCIM Sync
|
||||
|
||||

|
||||
|
||||
### 4. Group on STACKIT Side
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## References & Documentation
|
||||
|
||||
- [Generic OIDC 2.0 Federation Guide](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/generic-oidc-2_0-federation-guide/)
|
||||
- [SCIM Endpoint STACKIT IdP Guide](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/scim-endpoint/)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 314 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 352 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
BIN
examples/iam-scim-integration/docs/authentik-scim-sync.png
Normal file
BIN
examples/iam-scim-integration/docs/authentik-scim-sync.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 395 KiB |
BIN
examples/iam-scim-integration/docs/authentik-user-management.png
Normal file
BIN
examples/iam-scim-integration/docs/authentik-user-management.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 322 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 212 KiB |
Loading…
Add table
Add a link
Reference in a new issue