diff --git a/charts/self-host/README.md b/charts/self-host/README.md index 27c49a5c0..48f93ee29 100644 --- a/charts/self-host/README.md +++ b/charts/self-host/README.md @@ -285,6 +285,48 @@ component: You can override the image repository for any component. +#### Extra Volumes + +Every long-running service under `component.` accepts `extraVolumeMounts` (added to the container) and `extraVolumes` (added to the pod). The pre-/post-install hook and job pods share a single `jobs.extraVolumeMounts` / `jobs.extraVolumes` pair, and the database (MSSQL) pod uses `database.extraVolumeMounts` / `database.extraVolumes`. All default to `[]`, so leaving them unset changes nothing. + +This is useful for hardened deployments that set `readOnlyRootFilesystem: true`, where containers need writable scratch space (typically `/tmp`) mounted as an `emptyDir`. Supply the volume where it is needed instead of patching the chart: + +```yaml +# Writable /tmp for the hardened app containers +component: + api: + securityContext: + readOnlyRootFilesystem: true + extraVolumeMounts: + - name: tmp + mountPath: /tmp + extraVolumes: + - name: tmp + emptyDir: {} + +# Writable /tmp for every pre-/post-install hook and job pod +jobs: + securityContext: + readOnlyRootFilesystem: true + extraVolumeMounts: + - name: tmp + mountPath: /tmp + extraVolumes: + - name: tmp + emptyDir: {} + +# Writable scratch for the MSSQL pod +database: + extraVolumeMounts: + - name: mssql-secrets + mountPath: /var/opt/mssql/secrets + extraVolumes: + - name: mssql-secrets + emptyDir: {} +``` + +`extraVolumes` accepts any Kubernetes volume source (`emptyDir`, `configMap`, `secret`, `persistentVolumeClaim`, `csi`, etc.), and each `extraVolumeMounts` entry must reference a volume `name` defined in the corresponding `extraVolumes` list. + #### Raw Manifests Files This chart allows you to include other Kubernetes manifest files either pre- or post-install. To do this, update the `rawManifests` section of the chart diff --git a/charts/self-host/templates/mssql.yaml b/charts/self-host/templates/mssql.yaml index 4595b0d44..b49d46e50 100644 --- a/charts/self-host/templates/mssql.yaml +++ b/charts/self-host/templates/mssql.yaml @@ -104,6 +104,9 @@ spec: mountPath: "/mnt/secrets-store" readOnly: true {{- end }} + {{- with .Values.database.extraVolumeMounts }} +{{ toYaml . | indent 12 }} + {{- end }} livenessProbe: tcpSocket: port: mssql @@ -148,6 +151,9 @@ spec: volumeAttributes: secretProviderClass: {{ .Values.secrets.secretProviderClass }} {{- end }} + {{- with .Values.database.extraVolumes }} +{{ toYaml . | indent 8 }} + {{- end }} --- kind: Service diff --git a/charts/self-host/templates/post-delete-hook.yaml b/charts/self-host/templates/post-delete-hook.yaml index 1d4cc3e7e..0f477cb8b 100644 --- a/charts/self-host/templates/post-delete-hook.yaml +++ b/charts/self-host/templates/post-delete-hook.yaml @@ -83,5 +83,13 @@ spec: resources: {{- toYaml .Values.jobs.cleanup.resources | nindent 10 }} {{- end }} + {{- with .Values.jobs.extraVolumeMounts }} + volumeMounts: +{{ toYaml . | indent 8 }} + {{- end }} restartPolicy: Never + {{- with .Values.jobs.extraVolumes }} + volumes: +{{ toYaml . | indent 6 }} + {{- end }} {{- end }} diff --git a/charts/self-host/templates/post-install-db-migrator-job.yaml b/charts/self-host/templates/post-install-db-migrator-job.yaml index 5f47c9ce0..2c137ba2a 100644 --- a/charts/self-host/templates/post-install-db-migrator-job.yaml +++ b/charts/self-host/templates/post-install-db-migrator-job.yaml @@ -98,6 +98,9 @@ spec: - name: mssql-data mountPath: /db {{- end }} + {{- with .Values.jobs.extraVolumeMounts }} +{{ toYaml . | indent 10 }} + {{- end }} containers: - name: migrate-db env: @@ -129,6 +132,9 @@ spec: mountPath: "/mnt/secrets-store" readOnly: true {{- end }} + {{- with .Values.jobs.extraVolumeMounts }} +{{ toYaml . | indent 8 }} + {{- end }} {{- if or ( not .Values.database.enabled ) ( and .Values.database.enabled .Release.IsUpgrade ) }} args: [ "-f", "DbScripts_transition", "-r"] {{- end }} @@ -149,4 +155,7 @@ spec: volumeAttributes: secretProviderClass: {{ .Values.secrets.secretProviderClass }} {{- end }} + {{- with .Values.jobs.extraVolumes }} +{{ toYaml . | indent 8 }} + {{- end }} {{- end }} diff --git a/charts/self-host/templates/pre-install-db-migrator-job.yaml b/charts/self-host/templates/pre-install-db-migrator-job.yaml index 172597ed4..8957f1d7a 100644 --- a/charts/self-host/templates/pre-install-db-migrator-job.yaml +++ b/charts/self-host/templates/pre-install-db-migrator-job.yaml @@ -94,6 +94,9 @@ spec: mountPath: "/mnt/secrets-store" readOnly: true {{- end }} + {{- with .Values.jobs.extraVolumeMounts }} +{{ toYaml . | indent 8 }} + {{- end }} restartPolicy: Never volumes: - name: migrator-extract-dir @@ -106,4 +109,7 @@ spec: volumeAttributes: secretProviderClass: {{ .Values.secrets.secretProviderClass }} {{- end }} + {{- with .Values.jobs.extraVolumes }} +{{ toYaml . | indent 8 }} + {{- end }} {{- end }} diff --git a/charts/self-host/templates/pre-install-job.yaml b/charts/self-host/templates/pre-install-job.yaml index 092967a0d..09aa71219 100644 --- a/charts/self-host/templates/pre-install-job.yaml +++ b/charts/self-host/templates/pre-install-job.yaml @@ -90,6 +90,9 @@ spec: volumeMounts: - name: temp mountPath: "/bitwarden" + {{- with .Values.jobs.extraVolumeMounts }} +{{ toYaml . | indent 8 }} + {{- end }} {{- end }} containers: - name: create-resources @@ -117,9 +120,15 @@ spec: volumeMounts: - name: temp mountPath: "/bitwarden" + {{- with .Values.jobs.extraVolumeMounts }} +{{ toYaml . | indent 8 }} + {{- end }} restartPolicy: Never volumes: - name: temp emptyDir: medium: Memory + {{- with .Values.jobs.extraVolumes }} +{{ toYaml . | indent 8 }} + {{- end }} {{- end }} diff --git a/charts/self-host/templates/pre-install-secret-sql.yaml b/charts/self-host/templates/pre-install-secret-sql.yaml index 98b087069..e45b57b50 100644 --- a/charts/self-host/templates/pre-install-secret-sql.yaml +++ b/charts/self-host/templates/pre-install-secret-sql.yaml @@ -93,6 +93,9 @@ spec: mountPath: "/mnt/secrets-store" readOnly: true {{- end }} + {{- with .Values.jobs.extraVolumeMounts }} +{{ toYaml . | indent 8 }} + {{- end }} restartPolicy: Never volumes: - name: temp @@ -106,4 +109,7 @@ spec: volumeAttributes: secretProviderClass: {{ .Values.secrets.secretProviderClass }} {{- end }} + {{- with .Values.jobs.extraVolumes }} +{{ toYaml . | indent 8 }} + {{- end }} {{- end }} diff --git a/charts/self-host/tests/hook_extras_test.yaml b/charts/self-host/tests/hook_extras_test.yaml new file mode 100644 index 000000000..faca71999 --- /dev/null +++ b/charts/self-host/tests/hook_extras_test.yaml @@ -0,0 +1,237 @@ +suite: test hook/job and mssql extraVolumeMounts and extraVolumes +templates: + - templates/helpers.tpl + - templates/pre-install-job.yaml + - templates/pre-install-secret-sql.yaml + - templates/pre-install-db-migrator-job.yaml + - templates/post-install-db-migrator-job.yaml + - templates/post-delete-hook.yaml + - templates/mssql.yaml + +tests: + # pre-install-job (setup) - jobs.* on the create-resources container and + # the generate-identity-cert init container + - it: pre-install-job - should render jobs.extraVolumeMounts on both containers + template: templates/pre-install-job.yaml + set: + secrets.identityCertificate.generate: true + jobs.extraVolumeMounts[0].mountPath: /etc/custom/config + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - contains: + path: spec.template.spec.initContainers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + + - it: pre-install-job - should render jobs.extraVolumes on the pod + template: templates/pre-install-job.yaml + set: + secrets.identityCertificate.generate: true + jobs.extraVolumes[0].configMap.name: extra-configmap + asserts: + - contains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + - it: pre-install-job - should not render extra volumes when empty + template: templates/pre-install-job.yaml + set: + secrets.identityCertificate.generate: true + asserts: + - notContains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - notContains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + # pre-install-secret-sql (secret) - jobs.* on the create-resources container + - it: pre-install-secret-sql - should render jobs.extraVolumeMounts and extraVolumes + template: templates/pre-install-secret-sql.yaml + set: + database.enabled: true + jobs.extraVolumeMounts[0].mountPath: /etc/custom/config + jobs.extraVolumes[0].configMap.name: extra-configmap + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - contains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + - it: pre-install-secret-sql - should not render extra volumes when empty + template: templates/pre-install-secret-sql.yaml + set: + database.enabled: true + asserts: + - notContains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + + # pre-install-db-migrator-job - jobs.* on the migrate-db container + - it: pre-install-db-migrator-job - should render jobs.extraVolumeMounts and extraVolumes + template: templates/pre-install-db-migrator-job.yaml + set: + jobs.extraVolumeMounts[0].mountPath: /etc/custom/config + jobs.extraVolumes[0].configMap.name: extra-configmap + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - contains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + - it: pre-install-db-migrator-job - should not render extra volumes when empty + template: templates/pre-install-db-migrator-job.yaml + asserts: + - notContains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + + # post-install-db-migrator-job - jobs.* on both the wait-for-db init + # container and the migrate-db container + - it: post-install-db-migrator-job - should render jobs.extraVolumeMounts on both containers + template: templates/post-install-db-migrator-job.yaml + set: + database.enabled: true + jobs.extraVolumeMounts[0].mountPath: /etc/custom/config + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - contains: + path: spec.template.spec.initContainers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + + - it: post-install-db-migrator-job - should render jobs.extraVolumes on the pod + template: templates/post-install-db-migrator-job.yaml + set: + database.enabled: true + jobs.extraVolumes[0].configMap.name: extra-configmap + asserts: + - contains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + - it: post-install-db-migrator-job - should not render extra volumes when empty + template: templates/post-install-db-migrator-job.yaml + set: + database.enabled: true + asserts: + - notContains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - notContains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + # post-delete-hook (cleanup) - jobs.* on the delete-resources container; + # this template has no volumeMounts/volumes by default + - it: post-delete-hook - should render jobs.extraVolumeMounts and extraVolumes + template: templates/post-delete-hook.yaml + set: + jobs.cleanup.enabled: true + jobs.extraVolumeMounts[0].mountPath: /etc/custom/config + jobs.extraVolumes[0].configMap.name: extra-configmap + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - contains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + - it: post-delete-hook - should not render volumeMounts or volumes when empty + template: templates/post-delete-hook.yaml + set: + jobs.cleanup.enabled: true + asserts: + - notExists: + path: spec.template.spec.containers[0].volumeMounts + documentIndex: 0 + - notExists: + path: spec.template.spec.volumes + documentIndex: 0 + + # mssql - database.* on the mssql container and pod + - it: mssql - should render database.extraVolumeMounts and extraVolumes + template: templates/mssql.yaml + set: + database.enabled: true + database.extraVolumeMounts[0].mountPath: /etc/custom/config + database.extraVolumes[0].configMap.name: extra-configmap + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - contains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 + + - it: mssql - should not render extra volumes when empty + template: templates/mssql.yaml + set: + database.enabled: true + asserts: + - notContains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /etc/custom/config + documentIndex: 0 + - notContains: + path: spec.template.spec.volumes + content: + configMap: + name: extra-configmap + documentIndex: 0 diff --git a/charts/self-host/values.schema.json b/charts/self-host/values.schema.json index 68852002b..f739b4c80 100644 --- a/charts/self-host/values.schema.json +++ b/charts/self-host/values.schema.json @@ -2430,6 +2430,22 @@ "title": "enabled", "type": "boolean" }, + "extraVolumeMounts": { + "description": "Extra volume mounts to add to the MSSQL container", + "items": { + "required": [] + }, + "title": "extraVolumeMounts", + "type": "array" + }, + "extraVolumes": { + "description": "Extra volumes to add to the MSSQL pod", + "items": { + "required": [] + }, + "title": "extraVolumes", + "type": "array" + }, "image": { "description": "Image repository, tag, and pull policy", "properties": { @@ -3473,6 +3489,22 @@ "title": "db", "type": "object" }, + "extraVolumeMounts": { + "description": "Extra volume mounts to add to the pre- and post-install hook/job containers", + "items": { + "required": [] + }, + "title": "extraVolumeMounts", + "type": "array" + }, + "extraVolumes": { + "description": "Extra volumes to add to the pre- and post-install hook/job pods", + "items": { + "required": [] + }, + "title": "extraVolumes", + "type": "array" + }, "podSecurityContext": { "required": [], "title": "podSecurityContext", diff --git a/charts/self-host/values.yaml b/charts/self-host/values.yaml index b52980d37..0de6ae7cf 100644 --- a/charts/self-host/values.yaml +++ b/charts/self-host/values.yaml @@ -887,6 +887,11 @@ jobs: podSecurityContext: {} + # Extra volume mounts to add to the pre- and post-install hook/job containers + extraVolumeMounts: [] + # Extra volumes to add to the pre- and post-install hook/job pods + extraVolumes: [] + db: preInstallMigrator: # Additional job labels @@ -1052,6 +1057,10 @@ database: podSecurityContext: {} # Run the pod under a service account you create. This is especially useful for OpenShift deployments podServiceAccount: "" + # Extra volume mounts to add to the MSSQL container + extraVolumeMounts: [] + # Extra volumes to add to the MSSQL pod + extraVolumes: [] # You can specify raw Kubernetes manifests that will be applied before or after the base Helm install. # Please see the chart README in GitHub for more information and examples.