diff --git a/modules/kubernetes/ingress_factory/main.tf b/modules/kubernetes/ingress_factory/main.tf
index d367fc8a..acff9fc3 100644
--- a/modules/kubernetes/ingress_factory/main.tf
+++ b/modules/kubernetes/ingress_factory/main.tf
@@ -32,14 +32,6 @@ variable "max_body_size" {
type = string
default = "50m"
}
-variable "use_proxy_protocol" {
- type = bool
- default = true
-}
-variable "proxy_timeout" {
- type = number
- default = 60
-}
variable "extra_annotations" {
default = {}
}
@@ -59,9 +51,13 @@ variable "rybbit_site_id" {
default = null
type = string
}
-variable "additional_configuration_snippet" {
+variable "custom_content_security_policy" {
type = string
- default = ""
+ default = null
+}
+variable "exclude_crowdsec" {
+ type = bool
+ default = false
}
@@ -93,79 +89,40 @@ resource "kubernetes_ingress_v1" "proxied-ingress" {
name = var.name
namespace = var.namespace
annotations = merge({
- "kubernetes.io/ingress.class" = "nginx"
- "nginx.ingress.kubernetes.io/backend-protocol" = "${var.backend_protocol}"
-
- "nginx.ingress.kubernetes.io/auth-url" : var.protected ? "http://ak-outpost-authentik-embedded-outpost.authentik.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx" : null
- "nginx.ingress.kubernetes.io/auth-signin" : var.protected ? "https://authentik.viktorbarzin.me/outpost.goauthentik.io/start?rd=$scheme%3A%2F%2F$host$escaped_request_uri" : null
- "nginx.ingress.kubernetes.io/auth-snippet" : var.protected ? "proxy_set_header X-Forwarded-Host $http_host;" : null
- "nginx.ingress.kubernetes.io/auth-response-headers" : var.protected ? "X-authentik-username,X-authentik-uid,X-authentik-email,X-authentik-name,X-authentik-groups" : null
-
- "nginx.ingress.kubernetes.io/proxy-body-size" : var.max_body_size
- "nginx.ingress.kubernetes.io/use-proxy-protocol" : var.use_proxy_protocol
- "nginx.ingress.kubernetes.io/proxy-connect-timeout" : var.proxy_timeout
- "nginx.ingress.kubernetes.io/proxy-send-timeout" : var.proxy_timeout
- "nginx.ingress.kubernetes.io/proxy-read-timeout" : var.proxy_timeout
- "nginx.ingress.kubernetes.io/proxy-buffering" : "on"
-
- "nginx.ingress.kubernetes.io/whitelist-source-range" : var.allow_local_access_only ? "192.168.1.0/24, 10.0.0.0/8, ::1/128, fc00::/7, fe80::/10" : "0.0.0.0/0, ::/0"
- "nginx.ingress.kubernetes.io/ssl-redirect" : "${var.ssl_redirect}"
-
- # DDOS protection
- "nginx.ingress.kubernetes.io/limit-connections" : 100
- "nginx.ingress.kubernetes.io/limit-rps" : 5
- "nginx.ingress.kubernetes.io/limit-rpm" : 100
- "nginx.ingress.kubernetes.io/limit-burst-multiplier" : 50
- "nginx.ingress.kubernetes.io/limit-rate-after" : 100
- "nginx.ingress.kubernetes.io/configuration-snippet" = <<-EOF
- limit_req_status 429;
- limit_conn_status 429;
- # Prevent iframe embedding (clickjacking protection) - allow subdomains only
- add_header Content-Security-Policy "frame-ancestors 'self' *.viktorbarzin.me viktorbarzin.me" always;
- ${var.rybbit_site_id != null ? <<-JS
- # Rybbit Analytics
- # Only modify HTML
- sub_filter_types text/html;
- sub_filter_once off;
-
- # Disable compression so sub_filter works
- proxy_set_header Accept-Encoding "";
-
- # Inject analytics before
- sub_filter '' '
-
- ';
- JS
- : ""
- }
- ${var.additional_configuration_snippet}
- EOF
-
- }, var.extra_annotations)
-}
-
-spec {
- tls {
- hosts = ["${var.name}.${var.root_domain}"] # TODO: refactor me to be easier to use
- secret_name = var.tls_secret_name
+ "traefik.ingress.kubernetes.io/router.middlewares" = join(",", compact([
+ "traefik-rate-limit@kubernetescrd",
+ var.custom_content_security_policy == null ? "traefik-csp-headers@kubernetescrd" : null,
+ var.exclude_crowdsec ? null : "traefik-crowdsec@kubernetescrd",
+ var.protected ? "traefik-authentik-forward-auth@kubernetescrd" : null,
+ var.allow_local_access_only ? "traefik-local-only@kubernetescrd" : null,
+ var.rybbit_site_id != null ? "${var.namespace}-rybbit-analytics-${var.name}@kubernetescrd" : null,
+ var.custom_content_security_policy != null ? "${var.namespace}-custom-csp-${var.name}@kubernetescrd" : null,
+ ]))
+ "traefik.ingress.kubernetes.io/router.entrypoints" = "websecure"
+ }, var.extra_annotations)
}
- rule {
- host = "${var.host != null ? var.host : var.name}.${var.root_domain}"
- http {
- dynamic "path" {
- # for_each = { for pr in var.ingress_path : pr => pr }
- for_each = var.ingress_path
- content {
- path = path.value
- backend {
- service {
+ spec {
+ ingress_class_name = "traefik"
+ tls {
+ hosts = ["${var.name}.${var.root_domain}"]
+ secret_name = var.tls_secret_name
+ }
+ rule {
+ host = "${var.host != null ? var.host : var.name}.${var.root_domain}"
+ http {
+ dynamic "path" {
+ for_each = var.ingress_path
- name = var.service_name != null ? var.service_name : var.name
- port {
- number = var.port
+ content {
+ path = path.value
+ backend {
+ service {
+
+ name = var.service_name != null ? var.service_name : var.name
+ port {
+ number = var.port
+ }
}
}
}
@@ -174,5 +131,46 @@ spec {
}
}
}
+
+# Rybbit analytics middleware (rewritebody plugin) - created per service when rybbit_site_id is set
+resource "kubernetes_manifest" "rybbit_analytics" {
+ count = var.rybbit_site_id != null ? 1 : 0
+
+ manifest = {
+ apiVersion = "traefik.io/v1alpha1"
+ kind = "Middleware"
+ metadata = {
+ name = "rybbit-analytics-${var.name}"
+ namespace = var.namespace
+ }
+ spec = {
+ plugin = {
+ rewritebody = {
+ rewrites = [{
+ regex = ""
+ replacement = ""
+ }]
+ }
+ }
+ }
+ }
}
+# Custom CSP headers middleware - created per service when custom_content_security_policy is set
+resource "kubernetes_manifest" "custom_csp" {
+ count = var.custom_content_security_policy != null ? 1 : 0
+
+ manifest = {
+ apiVersion = "traefik.io/v1alpha1"
+ kind = "Middleware"
+ metadata = {
+ name = "custom-csp-${var.name}"
+ namespace = var.namespace
+ }
+ spec = {
+ headers = {
+ contentSecurityPolicy = var.custom_content_security_policy
+ }
+ }
+ }
+}