# dsh-pentester/kali —— 唯一工厂 Toolbox 镜像。
#
# Kali Linux（rolling）+ 精选渗透测试工具集。Agent 从不指定镜像名：
# 经 /pentester/tools.json 发现工具，一切执行走 pentester_container_exec
# （契约见 docs/architecture.md）。
#
# 构建（仓库根目录，或直接运行 bash scripts/build-docker-image.sh）：
#   docker build -t fb0sh/dsh-pentester-kali:latest docker/kali
#
# 工具契约：
#   /pentester/tools.json     — 构建期由 bin/gen-tools-json.sh 探测生成
#                               （command -v 探测，装漏的工具不会进目录）
#   /pentester/bin/tool-list  — 分类清单
#   /pentester/bin/tool-info  — 单工具详情
#   /pentester/VERSION        — dsh-pentester-kali 镜像版本
#   /workspace                — 项目共享 docker volume（该项目所有容器
#                               共同挂载）
#   /workspace/traffic/          — 全流量记录（只记录，不分析）：
#                                 pcap/（tcpdump 常开）+ flows.mitm
#                                 （mitmproxy :8080，agent 走它可得明文 HTTP）


# =============================================================================
# Kali 基础层
#
# Builder / Runtime / KB Builder 共用这一层：
#   - Kali sources
#   - CA
#   - archive keyring
#
# http_proxy / https_proxy / no_proxy 不通过 ARG/ENV 显式声明。
# Docker/BuildKit 原生提供这些 proxy build args；构建工具通过 buildargs 传入即可。
# =============================================================================

FROM kalilinux/kali-rolling:latest AS kali-base

SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]

ARG DEBIAN_FRONTEND=noninteractive

# KALI_SOURCES：自定义 sources.list 全文（构建脚本传入）；
# 为空时走官方源 http 引导装 CA → 切 https 的默认流程。
ARG KALI_SOURCES=""

# 基础 Kali 镜像可能没有完整 CA。
# 自定义 https 源先临时转换为 http，引导安装 CA 后再恢复用户原文。
RUN --mount=type=cache,id=dsh-kali-apt-lists,target=/var/lib/apt/lists,sharing=locked \
    --mount=type=cache,id=dsh-kali-apt-cache,target=/var/cache/apt,sharing=locked \
    rm -f /etc/apt/sources.list.d/*.list \
          /etc/apt/sources.list.d/*.sources; \
    \
    if [[ -n "${KALI_SOURCES}" ]]; then \
        printf '%s\n' "${KALI_SOURCES}" \
          | sed 's|https://|http://|g' \
          > /etc/apt/sources.list; \
        \
        apt-get update; \
        apt-get install -y --no-install-recommends \
            ca-certificates \
            kali-archive-keyring; \
        \
        printf '%s\n' "${KALI_SOURCES}" \
          > /etc/apt/sources.list; \
    else \
        printf '%s\n' \
          'deb http://http.kali.org/kali kali-rolling main contrib non-free non-free-firmware' \
          > /etc/apt/sources.list; \
        \
        apt-get update; \
        apt-get install -y --no-install-recommends \
            ca-certificates \
            kali-archive-keyring; \
        \
        printf '%s\n' \
          'deb https://http.kali.org/kali kali-rolling main contrib non-free non-free-firmware' \
          'deb-src https://http.kali.org/kali kali-rolling main contrib non-free non-free-firmware' \
          > /etc/apt/sources.list; \
    fi


# =============================================================================
# Builder 阶段：编译 Go 工具族（strix 多阶段模式）
#
# 编译缓存和 module cache 均使用 BuildKit cache mount，
# 不进入最终 Runtime 镜像。
# =============================================================================

FROM kali-base AS gobuilder

ENV GOBIN=/out/bin

RUN --mount=type=cache,id=dsh-kali-apt-lists,target=/var/lib/apt/lists,sharing=locked \
    --mount=type=cache,id=dsh-kali-apt-cache,target=/var/cache/apt,sharing=locked \
    apt-get update && \
    apt-get install -y --no-install-recommends \
        golang-go \
        git \
        build-essential \
        pkg-config

RUN mkdir -p /out/bin


# 去掉 Go 二进制的调试信息，减小体积
RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/projectdiscovery/httpx/cmd/httpx@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/projectdiscovery/katana/cmd/katana@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/projectdiscovery/naabu/v2/cmd/naabu@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/projectdiscovery/dnsx/cmd/dnsx@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/jaeles-project/gospider@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/tomnomnom/gron@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    CGO_ENABLED=1 \
    go install -ldflags="-s -w" \
        github.com/xo/usql@latest


RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    go install -ldflags="-s -w" \
        github.com/xiecat/fofax/cmd/fofax@latest

RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
    --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
    git clone --depth=1 \
        https://github.com/Rvn0xsy/red-tldr.git \
        /tmp/red-tldr && \
    cd /tmp/red-tldr && \
    go build -ldflags="-s -w" \
        -o /out/bin/red-tldr . && \
    rm -rf /tmp/red-tldr

# ── Go 增量工具区 ────────────────────────────────────────────────────────────
#
# 后续新增 Go 工具只向下追加新的 RUN。
# 不要修改上面的已有 RUN，这样已有 Go 工具层继续命中缓存。
#
# 示例：
#
# RUN --mount=type=cache,id=dsh-go-mod,target=/root/go/pkg/mod \
#     --mount=type=cache,id=dsh-go-build,target=/root/.cache/go-build \
#     go install -ldflags="-s -w" \
#         github.com/tomnomnom/assetfinder@latest



# =============================================================================
# KB Builder
#
# 知识库与 Runtime 完全分离构建：
#   - 修改 Runtime 工具不会重新 clone KB
#   - clone 产生的 Git 元数据可以在进入最终镜像前剥离
#
# KEEP_KB_GIT=0：
#   默认删除每个 KB 顶层 .git，显著降低最终镜像体积。
#
# 如果确实需要在容器内对 KB 使用 git history：
#   --build-arg KEEP_KB_GIT=1
# =============================================================================

FROM kali-base AS kb-builder

ARG WITH_KB=1
ARG KEEP_KB_GIT=0

RUN --mount=type=cache,id=dsh-kali-apt-lists,target=/var/lib/apt/lists,sharing=locked \
    --mount=type=cache,id=dsh-kali-apt-cache,target=/var/cache/apt,sharing=locked \
    apt-get update && \
    apt-get install -y --no-install-recommends \
        git

COPY bin/clone-kb /usr/local/bin/clone-kb

RUN chmod +x /usr/local/bin/clone-kb && \
    mkdir -p /opt/kb && \
    git config --global http.version HTTP/1.1 && \
    git config --global http.lowSpeedLimit 1000 && \
    git config --global http.lowSpeedTime 60


# ── 知识库层（默认打包；--build-arg WITH_KB=0 可裁剪减小体积）────────────────

RUN if [[ "${WITH_KB}" == "1" ]]; then \
        clone-kb vulhub vulhub/vulhub 500; \
        if [[ "${KEEP_KB_GIT}" != "1" ]]; then \
            rm -rf /opt/kb/vulhub/.git; \
        fi; \
    fi


RUN if [[ "${WITH_KB}" == "1" ]]; then \
        clone-kb PayloadsAllTheThings swisskyrepo/PayloadsAllTheThings 400; \
        if [[ "${KEEP_KB_GIT}" != "1" ]]; then \
            rm -rf /opt/kb/PayloadsAllTheThings/.git; \
        fi; \
    fi


RUN if [[ "${WITH_KB}" == "1" ]]; then \
        clone-kb awesome-poc Threekiii/Awesome-POC 300; \
        if [[ "${KEEP_KB_GIT}" != "1" ]]; then \
            rm -rf /opt/kb/awesome-poc/.git; \
        fi; \
    fi


RUN if [[ "${WITH_KB}" == "1" ]]; then \
        clone-kb exphub zhzyker/exphub 60; \
        if [[ "${KEEP_KB_GIT}" != "1" ]]; then \
            rm -rf /opt/kb/exphub/.git; \
        fi; \
    fi


RUN if [[ "${WITH_KB}" == "1" ]]; then \
        find /opt/kb -type f \( \
            -name '*.md' -o \
            -name '*.py' -o \
            -name '*.txt' -o \
            -name '*.yaml' \
        \) \
        | sed 's|^/opt/kb/||' \
        | sort \
        > /opt/kb/INDEX.txt; \
    fi



# =============================================================================
# Runtime 阶段
# =============================================================================

FROM kali-base AS runtime

# /pentester 是最终镜像中 dsh-pentester-kali 的产品根目录。
#
#   /pentester/bin/          — dsh-pentester 自身脚本 / Agent 接口
#   /pentester/tools/bin/    — Go 与其他自定义可执行工具
#   /pentester/tools/jars/   — Java JAR 工具资产
#   /pentester/tools/pipx/   — pipx 隔离环境
#   /pentester/kb/           — 知识库
#
# 自定义工具不再散落到 /usr/local/bin 和 /root/.local/bin。
ENV PIPX_HOME="/pentester/tools/pipx" \
    PIPX_BIN_DIR="/pentester/tools/bin" \
    PATH="/pentester/bin:/pentester/tools/bin:${PATH}"


# =============================================================================
# STABLE APT AREA
#
# 下面 1～9 类工具属于稳定工具集，但统一在一个 APT transaction 中安装：
#   - 只执行一次 apt-get update
#   - 减少重复网络请求和构建时间
#   - 分类仍完整保留，RUN 内使用对应的 Bash 数组组织
#
# 分类：
#   1. 基础 / UNIX / 开发运行时（agent 脚本 + 输出解析）
#   2. 网络 / 诊断
#   3. 网络发现 / 端口扫描
#   4. DNS / 子域名 / OSINT
#   5. Web 发现 / fuzz / 爬取 + 漏洞扫描
#   6. 密码 / 爆破 / 凭据
#   7. SMB / Windows / AD
#   8. 字典（rockyou + seclists）
#   9. 杂项取证 / 逆向 / 响应
#
# 后续新增工具不要再修改这里。
# 新工具统一追加到后面的 EXTRA TOOLS 区域，
# 避免破坏这个已经很重、但稳定的缓存层。
#
# APT lists/cache 使用 BuildKit cache mount，不写入最终镜像层。
# =============================================================================

RUN --mount=type=cache,id=dsh-kali-apt-lists,target=/var/lib/apt/lists,sharing=locked \
    --mount=type=cache,id=dsh-kali-apt-cache,target=/var/cache/apt,sharing=locked \
    base_tools=( \
        zsh \
        tmux \
        screen \
        vim \
        nano \
        tree \
        file \
        less \
        gawk \
        ripgrep \
        fd-find \
        xh \
        sd \
        miller \
        hurl \
        git \
        curl \
        wget \
        aria2 \
        jq \
        yq \
        python3 \
        python3-pip \
        python3-venv \
        pipx \
        ruby \
        perl \
        default-jre \
        unzip \
        zip \
        p7zip-full \
        tar \
        gzip \
        bzip2 \
        xz-utils \
        build-essential \
        pkg-config \
        openssl \
        golang-go \
    ); \
    network_tools=( \
        iproute2 \
        iputils-ping \
        net-tools \
        dnsutils \
        whois \
        traceroute \
        mtr-tiny \
        tcpdump \
        tshark \
        netcat-openbsd \
        socat \
        ncat \
        telnet \
        openssh-client \
        proxychains4 \
        torsocks \
    ); \
    discovery_tools=( \
        nmap \
        masscan \
        arp-scan \
        netdiscover \
    ); \
    osint_tools=( \
        dnsrecon \
        dnsenum \
        fierce \
        amass \
        subfinder \
        theharvester \
        whatweb \
        wafw00f \
    ); \
    web_tools=( \
        ffuf \
        gobuster \
        feroxbuster \
        dirb \
        dirbuster \
        nikto \
        nuclei \
        sqlmap \
    ); \
    credential_tools=( \
        hydra \
        john \
        medusa \
        crunch \
        hashid \
        hashcat \
    ); \
    windows_ad_tools=( \
        smbclient \
        enum4linux-ng \
        impacket-scripts \
        netexec \
        evil-winrm \
    ); \
    wordlist_tools=( \
        seclists \
        wordlists \
    ); \
    analysis_tools=( \
        exiftool \
        binwalk \
        foremost \
        radare2 \
        gdb \
        responder \
        bettercap \
    ); \
    apt-get update && \
    apt-get install -y --no-install-recommends \
        "${base_tools[@]}" \
        "${network_tools[@]}" \
        "${discovery_tools[@]}" \
        "${osint_tools[@]}" \
        "${web_tools[@]}" \
        "${credential_tools[@]}" \
        "${windows_ad_tools[@]}" \
        "${wordlist_tools[@]}" \
        "${analysis_tools[@]}" && \
    ln -sf /usr/bin/fdfind /usr/local/bin/fd



# =============================================================================
# Stable Custom Tools
# =============================================================================


# ── jc（anything→JSON）+ Java 反序列化三件套（gh-proxy 回退，hxbai 模式）────

RUN --mount=type=cache,id=dsh-pip-cache,target=/root/.cache/pip \
    mkdir -p \
        /pentester/tools/bin \
        /pentester/tools/jars \
        /pentester/tools/pipx && \
    pipx install jc


RUN \
    for jar in \
        "ysoserial|https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar" \
        "marshalsec|https://github.com/0ofo/marshalsec.jar/releases/download/0.0.3/marshalsec-0.0.3-SNAPSHOT-all.jar" \
        "JNDI-Injection-Exploit|https://github.com/welk1n/JNDI-Injection-Exploit/releases/download/v1.0/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar"; \
    do \
        name="${jar%%|*}"; \
        url="${jar#*|}"; \
        ok=0; \
        \
        for u in \
            "https://gh-proxy.com/${url}" \
            "https://ghproxy.net/${url}" \
            "${url}"; \
        do \
            if curl \
                -fL \
                --retry 2 \
                --retry-delay 1 \
                --connect-timeout 10 \
                --max-time 120 \
                -o "/pentester/tools/jars/${name}.jar" \
                "${u}"; \
            then \
                if [[ -s "/pentester/tools/jars/${name}.jar" ]]; then \
                    ok=1; \
                    break; \
                fi; \
            fi; \
            \
            rm -f "/pentester/tools/jars/${name}.jar"; \
        done; \
        \
        if [[ "${ok}" != "1" ]]; then \
            echo "ERROR: ${name} jar download failed" >&2; \
            exit 1; \
        fi; \
        \
        bin_name="$(printf '%s' "${name}" | tr 'A-Z' 'a-z')"; \
        printf '#!/bin/sh\nexec java -jar /pentester/tools/jars/%s.jar "$@"\n' \
            "${name}" \
            > "/pentester/tools/bin/${bin_name}"; \
        chmod +x "/pentester/tools/bin/${bin_name}"; \
    done


# ── mitmproxy（全流量记录的 HTTP 层；pipx 隔离安装）──────────────────────

RUN --mount=type=cache,id=dsh-pip-cache,target=/root/.cache/pip \
    pipx install mitmproxy && \
    /pentester/tools/bin/mitmdump --version


# ── fscan（内网综合扫描工具）──────────────────────────────────────────────

RUN \
    wget \
        -q \
        -T 20 \
        -O /pentester/tools/bin/fscan \
        "https://github.com/shadow1ng/fscan/releases/download/v2.2.0/fscan_2.2.0_linux_x64" && \
    test -s /pentester/tools/bin/fscan && \
    chmod +x /pentester/tools/bin/fscan


# ── kscan（内网综合扫描工具）──────────────────────────────────────────────

RUN \
    wget \
        -q \
        -T 20 \
        -O /tmp/kscan.zip \
        "https://github.com/lcvvvv/kscan/releases/download/v1.85/kscan_linux_amd64.zip" && \
    unzip \
        -q \
        /tmp/kscan.zip \
        -d /tmp/kscan_extract && \
    mv \
        /tmp/kscan_extract/kscan_linux_amd64 \
        /pentester/tools/bin/kscan && \
    chmod +x /pentester/tools/bin/kscan && \
    rm -rf \
        /tmp/kscan.zip \
        /tmp/kscan_extract


# ── defaulthound（默认口令扫描工具）────────────────────────────────────────

RUN \
    wget \
        -q \
        -T 20 \
        -O /tmp/defaulthound.tar.gz \
        "https://github.com/fb0sh/DefaultHound/releases/download/v2.12.0/defaulthound-x86_64-unknown-linux-gnu-v2.12.0.tar.gz" && \
    tar \
        -xzf /tmp/defaulthound.tar.gz \
        -C /tmp && \
    mv \
        /tmp/defaulthound \
        /pentester/tools/bin/defaulthound && \
    chmod +x /pentester/tools/bin/defaulthound && \
    rm -f /tmp/defaulthound.tar.gz



# =============================================================================
# Knowledge Base
#
# KB 从独立 stage 复制到 /pentester/kb。
# kb-builder 内部仍使用 /opt/kb 作为构建暂存路径，避免改变 clone-kb 的既有契约。
# 修改下面的 Go/EXTRA/bin 不会重新执行 clone。
# =============================================================================

COPY --from=kb-builder /opt/kb/ /pentester/kb/

# 保留原先对 Git 的网络稳定性配置。
COPY --from=kb-builder \
    /root/.gitconfig \
    /root/.gitconfig



# =============================================================================
# Go 工具族（builder 阶段产物：PD 家族 + interactsh/gospider/gron）
#
# 故意位于 KB 后面。
# 新增 Go 工具只影响 gobuilder 后部以及这里之后的最终层。
# =============================================================================

COPY --from=gobuilder /out/bin/ /pentester/tools/bin/



# =============================================================================
# EXTRA TOOLS —— 后续新增工具统一放这里
#
# 这是以后最常修改的区域。
#
# 原则：
#
#   Go 新工具
#       → gobuilder 最后的“Go 增量工具区”
#
#   apt 新工具
#       → EXTRA APT 继续向下追加独立 RUN
#
#   GitHub / wget / curl 二进制
#       → EXTRA CUSTOM 继续向下追加独立 RUN
#
#   pipx 工具
#       → EXTRA PIPX 继续向下追加独立 RUN
#
# 不要为了新增工具回头修改 STABLE APT / Stable Custom Tools。
# =============================================================================


# ── EXTRA APT ────────────────────────────────────────────────────────────────
#
# 示例：
#
# RUN --mount=type=cache,id=dsh-kali-apt-lists,target=/var/lib/apt/lists,sharing=locked \
#     --mount=type=cache,id=dsh-kali-apt-cache,target=/var/cache/apt,sharing=locked \
#     apt-get update && \
#     apt-get install -y --no-install-recommends \
#         wpscan
#
#
# 再增加第二个：
#
# RUN --mount=type=cache,id=dsh-kali-apt-lists,target=/var/lib/apt/lists,sharing=locked \
#     --mount=type=cache,id=dsh-kali-apt-cache,target=/var/cache/apt,sharing=locked \
#     apt-get update && \
#     apt-get install -y --no-install-recommends \
#         another-tool



# ── EXTRA CUSTOM ─────────────────────────────────────────────────────────────
#
# 示例：
#
# RUN \
#     wget \
#         -q \
#         -O /pentester/tools/bin/some-tool \
#         "https://github.com/example/some-tool/releases/download/v1.0/some-tool_linux_amd64" && \
#     chmod +x /pentester/tools/bin/some-tool



# ── EXTRA PIPX ───────────────────────────────────────────────────────────────
#
# 示例：
#
# RUN --mount=type=cache,id=dsh-pip-cache,target=/root/.cache/pip \
#     pipx install some-tool



# =============================================================================
# Agent Toolbox Interface
#
# /pentester 是 dsh-pentester-kali 的产品根目录：
#   /pentester/VERSION
#   /pentester/tools.json
#   /pentester/bin/          — dsh-pentester 自身脚本 / Agent 接口
#   /pentester/tools/bin/    — Go / 自定义可执行工具
#   /pentester/tools/jars/   — Java JAR 工具资产
#   /pentester/tools/pipx/   — pipx 隔离环境
#   /pentester/kb/           — 知识库
#
# bin/ 是开发过程中最容易变化的部分，因此故意放到整个 Dockerfile 最后。
#
# 修改：
#   tool-list
#   tool-info
#   gen-tools-json.sh
#   其他 toolbox scripts
#
# 不会再导致前面的 KB / Go / Stable Tools 重新构建。
# =============================================================================


# =============================================================================
# Image Version
#
# 版本唯一来源：docker/kali/VERSION
#
# 构建 CLI 读取 VERSION，并通过
# DSH_PENTESTER_KALI_VERSION build arg 注入镜像元数据；
# 同一值写入 OCI label、ENV 和 /pentester/VERSION。
#
# 故意放在 Dockerfile 后部：
# 单纯修改版本号不会使 APT / KB / Go 等昂贵层失效。
# =============================================================================

ARG DSH_PENTESTER_KALI_VERSION

LABEL org.opencontainers.image.title="dsh-pentester-kali" \
      org.opencontainers.image.version="${DSH_PENTESTER_KALI_VERSION}"

ENV DSH_PENTESTER_KALI_VERSION="${DSH_PENTESTER_KALI_VERSION}"

COPY bin/ /pentester/bin/


# ── 工具目录生成 + 版本写入 + 清理 ───────────────────────────────────────────

RUN \
    test -n "${DSH_PENTESTER_KALI_VERSION}" && \
    chmod +x /pentester/bin/* && \
    printf '%s\n' "${DSH_PENTESTER_KALI_VERSION}" \
        > /pentester/VERSION && \
    /pentester/bin/gen-tools-json.sh \
        /pentester/tools.json && \
    rm -rf \
        /root/.cache \
        /tmp/*


# ── proxychains → local mitmproxy :8080 ───────────────────────────────────────
#
# 默认不强制任何工具走代理。
# Agent 需要记录 HTTP(S) 明文流量时显式使用：
#
#   proxychains curl https://example.com
#   proxychains wget https://example.com
#
# proxychains 将 TCP 连接交给本容器 mitmproxy regular HTTP proxy :8080。
# -----------------------------------------------------------------------------

RUN \
    printf '%s\n' \
        'strict_chain' \
        'proxy_dns' \
        'quiet_mode' \
        'tcp_read_time_out 15000' \
        'tcp_connect_time_out 8000' \
        '' \
        '[ProxyList]' \
        'http 127.0.0.1 8080' \
        > /etc/proxychains4.conf && \
    ln -sf /usr/bin/proxychains4 /usr/local/bin/proxychains

# =============================================================================
# 构建期自检
#
# 目的不是替代 tools.json，而是保证：
#   - 核心 APT 工具真的可执行
#   - Go Builder 产物真的被 COPY
#   - pipx 工具 PATH 正确
#   - 自定义二进制位置正确
#   - Java JAR/wrapper 正确
#   - 数据包存在
#   - Agent toolbox catalog 可以正常工作
#
# 任一关键项缺失，镜像直接 build fail。
# =============================================================================

RUN \
    test -d /pentester/tools/bin; \
    test -d /pentester/tools/jars; \
    test -d /pentester/tools/pipx; \
    test -x /pentester/tools/bin/httpx; \
    test -x /pentester/tools/bin/fscan; \
    test -x /pentester/tools/bin/kscan; \
    test -x /pentester/tools/bin/defaulthound; \
    test -x /pentester/tools/bin/jc; \
    test -x /pentester/tools/bin/mitmdump; \
    \
    required_commands=( \
        git \
        curl \
        wget \
        jq \
        yq \
        python3 \
        pipx \
        java \
        go \
        nmap \
        masscan \
        arp-scan \
        ffuf \
        gobuster \
        feroxbuster \
        nikto \
        nuclei \
        sqlmap \
        hydra \
        john \
        hashcat \
        smbclient \
        evil-winrm \
        exiftool \
        binwalk \
        radare2 \
        gdb \
        bettercap \
        httpx \
        katana \
        naabu \
        dnsx \
        interactsh-client \
        gospider \
        gron \
        usql \
        fofax \
        jc \
        mitmdump \
        fscan \
        kscan \
        defaulthound \
        ysoserial \
        marshalsec \
        jndi-injection-exploit \
        tool-list \
        tool-info \
    ); \
    \
    for cmd in "${required_commands[@]}"; do \
        if ! command -v "${cmd}" >/dev/null 2>&1; then \
            echo "ERROR: required command missing: ${cmd}" >&2; \
            exit 1; \
        fi; \
    done; \
    \
    for jar in \
        /pentester/tools/jars/ysoserial.jar \
        /pentester/tools/jars/marshalsec.jar \
        /pentester/tools/jars/JNDI-Injection-Exploit.jar; \
    do \
        if [[ ! -s "${jar}" ]]; then \
            echo "ERROR: required jar missing: ${jar}" >&2; \
            exit 1; \
        fi; \
    done; \
    \
    for pkg in \
        seclists \
        wordlists \
        impacket-scripts \
        netexec \
        responder; \
    do \
        if ! dpkg-query \
            -W \
            -f='${Status}' \
            "${pkg}" \
            2>/dev/null \
            | grep -q '^install ok installed$'; \
        then \
            echo "ERROR: required package missing: ${pkg}" >&2; \
            exit 1; \
        fi; \
    done; \
    \
    test -s /pentester/tools.json; \
    test -x /pentester/bin/tool-list; \
    test -x /pentester/bin/tool-info; \
    test -s /pentester/VERSION; \
    test "$(cat /pentester/VERSION)" = "${DSH_PENTESTER_KALI_VERSION}"; \
    \
    tool-list >/dev/null; \
    tool-info nmap >/dev/null; \
    tool-info httpx >/dev/null; \
    \
    echo "Toolbox self-check: OK"



# 构建代理不泄漏进成品镜像。
#
# 本版本没有通过 ENV 写入构建代理，因此这里无需再显式清空
# http_proxy / https_proxy / no_proxy。


# PROMPT and some skills
COPY TOOL_PROMPT.md /pentester/PROMPT.md
COPY REPORT_TEMPLATE.md /pentester/REPORT_TEMPLATE.md

WORKDIR /workspace

ENTRYPOINT ["/pentester/bin/entrypoint.sh"]

CMD ["sleep", "infinity"]
