Running pgAdmin4 on certain kubernetes distributions that includes security policies like OpenShift 'restricted-v2' SCC or 'restricted' Pod Security Standard can be a real pain and difficult even if you are very experienced with kubernetes and security concepts of k8s.
Most people will find themselves either giving some privileges to their container or using some custom made container image or giving up.
It is true that pgAdmin4 container is not well suited for DevOps security standards.
Lets get to the practical needs to run it.
First of all, the pgAdmin4 container was running as predefined user 'pgadmin' by default and I have commited to official pgAdmin4 Dockerfile (PR) to change it to user 5050 instead (pgadmin UID == 5050), because if k8s securityContext runAsNonRoot=true is set, k8s wouldn't know what uid the user would run with by reading the image's metadata which will result in CreateContainerConfigError. Implementation since pgAdmin4 v9.4.0 which doesn't exist at the time im writing this but tag 'snapshot' can be used instead.
I will number the things we have to handle to run this container securely
1. Change listen port to higher than 1023 (Must if using OpenShift or choosing the second option in section 7)
2. Disable postfix service (If you don't disable it, the application will throw a warning but won't crash)
3. Writing pgadmin data to /var/lib/pgadmin during runtime (Not a must if running as user 5050 and readOnlyFileSystem=false is set, otherwise a must)
4. Writing logs to /var/log/pgadmin during runtime (Not a must if running as user 5050 and readOnlyFileSystem=false is set, otherwise a must)
5. Writing cache to /tmp during runtime (Must only if using securityContext readOnlyFileSystem=true)
6. /pgadmin4/config_distro.py file is getting overriden during runtime, (Not a must if running as user 5050 and readOnlyFileSystem=false is set, otherwise a must)
7. Unlock the usage of 'python3' CLI (/venv/bin/python3: Operation not permitted) error. (2 ways, depends on your security policy)
Lets look at each of them
1. Probably the easiest along the next one, adding the next environment variable to your pod. PGADMIN_LISTEN_PORT="8080"
env: - name: PGADMIN_LISTEN_PORT value: "8080"
env: - name: PGADMIN_DISABLE_POSTFIX value: "true"
volumes:
- name: pgadmin-data
emptyDir: {}
volumeMounts: - name: pgadmin-data mountPath: /var/lib/pgadmin
volumes:
- name: empty-dir
emptyDir: {}
volumeMounts: - name: empty-dir mountPath: /var/log/pgadmin subPath: logs - name: empty-dir mountPath: /tmp subPath: tmp
volumes:
- name empty-dir
emptyDir: {}
initContainers:
- name: modify-config-distro-py-permissions
workingDir: /emptydir
command: ["sh", "-x", "-c"]
args: ["cp /pgadmin4/config_distro.py . && chmod 777 config_distro.py"]
image: docker.io/dpage/pgadmin4:<MAKE SURE ITS THE SAME IMAGE AS THE ORIGINAL CONTAINER>
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
seLinuxOptions: {}
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: empty-dir
mountPath: /emptydir
containers:
- volumeMounts
- name: empty-dir
mountPath: /pgadmin4/config_distro.py
subPath: config_distro.py
...
...
securityContext:
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
initContainers:
- name: unset-python3-cli-net-cap
workingDir: /emptydir
command: ["sh", "-x", "-c"]
args: ["ls /usr/bin/python3.* | sort -V -r | head -n 1 | xargs -I {} cp {} python3"]
image: docker.io/dpage/pgadmin4:<MAKE SURE ITS THE SAME IMAGE AS THE ORIGINAL CONTAINER>
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
seLinuxOptions: {}
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: empty-dir
mountPath: /emptydir
containers:
- volumeMounts:
- name: empty-dir
mountPath: /usr/bin/python3
subPath python3
...
...
kubectl create -f -n YOUR_NAMESPACE