#27: never publish a DKIM record with an empty key, and say why one is missing
A fresh deployment published "v=DKIM1; k=rsa; p=" for its own domain. An empty p= is not an absent key, it is a revoked one (RFC 6376 section 3.6.1): every verifier reading it treats all signatures from that selector as invalid. On a domain whose DMARC policy is p=quarantine with strict alignment - which this reconciler generates - that quarantines all of its own outbound mail. Worse than publishing nothing. The chain: DkimRepository.Insert is an INSERT ... SELECT conditional on the domain existing in the domains table, so on an empty database it inserts no rows and returns no error. FindPublicKey then finds nothing, ensure() returns an empty string with no error, and the reconciler faithfully published the empty value. Every field along that path was behaving as written; nothing checked that the result meant anything. Two changes: - The record builder omits a DKIM record when its key is empty, so the revocation cannot be published regardless of why the key is missing. - Provisioning logs when it produced no key, naming the likely cause. The insert being conditional on an onboarded domain is exactly the case a new operator hits, and "no key, domain probably not onboarded" is the difference between a diagnosis and unsigned mail with no explanation. It stays non-fatal: erroring here would abort the whole reconcile and leave a new install with no A, MX or SPF records either. Found while migrating to a new host: the fresh database had no domain row, so the first reconcile revoked the domain's DKIM. The two published records have been deleted from the zone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7c3a2d165a
commit
de16efe874
5 files changed
+170
-18
No files matched your search
+14
-2
@@ -6,6 +6,8 @@
|
||||
# secret in a published repository is not a secret.
|
||||
#
|
||||
# Generate each secret with: openssl rand -base64 36
|
||||
# except POSTGRES_PASSWORD and REDIS_PASSWORD, which go inside connection URIs
|
||||
# and must be URL-safe - see the note above them.
|
||||
|
||||
# --- Container images -------------------------------------------------------
|
||||
# Published by .github/workflows/release.yml for linux/amd64 and linux/arm64.
|
||||
@@ -26,10 +28,20 @@ PUBLIC_IPV4=203.0.113.10 # CHANGE - the VPS public IPv4
|
||||
PUBLIC_IPV6=
|
||||
|
||||
# --- Secrets ----------------------------------------------------------------
|
||||
# These two are substituted into connection URIs - postgres://user:PASS@db/... and
|
||||
# redis://:PASS@redis:6379 - so they must contain no character that means
|
||||
# something in a URL. Use hex:
|
||||
#
|
||||
# openssl rand -hex 24
|
||||
#
|
||||
# NOT `openssl rand -base64`, whose alphabet includes "/" and "+". A "/" ends
|
||||
# the authority component, so the host is parsed as part of the password and
|
||||
# every connection fails authentication - which surfaces as the migrations
|
||||
# container exiting 1 while Postgres itself reports healthy.
|
||||
POSTGRES_DB=lambdamail
|
||||
POSTGRES_USER=lambdamail
|
||||
POSTGRES_PASSWORD=CHANGE-generate-with-openssl-rand
|
||||
REDIS_PASSWORD=CHANGE-generate-with-openssl-rand
|
||||
POSTGRES_PASSWORD=CHANGE-generate-with-openssl-rand-hex-24
|
||||
REDIS_PASSWORD=CHANGE-generate-with-openssl-rand-hex-24
|
||||
# Signs webmail and admin sessions. Minimum 32 characters; the auth service
|
||||
# refuses to start below that.
|
||||
JWT_SECRET=CHANGE-generate-with-openssl-rand-at-least-32-chars
|
||||
|
||||
Reference in new issue
Block a user