commit 84ab05a787db5488718d87a11897e5204e4a0416
Author: Christoph Lohmann <20h@r-36.net>
Date: Thu, 1 May 2014 18:13:49 +0200
Initial commit of ns-tools.
Diffstat:
20 files changed, 689 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT/X Consortium License
+
+© 2013-14 Christoph Lohmann <20h@r-36.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
@@ -0,0 +1,81 @@
+# Namespace tools
+
+## Namespaces
+
+Namespaces are basically installations of whatever Linux distribution
+you can find. Ns‐tools is using capchroot(1) to allow chroot into them
+based on group and user authentication. Some wrapper utilities allow the
+generation of wrapper scripts in /bin to run utilities in the names‐
+paces.
+
+### Namespace configuration
+
+The NSROOT variable is not yet implemented. For now /ns is the base
+path. You can configure every namespace using an »rc.conf« file in
+/ns/$namespace/.ns/. There the variables showin in ns‐prepare(1) are
+shown.
+
+When a command is run, it is checked, whether a namespace is prepared.
+The ONBOOT=1 variable defines, if the namespace should be prepared on
+boot. The ns‐boot(1) script should be run in your init scripts, if this
+is required.
+
+Alos look at the different variables to define which configuration files
+should be copied over, linked or run over.
+
+## Installation (pre-alpha)
+
+ # Base installation
+ mkdir /ns
+ cp bin/* /bin
+
+ # Install capchroot as stated below.
+
+ # Install a Debian 7.0 image
+ imageuri="$(ns-vzinit list | grep "debian-7.0-$(uname -m)")"
+ ns-vzinit install "$imageuri" /ns/debian
+
+ ns-chroot debian
+ debian shell> apt-get install nmap
+ debian shell> exit
+
+ ns-wrapper-install debian nmap
+ /bin/nmap -h
+ ns-chroot debian man nmap
+
+### Capchroot
+
+Here are the links to install capchroot. For now this isn't automated.
+
+https://dev.archlinux.org/~thomas/capchroot/
+http://bedrocklinux.org/1.0alpha1/install.html#DOWNLOAD%20Capchroot
+
+After you have a capchroot(1) binary, copy it to your PATH. Then create the
+/etc/capchroot.allow file to define users which are allowed to run capchroot
+and where. On my setup there is a »ns« group, which members are allowed to
+chroot to the defined namespaces.
+
+ cat /etc/capchroot.allow
+ /ns/debian @ns
+ ...
+
+## Issues in the concept
+* Unchroot is not yet implemented, so a complete linking in of X11 is not
+ possible.
+* Manpage paths are not global.
+* Installation is weird.
+* No Makefiles.
+* Should be run on top of a static OS, but can be run everywhere, where chroot
+ is allowed.
+
+## Links
+
+git://git.r-36.net/ns-tools
+http://git.r-36.net/ns-tools
+Bugs + Patches: 20h@r-36.net
+
+
+Have fun!
+
+Christoph Lohmann <20h@r-36.net>
+
diff --git a/bin/ns-boot b/bin/ns-boot
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+for ns in $(ls -1 /ns);
+do
+ ns-prepare -b $(ns-root "$ns")
+done
+
+
diff --git a/bin/ns-chroot b/bin/ns-chroot
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+curdir="$(pwd)"
+
+dounprepare=0
+[ "$1" = "-u" ] && dounprepare=1 && shift 1
+
+if [ $# -lt 1 ];
+then
+ printf "usage: [-u] %s ns [cmd]\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+[ -e "$nsroot/.ns/rc.conf" ] && . "$nsroot/.ns/rc.conf"
+if [ -n "$SHBIN" ];
+then
+ cmd="$SHBIN"
+else
+ cmd="/bin/sh"
+fi
+[ $# -gt 1 ] && cmd="$2" && shift 1
+shift 1
+
+ns-prepare "$nsroot"
+[ $? -gt 0 ] && exit 1
+
+export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
+args="$@"
+if [ ! -d "${nsroot}${curdir}" ];
+then
+ capchroot "$nsroot" $cmd -- "$@"
+else
+ capchroot -d "$curdir" "$nsroot" $cmd -- "$@"
+fi
+
+if [ $dounprepare -eq 1 ];
+then
+ ns-unprepare "$nsroot"
+else
+ lsof "$nsroot" >/dev/null 2>&1
+ [ $? -gt 0 ] && ns-unprepare "$nsroot"
+fi
+
+exit 0
+
diff --git a/bin/ns-copy-intel-ucode b/bin/ns-copy-intel-ucode
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if [ $# -lt 1 ];
+then
+ printf "usage: %s ns\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+firmwarepath="/usr/lib/firmware/intel-ucode"
+nsroot="$(ns-root "$1")"
+
+if [ ! -d "${nsroot}${firmwarepath}" ];
+then
+ printf "No '%s' in '%s' found.\n" \
+ "${firmwarepath}" "${nsroot}" 2>&1
+ exit 1
+fi
+
+[ ! -d "${firmwarepath}" ] && mkdir -p "${firmwarepath}"
+
+cp -rf ${nsroot}${firmwarepath}/* "${firmwarepath}"
+
diff --git a/bin/ns-gencapchrootallow b/bin/ns-gencapchrootallow
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ $# -lt 1 ];
+then
+ printf "usage: %s root\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+cd "$nsroot"
+for ns in $(ls -1d */);
+do
+ printf "%s/%s @ns\n" "$nsroot" "$(printf "%s\n" "$ns" | tr -d "/")"
+done
+
diff --git a/bin/ns-init b/bin/ns-init
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+mkdir -p /ns
+
diff --git a/bin/ns-kill b/bin/ns-kill
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+usage() {
+ printf "usage: %s ns\n" "$(basename $1)" >&2
+ exit 1
+}
+
+[ $# -lt 1 ] && usage $0
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+lsof -Fp "$nsroot" 2>/dev/null \
+ | cut -b 2- \
+ | xargs -n 1 kill -TERM
+
diff --git a/bin/ns-lsof b/bin/ns-lsof
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+usage() {
+ printf "usage: %s ns\n" "$(basename $1)" >&2
+ exit 1
+}
+
+[ $# -lt 1 ] && usage $0
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+lsof "$nsroot"
+
diff --git a/bin/ns-path b/bin/ns-path
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+usage() {
+ printf "usage: %s [-rn] ns cmd\n" "$(basename $1)" >&2
+ exit 1
+}
+
+dorecursive=0
+stripns=0
+while getopts "rn" opt;
+do
+ case $opt in
+ r)
+ dorecursive=1
+ ;;
+ n)
+ stripns=1
+ ;;
+ *)
+ usage $0
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+[ $# -lt 2 ] && usage $0
+
+findpath() {
+ errorn=1
+ justone=0
+ [ "$1" = "-1" ] && justone=1 && shift 1
+
+ fnsroot="$1"
+ fcmd="$2"
+ NSPATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
+ [ -e "$fnsroot/.ns/rc.conf" ] && . "$fnsroot/.ns/rc.conf"
+
+ for p in $(echo $NSPATH | tr ':' ' ');
+ do
+ if [ -x "$fnsroot${p}/$fcmd" -o -L "$fnsroot${p}/$fcmd" ];
+ then
+ errorn=0
+ if [ $stripns -eq 1 ];
+ then
+ printf "%s/%s\n" "$p" "$fcmd"
+ else
+ printf "%s%s/%s\n" "$fnsroot" "$p" "$fcmd"
+ fi
+ [ $justone -eq 1 ] && return 0
+ fi
+ done
+
+ return $errorn
+}
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+cmd="$2"
+rerrno=1
+if [ $dorecursive -eq 1 ];
+then
+ cd "$nsroot";
+ for ns in $(ls -1d */);
+ do
+ findpath "$nsroot/$(printf "%s\n" "$ns" | tr -d "/")" "$cmd"
+ [ $? -eq 0 ] && rerrno=0
+ done
+else
+ findpath -1 "$nsroot" "$cmd"
+ rerrno=$?
+fi
+
+if [ $rerrno -gt 0 ];
+then
+ printf "Could not find %s in namespace %s.\n" "$cmd" "$nsroot" >&2
+ exit 1
+else
+ exit 0
+fi
+
diff --git a/bin/ns-prepare b/bin/ns-prepare
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+doforce=0
+doforceonboot=0
+[ "$1" = "-f" ] && doforce=1 && shift 1
+[ "$1" = "-b" ] && doforceonboot=1 && shift 1
+
+if [ $# -lt 1 ];
+then
+ printf "usage: %s [-f] ns\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+shift 1
+
+[ -e "$nsroot/.ns/prepared" \
+ -a $doforce -eq 0 \
+ -a $doforceonboot -eq 0 ] && exit 0
+
+MOUNTFS=""
+UMOUNTFS=""
+TOUCHFILES=""
+COPYFILES=""
+LINKFILES=""
+ONBOOT=0
+
+[ -e "$nsroot/.ns/rc.conf" ] && . "$nsroot/.ns/rc.conf"
+[ $ONBOOT -eq 0 -a $doforceonboot -gt 0 ] && exit 0
+
+if [ ! -d "$nsroot" ];
+then
+ printf "$nsroot does not seem to be a valid directory.\n" >&2
+ exit 1
+fi
+
+if [ ! -d "$nsroot/.ns" ];
+then
+ mkdir -p "$nsroot/.ns"
+ printf "MOUNTFS=\"\"\n" \
+ "UMOUNTFS=\"\"\n" \
+ "TOUCHFILES=\"\"\n" \
+ "LINKFILES=\"\"\n" \
+ "COPYFILES=\"\"\n" > "$nsroot/.ns/rc.conf"
+fi
+
+filesystems="$MOUNTFS proc sys tmp dev dev/pts mnt home run devel nix usr/share/terminfo"
+for m in $filesystems;
+do
+ mkdir -p "$nsroot/$m"
+ mountpoint -q "$nsroot/$m" || mount -o rbind "/$m" "$nsroot/$m"
+done
+
+#[ -d "$nsroot/mnt/root" ] || mkdir -p "$nsroot/mnt/root"
+#mountpoint -q "$nsroot/mnt/root" || mount -o rbind / "$nsroot/mnt/root"
+
+tfs="etc/mtab $TOUCHFILES";
+for f in $tfs;
+do
+ touch "$nsroot/$f"
+done
+
+cfs="bin/nssh bin/capchroot $COPYFILES"
+for f in $cfs;
+do
+ [ -e "/$f" ] && cp -f "/$f" "$nsroot/$f"
+done
+
+lnfs="etc/resolv.conf etc/hostname etc/localtime etc/capchroot.allow etc/hosts etc/locale.gen $LINKFILES"
+for f in $lnfs;
+do
+ [ -e "/$f" ] && ln -f "/$f" "$nsroot/$f"
+done
+
+[ -x /bin/setcap ] && setcap cap_sys_chroot=ep "$nsroot/bin/capchroot"
+
+touch "$nsroot/.ns/prepared"
+[ $ONBOOT -gt 0 ] && touch "$nsroot/.ns/preparedonboot"
+printf "$nsroot has been prepared.\n"
+
+exit 0
+
diff --git a/bin/ns-root b/bin/ns-root
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+if [ "$#" -lt 1 ];
+then
+ printf "usage: %s nsroot\n" "$(basename "$0")" >&2
+ exit 1
+fi
+nsroot="$1"
+
+if [ -z "$(printf "%s\n" "$nsroot" | grep "/")" ];
+then
+ if [ -e "/ns/$nsroot" ];
+ then
+ printf "/ns/%s\n" "$nsroot"
+ exit 0
+ fi
+ printf "Could not find nsroot '%s'.\n" "$nsroot" >&2
+ exit 1
+fi
+
+if [ ! -e "$nsroot" ];
+then
+ printf "Could not find nsroot '%s'.\n" "$nsroot" >&2
+ exit 1
+fi
+
+printf "%s\n" "$nsroot"
+exit 0
+
+
diff --git a/bin/ns-umount b/bin/ns-umount
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+if [ $# -lt 1 ];
+then
+ printf "usage: %s nsroot\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+mount | cut -d' ' -f 3 | grep "^${nsroot}" | sort -r \
+ | while read -r m;
+ do
+ printf "Unmounting '%s'.\n" "$m"
+ umount "$m";
+ done
+
diff --git a/bin/ns-unprepare b/bin/ns-unprepare
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+doforce=0
+[ "$1" = "-f" ] && doforce=1 && shift 1
+
+if [ $# -lt 1 ];
+then
+ printf "usage: %s ns\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+[ -e "$nsroot/.ns/preparedonboot" -a $doforce -eq 0 ] && exit 0
+[ ! -e "$nsroot/.ns/prepared" -a $doforce -eq 0 ] && exit 0
+
+MOUNTFS=""
+UMOUNTFS=""
+TOUCHFILES=""
+COPYFILES=""
+[ -e "$nsroot/.ns/rc.conf" ] && . "$nsroot/.ns/rc.conf"
+
+if [ ! -d "$nsroot" ];
+then
+ printf "$nsroot does not seem to be a valid directory.\n" >&2
+ exit 1
+fi
+
+ns-umount "$nsroot" >/dev/null
+
+#ufilesystems="$UMOUNTFS proc sys tmp dev/pts mnt home run etc/conn etc/svc devel dev"
+#for m in $ufilesystems;
+#do
+# umount "$nsroot/$m"
+#done
+
+rm -f "$nsroot/.ns/prepared"
+rm -f "$nsroot/.ns/preparedonboot"
+printf "$nsroot has been unprepared.\n"
+
+exit 0
+
diff --git a/bin/ns-unprepare-all b/bin/ns-unprepare-all
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for ns in $(ls -1 /ns);
+do
+ ns-unprepare -f $(ns-root "$ns")
+done
+
diff --git a/bin/ns-update b/bin/ns-update
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+usage() {
+ printf "usage: %s [-r] ns\n" "$(basename $1)" >&2
+ exit 1
+}
+
+dorecursive=0
+while getopts "r" opt;
+do
+ case $opt in
+ r)
+ dorecursive=1
+ ;;
+ *)
+ usage $0
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+[ $# -lt 1 ] && usage $0
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+updatens() {
+ fnsroot="$1"
+
+ # custom
+ UPDATECMD=""
+ [ -e "$fnsroot/.ns/rc.conf" ] && . "$fnsroot/.ns/rc.conf"
+ if [ -n "$UPDATECMD" ];
+ then
+ ns-chroot "$fnsroot" "$UPDATECMD"
+ return $?
+ fi
+
+ # pacman
+ ppath="$(ns-path "$fnsroot" pacman 2>/dev/null)"
+ if [ $? -eq 0 ];
+ then
+ ns-chroot "$fnsroot" pacman -Syu
+ return $?
+ fi
+
+ # apt-get
+ apath="$(ns-path "$fnsroot" apt-get 2>/dev/null)"
+ if [ $? -eq 0 ];
+ then
+ ns-chroot "$fnsroot" apt-get update
+ [ $? -gt 0 ] && return $?
+ ns-chroot "$fnsroot" apt-get upgrade
+ return $?
+ fi
+
+ # yum
+ ypath="$(ns-path "$fnsroot" yum 2>/dev/null)"
+ if [ $? -eq 0 ];
+ then
+ ns-chroot "$fnsroot" yum update
+ return $?
+ fi
+
+ printf "Could not find update command for namespace %s.\n" "$fnsroot" >&2
+ return 1
+}
+
+rerrno=0
+if [ $dorecursive -eq 1 ];
+then
+ cd "$nsroot"
+ for ns in $(ls -1d */);
+ do
+ updatens "$nsroot/$(printf "%s\n" "$ns" | tr -d "/")"
+ [ $? -gt 0 ] && rerrno=1
+ done
+else
+ updatens "$nsroot"
+ rerrno=$?
+fi
+
+if [ $rerrno -gt 0 ];
+then
+ printf "Could not update namespace %s.\n" "$nsroot" >&2
+ exit 1
+else
+ exit 0
+fi
+
diff --git a/bin/ns-user b/bin/ns-user
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+nsroot="$(ns-root "$1")"
+[ $? -gt 0 ] && exit $?
+
+user="$2"
+
+
diff --git a/bin/ns-vzinit b/bin/ns-vzinit
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+getsortedhreflist() {
+ wget -q -O - "$1" | sed 's/.*href="\([^"]*\)".*/\1/g' | grep ".tar...$" \
+ | sort | while read -r href;
+ do
+ printf "%s/%s\n" "$1" "$href"
+ done
+}
+
+#baseuri="http://download.proxmox.com/appliances"
+#submodules="mail system www admin"
+baseuri="http://download.openvz.org/template/precreated"
+submodules="beta contrib unsupported"
+
+if [ $# -lt 1 ];
+then
+ printf "usage: %s cmd [opts]\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+cmd="$1"
+
+case "$cmd" in
+list)
+ if [ $# -gt 1 ];
+ then
+ baseuri="$2"
+ shift 2
+ submodules="$*"
+ fi
+
+ getsortedhreflist "$baseuri"
+ for m in $submodules;
+ do
+ getsortedhreflist "$baseuri/$m"
+ done
+ ;;
+install)
+ if [ $# -lt 3 ];
+ then
+ printf "usage: %s install uri nsroot\n" "$(basename $0)" >&2
+ exit 1
+ fi
+
+ nsroot="$3"
+ [ ! -d "$nsroot" ] && mkdir -p "$nsroot"
+ cd "$nsroot"
+ [ $? -gt 0 ] && exit 1
+
+ filename="$(basename "$2")"
+ wget -O "$filename" "$2"
+ tar -xf "$filename"
+ rm -f "$filename"
+
+ printf "$nsroot has been installed from $2.\n"
+
+ ;;
+esac
+
+exit 0
+
diff --git a/bin/ns-wrapper b/bin/ns-wrapper
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ $# -lt 2 ];
+then
+ printf "usage: %s ns cmd\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+# nroot is checked by ns-path
+nroot="$1"
+cmd="$2"
+
+path="$(ns-path -n $nroot $cmd)"
+[ $? -gt 0 ] && exit 1
+
+printf "#!/bin/sh\nns-chroot \"%s\" %s \"\$@\"\n" "$nroot" "$path"
+
diff --git a/bin/ns-wrapper-install b/bin/ns-wrapper-install
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+if [ $# -lt 2 ];
+then
+ printf "usage: %s ns cmd\n" "$(basename $0)" >&2
+ exit 1
+fi
+
+# nsroot is checked by ns-wrapper
+nroot="$1"
+cmd="$2"
+
+cmdw="$(ns-wrapper $nroot $cmd)"
+[ $? -gt 0 ] && exit 1
+
+printf "%s\n" "$cmdw" > /bin/$cmd
+chmod 755 /bin/$cmd
+