Skip to content

Security posture ​

The backup pods run privileged with SYS_ADMIN (node backups also mount the host / read-only). This is required to read arbitrary source paths and mount FUSE. Keep the Borg UI Ingress restricted to trusted networks — it can reach every repository.

The Borg UI server is privileged by default too, for FUSE: server-side backups of SSH sources, cloud mirrors of SSH repositories and "Mount archive" mount through it. containerd lets a container open /dev/fuse only when it is privileged or a device plugin assigned the device; mounting /dev/fuse as a hostPath is not enough. Two values take the privilege away:

ValuesUI container
default (borgUI.fuse.enabled: true)privileged: true
borgUI.fuse.deviceResource: squat.ai/fuse (the resource your FUSE device plugin advertises, e.g. generic-device-plugin)not privileged; one FUSE device, SYS_ADMIN, privilege escalation for fusermount3, AppArmor unconfined
borgUI.fuse.enabled: falsenot privileged, no privilege escalation, no FUSE; the three features above fail, and so does sudo in the container (package install commands such as sudo apt-get)

Unprivileged, the container keeps CHOWN, DAC_OVERRIDE, FOWNER, SETGID and SETUID: its entrypoint prepares /data as root and then drops to the borg user. A borgUI.containerSecurityContext you set replaces all of this.

With node.datastoreSnapshot the node archives hold every Secret of the cluster, and with kubeadm its certificate authority's keys: whoever can read the repository and has its passphrase holds the cluster, and in an authenticated* or none repository whoever can read it.

With node.sqlite the node pods get a ServiceAccount of their own that may read the listed claims and all PersistentVolumes, nothing else; the files they copy are ones they could read through the host root already.

The repository server is the exception: unprivileged, no capabilities, read-only root filesystem. It shares the ssh Secret with the backup pods, so those pods can read its host key; keep ssh_host_ed25519_key out of the Secret of a release that does not run the server. All clients are served by one user: what keeps them apart is the directory their key is bound to, not file ownership.

Distributed under the AGPL-3.0-only license.