diff --git a/pkg/certmanager/acme.go b/pkg/certmanager/acme.go index c46486651..d284ea837 100644 --- a/pkg/certmanager/acme.go +++ b/pkg/certmanager/acme.go @@ -25,11 +25,11 @@ import ( "fmt" "time" + "go.gearno.de/kit/httpclient" + "go.gearno.de/kit/log" "go.probo.inc/probo/pkg/crypto/keys" "go.probo.inc/probo/pkg/crypto/pem" "go.probo.inc/probo/pkg/version" - "go.gearno.de/kit/httpclient" - "go.gearno.de/kit/log" "golang.org/x/crypto/acme" ) diff --git a/pkg/certmanager/acme_challenge_handler.go b/pkg/certmanager/acme_challenge_handler.go index 05a346641..2fa2447ac 100644 --- a/pkg/certmanager/acme_challenge_handler.go +++ b/pkg/certmanager/acme_challenge_handler.go @@ -19,10 +19,10 @@ import ( "net/http" "strings" - "go.probo.inc/probo/pkg/coredata" - "go.probo.inc/probo/pkg/crypto/cipher" "go.gearno.de/kit/log" "go.gearno.de/kit/pg" + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/crypto/cipher" ) type ACMEChallengeHandler struct { diff --git a/pkg/certmanager/cache_store.go b/pkg/certmanager/cache_store.go index ee8a0fb5f..642b7e176 100644 --- a/pkg/certmanager/cache_store.go +++ b/pkg/certmanager/cache_store.go @@ -19,10 +19,10 @@ import ( "fmt" "time" - "go.probo.inc/probo/pkg/coredata" - "go.probo.inc/probo/pkg/crypto/cipher" "go.gearno.de/kit/log" "go.gearno.de/kit/pg" + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/crypto/cipher" ) type ( diff --git a/pkg/certmanager/provisioner.go b/pkg/certmanager/provisioner.go index 4998efa77..8e4ded3cf 100644 --- a/pkg/certmanager/provisioner.go +++ b/pkg/certmanager/provisioner.go @@ -20,10 +20,10 @@ import ( "strings" "time" - "go.probo.inc/probo/pkg/coredata" - "go.probo.inc/probo/pkg/crypto/cipher" "go.gearno.de/kit/log" "go.gearno.de/kit/pg" + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/crypto/cipher" ) type ( @@ -31,6 +31,7 @@ type ( pg *pg.Client acmeService *ACMEService encryptionKey cipher.EncryptionKey + cnameTarget string interval time.Duration logger *log.Logger } @@ -40,6 +41,7 @@ func NewProvisioner( pg *pg.Client, acmeService *ACMEService, encryptionKey cipher.EncryptionKey, + cnameTarget string, interval time.Duration, logger *log.Logger, ) *Provisioner { @@ -47,6 +49,7 @@ func NewProvisioner( pg: pg, acmeService: acmeService, encryptionKey: encryptionKey, + cnameTarget: cnameTarget, interval: interval, logger: logger.Named("certmanager.provisioner"), } @@ -75,6 +78,28 @@ func (p *Provisioner) Run(ctx context.Context) error { } } +func (p *Provisioner) checkDNSConfiguration(domain string) error { + if p.cnameTarget == "" { + return nil + } + cnameRecords, err := net.LookupCNAME(domain) + if err != nil { + return fmt.Errorf("DNS lookup Failed: %w", err) + } + expectedTarget := strings.TrimSuffix(p.cnameTarget, ".") + actualTarget := strings.TrimSuffix(cnameRecords, ".") + + if !strings.EqualFold(actualTarget, expectedTarget) { + return fmt.Errorf( + "DNS configuration mismatch: domain %q resolves to %q, expected %q", + domain, + actualTarget, + expectedTarget, + ) + } + return nil +} + func (p *Provisioner) checkPendingDomains(ctx context.Context) error { return p.pg.WithConn( ctx, @@ -208,7 +233,17 @@ func (p *Provisioner) provisionDomainCertificate( domain *coredata.CustomDomain, ) error { if domain.SSLStatus == coredata.CustomDomainSSLStatusPending { - p.logger.InfoCtx(ctx, "initiating HTTP challenge for domain", log.String("domain", domain.Domain)) + if err := p.checkDNSConfiguration(domain.Domain); err != nil { + p.logger.WarnCtx( + ctx, + "DNS configuration check failed, skipping ACME challenge", + log.String("domain", domain.Domain), + log.Error(err), + ) + return fmt.Errorf("DNS configuration not ready: %w", err) + } + + p.logger.InfoCtx(ctx, "DNS configuration verified, initiating HTTP challenge for domain", log.String("domain", domain.Domain)) challenge, err := p.acmeService.GetHTTPChallenge(ctx, domain.Domain) if err != nil { diff --git a/pkg/certmanager/renewer.go b/pkg/certmanager/renewer.go index 4c673571a..ba6573130 100644 --- a/pkg/certmanager/renewer.go +++ b/pkg/certmanager/renewer.go @@ -20,10 +20,10 @@ import ( "fmt" "time" - "go.probo.inc/probo/pkg/coredata" - "go.probo.inc/probo/pkg/crypto/cipher" "go.gearno.de/kit/log" "go.gearno.de/kit/pg" + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/crypto/cipher" ) type ( diff --git a/pkg/certmanager/selector.go b/pkg/certmanager/selector.go index cc28e2d88..a0a90f46c 100644 --- a/pkg/certmanager/selector.go +++ b/pkg/certmanager/selector.go @@ -21,9 +21,9 @@ import ( "sync" "time" + "go.gearno.de/kit/pg" "go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/crypto/cipher" - "go.gearno.de/kit/pg" ) type ( diff --git a/pkg/probod/probod.go b/pkg/probod/probod.go index dcec261ba..16814d3a5 100644 --- a/pkg/probod/probod.go +++ b/pkg/probod/probod.go @@ -634,7 +634,7 @@ func (impl *Implm) runTrustCenterServer( if certProvisioningInterval == 0 { certProvisioningInterval = 30 * time.Second } - certProvisioner := certmanager.NewProvisioner(pgClient, acmeService, impl.cfg.EncryptionKey, certProvisioningInterval, l) + certProvisioner := certmanager.NewProvisioner(pgClient, acmeService, impl.cfg.EncryptionKey, impl.cfg.CustomDomains.CnameTarget, certProvisioningInterval, l) g, ctx := errgroup.WithContext(ctx)