diff --git a/apps/production/kustomization.yaml b/apps/production/kustomization.yaml index dcfddde..df2bea1 100644 --- a/apps/production/kustomization.yaml +++ b/apps/production/kustomization.yaml @@ -39,4 +39,7 @@ resources: - networkpolicy.yaml # Backup zur Hetzner Storage Box (Issues #6 + #15) - synapse-backup-secret.yaml - - synapse-backup.yaml \ No newline at end of file + - synapse-backup.yaml + # Automatisierte TURN-Secret-Rotation (Issue #38) + - turn-secret-rotation-secret.yaml + - turn-secret-rotation.yaml \ No newline at end of file diff --git a/apps/production/turn-secret-rotation-secret.yaml b/apps/production/turn-secret-rotation-secret.yaml new file mode 100644 index 0000000..19022c1 --- /dev/null +++ b/apps/production/turn-secret-rotation-secret.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Secret +metadata: + name: turn-secret-rotation-credentials + namespace: matrix +stringData: + age-key.txt: ENC[AES256_GCM,data:4LAs9LLFo38UMHXCo4lun9RHxGnDyp7GWlaNdIqqkSL9lNv7+ILdlc03CxFVobCYxK65xMOn1xdEty+887JBMlawST04am/5MkAnUivKwXCw8OHmbZhCwKHFqSYH/NsgVNf+btZKIIny8XPVQAPj/vQIi+Ity+BQyPkEZ1WUcsqjDoaK9IFhQTePJtHgWivhOY2WpUt/TP7vTfub4TOrgVpzNd9LIpBkwq+zhpVXKwnYUWOuLMXlPe08kazy,iv:9A24HbTl24slj+qTCfyI01+dGqRFVPDUA0wp2kSUHpc=,tag:iQxU0dWD4Noo1m0HXhV6vQ==,type:str] + gitea-token: ENC[AES256_GCM,data:iOhtEYm84Ds66psIlDhtWeicPD41XbXpO59Fs7tjy5g=,iv:0V+oYVBcOPeDHqx3jbMXlBFIPoH/Nk93nexVj5ii5uE=,tag:bROBGcgtl+l09DaYKrceGg==,type:str] +sops: + age: + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5S3BtTHNLVGVVM2ZpTlZS + Y3pGMS9CSkNsdUpPbWtkSTRHK0p6U2lwdEJnClVWdXp4SllyM1hvbTZyTU40SDc2 + QlVtMDduZWpaVENiYnhMNlFXd01QblEKLS0tIGNzTGRZcmoyaFltUHRDSHBPZE1N + OCszUkl1VjQ5V3F2cVI4dXJFcER5YXcK+2Eh1JNLuMiCnpQ3cL/I7XTykkIZ3tqp + O3c9UwYs1FAZWlMgElTBTqsmut1ShduIYfDFRKGeS0UxPEM4U+tIGw== + -----END AGE ENCRYPTED FILE----- + recipient: age14l0hwfqylwpemz5y2ghh2yxk0phszlnj3qlejhue0fw0kz3tmfgqdsjzdh + encrypted_regex: ^(data|stringData)$ + lastmodified: "2026-07-28T19:19:05Z" + mac: ENC[AES256_GCM,data:flnni0kqMnhaIX6oNcC+3Z89N+FCLo6mCKlPUACYCvW/DeJqemfshiHMdYKK9qeF3HEbvyUK8rku+rz/1z7DhcKITHFVeSLTJhJnZ2hUNnyGNNKKwpWknjz3J3sINC//5AUYRDIaO90Gv/Cu/u/uRvH4uvX4+zyYJxup4xVEudg=,iv:YXcVUhmCZNTBeui+JdFrmktdXK7miBHlUK2BmddUe8o=,tag:Ydu5HnbemG77kIqon8uojA==,type:str] + version: 3.13.3 diff --git a/apps/production/turn-secret-rotation.yaml b/apps/production/turn-secret-rotation.yaml new file mode 100644 index 0000000..95802f4 --- /dev/null +++ b/apps/production/turn-secret-rotation.yaml @@ -0,0 +1,63 @@ +# Automated TURN shared-secret rotation (Issue #38). Generates a new secret, re-encrypts +# apps/production/coturn-secret.yaml and synapse-turn-secret.yaml using a dedicated, +# narrowly-scoped age key (see turn-secret-rotation-secret.yaml - it can only decrypt these +# two files, not the repo's master sops-age key), bumps the checksum/rotated-at annotations +# so a merge restarts both consumers automatically, and opens a Pull Request rather than +# pushing straight to main - a human reviews and merges it. +apiVersion: batch/v1 +kind: CronJob +metadata: + name: turn-secret-rotation + namespace: matrix +spec: + schedule: "0 4 1 * *" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + backoffLimit: 1 + template: + metadata: + labels: + app.kubernetes.io/name: turn-secret-rotation + app.kubernetes.io/component: rotation + spec: + restartPolicy: OnFailure + containers: + - name: rotate + image: rohana.axion1337.de/sorb/axion-secret-rotation:v1 + env: + - name: GITEA_HOST + value: "rohana.axion1337.de" + - name: GITEA_REPO + value: "sorb/axion1337.chat-gitops" + - name: GITEA_TOKEN + valueFrom: + secretKeyRef: + name: turn-secret-rotation-credentials + key: gitea-token + - name: SOPS_AGE_KEY_FILE + value: /secrets/age/age-key.txt + - name: GIT_AUTHOR_NAME + value: "turn-secret-rotation" + - name: GIT_AUTHOR_EMAIL + value: "turn-secret-rotation@axion1337.chat" + volumeMounts: + - name: age-key + mountPath: /secrets/age + readOnly: true + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + memory: 128Mi + volumes: + - name: age-key + secret: + secretName: turn-secret-rotation-credentials + items: + - key: age-key.txt + path: age-key.txt + mode: 0400