Traefik basic auth + middlewares

This commit is contained in:
Greyscale 2025-01-16 19:38:54 +01:00
parent bfb1f46683
commit 5e73523c38
Signed by: grey
GPG key ID: DDB392AE64B32D89
6 changed files with 70 additions and 20 deletions

View file

@ -23,5 +23,11 @@ resource "local_file" "debug" {
traefik = var.traefik
placement_constraints = var.placement_constraints
build_tags = local.is_build ? local.tags : []
labels = {
computed = local.labels,
traefik = local.traefik_labels,
provided = var.labels,
final = local.merged_labels
}
}))
}

View file

@ -7,4 +7,5 @@ locals {
"ooo.grey.service.name" = var.service_name
"ooo.grey.service.image" = local.image
}
merged_labels = { for key, value in merge(local.labels, local.traefik_labels, var.labels) : key => value if value != null }
}

View file

@ -13,10 +13,19 @@ output "volumes" {
output "docker_service" {
value = docker_service.instance
}
locals {
first_auth = var.traefik.basic-auth-users != null ? "${try(var.traefik.basic-auth-users[0], null)}:${try(nonsensitive(random_password.password[var.traefik.basic-auth-users[0]].result), null)}@" : null
}
output "endpoint" {
value = try(
"https://${var.traefik.domain}",
"http://${docker_service.instance.name}:${docker_service.instance.endpoint_spec[0].ports[0].target_port}",
"https://${local.first_auth}${var.traefik.domain}",
"http://${local.first_auth}${docker_service.instance.name}:${docker_service.instance.endpoint_spec[0].ports[0].target_port}",
null
)
}
output "basic_auth_users" {
value = {
for user in var.traefik.basic-auth-users : user => nonsensitive(htpasswd_password.htpasswd[user].bcrypt)
}
}

View file

@ -82,7 +82,7 @@ resource "docker_service" "instance" {
# Apply the list of Container Labels
dynamic "labels" {
# Filter out null values
for_each = { for key, value in merge(local.labels, local.traefik_labels, var.labels) : key => value if value != null }
for_each = local.merged_labels
content {
label = labels.key
value = labels.value
@ -188,7 +188,7 @@ resource "docker_service" "instance" {
# Service Labels
dynamic "labels" {
for_each = { for key, value in merge(local.labels, local.traefik_labels, var.labels) : key => value if value != null }
for_each = local.merged_labels
content {
label = labels.key
value = labels.value

View file

@ -4,11 +4,15 @@ terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~>3.0"
version = "~> 3.0"
}
local = {
source = "hashicorp/local"
version = "~>2.1"
version = "~> 2.1"
}
htpasswd = {
source = "loafoe/htpasswd"
version = "~> 1.0"
}
}
}

View file

@ -1,19 +1,33 @@
variable "traefik" {
default = null
type = object({
domain = string
port = optional(number)
non-ssl = optional(bool, true)
ssl = optional(bool, false)
rule = optional(string)
middlewares = optional(list(string))
network = optional(object({
name = string
id = string
}))
domain = string
port = optional(number)
non-ssl = optional(bool, true)
ssl = optional(bool, false)
rule = optional(string)
middlewares = optional(list(string))
network = optional(object({ name = string, id = string }))
basic-auth-users = optional(list(string))
})
description = "Whether to enable traefik for the service."
}
resource "random_password" "password" {
for_each = toset(var.traefik.basic-auth-users)
length = 16
special = false
}
resource "random_password" "salt" {
for_each = toset(var.traefik.basic-auth-users)
length = 8
special = true
override_special = "!@#%&*()-_=+[]{}<>:?"
}
resource "htpasswd_password" "htpasswd" {
for_each = toset(var.traefik.basic-auth-users)
password = random_password.password[each.key].result
salt = random_password.salt[each.key].result
}
locals {
is_traefik = var.traefik != null
# Calculate the traefik labels to use if enabled
@ -21,6 +35,21 @@ locals {
substr(var.stack_name, 0, 20),
substr(var.service_name, 0, 63 - 1 - 20),
])
traefik_basic_auth = (
local.is_traefik
? (
var.traefik.basic-auth-users != null
? {
"traefik.http.middlewares.${local.traefik_service}-auth.basicauth.users" = join(",", [
for user in var.traefik.basic-auth-users : "${user}:${htpasswd_password.htpasswd[user].bcrypt}"
])
}
: {}
) : {}
)
traefik_middlewares = concat(coalesce(var.traefik.middlewares, []), [
local.traefik_basic_auth != null ? "${local.traefik_service}-auth" : null
])
traefik_rule = (
local.is_traefik
? (
@ -51,12 +80,13 @@ locals {
"traefik.http.services.${local.traefik_service}-ssl.loadbalancer.passhostheader" = var.traefik.ssl ? "true" : null
"traefik.http.services.${local.traefik_service}-ssl.loadbalancer.server.port" = var.traefik.ssl ? var.traefik.port : null
},
(var.traefik.middlewares != null
(local.traefik_middlewares != null
? {
"traefik.http.routers.${local.traefik_service}.middlewares" = join(",", var.traefik.middlewares)
"traefik.http.routers.${local.traefik_service}-ssl.middlewares" = join(",", var.traefik.middlewares)
"traefik.http.routers.${local.traefik_service}.middlewares" = join(",", local.traefik_middlewares)
"traefik.http.routers.${local.traefik_service}-ssl.middlewares" = join(",", local.traefik_middlewares)
} : {}
)
),
local.traefik_basic_auth,
) : {})
}