Docker bind-mount security issues


Recommended Posts

I'm running a jenkins server for ci/cd in a docker container based on alpine.  The jenkins docker runs processes as 1000, which conflicts with my users.  I take that as a base for my own image to add other stuff I need, so in my image I use usermod and such to change the "jenkins" user to 1006, which won't conflict with my users.  I also create a group jenkins-data-users with gid=2000 and assign that as the primary group for jenkins.

On my unraid host, I have the jenkins-data-users group with gid=2000 and uid 1006 is jenkins-docker.  I have added myself ("paddy" in the listings below) to the jenkins-data-users group.  And if it matters, I'm not even sure how to log into the console in unraid as "myself", I only log in as root.  So I when I access the various folders as myself, I'm accessing them through the unraid shares from a windows machine.

 

I use bind-mount to point /var/jenkins_home to /mnt/user/appdata/jenkins.

I have another set up for /deploymentBackups in the container pointed to /mnt/user/appdata/jenkinsDeploymentBackups.

Finally, I have a third with /deployments/offsiteBackup pointed to /mnt/user/appdata/offsiteBackup

 

User setup on host:

paddy:x:1001:100::/:/bin/false

jenkins-docker:x:1006:100:Jenkins docker runner for access to bind-mounts:/:/bin/false

 

user setup in container:

jenkins:x:1006:2000:Linux User,,,:/var/jenkins_home:/bin/bash

 

group setup on host:

jenkins-data-users:x:2000:paddy,jenkins-docker

 

group setup in container:

jenkins:x:1000:jenkins
jenkins-data-users:x:2000:

 

Folder setups from the host:
 

drwxr-----  1 jenkins-docker jenkins-data-users 1268 Jun 27 23:45 jenkins
drwxrw----  1 paddy          jenkins-data-users    0 Jun 26 04:49 jenkinsDeploymentBackups
drwxrwxrwx  1 paddy          jenkins-data-users  210 Jun 27 16:24 offsiteBackup

 

Folder setups in the container:
 

drwxrw----   1 1001 jenkins-data-users    0 Jun 26 04:49 deploymentBackups
drwxr-xr-x   1 root root                 26 Jun 27 23:53 deployments
drwxrwxrwx   1 1001 jenkins-data-users  210 Jun 27 16:24 deployments/offsiteBackup

 

The idea is that jenkins writes its data to the jenkins folder, but I need access to back it up, so I, as a member of the data users group, have read rights.  I own the other two folders and jenkins just writes to them  deploymentBackups is debatable, because in the happy-path, it's only used for jenkins to back up whatever is currently in the deployment path so that it won't be overwritten.  But jenkins definitely shouldn't own the offsiteBackups deployment path, as all it is ever doing is pushing a new version.  I maintain configuration and whatever else needs doing there, so I own that.

And, at all costs, I DON'T want to rebuild the base docker image.  I want to always be able to pull latest from docker up as my base, instead of having to grab their latest dockerfile and look for changes.  (Obviously with the caveat that if they ever change their user setup, my extension image is going to barf anyway.)

 

But this isn't working.

As myself (again, via an unraid share) I can't see anything inside the jenkins folder.

I can see and manipulate the offsiteBackup folder, and jenkins in the container can see and read files I drop there, but I can't read anything new it creates there.  And I get invalid operation errors if container jenkins tries to change ownership of what it creates, and I don't know if that is because of a lack of permissions, or a limitation of alpine.

And container jenkins can't cd into deploymentBackups or create anything at all there.  I can create something and container jenkins can see it via dir, but it can't view permissions, timestamp, etc, it's just ???? other than the name.

 

What am I doing wrong?  This is sandbox/learning for me, so I'm less concerned with whether I SHOULD be doing something than I am about HOW I can do what I want.  For instance, I probably shouldn't have write rights to the deployment folder once ci/cd is dropping files, and all manipulation should go through source control.  But if I can ever get it working the way I want, it will be trivial to "break" it later and secure it, whereas if I can't set it up insecure now, then I'll never know what it is that's actually making it secure.

 

Edited by NBjXvmXytwOAArTYRbLzdrQJ
Link to comment

I'm not expecting my docker user or my backup user to be able to log to the console or use the ui, I just need it to have access to these files in appdata.  And I need to be able to access them from the outside, while also preventing access from any of my other users, either unraid users or users from other containers.  Are you saying I'm doing it right, and docker just won't support it?

Link to comment

The point is that unRAID doesnt use file permissions the way general purpose linux does. The users you create in unRAID only exist from the perspective of share level network security. Under the hood linux users and groups are not really used to control file access. Applications that run directly on unRAID run as root, applications in containers are expected to have their container permissions mapped to nobody:users on the unraid host and only be given bind mounts to the specific directories need as a means of controlling what they can access.

Link to comment

How am I supposed to map the container user?  Does the docker daemon running on unraid use the --userns-remap option?  Specifying -u on the docker run or specifying a different user in the dockerfile just puts that user as the owner of files inside and outside the container; there's no mapping occurring right now as far as I can tell.  All of my containers running as root create files on the host as root.  All of the containers running as anything else show files created and owned by that "anything else", even if the user:group doesn't exist on the host.  Eg, nginx runs as user nginx:nginx, which is 101:101 in the container; on the host, files it creates show as 101:console.  So I can't set the container to run as nobody with -u, or it won't have any rights even within the container to do its job, right?

If docker isn't already running with --userns-remap, and I enable it with the /etc/docker/daemon.json per https://docs.docker.com/engine/security/userns-remap/, will that change survive a reboot, or is that directory one of the virtual ram directories that will be recreated?

 

What I'm trying to do is mitigate against container breakout and similar situations.  I'm assuming that an externally-facing container (or even an internal one) is compromised by some sort of malware.  At that point, I couldn't keep it from accessing the bind-mounts; something like nginrat would have unrestricted access to web data and webdav user files without being limited by the nginx access controls, and there's nothing I can do to limit it at that point.  But if 101:console has access to any sensitive data on the host, the malware would be able to access it if it could break out of the container, and that's the exposure I'm trying to work out how to limit.  That and the same general issue of keeping my docker users and my unraid users from overlapping to prevent rights of one accidentally giving the other rights.

Edited by NBjXvmXytwOAArTYRbLzdrQJ
Link to comment
19 hours ago, NBjXvmXytwOAArTYRbLzdrQJ said:

How am I supposed to map the container user? 

Many containers available in User Applications (and many found in the wild) have environmental variables like PUID and PGID that allow you to specify the user and group that the app in the container runs under. Match those to nobody:users on the unRAID host.

 

19 hours ago, NBjXvmXytwOAArTYRbLzdrQJ said:

If docker isn't already running with --userns-remap, and I enable it with the /etc/docker/daemon.json per https://docs.docker.com/engine/security/userns-remap/, will that change survive a reboot, or is that directory one of the virtual ram directories that will be recreated?

It will not survive reboot. You would have to use a user script or go file mod to make that change on every boot.

 

19 hours ago, NBjXvmXytwOAArTYRbLzdrQJ said:

What I'm trying to do is mitigate against container breakout and similar situations.  I'm assuming that an externally-facing container (or even an internal one) is compromised by some sort of malware.  At that point, I couldn't keep it from accessing the bind-mounts; something like nginrat would have unrestricted access to web data and webdav user files without being limited by the nginx access controls, and there's nothing I can do to limit it at that point.  But if 101:console has access to any sensitive data on the host, the malware would be able to access it if it could break out of the container, and that's the exposure I'm trying to work out how to limit.  That and the same general issue of keeping my docker users and my unraid users from overlapping to prevent rights of one accidentally giving the other rights.

unRAID is not really designed with security at the forefront. Its inclusion of docker is more aimed at providing simple to install apps rather than hosting internet facing services. If security of your hosted apps is your primary concern i would recommend running a VM with a more general os and run your secure docker services on that.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.