From 2a1ba01940682d16c1d376ff490d3b5098c74739 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Sun, 26 Apr 2026 22:29:48 +0700 Subject: [PATCH 1/6] Bump checker-sdk to v1.5.0 --- checkers/matrix_federation.go | 6 ++++-- checkers/ns_restrictions.go | 6 ++++-- checkers/ping.go | 6 ++++-- checkers/zonemaster.go | 6 ++++-- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/checkers/matrix_federation.go b/checkers/matrix_federation.go index b6175d1f..d8af5b0a 100644 --- a/checkers/matrix_federation.go +++ b/checkers/matrix_federation.go @@ -23,11 +23,13 @@ package checkers import ( matrix "git.happydns.org/checker-matrix/checker" + sdk "git.happydns.org/checker-sdk-go/checker" "git.happydns.org/happyDomain/internal/checker" ) func init() { - checker.RegisterObservationProvider(matrix.Provider()) + prvd := matrix.Provider() + checker.RegisterObservationProvider(prvd) // Not Externalizable checker as it already calls a HTTP API - checker.RegisterChecker(matrix.Definition()) + checker.RegisterChecker(prvd.(sdk.CheckerDefinitionProvider).Definition()) } diff --git a/checkers/ns_restrictions.go b/checkers/ns_restrictions.go index 18de6291..a7c072d5 100644 --- a/checkers/ns_restrictions.go +++ b/checkers/ns_restrictions.go @@ -23,10 +23,12 @@ package checkers import ( nsr "git.happydns.org/checker-ns-restrictions/checker" + sdk "git.happydns.org/checker-sdk-go/checker" "git.happydns.org/happyDomain/internal/checker" ) func init() { - checker.RegisterObservationProvider(nsr.Provider()) - checker.RegisterExternalizableChecker(nsr.Definition()) + prvd := nsr.Provider() + checker.RegisterObservationProvider(prvd) + checker.RegisterExternalizableChecker(prvd.(sdk.CheckerDefinitionProvider).Definition()) } diff --git a/checkers/ping.go b/checkers/ping.go index c289d892..cab74a4c 100644 --- a/checkers/ping.go +++ b/checkers/ping.go @@ -23,10 +23,12 @@ package checkers import ( ping "git.happydns.org/checker-ping/checker" + sdk "git.happydns.org/checker-sdk-go/checker" "git.happydns.org/happyDomain/internal/checker" ) func init() { - checker.RegisterObservationProvider(ping.Provider()) - checker.RegisterExternalizableChecker(ping.Definition()) + prvd := ping.Provider() + checker.RegisterObservationProvider(prvd) + checker.RegisterExternalizableChecker(prvd.(sdk.CheckerDefinitionProvider).Definition()) } diff --git a/checkers/zonemaster.go b/checkers/zonemaster.go index d8c56d05..a5f03c2f 100644 --- a/checkers/zonemaster.go +++ b/checkers/zonemaster.go @@ -22,12 +22,14 @@ package checkers import ( + sdk "git.happydns.org/checker-sdk-go/checker" zonemaster "git.happydns.org/checker-zonemaster/checker" "git.happydns.org/happyDomain/internal/checker" ) func init() { - checker.RegisterObservationProvider(zonemaster.Provider()) + prvd := zonemaster.Provider() + checker.RegisterObservationProvider(prvd) // Not Externalizable checker as it already calls a HTTP API - checker.RegisterChecker(zonemaster.Definition()) + checker.RegisterChecker(prvd.(sdk.CheckerDefinitionProvider).Definition()) } diff --git a/go.mod b/go.mod index e0680cf9..2b9e6a9b 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.happydns.org/checker-matrix v0.1.0 git.happydns.org/checker-ns-restrictions v0.1.0 git.happydns.org/checker-ping v0.1.0 - git.happydns.org/checker-sdk-go v1.4.0 + git.happydns.org/checker-sdk-go v1.5.0 git.happydns.org/checker-zonemaster v0.1.0 github.com/JGLTechnologies/gin-rate-limit v1.5.8 github.com/StackExchange/dnscontrol/v4 v4.34.0 diff --git a/go.sum b/go.sum index 2c79e56f..cd1d00db 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ git.happydns.org/checker-ns-restrictions v0.1.0 h1:SfIst5rHmviH9YGfUH3R108iZpeHk git.happydns.org/checker-ns-restrictions v0.1.0/go.mod h1:8B0KhImefLDFNIYYxdztsCq3576PIT7vM5KhXnwZ1Zw= git.happydns.org/checker-ping v0.1.0 h1:Cu9Upvs/WoAWHi0A/1QahmuqB4/99n/jK29W/Bnv2y0= git.happydns.org/checker-ping v0.1.0/go.mod h1:P0xv85b2MoVud7UXbfoS0n3qMlyQGfg+uz1knN+7Q7w= -git.happydns.org/checker-sdk-go v1.4.0 h1:sO8EnF3suhNgYLRsbmCZWJOymH/oNMrOUqj3FEzJArs= -git.happydns.org/checker-sdk-go v1.4.0/go.mod h1:aNAcfYFfbhvH9kJhE0Njp5GX0dQbxdRB0rJ0KvSC5nI= +git.happydns.org/checker-sdk-go v1.5.0 h1:5uD5Cm6xJ+lwnhbJ09iCXGHbYS9zRh+Yh0NeBHkAPBY= +git.happydns.org/checker-sdk-go v1.5.0/go.mod h1:aNAcfYFfbhvH9kJhE0Njp5GX0dQbxdRB0rJ0KvSC5nI= git.happydns.org/checker-zonemaster v0.1.0 h1:1Qa0HtAGTfNU/3XvHhxDNJR9Td8DLQa8PrcNbexoeyI= git.happydns.org/checker-zonemaster v0.1.0/go.mod h1:HnVHYW3EZWy03Z0g1KMLUT9XJbIzmgoFBfid/jpe6kA= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28= From 0ee552a35b3ec92cf61c4d46794f75291251bad4 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Mon, 27 Apr 2026 00:05:24 +0700 Subject: [PATCH 2/6] Add per-checker remote address CLI flags Register one -checker--remote-address flag per registered checker, allowing operators to delegate a checker's observation collection to a remote HTTP service at startup. When set, the CLI/config value wins over any per-checker "endpoint" AdminOpt. Co-Authored-By: Claude Opus 4.7 (1M context) --- internal/app/app.go | 5 ++++ internal/config/cli.go | 15 ++++++++++ internal/config/custom.go | 23 ++++++++++++++ internal/usecase/checker/checker_engine.go | 35 +++++++++++++++------- model/config.go | 6 ++++ 5 files changed, 74 insertions(+), 10 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index 44bcb82a..9d351899 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -287,6 +287,11 @@ func (app *App) initUsecases() { app.store, app.store, ) + if setter, ok := app.usecases.checkerEngine.(interface { + SetRemoteAddresses(map[string]string) + }); ok { + setter.SetRemoteAddresses(app.cfg.CheckerRemoteAddresses) + } // Build the user-level gate so paused or long-inactive users do not // get checked. The same user resolver is reused by the janitor for // per-user retention overrides. diff --git a/internal/config/cli.go b/internal/config/cli.go index 6937afe2..bc660ad9 100644 --- a/internal/config/cli.go +++ b/internal/config/cli.go @@ -27,6 +27,7 @@ import ( "runtime" "time" + "git.happydns.org/happyDomain/internal/checker" "git.happydns.org/happyDomain/internal/storage" "git.happydns.org/happyDomain/model" ) @@ -70,6 +71,20 @@ func declareFlags(o *happydns.Options) { flag.Var(&stringSlice{&o.PluginsDirectories}, "plugins-directory", "Path to a directory containing checker plugins (.so files); may be repeated") + // One -checker--remote-address flag per registered checker. Checkers + // register themselves in init() of the blank-imported `checkers` package, + // so by the time declareFlags runs the registry is fully populated. + if o.CheckerRemoteAddresses == nil { + o.CheckerRemoteAddresses = map[string]string{} + } + for id := range checker.GetCheckers() { + flag.Var( + &mapEntry{Map: &o.CheckerRemoteAddresses, Key: id}, + fmt.Sprintf("checker-%s-remote-address", id), + fmt.Sprintf("URL of a remote HTTP service that should run the %q checker (overrides any per-checker endpoint AdminOpt)", id), + ) + } + // Others flags are declared in some other files likes sources, storages, ... when they need specials configurations } diff --git a/internal/config/custom.go b/internal/config/custom.go index 775f9026..d2b7c08a 100644 --- a/internal/config/custom.go +++ b/internal/config/custom.go @@ -46,6 +46,29 @@ func (s *stringSlice) Set(value string) error { return nil } +// mapEntry is a flag.Value that writes the flag value into a map under a +// preset key. Used to register one flag per checker writing into a shared +// map[string]string on Options. +type mapEntry struct { + Map *map[string]string + Key string +} + +func (m *mapEntry) String() string { + if m.Map == nil || *m.Map == nil { + return "" + } + return (*m.Map)[m.Key] +} + +func (m *mapEntry) Set(value string) error { + if *m.Map == nil { + *m.Map = map[string]string{} + } + (*m.Map)[m.Key] = value + return nil +} + type JWTSecretKey struct { Secret *[]byte } diff --git a/internal/usecase/checker/checker_engine.go b/internal/usecase/checker/checker_engine.go index 656f538d..731a241f 100644 --- a/internal/usecase/checker/checker_engine.go +++ b/internal/usecase/checker/checker_engine.go @@ -34,14 +34,23 @@ import ( // checkerEngine implements the happydns.CheckerEngine interface. type checkerEngine struct { - optionsUC *CheckerOptionsUsecase - evalStore CheckEvaluationStorage - execStore ExecutionStorage - snapStore ObservationSnapshotStorage - cacheStore ObservationCacheStorage - entryStore DiscoveryEntryStorage - obsRefStore DiscoveryObservationStorage - relatedLookup checkerPkg.RelatedObservationLookup + optionsUC *CheckerOptionsUsecase + evalStore CheckEvaluationStorage + execStore ExecutionStorage + snapStore ObservationSnapshotStorage + cacheStore ObservationCacheStorage + entryStore DiscoveryEntryStorage + obsRefStore DiscoveryObservationStorage + relatedLookup checkerPkg.RelatedObservationLookup + remoteAddresses map[string]string +} + +// SetRemoteAddresses installs a checker-ID -> remote HTTP endpoint map. When +// a non-empty entry exists for a checker, runPipeline routes its observation +// collection through the remote service instead of the local provider, and +// takes precedence over any per-checker "endpoint" AdminOpt. +func (e *checkerEngine) SetRemoteAddresses(addrs map[string]string) { + e.remoteAddresses = addrs } // NewCheckerEngine creates a new CheckerEngine implementation. Passing nil @@ -189,8 +198,14 @@ func (e *checkerEngine) runPipeline(ctx context.Context, def *happydns.CheckerDe obsCtx.SetRelatedLookup(def.ID, e.relatedLookup) } - // If an endpoint is configured, override observation providers with HTTP transport. - if endpoint, ok := mergedOpts["endpoint"].(string); ok && endpoint != "" { + // If an endpoint is configured, override observation providers with HTTP + // transport. The CLI/config -checker--remote-address value (if set) + // wins over the per-checker "endpoint" AdminOpt. + endpoint, _ := mergedOpts["endpoint"].(string) + if cli, ok := e.remoteAddresses[def.ID]; ok && cli != "" { + endpoint = cli + } + if endpoint != "" { for _, key := range def.ObservationKeys { obsCtx.SetProviderOverride(key, checkerPkg.NewHTTPObservationProvider(key, endpoint)) } diff --git a/model/config.go b/model/config.go index a22e788e..8bae67e6 100644 --- a/model/config.go +++ b/model/config.go @@ -134,6 +134,12 @@ type Options struct { // PluginsDirectories lists filesystem paths scanned at startup for // checker plugins (.so files). PluginsDirectories []string + + // CheckerRemoteAddresses maps a checker ID to the URL of a remote HTTP + // service that should run that checker's observation collection. When + // set for a given checker, this CLI/config value takes precedence over + // any per-checker "endpoint" AdminOpt. + CheckerRemoteAddresses map[string]string } // GetBaseURL returns the full url to the absolute ExternalURL, including BaseURL. From fdf9d88383d0cbd383a28113e197550b38110cba Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 22 Apr 2026 15:45:41 +0700 Subject: [PATCH 3/6] Add TLS checker --- checkers/tls.go | 34 ++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ 3 files changed, 37 insertions(+) create mode 100644 checkers/tls.go diff --git a/checkers/tls.go b/checkers/tls.go new file mode 100644 index 00000000..f7c8e8ea --- /dev/null +++ b/checkers/tls.go @@ -0,0 +1,34 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2026 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package checkers + +import ( + sdk "git.happydns.org/checker-sdk-go/checker" + tls "git.happydns.org/checker-tls/checker" + "git.happydns.org/happyDomain/internal/checker" +) + +func init() { + prvd := tls.Provider() + checker.RegisterObservationProvider(prvd) + checker.RegisterExternalizableChecker(prvd.(sdk.CheckerDefinitionProvider).Definition()) +} diff --git a/go.mod b/go.mod index 2b9e6a9b..62554ca4 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( git.happydns.org/checker-ns-restrictions v0.1.0 git.happydns.org/checker-ping v0.1.0 git.happydns.org/checker-sdk-go v1.5.0 + git.happydns.org/checker-tls v0.6.2 git.happydns.org/checker-zonemaster v0.1.0 github.com/JGLTechnologies/gin-rate-limit v1.5.8 github.com/StackExchange/dnscontrol/v4 v4.34.0 diff --git a/go.sum b/go.sum index cd1d00db..930d6c9a 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ git.happydns.org/checker-ping v0.1.0 h1:Cu9Upvs/WoAWHi0A/1QahmuqB4/99n/jK29W/Bnv git.happydns.org/checker-ping v0.1.0/go.mod h1:P0xv85b2MoVud7UXbfoS0n3qMlyQGfg+uz1knN+7Q7w= git.happydns.org/checker-sdk-go v1.5.0 h1:5uD5Cm6xJ+lwnhbJ09iCXGHbYS9zRh+Yh0NeBHkAPBY= git.happydns.org/checker-sdk-go v1.5.0/go.mod h1:aNAcfYFfbhvH9kJhE0Njp5GX0dQbxdRB0rJ0KvSC5nI= +git.happydns.org/checker-tls v0.6.2 h1:8oKia1XlD+tklyqrwzmUgFH1Kw8VLSLLF9suZ7Qr14E= +git.happydns.org/checker-tls v0.6.2/go.mod h1:9tpnxg0iOwS+7If64DRG1jqYonUAgxOBuxwfF5mVkL4= git.happydns.org/checker-zonemaster v0.1.0 h1:1Qa0HtAGTfNU/3XvHhxDNJR9Td8DLQa8PrcNbexoeyI= git.happydns.org/checker-zonemaster v0.1.0/go.mod h1:HnVHYW3EZWy03Z0g1KMLUT9XJbIzmgoFBfid/jpe6kA= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28= From a867ff92e93be6a2e1e113a69f9c5faa31a61ff2 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Apr 2026 12:05:05 +0700 Subject: [PATCH 4/6] api: New route to retrieve current TLS certificate chain --- internal/api/controller/certificate.go | 138 +++++++++++++++++++++++++ internal/api/route/domain.go | 3 + 2 files changed, 141 insertions(+) create mode 100644 internal/api/controller/certificate.go diff --git a/internal/api/controller/certificate.go b/internal/api/controller/certificate.go new file mode 100644 index 00000000..9befcfb7 --- /dev/null +++ b/internal/api/controller/certificate.go @@ -0,0 +1,138 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2026 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Package controller exposes the "fetch certificate" endpoint used by the +// TLSA editor to prefill Certificate hashes from a live TLS endpoint. +// +// Scoped to the domain the user owns (DomainHandler middleware + suffix +// check) so it cannot be repurposed as an arbitrary TLS-probing proxy. +package controller + +import ( + "fmt" + "net" + "net/http" + "strconv" + "strings" + "time" + + "github.com/gin-gonic/gin" + + tls "git.happydns.org/checker-tls/checker" + "git.happydns.org/happyDomain/internal/api/middleware" + "git.happydns.org/happyDomain/model" +) + +const fetchCertificateTimeout = 10 * time.Second + +type CertificateController struct{} + +func NewCertificateController() *CertificateController { + return &CertificateController{} +} + +// fetchCertificateRequest is the editor's selection. Host is the owner +// subdomain (without "_port._proto"); STARTTLS is optional and when empty +// we auto-map a handful of common ports. +type fetchCertificateRequest struct { + Host string `json:"host" binding:"required"` + Port uint16 `json:"port" binding:"required"` + Proto string `json:"proto"` + STARTTLS string `json:"starttls"` +} + +// fetchCertificateResponse carries the full chain (leaf first) so the editor +// can offer DANE-EE and DANE-TA hashes side by side. +type fetchCertificateResponse struct { + Endpoint string `json:"endpoint"` + Chain []tls.CertInfo `json:"chain"` +} + +// FetchCertificate dials the requested endpoint and returns DANE-friendly +// pre-hashed views of the server's certificate chain. +// +// @Summary Fetch a live certificate for a subdomain +// @Tags domains +// @Accept json +// @Produce json +// @Param domain path string true "Domain identifier" +// @Param body body fetchCertificateRequest true "Endpoint to probe" +// @Success 200 {object} fetchCertificateResponse +// @Failure 400 {object} happydns.ErrorResponse "Invalid input" +// @Failure 403 {object} happydns.ErrorResponse "Host not under this domain" +// @Failure 502 {object} happydns.ErrorResponse "Upstream TLS error" +// @Router /domains/{domain}/fetch-certificate [post] +func (cc *CertificateController) FetchCertificate(c *gin.Context) { + var req fetchCertificateRequest + if err := c.ShouldBindJSON(&req); err != nil { + middleware.ErrorResponse(c, http.StatusBadRequest, err) + return + } + if req.Port == 0 { + middleware.ErrorResponse(c, http.StatusBadRequest, fmt.Errorf("port is required")) + return + } + proto := strings.ToLower(strings.TrimSpace(req.Proto)) + if proto == "" { + proto = "tcp" + } + if proto != "tcp" && proto != "udp" { + middleware.ErrorResponse(c, http.StatusBadRequest, fmt.Errorf("unsupported proto %q", req.Proto)) + return + } + + // Authorization: the authenticated domain must be a suffix of Host. We + // trust c.Get("domain") (set by DomainHandler), not the client-supplied + // Host, so the endpoint can't double as an arbitrary TLS-probing proxy. + domVal, ok := c.Get("domain") + if !ok { + middleware.ErrorResponse(c, http.StatusForbidden, fmt.Errorf("domain context missing")) + return + } + dom, ok := domVal.(*happydns.Domain) + if !ok { + middleware.ErrorResponse(c, http.StatusInternalServerError, fmt.Errorf("unexpected domain context type")) + return + } + host := strings.TrimSpace(req.Host) + if !strings.HasSuffix(host, dom.DomainName) { + middleware.ErrorResponse(c, http.StatusForbidden, fmt.Errorf("host %q is not under %q", host, dom.DomainName)) + return + } + + host = strings.TrimSuffix(host, ".") + + starttls := req.STARTTLS + if starttls == "" { + starttls = tls.AutoSTARTTLS(req.Port) + } + + chain, err := tls.FetchChain(c.Request.Context(), host, req.Port, starttls, fetchCertificateTimeout) + if err != nil { + middleware.ErrorResponse(c, http.StatusBadGateway, err) + return + } + + c.JSON(http.StatusOK, fetchCertificateResponse{ + Endpoint: net.JoinHostPort(host, strconv.FormatUint(uint64(req.Port), 10)), + Chain: tls.BuildChain(chain), + }) +} diff --git a/internal/api/route/domain.go b/internal/api/route/domain.go index 90e44736..c5586f27 100644 --- a/internal/api/route/domain.go +++ b/internal/api/route/domain.go @@ -67,6 +67,9 @@ func DeclareDomainRoutes( apiDomainsRoutes.POST("/zone", dc.ImportZone) apiDomainsRoutes.POST("/retrieve_zone", dc.RetrieveZone) + certCtrl := controller.NewCertificateController() + apiDomainsRoutes.POST("/fetch-certificate", certCtrl.FetchCertificate) + // Mount domain-scoped checker routes. if cc != nil { DeclareScopedCheckerRoutes(apiDomainsRoutes, cc) From bebb58beaf0764e39bf067939e766f313cb6524b Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Apr 2026 12:05:29 +0700 Subject: [PATCH 5/6] web: revamp TLSA editor. Able to import certificate and fetch through API current chain to auto-fill --- .../services/editors/svcs.TLSAs.svelte | 462 ++++++++++++++---- 1 file changed, 376 insertions(+), 86 deletions(-) diff --git a/web/src/lib/components/services/editors/svcs.TLSAs.svelte b/web/src/lib/components/services/editors/svcs.TLSAs.svelte index 6a80cbce..fee10bf4 100644 --- a/web/src/lib/components/services/editors/svcs.TLSAs.svelte +++ b/web/src/lib/components/services/editors/svcs.TLSAs.svelte @@ -22,9 +22,6 @@ --> -
- - - - - - {#snippet header(field: string)} - {#if field == "Usage"} - Certificate Usage - {:else if field == "Selector"} - Selector - {:else if field == "MatchingType"} - Matching Type - {:else if field == "Certificate"} - Certificate - {/if} - {/snippet} - {#snippet field(idx: number, field: string)} - {@const tlsaArray = (value["tlsa"] as any) as dnsRR[]} - {#if tlsaArray && tlsaArray[idx]} - +
+
+ + - {/if} - {/snippet} - +
+
+ + +
+
+ TLSA owner: {fullDn}.{dn || origin.domain} +
+
+ + {#if errorMsg} + + {/if} + + {#each records() as rec, i} +
+ Record #{i + 1} + +
+ + +
+ +
+
+ + + {USAGE.find((x) => x.v === rec.Usage)?.hint || ""} +
+
+ + + {SELECTOR.find((x) => x.v === rec.Selector)?.hint || ""} +
+
+ + + {MATCHING.find((x) => x.v === rec.MatchingType)?.hint || ""} +
+
+ +
+ + +
+ + {#if !readonly} +
+ + + +
+ {/if} +
+ {/each} + + {#if !readonly} + + {/if}
From 3d3819d3f975255e1c640557b81340958f4581ab Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Apr 2026 12:22:29 +0700 Subject: [PATCH 6/6] Add TLSA checker --- checkers/dane.go | 34 ++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ 3 files changed, 37 insertions(+) create mode 100644 checkers/dane.go diff --git a/checkers/dane.go b/checkers/dane.go new file mode 100644 index 00000000..b79514ef --- /dev/null +++ b/checkers/dane.go @@ -0,0 +1,34 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2026 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package checkers + +import ( + dane "git.happydns.org/checker-dane/checker" + sdk "git.happydns.org/checker-sdk-go/checker" + "git.happydns.org/happyDomain/internal/checker" +) + +func init() { + prvd := dane.Provider() + checker.RegisterObservationProvider(prvd) + checker.RegisterExternalizableChecker(prvd.(sdk.CheckerDefinitionProvider).Definition()) +} diff --git a/go.mod b/go.mod index 62554ca4..c02e42b3 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.25.0 toolchain go1.26.2 require ( + git.happydns.org/checker-dane v0.1.3 git.happydns.org/checker-matrix v0.1.0 git.happydns.org/checker-ns-restrictions v0.1.0 git.happydns.org/checker-ping v0.1.0 diff --git a/go.sum b/go.sum index 930d6c9a..baff280e 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCB codeberg.org/miekg/dns v0.6.73 h1:4aRD1k1THw49vpe1d+W3KO16adAGN8Raxdi0WGvvbrY= codeberg.org/miekg/dns v0.6.73/go.mod h1:58Y3ZTg6Z5ZEm/ZAAwHehbZfrD4u5mE4RByHoPEMyKk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +git.happydns.org/checker-dane v0.1.3 h1:9VpQ4FrWJE/O6MZ08FCk1vmHsr3u5V7478als9Y4jl8= +git.happydns.org/checker-dane v0.1.3/go.mod h1:md5SQA8M1QGq9MoXe3QVV+m55I+r8lU4iYx5KzvkbII= git.happydns.org/checker-matrix v0.1.0 h1:GGNIkJBlqvGtP42wbvyCr+vWQyZXYqNOQVRgFjsOzF0= git.happydns.org/checker-matrix v0.1.0/go.mod h1:L0MxEEyuLFrR3aWBW54wHQ1EvVIx4zx9IZmuh8HUHOA= git.happydns.org/checker-ns-restrictions v0.1.0 h1:SfIst5rHmviH9YGfUH3R108iZpeHk53f3C1j6YNDmPA=