# auth-system namespace
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: auth-system-namespace
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: v1
      kind: Namespace
      metadata:
        name: auth-system
---
# Keycloak service account
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-service-account
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: keycloak
        namespace: auth-system
---
# Keycloak role
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-role
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: rbac.authorization.k8s.io/v1
      kind: Role
      metadata:
        name: keycloak
        namespace: auth-system
      rules:
      - apiGroups: [""]
        resources: ["secrets", "configmaps", "pods"]
        verbs: ["get", "list", "watch"]
---
# Keycloak role binding
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-role-binding
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: rbac.authorization.k8s.io/v1
      kind: RoleBinding
      metadata:
        name: keycloak
        namespace: auth-system
      subjects:
      - kind: ServiceAccount
        name: keycloak
        namespace: auth-system
      roleRef:
        kind: Role
        name: keycloak
        apiGroup: rbac.authorization.k8s.io
---
# Keycloak admin credentials
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-admin-secret
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: v1
      kind: Secret
      metadata:
        name: keycloak-admin-creds
        namespace: auth-system
      type: Opaque
      stringData:
        password: "thefi9paechooh"
---
# PostgreSQL credentials
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-postgresql-secret
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: v1
      kind: Secret
      metadata:
        name: keycloak-postgresql
        namespace: auth-system
      type: Opaque
      stringData:
        postgresql-password: "keycloak-db-password"
        POSTGRES_PASSWORD: "keycloak-db-password"
        POSTGRES_USER: "keycloak"
        POSTGRES_DB: "keycloak"
---
# PostgreSQL StatefulSet
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-postgresql-statefulset
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: keycloak-postgresql
        namespace: auth-system
      spec:
        serviceName: keycloak-postgresql
        replicas: 1
        selector:
          matchLabels:
            app: keycloak-postgresql
        template:
          metadata:
            labels:
              app: keycloak-postgresql
          spec:
            containers:
            - name: postgresql
              image: postgres:17-bookworm
              ports:
              - containerPort: 5432
                name: postgresql
              envFrom:
              - secretRef:
                  name: keycloak-postgresql
              resources:
                requests:
                  cpu: 250m
                  memory: 256Mi
                limits:
                  cpu: 500m
                  memory: 512Mi
              volumeMounts:
              - name: data
                mountPath: /var/lib/postgresql/data
                subPath: pgdata
              readinessProbe:
                exec:
                  command:
                  - pg_isready
                  - -U
                  - keycloak
                initialDelaySeconds: 5
                periodSeconds: 10
              livenessProbe:
                exec:
                  command:
                  - pg_isready
                  - -U
                  - keycloak
                initialDelaySeconds: 30
                periodSeconds: 30
        volumeClaimTemplates:
        - metadata:
            name: data
          spec:
            accessModes:
            - ReadWriteOnce
            storageClassName: civo-volume
            resources:
              requests:
                storage: 5Gi
---
# PostgreSQL Service
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-postgresql-service
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: v1
      kind: Service
      metadata:
        name: keycloak-postgresql
        namespace: auth-system
      spec:
        selector:
          app: keycloak-postgresql
        ports:
        - name: postgresql
          port: 5432
          targetPort: 5432
        type: ClusterIP
---
# Keycloak Deployment
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-deployment
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: keycloak
        namespace: auth-system
        labels:
          app: keycloak
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: keycloak
        template:
          metadata:
            labels:
              app: keycloak
          spec:
            serviceAccountName: keycloak
            containers:
            - name: keycloak
              image: quay.io/keycloak/keycloak:24.0.4
              args:
              - start
              - --db=postgres
              - --hostname=auth.nge6.com
              - --hostname-strict=false
              - --hostname-strict-https=false
              - --proxy=edge
              - --http-enabled=true
              ports:
              - containerPort: 8080
                name: http
              env:
              - name: KEYCLOAK_ADMIN
                value: admin
              - name: KEYCLOAK_ADMIN_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: keycloak-admin-creds
                    key: password
              - name: KC_DB
                value: postgres
              - name: KC_DB_URL
                value: jdbc:postgresql://keycloak-postgresql:5432/keycloak
              - name: KC_DB_USERNAME
                value: keycloak
              - name: KC_DB_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: keycloak-postgresql
                    key: postgresql-password
              resources:
                requests:
                  cpu: 500m
                  memory: 512Mi
                limits:
                  cpu: "1"
                  memory: 1Gi
              readinessProbe:
                httpGet:
                  path: /realms/master
                  port: 8080
                initialDelaySeconds: 90
                timeoutSeconds: 3
                periodSeconds: 10
                failureThreshold: 10
              livenessProbe:
                httpGet:
                  path: /realms/master
                  port: 8080
                initialDelaySeconds: 120
                timeoutSeconds: 5
                periodSeconds: 30
                failureThreshold: 10
              startupProbe:
                httpGet:
                  path: /realms/master
                  port: 8080
                initialDelaySeconds: 60
                timeoutSeconds: 3
                periodSeconds: 5
                failureThreshold: 30
---
# Keycloak Service
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-service
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: v1
      kind: Service
      metadata:
        name: keycloak-http
        namespace: auth-system
      spec:
        selector:
          app: keycloak
        ports:
        - name: http
          port: 80
          targetPort: 8080
        type: ClusterIP
---
# Keycloak SSL Certificate
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-certificate
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: cert-manager.io/v1
      kind: Certificate
      metadata:
        name: keycloak-tls
        namespace: emissary
      spec:
        secretName: keycloak-tls
        issuerRef:
          name: letsencrypt-dns
          kind: ClusterIssuer
        dnsNames:
          - auth.nge6.com
---
# Keycloak Ambassador Host
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-host
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: getambassador.io/v3alpha1
      kind: Host
      metadata:
        name: keycloak-host
        namespace: emissary
        annotations:
          external-dns.ambassador-service: emissary-ingress.emissary.svc.cluster.local
          external-dns.alpha.kubernetes.io/target: 212.2.241.28
      spec:
        hostname: auth.nge6.com
        tlsSecret:
          name: keycloak-tls
---
# Keycloak Ambassador Mapping
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
  name: keycloak-mapping
  namespace: crossplane-system
spec:
  providerConfigRef:
    name: kubernetes-provider
  forProvider:
    manifest:
      apiVersion: getambassador.io/v3alpha1
      kind: Mapping
      metadata:
        name: keycloak-mapping
        namespace: emissary
      spec:
        hostname: auth.nge6.com
        prefix: /
        service: keycloak-http.auth-system:80
        timeout_ms: 30000
        connect_timeout_ms: 10000
