# Riposte EGRESS-GATEWAY image (Track B) - the minimal packet-filter appliance that
# GatewayOrchestrator (src/riposte/sandbox/gateway.py) runs as a dual-homed filtering
# gateway between an untrusted --cap-drop ALL sandbox and the outside world. This is
# NOT the heavy Kali sandbox image (docker/sandbox/Dockerfile): it carries ONLY the
# packet-filter plumbing (nftables/iptables/iproute2) and NO security tools, NO
# untrusted code, nothing fetched from the network at build beyond the distro packages.
#
# DRIVEN ENTIRELY VIA docker exec. PID 1 is `sleep infinity` and does NOTHING (no
# entrypoint, no network I/O at startup) - mirroring the sandbox image's do-nothing-PID1
# property. The orchestrator runs this image roughly as:
#   docker run -d --network <sandbox-net> --cap-drop ALL --cap-add NET_ADMIN \
#       --sysctl net.ipv4.ip_forward=1 --read-only riposte-gateway:pinned sleep infinity
# then dual-homes it onto the external net and drives ALL real work via `docker exec`:
#   - installs the compiled FORWARD ruleset via `nft -f -` (compile_nftables_forward),
#   - the inet-table masquerade (postrouting nat chain) is loaded the same way,
#   - the ephemeral --rm init sidecar reuses THIS SAME image for `ip route` / `iptables`
#     to pin the sandbox's default route through the gateway.
# Hence the package set below is exactly { nftables, iptables, iproute2 } plus
# ca-certificates (trivial, harmless), and nothing else.
#
# CAPABILITIES: the container holds ONLY CAP_NET_ADMIN (the orchestrator passes
# --cap-drop ALL --cap-add NET_ADMIN). It runs as ROOT (uid 0) INSIDE the container
# ON PURPOSE: nft/ip/iptables require CAP_NET_ADMIN as uid 0 to load rules and edit
# routes, and dropping to a non-root uid would lose the effective capability. This is
# NOT a privilege risk: the container holds ONLY NET_ADMIN (everything else dropped),
# the rootfs is --read-only, and it runs NO untrusted code (it is a pinned appliance we
# build and control - all untrusted tools run in the SEPARATE cap-drop-ALL sandbox).
# It is a contained single-purpose appliance, not a privileged host.
#
# Build (amd64; the appliance is arch-agnostic but build for the sandbox host arch):
#   docker build -f docker/gateway/Dockerfile -t riposte-gateway:pinned .
#
# OFFLINE GATE: tests/sandbox/test_gateway_image.py cross-checks THIS file at the text
# level WITHOUT building or launching anything (mirrors test_image_manifest.py). The
# real `docker build` + an `nft -f -` load validation (including the inet-table
# masquerade syntax that compile_nftables_forward emits) is a FOUNDER/integration step.

# Minimal base, PINNED to a specific Alpine version tag (NOT :latest) for a small,
# reproducible appliance. SUPPLY CHAIN: a real production build MUST additionally pin
# by sha256 digest so the tag cannot be re-pointed upstream. Set GATEWAY_BASE_DIGEST to
# the resolved manifest digest before the founder/integration build, e.g.:
#   docker build --build-arg GATEWAY_BASE_DIGEST=@sha256:<64-hex> ...
# (leave it empty here; the offline gate does not build, and the digest is resolved at
# the integration step, exactly as the sandbox image defers its heavy pins).
ARG GATEWAY_BASE_VERSION=3.20.3
ARG GATEWAY_BASE_DIGEST=
FROM alpine:${GATEWAY_BASE_VERSION}${GATEWAY_BASE_DIGEST}

# ONLY the packet-filter plumbing the gateway + init sidecar need:
#   - nftables  : load the compiled FORWARD ruleset via `nft -f -` (incl. inet masquerade)
#   - iptables  : the init sidecar drops traffic to the docker bridge gateway
#   - iproute2  : `ip route` for default-route pinning + verification
#   - ca-certificates : trivial, harmless; present for completeness only
# NOTHING ELSE is installed: no nmap/sqlmap/curl-as-a-tool, no scripting beyond the
# busybox shell, no untrusted code. This is a hardened, single-purpose appliance.
RUN apk add --no-cache \
        nftables \
        iptables \
        iproute2 \
        ca-certificates

# PID 1 does NOTHING. No ENTRYPOINT, no startup network I/O: the orchestrator performs
# every real action via `docker run ... sleep infinity` followed by `docker exec`. This
# matches the sandbox image's do-nothing-PID1 contract.
CMD ["sleep", "infinity"]
