panel-dkim-signing stage 2: OpenDKIM removed
test / test (push) Canceled after 0s

The panel's signer is the only one. Gone: the opendkim package and its
configuration, the syslog-relay and opendkim programs, /dev/log and
/run/opendkim, the reload by USR1 through supervisord
(internal/supervisor/supervisor.go), internal/syslogrelay, the port of
OpenDKIM's From: parser (internal/milter/mailparse.go and its probe,
harness and test/upstream scripts), OPENDKIM_SOCKET and OPENDKIM_DIR.

Keys: internal/domain/keys.go (Keys, NewKeys, DKIM_DIR=/data/dkim) keeps
the keys and writes a selector table, /data/dkim/selectors ("<name>
<selector>"), which the signer reads in place of the KeyTable - it reads
no database, as the sender check reads none. The table is written before
the signer serves (EnsureServerSigned moved there from the notifier).
Keys and table 0600, directories 0700, the panel's. The entrypoint copies
/data/opendkim/keys once, as the panel user, into /data/dkim.new renamed
when whole, and stops the start if the copy fails; /data/opendkim is left
for a rollback to 2.7.x.

Sender check: one RFC 5322 address as a mail program reads it, held
against the bindings; the 256-byte refusal and the texts naming OpenDKIM
go. Allowed() folded the domain through strings.ToLower, which makes the
Kelvin sign a "k" - the comparison with OpenDKIM's reading had hidden it;
it folds ASCII only now.

Health: two dkim-signer rows (applications, notifications) in Milter
sockets, opendkim out of the liveness set; the card no longer takes any
row with a note for the spam filter. Texts as in the design commit.

KILL stays in deploy/docker-compose.yml: measured on the test server,
root without it cannot signal a process of another uid - supervisord
stopping the panel, Postfix's master its children. The plan's "only use
was the reload" was wrong; the comment now gives the real uses.

e2e: one signature, the panel's, verified by dkimpy; the /data/dkim modes;
the OpenDKIM log and process checks, testNeverSignedForAnother and the
cited opendkim, libopendkim11 and libmilter1.0.1 go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-16 01:05:39 +03:00
co-authored by Claude Opus 5.5
parent 005922bc7d
commit faa3c11ae7
96 changed files with 971 additions and 2247 deletions
+10 -44
View File
@@ -1,8 +1,8 @@
; SelfPost process supervision.
;
; Start ORDER is enforced by priority=: OpenDKIM, then the panel (which opens
; the sender check's and the journal-milter's sockets), then the Postfix
; wrapper — which additionally blocks until the milter sockets are ready
; Start ORDER is enforced by priority=: the panel (which opens the sender
; check's, the DKIM signer's and the journal-milter's sockets), then the
; Postfix wrapper — which additionally blocks until the milter sockets are ready
; before starting Postfix. (supervisor 4.2.5, docs/configuration.rst,
; [program:x] "priority": "the start and shutdown ordering"; supervisor/
; supervisord.py, runforever(), transitions every group in that order in one
@@ -17,7 +17,7 @@
; (supervisor 4.2.5, supervisor/process.py, Subprocess.finish() and
; transition()): an exit after it is EXITED and simply restarted, for ever -
; which the count of exits covers (audit 2026-10-12, L32). logrotate's,
; postfix-reload's and syslog-relay's failures are left on Server > Health
; postfix-reload's and cert-reload's failures are left on Server > Health
; (build/crashexit.py).
[supervisord]
@@ -29,12 +29,11 @@ pidfile=/run/supervisord.pid
loglevel=info
; The control socket is reachable by the `supervisor` group, whose one member
; is the panel (the unprivileged `panel` user): it asks supervisord to signal
; OpenDKIM after it rewrites the DKIM tables, to run the Postfix reload, and
; for the processes' state. Whoever reaches the socket can stop, start or
; restart any program, so it is not the shared `selfpost` group's: OpenDKIM
; and Postfix are in that one for the files under /data, and a fault in either
; must not reach every other program (audit 2026-10-12, stage 5). Not
; is the panel (the unprivileged `panel` user): it asks supervisord to run the
; Postfix reload, and for the processes' state. Whoever reaches the socket can
; stop, start or restart any program, so it is not the shared `selfpost`
; group's: Postfix is in that one for the files under /data, and a fault in
; it must not reach every other program (audit 2026-10-12, stage 5). Not
; reachable by world. No HTTP auth is configured because access is gated by
; socket permissions, not the network. (supervisor 4.2.5,
; docs/configuration.rst, [unix_http_server]: chmod and chown set the socket's
@@ -50,38 +49,6 @@ supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///run/supervisor.sock
; The container's /dev/log (a link to the socket below, build/entrypoint.sh):
; what OpenDKIM - which logs through syslog(3) and nothing else - sends there
; comes out on stdout, into the container's log (internal/syslogrelay; audit
; 2026-10-12, L30). Before OpenDKIM, so its first lines are not lost; a
; message sent while nothing listens is dropped by syslog(3), not queued.
[program:syslog-relay]
command=/usr/local/bin/panel -syslog-relay=/run/syslog/log
user=panel
priority=50
autostart=true
autorestart=true
startretries=3
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:opendkim]
; It waits, five seconds at most, for the syslog relay's socket: supervisord
; starts programs in priority order without waiting for one to be ready, and
; OpenDKIM's start line would go nowhere (review of audit stage 5). exec keeps
; the supervised pid OpenDKIM's.
command=/bin/sh -c 'i=0; while [ ! -S /run/syslog/log ] && [ "$i" -lt 50 ]; do sleep 0.1; i=$((i+1)); done; exec /usr/sbin/opendkim -f -x /etc/opendkim.conf'
priority=100
autostart=true
autorestart=true
startretries=3
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
; user=panel also gives the panel its supplementary groups, selfpost and
; postdrop (build/Dockerfile): supervisor 4.2.5, supervisor/options.py,
; drop_privileges(), os.setgroups() from the user's memberships in
@@ -122,8 +89,7 @@ stderr_logfile_maxbytes=0
; One-shot reload helper. The panel runs unprivileged and cannot run `postfix
; reload` itself, and it cannot signal the Postfix master directly: `postfix
; start-fg` forks a separate master process, so a signal to the supervised
; foreground process never reaches it (unlike OpenDKIM, which runs in the
; foreground as the supervised process itself). Instead the panel asks
; foreground process never reaches it. Instead the panel asks
; supervisord — over the group-accessible control socket — to run this program,
; which runs the canonical `postfix reload` as root - or exits 75 when no
; master runs (build/postfix-reload.sh). autostart is off (it only runs on