# syntax=docker/dockerfile:1
#
# recon-triage — Docker-only build. Multi-stage:
#   go-builder : compiles pinned ProjectDiscovery Go tools (static binaries)
#   test       : runs the fully-offline pytest suite (used by `make test`)
#   runtime    : minimal Alpine image, non-root, with nmap + exploitdb + the app
#
# Alpine is used throughout (musl). All Python deps (pydantic v2 included) ship
# musllinux wheels, so no Debian fallback is needed.

# ---------------------------------------------------------------------------
# Stage 1: build Go recon tools. Pinned for reproducibility.
# ---------------------------------------------------------------------------
FROM golang:1.23-alpine AS go-builder

# libpcap-dev is required to compile naabu; git for go module fetches.
RUN apk add --no-cache git build-base libpcap-dev

ENV CGO_ENABLED=1 GOFLAGS=-buildvcs=false

# Pinned tool versions (see README "Tool versions").
ARG SUBFINDER_VERSION=v2.6.6
ARG DNSX_VERSION=v1.2.1
ARG NAABU_VERSION=v2.3.1
ARG HTTPX_VERSION=v1.6.9
ARG NUCLEI_VERSION=v3.3.5

RUN go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@${SUBFINDER_VERSION} \
 && go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@${DNSX_VERSION} \
 && go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@${NAABU_VERSION} \
 && go install -v github.com/projectdiscovery/httpx/cmd/httpx@${HTTPX_VERSION} \
 && go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@${NUCLEI_VERSION}

# ---------------------------------------------------------------------------
# Stage 1b: fetch Exploit-DB + searchsploit at BUILD time (release-independent;
# the Alpine `exploitdb` package is not in every release's stable repo). The DB
# ships inside the image, so searchsploit needs NO network at runtime.
# ---------------------------------------------------------------------------
FROM alpine:3.20 AS exploitdb-builder
ARG EXPLOITDB_REF=main
RUN apk add --no-cache git \
 && git clone --depth 1 --branch ${EXPLOITDB_REF} \
      https://gitlab.com/exploit-database/exploitdb.git /opt/exploitdb \
 && rm -rf /opt/exploitdb/.git

# ---------------------------------------------------------------------------
# Stage 2: offline test image. No Go tools, no network at runtime — the suite
# is driven entirely by committed fixtures and an injected searchsploit stub.
# ---------------------------------------------------------------------------
FROM python:3.12-alpine AS test

WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

COPY pyproject.toml README.md ./
COPY src ./src
RUN pip install --no-cache-dir -e ".[dev]"

COPY tests ./tests
# Fully offline: -p no:cacheprovider keeps it hermetic.
RUN python -m pytest -q -p no:cacheprovider

# ---------------------------------------------------------------------------
# Stage 3: runtime image. Non-root, connect-scan by default (no caps needed).
# ---------------------------------------------------------------------------
FROM python:3.12-alpine AS runtime

# Runtime packages:
#   nmap            service/version detection
#   libpcap         naabu runtime dependency
#   bash, coreutils searchsploit is a bash script using standard text utilities
#   ca-certificates TLS roots for passive sources / optional LLM endpoint
RUN apk add --no-cache \
        nmap nmap-scripts \
        libpcap \
        ca-certificates \
        bash coreutils

# Copy compiled recon tools from the builder.
COPY --from=go-builder /go/bin/subfinder /usr/local/bin/subfinder
COPY --from=go-builder /go/bin/dnsx      /usr/local/bin/dnsx
COPY --from=go-builder /go/bin/naabu     /usr/local/bin/naabu
COPY --from=go-builder /go/bin/httpx     /usr/local/bin/httpx
COPY --from=go-builder /go/bin/nuclei    /usr/local/bin/nuclei

# Exploit-DB checkout (DB shipped in the image). searchsploit resolves its DB path
# relative to the real script location, so a symlink onto PATH is sufficient.
COPY --from=exploitdb-builder /opt/exploitdb /opt/exploitdb
RUN ln -sf /opt/exploitdb/searchsploit /usr/local/bin/searchsploit \
 && searchsploit --json apache >/dev/null 2>&1 || true

# Install the app into an isolated venv.
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
COPY pyproject.toml README.md ./
COPY src ./src
RUN pip install --no-cache-dir .

# Export the JSON Schema into the image for inspection.
COPY tests/fixtures ./tests/fixtures
RUN python -m recon_triage.schema /app/schemas

# Non-root user. Connect scans need no elevated capabilities.
RUN addgroup -S app && adduser -S -G app -h /home/app app \
 && mkdir -p /data/out /home/app/nuclei-templates \
 && chown -R app:app /data /home/app /app/schemas
USER app

# nuclei templates cache to a mountable volume (not baked into the image).
ENV NUCLEI_TEMPLATES_DIR=/home/app/nuclei-templates
ENV HOME=/home/app

ENTRYPOINT ["recon-triage"]
CMD ["--help"]
