diff --git a/modules/swarm/wekan/authentik.tf b/modules/swarm/wekan/authentik.tf new file mode 100644 index 0000000..2a4ce9f --- /dev/null +++ b/modules/swarm/wekan/authentik.tf @@ -0,0 +1,36 @@ +data "authentik_flow" "default_authorization_flow" { + slug = "default-provider-authorization-implicit-consent" +} + +data "authentik_flow" "default_authentication_flow" { + slug = "default-authentication-flow" +} + + +data "authentik_scope_mapping" "wekan" { + managed_list = [ + "goauthentik.io/providers/oauth2/scope-email", + "goauthentik.io/providers/oauth2/scope-openid", + "goauthentik.io/providers/oauth2/scope-profile" + ] +} + + +resource "authentik_provider_oauth2" "wekan" { + name = "Wekan" + client_id = var.secrets.authentik_client_id + client_secret = var.secrets.authentik_client_secret + authorization_flow = data.authentik_flow.default_authorization_flow.id + authentication_flow = data.authentik_flow.default_authentication_flow.id + redirect_uris = [ + "https://kanban.chaoswest.tv/_oauth/oidc" + ] + sub_mode = "user_username" + property_mappings = data.authentik_scope_mapping.wekan.ids +} + +resource "authentik_application" "wekan" { + name = "Wekan" + slug = "wekan" + protocol_provider = authentik_provider_oauth2.wekan.id +} \ No newline at end of file diff --git a/modules/swarm/wekan/main.tf b/modules/swarm/wekan/main.tf new file mode 100644 index 0000000..04d5592 --- /dev/null +++ b/modules/swarm/wekan/main.tf @@ -0,0 +1,100 @@ +data "docker_registry_image" "wekan" { + name = "quay.io/wekan/wekan" +} + +data "docker_registry_image" "mongo" { + name = "mongo:6" // Yes. Don't ask. +} + +data "docker_network" "traefik" { + name = "traefik" +} + +resource "docker_network" "wekan" { + name = "wekan" + attachable = true + driver = "overlay" + + lifecycle { + ignore_changes = [labels] + } +} + + + +locals { + labels = { + "shepherd.auto-update" = "true", + "traefik.enable" = "true" + "traefik.http.services.wekan.loadbalancer.server.port" = "8080", + "traefik.http.routers.wekan.rule" = "Host(`kanban.chaoswest.tv`)", + "traefik.http.routers.wekan.tls" = "true", + "traefik.http.routers.wekan.tls.certresolver" = "default", + } +} + +resource "docker_service" "mongo" { + name = "wekan-mongo" + + task_spec { + networks_advanced { + name = docker_network.wekan.id + } + + container_spec { + image = "${data.docker_registry_image.mongo.name}@${data.docker_registry_image.mongo.sha256_digest}" + + mounts { + target = "/data/db" + source = "/mnt/data/kanban/mongodb/" + type = "bind" + } + } + } +} + +resource "docker_service" "wekan" { + name = "wekan" + + dynamic "labels" { + for_each = local.labels + content { + label = labels.key + value = labels.value + } + } + + task_spec { + networks_advanced { + name = data.docker_network.traefik.id + } + + networks_advanced { + name = docker_network.wekan.id + } + + container_spec { + image = "${data.docker_registry_image.wekan.name}@${data.docker_registry_image.wekan.sha256_digest}" + + env = merge({ + for k, v in var.secrets : k => v + }, { + MONGO_URL = "mongodb://wekan-mongo:27017/wekan" + ROOT_URL = "https://kanban.chaoswest.tv/" + #OIDC_REDIRECTION_ENABLED = "true" + OAUTH2_ENABLED = "true" + OAUTH2_LOGIN_STYLE = "redirect" + OAUTH2_SERVER_URL = "https://authentik.montage2.de" + OAUTH2_CLIENT_ID = var.secrets.authentik_client_id + OAUTH2_SECRET = var.secrets.authentik_client_secret + OAUTH2_AUTH_ENDPOINT = "/application/o/authorize/" + OAUTH2_USERINFO_ENDPOINT = "/application/o/userinfo/" + OAUTH2_TOKEN_ENDPOINT = "/application/o/token/" + OAUTH2_ID_MAP = "preferred_username" + OAUTH2_USERNAME_MAP = "preferred_username" + OAUTH2_FULLNAME_MAP = "given_name" + OAUTH2_EMAIL_MAP = "email" + }) + } + } +} diff --git a/modules/swarm/wekan/outputs.tf b/modules/swarm/wekan/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/swarm/wekan/variables.tf b/modules/swarm/wekan/variables.tf new file mode 100644 index 0000000..9d6f6bd --- /dev/null +++ b/modules/swarm/wekan/variables.tf @@ -0,0 +1,4 @@ +variable "secrets" { + description = "map of secrets to be used by hedgedoc" + type = map(string) +} diff --git a/modules/swarm/wekan/version.tf b/modules/swarm/wekan/version.tf new file mode 100644 index 0000000..50553b1 --- /dev/null +++ b/modules/swarm/wekan/version.tf @@ -0,0 +1,17 @@ +terraform { + required_version = "1.5.5" + required_providers { + authentik = { + source = "goauthentik/authentik" + version = "~>2023.10.0" + } + hetznerdns = { + source = "timohirt/hetznerdns" + version = "~>2.2" + } + docker = { + source = "kreuzwerker/docker" + version = "~>3.0" + } + } +} diff --git a/stacks/ax41-1/.terraform.lock.hcl b/stacks/ax41-1/.terraform.lock.hcl index 5f3f22e..432596e 100644 --- a/stacks/ax41-1/.terraform.lock.hcl +++ b/stacks/ax41-1/.terraform.lock.hcl @@ -16,6 +16,28 @@ provider "registry.terraform.io/carlpett/sops" { ] } +provider "registry.terraform.io/goauthentik/authentik" { + version = "2023.10.0" + constraints = "~> 2023.10.0" + hashes = [ + "h1:d6pqTwKRUjRsHgkS5w2HxZGAHnpqCvDBu5WlDVlsOLM=", + "zh:01fa235282d58dfa12550a7ee5a24c9ac0e48892efc7a457a2706af939ede015", + "zh:0c33b5596e0fce54f5c2627607c9b2a2e9c40dece4310740fa96bdba7ecd36a9", + "zh:1d649be216390208d78197c27a63ea3bc467be8b242fb575835671e0adf21523", + "zh:360b0d6b77a641f58dfc1df1e52b4c257e0cab8724ed93cba3a53ec34fcc4541", + "zh:497f7620d385c074ec72c8c205e8f5c77fcead30931d49d3b2370618b6a4b424", + "zh:774f85fe6f7ab47477c537c86fcf7489c1c710519468ab4fa74a0f79273c38e8", + "zh:83d313d68d72019686fb0aa30dc256d6b94397df069efa9af592fc4f7e4ccf6c", + "zh:85f02dd87a27f0ea8c1df98de8077ca3bdeb4e172c2d4493dba4ad22db455103", + "zh:8824471dc63a90fa6c7b98d122d948d040cb4d646640e255248163eaf6a059dc", + "zh:a7f0da13685673a7dfe257bd4ce5200ff8968b8960a5e617346cb4d854127540", + "zh:ae6adcc5b0cf661abbf65f9a585fbffeaa78e84409e028ef12d55b9ae89d0241", + "zh:b268363560ebfe8b89ed8e78c9a0b255fceec0d3b480c8e9c84e49d8a7da9c7e", + "zh:c747004f9bbc55316c8c16a8a519bcd6fa5a5a183172de408151e9ca453e9e40", + "zh:dd5cbca3b219caac0b412d12175d96f531f63ae363dabf4178649bf51171c5e9", + ] +} + provider "registry.terraform.io/kreuzwerker/docker" { version = "3.0.2" constraints = "~> 3.0" diff --git a/stacks/ax41-1/main.tf b/stacks/ax41-1/main.tf index fafaf99..ec6da4a 100644 --- a/stacks/ax41-1/main.tf +++ b/stacks/ax41-1/main.tf @@ -21,6 +21,11 @@ module "jitsi" { secrets = yamldecode(data.sops_file.secrets.raw).swarm.jitsi } +module "wekan" { + source = "../../modules/swarm/wekan" + secrets = yamldecode(data.sops_file.secrets.raw).swarm.wekan +} + module "hedgedoc" { source = "../../modules/swarm/hedgedoc" secrets = yamldecode(data.sops_file.secrets.raw).swarm.hedgedoc diff --git a/stacks/ax41-1/provider.tf b/stacks/ax41-1/provider.tf index d88c14d..4210c03 100644 --- a/stacks/ax41-1/provider.tf +++ b/stacks/ax41-1/provider.tf @@ -8,3 +8,7 @@ provider "sops" {} provider "hetznerdns" { apitoken = data.sops_file.secrets.data["hetzner_dns_api_token"] } + +provider "authentik" { + url = "https://authentik.montage2.de" +} \ No newline at end of file diff --git a/stacks/ax41-1/secrets.enc.yaml b/stacks/ax41-1/secrets.enc.yaml index 6ce81e2..b35e7aa 100644 --- a/stacks/ax41-1/secrets.enc.yaml +++ b/stacks/ax41-1/secrets.enc.yaml @@ -16,6 +16,9 @@ swarm: CMD_GITLAB_CLIENTSECRET: ENC[AES256_GCM,data:htsR1iVbrGzvvy895ovDxGUemWLxbhHSkJEGcsXk5nwtOoLt1I4N6XNLlPSQ94EzZLJ65bF8Ay3l8nK11B/waw==,iv:aOyhuicriQB2gQJSzKzFvlEK6ZI6zeF5gz4Jjy3anDE=,tag:ldyjLIswF+0Uh8STV0Jmpw==,type:str] CMD_OAUTH2_CLIENT_ID: ENC[AES256_GCM,data:rwt7C+jxcXZRgAHq5D0iIsPCjBjDiBoUb8bYVQtA6qejqDmfXGHAzg==,iv:HL6N9f6gysDJwUYJKV18fdqy+2zAUOiL9HK+k5DvieU=,tag:CqZb/U5LSDBo4K1X79rOTQ==,type:str] CMD_OAUTH2_CLIENT_SECRET: ENC[AES256_GCM,data:F3lebEE0hnwopmKEAD3ySrMEnnjMBy0hgaKcLkZwelIR+j5kR8fUtD2ITndKgQLFhPQXvC5PAkTW93I3tu9Z91/TseIcgZsivxXmRdScMucY0Wmrt/8+yAHKPZxhDsaZbvRnVhwL6v22/eqnmTNDbn62r9I6QfZUqwrogV2wY1I=,iv:vibJn1HyaQ/xgsQvSp7e+cgGhZmsDrsUz/b78XG63oU=,tag:7rKcELyRIkKu2SByXwSTNQ==,type:str] + wekan: + authentik_client_id: ENC[AES256_GCM,data:OBS8HEY=,iv:XpIhSFM6jVRIcTkXmiIdgLNxrDltE7lxIz5OVvkKnQs=,tag:OpwLMCUOyTt9HxenS+4HXg==,type:str] + authentik_client_secret: ENC[AES256_GCM,data:xUpYD1TB9AEo2yCcmgw4Zv7TaFb+zhOgArd5lCd3SmaezQAdoshK+rFoSgxPPfC9AGmA9T40B4S+sZCejNmxZA==,iv:DFlHS0HUVCNaIzXCkveVMeUFuOsC4YFbsse+lLiYzsY=,tag:SAxX2mFQ4yrL/epaq2A/rA==,type:str] sops: kms: [] gcp_kms: [] @@ -31,8 +34,8 @@ sops: WmlRUnowa2lMNWpDT0xEU0htV0w3U00K1f/SO/FBvC9lIBzveBEwhopj5ryMVCmD jw8AdxvmMwsCSfIROKkzMqiUs2zsj6FOMlYFI1Rb07mItSO2Yd7TsA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-01-31T16:00:34Z" - mac: ENC[AES256_GCM,data:XJsH39oi1N0JRwoIP6mvdQfSsBtaxn4N6KZYIHhTXR6Yz2/U2HpGyYoKl7vl2HJBPdjECeje4R1lS4w/I0G++qMpsZHdQglVrSjkpq2P1yZVYFRjN1Xyfjzi58O3WegNLftQpXdlx0T9FCNDLdD6+8BSownLxWWUlp0bpwOIWBc=,iv:f8TSh+aBUuFbLHD/kbA2qkqsZI5oGvlyQt2sO4TRQxk=,tag:DVS91MmrQa8I1Hbz07Ff8Q==,type:str] + lastmodified: "2024-02-07T08:01:01Z" + mac: ENC[AES256_GCM,data:PcBpNRbCuv8/wkrI+zP/VkqBNkKG1coENkhgSy/Z3L1PQ4y6atqbQhQLdfzw+FDHqAn1IVCJirIzI4EGzT2iychn4gZlE7hcK6n0y4eeVRlWzI3pc8QgrD0CoYsa+YsM3fWDLSaY5vOVqa8puQDkNQIC796cOyePNfCnqX6wZWQ=,iv:g2JNSNLqt3ryk8KRU6WKc9V7Gb2KJqtxFsDb6ba17+c=,tag:3gZFQqYypdJAZ/vxinE3Wg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.8.1 diff --git a/stacks/ax41-1/version.tf b/stacks/ax41-1/version.tf index 24fd213..d1d8e22 100644 --- a/stacks/ax41-1/version.tf +++ b/stacks/ax41-1/version.tf @@ -8,6 +8,10 @@ terraform { } required_providers { + authentik = { + source = "goauthentik/authentik" + version = "~>2023.10.0" + } hetznerdns = { source = "timohirt/hetznerdns" version = "~>2.2"