From 7095aa66a21a057f73dc3880a6ad7fd5dd4a2f33 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Sun, 4 Dec 2022 16:11:27 +0100 Subject: [PATCH] fix: return an error when extracting record name (#1778) --- providers/dns/allinkl/allinkl.go | 6 ++-- providers/dns/azure/azure.go | 7 ----- providers/dns/azure/private.go | 18 +++++++---- providers/dns/azure/public.go | 18 +++++++---- providers/dns/cloudns/internal/client.go | 26 ++++++++++------ providers/dns/cloudns/internal/client_test.go | 16 +++++----- providers/dns/cloudxns/internal/client.go | 8 +++-- providers/dns/domeneshop/domeneshop.go | 9 +++--- providers/dns/dynu/dynu.go | 9 ++++-- providers/dns/epik/epik.go | 15 ++++++++-- providers/dns/freemyip/freemyip.go | 15 ++++++---- providers/dns/hosttech/hosttech.go | 8 +++-- providers/dns/joker/provider_dmapi.go | 25 ++++++++-------- providers/dns/joker/provider_svc.go | 14 ++++++--- providers/dns/liara/liara.go | 8 +++-- providers/dns/linode/linode.go | 10 +++++-- providers/dns/loopia/loopia.go | 30 ++++++++++++------- providers/dns/loopia/loopia_test.go | 3 +- providers/dns/ns1/ns1.go | 3 +- providers/dns/porkbun/porkbun.go | 8 +++-- providers/dns/regru/regru.go | 13 ++++++-- providers/dns/simply/simply.go | 6 ++-- providers/dns/transip/transip.go | 19 +++++++----- providers/dns/variomedia/variomedia.go | 7 ++++- providers/dns/vegadns/vegadns.go | 3 +- providers/dns/vinyldns/vinyldns.go | 8 +++-- providers/dns/wedos/wedos.go | 11 +++++-- 27 files changed, 207 insertions(+), 116 deletions(-) diff --git a/providers/dns/allinkl/allinkl.go b/providers/dns/allinkl/allinkl.go index 4675b6e6..655ce150 100644 --- a/providers/dns/allinkl/allinkl.go +++ b/providers/dns/allinkl/allinkl.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "strings" "sync" "time" @@ -114,7 +113,10 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("allinkl: %w", err) } - subDomain := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("allinkl: %w", err) + } record := internal.DNSRequest{ ZoneHost: authZone, diff --git a/providers/dns/azure/azure.go b/providers/dns/azure/azure.go index 33c862a2..8ace21fb 100644 --- a/providers/dns/azure/azure.go +++ b/providers/dns/azure/azure.go @@ -7,14 +7,12 @@ import ( "fmt" "io" "net/http" - "strings" "time" "github.com/Azure/go-autorest/autorest" aazure "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/azure/auth" "github.com/go-acme/lego/v4/challenge" - "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" ) @@ -179,11 +177,6 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return d.provider.CleanUp(domain, token, keyAuth) } -// Returns the relative record to the domain. -func toRelativeRecord(domain, zone string) string { - return dns01.UnFqdn(strings.TrimSuffix(domain, zone)) -} - func getAuthorizer(config *Config) (autorest.Authorizer, error) { if config.ClientID != "" && config.ClientSecret != "" && config.TenantID != "" { credentialsConfig := auth.ClientCredentialsConfig{ diff --git a/providers/dns/azure/private.go b/providers/dns/azure/private.go index 3da08c8a..e10412c7 100644 --- a/providers/dns/azure/private.go +++ b/providers/dns/azure/private.go @@ -39,10 +39,13 @@ func (d *dnsProviderPrivate) Present(domain, token, keyAuth string) error { rsc := privatedns.NewRecordSetsClientWithBaseURI(d.config.ResourceManagerEndpoint, d.config.SubscriptionID) rsc.Authorizer = d.authorizer - relative := toRelativeRecord(fqdn, dns01.ToFqdn(zone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("azure: %w", err) + } // Get existing record set - rset, err := rsc.Get(ctx, d.config.ResourceGroup, zone, privatedns.TXT, relative) + rset, err := rsc.Get(ctx, d.config.ResourceGroup, zone, privatedns.TXT, subDomain) if err != nil { var detailed autorest.DetailedError if !errors.As(err, &detailed) || detailed.StatusCode != http.StatusNotFound { @@ -68,14 +71,14 @@ func (d *dnsProviderPrivate) Present(domain, token, keyAuth string) error { } rec := privatedns.RecordSet{ - Name: &relative, + Name: &subDomain, RecordSetProperties: &privatedns.RecordSetProperties{ TTL: to.Int64Ptr(int64(d.config.TTL)), TxtRecords: &txtRecords, }, } - _, err = rsc.CreateOrUpdate(ctx, d.config.ResourceGroup, zone, privatedns.TXT, relative, rec, "", "") + _, err = rsc.CreateOrUpdate(ctx, d.config.ResourceGroup, zone, privatedns.TXT, subDomain, rec, "", "") if err != nil { return fmt.Errorf("azure: %w", err) } @@ -92,12 +95,15 @@ func (d *dnsProviderPrivate) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("azure: %w", err) } - relative := toRelativeRecord(fqdn, dns01.ToFqdn(zone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("azure: %w", err) + } rsc := privatedns.NewRecordSetsClientWithBaseURI(d.config.ResourceManagerEndpoint, d.config.SubscriptionID) rsc.Authorizer = d.authorizer - _, err = rsc.Delete(ctx, d.config.ResourceGroup, zone, privatedns.TXT, relative, "") + _, err = rsc.Delete(ctx, d.config.ResourceGroup, zone, privatedns.TXT, subDomain, "") if err != nil { return fmt.Errorf("azure: %w", err) } diff --git a/providers/dns/azure/public.go b/providers/dns/azure/public.go index 26a5efe8..c7bcefd1 100644 --- a/providers/dns/azure/public.go +++ b/providers/dns/azure/public.go @@ -39,10 +39,13 @@ func (d *dnsProviderPublic) Present(domain, token, keyAuth string) error { rsc := dns.NewRecordSetsClientWithBaseURI(d.config.ResourceManagerEndpoint, d.config.SubscriptionID) rsc.Authorizer = d.authorizer - relative := toRelativeRecord(fqdn, dns01.ToFqdn(zone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("azure: %w", err) + } // Get existing record set - rset, err := rsc.Get(ctx, d.config.ResourceGroup, zone, relative, dns.TXT) + rset, err := rsc.Get(ctx, d.config.ResourceGroup, zone, subDomain, dns.TXT) if err != nil { var detailed autorest.DetailedError if !errors.As(err, &detailed) || detailed.StatusCode != http.StatusNotFound { @@ -68,14 +71,14 @@ func (d *dnsProviderPublic) Present(domain, token, keyAuth string) error { } rec := dns.RecordSet{ - Name: &relative, + Name: &subDomain, RecordSetProperties: &dns.RecordSetProperties{ TTL: to.Int64Ptr(int64(d.config.TTL)), TxtRecords: &txtRecords, }, } - _, err = rsc.CreateOrUpdate(ctx, d.config.ResourceGroup, zone, relative, dns.TXT, rec, "", "") + _, err = rsc.CreateOrUpdate(ctx, d.config.ResourceGroup, zone, subDomain, dns.TXT, rec, "", "") if err != nil { return fmt.Errorf("azure: %w", err) } @@ -92,12 +95,15 @@ func (d *dnsProviderPublic) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("azure: %w", err) } - relative := toRelativeRecord(fqdn, dns01.ToFqdn(zone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("azure: %w", err) + } rsc := dns.NewRecordSetsClientWithBaseURI(d.config.ResourceManagerEndpoint, d.config.SubscriptionID) rsc.Authorizer = d.authorizer - _, err = rsc.Delete(ctx, d.config.ResourceGroup, zone, relative, dns.TXT, "") + _, err = rsc.Delete(ctx, d.config.ResourceGroup, zone, subDomain, dns.TXT, "") if err != nil { return fmt.Errorf("azure: %w", err) } diff --git a/providers/dns/cloudns/internal/client.go b/providers/dns/cloudns/internal/client.go index d5b6a60e..a63ecc84 100644 --- a/providers/dns/cloudns/internal/client.go +++ b/providers/dns/cloudns/internal/client.go @@ -9,7 +9,6 @@ import ( "net/url" "path" "strconv" - "strings" "github.com/go-acme/lego/v4/challenge/dns01" ) @@ -89,7 +88,10 @@ func (c *Client) GetZone(authFQDN string) (*Zone, error) { // FindTxtRecord returns the TXT record a zone ID and a FQDN. func (c *Client) FindTxtRecord(zoneName, fqdn string) (*TXTRecord, error) { - host := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), zoneName)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zoneName) + if err != nil { + return nil, err + } reqURL, err := c.BaseURL.Parse(path.Join(c.BaseURL.Path, "records.json")) if err != nil { @@ -98,7 +100,7 @@ func (c *Client) FindTxtRecord(zoneName, fqdn string) (*TXTRecord, error) { q := reqURL.Query() q.Set("domain-name", zoneName) - q.Set("host", host) + q.Set("host", subDomain) q.Set("type", "TXT") reqURL.RawQuery = q.Encode() @@ -118,7 +120,7 @@ func (c *Client) FindTxtRecord(zoneName, fqdn string) (*TXTRecord, error) { } for _, record := range records { - if record.Host == host && record.Type == "TXT" { + if record.Host == subDomain && record.Type == "TXT" { return &record, nil } } @@ -128,7 +130,10 @@ func (c *Client) FindTxtRecord(zoneName, fqdn string) (*TXTRecord, error) { // ListTxtRecords returns the TXT records a zone ID and a FQDN. func (c *Client) ListTxtRecords(zoneName, fqdn string) ([]TXTRecord, error) { - host := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), zoneName)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zoneName) + if err != nil { + return nil, err + } reqURL, err := c.BaseURL.Parse(path.Join(c.BaseURL.Path, "records.json")) if err != nil { @@ -137,7 +142,7 @@ func (c *Client) ListTxtRecords(zoneName, fqdn string) ([]TXTRecord, error) { q := reqURL.Query() q.Set("domain-name", zoneName) - q.Set("host", host) + q.Set("host", subDomain) q.Set("type", "TXT") reqURL.RawQuery = q.Encode() @@ -158,7 +163,7 @@ func (c *Client) ListTxtRecords(zoneName, fqdn string) ([]TXTRecord, error) { var records []TXTRecord for _, record := range raw { - if record.Host == host && record.Type == "TXT" { + if record.Host == subDomain && record.Type == "TXT" { records = append(records, record) } } @@ -168,7 +173,10 @@ func (c *Client) ListTxtRecords(zoneName, fqdn string) ([]TXTRecord, error) { // AddTxtRecord adds a TXT record. func (c *Client) AddTxtRecord(zoneName, fqdn, value string, ttl int) error { - host := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), zoneName)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zoneName) + if err != nil { + return err + } reqURL, err := c.BaseURL.Parse(path.Join(c.BaseURL.Path, "add-record.json")) if err != nil { @@ -177,7 +185,7 @@ func (c *Client) AddTxtRecord(zoneName, fqdn, value string, ttl int) error { q := reqURL.Query() q.Set("domain-name", zoneName) - q.Set("host", host) + q.Set("host", subDomain) q.Set("record", value) q.Set("ttl", strconv.Itoa(ttlRounder(ttl))) q.Set("record-type", "TXT") diff --git a/providers/dns/cloudns/internal/client_test.go b/providers/dns/cloudns/internal/client_test.go index 8a9c53b9..277063a8 100644 --- a/providers/dns/cloudns/internal/client_test.go +++ b/providers/dns/cloudns/internal/client_test.go @@ -212,14 +212,14 @@ func TestClient_FindTxtRecord(t *testing.T) { }, { desc: "zero records", - authFQDN: "_acme-challenge.foo.com.", - zoneName: "test-zone", + authFQDN: "_acme-challenge.example.com.", + zoneName: "example.com", apiResponse: `[]`, }, { desc: "invalid json response", - authFQDN: "_acme-challenge.foo.com.", - zoneName: "test-zone", + authFQDN: "_acme-challenge.example.com.", + zoneName: "example.com", apiResponse: `[{}]`, expected: expected{ errorMsg: "failed to unmarshall TXT records: json: cannot unmarshal array into Go value of type map[string]internal.TXTRecord: [{}]", @@ -327,14 +327,14 @@ func TestClient_ListTxtRecord(t *testing.T) { }, { desc: "zero records", - authFQDN: "_acme-challenge.foo.com.", - zoneName: "test-zone", + authFQDN: "_acme-challenge.example.com.", + zoneName: "example.com", apiResponse: `[]`, }, { desc: "invalid json response", - authFQDN: "_acme-challenge.foo.com.", - zoneName: "test-zone", + authFQDN: "_acme-challenge.example.com.", + zoneName: "example.com", apiResponse: `[{}]`, expected: expected{ errorMsg: "failed to unmarshall TXT records: json: cannot unmarshal array into Go value of type map[string]internal.TXTRecord: [{}]", diff --git a/providers/dns/cloudxns/internal/client.go b/providers/dns/cloudxns/internal/client.go index 8a1c100c..dd151184 100644 --- a/providers/dns/cloudxns/internal/client.go +++ b/providers/dns/cloudxns/internal/client.go @@ -10,7 +10,6 @@ import ( "io" "net/http" "strconv" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -127,9 +126,14 @@ func (c *Client) AddTxtRecord(info *Data, fqdn, value string, ttl int) error { return fmt.Errorf("CloudXNS: invalid zone ID: %w", err) } + subDomain, err := dns01.ExtractSubDomain(fqdn, info.Domain) + if err != nil { + return fmt.Errorf("CloudXNS: %w", err) + } + payload := TXTRecord{ ID: id, - Host: dns01.UnFqdn(strings.TrimSuffix(fqdn, info.Domain)), + Host: subDomain, Value: value, Type: "TXT", LineID: 1, diff --git a/providers/dns/domeneshop/domeneshop.go b/providers/dns/domeneshop/domeneshop.go index d7c4b309..f5bf9b81 100644 --- a/providers/dns/domeneshop/domeneshop.go +++ b/providers/dns/domeneshop/domeneshop.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -142,8 +141,10 @@ func (d *DNSProvider) splitDomain(fqdn string) (string, string, error) { return "", "", err } - host := dns01.UnFqdn(strings.TrimSuffix(fqdn, zone)) - zone = dns01.UnFqdn(zone) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return "", "", err + } - return zone, host, nil + return dns01.UnFqdn(zone), subDomain, nil } diff --git a/providers/dns/dynu/dynu.go b/providers/dns/dynu/dynu.go index 33b42aab..c2df9fb4 100644 --- a/providers/dns/dynu/dynu.go +++ b/providers/dns/dynu/dynu.go @@ -5,13 +5,11 @@ import ( "errors" "fmt" "net/http" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" "github.com/go-acme/lego/v4/providers/dns/dynu/internal" - "github.com/miekg/dns" ) // Environment variables names. @@ -117,11 +115,16 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { } } + subDomain, err := dns01.ExtractSubDomain(fqdn, domain) + if err != nil { + return fmt.Errorf("dynu: %w", err) + } + record := internal.DNSRecord{ Type: "TXT", DomainName: rootDomain.DomainName, Hostname: dns01.UnFqdn(fqdn), - NodeName: dns01.UnFqdn(strings.TrimSuffix(fqdn, dns.Fqdn(domain))), + NodeName: subDomain, TextData: value, State: true, TTL: d.config.TTL, diff --git a/providers/dns/epik/epik.go b/providers/dns/epik/epik.go index 1f906e4c..f6ad5ef2 100644 --- a/providers/dns/epik/epik.go +++ b/providers/dns/epik/epik.go @@ -101,8 +101,13 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("epik: %w", err) } + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("epik: %w", err) + } + record := internal.RecordRequest{ - Host: dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)), + Host: subDomain, Type: "TXT", Data: value, TTL: d.config.TTL, @@ -127,15 +132,19 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { } dom := dns01.UnFqdn(authZone) - host := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)) records, err := d.client.GetDNSRecords(dom) if err != nil { return fmt.Errorf("epik: %w", err) } + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("epik: %w", err) + } + for _, record := range records { - if strings.EqualFold(record.Type, "TXT") && record.Data == value && record.Name == host { + if strings.EqualFold(record.Type, "TXT") && record.Data == value && record.Name == subDomain { _, err = d.client.RemoveHostRecord(dom, record.ID) if err != nil { return fmt.Errorf("epik: %w", err) diff --git a/providers/dns/freemyip/freemyip.go b/providers/dns/freemyip/freemyip.go index 53172a37..bd723d5c 100644 --- a/providers/dns/freemyip/freemyip.go +++ b/providers/dns/freemyip/freemyip.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "net/http" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -108,9 +107,12 @@ func (d *DNSProvider) Sequential() time.Duration { func (d *DNSProvider) Present(domain, token, keyAuth string) error { fqdn, value := dns01.GetRecord(domain, keyAuth) - subDomain := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), freemyip.RootDomain)) + subDomain, err := dns01.ExtractSubDomain(fqdn, freemyip.RootDomain) + if err != nil { + return fmt.Errorf("freemyip: %w", err) + } - _, err := d.client.EditTXTRecord(context.Background(), subDomain, value) + _, err = d.client.EditTXTRecord(context.Background(), subDomain, value) if err != nil { return fmt.Errorf("freemyip: %w", err) } @@ -122,9 +124,12 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { fqdn, _ := dns01.GetRecord(domain, keyAuth) - subDomain := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), freemyip.RootDomain)) + subDomain, err := dns01.ExtractSubDomain(fqdn, freemyip.RootDomain) + if err != nil { + return fmt.Errorf("freemyip: %w", err) + } - _, err := d.client.DeleteTXTRecord(context.Background(), subDomain) + _, err = d.client.DeleteTXTRecord(context.Background(), subDomain) if err != nil { return fmt.Errorf("freemyip: %w", err) } diff --git a/providers/dns/hosttech/hosttech.go b/providers/dns/hosttech/hosttech.go index 0920a6b0..aa054d22 100644 --- a/providers/dns/hosttech/hosttech.go +++ b/providers/dns/hosttech/hosttech.go @@ -6,7 +6,6 @@ import ( "fmt" "net/http" "strconv" - "strings" "sync" "time" @@ -114,9 +113,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("hosttech: could not find zone for domain %q (%s): %w", domain, authZone, err) } + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("hosttech: %w", err) + } + record := internal.Record{ Type: "TXT", - Name: dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)), + Name: subDomain, Text: value, TTL: d.config.TTL, } diff --git a/providers/dns/joker/provider_dmapi.go b/providers/dns/joker/provider_dmapi.go index f0cb3185..8b579bd8 100644 --- a/providers/dns/joker/provider_dmapi.go +++ b/providers/dns/joker/provider_dmapi.go @@ -3,7 +3,6 @@ package joker import ( "errors" "fmt" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -81,10 +80,13 @@ func (d *dmapiProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("joker: %w", err) } - relative := getRelative(fqdn, zone) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("joker: %w", err) + } if d.config.Debug { - log.Infof("[%s] joker: adding TXT record %q to zone %q with value %q", domain, relative, zone, value) + log.Infof("[%s] joker: adding TXT record %q to zone %q with value %q", domain, subDomain, zone, value) } response, err := d.client.Login() @@ -97,7 +99,7 @@ func (d *dmapiProvider) Present(domain, token, keyAuth string) error { return formatResponseError(response, err) } - dnsZone := dmapi.AddTxtEntryToZone(response.Body, relative, value, d.config.TTL) + dnsZone := dmapi.AddTxtEntryToZone(response.Body, subDomain, value, d.config.TTL) response, err = d.client.PutZone(zone, dnsZone) if err != nil || response.StatusCode != 0 { @@ -116,10 +118,13 @@ func (d *dmapiProvider) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("joker: %w", err) } - relative := getRelative(fqdn, zone) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("joker: %w", err) + } if d.config.Debug { - log.Infof("[%s] joker: removing entry %q from zone %q", domain, relative, zone) + log.Infof("[%s] joker: removing entry %q from zone %q", domain, subDomain, zone) } response, err := d.client.Login() @@ -128,7 +133,7 @@ func (d *dmapiProvider) CleanUp(domain, token, keyAuth string) error { } defer func() { - // Try to logout in case of errors + // Try to log out in case of errors _, _ = d.client.Logout() }() @@ -137,7 +142,7 @@ func (d *dmapiProvider) CleanUp(domain, token, keyAuth string) error { return formatResponseError(response, err) } - dnsZone, modified := dmapi.RemoveTxtEntryFromZone(response.Body, relative) + dnsZone, modified := dmapi.RemoveTxtEntryFromZone(response.Body, subDomain) if modified { response, err = d.client.PutZone(zone, dnsZone) if err != nil || response.StatusCode != 0 { @@ -152,10 +157,6 @@ func (d *dmapiProvider) CleanUp(domain, token, keyAuth string) error { return nil } -func getRelative(fqdn, zone string) string { - return dns01.UnFqdn(strings.TrimSuffix(fqdn, dns01.ToFqdn(zone))) -} - // formatResponseError formats error with optional details from DMAPI response. func formatResponseError(response *dmapi.Response, err error) error { if response != nil { diff --git a/providers/dns/joker/provider_svc.go b/providers/dns/joker/provider_svc.go index 781f1e2c..1e2046cf 100644 --- a/providers/dns/joker/provider_svc.go +++ b/providers/dns/joker/provider_svc.go @@ -61,9 +61,12 @@ func (d *svcProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("joker: %w", err) } - relative := getRelative(fqdn, zone) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("joker: %w", err) + } - return d.client.Send(dns01.UnFqdn(zone), relative, value) + return d.client.Send(dns01.UnFqdn(zone), subDomain, value) } // CleanUp removes the TXT record matching the specified parameters. @@ -75,9 +78,12 @@ func (d *svcProvider) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("joker: %w", err) } - relative := getRelative(fqdn, zone) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return fmt.Errorf("joker: %w", err) + } - return d.client.Send(dns01.UnFqdn(zone), relative, "") + return d.client.Send(dns01.UnFqdn(zone), subDomain, "") } // Sequential All DNS challenges for this provider will be resolved sequentially. diff --git a/providers/dns/liara/liara.go b/providers/dns/liara/liara.go index 2c9db3c3..a72fe0fe 100644 --- a/providers/dns/liara/liara.go +++ b/providers/dns/liara/liara.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "strings" "sync" "time" @@ -128,9 +127,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("liara: %w", err) } + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("liara: %w", err) + } + record := internal.Record{ Type: "TXT", - Name: dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)), + Name: subDomain, Contents: []internal.Content{{Text: value}}, TTL: d.config.TTL, } diff --git a/providers/dns/linode/linode.go b/providers/dns/linode/linode.go index b18476a5..c90bb848 100644 --- a/providers/dns/linode/linode.go +++ b/providers/dns/linode/linode.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "net/http" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -167,7 +166,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { // Remove the specified resource, if it exists. for _, resource := range resources { - if (resource.Name == strings.TrimSuffix(fqdn, ".") || resource.Name == zone.resourceName) && + if (resource.Name == dns01.UnFqdn(fqdn) || resource.Name == zone.resourceName) && resource.Target == value { if err := d.client.DeleteDomainRecord(context.Background(), zone.domainID, resource.ID); err != nil { return err @@ -201,8 +200,13 @@ func (d *DNSProvider) getHostedZoneInfo(fqdn string) (*hostedZoneInfo, error) { return nil, errors.New("domain not found") } + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return nil, err + } + return &hostedZoneInfo{ domainID: domains[0].ID, - resourceName: strings.TrimSuffix(fqdn, "."+authZone), + resourceName: subDomain, }, nil } diff --git a/providers/dns/loopia/loopia.go b/providers/dns/loopia/loopia.go index 446ce228..331273ab 100644 --- a/providers/dns/loopia/loopia.go +++ b/providers/dns/loopia/loopia.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "strings" "sync" "time" @@ -131,14 +130,17 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { func (d *DNSProvider) Present(domain, token, keyAuth string) error { fqdn, value := dns01.GetRecord(domain, keyAuth) - subdomain, authZone := d.splitDomain(fqdn) + subDomain, authZone, err := d.splitDomain(fqdn) + if err != nil { + return fmt.Errorf("loopia: %w", err) + } - err := d.client.AddTXTRecord(authZone, subdomain, d.config.TTL, value) + err = d.client.AddTXTRecord(authZone, subDomain, d.config.TTL, value) if err != nil { return fmt.Errorf("loopia: failed to add TXT record: %w", err) } - txtRecords, err := d.client.GetTXTRecords(authZone, subdomain) + txtRecords, err := d.client.GetTXTRecords(authZone, subDomain) if err != nil { return fmt.Errorf("loopia: failed to get TXT records: %w", err) } @@ -160,17 +162,20 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { fqdn, _ := dns01.GetRecord(domain, keyAuth) - subdomain, authZone := d.splitDomain(fqdn) + subDomain, authZone, err := d.splitDomain(fqdn) + if err != nil { + return fmt.Errorf("loopia: %w", err) + } d.inProgressMu.Lock() defer d.inProgressMu.Unlock() - err := d.client.RemoveTXTRecord(authZone, subdomain, d.inProgressInfo[token]) + err = d.client.RemoveTXTRecord(authZone, subDomain, d.inProgressInfo[token]) if err != nil { return fmt.Errorf("loopia: failed to remove TXT record: %w", err) } - records, err := d.client.GetTXTRecords(authZone, subdomain) + records, err := d.client.GetTXTRecords(authZone, subDomain) if err != nil { return fmt.Errorf("loopia: failed to get TXT records: %w", err) } @@ -179,7 +184,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return nil } - err = d.client.RemoveSubdomain(authZone, subdomain) + err = d.client.RemoveSubdomain(authZone, subDomain) if err != nil { return fmt.Errorf("loopia: failed to remove sub-domain: %w", err) } @@ -187,11 +192,14 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return nil } -func (d *DNSProvider) splitDomain(fqdn string) (string, string) { +func (d *DNSProvider) splitDomain(fqdn string) (string, string, error) { authZone, _ := d.findZoneByFqdn(fqdn) authZone = dns01.UnFqdn(authZone) - subdomain := strings.TrimSuffix(dns01.UnFqdn(fqdn), "."+authZone) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return "", "", err + } - return subdomain, authZone + return subDomain, authZone, nil } diff --git a/providers/dns/loopia/loopia_test.go b/providers/dns/loopia/loopia_test.go index cacffabf..e397c963 100644 --- a/providers/dns/loopia/loopia_test.go +++ b/providers/dns/loopia/loopia_test.go @@ -55,7 +55,8 @@ func TestSplitDomain(t *testing.T) { for _, test := range testCases { t.Run(test.desc, func(t *testing.T) { - subdomain, domain := provider.splitDomain(test.fqdn) + subdomain, domain, err := provider.splitDomain(test.fqdn) + require.NoError(t, err) assert.Equal(t, test.subdomain, subdomain) assert.Equal(t, test.domain, domain) diff --git a/providers/dns/ns1/ns1.go b/providers/dns/ns1/ns1.go index 42d99565..7b6b6dea 100644 --- a/providers/dns/ns1/ns1.go +++ b/providers/dns/ns1/ns1.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -170,5 +169,5 @@ func getAuthZone(fqdn string) (string, error) { return "", err } - return strings.TrimSuffix(authZone, "."), nil + return dns01.UnFqdn(authZone), nil } diff --git a/providers/dns/porkbun/porkbun.go b/providers/dns/porkbun/porkbun.go index 1ec5e52a..d5b66eab 100644 --- a/providers/dns/porkbun/porkbun.go +++ b/providers/dns/porkbun/porkbun.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" "strconv" - "strings" "sync" "time" @@ -175,7 +174,10 @@ func splitDomain(fqdn string) (string, string, error) { return "", "", err } - host := dns01.UnFqdn(strings.TrimSuffix(fqdn, zone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return "", "", err + } - return zone, host, nil + return zone, subDomain, nil } diff --git a/providers/dns/regru/regru.go b/providers/dns/regru/regru.go index 318d3893..fd0df3a2 100644 --- a/providers/dns/regru/regru.go +++ b/providers/dns/regru/regru.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -105,7 +104,11 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("regru: could not find zone for domain %q and fqdn %q : %w", domain, fqdn, err) } - subDomain := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("regru: %w", err) + } + err = d.client.AddTXTRecord(dns01.UnFqdn(authZone), subDomain, value) if err != nil { return fmt.Errorf("regru: failed to create TXT records [domain: %s, sub domain: %s]: %w", @@ -124,7 +127,11 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("regru: could not find zone for domain %q and fqdn %q : %w", domain, fqdn, err) } - subDomain := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("regru: %w", err) + } + err = d.client.RemoveTxtRecord(dns01.UnFqdn(authZone), subDomain, value) if err != nil { return fmt.Errorf("regru: failed to remove TXT records [domain: %s, sub domain: %s]: %w", diff --git a/providers/dns/simply/simply.go b/providers/dns/simply/simply.go index 0daddf45..a90c1af7 100644 --- a/providers/dns/simply/simply.go +++ b/providers/dns/simply/simply.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "strings" "sync" "time" @@ -119,7 +118,10 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { } authZone = dns01.UnFqdn(authZone) - subDomain := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("regru: %w", err) + } recordBody := internal.Record{ Name: subDomain, diff --git a/providers/dns/transip/transip.go b/providers/dns/transip/transip.go index 99a35045..95b21e30 100644 --- a/providers/dns/transip/transip.go +++ b/providers/dns/transip/transip.go @@ -4,7 +4,6 @@ package transip import ( "errors" "fmt" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -99,10 +98,13 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return err } - domainName := dns01.UnFqdn(authZone) - // get the subDomain - subDomain := strings.TrimSuffix(dns01.UnFqdn(fqdn), "."+domainName) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("transip: %w", err) + } + + domainName := dns01.UnFqdn(authZone) entry := transipdomain.DNSEntry{ Name: subDomain, @@ -128,10 +130,13 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return err } - domainName := dns01.UnFqdn(authZone) - // get the subDomain - subDomain := strings.TrimSuffix(dns01.UnFqdn(fqdn), "."+domainName) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("transip: %w", err) + } + + domainName := dns01.UnFqdn(authZone) // get all DNS entries dnsEntries, err := d.repository.GetDNSEntries(domainName) diff --git a/providers/dns/variomedia/variomedia.go b/providers/dns/variomedia/variomedia.go index 7c1937af..0d95ca75 100644 --- a/providers/dns/variomedia/variomedia.go +++ b/providers/dns/variomedia/variomedia.go @@ -121,9 +121,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("variomedia: %w", err) } + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("variomedia: %w", err) + } + record := internal.DNSRecord{ RecordType: "TXT", - Name: dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)), + Name: subDomain, Domain: dns01.UnFqdn(authZone), Data: value, TTL: d.config.TTL, diff --git a/providers/dns/vegadns/vegadns.go b/providers/dns/vegadns/vegadns.go index 9b91f115..4678a5ae 100644 --- a/providers/dns/vegadns/vegadns.go +++ b/providers/dns/vegadns/vegadns.go @@ -4,7 +4,6 @@ package vegadns import ( "errors" "fmt" - "strings" "time" vegaClient "github.com/OpenDNS/vegadns2client" @@ -111,7 +110,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("vegadns: can't find Authoritative Zone for %s in CleanUp: %w", fqdn, err) } - txt := strings.TrimSuffix(fqdn, ".") + txt := dns01.UnFqdn(fqdn) recordID, err := d.client.GetRecordID(domainID, txt, "TXT") if err != nil { diff --git a/providers/dns/vinyldns/vinyldns.go b/providers/dns/vinyldns/vinyldns.go index 9b4be610..86b66d0a 100644 --- a/providers/dns/vinyldns/vinyldns.go +++ b/providers/dns/vinyldns/vinyldns.go @@ -4,7 +4,6 @@ package vinyldns import ( "errors" "fmt" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -285,7 +284,10 @@ func splitDomain(fqdn string) (string, string, error) { return "", "", err } - host := dns01.UnFqdn(strings.TrimSuffix(fqdn, zone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, zone) + if err != nil { + return "", "", err + } - return zone, host, nil + return zone, subDomain, nil } diff --git a/providers/dns/wedos/wedos.go b/providers/dns/wedos/wedos.go index 250a3384..3e0a0f5a 100644 --- a/providers/dns/wedos/wedos.go +++ b/providers/dns/wedos/wedos.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" "strconv" - "strings" "time" "github.com/go-acme/lego/v4/challenge/dns01" @@ -112,7 +111,10 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("wedos: could not determine zone for domain %q: %w", domain, err) } - subDomain := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("wedos: %w", err) + } record := internal.DNSRow{ Name: subDomain, @@ -157,7 +159,10 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("wedos: could not determine zone for domain %q: %w", domain, err) } - subDomain := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone)) + subDomain, err := dns01.ExtractSubDomain(fqdn, authZone) + if err != nil { + return fmt.Errorf("wedos: %w", err) + } records, err := d.client.GetRecords(ctx, authZone) if err != nil {