diff --git a/kubernetes/loculus/templates/_config-processor.tpl b/kubernetes/loculus/templates/_config-processor.tpl index a4d9483ef9..0720634299 100644 --- a/kubernetes/loculus/templates/_config-processor.tpl +++ b/kubernetes/loculus/templates/_config-processor.tpl @@ -16,6 +16,7 @@ limits: cpu: 500m memory: 256Mi + {{- include "loculus.containerSecurityContext" (list "config-processor" .Values) | nindent 2 }} env: - name: LOCULUSSUB_smtpPassword valueFrom: diff --git a/kubernetes/loculus/templates/_ingest-pod-spec.tpl b/kubernetes/loculus/templates/_ingest-pod-spec.tpl index 34991456a6..9610311f46 100644 --- a/kubernetes/loculus/templates/_ingest-pod-spec.tpl +++ b/kubernetes/loculus/templates/_ingest-pod-spec.tpl @@ -26,12 +26,14 @@ metadata: spec: {{- include "possiblePriorityClassName" . | nindent 2 }} {{- include "loculus.podScheduling" . | nindent 2 }} + {{- include "loculus.podSecurityContext" (list "ingest" $Values) | nindent 2 }} serviceAccountName: loculus-ingest-lock restartPolicy: Never initContainers: - name: version-check image: busybox {{- include "loculus.resources" (list "ingest-init" $Values) | nindent 6 }} + {{- include "loculus.containerSecurityContext" (list "ingest-init" $Values) | nindent 6 }} command: ['sh', '-c', ' CONFIG_VERSION=$(grep "verify_loculus_version_is:" /package/config/config.yaml | sed "s/verify_loculus_version_is: //;"); DOCKER_TAG="{{ $dockerTag }}"; @@ -50,6 +52,7 @@ spec: subPath: config.yaml - name: wait-for-no-other-ingest image: alpine/kubectl:1.36.0 + {{- include "loculus.containerSecurityContext" (list "ingest-init" $Values) | nindent 6 }} command: - sh - -c @@ -80,6 +83,7 @@ spec: image: {{ $organismContent.ingest.image }}:{{ $dockerTag }} imagePullPolicy: {{ $Values.imagePullPolicy }} {{- include "loculus.resources" (list "ingest" $Values) | nindent 6 }} + {{- include "loculus.containerSecurityContext" (list "ingest" $Values) | nindent 6 }} env: - name: KEYCLOAK_INGEST_PASSWORD valueFrom: diff --git a/kubernetes/loculus/templates/_security-context.tpl b/kubernetes/loculus/templates/_security-context.tpl new file mode 100644 index 0000000000..89a04b660e --- /dev/null +++ b/kubernetes/loculus/templates/_security-context.tpl @@ -0,0 +1,27 @@ +{{- define "loculus.podSecurityContext" -}} +{{- $args := . -}} +{{- $componentName := index $args 0 -}} +{{- $values := index $args 1 -}} + +{{- if and $values.podSecurityContext (hasKey $values.podSecurityContext $componentName) }} +securityContext: +{{ toYaml (index $values.podSecurityContext $componentName) | indent 2 }} +{{- else if and $values.podSecurityContext (hasKey $values.podSecurityContext "default") }} +securityContext: +{{ toYaml $values.podSecurityContext.default | indent 2 }} +{{- end }} +{{- end }} + +{{- define "loculus.containerSecurityContext" -}} +{{- $args := . -}} +{{- $componentName := index $args 0 -}} +{{- $values := index $args 1 -}} + +{{- if and $values.containerSecurityContext (hasKey $values.containerSecurityContext $componentName) }} +securityContext: +{{ toYaml (index $values.containerSecurityContext $componentName) | indent 2 }} +{{- else if and $values.containerSecurityContext (hasKey $values.containerSecurityContext "default") }} +securityContext: +{{ toYaml $values.containerSecurityContext.default | indent 2 }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/kubernetes/loculus/templates/autoapprove-deployment.yaml b/kubernetes/loculus/templates/autoapprove-deployment.yaml index ee6946c6ad..cf76af0374 100644 --- a/kubernetes/loculus/templates/autoapprove-deployment.yaml +++ b/kubernetes/loculus/templates/autoapprove-deployment.yaml @@ -25,11 +25,13 @@ spec: spec: {{- include "possiblePriorityClassName" $ | nindent 6 }} {{- include "loculus.podScheduling" $ | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "ingest" .Values) | nindent 6 }} containers: - name: autoapprove image: ghcr.io/loculus-project/ingest:{{ $dockerTag }} imagePullPolicy: {{ .Values.imagePullPolicy }} {{- include "loculus.resources" (list "ingest" .Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "ingest" .Values) | nindent 10 }} env: - name: KEYCLOAK_INGEST_PASSWORD valueFrom: diff --git a/kubernetes/loculus/templates/docs-preview.yaml b/kubernetes/loculus/templates/docs-preview.yaml index facf18ec13..69889bb3a4 100644 --- a/kubernetes/loculus/templates/docs-preview.yaml +++ b/kubernetes/loculus/templates/docs-preview.yaml @@ -23,11 +23,13 @@ spec: component: docs spec: {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "docs" .Values) | nindent 6 }} containers: - name: docs image: "ghcr.io/loculus-project/docs:{{ $dockerTag }}" imagePullPolicy: {{ .Values.imagePullPolicy }} {{- include "loculus.resources" (list "docs" .Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "docs" .Values) | nindent 10 }} ports: - containerPort: 8080 diff --git a/kubernetes/loculus/templates/ena-submission-deployment.yaml b/kubernetes/loculus/templates/ena-submission-deployment.yaml index 92fee97f8c..ca1a4c4b64 100644 --- a/kubernetes/loculus/templates/ena-submission-deployment.yaml +++ b/kubernetes/loculus/templates/ena-submission-deployment.yaml @@ -23,6 +23,7 @@ spec: spec: {{- include "possiblePriorityClassName" . | nindent 6 }} {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "ena-submission" .Values) | nindent 6 }} initContainers: - name: ena-submission-flyway image: "ghcr.io/loculus-project/ena-submission-flyway:{{ $dockerTag }}" @@ -33,6 +34,7 @@ spec: limits: cpu: 500m memory: 256Mi + {{- include "loculus.containerSecurityContext" (list "ena-submission-flyway" $.Values) | nindent 10 }} command: ['flyway', 'migrate'] env: - name: FLYWAY_URL @@ -55,6 +57,7 @@ spec: image: "ghcr.io/loculus-project/ena-submission:{{ $dockerTag }}" imagePullPolicy: {{ $.Values.imagePullPolicy }} {{- include "loculus.resources" (list "ena-submission" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "ena-submission" $.Values) | nindent 10 }} env: - name: EXTERNAL_METADATA_UPDATER_PASSWORD valueFrom: @@ -144,12 +147,14 @@ spec: spec: {{- include "possiblePriorityClassName" . | nindent 10 }} {{- include "loculus.podScheduling" . | nindent 10 }} + {{- include "loculus.podSecurityContext" (list "ena-submission-list-cronjob" $.Values) | nindent 10 }} restartPolicy: Never containers: - name: ena-submission image: "ghcr.io/loculus-project/ena-submission:{{ $dockerTag }}" imagePullPolicy: {{ $.Values.imagePullPolicy }} {{- include "loculus.resources" (list "ena-submission-list-cronjob" $.Values) | nindent 14 }} + {{- include "loculus.containerSecurityContext" (list "ena-submission-list-cronjob" $.Values) | nindent 14 }} env: - name: EXTERNAL_METADATA_UPDATER_PASSWORD valueFrom: diff --git a/kubernetes/loculus/templates/ingest.yaml b/kubernetes/loculus/templates/ingest.yaml index adc1455578..0847d8908d 100644 --- a/kubernetes/loculus/templates/ingest.yaml +++ b/kubernetes/loculus/templates/ingest.yaml @@ -143,11 +143,13 @@ spec: spec: {{- include "possiblePriorityClassName" $ | nindent 6 }} {{- include "loculus.podScheduling" $ | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "ingest-trigger" $.Values) | nindent 6 }} restartPolicy: Never serviceAccountName: loculus-ingest-trigger containers: - name: trigger image: alpine/kubectl:1.36.0 + {{- include "loculus.containerSecurityContext" (list "ingest-trigger" $.Values) | nindent 10 }} command: - sh - -c diff --git a/kubernetes/loculus/templates/keycloak-database-standin.yaml b/kubernetes/loculus/templates/keycloak-database-standin.yaml index 8e70e794b4..615a022cf7 100644 --- a/kubernetes/loculus/templates/keycloak-database-standin.yaml +++ b/kubernetes/loculus/templates/keycloak-database-standin.yaml @@ -25,6 +25,7 @@ spec: component: keycloak-database spec: {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "keycloak-database" .Values) | nindent 6 }} containers: - name: loculus-keycloak-database image: postgres:15.12 @@ -34,6 +35,7 @@ spec: cpu: 10m limits: memory: "100Mi" + {{- include "loculus.containerSecurityContext" (list "keycloak-database" .Values) | nindent 10 }} ports: - containerPort: 5432 env: diff --git a/kubernetes/loculus/templates/keycloak-deployment.yaml b/kubernetes/loculus/templates/keycloak-deployment.yaml index d8799b96e9..d136259821 100644 --- a/kubernetes/loculus/templates/keycloak-deployment.yaml +++ b/kubernetes/loculus/templates/keycloak-deployment.yaml @@ -22,10 +22,11 @@ spec: app: loculus component: keycloak spec: - {{- include "possiblePriorityClassName" . | nindent 6 }} + {{- include "possiblePriorityClassName" . | nindent 6 }} {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "keycloak" .Values) | nindent 6 }} initContainers: -{{- include "loculus.configProcessor" (dict "name" "keycloak-config" "dockerTag" $dockerTag "imagePullPolicy" .Values.imagePullPolicy) | nindent 8 }} +{{- include "loculus.configProcessor" (dict "name" "keycloak-config" "dockerTag" $dockerTag "imagePullPolicy" .Values.imagePullPolicy "Values" .Values) | nindent 8 }} - name: keycloak-theme-prep resources: requests: @@ -34,6 +35,7 @@ spec: limits: cpu: 500m memory: 256Mi + {{- include "loculus.containerSecurityContext" (list "keycloak-theme-prep" $.Values) | nindent 10 }} image: "ghcr.io/loculus-project/keycloakify:{{ $dockerTag }}" volumeMounts: - name: theme-volume @@ -43,6 +45,7 @@ spec: # TODO #1221 image: quay.io/keycloak/keycloak:23.0 {{- include "loculus.resources" (list "keycloak" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "keycloak" $.Values) | nindent 10 }} env: - name: REGISTRATION_TERMS_MESSAGE value: {{ $.Values.registrationTermsMessage }} diff --git a/kubernetes/loculus/templates/lapis-deployment.yaml b/kubernetes/loculus/templates/lapis-deployment.yaml index 4119e39368..bc00ded452 100644 --- a/kubernetes/loculus/templates/lapis-deployment.yaml +++ b/kubernetes/loculus/templates/lapis-deployment.yaml @@ -25,13 +25,15 @@ spec: spec: {{- include "possiblePriorityClassName" $ | nindent 6 }} {{- include "loculus.podScheduling" $ | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "lapis" $.Values) | nindent 6 }} initContainers: - {{- include "loculus.configProcessor" (dict "name" "lapis-silo-database-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy) | nindent 8 }} + {{- include "loculus.configProcessor" (dict "name" "lapis-silo-database-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy "Values" $.Values) | nindent 8 }} containers: - name: lapis image: "{{ $.Values.images.lapis.repository }}:{{ $.Values.images.lapis.tag }}" imagePullPolicy: "{{ $.Values.images.lapis.pullPolicy | default $.Values.imagePullPolicy }}" {{- include "loculus.resources" (list "lapis" $.Values $key) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "lapis" $.Values) | nindent 10 }} ports: - containerPort: 8080 args: diff --git a/kubernetes/loculus/templates/loculus-backend.yaml b/kubernetes/loculus/templates/loculus-backend.yaml index 31b065d589..8249f6fa9b 100644 --- a/kubernetes/loculus/templates/loculus-backend.yaml +++ b/kubernetes/loculus/templates/loculus-backend.yaml @@ -23,13 +23,15 @@ spec: spec: {{- include "possiblePriorityClassName" . | nindent 6 }} {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "backend" $.Values) | nindent 6 }} initContainers: -{{- include "loculus.configProcessor" (dict "name" "loculus-backend-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy) | nindent 8 }} + {{- include "loculus.configProcessor" (dict "name" "loculus-backend-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy "Values" $.Values) | nindent 8 }} containers: - name: backend image: "{{ $.Values.images.backend.repository }}:{{ $.Values.images.backend.tag | default $dockerTag }}" imagePullPolicy: "{{ $.Values.images.backend.pullPolicy | default $.Values.imagePullPolicy }}" {{- include "loculus.resources" (list "backend" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "backend" $.Values) | nindent 10 }} startupProbe: httpGet: path: "/actuator/health/liveness" diff --git a/kubernetes/loculus/templates/loculus-database-standin.yaml b/kubernetes/loculus/templates/loculus-database-standin.yaml index 2ad91ab6d8..4efd29b259 100644 --- a/kubernetes/loculus/templates/loculus-database-standin.yaml +++ b/kubernetes/loculus/templates/loculus-database-standin.yaml @@ -25,6 +25,7 @@ spec: component: database spec: {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "database" .Values) | nindent 6 }} containers: - name: database image: postgres:15.12 @@ -39,6 +40,7 @@ spec: cpu: "250m" limits: memory: "2Gi" + {{- include "loculus.containerSecurityContext" (list "database" .Values) | nindent 8 }} ports: - containerPort: 5432 env: diff --git a/kubernetes/loculus/templates/loculus-preprocessing-deployment.yaml b/kubernetes/loculus/templates/loculus-preprocessing-deployment.yaml index 5c29a9497b..8a7e21d3ac 100644 --- a/kubernetes/loculus/templates/loculus-preprocessing-deployment.yaml +++ b/kubernetes/loculus/templates/loculus-preprocessing-deployment.yaml @@ -35,11 +35,13 @@ spec: spec: {{- include "possiblePriorityClassName" $ | nindent 6 }} {{- include "loculus.podScheduling" $ | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "preprocessing" $.Values) | nindent 6 }} containers: - name: preprocessing-{{ $organism }} image: {{ $processingConfig.image}}:{{ $thisDockerTag }} imagePullPolicy: {{ $.Values.imagePullPolicy }} {{- include "loculus.resources" (list "preprocessing" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "preprocessing" $.Values) | nindent 10 }} env: - name: KEYCLOAK_PASSWORD valueFrom: diff --git a/kubernetes/loculus/templates/loculus-website.yaml b/kubernetes/loculus/templates/loculus-website.yaml index ff4cd7207a..545ac66382 100644 --- a/kubernetes/loculus/templates/loculus-website.yaml +++ b/kubernetes/loculus/templates/loculus-website.yaml @@ -23,13 +23,15 @@ spec: spec: {{- include "possiblePriorityClassName" . | nindent 6 }} {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "website" $.Values) | nindent 6 }} initContainers: -{{- include "loculus.configProcessor" (dict "name" "loculus-website-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy) | nindent 8 }} + {{- include "loculus.configProcessor" (dict "name" "loculus-website-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy "Values" $.Values) | nindent 8 }} containers: - name: website image: "{{ $.Values.images.website.repository }}:{{ $.Values.images.website.tag | default $dockerTag }}" imagePullPolicy: "{{ $.Values.images.website.pullPolicy | default $.Values.imagePullPolicy }}" {{- include "loculus.resources" (list "website" .Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "website" $.Values) | nindent 10 }} ports: - containerPort: 3000 volumeMounts: diff --git a/kubernetes/loculus/templates/minio-deployment.yaml b/kubernetes/loculus/templates/minio-deployment.yaml index a386177559..e14145d740 100644 --- a/kubernetes/loculus/templates/minio-deployment.yaml +++ b/kubernetes/loculus/templates/minio-deployment.yaml @@ -42,6 +42,7 @@ spec: component: minio spec: {{- include "loculus.podScheduling" . | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "minio" $.Values) | nindent 6 }} volumes: - name: policy-volume configMap: @@ -50,6 +51,7 @@ spec: - name: minio image: minio/minio:latest {{- include "loculus.resources" (list "minio" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "minio" $.Values) | nindent 10 }} args: ["server", "/data"] ports: - containerPort: 9000 diff --git a/kubernetes/loculus/templates/raw-reads-processing-deployment.yaml b/kubernetes/loculus/templates/raw-reads-processing-deployment.yaml index af2a49b777..e9d04f5425 100644 --- a/kubernetes/loculus/templates/raw-reads-processing-deployment.yaml +++ b/kubernetes/loculus/templates/raw-reads-processing-deployment.yaml @@ -23,11 +23,13 @@ spec: spec: {{- include "possiblePriorityClassName" $ | nindent 6 }} {{- include "loculus.podScheduling" $ | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "raw-reads-processing" $.Values) | nindent 6 }} containers: - name: raw-reads-processing image: "ghcr.io/loculus-project/raw-reads-processing-service:{{ $dockerTag }}" imagePullPolicy: {{ $.Values.imagePullPolicy }} {{- include "loculus.resources" (list "raw-reads-processing" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "raw-reads-processing" $.Values) | nindent 10 }} args: - raw_reads_processing - "--config-file=/config/config.yaml" diff --git a/kubernetes/loculus/templates/silo-deployment.yaml b/kubernetes/loculus/templates/silo-deployment.yaml index b3fa005d91..1f3c4a029c 100644 --- a/kubernetes/loculus/templates/silo-deployment.yaml +++ b/kubernetes/loculus/templates/silo-deployment.yaml @@ -31,14 +31,16 @@ spec: spec: {{- include "possiblePriorityClassName" $ | nindent 6 }} {{- include "loculus.podScheduling" $ | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "silo" $.Values) | nindent 6 }} initContainers: - {{- include "loculus.configProcessor" (dict "name" "lapis-silo-database-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy) | nindent 8 }} + {{- include "loculus.configProcessor" (dict "name" "lapis-silo-database-config" "dockerTag" $dockerTag "imagePullPolicy" $.Values.imagePullPolicy "Values" $.Values) | nindent 8 }} containers: - name: silo image: "{{ $.Values.images.loculusSilo.repository }}:{{ $.Values.images.loculusSilo.tag | default $dockerTag }}" command: ["/usr/local/bin/silo"] imagePullPolicy: {{ $.Values.imagePullPolicy }} {{- include "loculus.resources" (list "silo" $.Values $key) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "silo" $.Values) | nindent 10 }} env: - name: SPDLOG_LEVEL value: "debug" @@ -77,6 +79,7 @@ spec: image: "{{ $.Values.images.loculusSilo.repository }}:{{ $.Values.images.loculusSilo.tag | default $dockerTag }}" imagePullPolicy: "{{ $.Values.images.loculusSilo.pullPolicy }}" {{- include "loculus.resources" (list "silo-importer" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "silo-importer" $.Values) | nindent 10 }} env: - name: BACKEND_BASE_URL {{- if $.Values.disableBackend }} diff --git a/kubernetes/loculus/templates/taxonomy-deployment.yaml b/kubernetes/loculus/templates/taxonomy-deployment.yaml index 8a85deed27..d3f1013d92 100644 --- a/kubernetes/loculus/templates/taxonomy-deployment.yaml +++ b/kubernetes/loculus/templates/taxonomy-deployment.yaml @@ -23,9 +23,11 @@ spec: spec: {{- include "possiblePriorityClassName" $ | nindent 6 }} {{- include "loculus.podScheduling" $ | nindent 6 }} + {{- include "loculus.podSecurityContext" (list "taxonomy-service" $.Values) | nindent 6 }} initContainers: - name: download-taxonomy-db image: alpine:3 + {{- include "loculus.containerSecurityContext" (list "download-taxonomy-db" $.Values) | nindent 10 }} command: ["sh", "-c"] args: - | @@ -44,6 +46,7 @@ spec: image: "ghcr.io/loculus-project/taxonomy-service:{{ $dockerTag }}" imagePullPolicy: {{ $.Values.imagePullPolicy }} {{- include "loculus.resources" (list "taxonomy-service" $.Values) | nindent 10 }} + {{- include "loculus.containerSecurityContext" (list "taxonomy-service" $.Values) | nindent 10 }} args: - taxonomy_service - "--config-file=/config/config.yaml" diff --git a/kubernetes/loculus/values.schema.json b/kubernetes/loculus/values.schema.json index 3494f37758..133820d3ce 100644 --- a/kubernetes/loculus/values.schema.json +++ b/kubernetes/loculus/values.schema.json @@ -1078,6 +1078,259 @@ }, "required": ["repository", "pullPolicy"], "additionalProperties": false + }, + "seLinuxOptions": { + "type": "object", + "additionalProperties": false, + "description": "SELinux options. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.36/#selinuxoptions-v1-core", + "properties": { + "user": { + "type": "string", + "description": "SELinux user label" + }, + "role": { + "type": "string", + "description": "SELinux role label" + }, + "type": { + "type": "string", + "description": "SELinux type label" + }, + "level": { + "type": "string", + "description": "SELinux level label (e.g. 's0:c123,c456')" + } + } + }, + "seccompProfile": { + "type": "object", + "additionalProperties": false, + "description": "Seccomp profile. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.36/#seccompprofile-v1-core", + "properties": { + "type": { + "type": "string", + "enum": ["RuntimeDefault", "Unconfined", "Localhost"], + "description": "The type of seccomp profile. RuntimeDefault uses the container runtime default, Unconfined disables seccomp, Localhost references a profile on the node." + }, + "localhostProfile": { + "type": "string", + "description": "Path of the pre-configured profile on the node, relative to the kubelet's seccomp profile location. Only valid when type is Localhost." + } + }, + "required": ["type"] + }, + "windowsOptions": { + "type": "object", + "additionalProperties": false, + "description": "Windows-specific security options. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.36/#windowssecuritycontextoptions-v1-core", + "properties": { + "gmsaCredentialSpecName": { + "type": "string", + "description": "Name of the GMSA credential spec to use" + }, + "gmsaCredentialSpec": { + "type": "string", + "description": "Inline GMSA credential spec to use" + }, + "runAsUserName": { + "type": "string", + "description": "The username to run the container's process as" + }, + "hostProcess": { + "type": "boolean", + "description": "Whether the container is a Windows HostProcess container" + } + } + }, + "podSecurityContextValue": { + "type": "object", + "additionalProperties": true, + "description": "Pod-level security context (spec.template.spec.securityContext). Applies to all containers in the pod. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", + "properties": { + "runAsUser": { + "type": "integer", + "description": "The UID to run all container processes in the pod as." + }, + "runAsGroup": { + "type": "integer", + "description": "The primary GID for all container processes in the pod." + }, + "runAsNonRoot": { + "type": "boolean", + "description": "If true, the kubelet will validate that the container runs as a non-root user before starting it." + }, + "supplementalGroups": { + "type": "array", + "items": { "type": "integer" }, + "description": "A list of additional GIDs to apply to all container processes in the pod." + }, + "supplementalGroupsPolicy": { + "type": "string", + "enum": ["Merge", "Strict"], + "description": "Defines how supplementary groups are calculated. Merge (default) merges /etc/group memberships; Strict only uses fsGroup, supplementalGroups and runAsGroup." + }, + "fsGroup": { + "type": "integer", + "description": "A special supplemental group applied to all containers. Kubernetes changes the ownership of volumes to this GID." + }, + "fsGroupChangePolicy": { + "type": "string", + "enum": ["Always", "OnRootMismatch"], + "description": "Controls how Kubernetes changes ownership and permissions of volumes to match fsGroup. OnRootMismatch only changes if the root directory ownership does not match." + }, + "seLinuxOptions": { "$ref": "#/definitions/seLinuxOptions" }, + "seLinuxChangePolicy": { + "type": "string", + "enum": ["MountOption", "Recursive"], + "description": "Controls how SELinux labels are applied to volumes. MountOption uses mount options where supported; Recursive relabels all files." + }, + "seccompProfile": { "$ref": "#/definitions/seccompProfile" }, + "sysctls": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "Name of a property to set (e.g. 'kernel.shm_rmid_forced')." + }, + "value": { + "type": "string", + "description": "Value of the property." + } + }, + "required": ["name", "value"] + }, + "description": "A list of sysctls to set on the pod." + }, + "windowsOptions": { "$ref": "#/definitions/windowsOptions" } + } + }, + "containerSecurityContextValue": { + "type": "object", + "additionalProperties": true, + "description": "Container-level security context (containers[].securityContext). Applies only to the individual container and overrides pod-level settings on overlap. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", + "properties": { + "runAsUser": { + "type": "integer", + "description": "The UID to run the container's process as." + }, + "runAsGroup": { + "type": "integer", + "description": "The primary GID for the container's process." + }, + "runAsNonRoot": { + "type": "boolean", + "description": "If true, the kubelet will validate that the container runs as a non-root user before starting it." + }, + "allowPrivilegeEscalation": { + "type": "boolean", + "description": "Controls whether a process can gain more privileges than its parent process. Always true when the container is privileged or has CAP_SYS_ADMIN." + }, + "privileged": { + "type": "boolean", + "description": "If true, runs the container in privileged mode (all capabilities, host access). Strongly discouraged in production." + }, + "readOnlyRootFilesystem": { + "type": "boolean", + "description": "If true, mounts the container's root filesystem as read-only." + }, + "capabilities": { + "type": "object", + "additionalProperties": false, + "description": "Linux capabilities to add or drop. Capability names omit the CAP_ prefix (e.g. 'NET_ADMIN').", + "properties": { + "add": { + "type": "array", + "items": { "type": "string" }, + "description": "Capabilities to add, e.g. ['NET_ADMIN']." + }, + "drop": { + "type": "array", + "items": { "type": "string" }, + "description": "Capabilities to drop, e.g. ['ALL']." + } + } + }, + "seLinuxOptions": { "$ref": "#/definitions/seLinuxOptions" }, + "seccompProfile": { "$ref": "#/definitions/seccompProfile" }, + "procMount": { + "type": "string", + "enum": ["Default", "Unmasked"], + "description": "Controls the container's /proc mount. Unmasked makes masked/read-only paths writable (requires user namespaces)." + }, + "appArmorProfile": { + "type": "object", + "additionalProperties": false, + "description": "AppArmor profile for the container. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.36/#apparmorprofile-v1-core", + "properties": { + "type": { + "type": "string", + "enum": ["RuntimeDefault", "Unconfined", "Localhost"], + "description": "The type of AppArmor profile. RuntimeDefault is the default, Unconfined disables AppArmor, Localhost references a profile loaded on the node." + }, + "localhostProfile": { + "type": "string", + "description": "Name of the pre-configured profile on the node. Only valid when type is Localhost." + } + }, + "required": ["type"] + }, + "windowsOptions": { "$ref": "#/definitions/windowsOptions" } + } + }, + "podSecurityContextSpec": { + "type": "object", + "additionalProperties": false, + "properties": { + "default": { "$ref": "#/definitions/podSecurityContextValue" }, + "website": { "$ref": "#/definitions/podSecurityContextValue" }, + "docs": { "$ref": "#/definitions/podSecurityContextValue" }, + "taxonomy-service": { "$ref": "#/definitions/podSecurityContextValue" }, + "ena-submission": { "$ref": "#/definitions/podSecurityContextValue" }, + "ena-submission-list-cronjob": { "$ref": "#/definitions/podSecurityContextValue" }, + "ingest": { "$ref": "#/definitions/podSecurityContextValue" }, + "ingest-trigger": { "$ref": "#/definitions/podSecurityContextValue" }, + "keycloak": { "$ref": "#/definitions/podSecurityContextValue" }, + "silo": { "$ref": "#/definitions/podSecurityContextValue" }, + "lapis": { "$ref": "#/definitions/podSecurityContextValue" }, + "backend": { "$ref": "#/definitions/podSecurityContextValue" }, + "preprocessing": { "$ref": "#/definitions/podSecurityContextValue" }, + "minio": { "$ref": "#/definitions/podSecurityContextValue" }, + "keycloak-database": { "$ref": "#/definitions/podSecurityContextValue" }, + "database": { "$ref": "#/definitions/podSecurityContextValue" }, + "raw-reads-processing": { "$ref": "#/definitions/podSecurityContextValue" } + } + }, + "containerSecurityContextSpec": { + "type": "object", + "additionalProperties": false, + "properties": { + "default": { "$ref": "#/definitions/containerSecurityContextValue" }, + "website": { "$ref": "#/definitions/containerSecurityContextValue" }, + "docs": { "$ref": "#/definitions/containerSecurityContextValue" }, + "taxonomy-service": { "$ref": "#/definitions/containerSecurityContextValue" }, + "download-taxonomy-db": { "$ref": "#/definitions/containerSecurityContextValue" }, + "ena-submission": { "$ref": "#/definitions/containerSecurityContextValue" }, + "ena-submission-flyway": { "$ref": "#/definitions/containerSecurityContextValue" }, + "ena-submission-list-cronjob": { "$ref": "#/definitions/containerSecurityContextValue" }, + "ingest": { "$ref": "#/definitions/containerSecurityContextValue" }, + "ingest-init": { "$ref": "#/definitions/containerSecurityContextValue" }, + "ingest-trigger": { "$ref": "#/definitions/containerSecurityContextValue" }, + "keycloak": { "$ref": "#/definitions/containerSecurityContextValue" }, + "keycloak-theme-prep": { "$ref": "#/definitions/containerSecurityContextValue" }, + "silo": { "$ref": "#/definitions/containerSecurityContextValue" }, + "lapis": { "$ref": "#/definitions/containerSecurityContextValue" }, + "silo-importer": { "$ref": "#/definitions/containerSecurityContextValue" }, + "backend": { "$ref": "#/definitions/containerSecurityContextValue" }, + "raw-reads-processing": { "$ref": "#/definitions/containerSecurityContextValue" }, + "preprocessing": { "$ref": "#/definitions/containerSecurityContextValue" }, + "minio": { "$ref": "#/definitions/containerSecurityContextValue" }, + "keycloak-database": { "$ref": "#/definitions/containerSecurityContextValue" }, + "database": { "$ref": "#/definitions/containerSecurityContextValue" }, + "config-processor": { "$ref": "#/definitions/containerSecurityContextValue" } + } } }, "type": "object", @@ -2060,6 +2313,18 @@ } } }, + "podSecurityContext": { + "groups": ["general"], + "type": "object", + "$ref": "#/definitions/podSecurityContextSpec", + "description": "Pod-level security context values keyed by workload name. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/." + }, + "containerSecurityContext": { + "groups": ["general"], + "type": "object", + "$ref": "#/definitions/containerSecurityContextSpec", + "description": "Container-level security context values keyed by workload or container name. Init containers with dedicated keys can be configured independently. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/." + }, "secrets": { "description": "TODO" }, diff --git a/kubernetes/loculus/values.yaml b/kubernetes/loculus/values.yaml index 5c08c71c44..6093624d03 100644 --- a/kubernetes/loculus/values.yaml +++ b/kubernetes/loculus/values.yaml @@ -7,6 +7,14 @@ podScheduling: tolerations: [] affinity: {} +# Optional pod-level securityContext. Supports a `default` entry applied to all workloads, +# plus per-component overrides (e.g. backend, silo, keycloak). A component-specific entry +# fully replaces `default`. To change a single field for one component, specify the +# complete security context for it. +podSecurityContext: {} +# Optional container-level securityContext. Same structure and override behavior as podSecurityContext above. +containerSecurityContext: {} + localHost: localhost robotsNoindexHeader: false seqSets: