Pin alpine:3.23, multi-stage runtime, smoke test, fix arg drift
- Pin both stages to alpine:3.23 (was floating 'alpine'). - Multi-stage: separate runtime image without rust+cargo+sdk, just python3. - venv for Python deps (PEP 668 on modern Alpine blocks system pip). - start.sh: -c <fieldMappings.yaml> (was .json — upstream renamed), drop -t which now means --template (Jinja2) not tmpdir. - test_smoke.sh: fetch Yamato sample-evtx on demand, scan, verify JSON + log produced, count Sigma rule hits. - fetch-test-data.sh + .gitignore for test-data/. Validated end-to-end on amd64 Linux: 5/5 PASS, 39 hits, Zircolite v3.6.3 with 2160 rules. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
test-data/
|
||||
+23
-4
@@ -1,12 +1,31 @@
|
||||
FROM alpine as builder
|
||||
FROM alpine:3.23 AS builder
|
||||
LABEL maintainer="tabledevil"
|
||||
RUN apk add --no-cache rust cargo python3 py3-pip alpine-sdk git bash
|
||||
ENV PATH=/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
RUN git clone https://github.com/wagga40/Zircolite /opt/zircolite
|
||||
|
||||
# Always grab the current Zircolite master + rules at build time.
|
||||
RUN git clone --depth=1 https://github.com/wagga40/Zircolite /opt/zircolite
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
ADD pip.conf /etc/pip.conf
|
||||
RUN cd /opt/zircolite && pip install -r requirements.txt
|
||||
|
||||
# Use a venv: PEP 668 on modern Alpine blocks system-pip.
|
||||
RUN python3 -m venv /opt/zircolite/venv \
|
||||
&& /opt/zircolite/venv/bin/pip install -r /opt/zircolite/requirements.txt
|
||||
|
||||
WORKDIR /data
|
||||
RUN mkdir /output && touch /output/notmounted
|
||||
RUN python3 /opt/zircolite/zircolite.py -U --rules /opt/zircolite/rules/
|
||||
|
||||
# Refresh sigma rules to latest at build time.
|
||||
RUN /opt/zircolite/venv/bin/python /opt/zircolite/zircolite.py -U --rules /opt/zircolite/rules/
|
||||
|
||||
ADD start.sh /root/start.sh
|
||||
RUN chmod +x /root/start.sh
|
||||
|
||||
FROM alpine:3.23
|
||||
RUN apk add --no-cache python3 bash
|
||||
COPY --from=builder /opt/zircolite /opt/zircolite
|
||||
COPY --from=builder /root/start.sh /root/start.sh
|
||||
RUN mkdir -p /output && touch /output/notmounted
|
||||
WORKDIR /data
|
||||
CMD ["/bin/bash","/root/start.sh"]
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
# Pull the upstream EVTX sample bundle (Yamato Security's curated bundle of
|
||||
# DeepBlueCLI, EVTX-ATTACK-SAMPLES, EVTX-to-MITRE-Attack, plus their own).
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
mkdir -p test-data
|
||||
[ -d test-data/sample-evtx ] || \
|
||||
git clone --depth=1 https://github.com/Yamato-Security/hayabusa-sample-evtx.git test-data/sample-evtx
|
||||
echo "ready: test-data/sample-evtx"
|
||||
@@ -32,4 +32,13 @@ fi
|
||||
outputf="${output}/zircolite_$(date +%s)"
|
||||
echo "output is goint to : ${outputf}"
|
||||
|
||||
python3 /opt/zircolite/zircolite.py --evtx /data --rules /opt/zircolite/rules/rules_windows_generic.json -c /opt/zircolite/config/fieldMappings.json -o "${outputf}.json" -t "${output}/tmp" -l "${outputf}.log"
|
||||
# --evtx <data dir> ; -o <json output> ; -l <logfile> ; -c <field mappings>.
|
||||
# Older start.sh passed -t <tmpdir>, but in current zircolite -t means
|
||||
# --template (Jinja2) which expects --templateOutput as well. Tmp is no
|
||||
# longer user-controllable so we drop it.
|
||||
/opt/zircolite/venv/bin/python /opt/zircolite/zircolite.py \
|
||||
--evtx /data \
|
||||
--rules /opt/zircolite/rules/rules_windows_generic.json \
|
||||
-c /opt/zircolite/config/fieldMappings.yaml \
|
||||
-o "${outputf}.json" \
|
||||
-l "${outputf}.log"
|
||||
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
# Smoke test for zircolite: fetch sample EVTX, run, check outputs, print stats.
|
||||
#
|
||||
# Available SUBSET values (under test-data/sample-evtx/):
|
||||
# DeepBlueCLI 21 files, ~30s — well-known PowerShell + auth attacks
|
||||
# YamatoSecurity 16 files, ~20s — Yamato Security's own samples
|
||||
# EVTX-ATTACK-SAMPLES 278 files, ~5min — sbousseaden's MITRE-mapped corpus
|
||||
# EVTX-to-MITRE-Attack 284 files, ~5min — mdecrevoisier's MITRE-mapped corpus
|
||||
# "" 599 files, ~10min — full bundle
|
||||
#
|
||||
# Env vars: TAG=ls-zircolite:test SUBSET=DeepBlueCLI KEEP_DATA=1
|
||||
set -u
|
||||
TAG="${TAG:-ls-zircolite:test}"
|
||||
SUBSET="${SUBSET:-DeepBlueCLI}"
|
||||
KEEP_DATA="${KEEP_DATA:-0}"
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
ROOT="$(pwd)"
|
||||
DATA="$ROOT/test-data/sample-evtx"
|
||||
OUT="$(mktemp -d)"
|
||||
trap 'rm -rf "$OUT"; [ "$KEEP_DATA" = 0 ] && rm -rf "$ROOT/test-data"' EXIT
|
||||
|
||||
pass=0; fail=0
|
||||
ok() { echo "PASS $1"; pass=$((pass+1)); }
|
||||
bad() { echo "FAIL $1"; fail=$((fail+1)); }
|
||||
|
||||
if docker image inspect "$TAG" >/dev/null 2>&1; then
|
||||
ok "image $TAG present"
|
||||
else
|
||||
bad "image $TAG not present"; exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$DATA" ]; then
|
||||
echo "Fetching sample EVTX..."
|
||||
./fetch-test-data.sh >/dev/null
|
||||
fi
|
||||
SCAN="$DATA/$SUBSET"; [ -z "$SUBSET" ] && SCAN="$DATA"
|
||||
n=$(find "$SCAN" -name "*.evtx" | wc -l | tr -d ' ')
|
||||
[ "$n" -gt 0 ] && ok "found $n EVTX in ${SUBSET:-<all>}" || { bad "no EVTX"; exit 1; }
|
||||
|
||||
echo "Running scan..."
|
||||
if docker run --rm --network=none -v "$SCAN:/data:ro" -v "$OUT:/output" "$TAG" >"$OUT/.run.log" 2>&1; then
|
||||
ok "container exited cleanly"
|
||||
else
|
||||
bad "container non-zero"; tail -20 "$OUT/.run.log"
|
||||
fi
|
||||
|
||||
json=$(ls "$OUT"/zircolite_*.json 2>/dev/null | head -1)
|
||||
log=$(ls "$OUT"/zircolite_*.log 2>/dev/null | head -1)
|
||||
[ -s "$json" ] && ok "JSON report exists ($(du -h "$json" | cut -f1))" || bad "JSON missing/empty"
|
||||
[ -s "$log" ] && ok "scan log exists" || bad "log missing"
|
||||
|
||||
if [ -s "$json" ]; then
|
||||
hits=$(grep -oE '"title"' "$json" | wc -l | tr -d ' ')
|
||||
echo
|
||||
echo "Sigma rule hits: $hits"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Summary: $pass pass, $fail fail"
|
||||
[ "$fail" -eq 0 ]
|
||||
Reference in New Issue
Block a user