From 6f7cab2e3b5c7a69d87f9c90706e1052f3f88e63 Mon Sep 17 00:00:00 2001 From: Ravin Perera <33562092+ravinsp@users.noreply.github.com> Date: Tue, 20 Jul 2021 12:57:29 +0530 Subject: [PATCH] Added docker registry scripts for future work. (#36) - Added docker private registry for future support. - Added automatic detection of host address. - Refactored cli args parsing. --- CMakeLists.txt | 2 +- dependencies/user-uninstall.sh | 25 +++++++------ installer/registry-install.sh | 61 ++++++++++++++++++++++++++++++++ installer/registry-uninstall.sh | 48 +++++++++++++++++++++++++ installer/sashimono-install.sh | 12 ++++++- installer/sashimono-uninstall.sh | 4 +++ src/conf.cpp | 10 +++--- src/conf.hpp | 25 +------------ src/main.cpp | 23 ++++++------ 9 files changed, 156 insertions(+), 54 deletions(-) create mode 100755 installer/registry-install.sh create mode 100755 installer/registry-uninstall.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index f3fd717..b97cefa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ target_precompile_headers(sagent PUBLIC src/pchheader.hpp) add_custom_target(installer COMMAND mkdir -p ./build/sashimono-installer COMMAND bash -c "cp -r ./build/{sagent,hpfs,hpws,user-install.sh,user-uninstall.sh,contract_template} ./build/sashimono-installer/" - COMMAND bash -c "cp -r ./installer/{docker-install.sh,sashimono-install.sh,sashimono-uninstall.sh} ./build/sashimono-installer/" + COMMAND bash -c "cp -r ./installer/{docker-install.sh,registry-install.sh,registry-uninstall.sh,sashimono-install.sh,sashimono-uninstall.sh} ./build/sashimono-installer/" COMMAND bash -c "cp -r ./dependencies/{user-cgcreate.sh,libblake3.so} ./build/sashimono-installer/" COMMAND tar cfz ./build/sashimono-installer.tar.gz --directory=./build/ sashimono-installer COMMAND rm -r ./build/sashimono-installer diff --git a/dependencies/user-uninstall.sh b/dependencies/user-uninstall.sh index 4c3676d..f3878be 100755 --- a/dependencies/user-uninstall.sh +++ b/dependencies/user-uninstall.sh @@ -3,17 +3,10 @@ # This is intended to be called by Sashimono agent or via the user-install script for rollback. user=$1 -contract_user="$user-secuser" -# Check whether this is a valid sashimono username. prefix="sashi" -[ ${#user} -lt 24 ] || [ ${#user} -gt 32 ] || [[ ! "$user" =~ ^$prefix[0-9]+$ ]] && echo "ARGS,UNINST_ERR" && exit 1 -cgroupsuffix="-cg" -user_dir=/home/$user -user_id=$(id -u "$user") -user_runtime_dir="/run/user/$user_id" -script_dir=$(dirname "$(realpath "$0")") -docker_bin=$script_dir/dockerbin +# Check whether this is a valid sashimono username. +[ ${#user} -lt 24 ] || [ ${#user} -gt 32 ] || [[ ! "$user" =~ ^$prefix[0-9]+$ ]] && echo "ARGS,UNINST_ERR" && exit 1 # Check if users exists. if [[ $(id -u "$user" 2>/dev/null || echo -1) -ge 0 ]]; then @@ -23,6 +16,14 @@ else exit 1 fi +contract_user="$user-secuser" +cgroupsuffix="-cg" +user_dir=/home/$user +user_id=$(id -u "$user") +user_runtime_dir="/run/user/$user_id" +script_dir=$(dirname "$(realpath "$0")") +docker_bin=$script_dir/dockerbin + echo "Uninstalling user '$user'." echo "Stopping and cleaning hpfs systemd services." @@ -36,8 +37,6 @@ sudo -u "$user" XDG_RUNTIME_DIR="$user_runtime_dir" systemctl --user disable "$l # Uninstall rootless dockerd. echo "Uninstalling rootless dockerd." sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/dockerd-rootless-setuptool.sh uninstall -echo "Removing rootless docker data." -sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/rootlesskit rm -rf "$user_dir"/.local/share/docker # Gracefully terminate user processes. echo "Terminating user processes." @@ -52,12 +51,12 @@ for mnt in "${mntarr[@]}"; do done # Force kill user processes. -procs=$(ps -U root 2>/dev/null | wc -l) +procs=$(ps -U $user 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) + procs=$(ps -U $user 2>/dev/null | wc -l) if [ "$procs" != "0" ]; then echo "Force killing user processes." pkill -SIGKILL -u "$user" diff --git a/installer/registry-install.sh b/installer/registry-install.sh new file mode 100755 index 0000000..bd84f98 --- /dev/null +++ b/installer/registry-install.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Sashimono docker registry installation script. + +docker_bin=$1 +user=$2 +port=$3 +hubacc="hotpocketdev" +images=("sashimono:hp-ubt.20.04" "sashimono:hp-ubt.20.04-njs.14") +user_dir=/home/$user + +# Check if users already exists. +[ "$(id -u "$user" 2>/dev/null || echo -1)" -ge 0 ] && echo "$user already exists." && exit 1 + +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 functioning. +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 -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$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 for docker registry." + +# Run the docker registry container on port 4444 +DOCKER_HOST=$dockerd_socket $docker_bin/docker run -d -p $port:5000 --restart=always --name registry registry:2 +echo "Docker registry listening at $port" + +# Prefetch the required docker images. +echo "Pulling Sashimono base contract images..." +for img in ${images[@]}; do + DOCKER_HOST=$dockerd_socket $docker_bin/docker pull $hubacc/$img + DOCKER_HOST=$dockerd_socket $docker_bin/docker tag $hubacc/$img localhost:$port/$img + DOCKER_HOST=$dockerd_socket $docker_bin/docker push localhost:$port/$img + DOCKER_HOST=$dockerd_socket $docker_bin/docker rmi $hubacc/$img +done + +exit 0 \ No newline at end of file diff --git a/installer/registry-uninstall.sh b/installer/registry-uninstall.sh new file mode 100755 index 0000000..2370c69 --- /dev/null +++ b/installer/registry-uninstall.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Sashimono docker registry installation script. + +docker_bin=$1 +user=$2 + +# Check if users exists. +if [[ $(id -u "$user" 2>/dev/null || echo -1) -ge 0 ]]; then + : +else + echo "$user does not exist." + exit 1 +fi + +user_dir=/home/$user +user_id=$(id -u "$user") +user_runtime_dir="/run/user/$user_id" + +# Uninstall rootless dockerd. +echo "Uninstalling rootless dockerd." +sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/dockerd-rootless-setuptool.sh uninstall + + +# Gracefully terminate user processes. +echo "Terminating user processes." +loginctl disable-linger $user +pkill -SIGINT -u $user +sleep 0.5 + +# Force kill user processes. +procs=$(ps -U $user 2>/dev/null | wc -l) +if [ "$procs" != "0" ]; then + + # Wait for some time and check again. + sleep 1 + procs=$(ps -U $user 2>/dev/null | wc -l) + if [ "$procs" != "0" ]; then + echo "Force killing user processes." + pkill -SIGKILL -u "$user" + fi + +fi + + +echo "Deleting user '$user'" +userdel "$user" +rm -r /home/"${user:?}" +exit 0 \ No newline at end of file diff --git a/installer/sashimono-install.sh b/installer/sashimono-install.sh index a833a42..0e480ca 100755 --- a/installer/sashimono-install.sh +++ b/installer/sashimono-install.sh @@ -9,6 +9,8 @@ sashimono_service="sashimono-agent" cgcreate_service="sashimono-cgcreate" group="sashimonousers" cgroupsuffix="-cg" +registryuser="sashidockerreg" +registryport=4444 script_dir=$(dirname "$(realpath "$0")") [ -d $sashimono_bin ] && [ -n "$(ls -A $sashimono_bin)" ] && @@ -65,13 +67,21 @@ chmod -R +x $sashimono_bin # Check whether docker installation dir is still empty. [ -z "$(ls -A $docker_bin 2>/dev/null)" ] && echo "Rootless Docker installation failed." && rollback +selfip=$(ip -4 a l ens3 | awk '/inet/ {print $2}' | cut -d/ -f1) + +# Install private docker registry. +# (Disabled until secure registry configuration) +# ./registry-install.sh $docker_bin $registryuser $registryport +# [ "$?" == "1" ] && rollback +# registry_addr=$selfip:$registryport + # Setting up cgroup rules. ! groupadd $group && echo "Group creation failed." && rollback ! echo "@$group cpu,memory %u$cgroupsuffix" >>/etc/cgrules.conf && echo "Cgroup rule creation failed." && rollback # Setup Sashimono data dir. cp -r "$script_dir"/contract_template $sashimono_data -$sashimono_bin/sagent new $sashimono_data +$sashimono_bin/sagent new $sashimono_data $selfip $registry_addr # Install Sashimono Agent cgcreate service. # This is a onshot service which runs only once. diff --git a/installer/sashimono-uninstall.sh b/installer/sashimono-uninstall.sh index d18361f..5cb8099 100755 --- a/installer/sashimono-uninstall.sh +++ b/installer/sashimono-uninstall.sh @@ -7,6 +7,7 @@ docker_bin=/usr/bin/sashimono-agent/dockerbin sashimono_data=/etc/sashimono sashimono_service="sashimono-agent" cgcreate_service="sashimono-cgcreate" +registryuser="sashidockerreg" group="sashimonousers" cgroupsuffix="-cg" quiet=$1 @@ -66,6 +67,9 @@ systemctl stop $sashimono_service systemctl disable $sashimono_service rm /etc/systemd/system/$sashimono_service.service +# echo "Removing Sashimono private docker registry..." +# ./registry-uninstall.sh $docker_bin $registryuser + echo "Deleting binaries..." rm -r $sashimono_bin diff --git a/src/conf.cpp b/src/conf.cpp index 78d1995..23225c5 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -33,7 +33,7 @@ namespace conf * Create config here. * @return 0 for success. -1 for failure. */ - int create() + int create(std::string_view host_addr, std::string_view registry_addr) { if (util::is_file_exists(ctx.config_file)) { @@ -57,7 +57,8 @@ namespace conf sa_config cfg = {}; cfg.version = version::AGENT_VERSION; - cfg.hp.host_address = "127.0.0.1"; + + cfg.hp.host_address = host_addr.empty() ? "127.0.0.1" : std::string(host_addr); cfg.hp.init_peer_port = 22861; cfg.hp.init_user_port = 8081; cfg.server.ip_port = {"127.0.0.1", 5000}; @@ -67,8 +68,9 @@ namespace conf cfg.system.max_cpu_us = 5000000; // CPU cfs period cannot be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000) per instance. cfg.system.max_storage_kbytes = 2048000; // Total 2GB - cfg.docker.images["ubt.20.04"] = "hotpocketdev/sashimono:hp-ubt.20.04"; - cfg.docker.images["ubt.20.04-njs.14"] = "hotpocketdev/sashimono:hp-ubt.20.04-njs.14"; + const std::string img_prefix = registry_addr.empty() ? "hotpocketdev" : std::string(registry_addr); + cfg.docker.images["ubt.20.04"] = img_prefix + "/sashimono:hp-ubt.20.04"; + cfg.docker.images["ubt.20.04-njs.14"] = img_prefix + "/sashimono:hp-ubt.20.04-njs.14"; cfg.log.max_file_count = 50; cfg.log.max_mbytes_per_file = 10; diff --git a/src/conf.hpp b/src/conf.hpp index ad52a8c..7a843de 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -51,29 +51,6 @@ namespace conf return uid <= 0 && gid <= 0; } - int from_string(std::string_view str) - { - if (str.empty()) - return 0; - - std::vector ids; - util::split_string(ids, str, ":"); - if (ids.size() == 2) - { - const int _uid = atoi(ids[0].c_str()); - const int _gid = atoi(ids[1].c_str()); - - if (_uid > 0 && _gid > 0) - { - uid = _uid; - gid = _gid; - return 0; - } - } - - return -1; - } - const std::string to_string() const { return (uid == 0 && gid == 0) ? "" : (std::to_string(uid) + ":" + std::to_string(gid)); @@ -150,7 +127,7 @@ namespace conf int init(); - int create(); + int create(std::string_view host_addr, std::string_view registry_addr); void set_dir_paths(std::string exepath, std::string datadir); diff --git a/src/main.cpp b/src/main.cpp index 238ac8f..e8527f7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,8 @@ std::cerr << "Arguments mismatch.\n"; \ std::cerr << "Usage:\n"; \ std::cerr << "sagent version\n"; \ - std::cerr << "sagent [data_dir]\n"; \ + std::cerr << "sagent new [data_dir] [host_addr] [registry_addr]\n"; \ + std::cerr << "sagent run [data_dir]\n"; \ std::cerr << "Example: sagent run /etc/sashimono\n"; \ return -1; \ } @@ -35,16 +36,10 @@ int parse_cmd(int argc, char **argv) { conf::ctx.command = argv[1]; - if (conf::ctx.command == "new" || conf::ctx.command == "run") - { - // We populate the global contract ctx with the detected command. - conf::set_dir_paths(argv[0], (argc == 3) ? argv[2] : ""); + if ((conf::ctx.command == "new" && argc >= 2 && argc <= 5) || + (conf::ctx.command == "run" && argc >= 2 && argc <= 3) || + (conf::ctx.command == "version" && argc == 2)) return 0; - } - else if (conf::ctx.command == "version") - { - return 0; - } } // If all extractions fail display help message and return -1. @@ -135,12 +130,18 @@ int main(int argc, char **argv) } if (conf::ctx.command == "new") { + conf::set_dir_paths(argv[0], (argc >= 3) ? argv[2] : ""); + // This will create a new config. - if (conf::create() != 0) + const std::string host_addr = (argc >= 4) ? argv[3] : ""; + const std::string registry_addr = (argc >= 5) ? argv[4] : ""; + if (conf::create(host_addr, registry_addr) != 0) return -1; } else if (conf::ctx.command == "run") { + conf::set_dir_paths(argv[0], (argc == 3) ? argv[2] : ""); + if (kill_switch(util::get_epoch_milliseconds())) { std::cerr << "Sashimono Agent usage limit failure.\n";