ehough / docker-nfs-server

A lightweight, robust, flexible, and containerized NFS server.
https://hub.docker.com/r/erichough/nfs-server/
GNU General Public License v3.0
669 stars 221 forks source link

No privs to container, how to mount before starting? #70

Open gsxryan opened 2 years ago

gsxryan commented 2 years ago

I would like to remove the following requirements to better secure the host.

--cap-add SYS_MODULE \
--cap-add SYS_ADMIN \

Would it be possible to mount the shares prior to starting the container, rather than mounting them after startup? I'm investigating this now, but have a ways to go to fully understand.

First command at hand: mount('rpc_pipefs','/var/lib/nfs/rpc_pipefs','rpc_pipefs',0x00008000,'(null)')

schilling-ryan commented 2 years ago

I know this is a bit old, and you've probably already found an answer but I figured I'd at least comment on it. From what I understand, SYS_ADMIN is the only capability required to perform mounts within containers. In newer kernels (specifically Ubuntu or variants with AppArmor) SYS_ADMIN is no longer sufficient to perform mounts and you either need --privileged or --security-opt apparmor:unconfined. Neither of those are great options as they basically open you up to privilege escalation exploits but there's no other way to allow this aside from doing the same configuration in AppArmor itself.

In your case, consider the container as either running or not running. There is no in-between state. So if you do not want to grant the appropriate permissions within the container to perform the mounting(i.e. when the container is running), then what you're thinking of is performing the mount on the container's host(i.e. when the container is not running yet) and then doing a simple mapping of "a local directory"(i.e. the one you mounted locally on the container host that is being shared by an NFS) into your container's directory.

gsxryan commented 2 years ago

Hello Ryan, It is old issue, but I've not been able to prioritize and find a solution yet, so thank you for your help.

I have a rough understanding, see if i'm following correctly; 1) What are all the mount points that require escalated permissions? I'm trying to identify all of them.
I commented out the boot_main_mounts to prevent mount at entrypoint.sh, and since it looks like they should mount in fstab on boot. But still will not run without --priv. I also commented out init_runtime_assertions to prevent the --priv checks.

The Script detects

rpc.nfsd: Unable to access /proc/fs/nfsd errno 2 (No such file or directory).
Please try, as root, 'mount -t nfsd nfsd /proc/fs/nfsd' and then restart rpc.nfsd to correct the problem

So it appears the fstab commands are not working as intended.

Does fstab (on start) also need privs to do own filesystem? or am i missing some other mount or action that requires priv? Dockerfile: echo "rpc_pipefs /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0" >> /etc/fstab && \ echo "nfsd /proc/fs/nfsd nfsd defaults 0 0" >> /etc/fstab

entrypoint.sh

boot_main_mounts() {

  # http://wiki.linux-nfs.org/wiki/index.php/Nfsv4_configuration
  boot_helper_mount "$MOUNT_PATH_RPC_PIPEFS"
  boot_helper_mount "$MOUNT_PATH_NFSD"
}

Translates to; mount -t rpc_pipefs /var/lib/nfs/rpc_pipefs -vvv mount -t nfsd /proc/fs/nfsd -vvv

2) How to mount those while the container is not running? Considering Dockerfile (volume?) - offline power down (move mount and fstab to methods prior to booting) fstab - on boot powering up entrypoint.sh mount - post boot powered up

3) Modify the run command to map the paths mounted.

schilling-ryan commented 2 years ago

Hey, sorry for the delay, I've given up using this as it did not accomplish what I was originally intending. I was attempting to containerize my NFS and use it as a sort of CSI driver replacement. The issue I had was the references to the nfs-server container that was hosting the NFS shares seemed to be unknown to the host (because Docker knows Docker DNS but the host itself doesn't) so all of the services/containers would fail to start citing a bad mount path. I have rolled the NFS back to the host level and just cut out all the permissions for the directories and opened them wide (nobody:nogroup and 777) and then set mounted the shares on my swarm nodes and changed the Docker compose config to point to the shares (which are mounted identically on all hosts). This works well enough for me, and originally I was not wanting to do this because it seems like a giant security issue setting permissions in this way...but I was ignoring the fact that I would otherwise have a container running as user 0 with high privileges, so there was really not much of a trade-off.

To your questions though, I am not sure how to get around this limitation. It seems the problem is with the permissions required to use the nfs-kernel-server module. Something with permissions limitations imposed by Docker as a security measure that is unique to the way NFS and fstab mount stuff. I really didn't troubleshoot this any more after I ran into this issue and started looking at alternatives but my search kept turning up ones that required K8s and I don't run K8s so most of those were out of the question and by the time I got back to this I just decided to retry NFS (for a 3rd time) straight on the hosts.