# CronJob for Secret Rotation # This job rotates secrets periodically and triggers External Secrets to sync apiVersion: batch/v1 kind: CronJob metadata: name: secrets-rotation namespace: veza-production spec: schedule: "0 2 * * 0" # Every Sunday at 2 AM successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 jobTemplate: spec: template: spec: serviceAccountName: secrets-rotation containers: - name: rotate-secrets image: vault:latest command: - /bin/sh - -c - | # Rotate JWT secret (if using Vault dynamic secrets) vault kv put secret/veza/production/jwt-secret value=$(openssl rand -base64 32) # Force External Secrets to sync kubectl annotate externalsecret veza-secrets \ force-sync=$(date +%s) \ -n veza-production \ --overwrite # Restart deployments to pick up new secrets kubectl rollout restart deployment/veza-backend-api -n veza-production kubectl rollout restart deployment/veza-stream-server -n veza-production env: - name: VAULT_ADDR value: "https://vault.veza.internal:8200" - name: KUBECONFIG value: /var/run/secrets/kubernetes.io/serviceaccount restartPolicy: OnFailure --- apiVersion: v1 kind: ServiceAccount metadata: name: secrets-rotation namespace: veza-production --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: secrets-rotation namespace: veza-production rules: - apiGroups: ["external-secrets.io"] resources: ["externalsecrets"] verbs: ["get", "patch", "update"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "patch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: secrets-rotation namespace: veza-production roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: secrets-rotation subjects: - kind: ServiceAccount name: secrets-rotation namespace: veza-production