vault: wire more services to CSI

This commit is contained in:
Brad Stein 2026-01-14 02:54:59 -03:00
parent 8a358832f3
commit fd2ae6bdd5
23 changed files with 436 additions and 130 deletions

View File

@ -26,15 +26,11 @@ spec:
- name: backend - name: backend
image: registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-92 # {"$imagepolicy": "bstein-dev-home:bstein-dev-home-backend"} image: registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-92 # {"$imagepolicy": "bstein-dev-home:bstein-dev-home-backend"}
imagePullPolicy: Always imagePullPolicy: Always
command: ["gunicorn"] command: ["/bin/sh", "-c"]
args: args:
- -b - >-
- 0.0.0.0:8080 . /vault/scripts/bstein_dev_home_vault_env.sh
- --workers && exec gunicorn -b 0.0.0.0:8080 --workers 2 --timeout 180 app:app
- "2"
- --timeout
- "180"
- app:app
env: env:
- name: AI_CHAT_API - name: AI_CHAT_API
value: http://ollama.ai.svc.cluster.local:11434 value: http://ollama.ai.svc.cluster.local:11434
@ -67,18 +63,8 @@ spec:
value: atlas value: atlas
- name: KEYCLOAK_ADMIN_CLIENT_ID - name: KEYCLOAK_ADMIN_CLIENT_ID
value: bstein-dev-home-admin 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 - name: ACCOUNT_ALLOWED_GROUPS
value: "" value: ""
- name: PORTAL_DATABASE_URL
valueFrom:
secretKeyRef:
name: atlas-portal-db
key: PORTAL_DATABASE_URL
- name: HTTP_CHECK_TIMEOUT_SEC - name: HTTP_CHECK_TIMEOUT_SEC
value: "2" value: "2"
- name: ACCESS_REQUEST_SUBMIT_RATE_LIMIT - name: ACCESS_REQUEST_SUBMIT_RATE_LIMIT
@ -108,6 +94,13 @@ spec:
initialDelaySeconds: 10 initialDelaySeconds: 10
periodSeconds: 10 periodSeconds: 10
timeoutSeconds: 3 timeoutSeconds: 3
volumeMounts:
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
- name: vault-scripts
mountPath: /vault/scripts
readOnly: true
resources: resources:
requests: requests:
cpu: 100m cpu: 100m
@ -115,3 +108,14 @@ spec:
limits: limits:
cpu: 500m cpu: 500m
memory: 512Mi 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

View File

@ -15,6 +15,7 @@ spec:
labels: labels:
app: chat-ai-gateway app: chat-ai-gateway
spec: spec:
serviceAccountName: bstein-dev-home
nodeSelector: nodeSelector:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: "true" node-role.kubernetes.io/worker: "true"
@ -23,20 +24,10 @@ spec:
image: python:3.11-slim image: python:3.11-slim
command: ["/bin/sh","-c"] command: ["/bin/sh","-c"]
args: args:
- python /app/gateway.py - . /vault/scripts/bstein_dev_home_vault_env.sh && exec python /app/gateway.py
env: env:
- name: UPSTREAM_URL - name: UPSTREAM_URL
value: http://bstein-dev-home-backend/api/chat 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: ports:
- name: http - name: http
containerPort: 8080 containerPort: 8080
@ -63,7 +54,23 @@ spec:
- name: code - name: code
mountPath: /app/gateway.py mountPath: /app/gateway.py
subPath: gateway.py subPath: gateway.py
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
- name: vault-scripts
mountPath: /vault/scripts
readOnly: true
volumes: volumes:
- name: code - name: code
configMap: configMap:
name: chat-ai-gateway 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

View File

@ -6,7 +6,7 @@ resources:
- namespace.yaml - namespace.yaml
- image.yaml - image.yaml
- rbac.yaml - rbac.yaml
- portal-e2e-client-secret-sync-rbac.yaml - secretproviderclass.yaml
- chat-ai-gateway-deployment.yaml - chat-ai-gateway-deployment.yaml
- chat-ai-gateway-service.yaml - chat-ai-gateway-service.yaml
- frontend-deployment.yaml - frontend-deployment.yaml
@ -17,6 +17,12 @@ resources:
- portal-onboarding-e2e-test-job.yaml - portal-onboarding-e2e-test-job.yaml
- ingress.yaml - ingress.yaml
configMapGenerator: 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 - name: chat-ai-gateway
namespace: bstein-dev-home namespace: bstein-dev-home
files: files:

View File

@ -9,6 +9,7 @@ spec:
template: template:
spec: spec:
restartPolicy: Never restartPolicy: Never
serviceAccountName: bstein-dev-home
containers: containers:
- name: test - name: test
image: python:3.11-slim image: python:3.11-slim
@ -21,21 +22,6 @@ spec:
value: atlas value: atlas
- name: KEYCLOAK_ADMIN_CLIENT_ID - name: KEYCLOAK_ADMIN_CLIENT_ID
value: bstein-dev-home-admin 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 - name: PORTAL_TARGET_CLIENT_ID
value: bstein-dev-home value: bstein-dev-home
- name: E2E_PORTAL_ADMIN_USERNAME - name: E2E_PORTAL_ADMIN_USERNAME
@ -54,13 +40,30 @@ spec:
args: args:
- | - |
set -euo pipefail set -euo pipefail
. /vault/scripts/bstein_dev_home_vault_env.sh
python /scripts/test_portal_onboarding_flow.py python /scripts/test_portal_onboarding_flow.py
volumeMounts: volumeMounts:
- name: tests - name: tests
mountPath: /scripts mountPath: /scripts
readOnly: true readOnly: true
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
- name: vault-scripts
mountPath: /vault/scripts
readOnly: true
volumes: volumes:
- name: tests - name: tests
configMap: configMap:
name: portal-onboarding-e2e-tests name: portal-onboarding-e2e-tests
defaultMode: 0555 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

View File

@ -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)"

View File

@ -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"

View File

@ -25,9 +25,11 @@ spec:
- name: sync - name: sync
image: registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-92 # {"$imagepolicy": "bstein-dev-home:bstein-dev-home-backend"} image: registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-92 # {"$imagepolicy": "bstein-dev-home:bstein-dev-home-backend"}
imagePullPolicy: Always imagePullPolicy: Always
command: command: ["/bin/sh", "-c"]
- python args:
- /scripts/vaultwarden_cred_sync.py - >-
. /vault/scripts/bstein_dev_home_vault_env.sh
&& exec python /scripts/vaultwarden_cred_sync.py
env: env:
- name: PYTHONPATH - name: PYTHONPATH
value: /app value: /app
@ -41,19 +43,30 @@ spec:
value: atlas value: atlas
- name: KEYCLOAK_ADMIN_CLIENT_ID - name: KEYCLOAK_ADMIN_CLIENT_ID
value: bstein-dev-home-admin 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 - name: HTTP_CHECK_TIMEOUT_SEC
value: "20" value: "20"
volumeMounts: volumeMounts:
- name: vaultwarden-cred-sync-script - name: vaultwarden-cred-sync-script
mountPath: /scripts mountPath: /scripts
readOnly: true readOnly: true
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
- name: vault-scripts
mountPath: /vault/scripts
readOnly: true
volumes: volumes:
- name: vaultwarden-cred-sync-script - name: vaultwarden-cred-sync-script
configMap: configMap:
name: vaultwarden-cred-sync-script name: vaultwarden-cred-sync-script
defaultMode: 0555 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

View File

@ -21,33 +21,19 @@ spec:
labels: labels:
app: gitea app: gitea
spec: spec:
serviceAccountName: gitea-vault
initContainers: initContainers:
- name: configure-oidc - name: configure-oidc
image: gitea/gitea:1.23 image: gitea/gitea:1.23
securityContext: securityContext:
runAsUser: 1000 runAsUser: 1000
runAsGroup: 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: command:
- /bin/bash - /bin/sh
- -c - -c
- | - |
set -euo pipefail set -euo pipefail
. /vault/scripts/gitea_vault_env.sh
APPINI=/data/gitea/conf/app.ini APPINI=/data/gitea/conf/app.ini
BIN=/usr/local/bin/gitea BIN=/usr/local/bin/gitea
@ -87,6 +73,18 @@ spec:
volumeMounts: volumeMounts:
- name: gitea-data - name: gitea-data
mountPath: /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: nodeSelector:
node-role.kubernetes.io/worker: "true" node-role.kubernetes.io/worker: "true"
affinity: affinity:
@ -107,6 +105,11 @@ spec:
containers: containers:
- name: gitea - name: gitea
image: gitea/gitea:1.23 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: ports:
- containerPort: 3000 - containerPort: 3000
name: http name: http
@ -143,16 +146,6 @@ spec:
value: "scm.bstein.dev" value: "scm.bstein.dev"
- name: GITEA__session__SAME_SITE - name: GITEA__session__SAME_SITE
value: "lax" 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 - name: DB_TYPE
value: "postgres" value: "postgres"
- name: DB_HOST - name: DB_HOST
@ -161,11 +154,6 @@ spec:
value: "gitea" value: "gitea"
- name: DB_USER - name: DB_USER
value: "gitea" value: "gitea"
- name: DB_PASS
valueFrom:
secretKeyRef:
name: gitea-db-secret
key: password
- name: START_SSH_SERVER - name: START_SSH_SERVER
value: "true" value: "true"
- name: SSH_PORT - name: SSH_PORT
@ -177,3 +165,13 @@ spec:
- name: gitea-data - name: gitea-data
persistentVolumeClaim: persistentVolumeClaim:
claimName: gitea-data 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

View File

@ -3,7 +3,16 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- namespace.yaml - namespace.yaml
- serviceaccount.yaml
- pvc.yaml
- secretproviderclass.yaml
- deployment.yaml - deployment.yaml
- service.yaml - service.yaml
- pvc.yaml
- ingress.yaml - ingress.yaml
configMapGenerator:
- name: gitea-vault-env
namespace: gitea
files:
- gitea_vault_env.sh=scripts/gitea_vault_env.sh
options:
disableNameSuffixHash: true

View File

@ -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)"

View File

@ -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"

View File

@ -0,0 +1,6 @@
# services/gitea/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitea-vault
namespace: gitea

View File

@ -21,6 +21,7 @@ spec:
labels: labels:
app: keycloak app: keycloak
spec: spec:
serviceAccountName: sso-vault
affinity: affinity:
nodeAffinity: nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: requiredDuringSchedulingIgnoredDuringExecution:
@ -69,28 +70,16 @@ spec:
- name: keycloak - name: keycloak
image: quay.io/keycloak/keycloak:26.0.7 image: quay.io/keycloak/keycloak:26.0.7
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c"]
args: args:
- start - >-
. /vault/scripts/keycloak_vault_env.sh
&& exec /opt/keycloak/bin/kc.sh start
env: env:
- name: KC_DB - name: KC_DB
value: postgres value: postgres
- name: KC_DB_URL_HOST - name: KC_DB_URL_HOST
value: postgres-service.postgres.svc.cluster.local 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 - name: KC_DB_SCHEMA
value: public value: public
- name: KC_HOSTNAME - name: KC_HOSTNAME
@ -115,16 +104,6 @@ spec:
value: "true" value: "true"
- name: KC_METRICS_ENABLED - name: KC_METRICS_ENABLED
value: "true" 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 - name: KC_EVENTS_LISTENERS
value: jboss-logging,mailu-http value: jboss-logging,mailu-http
- name: KC_SPI_EVENTS_LISTENER_MAILU-HTTP_ENDPOINT - name: KC_SPI_EVENTS_LISTENER_MAILU-HTTP_ENDPOINT
@ -153,9 +132,25 @@ spec:
mountPath: /opt/keycloak/data mountPath: /opt/keycloak/data
- name: providers - name: providers
mountPath: /opt/keycloak/providers mountPath: /opt/keycloak/providers
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
- name: vault-scripts
mountPath: /vault/scripts
readOnly: true
volumes: volumes:
- name: data - name: data
persistentVolumeClaim: persistentVolumeClaim:
claimName: keycloak-data claimName: keycloak-data
- name: providers - name: providers
emptyDir: {} 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

View File

@ -5,11 +5,11 @@ namespace: sso
resources: resources:
- namespace.yaml - namespace.yaml
- pvc.yaml - pvc.yaml
- serviceaccount.yaml
- secretproviderclass.yaml
- deployment.yaml - deployment.yaml
- realm-settings-job.yaml - realm-settings-job.yaml
- portal-e2e-client-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-target-client-job.yaml
- portal-e2e-token-exchange-permissions-job.yaml - portal-e2e-token-exchange-permissions-job.yaml
- portal-e2e-token-exchange-test-job.yaml - portal-e2e-token-exchange-test-job.yaml
@ -26,6 +26,9 @@ resources:
generatorOptions: generatorOptions:
disableNameSuffixHash: true disableNameSuffixHash: true
configMapGenerator: configMapGenerator:
- name: sso-vault-env
files:
- keycloak_vault_env.sh=scripts/keycloak_vault_env.sh
- name: portal-e2e-tests - name: portal-e2e-tests
files: files:
- test_portal_token_exchange.py=scripts/tests/test_portal_token_exchange.py - test_portal_token_exchange.py=scripts/tests/test_portal_token_exchange.py

View File

@ -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)"

View File

@ -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"

View File

@ -0,0 +1,6 @@
# services/keycloak/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: sso-vault
namespace: sso

View File

@ -35,16 +35,39 @@ vault write auth/kubernetes/config \
kubernetes_host="${k8s_host}" \ kubernetes_host="${k8s_host}" \
kubernetes_ca_cert="${k8s_ca}" 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}" policy_name="${namespace}"
service_account=""
shared_paths=""
case "${namespace}" in case "${namespace}" in
outline) service_account="outline-vault" ;; outline)
planka) service_account="planka-vault" ;; service_account="outline-vault"
*) log "unknown namespace ${namespace}"; exit 1 ;; ;;
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 esac
log "writing policy ${policy_name}" policy_body="$(cat <<EOF
vault policy write "${policy_name}" - <<EOF
path "kv/data/atlas/${namespace}/*" { path "kv/data/atlas/${namespace}/*" {
capabilities = ["read"] capabilities = ["read"]
} }
@ -52,6 +75,21 @@ path "kv/metadata/atlas/${namespace}/*" {
capabilities = ["list"] capabilities = ["list"]
} }
EOF EOF
)"
for shared in ${shared_paths}; do
policy_body="${policy_body}
path \"kv/data/atlas/${shared}\" {
capabilities = [\"read\"]
}
path \"kv/metadata/atlas/${shared}\" {
capabilities = [\"list\"]
}
"
done
log "writing policy ${policy_name}"
printf '%s\n' "${policy_body}" | vault policy write "${policy_name}" -
log "writing role ${namespace}" log "writing role ${namespace}"
vault write "auth/kubernetes/role/${namespace}" \ vault write "auth/kubernetes/role/${namespace}" \

View File

@ -19,9 +19,15 @@ spec:
labels: labels:
app: vaultwarden app: vaultwarden
spec: spec:
serviceAccountName: vaultwarden-vault
containers: containers:
- name: vaultwarden - name: vaultwarden
image: vaultwarden/server:1.33.2 image: vaultwarden/server:1.33.2
command: ["/bin/sh", "-c"]
args:
- >-
. /vault/scripts/vaultwarden_vault_env.sh
&& exec /start.sh
env: env:
- name: SIGNUPS_ALLOWED - name: SIGNUPS_ALLOWED
value: "false" value: "false"
@ -43,16 +49,6 @@ spec:
value: "postmaster@bstein.dev" value: "postmaster@bstein.dev"
- name: SMTP_FROM_NAME - name: SMTP_FROM_NAME
value: "Atlas Vaultwarden" 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: ports:
- name: http - name: http
containerPort: 80 containerPort: 80
@ -60,7 +56,23 @@ spec:
volumeMounts: volumeMounts:
- name: vaultwarden-data - name: vaultwarden-data
mountPath: /data mountPath: /data
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
- name: vault-scripts
mountPath: /vault/scripts
readOnly: true
volumes: volumes:
- name: vaultwarden-data - name: vaultwarden-data
persistentVolumeClaim: persistentVolumeClaim:
claimName: vaultwarden-data 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

View File

@ -4,7 +4,16 @@ kind: Kustomization
namespace: vaultwarden namespace: vaultwarden
resources: resources:
- namespace.yaml - namespace.yaml
- serviceaccount.yaml
- pvc.yaml - pvc.yaml
- secretproviderclass.yaml
- deployment.yaml - deployment.yaml
- service.yaml - service.yaml
- ingress.yaml - ingress.yaml
configMapGenerator:
- name: vaultwarden-vault-env
namespace: vaultwarden
files:
- vaultwarden_vault_env.sh=scripts/vaultwarden_vault_env.sh
options:
disableNameSuffixHash: true

View File

@ -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)"

View File

@ -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"

View File

@ -0,0 +1,6 @@
# services/vaultwarden/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: vaultwarden-vault
namespace: vaultwarden