chore(immich): hardening of security according to audit report by Polaris

This commit is contained in:
Tommy 2024-11-11 21:11:58 +01:00
parent 556acce1b2
commit d3dca67841
Signed by: tommy
SSH key fingerprint: SHA256:1LWgQT3QPHIT29plS8jjXc3S1FcE/4oGvsx3Efxs6Uc
6 changed files with 204 additions and 24 deletions

View file

@ -2,10 +2,11 @@ apiVersion: v2
name: immich name: immich
description: | description: |
High-performance self-hosted photo and video management High-performance self-hosted photo and video management
# renovate: image=ghcr.io/immich-app/immich-server
appVersion: 1.105.1 appVersion: 1.105.1
type: application type: application
icon: https://avatars.githubusercontent.com/u/109746326?s=200&v=4 icon: https://avatars.githubusercontent.com/u/109746326?s=200&v=4
version: 0.1.16 version: 1.0.0
maintainers: maintainers:
- name: Tommy Skaug - name: Tommy Skaug
email: tommy@skaug.me email: tommy@skaug.me

View file

@ -0,0 +1,78 @@
config:
externalUrl: https://photos.example.com/
machineLearningUrl: http://immich-machine-learning.home.svc.cluster.local:3003
image:
repository: ghcr.io/immich-app/immich-server
envSecretName: immich-secret
library:
persistence:
existingClaim: immich
configuration:
trash:
enabled: false
days: 30
storageTemplate:
enabled: true
template: "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}"
microservices:
securityContext: {}
resources:
limits:
memory: "3Gi"
cpu: "1000m"
requests:
cpu: 100m
memory: 100Mi
server:
securityContext: {}
resources:
limits:
memory: "3Gi"
cpu: "1000m"
requests:
cpu: 100m
memory: 100Mi
machineLearning:
persistence:
accessMode: ReadWriteOnce
size: 5Gi
image:
repository: ghcr.io/immich-app/immich-machine-learning
tag: v1.120.1
securityContext: {}
resources:
limits:
memory: "3Gi"
cpu: "1000m"
requests:
cpu: 100m
memory: 100Mi
initContainers:
dbInit:
image:
repository: ghcr.io/onedr0p/postgres-init
tag: "16"
existingSecretName: immich-postgres-init-secret
pgvecto:
image:
repository: tensorchord/pgvecto-rs
tag: "pg16-v0.2.1-rootless"
existingSecretName: immich-postgres-init-secret
metrics:
enabled: true
port: 9001
redis:
host: dragonfly.databases.svc.cluster.local
port: 6397
postgres:
host: postgres-pgvectors-rw.databases.svc.cluster.local

View file

@ -1,4 +1,3 @@
---
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
metadata: metadata:
@ -9,22 +8,37 @@ spec:
template: template:
spec: spec:
restartPolicy: Never restartPolicy: Never
automountServiceAccountToken: false
priorityClassName: "high-priority"
containers: containers:
- name: general-db-init - name: general-db-init
image: "{{ .Values.initContainers.dbInit.image.repository }}:{{ .Values.initContainers.dbInit.image.tag }}" image: "{{ .Values.initContainers.dbInit.image.repository }}:{{ .Values.initContainers.dbInit.image.tag }}"
imagePullPolicy: IfNotPresent
env: env:
- name: INIT_POSTGRES_HOST - name: INIT_POSTGRES_HOST
value: {{ .Values.postgres.host }} value: {{ .Values.postgres.host }}
envFrom: envFrom:
- secretRef: - secretRef:
name: {{ .Values.initContainers.dbInit.existingSecretName }} name: {{ .Values.initContainers.dbInit.existingSecretName }}
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
- name: pgvecto-db-init - name: pgvecto-db-init
command: [ "bin/sh", "-c", "psql -a -f /initdb/create-extensions.sql" ] command: [ "bin/sh", "-c", "psql -a -f /initdb/create-extensions.sql" ]
image: "{{ .Values.initContainers.pgvecto.image.repository }}:{{ .Values.initContainers.pgvecto.image.tag }}" image: "{{ .Values.initContainers.pgvecto.image.repository }}:{{ .Values.initContainers.pgvecto.image.tag }}"
imagePullPolicy: IfNotPresent
volumeMounts: volumeMounts:
- name: pgvector-initdb - name: pgvector-initdb
mountPath: /initdb mountPath: /initdb
readOnly: false readOnly: true
env: env:
- name: PGPASSWORD - name: PGPASSWORD
valueFrom: valueFrom:
@ -40,6 +54,17 @@ spec:
key: INIT_POSTGRES_DBNAME key: INIT_POSTGRES_DBNAME
- name: PGHOST - name: PGHOST
value: {{ .Values.postgres.host }} value: {{ .Values.postgres.host }}
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
volumes: volumes:
- name: pgvector-initdb - name: pgvector-initdb
configMap: configMap:

View file

@ -1,4 +1,3 @@
---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
@ -17,14 +16,30 @@ spec:
labels: labels:
app: {{ include "immich.fullname" . }}-machine-learning app: {{ include "immich.fullname" . }}-machine-learning
spec: spec:
priorityClassName: "high-priority"
automountServiceAccountToken: false
topologySpreadConstraints:
- maxSkew: 1
topologyKey: "topology.kubernetes.io/zone"
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: {{ include "immich.fullname" . }}-machine-learning
securityContext: securityContext:
{{- toYaml .Values.machineLearning.securityContext | nindent 8 }} runAsUser: 1000
runAsNonRoot: true
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
containers: containers:
- name: immich-machine-learning - name: immich-machine-learning
env: env:
{{- include "immich.envs" . | nindent 10 }} {{- include "immich.envs" . | nindent 10 }}
image: {{ .Values.machineLearning.image.repository }}:{{ .Values.machineLearning.image.tag }} image: {{ .Values.machineLearning.image.repository }}:{{ .Values.machineLearning.image.tag }}
imagePullPolicy: IfNotPresent imagePullPolicy: Always
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
livenessProbe: livenessProbe:
failureThreshold: 3 failureThreshold: 3
httpGet: httpGet:
@ -35,9 +50,9 @@ spec:
successThreshold: 1 successThreshold: 1
timeoutSeconds: 1 timeoutSeconds: 1
ports: ports:
- containerPort: 3003 - containerPort: 3003
name: http name: http
protocol: TCP protocol: TCP
readinessProbe: readinessProbe:
failureThreshold: 3 failureThreshold: 3
httpGet: httpGet:
@ -52,10 +67,20 @@ spec:
terminationMessagePath: /dev/termination-log terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File terminationMessagePolicy: File
volumeMounts: volumeMounts:
- mountPath: /cache - mountPath: /cache
name: cache name: cache
serviceAccountName: {{ include "immich.fullname" . }} serviceAccountName: {{ include "immich.fullname" . }}
volumes: volumes:
- name: cache - name: cache
persistentVolumeClaim: persistentVolumeClaim:
claimName: {{ include "immich.fullname" . }}-machine-learning-cache claimName: {{ include "immich.fullname" . }}-machine-learning-cache
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "immich.fullname" . }}-machine-learning-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: {{ include "immich.fullname" . }}-machine-learning

View file

@ -1,4 +1,3 @@
---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
@ -15,9 +14,20 @@ spec:
labels: labels:
app: {{ include "immich.fullname" . }}-microservices app: {{ include "immich.fullname" . }}-microservices
spec: spec:
priorityClassName: "high-priority"
automountServiceAccountToken: false
topologySpreadConstraints:
- maxSkew: 1
topologyKey: "topology.kubernetes.io/zone"
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: {{ include "immich.fullname" . }}-microservices
securityContext: securityContext:
{{- toYaml .Values.microservices.securityContext | nindent 8 }} runAsUser: 1000
automountServiceAccountToken: true runAsNonRoot: true
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
containers: containers:
- name: immich-microservices - name: immich-microservices
args: args:
@ -27,7 +37,11 @@ spec:
env: env:
{{- include "immich.envs" . | nindent 10 }} {{- include "immich.envs" . | nindent 10 }}
image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }} image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }}
imagePullPolicy: IfNotPresent imagePullPolicy: Always
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
livenessProbe: livenessProbe:
failureThreshold: 3 failureThreshold: 3
periodSeconds: 10 periodSeconds: 10
@ -65,3 +79,13 @@ spec:
- name: library - name: library
persistentVolumeClaim: persistentVolumeClaim:
claimName: {{ .Values.library.persistence.existingClaim }} claimName: {{ .Values.library.persistence.existingClaim }}
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "immich.fullname" . }}-microservices-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: {{ include "immich.fullname" . }}-microservices

View file

@ -1,4 +1,3 @@
---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
@ -15,8 +14,22 @@ spec:
labels: labels:
app: {{ include "immich.fullname" . }}-server app: {{ include "immich.fullname" . }}-server
spec: spec:
priorityClassName: "high-priority"
automountServiceAccountToken: false
topologySpreadConstraints:
- maxSkew: 1
topologyKey: "topology.kubernetes.io/zone"
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: {{ include "immich.fullname" . }}-server
securityContext: securityContext:
{{- toYaml .Values.server.securityContext | nindent 8 }} runAsUser: 1000
runAsNonRoot: true
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
containers: containers:
- name: immich-server - name: immich-server
args: args:
@ -26,7 +39,11 @@ spec:
env: env:
{{- include "immich.envs" . | nindent 10 }} {{- include "immich.envs" . | nindent 10 }}
image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }} image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }}
imagePullPolicy: IfNotPresent imagePullPolicy: Always
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
livenessProbe: livenessProbe:
failureThreshold: 3 failureThreshold: 3
httpGet: httpGet:
@ -64,3 +81,13 @@ spec:
- name: library - name: library
persistentVolumeClaim: persistentVolumeClaim:
claimName: {{ .Values.library.persistence.existingClaim }} claimName: {{ .Values.library.persistence.existingClaim }}
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "immich.fullname" . }}-server-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: {{ include "immich.fullname" . }}-server