diff --git a/installer/install.sh b/installer/install.sh deleted file mode 100755 index 418c79b..0000000 --- a/installer/install.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh -# Sashimono installation script. - -sashimono_user=sashimono -sashimono_user_dir=/home/$sashimono_user -sashimono_agent_dir=$sashimono_user_dir/sashimono-agent -dockerd_user=sashidockerd -dockerd_user_dir=/home/$dockerd_user -dockerd_socket_dir=$dockerd_user_dir/.docker/run -dockerd_socket=unix://$dockerd_socket_dir/docker.sock -mod_netfilter=br_netfilter - -# Check if users already exists. -[ `id -u $sashimono_user 2>/dev/null || echo -1` -ge 0 ] && echo "User '$sashimono_user' already exists." && exit 1 -[ `id -u $dockerd_user 2>/dev/null || echo -1` -ge 0 ] && echo "User '$dockerd_user' already exists." && exit 1 - -# Install curl if not exists (required to download installation artifacts). -[ ! $(command -v curl &> /dev/null) ] && apt-get install -y curl - - -# -------------------------------------- -# Setup dockerd user and service. -# -------------------------------------- -useradd --shell /usr/sbin/nologin -m $dockerd_user -usermod --lock $dockerd_user -loginctl enable-linger $dockerd_user # Enable lingering to support rootless dockerd service installation. -chmod o-rwx $dockerd_user_dir -echo "Created '$dockerd_user' user." - -dockerd_user_runtime_dir=/run/user/$(id -u $dockerd_user) - -# Download and install rootless dockerd. -sudo -u $dockerd_user mkdir -p $dockerd_socket_dir -loginctl enable-linger $dockerd_user -echo "Installing rootless dockerd..." -curl --silent -fSL https://get.docker.com/rootless | sudo -u $dockerd_user XDG_RUNTIME_DIR=$dockerd_user_runtime_dir sh > /dev/null -echo "Installed rootless dockerd." - -# After installing rootless dockerd, we need to stop and restart the dockerd service with our own daemon config. - -# Create new daemon config. -# - Disable dockerd inter-container communication. -# - Specify custom docker socket path. (So we can specify custom dir execute permission to user group) -sudo -u $dockerd_user mkdir -p $dockerd_user_dir/.config/docker -echo '{"icc":false,"hosts":["'$dockerd_socket'"]}' | sudo -u $dockerd_user tee $dockerd_user_dir/.config/docker/daemon.json >/dev/null - -# We need br_netfilter kernel module to make icc=false work. Otherwise dockerd won't start. -echo "Checking for '$mod_netfilter' kernel module..." -modprobe -n --first-time $mod_netfilter && modprobe $mod_netfilter && echo "Adding $mod_netfilter to /etc/modules" && printf "\n$mod_netfilter\n" >>/etc/modules - -# Stop and start the dockerd service. -sudo -u $dockerd_user XDG_RUNTIME_DIR=$dockerd_user_runtime_dir systemctl --user stop docker.service -sudo -u $dockerd_user XDG_RUNTIME_DIR=$dockerd_user_runtime_dir systemctl --user start docker.service -echo "Restarted dockerd service with Sashimono configuration." - -# Setup env variables for dockerd user. -echo " -export XDG_RUNTIME_DIR=$dockerd_user_runtime_dir -export PATH=$dockerd_user_dir/bin:\$PATH -export DOCKER_HOST=$dockerd_socket" >>$dockerd_user_dir/.bashrc - - -# -------------------------------------- -# Setup Sashimono user and agent. -# -------------------------------------- -useradd --shell /usr/sbin/nologin -m $sashimono_user -usermod --lock $sashimono_user -chmod o-rwx $sashimono_user_dir -echo "Created '$sashimono_user' user." - -# Following two permissions are required for Sashimono to interact with the dockerd UNIX socket. -# Add sashimono user to docker user group. -usermod -a -G $dockerd_user $sashimono_user -# Assign group execute permission for docker socket dir. -chmod g+x $dockerd_socket_dir - -# Setup sashimono agent directory. -mkdir -p $sashimono_agent_dir -# Copy docker client for sashimono user. -cp $dockerd_user_dir/bin/docker $sashimono_agent_dir/ -# TODO: Copy sashimono agent binaries. -# Set owner and group to be sashimono user. -chown --recursive $sashimono_user.$sashimono_user $sashimono_agent_dir -echo "Configured $sashimono_agent_dir" - -# Configure docker client context. -sudo -u $sashimono_user $sashimono_agent_dir/docker context create sashidockerctx --docker host=$dockerd_socket >/dev/null -sudo -u $sashimono_user $sashimono_agent_dir/docker context use sashidockerctx >/dev/null - -# Set PATH for convenience during interactive shell sessions. -echo "export PATH=$sashimono_agent_dir:\$PATH" >>$sashimono_user_dir/.bashrc - -echo "Done." diff --git a/installer/sashimono-install.sh b/installer/sashimono-install.sh new file mode 100755 index 0000000..292475c --- /dev/null +++ b/installer/sashimono-install.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Sashimono agent installation script. +# This must be executed with root privileges. + +sashimono_bin=/usr/bin/sashimono-agent +docker_bin=/usr/bin/sashimono-dockerbin + +echo "Installing Sashimono..." + +# Create bin dirs first so it automatically checks for privileged access. +mkdir -p $sashimono_bin +[ "$?" == "1" ] && echo "Could not create '$sashimono_bin'. Make sure you are running as sudo." && exit 1 +mkdir -p $docker_bin +[ "$?" == "1" ] && echo "Could not create '$docker_bin'. Make sure you are running as sudo." && exit 1 + +# Install curl if not exists (required to download installation artifacts). +if ! command -v curl &> /dev/null +then + apt-get install -y curl +fi + +# Install Sashimono agent binaries into sashimono bin dir. +# TODO. + +# Download docker packages into a tmp dir and extract into docker bin. +echo "Installing rootless docker packages into $docker_bin" +tmp=$(mktemp -d) +cd $tmp +curl https://download.docker.com/linux/static/stable/$(uname -m)/docker-20.10.7.tgz --output docker.tgz +curl https://download.docker.com/linux/static/stable/$(uname -m)/docker-rootless-extras-20.10.7.tgz --output rootless.tgz + +cd $docker_bin +tar zxf $tmp/docker.tgz --strip-components=1 +tar zxf $tmp/rootless.tgz --strip-components=1 + +rm -r $tmp + +# Check whether installation dir is still empty. +[ -z "$(ls -A $docker_bin 2>/dev/null)" ] && echo "Installation failed." && exit 1 + +echo "Done." +exit 0 diff --git a/installer/sashimono-uninstall.sh b/installer/sashimono-uninstall.sh new file mode 100755 index 0000000..8e09057 --- /dev/null +++ b/installer/sashimono-uninstall.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Sashimono agent uninstall script. + +sashimono_bin=/usr/bin/sashimono-agent +docker_bin=/usr/bin/sashimono-dockerbin + +# TODO: Uninstall all contract instance users + +echo "Deleting binaries..." +rm -r $sashimono_bin +rm -r $docker_bin + +echo "Done." diff --git a/installer/uninstall.sh b/installer/uninstall.sh deleted file mode 100755 index 0d5f483..0000000 --- a/installer/uninstall.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh -# Sashimono agent uninstall script. - -sashimono_user=sashimono -dockerd_user=sashidockerd -dockerd_user_dir=/home/$dockerd_user - -# Uninstall rootless dockerd. -echo "Uninstalling rootless dockerd..." -sudo -u $dockerd_user bash -i -c "$dockerd_user_dir/bin/dockerd-rootless-setuptool.sh uninstall" -echo "Removing rootless Docker data..." -sudo -u $dockerd_user $dockerd_user_dir/bin/rootlesskit rm -rf $dockerd_user_dir/.local/share/docker - -# Kill all processes for users. -echo "Killing user processes..." -loginctl disable-linger $dockerd_user -pkill -SIGKILL -u $dockerd_user -pkill -SIGKILL -u $sashimono_user - -echo "Deleting users..." -userdel $sashimono_user # Remove sashimono user first because it's in docker user's group. -userdel $dockerd_user - -rm -r /home/$sashimono_user -rm -r /home/$dockerd_user - -echo "Done." diff --git a/installer/user-install.sh b/installer/user-install.sh new file mode 100755 index 0000000..258b0c5 --- /dev/null +++ b/installer/user-install.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Sashimono contract instance user installation script. +# This is intended to be called by Sashimono agent. + +# $1 - A number with 25 or less digits. +uid=$1 +[ -z "$uid" ] && echo "ARGS,INST_ERR" && exit 1 +[ ${#uid} -gt 25 ] && echo "ARGS,INST_ERR" && exit 1 +[[ "$uid" =~ [^0-9] ]] && echo "ARGS,INST_ERR" && exit 1 + +user="sashi$uid" +user_dir=/home/$user +docker_bin=/usr/bin/sashimono-dockerbin + +# Check if users already exists. +[ `id -u $user 2>/dev/null || echo -1` -ge 0 ] && echo "HAS_USER,INST_ERR" && exit 1 + +function rollback() { + echo "Rolling back user installation. $1" + $(pwd)/user-uninstall.sh $uid + echo "Rolled back the installation." + echo "$1,INST_ERR" && exit 1 +} + +# Setup user and dockerd service. +useradd --shell /usr/sbin/nologin -m $user +usermod --lock $user +loginctl enable-linger $user # Enable lingering to support rootless dockerd service installation. +chmod o-rwx $user_dir +echo "Created '$user' user." + +user_id=$(id -u $user) +user_runtime_dir="/run/user/$user_id" +dockerd_socket="unix://$user_runtime_dir/docker.sock" + +# Setup env variables for the user. +echo " +export XDG_RUNTIME_DIR=$user_runtime_dir +export PATH=$docker_bin:\$PATH +export DOCKER_HOST=$dockerd_socket" >>$user_dir/.bashrc +echo "Updated user .bashrc." + +# Wait until user systemd is functionning. +user_systemd="" +for (( i=0; i<30; i++ )) +do + sleep 0.1 + user_systemd=$(sudo -u $user XDG_RUNTIME_DIR=$user_runtime_dir systemctl --user is-system-running 2>/dev/null) + [ "$user_systemd" == "running" ] && break +done +[ "$user_systemd" != "running" ] && rollback "NO_SYSTEMD" + +echo "Installing rootless dockerd for user." +sudo -u $user bash -i -c "$docker_bin/dockerd-rootless-setuptool.sh install" + +svcstat=$(sudo -u $user XDG_RUNTIME_DIR=$user_runtime_dir systemctl --user is-active docker.service) +[ "$svcstat" != "active" ] && rollback "NO_DOCKERSVC" + +echo "Installed rootless dockerd." +echo "$user_id,$user,$dockerd_socket,INST_SUC" +exit 0 diff --git a/installer/user-uninstall.sh b/installer/user-uninstall.sh new file mode 100755 index 0000000..c842b76 --- /dev/null +++ b/installer/user-uninstall.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# Sashimono contract instance user uninstall script. +# This is intended to be called by Sashimono agent or via the user-install script for rollback. + +# $1 - A number with 25 or less digits. +uid=$1 +[ -z "$uid" ] && echo "ARGS,UNINST_ERR" && exit 1 +[ ${#1} -gt 25 ] && echo "ARGS,UNINST_ERR" && exit 1 +[[ "$uid" =~ [^0-9] ]] && echo "ARGS,UNINST_ERR" && exit 1 + +user="sashi$uid" +user_dir=/home/$user +docker_bin=/usr/bin/sashimono-dockerbin + +# Check if users exists. +if [[ `id -u $user 2>/dev/null || echo -1` -ge 0 ]]; then + : +else + echo "NO_USER,UNINST_ERR" + exit 1 +fi + +# Uninstall rootless dockerd. +echo "Uninstalling rootless dockerd." +sudo -u $user bash -i -c "$docker_bin/dockerd-rootless-setuptool.sh uninstall" +echo "Removing rootless docker data." +sudo -u $user $docker_bin/rootlesskit rm -rf $user_dir/.local/share/docker + +# Gracefully terminate user processes. +echo "Terminating user processes." +loginctl disable-linger $user +pkill -SIGINT -u $user +sleep 0.5 +echo "Unmounting user filesystems." +fsmounts=$(cat /proc/mounts | cut -d ' ' -f 2 | grep "/home/$user") +readarray -t mntarr <<<"$fsmounts" +for mnt in "${mntarr[@]}" +do + [ -z "$mnt" ] || umount $mnt +done + +# Force kill user processes. +procs=$(ps -U root 2>/dev/null | wc -l) +if [ "$procs" != "0" ]; then + + # Wait for some time and check again. + sleep 1 + procs=$(ps -U root 2>/dev/null | wc -l) + if [ "$procs" != "0" ]; then + echo "Force killing user processes." + pkill -SIGKILL -u $user + fi + +fi + +echo "Deleting user." +userdel $user +rm -r /home/$user + +[ -d /home/$user ] && echo "NOT_CLEAN,UNINST_ERR" && exit 1 + +echo "UNINST_SUC" +exit 0