mirror of
https://github.com/caddyserver/caddy.git
synced 2025-08-07 09:04:04 -04:00
caddytls: Improve ECH error logging (close #7152)
This commit is contained in:
parent
0badb071ef
commit
731e6c2482
@ -291,18 +291,54 @@ func (t *TLS) publishECHConfigs() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("publishing ECH config list",
|
logger.Debug("publishing ECH config list",
|
||||||
|
zap.String("publisher", publisherKey),
|
||||||
zap.Strings("domains", dnsNamesToPublish),
|
zap.Strings("domains", dnsNamesToPublish),
|
||||||
zap.Uint8s("config_ids", configIDs))
|
zap.Uint8s("config_ids", configIDs))
|
||||||
|
|
||||||
// publish this ECH config list with this publisher
|
// publish this ECH config list with this publisher
|
||||||
pubTime := time.Now()
|
pubTime := time.Now()
|
||||||
err := publisher.PublishECHConfigList(t.ctx, dnsNamesToPublish, echCfgListBin)
|
err := publisher.PublishECHConfigList(t.ctx, dnsNamesToPublish, echCfgListBin)
|
||||||
if err == nil {
|
|
||||||
t.logger.Info("published ECH configuration list",
|
var publishErrs PublishECHConfigListErrors
|
||||||
|
if errors.As(err, &publishErrs) {
|
||||||
|
// at least a partial failure, maybe a complete failure, but we can
|
||||||
|
// log each error by domain
|
||||||
|
for innerName, domainErr := range publishErrs {
|
||||||
|
t.logger.Error("failed to publish ECH configuration list",
|
||||||
|
zap.String("publisher", publisherKey),
|
||||||
|
zap.String("domain", innerName),
|
||||||
|
zap.Uint8s("config_ids", configIDs),
|
||||||
|
zap.Error(domainErr))
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
// generic error; assume the entire thing failed, I guess
|
||||||
|
t.logger.Error("failed publishing ECH configuration list",
|
||||||
|
zap.String("publisher", publisherKey),
|
||||||
zap.Strings("domains", dnsNamesToPublish),
|
zap.Strings("domains", dnsNamesToPublish),
|
||||||
zap.Uint8s("config_ids", configIDs),
|
zap.Uint8s("config_ids", configIDs),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
// update publication history, so that we don't unnecessarily republish every time
|
}
|
||||||
|
|
||||||
|
if err == nil || (len(publishErrs) > 0 && len(publishErrs) < len(dnsNamesToPublish)) {
|
||||||
|
// if publication for at least some domains succeeded, we should update our publication
|
||||||
|
// state for those domains to avoid unnecessarily republishing every time
|
||||||
|
someAll := "all"
|
||||||
|
if len(publishErrs) > 0 {
|
||||||
|
someAll = "some"
|
||||||
|
}
|
||||||
|
// make a list of names that published successfully with this publisher
|
||||||
|
// so that we update only their state in storage, not the failed ones
|
||||||
|
var successNames []string
|
||||||
|
for _, name := range dnsNamesToPublish {
|
||||||
|
if _, ok := publishErrs[name]; !ok {
|
||||||
|
successNames = append(successNames, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.logger.Info("successfully published ECH configuration list for "+someAll+" domains",
|
||||||
|
zap.String("publisher", publisherKey),
|
||||||
|
zap.Strings("domains", successNames),
|
||||||
|
zap.Uint8s("config_ids", configIDs))
|
||||||
|
|
||||||
for _, cfg := range echCfgList {
|
for _, cfg := range echCfgList {
|
||||||
if cfg.meta.Publications == nil {
|
if cfg.meta.Publications == nil {
|
||||||
cfg.meta.Publications = make(publicationHistory)
|
cfg.meta.Publications = make(publicationHistory)
|
||||||
@ -310,7 +346,7 @@ func (t *TLS) publishECHConfigs() error {
|
|||||||
if _, ok := cfg.meta.Publications[publisherKey]; !ok {
|
if _, ok := cfg.meta.Publications[publisherKey]; !ok {
|
||||||
cfg.meta.Publications[publisherKey] = make(map[string]time.Time)
|
cfg.meta.Publications[publisherKey] = make(map[string]time.Time)
|
||||||
}
|
}
|
||||||
for _, name := range dnsNamesToPublish {
|
for _, name := range successNames {
|
||||||
cfg.meta.Publications[publisherKey][name] = pubTime
|
cfg.meta.Publications[publisherKey][name] = pubTime
|
||||||
}
|
}
|
||||||
metaBytes, err := json.Marshal(cfg.meta)
|
metaBytes, err := json.Marshal(cfg.meta)
|
||||||
@ -323,10 +359,10 @@ func (t *TLS) publishECHConfigs() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
t.logger.Error("publishing ECH configuration list",
|
t.logger.Error("all domains failed to publish ECH configuration list (see earlier errors)",
|
||||||
zap.Strings("domains", publication.Domains),
|
zap.String("publisher", publisherKey),
|
||||||
zap.Uint8s("config_ids", configIDs),
|
zap.Strings("domains", dnsNamesToPublish),
|
||||||
zap.Error(err))
|
zap.Uint8s("config_ids", configIDs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -631,17 +667,19 @@ func (dnsPub ECHDNSPublisher) PublisherKey() string {
|
|||||||
return string(dnsPub.provider.(caddy.Module).CaddyModule().ID)
|
return string(dnsPub.provider.(caddy.Module).CaddyModule().ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublishECHConfigList publishes the given ECH config list to the given DNS names.
|
// PublishECHConfigList publishes the given ECH config list (as binary) to the given DNS names.
|
||||||
|
// If there is an error, it may be of type PublishECHConfigListErrors, detailing
|
||||||
|
// potentially multiple errors keyed by associated innerName.
|
||||||
func (dnsPub *ECHDNSPublisher) PublishECHConfigList(ctx context.Context, innerNames []string, configListBin []byte) error {
|
func (dnsPub *ECHDNSPublisher) PublishECHConfigList(ctx context.Context, innerNames []string, configListBin []byte) error {
|
||||||
nameservers := certmagic.RecursiveNameservers(nil) // TODO: we could make resolvers configurable
|
nameservers := certmagic.RecursiveNameservers(nil) // TODO: we could make resolvers configurable
|
||||||
|
|
||||||
|
errs := make(PublishECHConfigListErrors)
|
||||||
|
|
||||||
nextName:
|
nextName:
|
||||||
for _, domain := range innerNames {
|
for _, domain := range innerNames {
|
||||||
zone, err := certmagic.FindZoneByFQDN(ctx, dnsPub.logger, domain, nameservers)
|
zone, err := certmagic.FindZoneByFQDN(ctx, dnsPub.logger, domain, nameservers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dnsPub.logger.Error("could not determine zone for domain",
|
errs[domain] = fmt.Errorf("could not determine zone for domain: %w (domain=%s nameservers=%v)", err, domain, nameservers)
|
||||||
zap.String("domain", domain),
|
|
||||||
zap.Error(err))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,9 +691,7 @@ nextName:
|
|||||||
// we can augment the ech SvcParamKey with any other existing SvcParams
|
// we can augment the ech SvcParamKey with any other existing SvcParams
|
||||||
recs, err := dnsPub.provider.GetRecords(ctx, zone)
|
recs, err := dnsPub.provider.GetRecords(ctx, zone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dnsPub.logger.Error("unable to get existing DNS records to publish ECH data to HTTPS DNS record",
|
errs[domain] = fmt.Errorf("unable to get existing DNS records to publish ECH data to HTTPS DNS record: %w", err)
|
||||||
zap.String("domain", domain),
|
|
||||||
zap.Error(err))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var httpsRec libdns.ServiceBinding
|
var httpsRec libdns.ServiceBinding
|
||||||
@ -713,16 +749,14 @@ nextName:
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: Maybe this should just stop and return the error...
|
errs[domain] = fmt.Errorf("unable to publish ECH data to HTTPS DNS record: %w (zone=%s dns_record_name=%s)", err, zone, relName)
|
||||||
dnsPub.logger.Error("unable to publish ECH data to HTTPS DNS record",
|
|
||||||
zap.String("domain", domain),
|
|
||||||
zap.String("zone", zone),
|
|
||||||
zap.String("dns_record_name", relName),
|
|
||||||
zap.Error(err))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return errs
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -956,13 +990,35 @@ type ECHPublisher interface {
|
|||||||
// It is used to prevent duplicating publications.
|
// It is used to prevent duplicating publications.
|
||||||
PublisherKey() string
|
PublisherKey() string
|
||||||
|
|
||||||
// Publishes the ECH config list for the given innerNames. Some publishers
|
// Publishes the ECH config list (as binary) for the given innerNames. Some
|
||||||
// may not need a list of inner/protected names, and can ignore the argument;
|
// publishers may not need a list of inner/protected names, and can ignore the
|
||||||
// most, however, will want to use it to know which inner names are to be
|
// argument; most, however, will want to use it to know which inner names are
|
||||||
// associated with the given ECH config list.
|
// to be associated with the given ECH config list.
|
||||||
|
//
|
||||||
|
// Implementations should return an error of type PublishECHConfigListErrors
|
||||||
|
// when relevant to key errors to their associated innerName, but should never
|
||||||
|
// return a non-nil PublishECHConfigListErrors when its length is 0.
|
||||||
PublishECHConfigList(ctx context.Context, innerNames []string, echConfigList []byte) error
|
PublishECHConfigList(ctx context.Context, innerNames []string, echConfigList []byte) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PublishECHConfigListErrors is returned by ECHPublishers to describe one or more
|
||||||
|
// errors publishing an ECH config list from PublishECHConfigList. A non-nil, empty
|
||||||
|
// value of this type should never be returned.
|
||||||
|
type PublishECHConfigListErrors map[string]error
|
||||||
|
|
||||||
|
func (p PublishECHConfigListErrors) Error() string {
|
||||||
|
var sb strings.Builder
|
||||||
|
for innerName, err := range p {
|
||||||
|
if sb.Len() > 0 {
|
||||||
|
sb.WriteString("; ")
|
||||||
|
}
|
||||||
|
sb.WriteString(innerName)
|
||||||
|
sb.WriteString(": ")
|
||||||
|
sb.WriteString(err.Error())
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
type echConfigMeta struct {
|
type echConfigMeta struct {
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
Publications publicationHistory `json:"publications"`
|
Publications publicationHistory `json:"publications"`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user