From 647a5577f11b5eb61bb32ad24562233e94829c90 Mon Sep 17 00:00:00 2001 From: klinch0 <68821526+klinch0@users.noreply.github.com> Date: Thu, 21 Nov 2024 03:18:19 +0300 Subject: [PATCH] add keycloak (#475) ## Summary by CodeRabbit ## Release Notes - **New Features** - Integrated Keycloak service into deployment configurations across multiple files, enhancing user authentication capabilities. - Introduced a new Helm chart for Keycloak, facilitating easier deployment and management. - Added Kubernetes Ingress and Service resources for Keycloak to manage external access and internal service routing. - Configured a PostgreSQL cluster specifically for Keycloak, ensuring data persistence. - **Bug Fixes** - Updated versioning in the installer script to ensure compatibility with the latest configurations. - **Documentation** - Added detailed configuration options for Keycloak deployment, including resource limits and ingress settings. --- .../core/platform/bundles/distro-full.yaml | 6 + .../core/platform/bundles/distro-hosted.yaml | 6 + packages/core/platform/bundles/paas-full.yaml | 6 + .../core/platform/bundles/paas-hosted.yaml | 8 +- packages/system/keycloak/Chart.yaml | 3 + packages/system/keycloak/templates/db.yaml | 12 ++ .../system/keycloak/templates/ingress.yaml | 36 +++++ .../keycloak/templates/service-headless.yaml | 9 ++ .../system/keycloak/templates/service.yaml | 12 ++ packages/system/keycloak/templates/sts.yaml | 135 ++++++++++++++++++ packages/system/keycloak/values.yaml | 14 ++ scripts/installer.sh | 2 +- scripts/migrations/7 | 9 ++ 13 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 packages/system/keycloak/Chart.yaml create mode 100644 packages/system/keycloak/templates/db.yaml create mode 100644 packages/system/keycloak/templates/ingress.yaml create mode 100644 packages/system/keycloak/templates/service-headless.yaml create mode 100644 packages/system/keycloak/templates/service.yaml create mode 100644 packages/system/keycloak/templates/sts.yaml create mode 100644 packages/system/keycloak/values.yaml create mode 100644 scripts/migrations/7 diff --git a/packages/core/platform/bundles/distro-full.yaml b/packages/core/platform/bundles/distro-full.yaml index ed329ade..6940951d 100644 --- a/packages/core/platform/bundles/distro-full.yaml +++ b/packages/core/platform/bundles/distro-full.yaml @@ -174,3 +174,9 @@ releases: namespace: cozy-external-secrets-operator optional: true dependsOn: [cilium] + +- name: keycloak + releaseName: keycloak + chart: cozy-keycloak + namespace: cozy-keycloak + dependsOn: [postgres-operator] diff --git a/packages/core/platform/bundles/distro-hosted.yaml b/packages/core/platform/bundles/distro-hosted.yaml index c88cf080..6ac84167 100644 --- a/packages/core/platform/bundles/distro-hosted.yaml +++ b/packages/core/platform/bundles/distro-hosted.yaml @@ -124,3 +124,9 @@ releases: namespace: cozy-external-secrets-operator optional: true dependsOn: [] + +- name: keycloak + releaseName: keycloak + chart: cozy-keycloak + namespace: cozy-keycloak + dependsOn: [postgres-operator] diff --git a/packages/core/platform/bundles/paas-full.yaml b/packages/core/platform/bundles/paas-full.yaml index 4a48a516..6b571344 100644 --- a/packages/core/platform/bundles/paas-full.yaml +++ b/packages/core/platform/bundles/paas-full.yaml @@ -249,3 +249,9 @@ releases: namespace: cozy-external-secrets-operator optional: true dependsOn: [cilium,kubeovn] + +- name: keycloak + releaseName: keycloak + chart: cozy-keycloak + namespace: cozy-keycloak + dependsOn: [postgres-operator] diff --git a/packages/core/platform/bundles/paas-hosted.yaml b/packages/core/platform/bundles/paas-hosted.yaml index 8aad507e..5dc8f247 100644 --- a/packages/core/platform/bundles/paas-hosted.yaml +++ b/packages/core/platform/bundles/paas-hosted.yaml @@ -19,7 +19,7 @@ releases: chart: cozy-cert-manager-crds namespace: cozy-cert-manager dependsOn: [] - + - name: cozystack-api releaseName: cozystack-api chart: cozy-cozystack-api @@ -145,3 +145,9 @@ releases: {{- end }} {{- end }} {{- end }} + +- name: keycloak + releaseName: keycloak + chart: cozy-keycloak + namespace: cozy-keycloak + dependsOn: [postgres-operator] diff --git a/packages/system/keycloak/Chart.yaml b/packages/system/keycloak/Chart.yaml new file mode 100644 index 00000000..72748d48 --- /dev/null +++ b/packages/system/keycloak/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-keycloak +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/keycloak/templates/db.yaml b/packages/system/keycloak/templates/db.yaml new file mode 100644 index 00000000..0ad0e34b --- /dev/null +++ b/packages/system/keycloak/templates/db.yaml @@ -0,0 +1,12 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: keycloak-db +spec: + instances: 2 + storage: + size: 20Gi + + inheritedMetadata: + labels: + policy.cozystack.io/allow-to-apiserver: "true" diff --git a/packages/system/keycloak/templates/ingress.yaml b/packages/system/keycloak/templates/ingress.yaml new file mode 100644 index 00000000..7618a9f5 --- /dev/null +++ b/packages/system/keycloak/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $host := index $cozyConfig.data "root-host" }} +{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} + +{{- $rootns := lookup "v1" "Namespace" "" "tenant-root" }} +{{- $ingress := index $rootns.metadata.annotations "namespace.cozystack.io/ingress" }} + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: keycloak-ingress + {{- with .Values.ingress.annotations }} + annotations: + {{- if ne $issuerType "cloudflare" }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} + {{- end }} + cert-manager.io/cluster-issuer: letsencrypt-prod + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ $ingress }} + tls: + - hosts: + - keycloak.{{ $host }} + secretName: web-tls + rules: + - host: keycloak.{{ $host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: keycloak-http + port: + name: http diff --git a/packages/system/keycloak/templates/service-headless.yaml b/packages/system/keycloak/templates/service-headless.yaml new file mode 100644 index 00000000..e5cfca28 --- /dev/null +++ b/packages/system/keycloak/templates/service-headless.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Service +metadata: + name: keycloak-headless +spec: + type: ClusterIP + clusterIP: None + selector: + app: keycloak-ha diff --git a/packages/system/keycloak/templates/service.yaml b/packages/system/keycloak/templates/service.yaml new file mode 100644 index 00000000..6d095618 --- /dev/null +++ b/packages/system/keycloak/templates/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: keycloak-http +spec: + type: ClusterIP + ports: + - name: http + port: 8080 + protocol: TCP + selector: + app: keycloak-ha diff --git a/packages/system/keycloak/templates/sts.yaml b/packages/system/keycloak/templates/sts.yaml new file mode 100644 index 00000000..b28a7efa --- /dev/null +++ b/packages/system/keycloak/templates/sts.yaml @@ -0,0 +1,135 @@ +{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $host := index $cozyConfig.data "root-host" }} +{{- $password := randAlphaNum 16 -}} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-credentials +stringData: + admin: {{ $password }} + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: keycloak + labels: + app: keycloak-ha +spec: + selector: + matchLabels: + app: keycloak-ha + replicas: 2 + serviceName: keycloak-headless + podManagementPolicy: Parallel + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + app: keycloak-ha + spec: + restartPolicy: Always + securityContext: + fsGroup: 1000 + containers: + - name: keycloak + image: {{ .Values.image }} + imagePullPolicy: Always + {{- if or .Values.resources.requests .Values.resources.limits }} + resources: + {{- if .Values.resources.limits }} + limits: + {{- toYaml .Values.resources.limits | nindent 14 }} + {{- end }} + {{- if .Values.resources.requests }} + requests: + {{- toYaml .Values.resources.requests | nindent 14 }} + {{- end }} + {{- end }} + securityContext: + runAsNonRoot: true + runAsUser: 1000 + capabilities: + drop: + - ALL + - CAP_NET_RAW + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + args: + - start + env: + - name: KC_METRICS_ENABLED + value: "true" + - name: KC_LOG_LEVEL + value: "info" + - name: KC_CACHE + value: "ispn" + - name: KC_CACHE_STACK + value: "kubernetes" + - name: KC_PROXY + value: "edge" + - name: KEYCLOAK_ADMIN + value: admin + - name: KEYCLOAK_ADMIN_PASSWORD + value: {{ $password }} + - name: KC_DB + value: "postgres" + - name: KC_DB_URL_HOST + valueFrom: + secretKeyRef: + name: keycloak-db-app + key: "host" + - name: KC_DB_URL_PORT + valueFrom: + secretKeyRef: + name: keycloak-db-app + key: "port" + - name: KC_DB_USERNAME + valueFrom: + secretKeyRef: + name: keycloak-db-app + key: "username" + - name: KC_DB_PASSWORD + valueFrom: + secretKeyRef: + name: keycloak-db-app + key: "password" + - name: KC_DB_URL_DATABASE + valueFrom: + secretKeyRef: + name: keycloak-db-app + key: "dbname" + - name: KC_FEATURES + value: "docker" + - name: KC_HOSTNAME + value: https://keycloak.{{ $host }} + - name: JAVA_OPTS_APPEND + value: "-Djgroups.dns.query=keycloak-headless.cozy-keycloak.svc.cozy.local" + ports: + - name: http + containerPort: 8080 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 120 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /realms/master + port: http + initialDelaySeconds: 60 + timeoutSeconds: 1 + volumes: + - name: init-script + configMap: + name: keycloak-init-script + volumeMounts: + - name: init-script + mountPath: /scripts + readOnly: true + terminationGracePeriodSeconds: 60 diff --git a/packages/system/keycloak/values.yaml b/packages/system/keycloak/values.yaml new file mode 100644 index 00000000..6972a39e --- /dev/null +++ b/packages/system/keycloak/values.yaml @@ -0,0 +1,14 @@ +image: quay.io/keycloak/keycloak:26.0.4 + +ingress: + annotations: + nginx.ingress.kubernetes.io/affinity: "cookie" + nginx.ingress.kubernetes.io/session-cookie-expires: "86400" + nginx.ingress.kubernetes.io/session-cookie-max-age: "86400" + nginx.ingress.kubernetes.io/session-cookie-name: "keycloak-cookie" +resources: + limits: + memory: 1500Mi + requests: + memory: 500Mi + cpu: 100m diff --git a/scripts/installer.sh b/scripts/installer.sh index 9a4d42e1..d3dce668 100755 --- a/scripts/installer.sh +++ b/scripts/installer.sh @@ -3,7 +3,7 @@ set -o pipefail set -e BUNDLE=$(set -x; kubectl get configmap -n cozy-system cozystack -o 'go-template={{index .data "bundle-name"}}') -VERSION=7 +VERSION=8 run_migrations() { if ! kubectl get configmap -n cozy-system cozystack-version; then diff --git a/scripts/migrations/7 b/scripts/migrations/7 new file mode 100644 index 00000000..2d73fe75 --- /dev/null +++ b/scripts/migrations/7 @@ -0,0 +1,9 @@ +#!/bin/sh +# Migration 7 --> 8 + + +host=$(kubectl get hr tenant-root -n tenant-root -o yaml | grep 'host:' | awk '{print $2}') +kubectl patch configmap -n cozy-system cozystack --type merge -p "{\"data\":{\"root-host\":\"$host\"}}" + +# Write version to cozystack-version config +kubectl create configmap -n cozy-system cozystack-version --from-literal=version=8 --dry-run=client -o yaml | kubectl apply -f-