forked from p15670423/monkey
Merge pull request #1367 from guardicore/local-docker-build
Local docker build
This commit is contained in:
commit
3def533502
|
@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- The capability for a user to specify their own SSL certificate. #1208
|
- The capability for a user to specify their own SSL certificate. #1208
|
||||||
- API endpoint for ransomware report. #1297
|
- API endpoint for ransomware report. #1297
|
||||||
- Add ransomware report. #1240
|
- Add ransomware report. #1240
|
||||||
|
- A script to build a docker image locally. #1140
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- server_config.json can be selected at runtime. #963
|
- server_config.json can be selected at runtime. #963
|
||||||
|
|
|
@ -9,25 +9,17 @@ Monkey AppImage
|
||||||
|
|
||||||
1. Create a clean VM or LXC (not docker!) based on Ubuntu 18.04.
|
1. Create a clean VM or LXC (not docker!) based on Ubuntu 18.04.
|
||||||
1. Copy the `deployment_scripts/appimage` directory to `$HOME/` in the VM.
|
1. Copy the `deployment_scripts/appimage` directory to `$HOME/` in the VM.
|
||||||
1. Run `sudo -v`.
|
|
||||||
1. On the VM, `cd $HOME/appimage`
|
1. On the VM, `cd $HOME/appimage`
|
||||||
|
1. Run `sudo -v`.
|
||||||
1. Execute `./build_appimage.sh`. This will pull all necessary dependencies
|
1. Execute `./build_appimage.sh`. This will pull all necessary dependencies
|
||||||
and build the AppImage.
|
and build the AppImage.
|
||||||
|
|
||||||
NOTE: This script is intended to be run from a clean VM. You can also manually
|
NOTE: This script is intended to be run from a clean VM. You can also manually
|
||||||
remove build artifacts by removing the following files and directories.
|
remove build artifacts by running `appimage/clean.sh`
|
||||||
|
|
||||||
- $HOME/.monkey_island (optional)
|
|
||||||
- $HOME/appimage/squashfs-root
|
|
||||||
- $HOME/git/monkey
|
|
||||||
- $HOME/appimage/Infection_Monkey*x86_64.AppImage
|
|
||||||
|
|
||||||
After removing the above files and directories, you can again execute `bash
|
|
||||||
build_appimage.sh`.
|
|
||||||
|
|
||||||
## Running the AppImage
|
## Running the AppImage
|
||||||
|
|
||||||
The build script will produce an AppImage executible named
|
The build script will produce an AppImage executable named
|
||||||
`Infection_Monkey-x86_64.AppImage`. Simply execute this file and you're off to
|
`Infection_Monkey-x86_64.AppImage`. Simply execute this file and you're off to
|
||||||
the races.
|
the races.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Infection Monkey
|
||||||
|
|
||||||
|
How to run Monkey Island from the docker file:
|
||||||
|
|
||||||
|
Note: Ports 5000 and 5001 must be available for the island to work.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Run the following commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo docker load -i dk.monkeyisland.MONKEY_VER_PLACEHOLDER.tar
|
||||||
|
sudo docker pull mongo:4.2
|
||||||
|
sudo mkdir -p /var/monkey-mongo/data/db
|
||||||
|
sudo docker run --name monkey-mongo --network=host -v /var/monkey-mongo/data/db:/data/db -d mongo:4.2
|
||||||
|
sudo docker run --name monkey-island --network=host -d guardicore/monkey-island:MONKEY_VER_PLACEHOLDER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Start Infecting
|
||||||
|
|
||||||
|
Open `https://<Server IP>:5000` using Google Chrome and follow the instructions. You can also visit [the Infection Monkey website](https://infectionmonkey.com) and read the in-depth Getting Started guides.
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Install python dependencies using the bitnami/python:3.7 image, which includes
|
||||||
|
# development dependencies.
|
||||||
|
FROM bitnami/python:3.7 as builder
|
||||||
|
COPY ./monkey /monkey
|
||||||
|
WORKDIR /monkey
|
||||||
|
RUN virtualenv .
|
||||||
|
RUN . bin/activate && \
|
||||||
|
cd monkey_island && \
|
||||||
|
pip install pipenv && \
|
||||||
|
pipenv sync
|
||||||
|
|
||||||
|
|
||||||
|
# Build the final application using the bitnami/python:3.7-prod image, which
|
||||||
|
# does not include development dependencies.
|
||||||
|
FROM bitnami/python:3.7-prod
|
||||||
|
RUN apt-get update && apt-get install -y iputils-ping && apt-get clean
|
||||||
|
COPY --from=builder /monkey /monkey
|
||||||
|
WORKDIR /monkey
|
||||||
|
EXPOSE 5000
|
||||||
|
EXPOSE 5001
|
||||||
|
RUN groupadd -r monkey-island && useradd --no-log-init -r -g monkey-island monkey-island
|
||||||
|
RUN chmod 444 /monkey/monkey_island/cc/server.key
|
||||||
|
RUN chmod 444 /monkey/monkey_island/cc/server.csr
|
||||||
|
RUN chmod 444 /monkey/monkey_island/cc/server.crt
|
||||||
|
RUN mkdir /monkey_island_data && chmod 700 /monkey_island_data && chown -R monkey-island:monkey-island /monkey_island_data
|
||||||
|
USER monkey-island
|
||||||
|
ENTRYPOINT ["/monkey/entrypoint.sh"]
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Monkey Island Docker Image
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
This directory contains the necessary artifacts for building an Infection
|
||||||
|
Monkey Docker image.
|
||||||
|
|
||||||
|
## Building a Docker image
|
||||||
|
1. Create a clean Ubuntu 18.04 VM (not WSL).
|
||||||
|
1. Copy the `docker/` directory to `$HOME/` in the VM.
|
||||||
|
1. On the VM, `cd $HOME/docker`
|
||||||
|
1. Run `sudo -v`.
|
||||||
|
1. Execute `./build_docker.sh`. This will pull all necessary dependencies
|
||||||
|
and build the Docker image.
|
||||||
|
|
||||||
|
NOTE: This script is intended to be run from a clean VM. You can also manually
|
||||||
|
remove build rtifacts by running `docker/clean.sh`
|
||||||
|
|
||||||
|
## Running the Docker Image
|
||||||
|
See `docker/DOCKER_README.md` for instructions on running the docker image.
|
|
@ -0,0 +1,316 @@
|
||||||
|
WORKSPACE=${WORKSPACE:-$HOME}
|
||||||
|
|
||||||
|
BUILD_DIR="$PWD/monkey"
|
||||||
|
|
||||||
|
GIT=$WORKSPACE/git
|
||||||
|
|
||||||
|
DEFAULT_REPO_MONKEY_HOME=$GIT/monkey
|
||||||
|
|
||||||
|
ISLAND_PATH="$BUILD_DIR/monkey_island"
|
||||||
|
ISLAND_BINARIES_PATH="$ISLAND_PATH/cc/binaries"
|
||||||
|
|
||||||
|
MONKEY_ORIGIN_URL="https://github.com/guardicore/monkey.git"
|
||||||
|
CONFIG_URL="https://raw.githubusercontent.com/guardicore/monkey/develop/deployment_scripts/config"
|
||||||
|
NODE_SRC=https://deb.nodesource.com/setup_12.x
|
||||||
|
ISLAND_DIR_COPY_TIMEOUT=60 #Seconds
|
||||||
|
|
||||||
|
OUTPUT_NAME_TGZ="$PWD/infection_monkey_docker_$(date +%Y%m%d_%H%M%S).tgz"
|
||||||
|
|
||||||
|
exit_if_missing_argument() {
|
||||||
|
if [ -z "$2" ] || [ "${2:0:1}" == "-" ]; then
|
||||||
|
echo "Error: Argument for $1 is missing" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_help() {
|
||||||
|
echo "usage: build_appimage.sh [--help] [--agent-binary-dir <PATH>] [--branch <BRANCH>]"
|
||||||
|
echo " [--monkey-repo <PATH>] [--version <MONKEY_VERSION>]"
|
||||||
|
echo ""
|
||||||
|
echo "Creates an AppImage package for Infection Monkey."
|
||||||
|
echo ""
|
||||||
|
echo "--agent-binary-dir A directory containing the agent binaries that"
|
||||||
|
echo " you'd like to include with the AppImage. If this"
|
||||||
|
echo " parameter is unspecified, the latest release"
|
||||||
|
echo " binaries will be downloaded from GitHub."
|
||||||
|
echo ""
|
||||||
|
echo "--as-root Throw caution to the wind and allow this script"
|
||||||
|
echo " to be run as root."
|
||||||
|
echo ""
|
||||||
|
echo "--branch The git branch you'd like the AppImage to be"
|
||||||
|
echo " built from. (Default: develop)"
|
||||||
|
echo ""
|
||||||
|
echo "--monkey-repo A directory containing the Infection Monkey git"
|
||||||
|
echo " repository. If the directory is empty or does"
|
||||||
|
echo " not exist, a new repo will be cloned from GitHub."
|
||||||
|
echo " If the directory is already a valid GitHub repo,"
|
||||||
|
echo " it will be used as-is and the --branch parameter"
|
||||||
|
echo " will have no effect."
|
||||||
|
echo " (Default: $DEFAULT_REPO_MONKEY_HOME)"
|
||||||
|
echo ""
|
||||||
|
echo "--version A version number for the AppImage package."
|
||||||
|
echo " (Default: dev)"
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
is_root() {
|
||||||
|
return "$(id -u)"
|
||||||
|
}
|
||||||
|
|
||||||
|
has_sudo() {
|
||||||
|
# 0 true, 1 false
|
||||||
|
sudo -nv > /dev/null 2>&1
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message() {
|
||||||
|
echo -e "\n\n"
|
||||||
|
echo -e "DOCKER IMAGE BUILDER: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_error() {
|
||||||
|
echo "Fix the errors above and rerun the script"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install_nodejs() {
|
||||||
|
log_message "Installing nodejs"
|
||||||
|
|
||||||
|
curl -sL $NODE_SRC | sudo -E bash -
|
||||||
|
sudo apt-get install -y nodejs
|
||||||
|
}
|
||||||
|
|
||||||
|
install_build_prereqs() {
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get upgrade -y
|
||||||
|
|
||||||
|
# monkey island prereqs
|
||||||
|
sudo apt-get install -y curl libcurl4 openssl git build-essential moreutils
|
||||||
|
install_nodejs
|
||||||
|
}
|
||||||
|
|
||||||
|
install_docker() {
|
||||||
|
sudo apt-get install -y docker.io
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_monkey_repo() {
|
||||||
|
local repo_dir=$1
|
||||||
|
local branch=$2
|
||||||
|
|
||||||
|
if [[ ! -d "$repo_dir" ]]; then
|
||||||
|
mkdir -p "$repo_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_message "Cloning files from git"
|
||||||
|
git clone -c core.autocrlf=false --single-branch --recurse-submodules -b "$branch" "$MONKEY_ORIGIN_URL" "$repo_dir" 2>&1 || handle_error
|
||||||
|
}
|
||||||
|
|
||||||
|
is_valid_git_repo() {
|
||||||
|
pushd "$1" 2>/dev/null || return 1
|
||||||
|
git status >/dev/null 2>&1
|
||||||
|
success="$?"
|
||||||
|
popd || exit 1
|
||||||
|
|
||||||
|
return $success
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_build_dir() {
|
||||||
|
local agent_binary_dir=$1
|
||||||
|
local monkey_repo=$2
|
||||||
|
|
||||||
|
mkdir "$BUILD_DIR"
|
||||||
|
|
||||||
|
copy_entrypoint_to_build_dir
|
||||||
|
|
||||||
|
copy_monkey_island_to_build_dir "$monkey_repo/monkey"
|
||||||
|
add_agent_binaries_to_build_dir "$agent_binary_dir"
|
||||||
|
|
||||||
|
generate_ssl_cert
|
||||||
|
|
||||||
|
build_frontend
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_entrypoint_to_build_dir() {
|
||||||
|
cp ./entrypoint.sh "$BUILD_DIR"
|
||||||
|
chmod 755 "$BUILD_DIR/entrypoint.sh"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_monkey_island_to_build_dir() {
|
||||||
|
local src=$1
|
||||||
|
|
||||||
|
cp "$src"/__init__.py "$BUILD_DIR"
|
||||||
|
cp "$src"/monkey_island.py "$BUILD_DIR"
|
||||||
|
cp -v -r "$src"/common "$BUILD_DIR/"
|
||||||
|
|
||||||
|
rsync \
|
||||||
|
-avr \
|
||||||
|
--exclude=monkey_island/cc/ui/node_modules \
|
||||||
|
--exclude=monkey_island/cc/ui/.npm \
|
||||||
|
"$src"/monkey_island "$BUILD_DIR/"
|
||||||
|
|
||||||
|
cp ./server_config.json "$BUILD_DIR"/monkey_island/cc/
|
||||||
|
}
|
||||||
|
|
||||||
|
add_agent_binaries_to_build_dir() {
|
||||||
|
local agent_binary_dir=$1
|
||||||
|
|
||||||
|
if [ -z "$agent_binary_dir" ]; then
|
||||||
|
download_monkey_agent_binaries
|
||||||
|
else
|
||||||
|
copy_agent_binaries_to_appdir "$agent_binary_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
make_linux_binaries_executable
|
||||||
|
}
|
||||||
|
|
||||||
|
download_monkey_agent_binaries() {
|
||||||
|
log_message "Downloading monkey agent binaries to ${ISLAND_BINARIES_PATH}"
|
||||||
|
|
||||||
|
load_monkey_binary_config
|
||||||
|
|
||||||
|
mkdir -p "${ISLAND_BINARIES_PATH}" || handle_error
|
||||||
|
curl -L -o "${ISLAND_BINARIES_PATH}/${LINUX_32_BINARY_NAME}" "${LINUX_32_BINARY_URL}"
|
||||||
|
curl -L -o "${ISLAND_BINARIES_PATH}/${LINUX_64_BINARY_NAME}" "${LINUX_64_BINARY_URL}"
|
||||||
|
curl -L -o "${ISLAND_BINARIES_PATH}/${WINDOWS_32_BINARY_NAME}" "${WINDOWS_32_BINARY_URL}"
|
||||||
|
curl -L -o "${ISLAND_BINARIES_PATH}/${WINDOWS_64_BINARY_NAME}" "${WINDOWS_64_BINARY_URL}"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_monkey_binary_config() {
|
||||||
|
tmpfile=$(mktemp)
|
||||||
|
|
||||||
|
log_message "Downloading prebuilt binary configuration"
|
||||||
|
curl -L -s -o "$tmpfile" "$CONFIG_URL"
|
||||||
|
|
||||||
|
log_message "Loading configuration"
|
||||||
|
source "$tmpfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_agent_binaries_to_appdir() {
|
||||||
|
cp "$1"/* "$ISLAND_BINARIES_PATH/"
|
||||||
|
}
|
||||||
|
|
||||||
|
make_linux_binaries_executable() {
|
||||||
|
chmod a+x "$ISLAND_BINARIES_PATH"/monkey-linux-*
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_ssl_cert() {
|
||||||
|
log_message "Generating certificate"
|
||||||
|
|
||||||
|
chmod u+x "${ISLAND_PATH}"/linux/create_certificate.sh
|
||||||
|
"${ISLAND_PATH}"/linux/create_certificate.sh "${ISLAND_PATH}"/cc
|
||||||
|
}
|
||||||
|
|
||||||
|
build_frontend() {
|
||||||
|
pushd "$ISLAND_PATH/cc/ui" || handle_error
|
||||||
|
|
||||||
|
log_message "Generating front end"
|
||||||
|
npm ci
|
||||||
|
npm run dist
|
||||||
|
|
||||||
|
popd || handle_error
|
||||||
|
|
||||||
|
remove_node_modules
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_node_modules() {
|
||||||
|
# Node has served its purpose. We don't need to deliver the node modules with
|
||||||
|
# the AppImage.
|
||||||
|
rm -rf "$ISLAND_PATH"/cc/ui/node_modules
|
||||||
|
rm -rf "$ISLAND_PATH"/cc/ui/.npm
|
||||||
|
}
|
||||||
|
|
||||||
|
build_docker_image() {
|
||||||
|
local version=$1
|
||||||
|
|
||||||
|
docker_image_name=guardicore/monkey-island:$version
|
||||||
|
tar_name=./dk.monkeyisland.$version.tar
|
||||||
|
|
||||||
|
build_docker_image_tar "$docker_image_name" "$tar_name"
|
||||||
|
build_docker_image_tgz "$tar_name" "$version"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_docker_image_tar() {
|
||||||
|
sudo docker build . -t "$1"
|
||||||
|
sudo docker save "$1" > "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_docker_image_tgz() {
|
||||||
|
mkdir tgz
|
||||||
|
cp "$1" ./tgz
|
||||||
|
cp ./DOCKER_README.md ./tgz/README.md
|
||||||
|
tar -C ./tgz -cvf "$OUTPUT_NAME_TGZ" --gzip .
|
||||||
|
}
|
||||||
|
|
||||||
|
agent_binary_dir=""
|
||||||
|
as_root=false
|
||||||
|
branch="develop"
|
||||||
|
monkey_repo="$DEFAULT_REPO_MONKEY_HOME"
|
||||||
|
monkey_version="dev"
|
||||||
|
|
||||||
|
|
||||||
|
while (( "$#" )); do
|
||||||
|
case "$1" in
|
||||||
|
--agent-binary-dir)
|
||||||
|
exit_if_missing_argument "$1" "$2"
|
||||||
|
|
||||||
|
agent_binary_dir=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--as-root)
|
||||||
|
as_root=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--branch)
|
||||||
|
exit_if_missing_argument "$1" "$2"
|
||||||
|
|
||||||
|
branch=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo_help
|
||||||
|
;;
|
||||||
|
--monkey-repo)
|
||||||
|
exit_if_missing_argument "$1" "$2"
|
||||||
|
|
||||||
|
monkey_repo=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--version)
|
||||||
|
exit_if_missing_argument "$1" "$2"
|
||||||
|
|
||||||
|
monkey_version=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Unsupported parameter $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
log_message "Building Monkey Island Docker image."
|
||||||
|
|
||||||
|
if ! $as_root && is_root; then
|
||||||
|
log_message "Please don't run this script as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! has_sudo; then
|
||||||
|
log_message "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
|
||||||
|
|
||||||
|
install_build_prereqs
|
||||||
|
install_docker
|
||||||
|
|
||||||
|
if ! is_valid_git_repo "$monkey_repo"; then
|
||||||
|
clone_monkey_repo "$monkey_repo" "$branch"
|
||||||
|
fi
|
||||||
|
|
||||||
|
setup_build_dir "$agent_binary_dir" "$monkey_repo"
|
||||||
|
build_docker_image "$monkey_version"
|
||||||
|
|
||||||
|
log_message "Docker build script finished."
|
||||||
|
exit 0
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This is a utility script to clean up after a failed or successful Docker
|
||||||
|
# image build in order to speed up development and debugging
|
||||||
|
|
||||||
|
BUILD_DIR=$HOME/docker
|
||||||
|
|
||||||
|
rm -rf $HOME/git/monkey
|
||||||
|
rm -rf $BUILD_DIR/monkey
|
||||||
|
rm -rf $BUILD_DIR/tgz
|
||||||
|
rm $BUILD_DIR/dk.monkeyisland.*.tar
|
||||||
|
rm $BUILD_DIR/infection_monkey_docker*.tgz
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "$@"
|
||||||
|
|
||||||
|
source /monkey/bin/activate
|
||||||
|
python /monkey/monkey_island.py "$@"
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"data_dir": "/monkey_island_data",
|
||||||
|
"log_level": "DEBUG",
|
||||||
|
"environment": {
|
||||||
|
"server_config": "password",
|
||||||
|
"deployment": "docker"
|
||||||
|
},
|
||||||
|
"mongodb": {
|
||||||
|
"start_mongodb": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue