No description
  • Go 98.9%
  • Makefile 0.6%
  • Dockerfile 0.5%
Find a file
2026-04-30 09:17:33 +07:00
checker checker: join recorded owner Hdr.Name to parent FQDN 2026-04-30 09:17:33 +07:00
plugin Initial commit 2026-04-26 18:11:28 +07:00
.gitignore Initial commit 2026-04-26 18:11:28 +07:00
Dockerfile docker: add HEALTHCHECK probing /health 2026-04-26 18:11:28 +07:00
go.mod docker: add HEALTHCHECK probing /health 2026-04-26 18:11:28 +07:00
go.sum docker: add HEALTHCHECK probing /health 2026-04-26 18:11:28 +07:00
LICENSE Initial commit 2026-04-26 18:11:28 +07:00
main.go Initial commit 2026-04-26 18:11:28 +07:00
Makefile Initial commit 2026-04-26 18:11:28 +07:00
NOTICE Initial commit 2026-04-26 18:11:28 +07:00
README.md Initial commit 2026-04-26 18:11:28 +07:00

checker-email-keys

DANE-Email posture checker for happyDomain.

Runs a comprehensive testsuite on a domain's DNS-published OpenPGP key (OPENPGPKEY, RFC 7929) or S/MIME certificate (SMIMEA, RFC 8162) and renders an actionable HTML report whose top block nudges the user toward the fix for the most common failure scenarios.

This checker binds to the happyDomain services:

  • abstract.OpenPGP: individual user's PGP key, owner-hashed below ._openpgpkey.<zone>.
  • abstract.SMimeCert: user's S/MIME certificate, owner-hashed below ._smimecert.<zone>.

Security scope

This checker validates DNS publication and the structure/metadata of the keys it finds. It does not cryptographically verify them:

  • OpenPGP signatures (self-signatures, third-party certifications, revocations beyond the presence of a revocation packet) are not verified.
  • S/MIME certificate chains are not built or validated against any trust anchor; revocation (CRL/OCSP) is not checked.
  • Authenticity of the records themselves is delegated to the validating resolver via the DNSSEC AD flag (see dnssec_not_validated). Run the checker against a resolver you trust to perform DNSSEC validation.

Treat a green report as "the record is well-formed and DNSSEC-signed", not as "the key is trustworthy".

Tests run

All findings are tagged by severity (info / warn / crit) so the rule engine can fold them into a single CheckState.

DNS (both record types)

Code Severity What it catches
dns_query_failed crit The resolver returned an error or did not answer.
dns_no_record crit The authoritative answer has no record at the expected owner.
dnssec_not_validated crit / warn The validating resolver did not set AD. RFC 7929/8162 mandate DNSSEC; the severity is configurable via requireDNSSEC.
dns_record_mismatch warn The record returned by DNS differs from the one declared in the service (typically a stale zone on the authoritative servers).
owner_hash_mismatch crit Record owner-name first label is not sha256(localpart)[:28]; mail clients will never find it.

OpenPGP-specific (RFC 7929)

Code Severity What it catches
pgp_parse_error crit Malformed base64 or OpenPGP packet stream.
pgp_no_entity crit Record decoded but carries no valid entity.
pgp_primary_revoked crit Primary key has a revocation signature.
pgp_primary_expired crit Self-signature expired; clients will refuse to encrypt.
pgp_primary_expiring_soon warn Expires within the certExpiryWarnDays window (default 30).
pgp_weak_algorithm warn Uses DSA / ElGamal (phase-out).
pgp_weak_key_size crit / warn RSA below 2048 bits is critical, 2048-3071 is a warn.
pgp_no_encryption_subkey crit No active key in the entity advertises encryption capability.
pgp_no_identity warn No self-signed User ID.
pgp_uid_mismatch info None of the UIDs reference <username@…>.
pgp_multiple_entities warn Record carries more than one entity (RFC 7929 recommends one).
pgp_record_too_large warn Raw key > 4 KiB; forces UDP→TCP fallback on every lookup.

SMIMEA-specific (RFC 8162)

Code Severity What it catches
smimea_bad_usage / _selector / _match_type crit Field outside the allowed range.
smimea_cert_parse_error crit Hex-encoded blob is not a valid X.509 certificate / SPKI.
smimea_cert_expired / _not_yet_valid crit notBefore / notAfter gate the current time out.
smimea_cert_expiring_soon warn Within the certExpiryWarnDays window.
smimea_no_email_protection_eku crit / warn Missing emailProtection EKU (RFC 8550/8551 agents will reject).
smimea_missing_key_usage warn Neither digitalSignature nor keyEncipherment key-usage is set.
smimea_email_mismatch info No email SAN starts with <username>@.
smimea_weak_signature_algorithm crit MD5 / SHA-1 based signature.
smimea_weak_key_size crit / warn RSA < 2048 / 3072 bits.
smimea_self_signed info Self-signed certificate paired with PKIX-EE usage.
smimea_hash_only info Matching-type 1/2 only carries a digest; certificate can't be inspected.

Options

Id Type Default Description
resolver string (system) Validating resolver to query; comma-separated list accepted.
certExpiryWarnDays number 30 Raise an expiring_soon warning within this window.
requireDNSSEC bool true When false, missing AD is a warn instead of crit.
requireEmailProtection bool true When false, missing emailProtection EKU is a warn instead of crit.

Auto-filled by the host: domain_name, subdomain, service, service_type.

Running

# Plugin (loaded by happyDomain at startup)
make plugin

# Standalone HTTP server
make && ./checker-email-keys -listen :8080