Skip to content

Instantly share code, notes, and snippets.

@mconcas
Last active May 24, 2016 19:47
Show Gist options
  • Save mconcas/2f437edb089c988f2d1afb8acc49a81a to your computer and use it in GitHub Desktop.
Save mconcas/2f437edb089c988f2d1afb8acc49a81a to your computer and use it in GitHub Desktop.
Quick note to mount a cvmfs filesystem into a Docker container

Mount CVMFS inside a Docker container

RHEL7 or Ubuntu with apparmor in complain mode

On the host

Provided that FUSE is installed and loaded on your kernel, which is easily checked running:

~ $ sudo modprobe --first-time fuse
modprobe: ERROR: could not insert 'fuse': Module already in kernel

you can start a docker container, say from a vanilla centos:6 based image:

~ $ docker run docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse centos:6 /bin/bash

On Ubuntu with running apparmor and not in complain mode

Assuming you are happy with using docker alongside apparmor, you're probably aware that a MAC (Mandatory Access Control) context can limit access to inodes even though you are root.

Image

(All credits for this image go to: This Source )

In a nuteshell: even adding the right linux-capabilities to our container execution, in order to allow mount or ptrace, if your generic MAC profile is too restrictive, you actually won't be able to mount anything inside your container.

Thus you need to declare a proper profile in order to be allowed (by SELinux or Apparmor) to enable those capabilities.

How to write a proper apparmor profile

Docker comes with a default profile located in /etc/apparmor.d/docker. Its content should be something like (current Docker version: Docker version 1.11.1, build 5604cbe):



#include <tunables/global>


profile docker-default flags=(attach_disconnected,mediate_deleted) {

  #include <abstractions/base>


  network,
  capability,
  file,
  umount,

  deny @{PROC}/* w,   # deny write for all files directly in /proc (not in a subdir)
  # deny write to files not in /proc/<number>/** or /proc/sys/**
  deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w,
  deny @{PROC}/sys/[^k]** w,  # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel)
  deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w,  # deny everything except shm* in /proc/sys/kernel/
  deny @{PROC}/sysrq-trigger rwklx,
  deny @{PROC}/mem rwklx,
  deny @{PROC}/kmem rwklx,
  deny @{PROC}/kcore rwklx,

  deny mount,

  deny /sys/[^f]*/** wklx,
  deny /sys/f[^s]*/** wklx,
  deny /sys/fs/[^c]*/** wklx,
  deny /sys/fs/c[^g]*/** wklx,
  deny /sys/fs/cg[^r]*/** wklx,
  deny /sys/firmware/efi/efivars/** rwklx,
  deny /sys/kernel/security/** rwklx,


  # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
  ptrace (trace,read) peer=docker-default,

}

As you can see the line deny mount, is self-explained.
What we are going to do is to allow containers to perform ptrace() calls and mount CVMFS devices (FUSE). According with the only decent guide found on the internet, I edited the previous file:



#include <tunables/global>


profile docker-cvmfs flags=(attach_disconnected,mediate_deleted) {

  #include <abstractions/base>


  network,
  capability,
  file,
  umount,
  mount,
  ptrace,

  deny @{PROC}/* w,   # deny write for all files directly in /proc (not in a subdir)
  # deny write to files not in /proc/<number>/** or /proc/sys/**
  deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w,
  deny @{PROC}/sys/[^k]** w,  # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel)
  deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w,  # deny everything except shm* in /proc/sys/kernel/
  deny @{PROC}/sysrq-trigger rwklx,
  deny @{PROC}/mem rwklx,
  deny @{PROC}/kmem rwklx,
  deny @{PROC}/kcore rwklx,

  # deny mount,

  deny /sys/[^f]*/** wklx,
  deny /sys/f[^s]*/** wklx,
  deny /sys/fs/[^c]*/** wklx,
  deny /sys/fs/c[^g]*/** wklx,
  deny /sys/fs/cg[^r]*/** wklx,
  deny /sys/firmware/efi/efivars/** rwklx,
  deny /sys/kernel/security/** rwklx,


  # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
  # ptrace (trace,read) peer=docker-default,

}

Add this profile assuming it is located in /etc/apparmor.d/docker-cvmfs to apparmor:

~ # apparmor_parser -rW /etc/apparmor.d/docker-cvmfs

Now you should be able to apply a --security-opt apparmor=<profile> flag. For example:

~ $ docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse --security-opt apparmor=docker-cvmfs alisw/slc6-cvmfs /bin/bash

For further informations: SYS_ADMIN capability.

Install CVMFS into a centos:6 container

Create a file named /etc/yum.repos.d/cvmfs.repo with the following content:

[cvmfs]
name=CernVM-FS Stable
baseurl=http://cvmrepo.web.cern.ch/cvmrepo/yum/cvmfs/EL/$releasever/$basearch
enabled=1
gpgcheck=0

Now install CVMFS:

~ # yum install -y cvmfs

and, for example:

~ # mount -t cvmfs alice.cern.ch /cvmfs
@dberzano
Copy link

Worth a read: https://lwn.net/Articles/486306/

Maybe there is something less invasive for FUSE?

@dberzano
Copy link

@mconcas
Copy link
Author

mconcas commented May 24, 2016

TIL:

  1. Linux Capabilities can be limited with more granularity using Linux Security Module Frameworks -> Apparmor can be a powerful tool and might help us
  2. Apparmor profiles changes/updates are effective on running containers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment