fix(telephony): chown /shared-tts in initContainer + harden security context

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) <noreply@anthropic.com>
This commit is contained in:
Andrew Stoltz
2026-04-16 16:29:21 -05:00
parent d3ffad9190
commit 4f33d7a053

View File

@@ -118,16 +118,25 @@ spec:
app: telephony-web app: telephony-web
spec: spec:
securityContext: securityContext:
runAsNonRoot: true
runAsUser: 1654
runAsGroup: 1654
fsGroup: 1654 fsGroup: 1654
nodeSelector: nodeSelector:
kubernetes.io/hostname: rke2-agent1 kubernetes.io/hostname: rke2-agent1
initContainers: initContainers:
- name: fix-data-perms - name: fix-data-perms
image: busybox:latest 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: volumeMounts:
- name: telephony-data - name: telephony-data
mountPath: /data mountPath: /data
- name: shared-tts
mountPath: /shared-tts
hostNetwork: true hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet dnsPolicy: ClusterFirstWithHostNet
affinity: affinity:
@@ -141,6 +150,11 @@ spec:
- name: telephony-web - name: telephony-web
image: localhost/fc-telephony-web:v20260325d image: localhost/fc-telephony-web:v20260325d
imagePullPolicy: Never imagePullPolicy: Never
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
ports: ports:
- containerPort: 5100 - containerPort: 5100
name: http name: http
@@ -170,6 +184,10 @@ spec:
readOnly: true readOnly: true
- name: telephony-data - name: telephony-data
mountPath: /data mountPath: /data
- name: tmp
mountPath: /tmp
- name: logs
mountPath: /app/logs
# Shared TTS audio — we write Piper .sln16 output here; Asterisk # Shared TTS audio — we write Piper .sln16 output here; Asterisk
# pod reads the same hostPath at /var/lib/asterisk/sounds/tts and # pod reads the same hostPath at /var/lib/asterisk/sounds/tts and
# plays via `sound:tts/<name>`. Both pods are pinned to rke2-agent1. # plays via `sound:tts/<name>`. Both pods are pinned to rke2-agent1.
@@ -201,6 +219,10 @@ spec:
- name: telephony-data - name: telephony-data
persistentVolumeClaim: persistentVolumeClaim:
claimName: telephony-data claimName: telephony-data
- name: tmp
emptyDir: {}
- name: logs
emptyDir: {}
- name: shared-tts - name: shared-tts
hostPath: hostPath:
path: /tmp/tts-audio path: /tmp/tts-audio