|
1 |
| -FROM ubuntu:24.04 |
2 |
| -SHELL ["/bin/bash", "-c"] |
3 |
| - |
4 |
| -ARG TZ="UTC" |
5 |
| -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ |
6 |
| - echo $TZ > /etc/timezone |
| 1 | +# This file uses a staged build, using a different stage to build the UI (magma) |
| 2 | +# Build the UI |
| 3 | +FROM node:23 AS ui-build |
7 | 4 |
|
8 | 5 | WORKDIR /usr/src/app
|
9 | 6 |
|
10 |
| -# Make sure user cloned caldera recursively before installing anything. |
11 | 7 | ADD . .
|
12 |
| -RUN if [ -z "$(ls plugins/stockpile)" ]; then echo "stockpile plugin not downloaded - please ensure you recursively cloned the caldera git repository and try again."; exit 1; fi |
13 |
| - |
14 |
| -RUN apt-get update && \ |
15 |
| - apt-get -y install python3 python3-pip python3-venv git curl golang-go |
16 |
| - |
17 |
| - |
18 |
| -#WIN_BUILD is used to enable windows build in sandcat plugin |
19 |
| -ARG WIN_BUILD=false |
20 |
| -RUN if [ "$WIN_BUILD" = "true" ] ; then apt-get -y install mingw-w64; fi |
21 |
| - |
22 |
| -# Set up python virtualenv |
23 |
| -ENV VIRTUAL_ENV=/opt/venv/caldera |
24 |
| -RUN python3 -m venv $VIRTUAL_ENV |
25 |
| -ENV PATH="$VIRTUAL_ENV/bin:$PATH" |
26 |
| - |
27 |
| -# Install pip requirements |
28 |
| -RUN pip3 install --no-cache-dir -r requirements.txt |
29 |
| - |
30 |
| -# Set up config file and disable atomic by default |
31 |
| -RUN python3 -c "import app; import app.utility.config_generator; app.utility.config_generator.ensure_local_config();"; \ |
32 |
| - sed -i '/\- atomic/d' conf/local.yml; |
| 8 | +# Build VueJS front-end |
| 9 | +RUN (cd plugins/magma; npm install && npm run build) |
| 10 | + |
| 11 | +# This is the runtime stage |
| 12 | +# It containes all dependencies required by caldera |
| 13 | +FROM debian:bookworm-slim AS runtime |
| 14 | + |
| 15 | +# There are two variants - slim and full |
| 16 | +# The slim variant excludes some dependencies of *emu* and *atomic* that can be downloaded on-demand if needed |
| 17 | +# They are very large |
| 18 | +ARG VARIANT=full |
| 19 | +ENV VARIANT=${VARIANT} |
| 20 | + |
| 21 | +# Display an error if variant is set incorrectly, otherwise just print information regarding which variant is in use |
| 22 | +RUN if [ "$VARIANT" = "full" ]; then \ |
| 23 | + echo "Building \"full\" container suitable for offline use!"; \ |
| 24 | + elif [ "$VARIANT" = "slim" ]; then \ |
| 25 | + echo "Building slim container - some plugins (emu, atomic) may not be available without an internet connection!"; \ |
| 26 | + else \ |
| 27 | + echo "Invalid Docker build-arg for VARIANT! Please provide either \"full\" or \"slim\"."; \ |
| 28 | + exit 1; \ |
| 29 | +fi |
33 | 30 |
|
34 |
| -# Compile default sandcat agent binaries, which will download basic golang dependencies. |
| 31 | +WORKDIR /usr/src/app |
35 | 32 |
|
36 |
| -# Install Go dependencies |
37 |
| -WORKDIR /usr/src/app/plugins/sandcat/gocat |
38 |
| -RUN go mod tidy && go mod download |
| 33 | +# Copy in source code and compiled UI |
| 34 | +# IMPORTANT NOTE: the .dockerignore file is very important in preventing weird issues. |
| 35 | +# Especially if caldera was ever compiled outside of Docker - we don't want those files to interfere with this build process, |
| 36 | +# which should be repeatable. |
| 37 | +ADD . . |
| 38 | +COPY --from=ui-build /usr/src/app/plugins/magma/dist /usr/src/app/plugins/magma/dist |
39 | 39 |
|
40 |
| -WORKDIR /usr/src/app/plugins/sandcat |
| 40 | +# From https://docs.docker.com/build/building/best-practices/ |
| 41 | +# Install caldera dependencies |
| 42 | +RUN apt-get update && \ |
| 43 | +apt-get --no-install-recommends -y install git curl unzip python3-dev python3-pip golang-go mingw-w64 zlib1g gcc && \ |
| 44 | +rm -rf /var/lib/apt/lists/* |
41 | 45 |
|
42 | 46 | # Fix line ending error that can be caused by cloning the project in a Windows environment
|
43 |
| -RUN if [ "$WIN_BUILD" = "true" ] ; then cp ./update-agents.sh ./update-agents-copy.sh; fi |
44 |
| -RUN if [ "$WIN_BUILD" = "true" ] ; then tr -d '\15\32' < ./update-agents-copy.sh > ./update-agents.sh; fi |
45 |
| -RUN if [ "$WIN_BUILD" = "true" ] ; then rm ./update-agents-copy.sh; fi |
46 |
| - |
47 |
| -RUN ./update-agents.sh |
48 |
| - |
49 |
| -# Check if we can compile the sandcat extensions, which will download golang dependencies for agent extensions |
50 |
| -RUN mkdir /tmp/gocatextensionstest |
51 |
| - |
52 |
| -RUN cp -R ./gocat /tmp/gocatextensionstest/gocat |
53 |
| -RUN cp -R ./gocat-extensions/* /tmp/gocatextensionstest/gocat/ |
| 47 | +RUN cd /usr/src/app/plugins/sandcat; tr -d '\15\32' < ./update-agents.sh > ./update-agents.sh |
54 | 48 |
|
55 |
| -RUN cp ./update-agents.sh /tmp/gocatextensionstest/update-agents.sh |
56 |
| - |
57 |
| -WORKDIR /tmp/gocatextensionstest |
58 |
| - |
59 |
| -RUN mkdir /tmp/gocatextensionstest/payloads |
| 49 | +# Set timezone (default to UTC) |
| 50 | +ARG TZ="UTC" |
| 51 | +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ |
| 52 | + echo $TZ > /etc/timezone |
60 | 53 |
|
61 |
| -RUN ./update-agents.sh |
| 54 | +# Install pip requirements |
| 55 | +RUN pip3 install --break-system-packages --no-cache-dir -r requirements.txt |
| 56 | + |
| 57 | +# For offline atomic (disable it by default in slim image) |
| 58 | +# Disable atomic if this is not downloaded |
| 59 | +RUN if [ ! -d "/usr/src/app/plugins/atomic/data/atomic-red-team" ] && [ "$VARIANT" = "full" ]; then \ |
| 60 | + git clone --depth 1 https://github.com/redcanaryco/atomic-red-team.git \ |
| 61 | + /usr/src/app/plugins/atomic/data/atomic-red-team; \ |
| 62 | + else \ |
| 63 | + sed -i '/\- atomic/d' conf/default.yml; \ |
| 64 | +fi |
62 | 65 |
|
63 |
| -# Clone atomic red team repo for the atomic plugin |
64 |
| -RUN if [ ! -d "/usr/src/app/plugins/atomic/data/atomic-red-team" ]; then \ |
65 |
| - git clone --depth 1 https://github.com/redcanaryco/atomic-red-team.git \ |
66 |
| - /usr/src/app/plugins/atomic/data/atomic-red-team; \ |
| 66 | +# For offline emu |
| 67 | +# (Emu is disabled by default, no need to disable it if slim variant is being built) |
| 68 | +RUN if [ ! -d "/usr/src/app/plugins/emu/data/adversary-emulation-plans" ] && [ "$VARIANT" = "full" ]; then \ |
| 69 | + git clone --depth 1 https://github.com/center-for-threat-informed-defense/adversary_emulation_library \ |
| 70 | + /usr/src/app/plugins/emu/data/adversary-emulation-plans; \ |
67 | 71 | fi
|
68 | 72 |
|
69 |
| -WORKDIR /usr/src/app/plugins/emu |
| 73 | +# Download emu payloads |
| 74 | +# emu doesn't seem capable of running this itself - always download |
| 75 | +RUN cd /usr/src/app/plugins/emu; ./download_payloads.sh |
70 | 76 |
|
71 |
| -# If emu is enabled, complete necessary installation steps |
72 |
| -RUN if [ $(grep -c "\- emu" ../../conf/local.yml) ]; then \ |
73 |
| - apt-get -y install zlib1g unzip; \ |
74 |
| - pip3 install -r requirements.txt; \ |
75 |
| - ./download_payloads.sh; \ |
76 |
| -fi |
| 77 | +# The commands above (git clone) will generate *huge* .git folders - remove them |
| 78 | +RUN (find . -type d -name ".git") | xargs rm -rf |
77 | 79 |
|
78 |
| -WORKDIR /usr/src/app |
| 80 | +# Install Go dependencies |
| 81 | +RUN cd /usr/src/app/plugins/sandcat/gocat; go mod tidy && go mod download |
79 | 82 |
|
80 |
| -# Install Node.js, npm, and other build VueJS front-end |
81 |
| -RUN apt-get update && \ |
82 |
| - apt-get install -y nodejs npm && \ |
83 |
| - # Directly use npm to install dependencies and build the application |
84 |
| - (cd plugins/magma && npm install) && \ |
85 |
| - (cd plugins/magma && npm run build) && \ |
86 |
| - # Remove Node.js, npm, and other unnecessary packages |
87 |
| - apt-get remove -y nodejs npm && \ |
88 |
| - apt-get autoremove -y && \ |
89 |
| - apt-get clean && \ |
90 |
| - rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* |
| 83 | +# Update sandcat agents |
| 84 | +RUN cd /usr/src/app/plugins/sandcat; ./update-agents.sh |
91 | 85 |
|
92 |
| -WORKDIR /usr/src/app |
| 86 | +# Make sure emu can always be used in container (even if not enabled right now) |
| 87 | +RUN cd /usr/src/app/plugins/emu; \ |
| 88 | + pip3 install --break-system-packages -r requirements.txt |
93 | 89 |
|
94 | 90 | STOPSIGNAL SIGINT
|
95 | 91 |
|
|
0 commit comments