diff --git a/services/bstein-dev-home/backend-deployment.yaml b/services/bstein-dev-home/backend-deployment.yaml index 2e92443..08f73f7 100644 --- a/services/bstein-dev-home/backend-deployment.yaml +++ b/services/bstein-dev-home/backend-deployment.yaml @@ -26,15 +26,11 @@ spec: - name: backend image: registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-92 # {"$imagepolicy": "bstein-dev-home:bstein-dev-home-backend"} imagePullPolicy: Always - command: ["gunicorn"] + command: ["/bin/sh", "-c"] args: - - -b - - 0.0.0.0:8080 - - --workers - - "2" - - --timeout - - "180" - - app:app + - >- + . /vault/scripts/bstein_dev_home_vault_env.sh + && exec gunicorn -b 0.0.0.0:8080 --workers 2 --timeout 180 app:app env: - name: AI_CHAT_API value: http://ollama.ai.svc.cluster.local:11434 @@ -67,18 +63,8 @@ spec: value: atlas - name: KEYCLOAK_ADMIN_CLIENT_ID value: bstein-dev-home-admin - - name: KEYCLOAK_ADMIN_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: bstein-dev-home-keycloak-admin - key: client_secret - name: ACCOUNT_ALLOWED_GROUPS value: "" - - name: PORTAL_DATABASE_URL - valueFrom: - secretKeyRef: - name: atlas-portal-db - key: PORTAL_DATABASE_URL - name: HTTP_CHECK_TIMEOUT_SEC value: "2" - name: ACCESS_REQUEST_SUBMIT_RATE_LIMIT @@ -108,6 +94,13 @@ spec: initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 + volumeMounts: + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true resources: requests: cpu: 100m @@ -115,3 +108,14 @@ spec: limits: cpu: 500m memory: 512Mi + volumes: + - name: vault-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: bstein-dev-home-vault + - name: vault-scripts + configMap: + name: bstein-dev-home-vault-env + defaultMode: 0555 diff --git a/services/bstein-dev-home/chat-ai-gateway-deployment.yaml b/services/bstein-dev-home/chat-ai-gateway-deployment.yaml index 7ac6504..4fb4ba5 100644 --- a/services/bstein-dev-home/chat-ai-gateway-deployment.yaml +++ b/services/bstein-dev-home/chat-ai-gateway-deployment.yaml @@ -15,6 +15,7 @@ spec: labels: app: chat-ai-gateway spec: + serviceAccountName: bstein-dev-home nodeSelector: kubernetes.io/arch: arm64 node-role.kubernetes.io/worker: "true" @@ -23,20 +24,10 @@ spec: image: python:3.11-slim command: ["/bin/sh","-c"] args: - - python /app/gateway.py + - . /vault/scripts/bstein_dev_home_vault_env.sh && exec python /app/gateway.py env: - name: UPSTREAM_URL value: http://bstein-dev-home-backend/api/chat - - name: CHAT_KEY_MATRIX - valueFrom: - secretKeyRef: - name: chat-ai-keys-runtime - key: matrix - - name: CHAT_KEY_HOMEPAGE - valueFrom: - secretKeyRef: - name: chat-ai-keys-runtime - key: homepage ports: - name: http containerPort: 8080 @@ -63,7 +54,23 @@ spec: - name: code mountPath: /app/gateway.py subPath: gateway.py + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true volumes: - name: code configMap: name: chat-ai-gateway + - name: vault-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: bstein-dev-home-vault + - name: vault-scripts + configMap: + name: bstein-dev-home-vault-env + defaultMode: 0555 diff --git a/services/bstein-dev-home/kustomization.yaml b/services/bstein-dev-home/kustomization.yaml index 56d9cfd..57228ed 100644 --- a/services/bstein-dev-home/kustomization.yaml +++ b/services/bstein-dev-home/kustomization.yaml @@ -6,7 +6,7 @@ resources: - namespace.yaml - image.yaml - rbac.yaml - - portal-e2e-client-secret-sync-rbac.yaml + - secretproviderclass.yaml - chat-ai-gateway-deployment.yaml - chat-ai-gateway-service.yaml - frontend-deployment.yaml @@ -17,6 +17,12 @@ resources: - portal-onboarding-e2e-test-job.yaml - ingress.yaml configMapGenerator: + - name: bstein-dev-home-vault-env + namespace: bstein-dev-home + files: + - bstein_dev_home_vault_env.sh=scripts/bstein_dev_home_vault_env.sh + options: + disableNameSuffixHash: true - name: chat-ai-gateway namespace: bstein-dev-home files: diff --git a/services/bstein-dev-home/portal-onboarding-e2e-test-job.yaml b/services/bstein-dev-home/portal-onboarding-e2e-test-job.yaml index 3170f86..18ef62a 100644 --- a/services/bstein-dev-home/portal-onboarding-e2e-test-job.yaml +++ b/services/bstein-dev-home/portal-onboarding-e2e-test-job.yaml @@ -9,6 +9,7 @@ spec: template: spec: restartPolicy: Never + serviceAccountName: bstein-dev-home containers: - name: test image: python:3.11-slim @@ -21,21 +22,6 @@ spec: value: atlas - name: KEYCLOAK_ADMIN_CLIENT_ID value: bstein-dev-home-admin - - name: KEYCLOAK_ADMIN_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: bstein-dev-home-keycloak-admin - key: client_secret - - name: PORTAL_E2E_CLIENT_ID - valueFrom: - secretKeyRef: - name: portal-e2e-client - key: client_id - - name: PORTAL_E2E_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: portal-e2e-client - key: client_secret - name: PORTAL_TARGET_CLIENT_ID value: bstein-dev-home - name: E2E_PORTAL_ADMIN_USERNAME @@ -54,13 +40,30 @@ spec: args: - | set -euo pipefail + . /vault/scripts/bstein_dev_home_vault_env.sh python /scripts/test_portal_onboarding_flow.py volumeMounts: - name: tests mountPath: /scripts readOnly: true + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true volumes: - name: tests configMap: name: portal-onboarding-e2e-tests defaultMode: 0555 + - name: vault-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: bstein-dev-home-vault + - name: vault-scripts + configMap: + name: bstein-dev-home-vault-env + defaultMode: 0555 diff --git a/services/bstein-dev-home/scripts/bstein_dev_home_vault_env.sh b/services/bstein-dev-home/scripts/bstein_dev_home_vault_env.sh new file mode 100644 index 0000000..8cab54e --- /dev/null +++ b/services/bstein-dev-home/scripts/bstein_dev_home_vault_env.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh +set -eu + +vault_dir="/vault/secrets" + +read_secret() { + cat "${vault_dir}/$1" +} + +export KEYCLOAK_ADMIN_CLIENT_SECRET="$(read_secret bstein-dev-home-keycloak-admin__client_secret)" +export PORTAL_DATABASE_URL="$(read_secret atlas-portal-db__PORTAL_DATABASE_URL)" + +export CHAT_KEY_MATRIX="$(read_secret chat-ai-keys-runtime__matrix)" +export CHAT_KEY_HOMEPAGE="$(read_secret chat-ai-keys-runtime__homepage)" + +export PORTAL_E2E_CLIENT_ID="$(read_secret portal-e2e-client__client_id)" +export PORTAL_E2E_CLIENT_SECRET="$(read_secret portal-e2e-client__client_secret)" diff --git a/services/bstein-dev-home/secretproviderclass.yaml b/services/bstein-dev-home/secretproviderclass.yaml new file mode 100644 index 0000000..83e94c0 --- /dev/null +++ b/services/bstein-dev-home/secretproviderclass.yaml @@ -0,0 +1,36 @@ +# services/bstein-dev-home/secretproviderclass.yaml +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: bstein-dev-home-vault + namespace: bstein-dev-home +spec: + provider: vault + parameters: + vaultAddress: "http://vault.vault.svc.cluster.local:8200" + roleName: "bstein-dev-home" + objects: | + - objectName: "atlas-portal-db__PORTAL_DATABASE_URL" + secretPath: "kv/data/atlas/bstein-dev-home/atlas-portal-db" + secretKey: "PORTAL_DATABASE_URL" + - objectName: "bstein-dev-home-keycloak-admin__client_secret" + secretPath: "kv/data/atlas/bstein-dev-home/bstein-dev-home-keycloak-admin" + secretKey: "client_secret" + - objectName: "chat-ai-keys__homepage" + secretPath: "kv/data/atlas/bstein-dev-home/chat-ai-keys" + secretKey: "homepage" + - objectName: "chat-ai-keys__matrix" + secretPath: "kv/data/atlas/bstein-dev-home/chat-ai-keys" + secretKey: "matrix" + - objectName: "chat-ai-keys-runtime__homepage" + secretPath: "kv/data/atlas/shared/chat-ai-keys-runtime" + secretKey: "homepage" + - objectName: "chat-ai-keys-runtime__matrix" + secretPath: "kv/data/atlas/shared/chat-ai-keys-runtime" + secretKey: "matrix" + - objectName: "portal-e2e-client__client_id" + secretPath: "kv/data/atlas/shared/portal-e2e-client" + secretKey: "client_id" + - objectName: "portal-e2e-client__client_secret" + secretPath: "kv/data/atlas/shared/portal-e2e-client" + secretKey: "client_secret" diff --git a/services/bstein-dev-home/vaultwarden-cred-sync-cronjob.yaml b/services/bstein-dev-home/vaultwarden-cred-sync-cronjob.yaml index 5e7c779..b531e7a 100644 --- a/services/bstein-dev-home/vaultwarden-cred-sync-cronjob.yaml +++ b/services/bstein-dev-home/vaultwarden-cred-sync-cronjob.yaml @@ -25,9 +25,11 @@ spec: - name: sync image: registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-92 # {"$imagepolicy": "bstein-dev-home:bstein-dev-home-backend"} imagePullPolicy: Always - command: - - python - - /scripts/vaultwarden_cred_sync.py + command: ["/bin/sh", "-c"] + args: + - >- + . /vault/scripts/bstein_dev_home_vault_env.sh + && exec python /scripts/vaultwarden_cred_sync.py env: - name: PYTHONPATH value: /app @@ -41,19 +43,30 @@ spec: value: atlas - name: KEYCLOAK_ADMIN_CLIENT_ID value: bstein-dev-home-admin - - name: KEYCLOAK_ADMIN_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: bstein-dev-home-keycloak-admin - key: client_secret - name: HTTP_CHECK_TIMEOUT_SEC value: "20" volumeMounts: - name: vaultwarden-cred-sync-script mountPath: /scripts readOnly: true + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true volumes: - name: vaultwarden-cred-sync-script configMap: name: vaultwarden-cred-sync-script defaultMode: 0555 + - name: vault-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: bstein-dev-home-vault + - name: vault-scripts + configMap: + name: bstein-dev-home-vault-env + defaultMode: 0555 diff --git a/services/gitea/deployment.yaml b/services/gitea/deployment.yaml index ed2cd63..13aef1e 100644 --- a/services/gitea/deployment.yaml +++ b/services/gitea/deployment.yaml @@ -21,33 +21,19 @@ spec: labels: app: gitea spec: + serviceAccountName: gitea-vault initContainers: - name: configure-oidc image: gitea/gitea:1.23 securityContext: runAsUser: 1000 runAsGroup: 1000 - env: - - name: CLIENT_ID - valueFrom: - secretKeyRef: - name: gitea-oidc - key: client_id - - name: CLIENT_SECRET - valueFrom: - secretKeyRef: - name: gitea-oidc - key: client_secret - - name: DISCOVERY_URL - valueFrom: - secretKeyRef: - name: gitea-oidc - key: openid_auto_discovery_url command: - - /bin/bash + - /bin/sh - -c - | set -euo pipefail + . /vault/scripts/gitea_vault_env.sh APPINI=/data/gitea/conf/app.ini BIN=/usr/local/bin/gitea @@ -87,6 +73,18 @@ spec: volumeMounts: - name: gitea-data mountPath: /data + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true nodeSelector: node-role.kubernetes.io/worker: "true" affinity: @@ -107,6 +105,11 @@ spec: containers: - name: gitea image: gitea/gitea:1.23 + command: ["/bin/sh", "-c"] + args: + - >- + . /vault/scripts/gitea_vault_env.sh + && exec /usr/bin/entrypoint /usr/bin/s6-svscan /etc/s6 ports: - containerPort: 3000 name: http @@ -143,16 +146,6 @@ spec: value: "scm.bstein.dev" - name: GITEA__session__SAME_SITE value: "lax" - - name: GITEA__security__SECRET_KEY - valueFrom: - secretKeyRef: - name: gitea-secret - key: SECRET_KEY - - name: GITEA__security__INTERNAL_TOKEN - valueFrom: - secretKeyRef: - name: gitea-secret - key: INTERNAL_TOKEN - name: DB_TYPE value: "postgres" - name: DB_HOST @@ -161,11 +154,6 @@ spec: value: "gitea" - name: DB_USER value: "gitea" - - name: DB_PASS - valueFrom: - secretKeyRef: - name: gitea-db-secret - key: password - name: START_SSH_SERVER value: "true" - name: SSH_PORT @@ -177,3 +165,13 @@ spec: - name: gitea-data persistentVolumeClaim: claimName: gitea-data + - name: vault-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: gitea-vault + - name: vault-scripts + configMap: + name: gitea-vault-env + defaultMode: 0555 diff --git a/services/gitea/kustomization.yaml b/services/gitea/kustomization.yaml index 36d6c23..466e6ce 100644 --- a/services/gitea/kustomization.yaml +++ b/services/gitea/kustomization.yaml @@ -3,7 +3,16 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml + - serviceaccount.yaml + - pvc.yaml + - secretproviderclass.yaml - deployment.yaml - service.yaml - - pvc.yaml - ingress.yaml +configMapGenerator: + - name: gitea-vault-env + namespace: gitea + files: + - gitea_vault_env.sh=scripts/gitea_vault_env.sh + options: + disableNameSuffixHash: true diff --git a/services/gitea/scripts/gitea_vault_env.sh b/services/gitea/scripts/gitea_vault_env.sh new file mode 100644 index 0000000..0e4c4a8 --- /dev/null +++ b/services/gitea/scripts/gitea_vault_env.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env sh +set -eu + +vault_dir="/vault/secrets" + +read_secret() { + cat "${vault_dir}/$1" +} + +export GITEA__security__SECRET_KEY="$(read_secret gitea-secret__SECRET_KEY)" +export GITEA__security__INTERNAL_TOKEN="$(read_secret gitea-secret__INTERNAL_TOKEN)" +export DB_PASS="$(read_secret gitea-db-secret__password)" +export CLIENT_ID="$(read_secret gitea-oidc__client_id)" +export CLIENT_SECRET="$(read_secret gitea-oidc__client_secret)" +export DISCOVERY_URL="$(read_secret gitea-oidc__openid_auto_discovery_url)" diff --git a/services/gitea/secretproviderclass.yaml b/services/gitea/secretproviderclass.yaml new file mode 100644 index 0000000..b555025 --- /dev/null +++ b/services/gitea/secretproviderclass.yaml @@ -0,0 +1,30 @@ +# services/gitea/secretproviderclass.yaml +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: gitea-vault + namespace: gitea +spec: + provider: vault + parameters: + vaultAddress: "http://vault.vault.svc.cluster.local:8200" + roleName: "gitea" + objects: | + - objectName: "gitea-db-secret__password" + secretPath: "kv/data/atlas/gitea/gitea-db-secret" + secretKey: "password" + - objectName: "gitea-secret__SECRET_KEY" + secretPath: "kv/data/atlas/gitea/gitea-secret" + secretKey: "SECRET_KEY" + - objectName: "gitea-secret__INTERNAL_TOKEN" + secretPath: "kv/data/atlas/gitea/gitea-secret" + secretKey: "INTERNAL_TOKEN" + - objectName: "gitea-oidc__client_id" + secretPath: "kv/data/atlas/gitea/gitea-oidc" + secretKey: "client_id" + - objectName: "gitea-oidc__client_secret" + secretPath: "kv/data/atlas/gitea/gitea-oidc" + secretKey: "client_secret" + - objectName: "gitea-oidc__openid_auto_discovery_url" + secretPath: "kv/data/atlas/gitea/gitea-oidc" + secretKey: "openid_auto_discovery_url" diff --git a/services/gitea/serviceaccount.yaml b/services/gitea/serviceaccount.yaml new file mode 100644 index 0000000..a91ca8a --- /dev/null +++ b/services/gitea/serviceaccount.yaml @@ -0,0 +1,6 @@ +# services/gitea/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: gitea-vault + namespace: gitea diff --git a/services/keycloak/deployment.yaml b/services/keycloak/deployment.yaml index 48cf5e0..3c116f6 100644 --- a/services/keycloak/deployment.yaml +++ b/services/keycloak/deployment.yaml @@ -21,6 +21,7 @@ spec: labels: app: keycloak spec: + serviceAccountName: sso-vault affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -69,28 +70,16 @@ spec: - name: keycloak image: quay.io/keycloak/keycloak:26.0.7 imagePullPolicy: IfNotPresent + command: ["/bin/sh", "-c"] args: - - start + - >- + . /vault/scripts/keycloak_vault_env.sh + && exec /opt/keycloak/bin/kc.sh start env: - name: KC_DB value: postgres - name: KC_DB_URL_HOST value: postgres-service.postgres.svc.cluster.local - - name: KC_DB_URL_DATABASE - valueFrom: - secretKeyRef: - name: keycloak-db - key: POSTGRES_DATABASE - - name: KC_DB_USERNAME - valueFrom: - secretKeyRef: - name: keycloak-db - key: POSTGRES_USER - - name: KC_DB_PASSWORD - valueFrom: - secretKeyRef: - name: keycloak-db - key: POSTGRES_PASSWORD - name: KC_DB_SCHEMA value: public - name: KC_HOSTNAME @@ -115,16 +104,6 @@ spec: value: "true" - name: KC_METRICS_ENABLED value: "true" - - name: KEYCLOAK_ADMIN - valueFrom: - secretKeyRef: - name: keycloak-admin - key: username - - name: KEYCLOAK_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: keycloak-admin - key: password - name: KC_EVENTS_LISTENERS value: jboss-logging,mailu-http - name: KC_SPI_EVENTS_LISTENER_MAILU-HTTP_ENDPOINT @@ -153,9 +132,25 @@ spec: mountPath: /opt/keycloak/data - name: providers mountPath: /opt/keycloak/providers + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true volumes: - name: data persistentVolumeClaim: claimName: keycloak-data - name: providers emptyDir: {} + - name: vault-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: sso-vault + - name: vault-scripts + configMap: + name: sso-vault-env + defaultMode: 0555 diff --git a/services/keycloak/kustomization.yaml b/services/keycloak/kustomization.yaml index 38da8bf..82df213 100644 --- a/services/keycloak/kustomization.yaml +++ b/services/keycloak/kustomization.yaml @@ -5,11 +5,11 @@ namespace: sso resources: - namespace.yaml - pvc.yaml + - serviceaccount.yaml + - secretproviderclass.yaml - deployment.yaml - realm-settings-job.yaml - portal-e2e-client-job.yaml - - portal-e2e-client-secret-sync-rbac.yaml - - portal-e2e-client-secret-sync-cronjob.yaml - portal-e2e-target-client-job.yaml - portal-e2e-token-exchange-permissions-job.yaml - portal-e2e-token-exchange-test-job.yaml @@ -26,6 +26,9 @@ resources: generatorOptions: disableNameSuffixHash: true configMapGenerator: + - name: sso-vault-env + files: + - keycloak_vault_env.sh=scripts/keycloak_vault_env.sh - name: portal-e2e-tests files: - test_portal_token_exchange.py=scripts/tests/test_portal_token_exchange.py diff --git a/services/keycloak/scripts/keycloak_vault_env.sh b/services/keycloak/scripts/keycloak_vault_env.sh new file mode 100644 index 0000000..a9cfdae --- /dev/null +++ b/services/keycloak/scripts/keycloak_vault_env.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env sh +set -eu + +vault_dir="/vault/secrets" + +read_secret() { + cat "${vault_dir}/$1" +} + +admin_user="$(read_secret keycloak-admin__username)" +admin_password="$(read_secret keycloak-admin__password)" + +export KEYCLOAK_ADMIN="${admin_user}" +export KEYCLOAK_ADMIN_USER="${admin_user}" +export KEYCLOAK_ADMIN_PASSWORD="${admin_password}" + +export KC_DB_URL_DATABASE="$(read_secret keycloak-db__POSTGRES_DATABASE)" +export KC_DB_USERNAME="$(read_secret keycloak-db__POSTGRES_USER)" +export KC_DB_PASSWORD="$(read_secret keycloak-db__POSTGRES_PASSWORD)" + +export PORTAL_E2E_CLIENT_ID="$(read_secret portal-e2e-client__client_id)" +export PORTAL_E2E_CLIENT_SECRET="$(read_secret portal-e2e-client__client_secret)" + +export LDAP_ADMIN_PASSWORD="$(read_secret openldap-admin__LDAP_ADMIN_PASSWORD)" +export LDAP_CONFIG_PASSWORD="$(read_secret openldap-admin__LDAP_CONFIG_PASSWORD)" diff --git a/services/keycloak/secretproviderclass.yaml b/services/keycloak/secretproviderclass.yaml new file mode 100644 index 0000000..7015c12 --- /dev/null +++ b/services/keycloak/secretproviderclass.yaml @@ -0,0 +1,39 @@ +# services/keycloak/secretproviderclass.yaml +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: sso-vault + namespace: sso +spec: + provider: vault + parameters: + vaultAddress: "http://vault.vault.svc.cluster.local:8200" + roleName: "sso" + objects: | + - objectName: "keycloak-db__POSTGRES_DATABASE" + secretPath: "kv/data/atlas/sso/keycloak-db" + secretKey: "POSTGRES_DATABASE" + - objectName: "keycloak-db__POSTGRES_USER" + secretPath: "kv/data/atlas/sso/keycloak-db" + secretKey: "POSTGRES_USER" + - objectName: "keycloak-db__POSTGRES_PASSWORD" + secretPath: "kv/data/atlas/sso/keycloak-db" + secretKey: "POSTGRES_PASSWORD" + - objectName: "keycloak-admin__username" + secretPath: "kv/data/atlas/shared/keycloak-admin" + secretKey: "username" + - objectName: "keycloak-admin__password" + secretPath: "kv/data/atlas/shared/keycloak-admin" + secretKey: "password" + - objectName: "portal-e2e-client__client_id" + secretPath: "kv/data/atlas/shared/portal-e2e-client" + secretKey: "client_id" + - objectName: "portal-e2e-client__client_secret" + secretPath: "kv/data/atlas/shared/portal-e2e-client" + secretKey: "client_secret" + - objectName: "openldap-admin__LDAP_ADMIN_PASSWORD" + secretPath: "kv/data/atlas/sso/openldap-admin" + secretKey: "LDAP_ADMIN_PASSWORD" + - objectName: "openldap-admin__LDAP_CONFIG_PASSWORD" + secretPath: "kv/data/atlas/sso/openldap-admin" + secretKey: "LDAP_CONFIG_PASSWORD" diff --git a/services/keycloak/serviceaccount.yaml b/services/keycloak/serviceaccount.yaml new file mode 100644 index 0000000..59d710f --- /dev/null +++ b/services/keycloak/serviceaccount.yaml @@ -0,0 +1,6 @@ +# services/keycloak/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sso-vault + namespace: sso diff --git a/services/vault/scripts/vault_k8s_auth_configure.sh b/services/vault/scripts/vault_k8s_auth_configure.sh index 14604cd..fdffbea 100644 --- a/services/vault/scripts/vault_k8s_auth_configure.sh +++ b/services/vault/scripts/vault_k8s_auth_configure.sh @@ -35,16 +35,39 @@ vault write auth/kubernetes/config \ kubernetes_host="${k8s_host}" \ kubernetes_ca_cert="${k8s_ca}" -for namespace in outline planka; do +for namespace in outline planka bstein-dev-home gitea vaultwarden sso; do policy_name="${namespace}" + service_account="" + shared_paths="" + case "${namespace}" in - outline) service_account="outline-vault" ;; - planka) service_account="planka-vault" ;; - *) log "unknown namespace ${namespace}"; exit 1 ;; + outline) + service_account="outline-vault" + ;; + planka) + service_account="planka-vault" + ;; + bstein-dev-home) + service_account="bstein-dev-home" + shared_paths="shared/chat-ai-keys-runtime shared/portal-e2e-client" + ;; + gitea) + service_account="gitea-vault" + ;; + vaultwarden) + service_account="vaultwarden-vault" + ;; + sso) + service_account="sso-vault,mas-secrets-ensure" + shared_paths="shared/keycloak-admin shared/portal-e2e-client" + ;; + *) + log "unknown namespace ${namespace}" + exit 1 + ;; esac - log "writing policy ${policy_name}" - vault policy write "${policy_name}" - <- + . /vault/scripts/vaultwarden_vault_env.sh + && exec /start.sh env: - name: SIGNUPS_ALLOWED value: "false" @@ -43,16 +49,6 @@ spec: value: "postmaster@bstein.dev" - name: SMTP_FROM_NAME value: "Atlas Vaultwarden" - - name: DATABASE_URL - valueFrom: - secretKeyRef: - name: vaultwarden-db-url - key: DATABASE_URL - - name: ADMIN_TOKEN - valueFrom: - secretKeyRef: - name: vaultwarden-admin - key: ADMIN_TOKEN ports: - name: http containerPort: 80 @@ -60,7 +56,23 @@ spec: volumeMounts: - name: vaultwarden-data mountPath: /data + - name: vault-secrets + mountPath: /vault/secrets + readOnly: true + - name: vault-scripts + mountPath: /vault/scripts + readOnly: true volumes: - name: vaultwarden-data persistentVolumeClaim: claimName: vaultwarden-data + - name: vault-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: vaultwarden-vault + - name: vault-scripts + configMap: + name: vaultwarden-vault-env + defaultMode: 0555 diff --git a/services/vaultwarden/kustomization.yaml b/services/vaultwarden/kustomization.yaml index f0d02fd..c1525f7 100644 --- a/services/vaultwarden/kustomization.yaml +++ b/services/vaultwarden/kustomization.yaml @@ -4,7 +4,16 @@ kind: Kustomization namespace: vaultwarden resources: - namespace.yaml + - serviceaccount.yaml - pvc.yaml + - secretproviderclass.yaml - deployment.yaml - service.yaml - ingress.yaml +configMapGenerator: + - name: vaultwarden-vault-env + namespace: vaultwarden + files: + - vaultwarden_vault_env.sh=scripts/vaultwarden_vault_env.sh + options: + disableNameSuffixHash: true diff --git a/services/vaultwarden/scripts/vaultwarden_vault_env.sh b/services/vaultwarden/scripts/vaultwarden_vault_env.sh new file mode 100644 index 0000000..133faaa --- /dev/null +++ b/services/vaultwarden/scripts/vaultwarden_vault_env.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -eu + +vault_dir="/vault/secrets" + +read_secret() { + cat "${vault_dir}/$1" +} + +export DATABASE_URL="$(read_secret vaultwarden-db-url__DATABASE_URL)" +export ADMIN_TOKEN="$(read_secret vaultwarden-admin__ADMIN_TOKEN)" diff --git a/services/vaultwarden/secretproviderclass.yaml b/services/vaultwarden/secretproviderclass.yaml new file mode 100644 index 0000000..6d4530b --- /dev/null +++ b/services/vaultwarden/secretproviderclass.yaml @@ -0,0 +1,18 @@ +# services/vaultwarden/secretproviderclass.yaml +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: vaultwarden-vault + namespace: vaultwarden +spec: + provider: vault + parameters: + vaultAddress: "http://vault.vault.svc.cluster.local:8200" + roleName: "vaultwarden" + objects: | + - objectName: "vaultwarden-db-url__DATABASE_URL" + secretPath: "kv/data/atlas/vaultwarden/vaultwarden-db-url" + secretKey: "DATABASE_URL" + - objectName: "vaultwarden-admin__ADMIN_TOKEN" + secretPath: "kv/data/atlas/vaultwarden/vaultwarden-admin" + secretKey: "ADMIN_TOKEN" diff --git a/services/vaultwarden/serviceaccount.yaml b/services/vaultwarden/serviceaccount.yaml new file mode 100644 index 0000000..445ee15 --- /dev/null +++ b/services/vaultwarden/serviceaccount.yaml @@ -0,0 +1,6 @@ +# services/vaultwarden/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vaultwarden-vault + namespace: vaultwarden