# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+LXC_MAPPED_UID=
+LXC_MAPPED_GID=
+SSH=
+
+# Make sure the usual locations are in PATH
+export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
+
am_in_userns() {
[ -e /proc/self/uid_map ] || { echo no; return; }
[ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
in_userns=0
[ $(am_in_userns) = "yes" ] && in_userns=1
+copy_binary()
+{
+ binary_path=`which $1`
+ if [ $? -ne 0 ]; then
+ echo "Unable to find $1 binary on the system"
+ return 1
+ fi
+
+ dir_path="${binary_path%/*}"
+ echo /{,usr/}{,s}bin | grep $dir_path >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Binary $1 is located at $binary_path and will not be copied"
+ echo "($dir_path not supported)"
+ return 1
+ fi
+
+ cp $binary_path $rootfs/$binary_path
+ if [ $? -ne 0 ]; then
+ echo "Failed to copy $binary_path to rootfs"
+ return 1
+ fi
+
+ return 0
+}
+
install_busybox()
{
rootfs=$1
# minimal devices needed for busybox
if [ $in_userns -eq 1 ]; then
- for dev in tty console tty0 tty1 tty5 ram0 null urandom; do
- touch $rootfs/dev/$dev
- echo "/dev/$dev dev/$dev none bind 0 0" >> $path/fstab
+ for dev in tty console tty0 tty1 ram0 null urandom; do
+ echo "lxc.mount.entry = /dev/$dev dev/$dev none bind,optional,create=file 0 0" >> $path/config
done
else
mknod -m 666 tty c 5 0 || res=1
# executable
chmod 744 $rootfs/etc/init.d/rcS || return 1
- # mount points
- cat <<EOF >> $rootfs/etc/fstab
-shm /dev/shm tmpfs defaults 0 0
-EOF
-
- # writable and readable for other
- chmod 644 $rootfs/etc/fstab || return 1
-
# launch rcS first then make a console available
# and propose a shell on the tty, the last one is
# not needed
return $res
}
+install_dropbear()
+{
+ # copy dropbear binary
+ copy_binary dropbear || return 1
+
+ # make symlinks to various ssh utilities
+ utils="\
+ $rootfs/usr/bin/dbclient \
+ $rootfs/usr/bin/scp \
+ $rootfs/usr/bin/ssh \
+ $rootfs/usr/sbin/dropbearkey \
+ $rootfs/usr/sbin/dropbearconvert \
+ "
+ echo $utils | xargs -n1 ln -s /usr/sbin/dropbear
+
+ # add necessary config files
+ mkdir $rootfs/etc/dropbear
+ dropbearkey -t rsa -f $rootfs/etc/dropbear/dropbear_rsa_host_key > /dev/null 2>&1
+ dropbearkey -t dss -f $rootfs/etc/dropbear/dropbear_dss_host_key > /dev/null 2>&1
+
+ echo "'dropbear' ssh utility installed"
+
+ return 0
+}
+
+install_openssh()
+{
+ # tools to be installed
+ server_utils="sshd"
+ client_utils="\
+ ssh \
+ scp \
+ "
+ client_optional_utils="\
+ sftp \
+ ssh-add \
+ ssh-agent \
+ ssh-keygen \
+ ssh-keyscan \
+ ssh-argv0 \
+ ssh-copy-id \
+ "
+
+ # new folders used by ssh
+ ssh_tree="\
+$rootfs/etc/ssh \
+$rootfs/var/empty/sshd \
+$rootfs/var/lib/empty/sshd \
+$rootfs/var/run/sshd \
+"
+
+ # create folder structure
+ mkdir -p $ssh_tree
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+
+ # copy binaries
+ for bin in $server_utils $client_utils; do
+ copy_binary $bin || return 1
+ done
+
+ for bin in $client_optional_utils; do
+ tool_path=`which $bin` && copy_binary $bin
+ done
+
+ # add user and group
+ cat <<EOF >> $rootfs/etc/passwd
+sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
+EOF
+
+ cat <<EOF >> $rootfs/etc/group
+sshd:x:74:
+EOF
+
+ # generate container keys
+ ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key >/dev/null 2>&1
+ ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key >/dev/null 2>&1
+
+ # by default setup root password with no password
+ cat <<EOF > $rootfs/etc/ssh/sshd_config
+Port 22
+Protocol 2
+HostKey /etc/ssh/ssh_host_rsa_key
+HostKey /etc/ssh/ssh_host_dsa_key
+UsePrivilegeSeparation yes
+KeyRegenerationInterval 3600
+ServerKeyBits 768
+SyslogFacility AUTH
+LogLevel INFO
+LoginGraceTime 120
+PermitRootLogin yes
+StrictModes yes
+RSAAuthentication yes
+PubkeyAuthentication yes
+IgnoreRhosts yes
+RhostsRSAAuthentication no
+HostbasedAuthentication no
+PermitEmptyPasswords yes
+ChallengeResponseAuthentication no
+EOF
+
+ echo "'OpenSSH' utility installed"
+
+ return 0
+}
+
configure_busybox()
{
rootfs=$1
return 1
fi
- file $(which busybox) | grep -q "statically linked"
- if [ $? -ne 0 ]; then
- echo "warning : busybox is not statically linked."
- echo "warning : The template script may not correctly"
- echo "warning : setup the container environment."
- fi
-
# copy busybox in the rootfs
cp $(which busybox) $rootfs/bin
if [ $? -ne 0 ]; then
# relink /sbin/init
ln $rootfs/bin/busybox $rootfs/sbin/init
+ # /etc/fstab must exist for "mount -a"
+ touch $rootfs/etc/fstab
+
# passwd exec must be setuid
chmod +s $rootfs/bin/passwd
touch $rootfs/etc/shadow
- # setting passwd for root
- CHPASSWD_FILE=$rootfs/root/chpasswd.sh
-
- cat <<EOF >$CHPASSWD_FILE
-echo "setting root password to \"root\""
-
-mount -n --bind /lib $rootfs/lib
-if [ \$? -ne 0 ]; then
- echo "Failed bind-mounting /lib at $rootfs/lib"
- exit 1
-fi
-
-chroot $rootfs chpasswd <<EOFF 2>/dev/null
-root:root
-EOFF
-
-
-if [ \$? -ne 0 ]; then
- echo "Failed to change root password"
- exit 1
-fi
-
-umount $rootfs/lib
-
-EOF
-
- lxc-unshare -s MOUNT -- /bin/sh < $CHPASSWD_FILE
- rm $CHPASSWD_FILE
-
- # add ssh functionality if dropbear package available on host
- which dropbear >/dev/null 2>&1
- if [ $? -eq 0 ]; then
- # copy dropbear binary
- cp $(which dropbear) $rootfs/usr/sbin
- if [ $? -ne 0 ]; then
- echo "Failed to copy dropbear in the rootfs"
- return 1
- fi
-
- # make symlinks to various ssh utilities
- utils="\
- $rootfs/usr/bin/dbclient \
- $rootfs/usr/bin/scp \
- $rootfs/usr/bin/ssh \
- $rootfs/usr/sbin/dropbearkey \
- $rootfs/usr/sbin/dropbearconvert \
- "
- echo $utils | xargs -n1 ln -s /usr/sbin/dropbear
-
- # add necessary config files
- mkdir $rootfs/etc/dropbear
- dropbearkey -t rsa -f $rootfs/etc/dropbear/dropbear_rsa_host_key &> /dev/null
- dropbearkey -t dss -f $rootfs/etc/dropbear/dropbear_dss_host_key &> /dev/null
-
- echo "'dropbear' ssh utility installed"
- fi
-
return 0
}
rootfs=$2
name=$3
-grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
+grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config
cat <<EOF >> $path/config
-lxc.utsname = $name
-lxc.tty = 1
-lxc.pts = 1
+lxc.signal.halt = SIGUSR1
+lxc.signal.reboot = SIGTERM
+lxc.uts.name = $name
+lxc.tty.max = 1
+lxc.pty.max = 1
lxc.cap.drop = sys_module mac_admin mac_override sys_time
# When using LXC with apparmor, uncomment the next line to run unconfined:
-#lxc.aa_profile = unconfined
+#lxc.apparmor.profile = unconfined
+
+lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
+lxc.mount.entry = shm /dev/shm tmpfs defaults 0 0
EOF
libdirs="\
fi
done
echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >>$path/config
- echo "lxc.mount.auto = proc:mixed sys" >>$path/config
+}
+
+remap_userns()
+{
+ path=$1
+
+ if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then
+ chown $LXC_MAPPED_UID $path/config >/dev/null 2>&1
+ chown -R root $path/rootfs >/dev/null 2>&1
+ fi
+
+ if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then
+ chgrp $LXC_MAPPED_GID $path/config >/dev/null 2>&1
+ chgrp -R root $path/rootfs >/dev/null 2>&1
+ fi
}
usage()
{
cat <<EOF
-$1 -h|--help -p|--path=<path>
+$1 -h|--help -p|--path=<path> -s|--ssh={dropbear,openssh}
EOF
return 0
}
-options=$(getopt -o hp:n: -l help,rootfs:,path:,name: -- "$@")
+options=$(getopt -o hp:n:s: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid:,ssh: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
-p|--path) path=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
+ --mapped-uid) LXC_MAPPED_UID=$2; shift 2;;
+ --mapped-gid) LXC_MAPPED_GID=$2; shift 2;;
+ -s|--ssh) SSH=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
# detect rootfs
config="$path/config"
if [ -z "$rootfs" ]; then
- if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
- rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config)
+ if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
+ rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
echo "failed to write configuration file"
exit 1
fi
+
+remap_userns $path
+if [ $? -ne 0 ]; then
+ echo "failed to remap files to user"
+ exit 1
+fi
+
+if [ -n "$SSH" ]; then
+ case "$SSH" in
+ "dropbear")
+ install_dropbear
+ if [ $? -ne 0 ]; then
+ echo "Unable to install 'dropbear' ssh utility"
+ exit 1
+ fi ;;
+ "openssh")
+ install_openssh
+ if [ $? -ne 0 ]; then
+ echo "Unable to install 'OpenSSH' utility"
+ exit 1
+ fi ;;
+ *)
+ echo "$SSH: unrecognized ssh utility"
+ exit 1
+ esac
+else
+ which dropbear >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ install_dropbear
+ fi
+fi