diff --git a/deploy/railiance/Dockerfile b/deploy/railiance/Dockerfile new file mode 100644 index 0000000..79c7708 --- /dev/null +++ b/deploy/railiance/Dockerfile @@ -0,0 +1,15 @@ +# MAS live-test MX for mas.coulomb.social (MAS-WP-0003). +# Build from the repo root: docker build -f deploy/railiance/Dockerfile . +FROM debian:bookworm-slim +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + postfix python3 python3-jsonschema ssl-cert ca-certificates && rm -rf /var/lib/apt/lists/* +RUN useradd -r -s /usr/sbin/nologin mas +COPY mas_core /app/mas_core +COPY mas_gateway /app/mas_gateway +COPY examples /app/examples +COPY experiments/postfix-probe/capture.py /app/capture.py +COPY deploy/railiance/entrypoint.sh /entrypoint.sh +ENV PYTHONPATH=/app +EXPOSE 25 8080 +ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] +CMD ["mx"] diff --git a/deploy/railiance/entrypoint.sh b/deploy/railiance/entrypoint.sh new file mode 100644 index 0000000..e5540ea --- /dev/null +++ b/deploy/railiance/entrypoint.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# mx : Postfix -> pipe -> mas-gateway -> capture (JSONL evidence) -> ticket service +# statute : static /.well-known/mas only (the only thing exposed over HTTPS) +set -e +DOMAIN="${MAS_DOMAIN:-mas.coulomb.social}" +STATUTE_DIR="/app/examples/statute/$DOMAIN" + +if [ "$1" = "statute" ]; then + exec python3 /app/examples/statute/serve.py "$STATUTE_DIR" --host 0.0.0.0 --port 8080 +fi + +cat > /usr/local/bin/mas-gateway < /etc/postfix/mas_rcpt.regexp +postconf -e \ + "maillog_file=/dev/stdout" "myhostname=$DOMAIN" "mydomain=$DOMAIN" \ + "mydestination=$DOMAIN" "relay_domains=" "mynetworks=127.0.0.0/8" \ + "smtpd_relay_restrictions=permit_mynetworks,check_recipient_access regexp:/etc/postfix/mas_rcpt.regexp,permit" \ + "local_transport=mas" "local_recipient_maps=" "mas_destination_recipient_limit=1" \ + "recipient_delimiter=+" "swap_bangpath=no" "allow_percent_hack=no" \ + "disable_vrfy_command=yes" "smtpd_helo_required=yes" "smtpd_recipient_limit=20" \ + "message_size_limit=10240000" "smtpd_banner=\$myhostname ESMTP MAS live test" \ + "smtpd_tls_security_level=may" \ + "smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem" \ + "smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key" \ + "inet_protocols=ipv4" "compatibility_level=3.6" +cat >> /etc/postfix/master.cf < 2 else None # optional JSONL evidence file +BIND = sys.argv[3] if len(sys.argv) > 3 else "0.0.0.0" EVENTS = [] @@ -20,7 +22,11 @@ class H(BaseHTTPRequestHandler): status, resp = r.status, r.read() except urllib.error.HTTPError as e: status, resp = e.code, e.read() - EVENTS.append({"event": json.loads(body), "app_status": status, "app": json.loads(resp or b"null")}) + rec = {"event": json.loads(body), "app_status": status, "app": json.loads(resp or b"null")} + EVENTS.append(rec) + if LOG: + with open(LOG, "a") as f: + f.write(json.dumps(rec) + "\n") self._send(status, resp) def do_GET(self): @@ -37,4 +43,4 @@ class H(BaseHTTPRequestHandler): pass -ThreadingHTTPServer(("0.0.0.0", 8024), H).serve_forever() +ThreadingHTTPServer((BIND, 8024), H).serve_forever()