Spaces:
Runtime error
Runtime error
Aaron Brown commited on
Commit Β·
58f7026
1
Parent(s): 8691b5f
Snapshot-driven service lifecycle, fix Bookworm build
Browse files- Dockerfile: remove nikto/hydra (not in Debian repos), install sqlmap
via pip, start only uvicorn at boot (no hardcoded services)
- start.sh: now snapshot-driven β reads spec.json topology.hosts to
determine which services to start per episode. Called by reset(),
not at container boot.
- Removes hardcoded infra assumptions β services scale with manifest
- Dockerfile +22 -14
- start.sh +116 -149
Dockerfile
CHANGED
|
@@ -1,15 +1,20 @@
|
|
| 1 |
# =============================================================================
|
| 2 |
# OpenRange β Production All-in-One Dockerfile
|
| 3 |
# =============================================================================
|
| 4 |
-
# Python 3.11 base
|
| 5 |
-
#
|
|
|
|
|
|
|
|
|
|
| 6 |
# =============================================================================
|
| 7 |
|
| 8 |
FROM python:3.11-slim-bookworm
|
| 9 |
|
| 10 |
ENV DEBIAN_FRONTEND=noninteractive
|
| 11 |
|
| 12 |
-
# ββ 1. System packages
|
|
|
|
|
|
|
| 13 |
|
| 14 |
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 15 |
# Web
|
|
@@ -26,26 +31,29 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
| 26 |
postfix \
|
| 27 |
# SSH
|
| 28 |
openssh-server \
|
| 29 |
-
#
|
| 30 |
-
nmap
|
| 31 |
netcat-openbsd dnsutils tcpdump curl wget sshpass \
|
| 32 |
iputils-ping whois \
|
| 33 |
# Utilities
|
| 34 |
jq procps iproute2 git ca-certificates bash \
|
| 35 |
&& rm -rf /var/lib/apt/lists/*
|
| 36 |
|
| 37 |
-
#
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
RUN pip install --no-cache-dir uv
|
| 40 |
|
| 41 |
-
# ββ 3. Create directories
|
| 42 |
|
| 43 |
-
RUN mkdir -p /var/log/siem/consolidated /run/sshd
|
| 44 |
/var/run/mysqld /var/log/mysql /var/log/nginx \
|
| 45 |
&& chown mysql:mysql /var/run/mysqld /var/log/mysql 2>/dev/null || true \
|
| 46 |
&& chmod 755 /var/log/siem
|
| 47 |
|
| 48 |
-
# ββ 4. Copy application code and install Python deps ββββββββββββββββββββββββ
|
| 49 |
|
| 50 |
WORKDIR /app
|
| 51 |
COPY . /app/env
|
|
@@ -59,19 +67,19 @@ RUN uv venv --python python3.11 /app/.venv \
|
|
| 59 |
uv sync --no-editable; \
|
| 60 |
fi
|
| 61 |
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
# ββ 5. Environment ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 65 |
|
| 66 |
ENV PATH="/app/.venv/bin:$PATH"
|
| 67 |
ENV PYTHONPATH="/app/env/src:/app/env:$PYTHONPATH"
|
| 68 |
ENV OPENRANGE_EXECUTION_MODE=subprocess
|
| 69 |
|
| 70 |
-
# ββ 6. Health check
|
| 71 |
|
| 72 |
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
| 73 |
CMD python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
|
| 74 |
|
| 75 |
EXPOSE 8000
|
| 76 |
|
| 77 |
-
|
|
|
|
|
|
|
|
|
| 1 |
# =============================================================================
|
| 2 |
# OpenRange β Production All-in-One Dockerfile
|
| 3 |
# =============================================================================
|
| 4 |
+
# Python 3.11 base image with system packages available for procedural
|
| 5 |
+
# service provisioning. The OpenEnv server (uvicorn) is the only process
|
| 6 |
+
# started at boot β individual services (mysql, nginx, slapd, β¦) are
|
| 7 |
+
# started/stopped dynamically by RangeEnvironment.reset() based on the
|
| 8 |
+
# active snapshot manifest. No services are hardcoded.
|
| 9 |
# =============================================================================
|
| 10 |
|
| 11 |
FROM python:3.11-slim-bookworm
|
| 12 |
|
| 13 |
ENV DEBIAN_FRONTEND=noninteractive
|
| 14 |
|
| 15 |
+
# ββ 1. System packages βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 16 |
+
# Install the *superset* of packages that any tier might need.
|
| 17 |
+
# The Builder/manifest decides which ones actually run per episode.
|
| 18 |
|
| 19 |
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 20 |
# Web
|
|
|
|
| 31 |
postfix \
|
| 32 |
# SSH
|
| 33 |
openssh-server \
|
| 34 |
+
# Recon & exploitation (available to agents via subprocess)
|
| 35 |
+
nmap \
|
| 36 |
netcat-openbsd dnsutils tcpdump curl wget sshpass \
|
| 37 |
iputils-ping whois \
|
| 38 |
# Utilities
|
| 39 |
jq procps iproute2 git ca-certificates bash \
|
| 40 |
&& rm -rf /var/lib/apt/lists/*
|
| 41 |
|
| 42 |
+
# Python-based security tools (not in Debian repos)
|
| 43 |
+
RUN pip install --no-cache-dir sqlmap
|
| 44 |
+
|
| 45 |
+
# ββ 2. Install uv for dependency management ββββββββββββββββββββββββββββββββββ
|
| 46 |
|
| 47 |
RUN pip install --no-cache-dir uv
|
| 48 |
|
| 49 |
+
# ββ 3. Create base directories βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 50 |
|
| 51 |
+
RUN mkdir -p /var/log/siem/consolidated /run/sshd \
|
| 52 |
/var/run/mysqld /var/log/mysql /var/log/nginx \
|
| 53 |
&& chown mysql:mysql /var/run/mysqld /var/log/mysql 2>/dev/null || true \
|
| 54 |
&& chmod 755 /var/log/siem
|
| 55 |
|
| 56 |
+
# ββ 4. Copy application code and install Python deps βββββββββββββββββββββββββ
|
| 57 |
|
| 58 |
WORKDIR /app
|
| 59 |
COPY . /app/env
|
|
|
|
| 67 |
uv sync --no-editable; \
|
| 68 |
fi
|
| 69 |
|
| 70 |
+
# ββ 5. Environment βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
|
|
|
| 71 |
|
| 72 |
ENV PATH="/app/.venv/bin:$PATH"
|
| 73 |
ENV PYTHONPATH="/app/env/src:/app/env:$PYTHONPATH"
|
| 74 |
ENV OPENRANGE_EXECUTION_MODE=subprocess
|
| 75 |
|
| 76 |
+
# ββ 6. Health check ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 77 |
|
| 78 |
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
| 79 |
CMD python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
|
| 80 |
|
| 81 |
EXPOSE 8000
|
| 82 |
|
| 83 |
+
# ββ 7. Start only the OpenEnv server β services are snapshot-driven ββββββββββ
|
| 84 |
+
|
| 85 |
+
CMD ["python3", "-m", "uvicorn", "open_range.server.app:app", "--host", "0.0.0.0", "--port", "8000"]
|
start.sh
CHANGED
|
@@ -1,15 +1,20 @@
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
# =============================================================================
|
| 3 |
-
# OpenRange β
|
| 4 |
# =============================================================================
|
| 5 |
-
#
|
| 6 |
-
#
|
| 7 |
-
#
|
| 8 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
# =============================================================================
|
| 10 |
|
| 11 |
set -uo pipefail
|
| 12 |
|
|
|
|
| 13 |
LOGDIR="/var/log/siem"
|
| 14 |
CONSOLIDATED="${LOGDIR}/consolidated"
|
| 15 |
|
|
@@ -26,193 +31,155 @@ cleanup() {
|
|
| 26 |
}
|
| 27 |
trap cleanup EXIT INT TERM
|
| 28 |
|
| 29 |
-
# ββ
|
| 30 |
|
| 31 |
-
echo "[start.sh] Creating required directories..."
|
| 32 |
mkdir -p "${CONSOLIDATED}"
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
if [ ! -d /var/lib/mysql/mysql ]; then
|
| 49 |
-
echo "[start.sh] Initializing database data directory..."
|
| 50 |
if command -v mariadb-install-db >/dev/null 2>&1; then
|
| 51 |
mariadb-install-db --user=mysql 2>&1 | tee "${LOGDIR}/mysql.log"
|
| 52 |
else
|
| 53 |
-
|
| 54 |
fi
|
| 55 |
fi
|
| 56 |
|
| 57 |
$MYSQLD --user=mysql --log-error="${LOGDIR}/mysql.log" &
|
| 58 |
PIDS+=($!)
|
| 59 |
|
| 60 |
-
|
| 61 |
-
ADMIN_CMD=$(command -v mariadb-admin || command -v mysqladmin || echo "")
|
| 62 |
for i in $(seq 1 30); do
|
| 63 |
-
if [ -n "$
|
| 64 |
-
echo " ready (${i}s)"
|
| 65 |
-
break
|
| 66 |
fi
|
| 67 |
-
echo -n "."
|
| 68 |
sleep 1
|
| 69 |
-
if [ "$i" -eq 30 ]; then
|
| 70 |
-
echo " TIMEOUT"
|
| 71 |
-
echo "[start.sh] WARNING: Database did not become ready in 30s"
|
| 72 |
-
fi
|
| 73 |
done
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
fi
|
| 77 |
-
|
| 78 |
-
# ββ 3. PHP-FPM ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 79 |
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
$PHP_FPM --nodaemonize --force-stderr \
|
| 85 |
-
> "${LOGDIR}/php-fpm.log" 2>&1 &
|
| 86 |
PIDS+=($!)
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
for i in $(seq 1 15); do
|
| 91 |
-
if ls /run/php/php*-fpm.sock >/dev/null 2>&1; then
|
| 92 |
-
echo " ready (${i}s)"
|
| 93 |
-
break
|
| 94 |
fi
|
| 95 |
-
echo -n "."
|
| 96 |
sleep 1
|
| 97 |
-
if [ "$i" -eq 15 ]; then
|
| 98 |
-
echo " TIMEOUT"
|
| 99 |
-
echo "[start.sh] WARNING: PHP-FPM socket not found after 15s"
|
| 100 |
-
fi
|
| 101 |
done
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
fi
|
| 105 |
-
|
| 106 |
-
# ββ 4. Nginx ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 107 |
-
|
| 108 |
-
echo "[start.sh] Starting Nginx..."
|
| 109 |
-
nginx -g "daemon off;" \
|
| 110 |
-
> "${LOGDIR}/nginx.log" 2>&1 &
|
| 111 |
-
PIDS+=($!)
|
| 112 |
-
|
| 113 |
-
echo -n "[start.sh] Waiting for Nginx readiness"
|
| 114 |
-
for i in $(seq 1 10); do
|
| 115 |
-
if curl -sf http://localhost:80/ >/dev/null 2>&1 || \
|
| 116 |
-
curl -sf http://localhost:80/ 2>&1 | grep -q ""; then
|
| 117 |
-
echo " ready (${i}s)"
|
| 118 |
-
break
|
| 119 |
-
fi
|
| 120 |
-
echo -n "."
|
| 121 |
-
sleep 1
|
| 122 |
-
if [ "$i" -eq 10 ]; then
|
| 123 |
-
echo " TIMEOUT"
|
| 124 |
-
echo "[start.sh] WARNING: Nginx did not respond within 10s"
|
| 125 |
-
fi
|
| 126 |
-
done
|
| 127 |
-
|
| 128 |
-
# ββ 5. rsyslog ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 129 |
-
|
| 130 |
-
echo "[start.sh] Starting rsyslog..."
|
| 131 |
-
rsyslogd -n \
|
| 132 |
-
> "${LOGDIR}/rsyslog.log" 2>&1 &
|
| 133 |
-
PIDS+=($!)
|
| 134 |
-
echo "[start.sh] rsyslog started (PID $!)"
|
| 135 |
-
|
| 136 |
-
# ββ 6. slapd (OpenLDAP) ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 137 |
|
| 138 |
-
|
| 139 |
-
if command -v slapd >/dev/null 2>&1; then
|
| 140 |
-
|
| 141 |
-
|
| 142 |
PIDS+=($!)
|
| 143 |
-
|
| 144 |
-
echo -n "[start.sh] Waiting for slapd readiness"
|
| 145 |
for i in $(seq 1 10); do
|
| 146 |
if ldapsearch -x -H ldap://localhost -b "" -s base namingContexts >/dev/null 2>&1; then
|
| 147 |
-
echo " ready (${i}s)"
|
| 148 |
-
break
|
| 149 |
fi
|
| 150 |
-
echo -n "."
|
| 151 |
sleep 1
|
| 152 |
-
if [ "$i" -eq 10 ]; then
|
| 153 |
-
echo " TIMEOUT"
|
| 154 |
-
echo "[start.sh] WARNING: slapd did not respond within 10s"
|
| 155 |
-
fi
|
| 156 |
done
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
fi
|
| 160 |
-
|
| 161 |
-
# ββ 7. Samba (smbd) βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 162 |
|
| 163 |
-
|
| 164 |
-
if command -v
|
| 165 |
-
|
| 166 |
-
> "${LOGDIR}/smbd.log" 2>&1 &
|
| 167 |
PIDS+=($!)
|
|
|
|
|
|
|
| 168 |
|
| 169 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
for i in $(seq 1 10); do
|
| 171 |
if smbclient -L localhost -N >/dev/null 2>&1; then
|
| 172 |
-
echo " ready (${i}s)"
|
| 173 |
-
break
|
| 174 |
fi
|
| 175 |
-
echo -n "."
|
| 176 |
sleep 1
|
| 177 |
-
if [ "$i" -eq 10 ]; then
|
| 178 |
-
echo " TIMEOUT"
|
| 179 |
-
echo "[start.sh] WARNING: smbd did not respond within 10s"
|
| 180 |
-
fi
|
| 181 |
done
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
fi
|
| 185 |
-
|
| 186 |
-
# ββ 8. Postfix ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 187 |
|
| 188 |
-
|
| 189 |
-
if command -v postfix >/dev/null 2>&1; then
|
| 190 |
postfix start > "${LOGDIR}/postfix.log" 2>&1 || true
|
| 191 |
-
echo "[start.sh]
|
| 192 |
-
|
| 193 |
-
echo "[start.sh] postfix not installed, skipping"
|
| 194 |
-
fi
|
| 195 |
-
|
| 196 |
-
# ββ 9. SSH ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 197 |
|
| 198 |
-
|
| 199 |
-
if command -v sshd >/dev/null 2>&1; then
|
|
|
|
| 200 |
/usr/sbin/sshd -E "${LOGDIR}/sshd.log" &
|
| 201 |
PIDS+=($!)
|
| 202 |
-
echo "[start.sh] sshd started
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
|
| 207 |
-
|
|
|
|
|
|
|
|
|
|
| 208 |
|
| 209 |
echo "============================================================"
|
| 210 |
-
echo "[start.sh]
|
| 211 |
echo "[start.sh] Logs at: ${LOGDIR}/"
|
| 212 |
-
echo "[start.sh] Starting uvicorn on port 8000..."
|
| 213 |
echo "============================================================"
|
| 214 |
-
|
| 215 |
-
# ββ 10. exec uvicorn as PID 1 ββββββββββββββββββββββββββββββββββββββββββββββ
|
| 216 |
-
|
| 217 |
-
cd /app/env
|
| 218 |
-
exec python3 -m uvicorn open_range.server.app:app --host 0.0.0.0 --port 8000
|
|
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
# =============================================================================
|
| 3 |
+
# OpenRange β Snapshot-Driven Service Startup
|
| 4 |
# =============================================================================
|
| 5 |
+
# Called by RangeEnvironment.reset() to start services defined in a snapshot.
|
| 6 |
+
# NOT called at container boot β the Dockerfile starts only uvicorn.
|
| 7 |
+
#
|
| 8 |
+
# Usage: start.sh <snapshot_dir>
|
| 9 |
+
# snapshot_dir must contain a spec.json with a topology.hosts list.
|
| 10 |
+
# Each host name maps to a known service (nginx, mysql, slapd, etc.).
|
| 11 |
+
#
|
| 12 |
+
# Services are started based on what the snapshot requires, not hardcoded.
|
| 13 |
# =============================================================================
|
| 14 |
|
| 15 |
set -uo pipefail
|
| 16 |
|
| 17 |
+
SNAPSHOT_DIR="${1:?Usage: start.sh <snapshot_dir>}"
|
| 18 |
LOGDIR="/var/log/siem"
|
| 19 |
CONSOLIDATED="${LOGDIR}/consolidated"
|
| 20 |
|
|
|
|
| 31 |
}
|
| 32 |
trap cleanup EXIT INT TERM
|
| 33 |
|
| 34 |
+
# ββ Parse snapshot topology βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 35 |
|
|
|
|
| 36 |
mkdir -p "${CONSOLIDATED}"
|
| 37 |
+
|
| 38 |
+
if [ ! -f "${SNAPSHOT_DIR}/spec.json" ]; then
|
| 39 |
+
echo "[start.sh] ERROR: No spec.json found in ${SNAPSHOT_DIR}"
|
| 40 |
+
exit 1
|
| 41 |
+
fi
|
| 42 |
+
|
| 43 |
+
# Extract host list from topology
|
| 44 |
+
HOSTS=$(python3 -c "
|
| 45 |
+
import json, sys
|
| 46 |
+
with open('${SNAPSHOT_DIR}/spec.json') as f:
|
| 47 |
+
spec = json.load(f)
|
| 48 |
+
hosts = spec.get('topology', {}).get('hosts', [])
|
| 49 |
+
print(' '.join(hosts))
|
| 50 |
+
" 2>/dev/null || echo "")
|
| 51 |
+
|
| 52 |
+
echo "[start.sh] Snapshot hosts: ${HOSTS:-none}"
|
| 53 |
+
|
| 54 |
+
# ββ Service starters (called only if snapshot needs them) βββββββββββββββββββββ
|
| 55 |
+
|
| 56 |
+
start_mysql() {
|
| 57 |
+
local MYSQLD=$(command -v mariadbd || command -v mysqld || echo "")
|
| 58 |
+
if [ -z "$MYSQLD" ]; then echo "[start.sh] mysql: not installed"; return; fi
|
| 59 |
+
|
| 60 |
+
mkdir -p /var/run/mysqld && chown mysql:mysql /var/run/mysqld 2>/dev/null || true
|
| 61 |
+
mkdir -p /var/log/mysql && chown mysql:mysql /var/log/mysql 2>/dev/null || true
|
| 62 |
+
|
| 63 |
if [ ! -d /var/lib/mysql/mysql ]; then
|
|
|
|
| 64 |
if command -v mariadb-install-db >/dev/null 2>&1; then
|
| 65 |
mariadb-install-db --user=mysql 2>&1 | tee "${LOGDIR}/mysql.log"
|
| 66 |
else
|
| 67 |
+
$MYSQLD --initialize-insecure --user=mysql 2>&1 | tee "${LOGDIR}/mysql.log"
|
| 68 |
fi
|
| 69 |
fi
|
| 70 |
|
| 71 |
$MYSQLD --user=mysql --log-error="${LOGDIR}/mysql.log" &
|
| 72 |
PIDS+=($!)
|
| 73 |
|
| 74 |
+
local ADMIN=$(command -v mariadb-admin || command -v mysqladmin || echo "")
|
|
|
|
| 75 |
for i in $(seq 1 30); do
|
| 76 |
+
if [ -n "$ADMIN" ] && $ADMIN ping --silent 2>/dev/null; then
|
| 77 |
+
echo "[start.sh] mysql: ready (${i}s)"; return
|
|
|
|
| 78 |
fi
|
|
|
|
| 79 |
sleep 1
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
done
|
| 81 |
+
echo "[start.sh] mysql: timeout"
|
| 82 |
+
}
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
+
start_nginx() {
|
| 85 |
+
if ! command -v nginx >/dev/null 2>&1; then echo "[start.sh] nginx: not installed"; return; fi
|
| 86 |
+
mkdir -p /var/log/nginx
|
| 87 |
+
nginx -g "daemon off;" > "${LOGDIR}/nginx.log" 2>&1 &
|
|
|
|
|
|
|
| 88 |
PIDS+=($!)
|
| 89 |
+
for i in $(seq 1 10); do
|
| 90 |
+
if curl -sf http://localhost:80/ >/dev/null 2>&1; then
|
| 91 |
+
echo "[start.sh] nginx: ready (${i}s)"; return
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
fi
|
|
|
|
| 93 |
sleep 1
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
done
|
| 95 |
+
echo "[start.sh] nginx: timeout"
|
| 96 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
+
start_slapd() {
|
| 99 |
+
if ! command -v slapd >/dev/null 2>&1; then echo "[start.sh] slapd: not installed"; return; fi
|
| 100 |
+
mkdir -p /var/run/slapd
|
| 101 |
+
slapd -h "ldap:/// ldapi:///" -u openldap -g openldap > "${LOGDIR}/slapd.log" 2>&1 &
|
| 102 |
PIDS+=($!)
|
|
|
|
|
|
|
| 103 |
for i in $(seq 1 10); do
|
| 104 |
if ldapsearch -x -H ldap://localhost -b "" -s base namingContexts >/dev/null 2>&1; then
|
| 105 |
+
echo "[start.sh] slapd: ready (${i}s)"; return
|
|
|
|
| 106 |
fi
|
|
|
|
| 107 |
sleep 1
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
done
|
| 109 |
+
echo "[start.sh] slapd: timeout"
|
| 110 |
+
}
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
+
start_rsyslog() {
|
| 113 |
+
if ! command -v rsyslogd >/dev/null 2>&1; then echo "[start.sh] rsyslog: not installed"; return; fi
|
| 114 |
+
rsyslogd -n > "${LOGDIR}/rsyslog.log" 2>&1 &
|
|
|
|
| 115 |
PIDS+=($!)
|
| 116 |
+
echo "[start.sh] rsyslog: started"
|
| 117 |
+
}
|
| 118 |
|
| 119 |
+
start_samba() {
|
| 120 |
+
if ! command -v smbd >/dev/null 2>&1; then echo "[start.sh] samba: not installed"; return; fi
|
| 121 |
+
mkdir -p /var/lib/samba/private
|
| 122 |
+
smbd --foreground --no-process-group > "${LOGDIR}/smbd.log" 2>&1 &
|
| 123 |
+
PIDS+=($!)
|
| 124 |
for i in $(seq 1 10); do
|
| 125 |
if smbclient -L localhost -N >/dev/null 2>&1; then
|
| 126 |
+
echo "[start.sh] samba: ready (${i}s)"; return
|
|
|
|
| 127 |
fi
|
|
|
|
| 128 |
sleep 1
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
done
|
| 130 |
+
echo "[start.sh] samba: timeout"
|
| 131 |
+
}
|
|
|
|
|
|
|
|
|
|
| 132 |
|
| 133 |
+
start_postfix() {
|
| 134 |
+
if ! command -v postfix >/dev/null 2>&1; then echo "[start.sh] postfix: not installed"; return; fi
|
| 135 |
postfix start > "${LOGDIR}/postfix.log" 2>&1 || true
|
| 136 |
+
echo "[start.sh] postfix: started"
|
| 137 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
+
start_sshd() {
|
| 140 |
+
if ! command -v sshd >/dev/null 2>&1; then echo "[start.sh] sshd: not installed"; return; fi
|
| 141 |
+
mkdir -p /var/run/sshd
|
| 142 |
/usr/sbin/sshd -E "${LOGDIR}/sshd.log" &
|
| 143 |
PIDS+=($!)
|
| 144 |
+
echo "[start.sh] sshd: started"
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
# ββ Map host names to services ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 148 |
+
# The manifest topology uses logical host names. Map them to service starters.
|
| 149 |
+
|
| 150 |
+
declare -A HOST_SERVICE_MAP=(
|
| 151 |
+
[web]=start_nginx
|
| 152 |
+
[db]=start_mysql
|
| 153 |
+
[ldap]=start_slapd
|
| 154 |
+
[siem]=start_rsyslog
|
| 155 |
+
[files]=start_samba
|
| 156 |
+
[mail]=start_postfix
|
| 157 |
+
[firewall]=start_rsyslog # firewall host uses rsyslog for logging
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
+
# SSH is started if any host needs remote access
|
| 161 |
+
SSH_NEEDED=false
|
| 162 |
+
|
| 163 |
+
for host in $HOSTS; do
|
| 164 |
+
starter="${HOST_SERVICE_MAP[$host]:-}"
|
| 165 |
+
if [ -n "$starter" ]; then
|
| 166 |
+
echo "[start.sh] Starting service for host: $host"
|
| 167 |
+
$starter
|
| 168 |
+
else
|
| 169 |
+
echo "[start.sh] Host '$host' has no mapped service (may be agent-only)"
|
| 170 |
+
fi
|
| 171 |
+
# Any host beyond attacker/siem might need SSH
|
| 172 |
+
if [ "$host" != "attacker" ] && [ "$host" != "siem" ]; then
|
| 173 |
+
SSH_NEEDED=true
|
| 174 |
+
fi
|
| 175 |
+
done
|
| 176 |
|
| 177 |
+
if $SSH_NEEDED; then
|
| 178 |
+
echo "[start.sh] Starting SSH (needed for host access)"
|
| 179 |
+
start_sshd
|
| 180 |
+
fi
|
| 181 |
|
| 182 |
echo "============================================================"
|
| 183 |
+
echo "[start.sh] Services started for snapshot. PIDs: ${PIDS[*]:-none}"
|
| 184 |
echo "[start.sh] Logs at: ${LOGDIR}/"
|
|
|
|
| 185 |
echo "============================================================"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|