diff --git a/apps/okd/forward.tf b/apps/okd/forward.tf deleted file mode 100644 index 96ec9cd..0000000 --- a/apps/okd/forward.tf +++ /dev/null @@ -1,161 +0,0 @@ -locals { - authentik-token = data.kubernetes_secret_v1.authentik.data["AUTHENTIK_BOOTSTRAP_TOKEN"] - request_headers = { - "Content-Type" = "application/json" - Authorization = "Bearer ${local.authentik-token}" - } - forward-outpost-providers = jsondecode(data.http.get_forward_outpost.response_body).results[0].providers - forward-outpost-pk = jsondecode(data.http.get_forward_outpost.response_body).results[0].pk - app-name = var.component == var.instance ? var.instance : format("%s-%s", var.component, var.instance) - app-icon = "static/assets/okd-logo.svg" - main-group = format("app-%s", local.app-name) - sub-groups = [] - external-url = format("https://%s", local.dns-names[0]) - access-token-validity = "hours=10" // ;minutes=10 - rules-icons = [ for v in local.dns-names : { - "host" = "${v}" - "http" = { - "paths" = [{ - "backend" = { - "service" = local.service - } - "path" = "/${local.app-icon}" - "pathType" = "Prefix" - }] - } - }] -} - -resource "kubectl_manifest" "prj_ingress_icon" { - force_conflicts = true - yaml_body = <<-EOF - apiVersion: "networking.k8s.io/v1" - kind: "Ingress" - metadata: - name: "${var.instance}-icons" - namespace: "${var.namespace}" - labels: ${jsonencode(local.common-labels)} - spec: - ingressClassName: "${var.ingress-class}" - rules: ${jsonencode(local.rules-icons)} - tls: - - hosts: ${jsonencode(local.dns-names)} - secretName: "${var.instance}-cert" - EOF -} - -data "authentik_flow" "default-authorization-flow" { - depends_on = [authentik_group.prj_users] - slug = "default-provider-authorization-implicit-consent" -} - -resource "authentik_provider_proxy" "prj_forward" { - name = local.app-name - external_host = local.external-url - authorization_flow = data.authentik_flow.default-authorization-flow.id - mode = "forward_single" - access_token_validity = local.access-token-validity -} - - -resource "authentik_application" "prj_application" { - name = local.app-name - slug = "${var.component}-${var.instance}" - group = var.app-group - protocol_provider = authentik_provider_proxy.prj_forward.id - meta_launch_url = local.external-url - meta_icon = format("%s/%s", local.external-url, local.app-icon) -} - -resource "authentik_group" "prj_users" { - name = local.main-group - attributes = jsonencode({"${local.app-name}" = true}) -} - -resource "authentik_group" "subgroup" { - count = length(local.sub-groups) - name = format("%s-%s", local.app-name, local.sub-groups[count.index]) - parent = authentik_group.prj_users.id -} - -resource "authentik_policy_expression" "policy" { - name = local.main-group - expression = <<-EOF - attr = request.user.group_attributes() - return attr['${local.app-name}'] if '${local.app-name}' in attr else False - EOF -} - -data "authentik_group" "vynil-admin" { - depends_on = [authentik_group.prj_users] # fake dependency so it is not evaluated at plan stage - name = "vynil-forward-admins" -} - -resource "authentik_policy_binding" "prj_access_users" { - target = authentik_application.prj_application.uuid - policy = authentik_policy_expression.policy.id - order = 0 -} -resource "authentik_policy_binding" "prj_access_vynil" { - target = authentik_application.prj_application.uuid - group = data.authentik_group.vynil-admin.id - order = 1 -} - -data "http" "get_forward_outpost" { - depends_on = [authentik_provider_proxy.prj_forward] - url = "http://authentik.${var.domain}-auth.svc/api/v3/outposts/instances/?name__iexact=forward" - method = "GET" - request_headers = local.request_headers - lifecycle { - postcondition { - condition = contains([200], self.status_code) - error_message = "Status code invalid" - } - } -} - -provider "restapi" { - uri = "http://authentik.${var.domain}-auth.svc/api/v3/" - headers = local.request_headers - create_method = "PATCH" - update_method = "PATCH" - destroy_method = "PATCH" - write_returns_object = true - id_attribute = "name" -} - -resource "restapi_object" "forward_outpost_binding" { - path = "/outposts/instances/${local.forward-outpost-pk}/" - data = jsonencode({ - name = "forward" - providers = contains(local.forward-outpost-providers, authentik_provider_proxy.prj_forward.id) ? local.forward-outpost-providers : concat(local.forward-outpost-providers, [authentik_provider_proxy.prj_forward.id]) - }) -} - -resource "kubectl_manifest" "prj_middleware" { - yaml_body = <<-EOF - apiVersion: traefik.containo.us/v1alpha1 - kind: Middleware - metadata: - name: "forward-${local.app-name}" - namespace: "${var.namespace}" - labels: ${jsonencode(local.common-labels)} - spec: - forwardAuth: - address: http://ak-outpost-forward.${var.domain}-auth.svc:9000/outpost.goauthentik.io/auth/traefik - trustForwardHeader: true - authResponseHeaders: - - X-authentik-username - # - X-authentik-groups - # - X-authentik-email - # - X-authentik-name - # - X-authentik-uid - # - X-authentik-jwt - # - X-authentik-meta-jwks - # - X-authentik-meta-outpost - # - X-authentik-meta-provider - # - X-authentik-meta-app - # - X-authentik-meta-version - EOF -} diff --git a/apps/okd/index.yaml b/apps/okd/index.yaml index 2c58f2a..0220347 100644 --- a/apps/okd/index.yaml +++ b/apps/okd/index.yaml @@ -6,6 +6,16 @@ metadata: name: okd description: null options: + sub-domain: + default: okd + examples: + - okd + type: string + app-group: + default: infra + examples: + - infra + type: string images: default: okd: @@ -49,46 +59,36 @@ options: type: string type: object type: object - namespaces: - default: [] - items: - type: string - type: array - cluster-admin: - default: false - examples: - - false - type: boolean - sub-domain: - default: okd - examples: - - okd - type: string - domain: - default: your-company - examples: - - your-company - type: string - issuer: - default: letsencrypt-prod - examples: - - letsencrypt-prod - type: string - app-group: - default: infra - examples: - - infra - type: string domain-name: default: your_company.com examples: - your_company.com type: string + cluster-admin: + default: false + examples: + - false + type: boolean + namespaces: + default: [] + items: + type: string + type: array + issuer: + default: letsencrypt-prod + examples: + - letsencrypt-prod + type: string ingress-class: default: traefik examples: - traefik type: string + domain: + default: your-company + examples: + - your-company + type: string dependencies: - dist: null category: share diff --git a/apps/okd/ingress.tf b/apps/okd/ingress.tf deleted file mode 100644 index 19ecf4f..0000000 --- a/apps/okd/ingress.tf +++ /dev/null @@ -1,76 +0,0 @@ - -locals { - dns-names = ["${var.sub-domain}.${var.domain-name}"] - middlewares = ["${var.instance}-https", "forward-${local.app-name}"] - service = { - "name" = "${var.component}-${var.instance}" - "port" = { - "number" = 80 - } - } - rules = [ for v in local.dns-names : { - "host" = "${v}" - "http" = { - "paths" = [{ - "backend" = { - "service" = local.service - } - "path" = "/" - "pathType" = "Prefix" - }] - } - }] -} - -resource "kubectl_manifest" "prj_certificate" { - yaml_body = <<-EOF - apiVersion: "cert-manager.io/v1" - kind: "Certificate" - metadata: - name: "${var.instance}" - namespace: "${var.namespace}" - labels: ${jsonencode(local.common-labels)} - spec: - secretName: "${var.instance}-cert" - dnsNames: ${jsonencode(local.dns-names)} - issuerRef: - name: "${var.issuer}" - kind: "ClusterIssuer" - group: "cert-manager.io" - EOF -} - -resource "kubectl_manifest" "prj_https_redirect" { - yaml_body = <<-EOF - apiVersion: "traefik.containo.us/v1alpha1" - kind: "Middleware" - metadata: - name: "${var.instance}-https" - namespace: "${var.namespace}" - labels: ${jsonencode(local.common-labels)} - spec: - redirectScheme: - scheme: "https" - permanent: true - EOF -} - -resource "kubectl_manifest" "prj_ingress" { - force_conflicts = true - yaml_body = <<-EOF - apiVersion: "networking.k8s.io/v1" - kind: "Ingress" - metadata: - name: "${var.instance}" - namespace: "${var.namespace}" - labels: ${jsonencode(local.common-labels)} - annotations: - "traefik.ingress.kubernetes.io/router.middlewares": "${join(",", [for m in local.middlewares : format("%s-%s@kubernetescrd", var.namespace, m)])}" - spec: - ingressClassName: "${var.ingress-class}" - rules: ${jsonencode(local.rules)} - tls: - - hosts: ${jsonencode(local.dns-names)} - secretName: "${var.instance}-cert" - EOF -} diff --git a/apps/okd/presentation.tf b/apps/okd/presentation.tf new file mode 100644 index 0000000..b504fd7 --- /dev/null +++ b/apps/okd/presentation.tf @@ -0,0 +1,89 @@ +locals { + dns-name = "${var.sub-domain}.${var.domain-name}" + dns-names = [local.dns-name] + app-name = var.component == var.instance ? var.instance : format("%s-%s", var.component, var.instance) + icon = "static/assets/okd-logo.svg" + request_headers = { + "Content-Type" = "application/json" + Authorization = "Bearer ${data.kubernetes_secret_v1.authentik.data["AUTHENTIK_BOOTSTRAP_TOKEN"]}" + } + service = { + "name" = "${var.component}-${var.instance}" + "port" = { + "number" = 80 + } + } +} + +module "service" { + source = "/dist/modules/service" + component = var.component + instance = var.instance + namespace = var.namespace + labels = local.common-labels + target = "http" + port = local.service.port.number + providers = { + kubectl = kubectl + } +} + +module "ingress" { + source = "/dist/modules/ingress" + component = var.component + instance = var.instance + namespace = var.namespace + issuer = var.issuer + ingress-class = var.ingress-class + labels = local.common-labels + dns-names = local.dns-names + middlewares = ["${var.instance}-https", "forward-${local.app-name}"] + service = local.service + providers = { + kubectl = kubectl + } +} + +module "application" { + source = "/dist/modules/application" + component = var.component + instance = var.instance + app-group = var.app-group + sub-domain = var.sub-domain + domain-name = var.domain-name + icon = local.icon + protocol_provider = module.forward.provider-id + providers = { + authentik = authentik + } +} + +provider "restapi" { + uri = "http://authentik.${var.domain}-auth.svc/api/v3/" + headers = local.request_headers + create_method = "PATCH" + update_method = "PATCH" + destroy_method = "PATCH" + write_returns_object = true + id_attribute = "name" +} + +module "forward" { + source = "/dist/modules/forward" + component = var.component + instance = var.instance + domain = var.domain + namespace = var.namespace + ingress-class = var.ingress-class + labels = local.common-labels + dns-names = local.dns-names + service = local.service + icon = local.icon + request_headers = local.request_headers + providers = { + restapi = restapi + http = http + kubectl = kubectl + authentik = authentik + } +} diff --git a/apps/okd/rbac.tf b/apps/okd/rbac.tf index a486953..379cd1d 100644 --- a/apps/okd/rbac.tf +++ b/apps/okd/rbac.tf @@ -79,7 +79,10 @@ resource "kubectl_manifest" "okd_clusterrole" { - apiGroups: [""] resources: ["namespaces"] resourceNames: ${jsonencode(local.sorted-namespaces)} - verbs: ["get", "list"] + verbs: ["get"] + - apiGroups: [""] + resources: ["namespaces"] + verbs: ["list"] EOF } diff --git a/apps/okd/svc.tf b/apps/okd/svc.tf deleted file mode 100644 index c73fa48..0000000 --- a/apps/okd/svc.tf +++ /dev/null @@ -1,18 +0,0 @@ -resource "kubectl_manifest" "service" { - yaml_body = <<-EOF - apiVersion: v1 - kind: Service - metadata: - name: "${var.component}-${var.instance}" - namespace: "${var.namespace}" - labels: ${jsonencode(local.common-labels)} - spec: - type: ClusterIP - ports: - - name: http - port: 80 - protocol: TCP - targetPort: http - selector: ${jsonencode(local.common-labels)} - EOF -}