diff --git a/build_scripts/appimage/AppRun b/build_scripts/appimage/AppRun index 53ef0fa5e..1ed075693 100755 --- a/build_scripts/appimage/AppRun +++ b/build_scripts/appimage/AppRun @@ -13,6 +13,10 @@ export TKPATH="${TK_LIBRARY}" # Export SSL certificate export SSL_CERT_FILE="${APPDIR}/opt/_internal/certs.pem" +if [ "$1" == "service" ] ; then + exec /bin/bash "${APPDIR}/install-infection-monkey-service.sh" ${@:2} +fi + # Call the entry point for opt in "$@" do diff --git a/build_scripts/appimage/appimage.sh b/build_scripts/appimage/appimage.sh index e5c6b97bf..16652c081 100755 --- a/build_scripts/appimage/appimage.sh +++ b/build_scripts/appimage/appimage.sh @@ -38,6 +38,7 @@ setup_build_dir() { copy_monkey_island_to_build_dir "$monkey_repo/monkey" "$BUILD_DIR" copy_server_config_to_build_dir + copy_infection_monkey_service_to_build_dir modify_deployment "$deployment_type" "$BUILD_DIR" add_agent_binaries_to_build_dir "$agent_binary_dir" "$BUILD_DIR" @@ -64,8 +65,12 @@ setup_python_37_appdir() { rm "$PYTHON_APPIMAGE" } +copy_infection_monkey_service_to_build_dir() { + cp "$APPIMAGE_DIR"/install-infection-monkey-service.sh "$APPDIR" +} + copy_server_config_to_build_dir() { - cp "$APPIMAGE_DIR"/server_config.json.standard "$BUILD_DIR"/monkey_island/cc/server_config.json + cp "$APPIMAGE_DIR"/server_config.json.standard "$BUILD_DIR"/monkey_island/cc/server_config.json } install_monkey_island_python_dependencies() { diff --git a/build_scripts/appimage/install-infection-monkey-service.sh b/build_scripts/appimage/install-infection-monkey-service.sh new file mode 100755 index 000000000..596dad010 --- /dev/null +++ b/build_scripts/appimage/install-infection-monkey-service.sh @@ -0,0 +1,165 @@ +#!/bin/bash + +set -e + +SCRIPT_NAME="$(basename "${APPIMAGE}")" +SYSTEMD_UNIT_FILENAME="infection-monkey.service" +TMP_SYSTEMD_UNIT="${PWD}/${SYSTEMD_UNIT_FILENAME}" +SYSTEMD_DIR="/lib/systemd/system" +MONKEY_BIN="/opt/infection-monkey/bin" +APPIMAGE_NAME="InfectionMonkey.AppImage" + +die() { + echo "$1" >&2 + echo "" + echo_help + exit 1 +} + +echo_help() { + echo "Installs the Infection Monkey service to run on boot." + echo "" + echo "Usage:" + echo " ${SCRIPT_NAME} service --install --user " + echo " ${SCRIPT_NAME} service --uninstall" + echo " ${SCRIPT_NAME} service -h|--help" + echo "" + echo "Options:" + echo " --install Install the Infection Monkey service" + echo " --user Configure the Infection Monkey service to run as a specific user" + echo " --uninstall Uninstall Infection Monkey service" +} + +install_service() { + copy_appimage + install_systemd_unit "$1" + + echo "The Infection Monkey service has been installed and will start on boot." + echo "Run 'systemctl start infection-monkey' to start the service now." +} + +copy_appimage() { + sudo mkdir --mode=0755 -p "${MONKEY_BIN}" + + if [ "${APPIMAGE}" != "${MONKEY_BIN}/${APPIMAGE_NAME}" ] ; then + umask 022 + sudo cp "${APPIMAGE}" "${MONKEY_BIN}/${APPIMAGE_NAME}" + sudo chmod 755 "${MONKEY_BIN}/${APPIMAGE_NAME}" + fi +} + +install_systemd_unit() { + umask 077 + cat > "${TMP_SYSTEMD_UNIT}" << EOF +[Unit] +Description=Infection Monkey Runner +After=network.target + +[Service] +User=$1 +Type=simple +ExecStart="${MONKEY_BIN}/${APPIMAGE_NAME}" + +[Install] +WantedBy=multi-user.target +EOF + + sudo mv "${TMP_SYSTEMD_UNIT}" "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}" + sudo systemctl enable "${SYSTEMD_UNIT_FILENAME}" &>/dev/null +} + +uninstall_service() { + if [ -f "${MONKEY_BIN}/${APPIMAGE_NAME}" ] ; then + sudo rm -f "${MONKEY_BIN}/${APPIMAGE_NAME}" + fi + + if [ -f "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}" ] ; then + sudo systemctl stop "${SYSTEMD_UNIT_FILENAME}" 2>/dev/null + sudo systemctl disable "${SYSTEMD_UNIT_FILENAME}" &>/dev/null + sudo rm "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}" + sudo systemctl daemon-reload + fi + + echo "The Infection Monkey service has been uninstalled" +} + +exit_if_user_doesnt_exist() { + if ! user_exists "$1" ; then + die "Error: User '$1' does not exist." + fi +} + +user_exists() { + id -u "$1" &>/dev/null +} + +has_sudo() { + # 0 true, 1 false + sudo -nv > /dev/null 2>&1 + return $? +} + +exit_if_missing_argument() { + if [ -z "$2" ] || [ "${2:0:1}" == "-" ]; then + die "Error: Argument for parameter '$1' is missing." + fi +} + +do_uninstall=false +do_install=false +username="" + +while (( "$#" )); do + case "$1" in + --user) + exit_if_missing_argument "$1" "$2" + exit_if_user_doesnt_exist "$2" + username=$2 + shift 2 + ;; + --install) + do_install=true + shift + ;; + --uninstall) + do_uninstall=true + shift + ;; + -h|--help) + echo_help + exit 0 + ;; + *) + die "Error: Unsupported parameter $1." + ;; + esac +done + +if ! has_sudo; then + die "Error: You need root permissions for some of this script operations. \ +Run \`sudo -v\`, enter your password, and then re-run this script." +fi + +if [ -z "${APPIMAGE}" ] ; then + die "Error: Missing 'APPIMAGE' environment variable. Try installing the Infection Monkey service through the AppImage" +fi + +if $do_install && $do_uninstall ; then + die "Error: The --install and --uninstall flags are mutually exclusive." +fi + +if $do_uninstall ; then + uninstall_service + exit 0 +fi + +if $do_install ; then + if [ -z "$username" ] ; then + die "Error: You must supply a username." + fi + + install_service "$username" + exit 0 +fi + +die "Error:You must specify either the --install or --uninstall flag." diff --git a/deployment_scripts/install-infection-monkey-service.sh b/deployment_scripts/install-infection-monkey-service.sh deleted file mode 100755 index e2c9a926f..000000000 --- a/deployment_scripts/install-infection-monkey-service.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash - -set -e - -SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" -SYSTEMD_UNIT_FILENAME="infection-monkey.service" -SYSTEMD_DIR="/lib/systemd/system" -MONKEY_BIN="/opt/infection-monkey/bin" -APPIMAGE_NAME="InfectionMonkey.AppImage" - -echo_help() { - echo "Installs the Infection Monkey service to run on boot." - echo "" - echo "Usage:" - echo " install-infection-monkey-service.sh --user --appimage " - echo " install-infection-monkey-service.sh --uninstall" - echo " install-infection-monkey-service.sh -h|--help" - echo "" - echo "Options:" - echo " --user User to run the service as" - echo " --appimage Path to AppImage" - echo " --uninstall Uninstall the Infection Monkey service" -} - -install_service() { - move_appimage "$2" - - cat > "${SCRIPT_DIR}/${SYSTEMD_UNIT_FILENAME}" << EOF -[Unit] -Description=Infection Monkey Runner -After=network.target - -[Service] -User=$1 -Type=simple -ExecStart="${MONKEY_BIN}/${APPIMAGE_NAME}" - -[Install] -WantedBy=multi-user.target -EOF - - umask 077 - sudo mv "${SCRIPT_DIR}/${SYSTEMD_UNIT_FILENAME}" "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}" - sudo systemctl enable "${SYSTEMD_UNIT_FILENAME}" &>/dev/null - - echo -e "The Infection Monkey service has been installed and will start on boot.\n\ -Run 'systemctl start infection-monkey' to start the service now." -} - -uninstall_service() { - if [ -f "${MONKEY_BIN}/${APPIMAGE_NAME}" ] ; then - sudo rm -f "${MONKEY_BIN}/${APPIMAGE_NAME}" - fi - - if [ -f "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}" ] ; then - sudo systemctl stop "${SYSTEMD_UNIT_FILENAME}" 2>/dev/null - sudo systemctl disable "${SYSTEMD_UNIT_FILENAME}" &>/dev/null - sudo rm "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}" - sudo systemctl daemon-reload - fi - - echo "The Infection Monkey service has been uninstalled" -} - -move_appimage() { - sudo mkdir --mode=0755 -p "${MONKEY_BIN}" - - if [ "$1" != "${MONKEY_BIN}/${APPIMAGE_NAME}" ] ; then - umask 022 - sudo cp "$appimage_path" "${MONKEY_BIN}/${APPIMAGE_NAME}" - sudo chmod 755 "${MONKEY_BIN}/${APPIMAGE_NAME}" - fi -} - -user_exists() { - id -u "$1" &>/dev/null -} - -assert_parameter_supplied() { - if [ -z "$2" ] ; then - echo "Error: missing required parameter '$1'" - echo_help - exit 1 - fi -} - -has_sudo() { - # 0 true, 1 false - sudo -nv > /dev/null 2>&1 - return $? -} - -exit_if_missing_argument() { - if [ -z "$2" ] || [ "${2:0:1}" == "-" ]; then - echo "Error: Argument for parameter '$1' is missing" >&2 - echo_help - exit 1 - fi -} - -do_uninstall=false -uname="" -appimage_path="" - -while (( "$#" )); do - case "$1" in - --user) - exit_if_missing_argument "$1" "$2" - - uname=$2 - shift 2 - ;; - --appimage) - exit_if_missing_argument "$1" "$2" - - appimage_path=$2 - shift 2 - ;; - --uninstall) - do_uninstall=true - shift - ;; - -h|--help) - echo_help - exit 0 - ;; - *) - echo "Error: Unsupported parameter $1" >&2 - exit 1 - ;; - esac -done - -if ! has_sudo; then - echo "Error: You need root permissions for some of this script operations. \ -Run \`sudo -v\`, enter your password, and then re-run this script." - exit 1 -fi - -if $do_uninstall ; then - uninstall_service - exit 0 -fi - -assert_parameter_supplied "--user" "$uname" -assert_parameter_supplied "--appimage" "$appimage_path" - -if ! user_exists "$uname" ; then - echo "Error: User '$uname' does not exist" - exit 1 -fi - -if [ ! -f "$appimage_path" ] ; then - if [ ! -f "${SCRIPT_DIR}/$appimage_path" ] ; then - echo "Error: AppImage '$appimage_path' does not exist" - exit 1 - fi - appimage_path="${SCRIPT_DIR}/$appimage_path" -fi - -install_service "$uname" "$appimage_path"