diff --git a/apps/artifacts.yaml b/apps/artifacts.yaml index 6455b23..624d8c9 100644 --- a/apps/artifacts.yaml +++ b/apps/artifacts.yaml @@ -14,3 +14,8 @@ spec: copy: - from: "@foundation/apps/spegel/**" to: "@artifact/" + - name: lldap + originRevision: "@foundation" + copy: + - from: "@foundation/apps/lldap/**" + to: "@artifact/" diff --git a/apps/lldap/base/cluster.yaml b/apps/lldap/base/cluster.yaml new file mode 100644 index 0000000..79c84d1 --- /dev/null +++ b/apps/lldap/base/cluster.yaml @@ -0,0 +1,10 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: db + namespace: lldap + # TODO: Add labels? +spec: + storage: + size: 8Gi + storageClass: local-path diff --git a/apps/lldap/base/deployment.yaml b/apps/lldap/base/deployment.yaml new file mode 100644 index 0000000..cb614e2 --- /dev/null +++ b/apps/lldap/base/deployment.yaml @@ -0,0 +1,80 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lldap + namespace: lldap + labels: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap +spec: + selector: + matchLabels: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap + template: + metadata: + labels: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap + spec: + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: lldap + image: lldap/lldap:2025-12-12-alpine-rootless + env: + - name: LLDAP_LDAP_BASE_DN + value: dc=huizinga,dc=dev + - name: LLDAP_LDAP_USER_PASS + valueFrom: + secretKeyRef: + name: credentials + key: admin-pass + - name: LLDAP_KEY_SEED + valueFrom: + secretKeyRef: + name: credentials + key: key-seed + - name: LLDAP_JWT_SECRET + valueFrom: + secretKeyRef: + name: credentials + key: jwt-secret + - name: LLDAP_DATABASE_URL + valueFrom: + secretKeyRef: + name: db-app + key: uri + - name: TZ + value: CET + livenessProbe: + exec: + command: + - /app/lldap + - healthcheck + initialDelaySeconds: 5 + periodSeconds: 30 + ports: + - name: ldap + containerPort: 3890 + - name: web + containerPort: 17170 + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + capabilities: + drop: + - ALL diff --git a/apps/lldap/base/http-route.yaml b/apps/lldap/base/http-route.yaml new file mode 100644 index 0000000..b4eda7b --- /dev/null +++ b/apps/lldap/base/http-route.yaml @@ -0,0 +1,13 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: lldap + namespace: lldap +spec: + parentRefs: + - name: gateway + namespace: default + rules: + - backendRefs: + - name: lldap + port: 17170 diff --git a/apps/lldap/base/kustomization.yaml b/apps/lldap/base/kustomization.yaml new file mode 100644 index 0000000..07ab273 --- /dev/null +++ b/apps/lldap/base/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - cluster.yaml + - deployment.yaml + - service.yaml + - http-route.yaml diff --git a/apps/lldap/base/namespace.yaml b/apps/lldap/base/namespace.yaml new file mode 100644 index 0000000..f208267 --- /dev/null +++ b/apps/lldap/base/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: lldap diff --git a/apps/lldap/base/service.yaml b/apps/lldap/base/service.yaml new file mode 100644 index 0000000..c2e232a --- /dev/null +++ b/apps/lldap/base/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: lldap + namespace: lldap + labels: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap +spec: + selector: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap + ports: + - name: ldap + port: 3890 + targetPort: ldap + - name: web + port: 17170 + targetPort: web diff --git a/apps/lldap/lldap.yaml b/apps/lldap/lldap.yaml new file mode 100644 index 0000000..6c225f2 --- /dev/null +++ b/apps/lldap/lldap.yaml @@ -0,0 +1,21 @@ +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: lldap + namespace: flux-system +spec: + interval: 1h + retryInterval: 2m + timeout: 5m + dependsOn: + - name: cnpg + sourceRef: + kind: ExternalArtifact + name: lldap + decryption: + provider: sops + secretRef: + name: sops-gpg + path: ./${cluster_env} + prune: true + wait: true diff --git a/apps/lldap/production/cluster.yaml b/apps/lldap/production/cluster.yaml new file mode 100644 index 0000000..b6a433c --- /dev/null +++ b/apps/lldap/production/cluster.yaml @@ -0,0 +1,6 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: postgres +spec: + instances: 2 diff --git a/apps/lldap/production/deployment.yaml b/apps/lldap/production/deployment.yaml new file mode 100644 index 0000000..25aa0bb --- /dev/null +++ b/apps/lldap/production/deployment.yaml @@ -0,0 +1,7 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lldap + namespace: lldap +spec: + replicas: 2 diff --git a/apps/lldap/production/http-route.yaml b/apps/lldap/production/http-route.yaml new file mode 100644 index 0000000..0d79ee2 --- /dev/null +++ b/apps/lldap/production/http-route.yaml @@ -0,0 +1,8 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: lldap + namespace: lldap +spec: + hostnames: + - "users.huizinga.dev" diff --git a/apps/lldap/production/kustomization.yaml b/apps/lldap/production/kustomization.yaml new file mode 100644 index 0000000..aeafa6a --- /dev/null +++ b/apps/lldap/production/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../base + - secret-credentials.enc.yaml +patches: + - path: deployment.yaml + target: + kind: Deployment + - path: cluster.yaml + target: + kind: Cluster + - path: http-route.yaml + target: + kind: HTTPRoute diff --git a/apps/lldap/production/secret-credentials.enc.yaml b/apps/lldap/production/secret-credentials.enc.yaml new file mode 100644 index 0000000..01182df --- /dev/null +++ b/apps/lldap/production/secret-credentials.enc.yaml @@ -0,0 +1,59 @@ +apiVersion: v1 +kind: Secret +metadata: + name: credentials + namespace: lldap + labels: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap +type: Opaque +data: + jwt-secret: ENC[AES256_GCM,data:yUAsoCIEXH491Ko4wEAAevSETdMFuhypNzuU2th5zlLd9hbVKqsjclvCTLDD8aW0Y9Lv70pzzAADPwFCKNH/rXx0DzaGOP139kLRYDHafz3RYeuoJjgBGw==,iv:x3EmPbbL/aj9CbwF8lleDL+nhlidPU8R3hwXygtj7D8=,tag:XD4C/pwFLFmDryBW7NqsWg==,type:str] + key-seed: ENC[AES256_GCM,data:3jWLtfny+ahtSkkmUdbg+wFbSGIcCxOv9BxVr0oNLTetXrAx+OcZ6dKp1ktj0J9aYEppqVuANUlfqyVzhIQXOT5GomQ+9jPC4uLmIz9tu1LAcfv9zuGl/w==,iv:e3aAI6JWq16YaUZqvKulkHyhLb8eWy9t2ni/jGeNFow=,tag:sZEEvxlq145klFkEMsUOuA==,type:str] + #ENC[AES256_GCM,data:AnCuvbVM6M62wuWmpUx3u/5WdaCo1T7eCvbY30okKbmWnvM0HQT2gGDTuhIaOlc=,iv:Ho+/CAvs69VJ+uwAIH8LVL344qlDaK5z3AvzWh/Jgm0=,tag:uNfN1P7lmWKBuCY7eiywDw==,type:comment] + admin-pass: ENC[AES256_GCM,data:yWzQTjN8kuGroShan7NxAw==,iv:IHw237PAqNNZ7KXIy2D8XMCLWSi3kJpLEnILhGm/Xl4=,tag:N79GjKNZNh9qJO+dpa0InQ==,type:str] +sops: + age: + - recipient: age1860txadrlqrjwnqh0g466re2nt8jk7xhj640pq9gpsddpg23uynqsp2hul + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCdVFuM2xvazBXY3kwTXVD + ZXdOS0pJLzVTVGJBb3RqYlhUN2IvNDNRSzNzCm8zcmlIU2h3RityUWFkZXU1R2xp + VUlobGZuOG1wbGxIMXVVekRaYTNGQUkKLS0tIHlMWkI0Qk9nUys1Sm4yNnVsakho + ZXl2RDhNNFZORW5lOGphSVY5WVJycWMKvnGem7wolSKMa8lshD90bMohdLMgYiTq + gHRN22irgd4pA2CpTcY47T2zhtVHU36PCXn+QFN936uF0vLf8Srwow== + -----END AGE ENCRYPTED FILE----- + - recipient: age1hktythzvsnth6u5en2lvag0tftnj9r03w7rpnzfgzgf5w95qxycq2azufj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkRHNUOXZFUGxEY0RRSGtz + OElnckFUVG1WOXhvZHhzczUxU3lZZlE5emo4Ck5qRnF6M1NCeGdkUVNuR0xzMWxs + SEdVL0lwOXJmWVdEZ0t3V2Jscy9lZG8KLS0tIGM0WC8vbEdHQ2puRVZIK3lXeUJJ + OVNqZnhRUEN5dTBBVXVlSDlidEU4K3cKhv2jSc+lJu+s3hbH6j1xrkaQSzds82rk + dlaisVQxQmxjKcyPHqudJZS6Qfq3kEn9cZOP4G8NYAh0zhzGvCKeqA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-12-17T02:58:02Z" + mac: ENC[AES256_GCM,data:yxmBIqS+KMr2Dp4eKslT1oNCcq2VEnGh4g3e7mkZzWjT6xPTdBEH8bT+c2XIFMWHJSUFoI7YyhvS1p5VgRBudaDyQCOk7tzyj0nkGiepZc1uYjSVO7VQ9CnfcdiD9AZ2srUjkcUoBaRfi2u6Qh2pPUUwMd4z8ms8v0CSk1qw0FE=,iv:V2rw624TN+pSGuq+JjVqM2bKozn7hGAykHV+638wo14=,tag:cdDascdYzzG33GztMd0Fdg==,type:str] + pgp: + - created_at: "2025-12-17T00:53:29Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA51kG++kLewoAQ/7BepX/31nKyUHnKC/7VnqTJk0x/gLmhko1/NukkApraXe + ctmZVk4TlG9N+DqEPHUYeMt7pu/1rvnWckh/OR2JU7AK8E33tnWITvr4AzQjk0zH + /V8n36ZA5/8Ppt9LJJSMVLaFEFjqiFy39Ggt6bx0SUX/CczTGkUYp+aJQfmDn+uR + GcJk9wR9/bu7+iOq8kuOA+renxGmdIcfMd6GKiHYScgv5tDN7pg7upXh1NPrVB8u + 3GTor40B1Ncjqv3L1Zbw1AZYdsmFRkSx1N2JJkxPZYbvI6cwuFMcFkXuX6JfuL8T + pW5ddsK/DF0qXAXSc378juOh/tRdktFz2QPv9X5CJnQUk0c19Beqb4tG4cVR9sF3 + SXTpaNmR4GG3ilY3ispzso7CQe+7RvLWGgsZAgPD1uC9SJGOBfvReJvQZUXyxUGo + /riTbUgFaBHmY6XWGy7Ecni333GtfGeN8qSIgPRhHg5f/BJX9Rp5ZG373S7iLuI4 + GpM12knQCjxfsMXjMs6/TtAwYhnIFG3WcCzJFzn+pqBiW7XJvegJPQAID5LDo4GG + EzCZylto1WCgRhdq+CNuybQTsj4TbvxzfPYf+gCURbisH8A3TTWp4eyyXHg5KS4z + 0TECkXpUXR/sD71HuBjxz1jfZiXFruDBldZDzZ2tZDdqQxAtk/DJGXcLmWF+HMbS + XgEvCI5gci7pYlsi60yitBcTPV2eEBh4zbRV53e12RGuhPwkxenX+6YRSCi0liOk + 5BizeCkfSRCLQHG1okeb1RIdnSoyOJ+KlrR4Y+1xeZp9ruWn/tPN7L3jCx8SX+Y= + =j+fd + -----END PGP MESSAGE----- + fp: CD17A34CBFB21DE9A73D47EB76BDEC4E165D8AD9 + encrypted_regex: ^(data|stringData)$ + version: 3.11.0 diff --git a/apps/lldap/staging/cluster.yaml b/apps/lldap/staging/cluster.yaml new file mode 100644 index 0000000..26751dc --- /dev/null +++ b/apps/lldap/staging/cluster.yaml @@ -0,0 +1,6 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: postgres +spec: + instances: 1 diff --git a/apps/lldap/staging/deployment.yaml b/apps/lldap/staging/deployment.yaml new file mode 100644 index 0000000..3d12195 --- /dev/null +++ b/apps/lldap/staging/deployment.yaml @@ -0,0 +1,7 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lldap + namespace: lldap +spec: + replicas: 1 diff --git a/apps/lldap/staging/http-route.yaml b/apps/lldap/staging/http-route.yaml new file mode 100644 index 0000000..b468e4f --- /dev/null +++ b/apps/lldap/staging/http-route.yaml @@ -0,0 +1,8 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: lldap + namespace: lldap +spec: + hostnames: + - "users.staging.huizinga.dev" diff --git a/apps/lldap/staging/kustomization.yaml b/apps/lldap/staging/kustomization.yaml new file mode 100644 index 0000000..aeafa6a --- /dev/null +++ b/apps/lldap/staging/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../base + - secret-credentials.enc.yaml +patches: + - path: deployment.yaml + target: + kind: Deployment + - path: cluster.yaml + target: + kind: Cluster + - path: http-route.yaml + target: + kind: HTTPRoute diff --git a/apps/lldap/staging/secret-credentials.enc.yaml b/apps/lldap/staging/secret-credentials.enc.yaml new file mode 100644 index 0000000..7aafcb7 --- /dev/null +++ b/apps/lldap/staging/secret-credentials.enc.yaml @@ -0,0 +1,58 @@ +apiVersion: v1 +kind: Secret +metadata: + name: credentials + namespace: lldap + labels: + app.kubernetes.io/name: lldap + app.kubernetes.io/instance: lldap +type: Opaque +data: + jwt-secret: ENC[AES256_GCM,data:cwKfSMzPPECNAba++x5ampK0pgCvOKRIEdPfLH5deDpnEASSlBjQZVo238YepBIAYu7Y0HCXCPppOtpX8zymD7Jxu1f5TrJoOJMwAlHYWT+IeBRVtpzgYA==,iv:bkNDqEriEnuSzvXxXAypGfwynPjYCVwN0NoAmcDftUc=,tag:DFkoIf92W8Ed60+azsfU+A==,type:str] + key-seed: ENC[AES256_GCM,data:bLpK9Tk5Eh2WBI5x94MssCyYEsMUMTJJymbdwsVeA6K/qBCxkPGkXf+kZZoaXkyLqW2lrPa8jIGv3LV6C4PqVJ+UOlgnvagQnCGnLylqX+3wkVhKLP5uYg==,iv:1RPLzof2Fwqm08Tfq7HR2esvPvkfBg0Uc+aM2SzpHhE=,tag:IsgLxUQriU9JUX2gEe/j8A==,type:str] + admin-pass: ENC[AES256_GCM,data:yWzQTjN8kuGroShan7NxAw==,iv:IHw237PAqNNZ7KXIy2D8XMCLWSi3kJpLEnILhGm/Xl4=,tag:N79GjKNZNh9qJO+dpa0InQ==,type:str] +sops: + age: + - recipient: age1860txadrlqrjwnqh0g466re2nt8jk7xhj640pq9gpsddpg23uynqsp2hul + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCdVFuM2xvazBXY3kwTXVD + ZXdOS0pJLzVTVGJBb3RqYlhUN2IvNDNRSzNzCm8zcmlIU2h3RityUWFkZXU1R2xp + VUlobGZuOG1wbGxIMXVVekRaYTNGQUkKLS0tIHlMWkI0Qk9nUys1Sm4yNnVsakho + ZXl2RDhNNFZORW5lOGphSVY5WVJycWMKvnGem7wolSKMa8lshD90bMohdLMgYiTq + gHRN22irgd4pA2CpTcY47T2zhtVHU36PCXn+QFN936uF0vLf8Srwow== + -----END AGE ENCRYPTED FILE----- + - recipient: age1hktythzvsnth6u5en2lvag0tftnj9r03w7rpnzfgzgf5w95qxycq2azufj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkRHNUOXZFUGxEY0RRSGtz + OElnckFUVG1WOXhvZHhzczUxU3lZZlE5emo4Ck5qRnF6M1NCeGdkUVNuR0xzMWxs + SEdVL0lwOXJmWVdEZ0t3V2Jscy9lZG8KLS0tIGM0WC8vbEdHQ2puRVZIK3lXeUJJ + OVNqZnhRUEN5dTBBVXVlSDlidEU4K3cKhv2jSc+lJu+s3hbH6j1xrkaQSzds82rk + dlaisVQxQmxjKcyPHqudJZS6Qfq3kEn9cZOP4G8NYAh0zhzGvCKeqA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-12-17T00:53:29Z" + mac: ENC[AES256_GCM,data:6/I2J7u9fGUdz2SbAF7dL2j5XQMICx+AgEaUQ3HUN/RvlhMzn9J3EdcLFQ+d9YwbSpCzuGTQBfqsky2oaD6fQWWefCOXAVdElCp2rxHAGK9u2pqhPbgcvbHKAWfvK2kml8qhjjam346xpj2yeP8UdWq6+KZq8B5OBsKYtx4KuKM=,iv:EeLpcggrglMvpUdjvH6rOyNRj2EkuToIwc+uEPUnlvI=,tag:juTwo5RbhGnddB3MF3WirQ==,type:str] + pgp: + - created_at: "2025-12-17T00:53:29Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA51kG++kLewoAQ/7BepX/31nKyUHnKC/7VnqTJk0x/gLmhko1/NukkApraXe + ctmZVk4TlG9N+DqEPHUYeMt7pu/1rvnWckh/OR2JU7AK8E33tnWITvr4AzQjk0zH + /V8n36ZA5/8Ppt9LJJSMVLaFEFjqiFy39Ggt6bx0SUX/CczTGkUYp+aJQfmDn+uR + GcJk9wR9/bu7+iOq8kuOA+renxGmdIcfMd6GKiHYScgv5tDN7pg7upXh1NPrVB8u + 3GTor40B1Ncjqv3L1Zbw1AZYdsmFRkSx1N2JJkxPZYbvI6cwuFMcFkXuX6JfuL8T + pW5ddsK/DF0qXAXSc378juOh/tRdktFz2QPv9X5CJnQUk0c19Beqb4tG4cVR9sF3 + SXTpaNmR4GG3ilY3ispzso7CQe+7RvLWGgsZAgPD1uC9SJGOBfvReJvQZUXyxUGo + /riTbUgFaBHmY6XWGy7Ecni333GtfGeN8qSIgPRhHg5f/BJX9Rp5ZG373S7iLuI4 + GpM12knQCjxfsMXjMs6/TtAwYhnIFG3WcCzJFzn+pqBiW7XJvegJPQAID5LDo4GG + EzCZylto1WCgRhdq+CNuybQTsj4TbvxzfPYf+gCURbisH8A3TTWp4eyyXHg5KS4z + 0TECkXpUXR/sD71HuBjxz1jfZiXFruDBldZDzZ2tZDdqQxAtk/DJGXcLmWF+HMbS + XgEvCI5gci7pYlsi60yitBcTPV2eEBh4zbRV53e12RGuhPwkxenX+6YRSCi0liOk + 5BizeCkfSRCLQHG1okeb1RIdnSoyOJ+KlrR4Y+1xeZp9ruWn/tPN7L3jCx8SX+Y= + =j+fd + -----END PGP MESSAGE----- + fp: CD17A34CBFB21DE9A73D47EB76BDEC4E165D8AD9 + encrypted_regex: ^(data|stringData)$ + version: 3.11.0 diff --git a/clusters/testing/kustomization.yaml b/clusters/testing/kustomization.yaml index 7ebdaf7..f6983ec 100644 --- a/clusters/testing/kustomization.yaml +++ b/clusters/testing/kustomization.yaml @@ -18,3 +18,4 @@ resources: - ../../apps/artifacts.yaml - ../../apps/spegel/spegel.yaml + - ../../apps/lldap/lldap.yaml