From 4f33d7a053a3a321a4fdfa7585c9572e2f81af8f Mon Sep 17 00:00:00 2001 From: Andrew Stoltz Date: Thu, 16 Apr 2026 16:29:21 -0500 Subject: [PATCH] fix(telephony): chown /shared-tts in initContainer + harden security context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two follow-ups to the Piper TTS wire-up landed in d3ffad9: 1. Telephony-web runs as uid 1654 (non-root), but the hostPath at /tmp/tts-audio is owned by root:root 0755. Pod couldn't write .sln16 files — every Piper call would succeed at the HTTP layer and then fall back to the sound map when File.WriteAllBytesAsync threw "Permission denied." Extend the existing fix-data-perms initContainer to chown the shared-tts mount too (0755 world-readable, so the Asterisk pod — running as a different uid — can still read). 2. Pod security context now explicitly sets runAsNonRoot: true + runAsUser 1654 + runAsGroup 1654 (cluster policy), matching the pattern used by every other FlowerCore service. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/telephony/telephony.yaml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/apps/telephony/telephony.yaml b/apps/telephony/telephony.yaml index 02d508a..05c175e 100644 --- a/apps/telephony/telephony.yaml +++ b/apps/telephony/telephony.yaml @@ -118,16 +118,25 @@ spec: app: telephony-web spec: securityContext: + runAsNonRoot: true + runAsUser: 1654 + runAsGroup: 1654 fsGroup: 1654 nodeSelector: kubernetes.io/hostname: rke2-agent1 initContainers: - name: fix-data-perms image: busybox:latest - command: ["sh", "-c", "chown -R 1654:1654 /data"] + # Also chown /shared-tts (hostPath /tmp/tts-audio) so the non-root + # app user (uid 1654) can write Piper .sln16 files that Asterisk + # reads at /var/lib/asterisk/sounds/tts. World-readable (755) is + # fine — Asterisk runs as a different uid in the other pod. + command: ["sh", "-c", "chown -R 1654:1654 /data && chown 1654:1654 /shared-tts && chmod 0755 /shared-tts"] volumeMounts: - name: telephony-data mountPath: /data + - name: shared-tts + mountPath: /shared-tts hostNetwork: true dnsPolicy: ClusterFirstWithHostNet affinity: @@ -141,6 +150,11 @@ spec: - name: telephony-web image: localhost/fc-telephony-web:v20260325d imagePullPolicy: Never + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: [ALL] ports: - containerPort: 5100 name: http @@ -170,6 +184,10 @@ spec: readOnly: true - name: telephony-data mountPath: /data + - name: tmp + mountPath: /tmp + - name: logs + mountPath: /app/logs # Shared TTS audio — we write Piper .sln16 output here; Asterisk # pod reads the same hostPath at /var/lib/asterisk/sounds/tts and # plays via `sound:tts/`. Both pods are pinned to rke2-agent1. @@ -201,6 +219,10 @@ spec: - name: telephony-data persistentVolumeClaim: claimName: telephony-data + - name: tmp + emptyDir: {} + - name: logs + emptyDir: {} - name: shared-tts hostPath: path: /tmp/tts-audio