ns-tools

Namespace utilities to reuse Open Source packaging efforts.
git clone git://r-36.net/ns-tools
Log | Files | Refs | LICENSE

commit 84ab05a787db5488718d87a11897e5204e4a0416
Author: Christoph Lohmann <20h@r-36.net>
Date:   Thu,  1 May 2014 18:13:49 +0200

Initial commit of ns-tools.

Diffstat:
LICENSE | 21+++++++++++++++++++++
README.md | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bin/ns-boot | 8++++++++
bin/ns-chroot | 48++++++++++++++++++++++++++++++++++++++++++++++++
bin/ns-copy-intel-ucode | 22++++++++++++++++++++++
bin/ns-gencapchrootallow | 17+++++++++++++++++
bin/ns-init | 4++++
bin/ns-kill | 16++++++++++++++++
bin/ns-lsof | 14++++++++++++++
bin/ns-path | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bin/ns-prepare | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bin/ns-root | 30++++++++++++++++++++++++++++++
bin/ns-umount | 18++++++++++++++++++
bin/ns-unprepare | 43+++++++++++++++++++++++++++++++++++++++++++
bin/ns-unprepare-all | 7+++++++
bin/ns-update | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bin/ns-user | 8++++++++
bin/ns-vzinit | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bin/ns-wrapper | 17+++++++++++++++++
bin/ns-wrapper-install | 18++++++++++++++++++
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 +