From c48e62b163941f1a37c8f9fd3ebc29298e8121f5 Mon Sep 17 00:00:00 2001
From: Sheogorath <sheogorath@shivering-isles.com>
Date: Sat, 30 Sep 2023 14:20:56 +0200
Subject: [PATCH] feat(mastodon): Rework chart to fully support PSS

This patch fixes the quite patching PSS support of the existing chart
and sets security contexts properly.
---
 charts/mastodon/Chart.yaml                    |   2 +-
 charts/mastodon/README.md                     |  11 +-
 .../templates/cronjob-media-remove.yaml       |   8 +
 .../templates/deployment-sidekiq.yaml         |   6 +-
 .../templates/deployment-streaming.yaml       |   4 +-
 charts/mastodon/templates/deployment-web.yaml |   4 +-
 .../templates/job-assets-precompile.yaml      |   8 +
 .../mastodon/templates/job-chewy-upgrade.yaml |   8 +
 .../mastodon/templates/job-create-admin.yaml  |   8 +
 charts/mastodon/templates/job-db-migrate.yaml |   8 +
 .../templates/job-db-pre-migrate.yaml         |   8 +
 .../tests/30_pss_restricted_test.yaml         |  36 ++++
 .../__snapshot__/50_sidekiq_test.yaml.snap    |   7 +-
 .../tests/__snapshot__/50_web_test.yaml.snap  |   4 +-
 .../80_subchart_redis_test.yaml.snap          |  18 +-
 .../__snapshot__/98_snapshot_test.yaml.snap   | 168 +++++++++++++++++-
 charts/mastodon/values.yaml                   |  17 +-
 17 files changed, 290 insertions(+), 35 deletions(-)
 create mode 100644 charts/mastodon/tests/30_pss_restricted_test.yaml

diff --git a/charts/mastodon/Chart.yaml b/charts/mastodon/Chart.yaml
index a1ae98481..d20722766 100644
--- a/charts/mastodon/Chart.yaml
+++ b/charts/mastodon/Chart.yaml
@@ -17,7 +17,7 @@ annotations:
     - name: support
       url: https://matrix.to/#/#mastodon-on-kubernetes:shivering-isles.com
 type: application
-version: 6.3.3
+version: 7.0.0
 # renovate: image=ghcr.io/mastodon/mastodon
 appVersion: "v4.1.9"
 
diff --git a/charts/mastodon/README.md b/charts/mastodon/README.md
index 79db2c079..4e708915d 100644
--- a/charts/mastodon/README.md
+++ b/charts/mastodon/README.md
@@ -1,6 +1,6 @@
 # mastodon
 
-![Version: 6.3.3](https://img.shields.io/badge/Version-6.3.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v4.1.9](https://img.shields.io/badge/AppVersion-v4.1.9-informational?style=flat-square)
+![Version: 7.0.0](https://img.shields.io/badge/Version-7.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v4.1.9](https://img.shields.io/badge/AppVersion-v4.1.9-informational?style=flat-square)
 
 Mastodon is a free, open-source social network server based on ActivityPub.
 
@@ -19,7 +19,7 @@ This unofficical Helm chart is maintained to the best of knowledge, with the lim
 |------------|------|---------|
 | https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami | elasticsearch | 19.11.1 |
 | https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami | postgresql | 11.9.13 |
-| https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami | redis | 18.0.2 |
+| https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami | redis | 18.0.4 |
 
 ## Values
 
@@ -101,17 +101,17 @@ This unofficical Helm chart is maintained to the best of knowledge, with the lim
 | mastodon.streaming.port | int | `4000` |  |
 | mastodon.streaming.replicas | int | `1` | Number of Streaming Pods running |
 | mastodon.streaming.resources | Streaming Container | `{}` | Resources for Streaming Pods, overwrites .Values.resources |
-| mastodon.streaming.securityContext | Streaming Container | `nil` | Security Context for Streaming Pods, overwrites .Values.securityContext |
+| mastodon.streaming.securityContext | Streaming Container | `{"readOnlyRootFilesystem":true}` | Security Context for Streaming Pods, overwrites .Values.securityContext |
 | mastodon.streaming.workers | int | `1` | this should be set manually since os.cpus() returns the number of CPUs on the node running the pod, which is unrelated to the resources allocated to the pod by k8s |
 | mastodon.web.affinity | object | `{}` | Affinity for Web Pods, overwrites .Values.affinity |
 | mastodon.web.podSecurityContext | object | `{}` | Pod Security Context for Web Pods, overwrites .Values.podSecurityContext |
 | mastodon.web.port | int | `3000` |  |
 | mastodon.web.replicas | int | `1` | Number of Web Pods running |
 | mastodon.web.resources | Web Container | `{}` | Resources for Web Pods, overwrites .Values.resources |
-| mastodon.web.securityContext | Web Container | `{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true}` | Security Context for Web Pods, overwrites .Values.securityContext |
+| mastodon.web.securityContext | Web Container | `{"readOnlyRootFilesystem":true}` | Security Context for Web Pods, overwrites .Values.securityContext |
 | mastodon.web_domain | string | `nil` | Use of WEB_DOMAIN requires careful consideration: https://docs.joinmastodon.org/admin/config/#federation You must redirect the path LOCAL_DOMAIN/.well-known/ to WEB_DOMAIN/.well-known/ as described Example: mastodon.example.com |
 | podAnnotations | object | `{}` | Kubernetes manages pods for jobs and pods for deployments differently, so you might need to apply different annotations to the two different sets of pods. The annotations set with podAnnotations will be added to all deployment-managed pods. |
-| podSecurityContext | object | `{"allowPrivilegeEscalation":false,"fsGroup":991,"runAsGroup":991,"runAsNonRoot":true,"runAsUser":991,"seccompProfile":{"type":"RuntimeDefault"}}` | https://github.com/mastodon/mastodon/blob/main/Dockerfile#L75  if you manually change the UID/GID environment variables, ensure these values match: |
+| podSecurityContext | object | `{"fsGroup":991,"runAsGroup":991,"runAsNonRoot":true,"runAsUser":991,"seccompProfile":{"type":"RuntimeDefault"}}` | base securityContext on Pod-Level. Can be overwritten but more specific contexts. Used to match the Upstream UID/GID |
 | postgresql.auth.database | string | `"mastodon_production"` |  |
 | postgresql.auth.existingSecret | string | `""` |  |
 | postgresql.auth.password | string | `""` |  |
@@ -126,6 +126,7 @@ This unofficical Helm chart is maintained to the best of knowledge, with the lim
 | redis.port | string | `"6379"` | port at which redis is available |
 | redis.redisUrl | string | `nil` | redisUrl overwrites redis.host and redis.port. It allows to use sentinal redis installations |
 | resources | object | `{}` | Default resources for all Deployments and jobs unless overwritten |
+| securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}}` | securityContext on Container-Level. Can be overwritten but more specific contexts. |
 | serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
 | serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
 | serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template |
diff --git a/charts/mastodon/templates/cronjob-media-remove.yaml b/charts/mastodon/templates/cronjob-media-remove.yaml
index fccd368a2..4707b6319 100644
--- a/charts/mastodon/templates/cronjob-media-remove.yaml
+++ b/charts/mastodon/templates/cronjob-media-remove.yaml
@@ -33,6 +33,10 @@ spec:
                           - rails
                   topologyKey: kubernetes.io/hostname
           {{- end }}
+          {{- with .Values.podSecurityContext }}
+          securityContext:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -69,6 +73,10 @@ spec:
                 {{- end }}
                 - name: "PORT"
                   value: {{ .Values.mastodon.web.port | quote }}
+              {{- with .Values.securityContext }}
+              securityContext:
+                {{- toYaml . | nindent 16 }}
+              {{- end }}
               {{- if (not .Values.mastodon.s3.enabled) }}
               volumeMounts:
                 - name: assets
diff --git a/charts/mastodon/templates/deployment-sidekiq.yaml b/charts/mastodon/templates/deployment-sidekiq.yaml
index ec91a8621..486c2e428 100644
--- a/charts/mastodon/templates/deployment-sidekiq.yaml
+++ b/charts/mastodon/templates/deployment-sidekiq.yaml
@@ -38,7 +38,7 @@ spec:
         {{- toYaml . | nindent 8 }}
       {{- end }}
       serviceAccountName: {{ include "mastodon.serviceAccountName" $context }}
-      {{- with (default $context.Values.podSecurityContext $context.Values.mastodon.sidekiq.podSecurityContext) }}
+      {{- with (deepCopy $context.Values.podSecurityContext | mergeOverwrite $context.Values.mastodon.sidekiq.podSecurityContext) }}
       securityContext:
         {{- toYaml . | nindent 8 }}
       {{- end }}
@@ -57,8 +57,10 @@ spec:
       {{- end }}
       containers:
         - name: {{ $context.Chart.Name }}
+          {{- with (deepCopy $context.Values.securityContext | mergeOverwrite  $context.Values.mastodon.sidekiq.securityContext ) }}
           securityContext:
-            {{- toYaml $context.Values.mastodon.sidekiq.securityContext | nindent 12 }}
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           image: "{{ $context.Values.image.repository }}:{{ $context.Values.image.tag | default $context.Chart.AppVersion }}"
           imagePullPolicy: {{ $context.Values.image.pullPolicy }}
           command:
diff --git a/charts/mastodon/templates/deployment-streaming.yaml b/charts/mastodon/templates/deployment-streaming.yaml
index 7c8bf15ac..746e411fa 100644
--- a/charts/mastodon/templates/deployment-streaming.yaml
+++ b/charts/mastodon/templates/deployment-streaming.yaml
@@ -28,13 +28,13 @@ spec:
         {{- toYaml . | nindent 8 }}
       {{- end }}
       serviceAccountName: {{ include "mastodon.serviceAccountName" . }}
-      {{- with (default .Values.podSecurityContext .Values.mastodon.streaming.podSecurityContext) }}
+      {{- with (deepCopy .Values.podSecurityContext | mergeOverwrite .Values.mastodon.streaming.podSecurityContext) }}
       securityContext:
         {{- toYaml . | nindent 8 }}
       {{- end }}
       containers:
         - name: {{ .Chart.Name }}-streaming
-          {{- with (default .Values.securityContext .Values.mastodon.streaming.securityContext) }}
+          {{- with (deepCopy .Values.securityContext | mergeOverwrite .Values.mastodon.streaming.securityContext) }}
           securityContext:
             {{- toYaml . | nindent 12 }}
           {{- end }}
diff --git a/charts/mastodon/templates/deployment-web.yaml b/charts/mastodon/templates/deployment-web.yaml
index 2a19fad08..0ba5374db 100644
--- a/charts/mastodon/templates/deployment-web.yaml
+++ b/charts/mastodon/templates/deployment-web.yaml
@@ -29,7 +29,7 @@ spec:
         {{- toYaml . | nindent 8 }}
       {{- end }}
       serviceAccountName: {{ include "mastodon.serviceAccountName" . }}
-      {{- with (default .Values.podSecurityContext .Values.mastodon.web.podSecurityContext) }}
+      {{- with (deepCopy .Values.podSecurityContext | mergeOverwrite .Values.mastodon.web.podSecurityContext) }}
       securityContext:
         {{- toYaml . | nindent 8 }}
       {{- end }}
@@ -44,7 +44,7 @@ spec:
       {{- end }}
       containers:
         - name: {{ .Chart.Name }}-web
-          {{- with (default .Values.securityContext .Values.mastodon.web.securityContext) }}
+          {{- with (deepCopy .Values.securityContext | mergeOverwrite .Values.mastodon.web.securityContext) }}
           securityContext:
             {{- toYaml . | nindent 12 }}
           {{- end }}
diff --git a/charts/mastodon/templates/job-assets-precompile.yaml b/charts/mastodon/templates/job-assets-precompile.yaml
index fd33b587c..f0604ced3 100644
--- a/charts/mastodon/templates/job-assets-precompile.yaml
+++ b/charts/mastodon/templates/job-assets-precompile.yaml
@@ -31,6 +31,10 @@ spec:
           persistentVolumeClaim:
             claimName: {{ template "mastodon.fullname" . }}-system
       {{- end }}
+      {{- with .Values.podSecurityContext }}
+      securityContext:
+        {{- toYaml . | nindent 12 }}
+      {{- end }}
       containers:
         - name: {{ include "mastodon.fullname" . }}-assets-precompile
           image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
@@ -60,6 +64,10 @@ spec:
             {{- end }}
             - name: "PORT"
               value: {{ .Values.mastodon.web.port | quote }}
+          {{- with .Values.securityContext }}
+          securityContext:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           {{- if (not .Values.mastodon.s3.enabled) }}
           volumeMounts:
             - name: assets
diff --git a/charts/mastodon/templates/job-chewy-upgrade.yaml b/charts/mastodon/templates/job-chewy-upgrade.yaml
index 6ce8b6914..dd8a8ad4c 100644
--- a/charts/mastodon/templates/job-chewy-upgrade.yaml
+++ b/charts/mastodon/templates/job-chewy-upgrade.yaml
@@ -32,6 +32,10 @@ spec:
           persistentVolumeClaim:
             claimName: {{ template "mastodon.fullname" . }}-system
       {{- end }}
+      {{- with .Values.podSecurityContext }}
+      securityContext:
+        {{- toYaml . | nindent 12 }}
+      {{- end }}
       containers:
         - name: {{ include "mastodon.fullname" . }}-chewy-setup
           image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
@@ -61,6 +65,10 @@ spec:
             {{- end }}
             - name: "PORT"
               value: {{ .Values.mastodon.web.port | quote }}
+          {{- with .Values.securityContext }}
+          securityContext:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           {{- if (not .Values.mastodon.s3.enabled) }}
           volumeMounts:
             - name: assets
diff --git a/charts/mastodon/templates/job-create-admin.yaml b/charts/mastodon/templates/job-create-admin.yaml
index 5bf7839ba..9fba07add 100644
--- a/charts/mastodon/templates/job-create-admin.yaml
+++ b/charts/mastodon/templates/job-create-admin.yaml
@@ -32,6 +32,10 @@ spec:
           persistentVolumeClaim:
             claimName: {{ template "mastodon.fullname" . }}-system
       {{- end }}
+      {{- with .Values.podSecurityContext }}
+      securityContext:
+        {{- toYaml . | nindent 12 }}
+      {{- end }}
       containers:
         - name: {{ include "mastodon.fullname" . }}-create-admin
           image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
@@ -66,6 +70,10 @@ spec:
             {{- end }}
             - name: "PORT"
               value: {{ .Values.mastodon.web.port | quote }}
+          {{- with .Values.securityContext }}
+          securityContext:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           {{- if (not .Values.mastodon.s3.enabled) }}
           volumeMounts:
             - name: assets
diff --git a/charts/mastodon/templates/job-db-migrate.yaml b/charts/mastodon/templates/job-db-migrate.yaml
index 390ec9db9..830f5b590 100644
--- a/charts/mastodon/templates/job-db-migrate.yaml
+++ b/charts/mastodon/templates/job-db-migrate.yaml
@@ -31,6 +31,10 @@ spec:
           persistentVolumeClaim:
             claimName: {{ template "mastodon.fullname" . }}-system
       {{- end }}
+      {{- with .Values.podSecurityContext }}
+      securityContext:
+        {{- toYaml . | nindent 12 }}
+      {{- end }}
       containers:
         - name: {{ include "mastodon.fullname" . }}-db-migrate
           image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
@@ -60,6 +64,10 @@ spec:
             {{- end }}
             - name: "PORT"
               value: {{ .Values.mastodon.web.port | quote }}
+          {{- with .Values.securityContext }}
+          securityContext:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           {{- if (not .Values.mastodon.s3.enabled) }}
           volumeMounts:
             - name: assets
diff --git a/charts/mastodon/templates/job-db-pre-migrate.yaml b/charts/mastodon/templates/job-db-pre-migrate.yaml
index 4f745ec35..f77a2525e 100644
--- a/charts/mastodon/templates/job-db-pre-migrate.yaml
+++ b/charts/mastodon/templates/job-db-pre-migrate.yaml
@@ -31,6 +31,10 @@ spec:
           persistentVolumeClaim:
             claimName: {{ template "mastodon.fullname" . }}-system
       {{- end }}
+      {{- with .Values.podSecurityContext }}
+      securityContext:
+        {{- toYaml . | nindent 12 }}
+      {{- end }}
       containers:
         - name: {{ include "mastodon.fullname" . }}-db-migrate
           image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
@@ -62,6 +66,10 @@ spec:
               value: {{ .Values.mastodon.web.port | quote }}
             - name: SKIP_POST_DEPLOYMENT_MIGRATIONS
               value: "true"
+          {{- with .Values.securityContext }}
+          securityContext:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           {{- if (not .Values.mastodon.s3.enabled) }}
           volumeMounts:
             - name: assets
diff --git a/charts/mastodon/tests/30_pss_restricted_test.yaml b/charts/mastodon/tests/30_pss_restricted_test.yaml
new file mode 100644
index 000000000..1bef054cd
--- /dev/null
+++ b/charts/mastodon/tests/30_pss_restricted_test.yaml
@@ -0,0 +1,36 @@
+suite: Pod Security Standards
+templates:
+  - deployment-sidekiq.yaml
+  - deployment-streaming.yaml
+  - deployment-web.yaml
+  - job-assets-precompile.yaml
+  - job-chewy-upgrade.yaml
+  - job-db-migrate.yaml
+  - job-db-pre-migrate.yaml
+tests:
+  - it: has allowPrivilegeEscalation set to false
+    values:
+      - mocks/dev.yaml
+      - mocks/sidekiq.yaml
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.capabilities.drop[0]
+          value: ALL
+      - equal:
+          path: spec.template.spec.securityContext.runAsNonRoot
+          value: true
+      - equal:
+          path: spec.template.spec.securityContext.runAsUser
+          value: 991
+      - equal:
+          path: spec.template.spec.securityContext.runAsGroup
+          value: 991
+      - equal:
+          path: spec.template.spec.securityContext.fsGroup
+          value: 991
+      - equal:
+          path: spec.template.spec.securityContext.seccompProfile.type
+          value: RuntimeDefault
\ No newline at end of file
diff --git a/charts/mastodon/tests/__snapshot__/50_sidekiq_test.yaml.snap b/charts/mastodon/tests/__snapshot__/50_sidekiq_test.yaml.snap
index f119198bf..b09d31f73 100644
--- a/charts/mastodon/tests/__snapshot__/50_sidekiq_test.yaml.snap
+++ b/charts/mastodon/tests/__snapshot__/50_sidekiq_test.yaml.snap
@@ -109,14 +109,17 @@ should match basic snapshot:
               imagePullPolicy: IfNotPresent
               name: mastodon
               resources: {}
-              securityContext: {}
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
diff --git a/charts/mastodon/tests/__snapshot__/50_web_test.yaml.snap b/charts/mastodon/tests/__snapshot__/50_web_test.yaml.snap
index 8d0d15233..72f109d77 100644
--- a/charts/mastodon/tests/__snapshot__/50_web_test.yaml.snap
+++ b/charts/mastodon/tests/__snapshot__/50_web_test.yaml.snap
@@ -107,6 +107,9 @@ should match basic snapshot:
                   port: http
               securityContext:
                 allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
                 readOnlyRootFilesystem: true
               startupProbe:
                 failureThreshold: 30
@@ -120,7 +123,6 @@ should match basic snapshot:
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
diff --git a/charts/mastodon/tests/__snapshot__/80_subchart_redis_test.yaml.snap b/charts/mastodon/tests/__snapshot__/80_subchart_redis_test.yaml.snap
index 3bee04fc5..bae0e7530 100644
--- a/charts/mastodon/tests/__snapshot__/80_subchart_redis_test.yaml.snap
+++ b/charts/mastodon/tests/__snapshot__/80_subchart_redis_test.yaml.snap
@@ -67,14 +67,17 @@ should allow disabling redis auth:
               imagePullPolicy: IfNotPresent
               name: mastodon
               resources: {}
-              securityContext: {}
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -150,8 +153,13 @@ should allow disabling redis auth:
                 httpGet:
                   path: /api/v1/streaming/health
                   port: streaming
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
+                readOnlyRootFilesystem: true
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -225,6 +233,9 @@ should allow disabling redis auth:
                   port: http
               securityContext:
                 allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
                 readOnlyRootFilesystem: true
               startupProbe:
                 failureThreshold: 30
@@ -238,7 +249,6 @@ should allow disabling redis auth:
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
diff --git a/charts/mastodon/tests/__snapshot__/98_snapshot_test.yaml.snap b/charts/mastodon/tests/__snapshot__/98_snapshot_test.yaml.snap
index 277867b61..a872391ce 100644
--- a/charts/mastodon/tests/__snapshot__/98_snapshot_test.yaml.snap
+++ b/charts/mastodon/tests/__snapshot__/98_snapshot_test.yaml.snap
@@ -90,12 +90,24 @@ should match basic snapshot:
                   image: ghcr.io/mastodon/mastodon:4.5.6
                   imagePullPolicy: IfNotPresent
                   name: RELEASE-NAME-mastodon-media-remove
+                  securityContext:
+                    allowPrivilegeEscalation: false
+                    capabilities:
+                      drop:
+                        - ALL
                   volumeMounts:
                     - mountPath: /opt/mastodon/public/assets
                       name: assets
                     - mountPath: /opt/mastodon/public/system
                       name: system
               restartPolicy: OnFailure
+              securityContext:
+                fsGroup: 991
+                runAsGroup: 991
+                runAsNonRoot: true
+                runAsUser: 991
+                seccompProfile:
+                  type: RuntimeDefault
               volumes:
                 - name: assets
                   persistentVolumeClaim:
@@ -177,14 +189,17 @@ should match basic snapshot:
               imagePullPolicy: IfNotPresent
               name: mastodon
               resources: {}
-              securityContext: {}
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -265,8 +280,13 @@ should match basic snapshot:
                 httpGet:
                   path: /api/v1/streaming/health
                   port: streaming
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
+                readOnlyRootFilesystem: true
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -345,6 +365,9 @@ should match basic snapshot:
                   port: http
               securityContext:
                 allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
                 readOnlyRootFilesystem: true
               startupProbe:
                 failureThreshold: 30
@@ -358,7 +381,6 @@ should match basic snapshot:
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -454,12 +476,24 @@ should match basic snapshot:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-assets-precompile
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -514,12 +548,24 @@ should match basic snapshot:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-chewy-setup
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -579,12 +625,24 @@ should match basic snapshot:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-create-admin
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -639,12 +697,24 @@ should match basic snapshot:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-db-migrate
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -701,12 +771,24 @@ should match basic snapshot:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-db-migrate
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -971,12 +1053,24 @@ should match basic snapshot without dependencies:
                   image: ghcr.io/mastodon/mastodon:4.5.6
                   imagePullPolicy: IfNotPresent
                   name: RELEASE-NAME-mastodon-media-remove
+                  securityContext:
+                    allowPrivilegeEscalation: false
+                    capabilities:
+                      drop:
+                        - ALL
                   volumeMounts:
                     - mountPath: /opt/mastodon/public/assets
                       name: assets
                     - mountPath: /opt/mastodon/public/system
                       name: system
               restartPolicy: OnFailure
+              securityContext:
+                fsGroup: 991
+                runAsGroup: 991
+                runAsNonRoot: true
+                runAsUser: 991
+                seccompProfile:
+                  type: RuntimeDefault
               volumes:
                 - name: assets
                   persistentVolumeClaim:
@@ -1058,14 +1152,17 @@ should match basic snapshot without dependencies:
               imagePullPolicy: IfNotPresent
               name: mastodon
               resources: {}
-              securityContext: {}
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -1146,8 +1243,13 @@ should match basic snapshot without dependencies:
                 httpGet:
                   path: /api/v1/streaming/health
                   port: streaming
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
+                readOnlyRootFilesystem: true
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -1226,6 +1328,9 @@ should match basic snapshot without dependencies:
                   port: http
               securityContext:
                 allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
                 readOnlyRootFilesystem: true
               startupProbe:
                 failureThreshold: 30
@@ -1239,7 +1344,6 @@ should match basic snapshot without dependencies:
                 - mountPath: /opt/mastodon/public/system
                   name: system
           securityContext:
-            allowPrivilegeEscalation: false
             fsGroup: 991
             runAsGroup: 991
             runAsNonRoot: true
@@ -1335,12 +1439,24 @@ should match basic snapshot without dependencies:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-assets-precompile
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -1400,12 +1516,24 @@ should match basic snapshot without dependencies:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-create-admin
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -1460,12 +1588,24 @@ should match basic snapshot without dependencies:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-db-migrate
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
@@ -1522,12 +1662,24 @@ should match basic snapshot without dependencies:
               image: ghcr.io/mastodon/mastodon:4.5.6
               imagePullPolicy: IfNotPresent
               name: RELEASE-NAME-mastodon-db-migrate
+              securityContext:
+                allowPrivilegeEscalation: false
+                capabilities:
+                  drop:
+                    - ALL
               volumeMounts:
                 - mountPath: /opt/mastodon/public/assets
                   name: assets
                 - mountPath: /opt/mastodon/public/system
                   name: system
           restartPolicy: Never
+          securityContext:
+            fsGroup: 991
+            runAsGroup: 991
+            runAsNonRoot: true
+            runAsUser: 991
+            seccompProfile:
+              type: RuntimeDefault
           volumes:
             - name: assets
               persistentVolumeClaim:
diff --git a/charts/mastodon/values.yaml b/charts/mastodon/values.yaml
index a1d060669..db78da6ce 100644
--- a/charts/mastodon/values.yaml
+++ b/charts/mastodon/values.yaml
@@ -164,6 +164,7 @@ mastodon:
     podSecurityContext: {}
     # -- (Streaming Container) Security Context for Streaming Pods, overwrites .Values.securityContext
     securityContext:
+      readOnlyRootFilesystem: true
     # -- (Streaming Container) Resources for Streaming Pods, overwrites .Values.resources
     resources: {}
     # limits:
@@ -182,7 +183,6 @@ mastodon:
     podSecurityContext: {}
     # -- (Web Container) Security Context for Web Pods, overwrites .Values.securityContext
     securityContext:
-      allowPrivilegeEscalation: false
       readOnlyRootFilesystem: true
     # -- (Web Container) Resources for Web Pods, overwrites .Values.resources
     resources: {}
@@ -388,12 +388,9 @@ externalAuth:
     #   search: "., -"
     #   replace: _
 
-# -- https://github.com/mastodon/mastodon/blob/main/Dockerfile#L75
-#
-# if you manually change the UID/GID environment variables, ensure these values
-# match:
+# -- base securityContext on Pod-Level. Can be overwritten but more specific contexts.
+# Used to match the Upstream UID/GID
 podSecurityContext:
-  allowPrivilegeEscalation: false
   runAsNonRoot: true
   runAsUser: 991
   runAsGroup: 991
@@ -401,8 +398,12 @@ podSecurityContext:
   seccompProfile:
     type: "RuntimeDefault"
 
-# @ignored
-securityContext: {}
+# -- securityContext on Container-Level. Can be overwritten but more specific contexts.
+securityContext:
+  allowPrivilegeEscalation: false
+  capabilities:
+    drop:
+      - ALL
 
 serviceAccount:
   # -- Specifies whether a service account should be created
-- 
GitLab