mirror of
https://github.com/mjl-/mox.git
synced 2025-07-13 04:54:39 +03:00
switch to slog.Logger for logging, for easier reuse of packages by external software
we don't want external software to include internal details like mlog. slog.Logger is/will be the standard. we still have mlog for its helper functions, and its handler that logs in concise logfmt used by mox. packages that are not meant for reuse still pass around mlog.Log for convenience. we use golang.org/x/exp/slog because we also support the previous Go toolchain version. with the next Go release, we'll switch to the builtin slog.
This commit is contained in:
42
spf/spf.go
42
spf/spf.go
@ -16,6 +16,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slog"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
|
||||
@ -28,8 +30,6 @@ import (
|
||||
// sure we make names absolute when looking up. For verifying, we do not want to
|
||||
// verify names relative to our local search domain.
|
||||
|
||||
var xlog = mlog.New("spf")
|
||||
|
||||
var (
|
||||
metricSPFVerify = promauto.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
@ -129,11 +129,11 @@ var timeNow = time.Now
|
||||
// Lookup looks up and parses an SPF TXT record for domain.
|
||||
//
|
||||
// authentic indicates if the DNS results were DNSSEC-verified.
|
||||
func Lookup(ctx context.Context, resolver dns.Resolver, domain dns.Domain) (rstatus Status, rtxt string, rrecord *Record, authentic bool, rerr error) {
|
||||
log := xlog.WithContext(ctx)
|
||||
func Lookup(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, domain dns.Domain) (rstatus Status, rtxt string, rrecord *Record, authentic bool, rerr error) {
|
||||
log := mlog.New("spf", elog)
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Debugx("spf lookup result", rerr, mlog.Field("domain", domain), mlog.Field("status", rstatus), mlog.Field("record", rrecord), mlog.Field("duration", time.Since(start)))
|
||||
log.Debugx("spf lookup result", rerr, slog.Any("domain", domain), slog.Any("status", rstatus), slog.Any("record", rrecord), slog.Duration("duration", time.Since(start)))
|
||||
}()
|
||||
|
||||
// ../rfc/7208:586
|
||||
@ -194,12 +194,12 @@ func Lookup(ctx context.Context, resolver dns.Resolver, domain dns.Domain) (rsta
|
||||
// of 2 lookups resulting in no records ("void lookups").
|
||||
//
|
||||
// authentic indicates if the DNS results were DNSSEC-verified.
|
||||
func Verify(ctx context.Context, resolver dns.Resolver, args Args) (received Received, domain dns.Domain, explanation string, authentic bool, rerr error) {
|
||||
log := xlog.WithContext(ctx)
|
||||
func Verify(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, args Args) (received Received, domain dns.Domain, explanation string, authentic bool, rerr error) {
|
||||
log := mlog.New("spf", elog)
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
metricSPFVerify.WithLabelValues(string(received.Result)).Observe(float64(time.Since(start)) / float64(time.Second))
|
||||
log.Debugx("spf verify result", rerr, mlog.Field("domain", args.domain), mlog.Field("ip", args.RemoteIP), mlog.Field("status", received.Result), mlog.Field("explanation", explanation), mlog.Field("duration", time.Since(start)))
|
||||
log.Debugx("spf verify result", rerr, slog.Any("domain", args.domain), slog.Any("ip", args.RemoteIP), slog.Any("status", received.Result), slog.String("explanation", explanation), slog.Duration("duration", time.Since(start)))
|
||||
}()
|
||||
|
||||
isHello, ok := prepare(&args)
|
||||
@ -215,7 +215,7 @@ func Verify(ctx context.Context, resolver dns.Resolver, args Args) (received Rec
|
||||
return received, dns.Domain{}, "", false, nil
|
||||
}
|
||||
|
||||
status, mechanism, expl, authentic, err := checkHost(ctx, resolver, args)
|
||||
status, mechanism, expl, authentic, err := checkHost(ctx, log, resolver, args)
|
||||
comment := fmt.Sprintf("domain %s", args.domain.ASCII)
|
||||
if isHello {
|
||||
comment += ", from ehlo because mailfrom is empty"
|
||||
@ -272,37 +272,35 @@ func prepare(args *Args) (isHello bool, ok bool) {
|
||||
}
|
||||
|
||||
// lookup spf record, then evaluate args against it.
|
||||
func checkHost(ctx context.Context, resolver dns.Resolver, args Args) (rstatus Status, mechanism, rexplanation string, rauthentic bool, rerr error) {
|
||||
status, _, record, rauthentic, err := Lookup(ctx, resolver, args.domain)
|
||||
func checkHost(ctx context.Context, log mlog.Log, resolver dns.Resolver, args Args) (rstatus Status, mechanism, rexplanation string, rauthentic bool, rerr error) {
|
||||
status, _, record, rauthentic, err := Lookup(ctx, log.Logger, resolver, args.domain)
|
||||
if err != nil {
|
||||
return status, "", "", rauthentic, err
|
||||
}
|
||||
|
||||
var evalAuthentic bool
|
||||
rstatus, mechanism, rexplanation, evalAuthentic, rerr = evaluate(ctx, record, resolver, args)
|
||||
rstatus, mechanism, rexplanation, evalAuthentic, rerr = evaluate(ctx, log, record, resolver, args)
|
||||
rauthentic = rauthentic && evalAuthentic
|
||||
return
|
||||
}
|
||||
|
||||
// Evaluate evaluates the IP and names from args against the SPF DNS record for the domain.
|
||||
func Evaluate(ctx context.Context, record *Record, resolver dns.Resolver, args Args) (rstatus Status, mechanism, rexplanation string, rauthentic bool, rerr error) {
|
||||
func Evaluate(ctx context.Context, elog *slog.Logger, record *Record, resolver dns.Resolver, args Args) (rstatus Status, mechanism, rexplanation string, rauthentic bool, rerr error) {
|
||||
log := mlog.New("spf", elog)
|
||||
_, ok := prepare(&args)
|
||||
if !ok {
|
||||
return StatusNone, "default", "", false, fmt.Errorf("no domain name to validate")
|
||||
}
|
||||
return evaluate(ctx, record, resolver, args)
|
||||
return evaluate(ctx, log, record, resolver, args)
|
||||
}
|
||||
|
||||
// evaluate RemoteIP against domain from args, given record.
|
||||
func evaluate(ctx context.Context, record *Record, resolver dns.Resolver, args Args) (rstatus Status, mechanism, rexplanation string, rauthentic bool, rerr error) {
|
||||
log := xlog.WithContext(ctx)
|
||||
func evaluate(ctx context.Context, log mlog.Log, record *Record, resolver dns.Resolver, args Args) (rstatus Status, mechanism, rexplanation string, rauthentic bool, rerr error) {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Debugx("spf evaluate result", rerr, mlog.Field("dnsrequests", *args.dnsRequests), mlog.Field("voidlookups", *args.voidLookups), mlog.Field("domain", args.domain), mlog.Field("status", rstatus), mlog.Field("mechanism", mechanism), mlog.Field("explanation", rexplanation), mlog.Field("duration", time.Since(start)))
|
||||
log.Debugx("spf evaluate result", rerr, slog.Int("dnsrequests", *args.dnsRequests), slog.Int("voidlookups", *args.voidLookups), slog.Any("domain", args.domain), slog.Any("status", rstatus), slog.String("mechanism", mechanism), slog.String("explanation", rexplanation), slog.Duration("duration", time.Since(start)))
|
||||
}()
|
||||
|
||||
resolver = dns.WithPackage(resolver, "spf")
|
||||
|
||||
if args.dnsRequests == nil {
|
||||
args.dnsRequests = new(int)
|
||||
args.voidLookups = new(int)
|
||||
@ -388,7 +386,7 @@ func evaluate(ctx context.Context, record *Record, resolver dns.Resolver, args A
|
||||
nargs := args
|
||||
nargs.domain = dns.Domain{ASCII: strings.TrimSuffix(name, ".")}
|
||||
nargs.explanation = &record.Explanation // ../rfc/7208:1548
|
||||
status, _, _, authentic, err := checkHost(ctx, resolver, nargs)
|
||||
status, _, _, authentic, err := checkHost(ctx, log, resolver, nargs)
|
||||
rauthentic = rauthentic && authentic
|
||||
// ../rfc/7208:1202
|
||||
switch status {
|
||||
@ -477,7 +475,7 @@ func evaluate(ctx context.Context, record *Record, resolver dns.Resolver, args A
|
||||
for _, rname := range rnames {
|
||||
rd, err := dns.ParseDomain(strings.TrimSuffix(rname, "."))
|
||||
if err != nil {
|
||||
log.Errorx("bad address in ptr record", err, mlog.Field("address", rname))
|
||||
log.Errorx("bad address in ptr record", err, slog.String("address", rname))
|
||||
continue
|
||||
}
|
||||
// ../rfc/7208-eid4751 ../rfc/7208:1323
|
||||
@ -565,7 +563,7 @@ func evaluate(ctx context.Context, record *Record, resolver dns.Resolver, args A
|
||||
nargs := args
|
||||
nargs.domain = dns.Domain{ASCII: strings.TrimSuffix(name, ".")}
|
||||
nargs.explanation = nil // ../rfc/7208:1548
|
||||
status, mechanism, expl, authentic, err := checkHost(ctx, resolver, nargs)
|
||||
status, mechanism, expl, authentic, err := checkHost(ctx, log, resolver, nargs)
|
||||
rauthentic = rauthentic && authentic
|
||||
if status == StatusNone {
|
||||
return StatusPermerror, mechanism, "", rauthentic, err
|
||||
|
@ -10,9 +10,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mjl-/mox/dns"
|
||||
"github.com/mjl-/mox/mlog"
|
||||
"github.com/mjl-/mox/smtp"
|
||||
)
|
||||
|
||||
var pkglog = mlog.New("spf", nil)
|
||||
|
||||
func TestLookup(t *testing.T) {
|
||||
resolver := dns.MockResolver{
|
||||
TXT: map[string][]string{
|
||||
@ -31,7 +34,7 @@ func TestLookup(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
d := dns.Domain{ASCII: domain}
|
||||
status, txt, record, _, err := Lookup(context.Background(), resolver, d)
|
||||
status, txt, record, _, err := Lookup(context.Background(), pkglog.Logger, resolver, d)
|
||||
if (err == nil) != (expErr == nil) || err != nil && !errors.Is(err, expErr) {
|
||||
t.Fatalf("got err %v, expected err %v", err, expErr)
|
||||
}
|
||||
@ -259,7 +262,7 @@ func TestVerify(t *testing.T) {
|
||||
LocalIP: xip("127.0.0.1"),
|
||||
LocalHostname: dns.Domain{ASCII: "localhost"},
|
||||
}
|
||||
received, _, _, _, err := Verify(ctx, r, args)
|
||||
received, _, _, _, err := Verify(ctx, pkglog.Logger, r, args)
|
||||
if received.Result != status {
|
||||
t.Fatalf("got status %q, expected %q, for ip %q (err %v)", received.Result, status, ip, err)
|
||||
}
|
||||
@ -345,7 +348,7 @@ func TestVerifyMultipleDomain(t *testing.T) {
|
||||
LocalIP: net.ParseIP("127.0.0.1"),
|
||||
LocalHostname: dns.Domain{ASCII: "localhost"},
|
||||
}
|
||||
received, _, _, _, err := Verify(context.Background(), resolver, args)
|
||||
received, _, _, _, err := Verify(context.Background(), pkglog.Logger, resolver, args)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
@ -370,7 +373,7 @@ func TestVerifyScenarios(t *testing.T) {
|
||||
test := func(resolver dns.Resolver, args Args, expStatus Status, expDomain string, expExpl string, expErr error) {
|
||||
t.Helper()
|
||||
|
||||
recv, d, expl, _, err := Verify(context.Background(), resolver, args)
|
||||
recv, d, expl, _, err := Verify(context.Background(), pkglog.Logger, resolver, args)
|
||||
if (err == nil) != (expErr == nil) || err != nil && !errors.Is(err, expErr) {
|
||||
t.Fatalf("got err %v, expected %v", err, expErr)
|
||||
}
|
||||
@ -505,7 +508,7 @@ func TestEvaluate(t *testing.T) {
|
||||
record := &Record{}
|
||||
resolver := dns.MockResolver{}
|
||||
args := Args{}
|
||||
status, _, _, _, _ := Evaluate(context.Background(), record, resolver, args)
|
||||
status, _, _, _, _ := Evaluate(context.Background(), pkglog.Logger, record, resolver, args)
|
||||
if status != StatusNone {
|
||||
t.Fatalf("got status %q, expected none", status)
|
||||
}
|
||||
@ -513,7 +516,7 @@ func TestEvaluate(t *testing.T) {
|
||||
args = Args{
|
||||
HelloDomain: dns.IPDomain{Domain: dns.Domain{ASCII: "test.example"}},
|
||||
}
|
||||
status, mechanism, _, _, err := Evaluate(context.Background(), record, resolver, args)
|
||||
status, mechanism, _, _, err := Evaluate(context.Background(), pkglog.Logger, record, resolver, args)
|
||||
if status != StatusNeutral || mechanism != "default" || err != nil {
|
||||
t.Fatalf("got status %q, mechanism %q, err %v, expected neutral, default, no error", status, mechanism, err)
|
||||
}
|
||||
|
Reference in New Issue
Block a user