diff --git a/decnet/templates/ssh/Dockerfile b/decnet/templates/ssh/Dockerfile index 00373f21..364f3bcc 100644 --- a/decnet/templates/ssh/Dockerfile +++ b/decnet/templates/ssh/Dockerfile @@ -52,9 +52,19 @@ RUN sed -i \ # /proc/1/fd/1 is the container-stdout fd Docker attached — writing there # surfaces lines in `docker logs` without needing a named pipe + relay cat # (which would be readable AND writable by any root-in-container process). +# +# Filter: drop sshd's native chatter ("Failed password", "Connection from", +# "Connection closed by …") and the pam_unix lines emitted from sshd's PAM +# stack (programname is inherited from the calling process, so pam_unix(sshd:*) +# lines arrive as programname=sshd). These add no signal — our auth-helper +# writes structured login_attempt events directly to /proc/1/fd/1 and +# capture.sh emits sessions via `logger -t systemd-journal`. sudo / login / +# su pam_unix lines are NOT dropped (different programname), so privilege +# escalation telemetry still flows. RUN printf '%s\n' \ '# auth + user events → container stdout as RFC 5424' \ '$template RFC5424fmt,"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n"' \ + ':programname, isequal, "sshd" stop' \ 'auth,authpriv.* /proc/1/fd/1;RFC5424fmt' \ 'user.* /proc/1/fd/1;RFC5424fmt' \ > /etc/rsyslog.d/50-journal-forward.conf diff --git a/tests/services/test_ssh.py b/tests/services/test_ssh.py index a3a67d45..2f6d724d 100644 --- a/tests/services/test_ssh.py +++ b/tests/services/test_ssh.py @@ -143,6 +143,23 @@ def test_dockerfile_rsyslog_conf_created(): assert "RFC5424fmt" in df +def test_dockerfile_drops_sshd_native_chatter(): + """sshd's native syslog (`Failed password`, `Connection from`, …) and + the pam_unix lines emitted from sshd's PAM stack add no signal — the + auth-helper writes structured login_attempt events out-of-band. The + rsyslog config must drop them via a `:programname, isequal, "sshd" stop` + rule that comes BEFORE the forwarding actions. sudo / login pam_unix + lines must still flow (different programname).""" + df = _dockerfile_text() + stop_rule = ':programname, isequal, "sshd" stop' + assert stop_rule in df, "sshd drop rule missing from rsyslog config" + # Order matters: stop must precede the forwarding actions inside the + # same printf block, otherwise rsyslog forwards before evaluating it. + stop_idx = df.index(stop_rule) + fwd_idx = df.index("auth,authpriv.* /proc/1/fd/1;RFC5424fmt") + assert stop_idx < fwd_idx, "stop rule must come before forwarding action" + + def test_dockerfile_sudoers_syslog(): df = _dockerfile_text() assert "syslog=auth" in df