Fix go/cgo dns resolver behaviour
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
1
go.mod
1
go.mod
@@ -3,6 +3,7 @@ module go.probo.inc/probo
|
|||||||
go 1.25.5
|
go 1.25.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
codeberg.org/miekg/dns v0.6.2
|
||||||
github.com/99designs/gqlgen v0.17.83
|
github.com/99designs/gqlgen v0.17.83
|
||||||
github.com/aws/aws-sdk-go-v2 v1.40.0
|
github.com/aws/aws-sdk-go-v2 v1.40.0
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.0
|
github.com/aws/aws-sdk-go-v2/credentials v1.19.0
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -1,3 +1,5 @@
|
|||||||
|
codeberg.org/miekg/dns v0.6.2 h1:gkuKad3tKCs4On/3ZlydASeXPc1uQaZNuDSxEXR7Mt0=
|
||||||
|
codeberg.org/miekg/dns v0.6.2/go.mod h1:IKSpRNHVdUyxHC457VnDQ9Dv05UhXXsALZAywCM7D54=
|
||||||
github.com/99designs/gqlgen v0.17.83 h1:LZOd4Of2snK5V22/ZWfBAPa3WoAZkBO70dKXM0ODHQk=
|
github.com/99designs/gqlgen v0.17.83 h1:LZOd4Of2snK5V22/ZWfBAPa3WoAZkBO70dKXM0ODHQk=
|
||||||
github.com/99designs/gqlgen v0.17.83/go.mod h1:q6Lb64wknFqNFSbSUGzKRKupklvY/xgNr62g0GGWPB8=
|
github.com/99designs/gqlgen v0.17.83/go.mod h1:q6Lb64wknFqNFSbSUGzKRKupklvY/xgNr62g0GGWPB8=
|
||||||
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
|
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -29,6 +28,8 @@ import (
|
|||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/crypto/cipher"
|
"go.probo.inc/probo/pkg/crypto/cipher"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
|
|
||||||
|
"codeberg.org/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -38,6 +39,7 @@ type (
|
|||||||
encryptionKey cipher.EncryptionKey
|
encryptionKey cipher.EncryptionKey
|
||||||
cnameTarget string
|
cnameTarget string
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
|
resolverAddr string
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -52,6 +54,7 @@ func NewProvisioner(
|
|||||||
encryptionKey cipher.EncryptionKey,
|
encryptionKey cipher.EncryptionKey,
|
||||||
cnameTarget string,
|
cnameTarget string,
|
||||||
interval time.Duration,
|
interval time.Duration,
|
||||||
|
resolverAddr string,
|
||||||
logger *log.Logger,
|
logger *log.Logger,
|
||||||
) *Provisioner {
|
) *Provisioner {
|
||||||
return &Provisioner{
|
return &Provisioner{
|
||||||
@@ -60,6 +63,7 @@ func NewProvisioner(
|
|||||||
encryptionKey: encryptionKey,
|
encryptionKey: encryptionKey,
|
||||||
cnameTarget: cnameTarget,
|
cnameTarget: cnameTarget,
|
||||||
interval: interval,
|
interval: interval,
|
||||||
|
resolverAddr: resolverAddr,
|
||||||
logger: logger.Named("certmanager.provisioner"),
|
logger: logger.Named("certmanager.provisioner"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,19 +92,45 @@ func (p *Provisioner) Run(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provisioner) checkDNSConfiguration(domain string) error {
|
func (p *Provisioner) checkDNSConfiguration(domain string) error {
|
||||||
cnameRecords, err := net.LookupCNAME(domain)
|
customerFQDN := domain
|
||||||
if err != nil {
|
if !strings.HasSuffix(customerFQDN, ".") {
|
||||||
return fmt.Errorf("cannot lookup cname for domain %q: %w", domain, err)
|
customerFQDN = customerFQDN + "."
|
||||||
}
|
}
|
||||||
expectedTarget := strings.TrimSuffix(p.cnameTarget, ".")
|
|
||||||
actualTarget := strings.TrimSuffix(cnameRecords, ".")
|
|
||||||
|
|
||||||
if !strings.EqualFold(actualTarget, expectedTarget) {
|
expectedFQDN := p.cnameTarget
|
||||||
|
if !strings.HasSuffix(expectedFQDN, ".") {
|
||||||
|
expectedFQDN = expectedFQDN + "."
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &dns.Msg{MsgHeader: dns.MsgHeader{ID: dns.ID(), RecursionDesired: true}}
|
||||||
|
msg.Question = []dns.RR{&dns.CNAME{Hdr: dns.Header{Name: customerFQDN, Class: dns.ClassINET}}}
|
||||||
|
|
||||||
|
client := dns.NewClient()
|
||||||
|
|
||||||
|
resp, _, err := client.Exchange(context.Background(), msg, "udp", p.resolverAddr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot exchange dns message: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.Answer) == 0 {
|
||||||
|
return fmt.Errorf("no cname records found for domain %q", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.Answer) > 1 {
|
||||||
|
return fmt.Errorf("multiple cname records found for domain %q", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedRecord, ok := resp.Answer[0].(*dns.CNAME)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("first answer is not a cname record for domain %q", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.EqualFold(expectedFQDN, resolvedRecord.Target) {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"cname target mismatch: domain %q resolves to %q, expected %q",
|
"cname target mismatch: domain %q resolves to %q, expected %q",
|
||||||
domain,
|
domain,
|
||||||
actualTarget,
|
resolvedRecord.Target,
|
||||||
p.cnameTarget,
|
expectedFQDN,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package probod
|
|||||||
type customDomainsConfig struct {
|
type customDomainsConfig struct {
|
||||||
RenewalInterval int `json:"renewal-interval"`
|
RenewalInterval int `json:"renewal-interval"`
|
||||||
ProvisionInterval int `json:"provision-interval"`
|
ProvisionInterval int `json:"provision-interval"`
|
||||||
|
ResolverAddr string `json:"resolver-addr"`
|
||||||
CnameTarget string `json:"cname-target"`
|
CnameTarget string `json:"cname-target"`
|
||||||
ACME acmeConfig `json:"acme"`
|
ACME acmeConfig `json:"acme"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ func New() *Implm {
|
|||||||
CustomDomains: customDomainsConfig{
|
CustomDomains: customDomainsConfig{
|
||||||
RenewalInterval: 3600,
|
RenewalInterval: 3600,
|
||||||
ProvisionInterval: 30,
|
ProvisionInterval: 30,
|
||||||
|
ResolverAddr: "8.8.8.8:53",
|
||||||
ACME: acmeConfig{
|
ACME: acmeConfig{
|
||||||
Directory: "https://acme-v02.api.letsencrypt.org/directory",
|
Directory: "https://acme-v02.api.letsencrypt.org/directory",
|
||||||
Email: "admin@getprobo.com",
|
Email: "admin@getprobo.com",
|
||||||
@@ -681,7 +682,7 @@ func (impl *Implm) runTrustCenterServer(
|
|||||||
if certProvisioningInterval == 0 {
|
if certProvisioningInterval == 0 {
|
||||||
certProvisioningInterval = 30 * time.Second
|
certProvisioningInterval = 30 * time.Second
|
||||||
}
|
}
|
||||||
certProvisioner := certmanager.NewProvisioner(pgClient, acmeService, impl.cfg.EncryptionKey, impl.cfg.CustomDomains.CnameTarget, certProvisioningInterval, l)
|
certProvisioner := certmanager.NewProvisioner(pgClient, acmeService, impl.cfg.EncryptionKey, impl.cfg.CustomDomains.CnameTarget, certProvisioningInterval, impl.cfg.CustomDomains.ResolverAddr, l)
|
||||||
|
|
||||||
g, ctx := errgroup.WithContext(ctx)
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user