mirror of
https://github.com/fsquillace/junest.git
synced 2026-01-23 02:34:30 +00:00
Issue #174: Add new program GRoot and change version option for JuNest!
This replaces jchroot because GRoot can be also used in a user namespace environment.
This commit is contained in:
parent
426b708d2d
commit
0f7fd33c53
13 changed files with 458 additions and 184 deletions
|
|
@ -169,14 +169,14 @@ Internals
|
|||
There are two main chroot jail used in JuNest.
|
||||
The main one is [proot](https://wiki.archlinux.org/index.php/Proot) which
|
||||
allows unprivileged users to execute programs inside a sandbox and
|
||||
jchroot, a small and portable version of
|
||||
GRoot, a small and portable version of
|
||||
[arch-chroot](https://wiki.archlinux.org/index.php/Chroot) which is an
|
||||
enhanced chroot for privileged users that mounts the primary directories
|
||||
(i.e. /proc, /sys, /dev and /run) before executing any programs inside
|
||||
the sandbox.
|
||||
|
||||
## Automatic fallback to classic chroot ##
|
||||
If jchroot fails for some reasons in the host system (i.e. it is not able to
|
||||
If GRoot fails for some reasons in the host system (i.e. it is not able to
|
||||
mount one of the directories),
|
||||
JuNest automatically tries to fallback to the classic chroot.
|
||||
|
||||
|
|
|
|||
180
bin/groot
Executable file
180
bin/groot
Executable file
|
|
@ -0,0 +1,180 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This script is the simplified and portable version of arch-chroot
|
||||
# (https://wiki.archlinux.org/index.php/Change_root#Using_arch-chroot)
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# JUNEST_BASE can be overridden for testing purposes.
|
||||
# There is no need for doing it for normal usage.
|
||||
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/..)}"
|
||||
NAME='GRoot'
|
||||
CMD='groot'
|
||||
DESCRIPTION="I am $NAME!"
|
||||
CHROOTCMD=${CHROOTCMD:-chroot}
|
||||
SHELL="/bin/sh"
|
||||
MOUNT=mount
|
||||
UMOUNT=umount
|
||||
MOUNTPOINT=mountpoint
|
||||
MKDIR=mkdir
|
||||
TOUCH=touch
|
||||
|
||||
NOT_EXISTING_FILE=103
|
||||
NOT_ABSOLUTE_PATH=111
|
||||
NO_ROOT_PRIVILEGES=110
|
||||
|
||||
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
||||
|
||||
|
||||
################################ MAIN FUNCTIONS ###########################
|
||||
|
||||
function chroot_add_mount() {
|
||||
$MOUNT "$@" && CHROOT_ACTIVE_MOUNTS=("${@: -1}" "${CHROOT_ACTIVE_MOUNTS[@]}")
|
||||
}
|
||||
|
||||
function chroot_teardown() {
|
||||
$UMOUNT "${CHROOT_ACTIVE_MOUNTS[@]}"
|
||||
unset CHROOT_ACTIVE_MOUNTS
|
||||
}
|
||||
|
||||
function chroot_maybe_add_mount() {
|
||||
local cond=$1
|
||||
shift
|
||||
if eval "$cond"; then
|
||||
chroot_add_mount "$@"
|
||||
return
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
function chroot_setup() {
|
||||
CHROOT_ACTIVE_MOUNTS=()
|
||||
check_and_trap 'chroot_teardown' EXIT
|
||||
|
||||
if ! chroot_maybe_add_mount "! $MOUNTPOINT -q '$CHROOTDIR'" --bind "$CHROOTDIR" "$CHROOTDIR"
|
||||
then
|
||||
warn "Failed mount of directories. $CHROOTDIR is already a mountpoint. Skipping it..."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local re='(.*):(.*)'
|
||||
for binds in ${BINDINGS[@]}
|
||||
do
|
||||
local host_path=""
|
||||
local guest_path=""
|
||||
if [[ $binds =~ $re ]]
|
||||
then
|
||||
local host_path="${BASH_REMATCH[1]}"
|
||||
local guest_path="${BASH_REMATCH[2]}"
|
||||
else
|
||||
local host_path="$binds"
|
||||
local guest_path="$binds"
|
||||
fi
|
||||
|
||||
create_node "${host_path}" "${CHROOTDIR}${guest_path}"
|
||||
chroot_add_mount --rbind "${host_path}" "${CHROOTDIR}${guest_path}"
|
||||
done
|
||||
}
|
||||
|
||||
function create_node() {
|
||||
local src="$1"
|
||||
local dst="$2"
|
||||
if [[ ! -e $src ]]
|
||||
then
|
||||
die_on_status $NOT_EXISTING_FILE "${src} does not exist."
|
||||
elif [[ $src != /* ]]
|
||||
then
|
||||
die_on_status $NOT_ABSOLUTE_PATH "${src} is not an absolute path."
|
||||
elif [[ -f $src ]]
|
||||
then
|
||||
$TOUCH "$dst"
|
||||
elif [[ -d $src ]]
|
||||
then
|
||||
$MKDIR -p "$dst"
|
||||
fi
|
||||
}
|
||||
|
||||
function usage() {
|
||||
cat <<EOF
|
||||
$NAME (v$(cat $JUNEST_BASE/VERSION)): $DESCRIPTION
|
||||
|
||||
Usage:
|
||||
$CMD [options] [<chroot-dir> [command]]
|
||||
|
||||
Options:
|
||||
-b, --bind <path>
|
||||
Make the content of <path> accessible in the guest rootfs.
|
||||
|
||||
This option makes any file or directory of the host rootfs
|
||||
accessible in the confined environment just as if it were part of
|
||||
the guest rootfs. By default the host path is bound to the same
|
||||
path in the guest rootfs but users can specify any other location
|
||||
with the syntax: -b <host_path>:<guest_location>. This option can
|
||||
be invoked multiple times and the paths specified must be absolutes.
|
||||
|
||||
-h, --help Print this help message
|
||||
|
||||
-V, --version Show the $NAME version
|
||||
|
||||
If 'command' is unspecified, $CMD will launch $SHELL.
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
version() {
|
||||
echo -e "$NAME $(cat $JUNEST_BASE/VERSION)"
|
||||
}
|
||||
|
||||
function parse_arguments() {
|
||||
OPT_BIND=false
|
||||
BINDINGS=()
|
||||
OPT_HELP=false
|
||||
OPT_VERSION=false
|
||||
for opt in "$@"
|
||||
do
|
||||
case "$1" in
|
||||
-b|--bind) OPT_BIND=true ; shift ; BINDINGS+=("$1") ; shift ;;
|
||||
-h|--help) OPT_HELP=true ; shift ;;
|
||||
-V|--version) OPT_VERSION=true ; shift ;;
|
||||
-*) die "Invalid option $1" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -z $1 ]]
|
||||
then
|
||||
CHROOTDIR="$1"
|
||||
shift
|
||||
fi
|
||||
ARGS=()
|
||||
for arg in "$@"
|
||||
do
|
||||
ARGS+=("$arg")
|
||||
done
|
||||
}
|
||||
|
||||
function is_user_root() {
|
||||
(( EUID == 0 ))
|
||||
}
|
||||
|
||||
function execute_operation() {
|
||||
$OPT_HELP && usage && return
|
||||
$OPT_VERSION && version && return
|
||||
|
||||
is_user_root || die_on_status $NO_ROOT_PRIVILEGES 'This script must be run with root privileges'
|
||||
|
||||
[[ -d $CHROOTDIR ]] || die_on_status $NOT_EXISTING_FILE "Can't create chroot on non-directory $CHROOTDIR"
|
||||
|
||||
chroot_setup "$CHROOTDIR" || die "Failed to setup chroot $CHROOTDIR"
|
||||
|
||||
$CHROOTCMD "$CHROOTDIR" "${ARGS[@]}"
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
parse_arguments "$@"
|
||||
execute_operation
|
||||
}
|
||||
|
||||
main "$@"
|
||||
98
bin/jchroot
98
bin/jchroot
|
|
@ -1,98 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This script is the simplified and portable version of arch-chroot
|
||||
# (https://wiki.archlinux.org/index.php/Change_root#Using_arch-chroot)
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
JUNEST_BASE="$(readlink -f $(dirname $(readlink -f "$0"))/..)"
|
||||
|
||||
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
||||
|
||||
################################ MAIN FUNCTIONS ###########################
|
||||
|
||||
chroot_add_mount() {
|
||||
mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}")
|
||||
}
|
||||
|
||||
chroot_maybe_add_mount() {
|
||||
local cond=$1; shift
|
||||
if eval "$cond"; then
|
||||
chroot_add_mount "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
chroot_setup() {
|
||||
CHROOT_ACTIVE_MOUNTS=()
|
||||
[[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap'
|
||||
trap 'chroot_teardown' EXIT
|
||||
|
||||
chroot_maybe_add_mount "! mountpoint -q '$1'" "$1" "$1" --bind &&
|
||||
chroot_add_mount proc "$1/proc" -t proc -o nosuid,noexec,nodev &&
|
||||
chroot_add_mount sys "$1/sys" -t sysfs -o nosuid,noexec,nodev,ro &&
|
||||
chroot_add_mount udev "$1/dev" -t devtmpfs -o mode=0755,nosuid &&
|
||||
chroot_add_mount devpts "$1/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec &&
|
||||
chroot_add_mount shm "$1/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev &&
|
||||
chroot_add_mount run "$1/run" -t tmpfs -o nosuid,nodev,mode=0755 &&
|
||||
chroot_add_mount tmp "$1/tmp" -t tmpfs -o mode=1777,atime,nodev,nosuid &&
|
||||
mkdir -p "$1/$HOME" &&
|
||||
chroot_add_mount $HOME "$1/$HOME" --bind
|
||||
|
||||
mkdir -p "$1/run/lock"
|
||||
}
|
||||
|
||||
chroot_teardown() {
|
||||
umount "${CHROOT_ACTIVE_MOUNTS[@]}"
|
||||
unset CHROOT_ACTIVE_MOUNTS
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: ${0##*/} chroot-dir [command]
|
||||
|
||||
-h Print this help message
|
||||
|
||||
If 'command' is unspecified, ${0##*/} will launch /bin/sh.
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
chroot_add_resolv_conf() {
|
||||
local chrootdir=$1 resolv_conf=$1/etc/resolv.conf
|
||||
|
||||
# Handle resolv.conf as a symlink to somewhere else.
|
||||
if [[ -L $chrootdir/etc/resolv.conf ]]; then
|
||||
# readlink(1) should always give us *something* since we know at this point
|
||||
# it's a symlink. For simplicity, ignore the case of nested symlinks.
|
||||
resolv_conf=$(readlink "$chrootdir/etc/resolv.conf")
|
||||
if [[ $resolv_conf = /* ]]; then
|
||||
resolv_conf=$chrootdir$resolv_conf
|
||||
else
|
||||
resolv_conf=$chrootdir/etc/$resolv_conf
|
||||
fi
|
||||
|
||||
# ensure file exists to bind mount over
|
||||
if [[ ! -f $resolv_conf ]]; then
|
||||
install -Dm644 /dev/null "$resolv_conf" || return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
chroot_add_mount /etc/resolv.conf "$resolv_conf" --bind
|
||||
}
|
||||
|
||||
if [[ -z $1 || $1 == -h || $1 == --help ]]; then
|
||||
usage
|
||||
exit $(( $# ? 0 : 1 ))
|
||||
fi
|
||||
|
||||
(( EUID == 0 )) || die 'This script must be run with root privileges'
|
||||
chrootdir=$1
|
||||
shift
|
||||
|
||||
[[ -d $chrootdir ]] || die "Can't create chroot on non-directory $chrootdir"
|
||||
|
||||
chroot_setup "$chrootdir" || die "failed to setup chroot $chrootdir"
|
||||
chroot_add_resolv_conf "$chrootdir" || die "failed to setup resolv.conf"
|
||||
|
||||
SHELL="/bin/sh" chroot "$chrootdir" "$@"
|
||||
20
bin/junest
20
bin/junest
|
|
@ -3,7 +3,11 @@
|
|||
# This file is part of JuNest (https://github.com/fsquillace/junest).
|
||||
#
|
||||
|
||||
JUNEST_BASE="$(readlink -f $(dirname $(readlink -f "$0"))/..)"
|
||||
set -e
|
||||
|
||||
# JUNEST_BASE can be overridden for testing purposes.
|
||||
# There is no need for doing it for normal usage.
|
||||
JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/..)}"
|
||||
|
||||
source "${JUNEST_BASE}/lib/utils/utils.sh"
|
||||
source "${JUNEST_BASE}/lib/core/common.sh"
|
||||
|
|
@ -32,10 +36,10 @@ usage() {
|
|||
echo
|
||||
echo -e "Access options:"
|
||||
echo -e "-f, --fakeroot Run $NAME with fakeroot privileges"
|
||||
echo -e "-r, --root Run $NAME with root privileges via jchroot"
|
||||
echo -e "-p, --backend-args <args> Arguments for backend program (PRoot or jchroot)"
|
||||
echo -e "-r, --root Run $NAME with root privileges via GRoot"
|
||||
echo -e "-p, --backend-args <args> Arguments for backend program (PRoot or GRoot)"
|
||||
echo -e " ($CMD -p \"--help\" to check out the PRoot options"
|
||||
echo -e " $CMD -u -p \"--help\" to check out the jchroot options)"
|
||||
echo -e " $CMD -u -p \"--help\" to check out the GRoot options)"
|
||||
echo -e "-u, --user-namespace Use Linux User Namespace instead of PRoot"
|
||||
echo
|
||||
echo -e "Building options:"
|
||||
|
|
@ -47,7 +51,7 @@ usage() {
|
|||
echo
|
||||
echo -e "General options:"
|
||||
echo -e "-h, --help Show this help message"
|
||||
echo -e "-v, --version Show the $NAME version"
|
||||
echo -e "-V, --version Show the $NAME version"
|
||||
}
|
||||
|
||||
version() {
|
||||
|
|
@ -169,7 +173,7 @@ function parse_arguments(){
|
|||
-s|--skip-root-tests) OPT_SKIP_ROOT_TEST=true ; shift ;;
|
||||
-d|--delete) OPT_DELETE=true ; shift ;;
|
||||
-h|--help) OPT_HELP=true ; shift ;;
|
||||
-v|--version) OPT_VERSION=true ; shift ;;
|
||||
-V|--version) OPT_VERSION=true ; shift ;;
|
||||
--) shift ; break ;;
|
||||
-*) die "Invalid option $1" ;;
|
||||
*) break ;;
|
||||
|
|
@ -231,11 +235,11 @@ function execute_operation(){
|
|||
|
||||
}
|
||||
|
||||
function cli() {
|
||||
function main() {
|
||||
parse_arguments "$@"
|
||||
check_cli
|
||||
execute_operation
|
||||
}
|
||||
|
||||
cli "$@"
|
||||
main "$@"
|
||||
# vim: set ts=4 sw=4 noet:
|
||||
|
|
|
|||
|
|
@ -69,11 +69,11 @@ function build_image_env(){
|
|||
# sed command is required for locale-gen
|
||||
sudo ln -sf /usr/share/zoneinfo/posix/UTC ${maindir}/root/etc/localtime
|
||||
sudo bash -c "echo 'en_US.UTF-8 UTF-8' >> ${maindir}/root/etc/locale.gen"
|
||||
sudo ${maindir}/root/opt/junest/bin/jchroot ${maindir}/root locale-gen
|
||||
sudo ${maindir}/root/opt/junest/bin/groot ${maindir}/root locale-gen
|
||||
sudo bash -c "echo LANG=\"en_US.UTF-8\" >> ${maindir}/root/etc/locale.conf"
|
||||
|
||||
info "Setting up the pacman keyring (this might take a while!)..."
|
||||
sudo ${maindir}/root/opt/junest/bin/jchroot ${maindir}/root bash -c \
|
||||
sudo ${maindir}/root/opt/junest/bin/groot ${maindir}/root bash -c \
|
||||
"pacman-key --init; pacman-key --populate archlinux; [ -e /etc/pacman.d/gnupg/S.gpg-agent ] && gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye"
|
||||
|
||||
sudo rm ${maindir}/root/var/cache/pacman/pkg/*
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#
|
||||
# vim: ft=sh
|
||||
|
||||
set -e
|
||||
|
||||
NAME='JuNest'
|
||||
CMD='junest'
|
||||
DESCRIPTION='The Arch Linux based distro that runs upon any Linux distros without root access'
|
||||
|
|
@ -79,7 +77,7 @@ SH=("/bin/sh" "--login")
|
|||
|
||||
# List of executables that are run in the host OS:
|
||||
PROOT="${JUNEST_HOME}/opt/proot/proot-${ARCH}"
|
||||
JCHROOT=${JUNEST_BASE}/bin/jchroot
|
||||
GROOT=${JUNEST_BASE}/bin/groot
|
||||
CLASSIC_CHROOT=chroot
|
||||
WGET="wget --no-check-certificate"
|
||||
CURL="curl -L -J -O -k"
|
||||
|
|
@ -125,7 +123,8 @@ function mkdir_cmd(){
|
|||
}
|
||||
|
||||
function zgrep_cmd(){
|
||||
$ZGREP $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$ZGREP $@
|
||||
# No need for LD_EXEC as zgrep is a POSIX shell script
|
||||
$ZGREP $@ || ${JUNEST_HOME}/usr/bin/$ZGREP $@
|
||||
}
|
||||
|
||||
function unshare_cmd(){
|
||||
|
|
@ -151,7 +150,7 @@ function download_cmd(){
|
|||
}
|
||||
|
||||
function chroot_cmd(){
|
||||
$JCHROOT "$@" || $CLASSIC_CHROOT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CLASSIC_CHROOT "$@"
|
||||
$GROOT "$@" || $CLASSIC_CHROOT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CLASSIC_CHROOT "$@"
|
||||
}
|
||||
|
||||
############## COMMON FUNCTIONS ###############
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ function run_env_as_user_with_namespace() {
|
|||
local bindings=${RESULT}
|
||||
unset RESULT
|
||||
|
||||
unshare_cmd --mount --user --map-root-user $JCHROOT $bindings $backend_args "$JUNEST_HOME"
|
||||
unshare_cmd --mount --user --map-root-user $GROOT $bindings $backend_args "$JUNEST_HOME"
|
||||
}
|
||||
|
||||
function run_env_as_fakeroot_with_namespace() {
|
||||
|
|
@ -69,9 +69,19 @@ function run_env_as_fakeroot_with_namespace() {
|
|||
|
||||
copy_common_files
|
||||
|
||||
#mkdir -p "$chrootdir/$HOME"
|
||||
#mkdir -p "$chrootdir/run/lock"
|
||||
#chroot_add_mount --rbind /proc "$chrootdir/proc/"
|
||||
#chroot_add_mount --rbind /dev "$chrootdir/dev/"
|
||||
#chroot_add_mount --rbind /sys "$chrootdir/sys/"
|
||||
#chroot_add_mount --rbind /tmp "$chrootdir/tmp/"
|
||||
## alternately create a new tmp istead of binding it:
|
||||
##chroot_add_mount -t tmpfs tmp "$chrootdir/tmp/"
|
||||
#chroot_add_mount --rbind $HOME "$chrootdir/$HOME"
|
||||
provide_common_bindings
|
||||
local bindings=${RESULT}
|
||||
unset RESULT
|
||||
|
||||
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $JCHROOT $bindings $backend_args "$JUNEST_HOME"
|
||||
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT $bindings $backend_args "$JUNEST_HOME"
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,6 +170,20 @@ function ask(){
|
|||
[ "$res" == "Y" ]
|
||||
}
|
||||
|
||||
function check_and_trap() {
|
||||
local sigs="${@:2:${#@}}"
|
||||
local traps="$(trap -p $sigs)"
|
||||
[[ $traps ]] && die "Attempting to overwrite existing $sigs trap: $traps"
|
||||
trap $@
|
||||
}
|
||||
|
||||
function check_and_force_trap() {
|
||||
local sigs="${@:2:${#@}}"
|
||||
local traps="$(trap -p $sigs)"
|
||||
[[ $traps ]] && warn "Attempting to overwrite existing $sigs trap: $traps"
|
||||
trap $@
|
||||
}
|
||||
|
||||
function insert_quotes_on_spaces(){
|
||||
# It inserts quotes between arguments.
|
||||
# Useful to preserve quotes on command
|
||||
|
|
|
|||
|
|
@ -104,10 +104,16 @@ function test_zgrep(){
|
|||
ZGREP=echo assertCommandSuccess zgrep_cmd new_file
|
||||
assertEquals "new_file" "$(cat $STDOUTF)"
|
||||
|
||||
ZGREP=false assertCommandSuccess zgrep_cmd new_file
|
||||
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false new_file" "$(cat $STDOUTF)"
|
||||
mkdir -p ${JUNEST_HOME}/usr/bin
|
||||
touch ${JUNEST_HOME}/usr/bin/false
|
||||
chmod +x ${JUNEST_HOME}/usr/bin/false
|
||||
|
||||
ZGREP=false LD_EXEC=false assertCommandFail zgrep_cmd new_file
|
||||
echo -e "#!/bin/bash\necho zgrep" > ${JUNEST_HOME}/usr/bin/false
|
||||
ZGREP=false assertCommandSuccess zgrep_cmd new_file
|
||||
assertEquals "zgrep" "$(cat $STDOUTF)"
|
||||
|
||||
echo -e "#!/bin/bash\nexit 1" > ${JUNEST_HOME}/usr/bin/false
|
||||
ZGREP=false assertCommandFail zgrep_cmd new_file
|
||||
}
|
||||
|
||||
function test_unshare(){
|
||||
|
|
@ -121,16 +127,16 @@ function test_unshare(){
|
|||
}
|
||||
|
||||
function test_chroot(){
|
||||
JCHROOT=echo assertCommandSuccess chroot_cmd root
|
||||
GROOT=echo assertCommandSuccess chroot_cmd root
|
||||
assertEquals "root" "$(cat $STDOUTF)"
|
||||
|
||||
JCHROOT=false CLASSIC_CHROOT=echo assertCommandSuccess chroot_cmd root
|
||||
GROOT=false CLASSIC_CHROOT=echo assertCommandSuccess chroot_cmd root
|
||||
assertEquals "root" "$(cat $STDOUTF)"
|
||||
|
||||
JCHROOT=false CLASSIC_CHROOT=false assertCommandSuccess chroot_cmd root
|
||||
GROOT=false CLASSIC_CHROOT=false assertCommandSuccess chroot_cmd root
|
||||
assertEquals "ld_exec $JUNEST_HOME/usr/bin/false root" "$(cat $STDOUTF)"
|
||||
|
||||
JCHROOT=false CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root
|
||||
GROOT=false CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root
|
||||
}
|
||||
|
||||
function test_proot_cmd_compat(){
|
||||
|
|
|
|||
137
tests/unit-tests/test-groot.sh
Executable file
137
tests/unit-tests/test-groot.sh
Executable file
|
|
@ -0,0 +1,137 @@
|
|||
#!/bin/bash
|
||||
source "$(dirname $0)/../utils/utils.sh"
|
||||
|
||||
JUNEST_BASE="$(readlink -f $(dirname $(readlink -f "$0"))/../..)"
|
||||
|
||||
# Disable the exiterr
|
||||
set +e
|
||||
|
||||
function oneTimeSetUp(){
|
||||
setUpUnitTests
|
||||
}
|
||||
|
||||
function setUp(){
|
||||
# Attempt to source the files under test to revert variable overrides
|
||||
source $JUNEST_BASE/bin/groot -h &> /dev/null
|
||||
set +e
|
||||
|
||||
cwdSetUp
|
||||
mkdir -p chrootdir
|
||||
|
||||
init_mocks
|
||||
}
|
||||
|
||||
function tearDown(){
|
||||
cwdTearDown
|
||||
}
|
||||
|
||||
## Mock functions ##
|
||||
function init_mocks() {
|
||||
function usage(){
|
||||
echo "usage"
|
||||
}
|
||||
function is_user_root() {
|
||||
return 0
|
||||
}
|
||||
function chroot() {
|
||||
echo "chroot($@)"
|
||||
}
|
||||
function mountpoint() {
|
||||
echo "mountpoint($@)"
|
||||
# As default suppose the mountpoint does not exist
|
||||
return 1
|
||||
}
|
||||
function mount() {
|
||||
echo "mount($@)"
|
||||
}
|
||||
function umount() {
|
||||
echo "umount($@)"
|
||||
}
|
||||
function check_and_trap() {
|
||||
echo "check_and_trap($@)"
|
||||
}
|
||||
}
|
||||
|
||||
function test_help(){
|
||||
assertCommandSuccess main -h
|
||||
assertEquals "usage" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess main --help
|
||||
assertEquals "usage" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_version(){
|
||||
assertCommandSuccess main -V
|
||||
assertEquals "$NAME $(cat $JUNEST_BASE/VERSION)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess main --version
|
||||
assertEquals "$NAME $(cat $JUNEST_BASE/VERSION)" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_no_root(){
|
||||
is_user_root() {
|
||||
return 1
|
||||
}
|
||||
assertCommandFailOnStatus $NO_ROOT_PRIVILEGES main
|
||||
}
|
||||
function test_groot_no_directory(){
|
||||
assertCommandFailOnStatus $NOT_EXISTING_FILE main no-directory
|
||||
}
|
||||
function test_groot_mountpoint_exist(){
|
||||
mountpoint_mock() {
|
||||
echo "mountpoint($@)"
|
||||
}
|
||||
MOUNTPOINT=mountpoint_mock
|
||||
assertCommandSuccess main chrootdir
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_mountpoint_does_not_exist(){
|
||||
assertCommandSuccess main chrootdir
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_bind(){
|
||||
assertCommandSuccess main -b /tmp chrootdir
|
||||
[[ -d chrootdir/tmp ]]
|
||||
assertEquals 0 $?
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_bind_file(){
|
||||
touch file_src
|
||||
assertCommandSuccess main -b ${PWD}/file_src:/file_src chrootdir
|
||||
[[ -f chrootdir/file_src ]]
|
||||
assertEquals 0 $?
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind ${PWD}/file_src chrootdir/file_src)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_bind_not_existing_node(){
|
||||
assertCommandFailOnStatus $NOT_EXISTING_FILE main -b ${PWD}/file_src:/file_src chrootdir
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_bind_not_absolute_path_node(){
|
||||
touch file_src
|
||||
assertCommandFailOnStatus $NOT_ABSOLUTE_PATH main -b file_src:/file_src chrootdir
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_bind_guest_host(){
|
||||
assertCommandSuccess main -b /tmp:/home/tmp chrootdir
|
||||
[[ -d chrootdir/home/tmp ]]
|
||||
assertEquals 0 $?
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_multiple_bind(){
|
||||
assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir
|
||||
[[ -d chrootdir/home/tmp ]]
|
||||
assertEquals 0 $?
|
||||
[[ -d chrootdir/dev ]]
|
||||
assertEquals 0 $?
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nmount(--rbind /dev chrootdir/dev)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_command(){
|
||||
assertCommandSuccess main chrootdir ls -la -h
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_groot_with_bind_and_command(){
|
||||
assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir ls -la -h
|
||||
[[ -d chrootdir/home/tmp ]]
|
||||
assertEquals 0 $?
|
||||
[[ -d chrootdir/dev ]]
|
||||
assertEquals 0 $?
|
||||
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nmount(--rbind /dev chrootdir/dev)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
|
||||
}
|
||||
|
||||
source $(dirname $0)/../utils/shunit2
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
#!/bin/bash
|
||||
source "$(dirname $0)/../utils/utils.sh"
|
||||
|
||||
source $(dirname $0)/../../bin/junest -h &> /dev/null
|
||||
JUNEST_BASE="$(dirname $0)/../.."
|
||||
source $JUNEST_BASE/bin/junest -h &> /dev/null
|
||||
|
||||
# Disable the exiterr
|
||||
set +e
|
||||
|
|
@ -68,149 +69,149 @@ function run_env_as_user_with_namespace(){
|
|||
}
|
||||
|
||||
function test_help(){
|
||||
assertCommandSuccess cli -h
|
||||
assertCommandSuccess main -h
|
||||
assertEquals "usage" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --help
|
||||
assertCommandSuccess main --help
|
||||
assertEquals "usage" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_version(){
|
||||
assertCommandSuccess cli -v
|
||||
assertCommandSuccess main -V
|
||||
assertEquals "version" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --version
|
||||
assertCommandSuccess main --version
|
||||
assertEquals "version" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_build_image_env(){
|
||||
assertCommandSuccess cli -b
|
||||
assertCommandSuccess main -b
|
||||
assertEquals "build_image_env(false,false)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --build-image
|
||||
assertCommandSuccess main --build-image
|
||||
assertEquals "build_image_env(false,false)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -b -s
|
||||
assertCommandSuccess main -b -s
|
||||
assertEquals "build_image_env(false,true)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -b -n
|
||||
assertCommandSuccess main -b -n
|
||||
assertEquals "build_image_env(true,false)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -b -n -s
|
||||
assertCommandSuccess main -b -n -s
|
||||
assertEquals "build_image_env(true,true)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --build-image --disable-validation --skip-root-tests
|
||||
assertCommandSuccess main --build-image --disable-validation --skip-root-tests
|
||||
assertEquals "build_image_env(true,true)" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_check_env(){
|
||||
assertCommandSuccess cli -c myscript
|
||||
assertCommandSuccess main -c myscript
|
||||
assertEquals "check_env(${JUNEST_HOME},myscript,false)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --check myscript
|
||||
assertCommandSuccess main --check myscript
|
||||
assertEquals "check_env(${JUNEST_HOME},myscript,false)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -c myscript -s
|
||||
assertCommandSuccess main -c myscript -s
|
||||
assertEquals "check_env(${JUNEST_HOME},myscript,true)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --check myscript --skip-root-tests
|
||||
assertCommandSuccess main --check myscript --skip-root-tests
|
||||
assertEquals "check_env(${JUNEST_HOME},myscript,true)" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_delete_env(){
|
||||
assertCommandSuccess cli -d
|
||||
assertCommandSuccess main -d
|
||||
assertEquals "delete_env" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --delete
|
||||
assertCommandSuccess main --delete
|
||||
assertEquals "delete_env" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_setup_env_from_file(){
|
||||
is_env_installed(){
|
||||
return 1
|
||||
}
|
||||
assertCommandSuccess cli -i myimage
|
||||
assertCommandSuccess main -i myimage
|
||||
assertEquals "$(echo -e "setup_env_from_file(myimage)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --setup-from-file myimage
|
||||
assertCommandSuccess main --setup-from-file myimage
|
||||
assertEquals "$(echo -e "setup_env_from_file(myimage)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
||||
|
||||
is_env_installed(){
|
||||
return 0
|
||||
}
|
||||
assertCommandFail cli -i myimage
|
||||
assertCommandFail main -i myimage
|
||||
}
|
||||
|
||||
function test_setup_env(){
|
||||
is_env_installed(){
|
||||
return 1
|
||||
}
|
||||
assertCommandSuccess cli -a arm
|
||||
assertCommandSuccess main -a arm
|
||||
assertEquals "$(echo -e "setup_env(arm)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --arch arm
|
||||
assertCommandSuccess main --arch arm
|
||||
assertEquals "$(echo -e "setup_env(arm)\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli
|
||||
assertCommandSuccess main
|
||||
assertEquals "$(echo -e "setup_env()\nrun_env_as_user(,)")" "$(cat $STDOUTF)"
|
||||
|
||||
is_env_installed(){
|
||||
return 0
|
||||
}
|
||||
assertCommandFail cli -a arm
|
||||
assertCommandFail main -a arm
|
||||
}
|
||||
function test_run_env_as_fakeroot(){
|
||||
assertCommandSuccess cli -f
|
||||
assertCommandSuccess main -f
|
||||
assertEquals "run_env_as_fakeroot(,)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --fakeroot
|
||||
assertCommandSuccess main --fakeroot
|
||||
assertEquals "run_env_as_fakeroot(,)" "$(cat $STDOUTF)"
|
||||
|
||||
assertCommandSuccess cli -f -p "-b arg"
|
||||
assertCommandSuccess main -f -p "-b arg"
|
||||
assertEquals "run_env_as_fakeroot(-b arg,)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -f -p "-b arg" -- command -kv
|
||||
assertCommandSuccess main -f -p "-b arg" -- command -kv
|
||||
assertEquals "run_env_as_fakeroot(-b arg,command -kv)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -f command --as
|
||||
assertCommandSuccess main -f command --as
|
||||
assertEquals "run_env_as_fakeroot(,command --as)" "$(cat $STDOUTF)"
|
||||
assertCommandFail cli -a "myarch" -f command --as
|
||||
assertCommandFail main -a "myarch" -f command --as
|
||||
}
|
||||
function test_run_env_as_user(){
|
||||
assertCommandSuccess cli
|
||||
assertCommandSuccess main
|
||||
assertEquals "run_env_as_user(,)" "$(cat $STDOUTF)"
|
||||
|
||||
assertCommandSuccess cli -p "-b arg"
|
||||
assertCommandSuccess main -p "-b arg"
|
||||
assertEquals "run_env_as_user(-b arg,)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -p "-b arg" -- command -ll
|
||||
assertCommandSuccess main -p "-b arg" -- command -ll
|
||||
assertEquals "run_env_as_user(-b arg,command -ll)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli command -ls
|
||||
assertCommandSuccess main command -ls
|
||||
assertEquals "run_env_as_user(,command -ls)" "$(cat $STDOUTF)"
|
||||
|
||||
assertCommandFail cli -a "myarch" -- command -ls
|
||||
assertCommandFail main -a "myarch" -- command -ls
|
||||
}
|
||||
function test_run_env_as_root(){
|
||||
assertCommandSuccess cli -r
|
||||
assertCommandSuccess main -r
|
||||
assertEquals "run_env_as_root " "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -r command
|
||||
assertCommandSuccess main -r command
|
||||
assertEquals "run_env_as_root command" "$(cat $STDOUTF)"
|
||||
}
|
||||
|
||||
function test_run_env_as_fakeroot_with_namespace(){
|
||||
assertCommandSuccess cli -u -f
|
||||
assertCommandSuccess main -u -f
|
||||
assertEquals "run_env_as_fakeroot_with_namespace(,)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli --user-namespace --fakeroot
|
||||
assertCommandSuccess main --user-namespace --fakeroot
|
||||
assertEquals "run_env_as_fakeroot_with_namespace(,)" "$(cat $STDOUTF)"
|
||||
|
||||
assertCommandSuccess cli -u -f -p "-b arg"
|
||||
assertCommandSuccess main -u -f -p "-b arg"
|
||||
assertEquals "run_env_as_fakeroot_with_namespace(-b arg,)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -u -f -p "-b arg" -- command -kv
|
||||
assertCommandSuccess main -u -f -p "-b arg" -- command -kv
|
||||
assertEquals "run_env_as_fakeroot_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -u -f command --as
|
||||
assertCommandSuccess main -u -f command --as
|
||||
assertEquals "run_env_as_fakeroot_with_namespace(,command --as)" "$(cat $STDOUTF)"
|
||||
}
|
||||
function test_run_env_as_user_with_namespace(){
|
||||
assertCommandSuccess cli -u
|
||||
assertCommandSuccess main -u
|
||||
assertEquals "run_env_as_user_with_namespace(,)" "$(cat $STDOUTF)"
|
||||
|
||||
assertCommandSuccess cli -u -p "-b arg"
|
||||
assertCommandSuccess main -u -p "-b arg"
|
||||
assertEquals "run_env_as_user_with_namespace(-b arg,)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -u -p "-b arg" -- command -ll
|
||||
assertCommandSuccess main -u -p "-b arg" -- command -ll
|
||||
assertEquals "run_env_as_user_with_namespace(-b arg,command -ll)" "$(cat $STDOUTF)"
|
||||
assertCommandSuccess cli -u command -ls
|
||||
assertCommandSuccess main -u command -ls
|
||||
assertEquals "run_env_as_user_with_namespace(,command -ls)" "$(cat $STDOUTF)"
|
||||
}
|
||||
|
||||
function test_check_cli(){
|
||||
assertCommandFail cli -b -h
|
||||
assertCommandFail cli -b -c
|
||||
assertCommandFail cli -d -s
|
||||
assertCommandFail cli -n -v
|
||||
assertCommandFail cli -d -r
|
||||
assertCommandFail cli -h -f
|
||||
assertCommandFail cli -v -i fsd
|
||||
assertCommandFail cli -f -r
|
||||
assertCommandFail cli -p args -v
|
||||
assertCommandFail cli -a arch -v
|
||||
assertCommandFail cli -d args
|
||||
assertCommandFail main -b -h
|
||||
assertCommandFail main -b -c
|
||||
assertCommandFail main -d -s
|
||||
assertCommandFail main -n -v
|
||||
assertCommandFail main -d -r
|
||||
assertCommandFail main -h -f
|
||||
assertCommandFail main -v -i fsd
|
||||
assertCommandFail main -f -r
|
||||
assertCommandFail main -p args -v
|
||||
assertCommandFail main -a arch -v
|
||||
assertCommandFail main -d args
|
||||
}
|
||||
|
||||
source $(dirname $0)/../utils/shunit2
|
||||
|
|
@ -79,6 +79,28 @@ function test_ask_wrong_default_answer() {
|
|||
assertEquals 33 $?
|
||||
}
|
||||
|
||||
function test_check_and_trap_fail() {
|
||||
trap echo EXIT
|
||||
trap ls QUIT
|
||||
assertCommandFailOnStatus 1 check_and_trap 'pwd' EXIT QUIT
|
||||
}
|
||||
|
||||
function test_check_and_trap() {
|
||||
trap - EXIT QUIT
|
||||
assertCommandSuccess check_and_trap 'echo' EXIT QUIT
|
||||
}
|
||||
|
||||
function test_check_and_force_trap_fail() {
|
||||
trap echo EXIT
|
||||
trap ls QUIT
|
||||
assertCommandSuccess check_and_force_trap 'echo' EXIT QUIT
|
||||
}
|
||||
|
||||
function test_check_and_force_trap() {
|
||||
trap - EXIT QUIT
|
||||
assertCommandSuccess check_and_force_trap 'echo' EXIT QUIT
|
||||
}
|
||||
|
||||
function test_insert_quotes_on_spaces(){
|
||||
assertCommandSuccess insert_quotes_on_spaces this is "a test"
|
||||
assertEquals "this is \"a test\"" "$(cat $STDOUTF)"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
OLD_CWD=${PWD}
|
||||
function cwdSetUp(){
|
||||
ORIGIN_CWD=$(TMPDIR=/tmp mktemp -d -t junest-cwd.XXXXXXXXXX)
|
||||
cd $ORIGIN_CWD
|
||||
|
|
@ -5,6 +6,7 @@ function cwdSetUp(){
|
|||
|
||||
function cwdTearDown(){
|
||||
rm -rf $ORIGIN_CWD
|
||||
cd $OLD_CWD
|
||||
}
|
||||
|
||||
function junestSetUp(){
|
||||
|
|
@ -12,15 +14,12 @@ function junestSetUp(){
|
|||
mkdir -p ${JUNEST_HOME}/etc/junest
|
||||
echo "JUNEST_ARCH=x86_64" > ${JUNEST_HOME}/etc/junest/info
|
||||
mkdir -p ${JUNEST_HOME}/etc/ca-certificates
|
||||
trap - QUIT EXIT ABRT KILL TERM INT
|
||||
trap "rm -rf ${JUNEST_HOME}" EXIT QUIT ABRT KILL TERM INT
|
||||
}
|
||||
|
||||
function junestTearDown(){
|
||||
# the CA directories are read only and can be deleted only by changing the mod
|
||||
[ -d ${JUNEST_HOME}/etc/ca-certificates ] && chmod -R +w ${JUNEST_HOME}/etc/ca-certificates
|
||||
rm -rf $JUNEST_HOME
|
||||
trap - QUIT EXIT ABRT KILL TERM INT
|
||||
unset JUNEST_HOME
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue