diff --git a/.github/ISSUE_TEMPLATE/new_dns_provider.yml b/.github/ISSUE_TEMPLATE/new_dns_provider.yml
index b319bc287..cfd6e5c8c 100644
--- a/.github/ISSUE_TEMPLATE/new_dns_provider.yml
+++ b/.github/ISSUE_TEMPLATE/new_dns_provider.yml
@@ -14,15 +14,9 @@ body:
required: true
- label: Yes, I know that the lego maintainers don't have an account in all DNS providers in the world.
required: true
-
- - type: checkboxes
- id: pr
- attributes:
- label: Implementation
- options:
- label: Yes, I'm able to create a pull request and be able to maintain the implementation.
required: false
- - label: Yes, I can test an implementation with the help of the maintainers if someone creates a pull request.
+ - label: Yes, I'm able to test an implementation if someone creates a pull request to add the support of this DNS provider.
required: false
- type: dropdown
diff --git a/README.md b/README.md
index e90e94962..9925979bd 100644
--- a/README.md
+++ b/README.md
@@ -73,75 +73,70 @@ If your DNS provider is not supported, please open an [issue](https://github.com
| Amazon Route 53 |
Anexia CloudDNS |
- ANS SafeDNS |
ArtFiles |
-
| ArvanCloud |
+
| Aurora DNS |
Autodns |
Axelname |
-
| Azion |
+
| Azure (deprecated) |
Azure DNS |
Baidu Cloud |
-
| Beget.com |
+
| Binary Lane |
Bindman |
Bluecat |
-
| Bluecat v2 |
+
| BookMyName |
Brandit (deprecated) |
Bunny |
-
| Checkdomain |
+
| Civo |
Cloud.ru |
CloudDNS |
-
| Cloudflare |
+
| ClouDNS |
CloudXNS (Deprecated) |
ConoHa v2 |
-
| ConoHa v3 |
+
| Constellix |
Core-Networks |
CPanel/WHM |
-
- | Czechia |
DDnss (DynDNS Service) |
+
| Derak Cloud |
deSEC.io |
-
| Designate DNSaaS for Openstack |
Digital Ocean |
+
| DirectAdmin |
DNS Made Easy |
-
| DNSExit |
dnsHome.de |
+
| DNSimple |
DNSPod (deprecated) |
-
| Domain Offensive (do.de) |
Domeneshop |
+
| DreamHost |
Duck DNS |
-
| Dyn |
DynDnsFree.de |
+
| Dynu |
EasyDNS |
-
| EdgeCenter |
Efficient IP |
- Epik |
- EuroDNS |
- | Excedo |
+ Epik |
Exoscale |
External program |
F5 XC |
@@ -271,35 +266,35 @@ If your DNS provider is not supported, please open an [issue](https://github.com
TodayNIC/时代互联 |
TransIP |
+ | UKFast SafeDNS |
Ultradns |
United-Domains |
Variomedia |
- VegaDNS |
+ | VegaDNS |
Vercel |
Versio.[nl|eu|uk] |
VinylDNS |
- Virtualname |
+ | Virtualname |
VK Cloud |
Volcano Engine/火山引擎 |
Vscale |
- Vultr |
+ | Vultr |
webnames.ca |
webnames.ru |
Websupport |
- WEDOS |
+ | WEDOS |
West.cn/西部数码 |
Yandex 360 |
Yandex Cloud |
- Yandex PDD |
+ | Yandex PDD |
Zone.ee |
ZoneEdit |
Zonomi |
- |
diff --git a/acme/api/internal/sender/useragent.go b/acme/api/internal/sender/useragent.go
index 51a1b4770..feda18cc7 100644
--- a/acme/api/internal/sender/useragent.go
+++ b/acme/api/internal/sender/useragent.go
@@ -9,5 +9,5 @@ const (
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
// values: detach|release
// NOTE: Update this with each tagged release.
- ourUserAgentComment = "detach"
+ ourUserAgentComment = "release"
)
diff --git a/challenge/resolver/errors.go b/challenge/resolver/errors.go
index 65a6ccdb7..6a859922c 100644
--- a/challenge/resolver/errors.go
+++ b/challenge/resolver/errors.go
@@ -3,8 +3,6 @@ package resolver
import (
"bytes"
"fmt"
- "maps"
- "slices"
"sort"
)
@@ -27,7 +25,3 @@ func (e obtainError) Error() string {
return buffer.String()
}
-
-func (e obtainError) Unwrap() []error {
- return slices.AppendSeq(make([]error, 0, len(e)), maps.Values(e))
-}
diff --git a/challenge/resolver/errors_test.go b/challenge/resolver/errors_test.go
deleted file mode 100644
index d4ab3c481..000000000
--- a/challenge/resolver/errors_test.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package resolver
-
-import (
- "errors"
- "testing"
-
- "github.com/go-acme/lego/v4/acme"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func Test_obtainError_Error(t *testing.T) {
- err := obtainError{
- "a": &acme.ProblemDetails{Type: "001"},
- "b": errors.New("oops"),
- "c": errors.New("I did it again"),
- }
-
- require.EqualError(t, err, `error: one or more domains had a problem:
-[a] acme: error: 0 :: 001 ::
-[b] oops
-[c] I did it again
-`)
-}
-
-func Test_obtainError_Unwrap(t *testing.T) {
- testCases := []struct {
- desc string
- err obtainError
- assert assert.BoolAssertionFunc
- }{
- {
- desc: "one ok",
- err: obtainError{
- "a": &acme.ProblemDetails{},
- "b": errors.New("oops"),
- "c": errors.New("I did it again"),
- },
- assert: assert.True,
- },
- {
- desc: "all ok",
- err: obtainError{
- "a": &acme.ProblemDetails{Type: "001"},
- "b": &acme.ProblemDetails{Type: "002"},
- "c": &acme.ProblemDetails{Type: "002"},
- },
- assert: assert.True,
- },
- {
- desc: "nope",
- err: obtainError{
- "a": errors.New("hello"),
- "b": errors.New("oops"),
- "c": errors.New("I did it again"),
- },
- assert: assert.False,
- },
- }
-
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- t.Parallel()
-
- var pd *acme.ProblemDetails
-
- test.assert(t, errors.As(test.err, &pd))
- })
- }
-}
diff --git a/cmd/lego/zz_gen_version.go b/cmd/lego/zz_gen_version.go
index cf9ad00ef..f0ca21326 100644
--- a/cmd/lego/zz_gen_version.go
+++ b/cmd/lego/zz_gen_version.go
@@ -2,7 +2,7 @@
package main
-const defaultVersion = "v4.32.0+dev-detach"
+const defaultVersion = "v4.32.0+dev-release"
var version = ""
diff --git a/cmd/zz_gen_cmd_dnshelp.go b/cmd/zz_gen_cmd_dnshelp.go
index f73f3920b..161729c79 100644
--- a/cmd/zz_gen_cmd_dnshelp.go
+++ b/cmd/zz_gen_cmd_dnshelp.go
@@ -49,7 +49,6 @@ func allDNSCodes() string {
"constellix",
"corenetworks",
"cpanel",
- "czechia",
"ddnss",
"derak",
"desec",
@@ -74,8 +73,6 @@ func allDNSCodes() string {
"edgeone",
"efficientip",
"epik",
- "eurodns",
- "excedo",
"exec",
"exoscale",
"f5xc",
@@ -1029,26 +1026,6 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/cpanel`)
- case "czechia":
- // generated from: providers/dns/czechia/czechia.toml
- ew.writeln(`Configuration for Czechia.`)
- ew.writeln(`Code: 'czechia'`)
- ew.writeln(`Since: 'v4.33.0'`)
- ew.writeln()
-
- ew.writeln(`Credentials:`)
- ew.writeln(` - "CZECHIA_TOKEN": Authorization token`)
- ew.writeln()
-
- ew.writeln(`Additional Configuration:`)
- ew.writeln(` - "CZECHIA_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
- ew.writeln(` - "CZECHIA_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
- ew.writeln(` - "CZECHIA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
- ew.writeln(` - "CZECHIA_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
-
- ew.writeln()
- ew.writeln(`More information: https://go-acme.github.io/lego/dns/czechia`)
-
case "ddnss":
// generated from: providers/dns/ddnss/ddnss.toml
ew.writeln(`Configuration for DDnss (DynDNS Service).`)
@@ -1564,48 +1541,6 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/epik`)
- case "eurodns":
- // generated from: providers/dns/eurodns/eurodns.toml
- ew.writeln(`Configuration for EuroDNS.`)
- ew.writeln(`Code: 'eurodns'`)
- ew.writeln(`Since: 'v4.33.0'`)
- ew.writeln()
-
- ew.writeln(`Credentials:`)
- ew.writeln(` - "EURODNS_API_KEY": API key`)
- ew.writeln(` - "EURODNS_APP_ID": Application ID`)
- ew.writeln()
-
- ew.writeln(`Additional Configuration:`)
- ew.writeln(` - "EURODNS_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
- ew.writeln(` - "EURODNS_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
- ew.writeln(` - "EURODNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
- ew.writeln(` - "EURODNS_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)`)
-
- ew.writeln()
- ew.writeln(`More information: https://go-acme.github.io/lego/dns/eurodns`)
-
- case "excedo":
- // generated from: providers/dns/excedo/excedo.toml
- ew.writeln(`Configuration for Excedo.`)
- ew.writeln(`Code: 'excedo'`)
- ew.writeln(`Since: 'v4.33.0'`)
- ew.writeln()
-
- ew.writeln(`Credentials:`)
- ew.writeln(` - "EXCEDO_API_KEY": API key`)
- ew.writeln(` - "EXCEDO_API_URL": API base URL`)
- ew.writeln()
-
- ew.writeln(`Additional Configuration:`)
- ew.writeln(` - "EXCEDO_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
- ew.writeln(` - "EXCEDO_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 10)`)
- ew.writeln(` - "EXCEDO_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 300)`)
- ew.writeln(` - "EXCEDO_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)`)
-
- ew.writeln()
- ew.writeln(`More information: https://go-acme.github.io/lego/dns/excedo`)
-
case "exec":
// generated from: providers/dns/exec/exec.toml
ew.writeln(`Configuration for External program.`)
@@ -2459,7 +2394,6 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln(` - "LIARA_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "LIARA_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "LIARA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
- ew.writeln(` - "LIARA_TEAM_ID": The team ID to access services in a team`)
ew.writeln(` - "LIARA_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)`)
ew.writeln()
@@ -3439,7 +3373,7 @@ func displayDNSHelp(w io.Writer, name string) error {
case "safedns":
// generated from: providers/dns/safedns/safedns.toml
- ew.writeln(`Configuration for ANS SafeDNS.`)
+ ew.writeln(`Configuration for UKFast SafeDNS.`)
ew.writeln(`Code: 'safedns'`)
ew.writeln(`Since: 'v4.6.0'`)
ew.writeln()
diff --git a/docs/content/dns/zz_gen_czechia.md b/docs/content/dns/zz_gen_czechia.md
deleted file mode 100644
index 7b1cdd1ae..000000000
--- a/docs/content/dns/zz_gen_czechia.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-title: "Czechia"
-date: 2019-03-03T16:39:46+01:00
-draft: false
-slug: czechia
-dnsprovider:
- since: "v4.33.0"
- code: "czechia"
- url: "https://www.czechia.com/"
----
-
-
-
-
-
-
-Configuration for [Czechia](https://www.czechia.com/).
-
-
-
-
-- Code: `czechia`
-- Since: v4.33.0
-
-
-Here is an example bash command using the Czechia provider:
-
-```bash
-CZECHIA_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \
-lego --dns czechia -d '*.example.com' -d example.com run
-```
-
-
-
-
-## Credentials
-
-| Environment Variable Name | Description |
-|-----------------------|-------------|
-| `CZECHIA_TOKEN` | Authorization token |
-
-The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
-More information [here]({{% ref "dns#configuration-and-credentials" %}}).
-
-
-## Additional Configuration
-
-| Environment Variable Name | Description |
-|--------------------------------|-------------|
-| `CZECHIA_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
-| `CZECHIA_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
-| `CZECHIA_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
-| `CZECHIA_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
-
-The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
-More information [here]({{% ref "dns#configuration-and-credentials" %}}).
-
-
-
-
-## More information
-
-- [API documentation](https://api.czechia.com/swagger/index.html)
-
-
-
-
diff --git a/docs/content/dns/zz_gen_eurodns.md b/docs/content/dns/zz_gen_eurodns.md
deleted file mode 100644
index cb5a0418d..000000000
--- a/docs/content/dns/zz_gen_eurodns.md
+++ /dev/null
@@ -1,69 +0,0 @@
----
-title: "EuroDNS"
-date: 2019-03-03T16:39:46+01:00
-draft: false
-slug: eurodns
-dnsprovider:
- since: "v4.33.0"
- code: "eurodns"
- url: "https://www.eurodns.com/"
----
-
-
-
-
-
-
-Configuration for [EuroDNS](https://www.eurodns.com/).
-
-
-
-
-- Code: `eurodns`
-- Since: v4.33.0
-
-
-Here is an example bash command using the EuroDNS provider:
-
-```bash
-EURODNS_APP_ID="xxx" \
-EURODNS_API_KEY="yyy" \
-lego --dns eurodns -d '*.example.com' -d example.com run
-```
-
-
-
-
-## Credentials
-
-| Environment Variable Name | Description |
-|-----------------------|-------------|
-| `EURODNS_API_KEY` | API key |
-| `EURODNS_APP_ID` | Application ID |
-
-The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
-More information [here]({{% ref "dns#configuration-and-credentials" %}}).
-
-
-## Additional Configuration
-
-| Environment Variable Name | Description |
-|--------------------------------|-------------|
-| `EURODNS_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
-| `EURODNS_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
-| `EURODNS_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
-| `EURODNS_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 600) |
-
-The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
-More information [here]({{% ref "dns#configuration-and-credentials" %}}).
-
-
-
-
-## More information
-
-- [API documentation](https://docapi.eurodns.com/)
-
-
-
-
diff --git a/docs/content/dns/zz_gen_excedo.md b/docs/content/dns/zz_gen_excedo.md
deleted file mode 100644
index 456e6f60a..000000000
--- a/docs/content/dns/zz_gen_excedo.md
+++ /dev/null
@@ -1,69 +0,0 @@
----
-title: "Excedo"
-date: 2019-03-03T16:39:46+01:00
-draft: false
-slug: excedo
-dnsprovider:
- since: "v4.33.0"
- code: "excedo"
- url: "https://excedo.se/"
----
-
-
-
-
-
-
-Configuration for [Excedo](https://excedo.se/).
-
-
-
-
-- Code: `excedo`
-- Since: v4.33.0
-
-
-Here is an example bash command using the Excedo provider:
-
-```bash
-EXCEDO_API_KEY=your-api-key \
-EXCEDO_API_URL=your-base-url \
-lego --dns excedo -d '*.example.com' -d example.com run
-```
-
-
-
-
-## Credentials
-
-| Environment Variable Name | Description |
-|-----------------------|-------------|
-| `EXCEDO_API_KEY` | API key |
-| `EXCEDO_API_URL` | API base URL |
-
-The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
-More information [here]({{% ref "dns#configuration-and-credentials" %}}).
-
-
-## Additional Configuration
-
-| Environment Variable Name | Description |
-|--------------------------------|-------------|
-| `EXCEDO_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
-| `EXCEDO_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 10) |
-| `EXCEDO_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 300) |
-| `EXCEDO_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 60) |
-
-The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
-More information [here]({{% ref "dns#configuration-and-credentials" %}}).
-
-
-
-
-## More information
-
-- [API documentation](none)
-
-
-
-
diff --git a/docs/content/dns/zz_gen_liara.md b/docs/content/dns/zz_gen_liara.md
index 658ce8077..8a6ddbd99 100644
--- a/docs/content/dns/zz_gen_liara.md
+++ b/docs/content/dns/zz_gen_liara.md
@@ -50,7 +50,6 @@ More information [here]({{% ref "dns#configuration-and-credentials" %}}).
| `LIARA_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `LIARA_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `LIARA_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
-| `LIARA_TEAM_ID` | The team ID to access services in a team |
| `LIARA_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
diff --git a/docs/content/dns/zz_gen_safedns.md b/docs/content/dns/zz_gen_safedns.md
index 4c20fca6a..e040a8a9f 100644
--- a/docs/content/dns/zz_gen_safedns.md
+++ b/docs/content/dns/zz_gen_safedns.md
@@ -1,12 +1,12 @@
---
-title: "ANS SafeDNS"
+title: "UKFast SafeDNS"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: safedns
dnsprovider:
since: "v4.6.0"
code: "safedns"
- url: "https://www.ans.co.uk/"
+ url: "https://www.ukfast.co.uk/dns-hosting.html"
---
@@ -14,7 +14,7 @@ dnsprovider:
-Configuration for [ANS SafeDNS](https://www.ans.co.uk/).
+Configuration for [UKFast SafeDNS](https://www.ukfast.co.uk/dns-hosting.html).
@@ -23,7 +23,7 @@ Configuration for [ANS SafeDNS](https://www.ans.co.uk/).
- Since: v4.6.0
-Here is an example bash command using the ANS SafeDNS provider:
+Here is an example bash command using the UKFast SafeDNS provider:
```bash
SAFEDNS_AUTH_TOKEN=xxxxxx \
diff --git a/docs/data/zz_cli_help.toml b/docs/data/zz_cli_help.toml
index 139143b17..925ef0b21 100644
--- a/docs/data/zz_cli_help.toml
+++ b/docs/data/zz_cli_help.toml
@@ -152,7 +152,7 @@ To display the documentation for a specific DNS provider, run:
$ lego dnshelp -c code
Supported DNS providers:
- acme-dns, active24, alidns, aliesa, allinkl, alwaysdata, anexia, artfiles, arvancloud, auroradns, autodns, axelname, azion, azure, azuredns, baiducloud, beget, binarylane, bindman, bluecat, bluecatv2, bookmyname, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudru, cloudxns, com35, conoha, conohav3, constellix, corenetworks, cpanel, czechia, ddnss, derak, desec, designate, digitalocean, directadmin, dnsexit, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dyndnsfree, dynu, easydns, edgecenter, edgedns, edgeone, efficientip, epik, eurodns, excedo, exec, exoscale, f5xc, freemyip, gandi, gandiv5, gcloud, gcore, gigahostno, glesys, godaddy, googledomains, gravity, hetzner, hostingde, hostinger, hostingnl, hosttech, httpnet, httpreq, huaweicloud, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, ionoscloud, ipv64, ispconfig, ispconfigddns, iwantmyname, jdcloud, joker, keyhelp, leaseweb, liara, lightsail, limacity, linode, liquidweb, loopia, luadns, mailinabox, manageengine, manual, metaname, metaregistrar, mijnhost, mittwald, myaddr, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, namesurfer, nearlyfreespeech, neodigit, netcup, netlify, nicmanager, nicru, nifcloud, njalla, nodion, ns1, octenium, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, rainyun, rcodezero, regfish, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, selectelv2, selfhostde, servercow, shellrent, simply, sonic, spaceship, stackpath, syse, technitium, tencentcloud, timewebcloud, todaynic, transip, ultradns, uniteddomains, variomedia, vegadns, vercel, versio, vinyldns, virtualname, vkcloud, volcengine, vscale, vultr, webnames, webnamesca, websupport, wedos, westcn, yandex, yandex360, yandexcloud, zoneedit, zoneee, zonomi
+ acme-dns, active24, alidns, aliesa, allinkl, alwaysdata, anexia, artfiles, arvancloud, auroradns, autodns, axelname, azion, azure, azuredns, baiducloud, beget, binarylane, bindman, bluecat, bluecatv2, bookmyname, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudru, cloudxns, com35, conoha, conohav3, constellix, corenetworks, cpanel, ddnss, derak, desec, designate, digitalocean, directadmin, dnsexit, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dyndnsfree, dynu, easydns, edgecenter, edgedns, edgeone, efficientip, epik, exec, exoscale, f5xc, freemyip, gandi, gandiv5, gcloud, gcore, gigahostno, glesys, godaddy, googledomains, gravity, hetzner, hostingde, hostinger, hostingnl, hosttech, httpnet, httpreq, huaweicloud, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, ionoscloud, ipv64, ispconfig, ispconfigddns, iwantmyname, jdcloud, joker, keyhelp, leaseweb, liara, lightsail, limacity, linode, liquidweb, loopia, luadns, mailinabox, manageengine, manual, metaname, metaregistrar, mijnhost, mittwald, myaddr, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, namesurfer, nearlyfreespeech, neodigit, netcup, netlify, nicmanager, nicru, nifcloud, njalla, nodion, ns1, octenium, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, rainyun, rcodezero, regfish, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, selectelv2, selfhostde, servercow, shellrent, simply, sonic, spaceship, stackpath, syse, technitium, tencentcloud, timewebcloud, todaynic, transip, ultradns, uniteddomains, variomedia, vegadns, vercel, versio, vinyldns, virtualname, vkcloud, volcengine, vscale, vultr, webnames, webnamesca, websupport, wedos, westcn, yandex, yandex360, yandexcloud, zoneedit, zoneee, zonomi
More information: https://go-acme.github.io/lego/dns
"""
diff --git a/providers/dns/czechia/czechia.go b/providers/dns/czechia/czechia.go
deleted file mode 100644
index 3ff397c35..000000000
--- a/providers/dns/czechia/czechia.go
+++ /dev/null
@@ -1,159 +0,0 @@
-// Package czechia implements a DNS provider for solving the DNS-01 challenge using Czechia.
-package czechia
-
-import (
- "context"
- "errors"
- "fmt"
- "net/http"
- "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/czechia/internal"
- "github.com/go-acme/lego/v4/providers/dns/internal/clientdebug"
-)
-
-// Environment variables names.
-const (
- envNamespace = "CZECHIA_"
-
- EnvToken = envNamespace + "TOKEN"
-
- EnvTTL = envNamespace + "TTL"
- EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
- EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
- EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
-)
-
-// Config is used to configure the creation of the DNSProvider.
-type Config struct {
- Token string
-
- PropagationTimeout time.Duration
- PollingInterval time.Duration
- TTL int
- HTTPClient *http.Client
-}
-
-// NewDefaultConfig returns a default configuration for the DNSProvider.
-func NewDefaultConfig() *Config {
- return &Config{
- TTL: env.GetOrDefaultInt(EnvTTL, dns01.DefaultTTL),
- PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
- PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
- HTTPClient: &http.Client{
- Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
- },
- }
-}
-
-// DNSProvider implements the challenge.Provider interface.
-type DNSProvider struct {
- config *Config
- client *internal.Client
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Czechia.
-func NewDNSProvider() (*DNSProvider, error) {
- values, err := env.Get(EnvToken)
- if err != nil {
- return nil, fmt.Errorf("czechia: %w", err)
- }
-
- config := NewDefaultConfig()
- config.Token = values[EnvToken]
-
- return NewDNSProviderConfig(config)
-}
-
-// NewDNSProviderConfig return a DNSProvider instance configured for Czechia.
-func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
- if config == nil {
- return nil, errors.New("czechia: the configuration of the DNS provider is nil")
- }
-
- client, err := internal.NewClient(config.Token)
- if err != nil {
- return nil, fmt.Errorf("czechia: %w", err)
- }
-
- if config.HTTPClient != nil {
- client.HTTPClient = config.HTTPClient
- }
-
- client.HTTPClient = clientdebug.Wrap(client.HTTPClient)
-
- return &DNSProvider{
- config: config,
- client: client,
- }, nil
-}
-
-// Present creates a TXT record using the specified parameters.
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- ctx := context.Background()
-
- info := dns01.GetChallengeInfo(domain, keyAuth)
-
- authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
- if err != nil {
- return fmt.Errorf("czechia: could not find zone for domain %q: %w", domain, err)
- }
-
- subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
- if err != nil {
- return fmt.Errorf("czechia: %w", err)
- }
-
- record := internal.TXTRecord{
- Hostname: subDomain,
- Text: info.Value,
- TTL: d.config.TTL,
- PublishZone: 1,
- }
-
- err = d.client.AddTXTRecord(ctx, dns01.UnFqdn(authZone), record)
- if err != nil {
- return fmt.Errorf("czechia: add TXT record: %w", err)
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- ctx := context.Background()
-
- info := dns01.GetChallengeInfo(domain, keyAuth)
-
- authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
- if err != nil {
- return fmt.Errorf("czechia: could not find zone for domain %q: %w", domain, err)
- }
-
- subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
- if err != nil {
- return fmt.Errorf("czechia: %w", err)
- }
-
- record := internal.TXTRecord{
- Hostname: subDomain,
- Text: info.Value,
- TTL: d.config.TTL,
- PublishZone: 1,
- }
-
- err = d.client.DeleteTXTRecord(ctx, dns01.UnFqdn(authZone), record)
- if err != nil {
- return fmt.Errorf("czechia: delete TXT record: %w", err)
- }
-
- return nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS propagation.
-// Adjusting here to cope with spikes in propagation times.
-func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return d.config.PropagationTimeout, d.config.PollingInterval
-}
diff --git a/providers/dns/czechia/czechia.toml b/providers/dns/czechia/czechia.toml
deleted file mode 100644
index 2a66d2054..000000000
--- a/providers/dns/czechia/czechia.toml
+++ /dev/null
@@ -1,22 +0,0 @@
-Name = "Czechia"
-Description = ''''''
-URL = "https://www.czechia.com/"
-Code = "czechia"
-Since = "v4.33.0"
-
-Example = '''
-CZECHIA_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \
-lego --dns czechia -d '*.example.com' -d example.com run
-'''
-
-[Configuration]
- [Configuration.Credentials]
- CZECHIA_TOKEN = "Authorization token"
- [Configuration.Additional]
- CZECHIA_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)"
- CZECHIA_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)"
- CZECHIA_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)"
- CZECHIA_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)"
-
-[Links]
- API = "https://api.czechia.com/swagger/index.html"
diff --git a/providers/dns/czechia/czechia_test.go b/providers/dns/czechia/czechia_test.go
deleted file mode 100644
index 7d9a2676c..000000000
--- a/providers/dns/czechia/czechia_test.go
+++ /dev/null
@@ -1,165 +0,0 @@
-package czechia
-
-import (
- "net/http/httptest"
- "net/url"
- "testing"
-
- "github.com/go-acme/lego/v4/platform/tester"
- "github.com/go-acme/lego/v4/platform/tester/servermock"
- "github.com/stretchr/testify/require"
-)
-
-const envDomain = envNamespace + "DOMAIN"
-
-var envTest = tester.NewEnvTest(EnvToken).WithDomain(envDomain)
-
-func TestNewDNSProvider(t *testing.T) {
- testCases := []struct {
- desc string
- envVars map[string]string
- expected string
- }{
- {
- desc: "success",
- envVars: map[string]string{
- EnvToken: "secret",
- },
- },
- {
- desc: "missing credentials",
- envVars: map[string]string{},
- expected: "czechia: some credentials information are missing: CZECHIA_TOKEN",
- },
- }
-
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- defer envTest.RestoreEnv()
-
- envTest.ClearEnv()
-
- envTest.Apply(test.envVars)
-
- p, err := NewDNSProvider()
-
- if test.expected == "" {
- require.NoError(t, err)
- require.NotNil(t, p)
- require.NotNil(t, p.config)
- require.NotNil(t, p.client)
- } else {
- require.EqualError(t, err, test.expected)
- }
- })
- }
-}
-
-func TestNewDNSProviderConfig(t *testing.T) {
- testCases := []struct {
- desc string
- token string
- expected string
- }{
- {
- desc: "success",
- token: "secret",
- },
- {
- desc: "missing credentials",
- expected: "czechia: credentials missing",
- },
- }
-
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- config := NewDefaultConfig()
- config.Token = test.token
-
- p, err := NewDNSProviderConfig(config)
-
- if test.expected == "" {
- require.NoError(t, err)
- require.NotNil(t, p)
- require.NotNil(t, p.config)
- require.NotNil(t, p.client)
- } else {
- require.EqualError(t, err, test.expected)
- }
- })
- }
-}
-
-func TestLivePresent(t *testing.T) {
- if !envTest.IsLiveTest() {
- t.Skip("skipping live test")
- }
-
- envTest.RestoreEnv()
-
- provider, err := NewDNSProvider()
- require.NoError(t, err)
-
- err = provider.Present(envTest.GetDomain(), "", "123d==")
- require.NoError(t, err)
-}
-
-func TestLiveCleanUp(t *testing.T) {
- if !envTest.IsLiveTest() {
- t.Skip("skipping live test")
- }
-
- envTest.RestoreEnv()
-
- provider, err := NewDNSProvider()
- require.NoError(t, err)
-
- err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
- require.NoError(t, err)
-}
-
-func mockBuilder() *servermock.Builder[*DNSProvider] {
- return servermock.NewBuilder(
- func(server *httptest.Server) (*DNSProvider, error) {
- config := NewDefaultConfig()
- config.Token = "secret"
- config.HTTPClient = server.Client()
-
- p, err := NewDNSProviderConfig(config)
- if err != nil {
- return nil, err
- }
-
- p.client.BaseURL, _ = url.Parse(server.URL)
-
- return p, nil
- },
- servermock.CheckHeader().
- WithJSONHeaders().
- With("AuthorizationToken", "secret"),
- )
-}
-
-func TestDNSProvider_Present(t *testing.T) {
- provider := mockBuilder().
- Route("POST /DNS/example.com/TXT",
- servermock.Noop(),
- servermock.CheckRequestJSONBodyFromInternal("add_txt_record-request.json"),
- ).
- Build(t)
-
- err := provider.Present("example.com", "abc", "123d==")
- require.NoError(t, err)
-}
-
-func TestDNSProvider_CleanUp(t *testing.T) {
- provider := mockBuilder().
- Route("DELETE /DNS/example.com/TXT",
- servermock.Noop(),
- servermock.CheckRequestJSONBodyFromInternal("add_txt_record-request.json"),
- ).
- Build(t)
-
- err := provider.CleanUp("example.com", "abc", "123d==")
- require.NoError(t, err)
-}
diff --git a/providers/dns/czechia/internal/client.go b/providers/dns/czechia/internal/client.go
deleted file mode 100644
index f3e0e462e..000000000
--- a/providers/dns/czechia/internal/client.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package internal
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "time"
-
- "github.com/go-acme/lego/v4/providers/dns/internal/errutils"
- "github.com/go-acme/lego/v4/providers/dns/internal/useragent"
-)
-
-const defaultBaseURL = "https://api.czechia.com/api"
-
-const authorizationTokenHeader = "AuthorizationToken"
-
-// Client the Czechia API client.
-type Client struct {
- token string
-
- BaseURL *url.URL
- HTTPClient *http.Client
-}
-
-// NewClient creates a new Client.
-func NewClient(token string) (*Client, error) {
- if token == "" {
- return nil, errors.New("credentials missing")
- }
-
- baseURL, _ := url.Parse(defaultBaseURL)
-
- return &Client{
- token: token,
- BaseURL: baseURL,
- HTTPClient: &http.Client{Timeout: 10 * time.Second},
- }, nil
-}
-
-func (c *Client) AddTXTRecord(ctx context.Context, domain string, record TXTRecord) error {
- endpoint := c.BaseURL.JoinPath("DNS", domain, "TXT")
-
- req, err := newJSONRequest(ctx, http.MethodPost, endpoint, record)
- if err != nil {
- return err
- }
-
- return c.do(req, nil)
-}
-
-func (c *Client) DeleteTXTRecord(ctx context.Context, domain string, record TXTRecord) error {
- endpoint := c.BaseURL.JoinPath("DNS", domain, "TXT")
-
- req, err := newJSONRequest(ctx, http.MethodDelete, endpoint, record)
- if err != nil {
- return err
- }
-
- return c.do(req, nil)
-}
-
-func (c *Client) do(req *http.Request, result any) error {
- useragent.SetHeader(req.Header)
-
- req.Header.Set(authorizationTokenHeader, c.token)
-
- resp, err := c.HTTPClient.Do(req)
- if err != nil {
- return errutils.NewHTTPDoError(req, err)
- }
-
- defer func() { _ = resp.Body.Close() }()
-
- if resp.StatusCode/100 != 2 {
- raw, _ := io.ReadAll(resp.Body)
-
- return errutils.NewUnexpectedStatusCodeError(req, resp.StatusCode, raw)
- }
-
- if result == nil {
- return nil
- }
-
- raw, err := io.ReadAll(resp.Body)
- if err != nil {
- return errutils.NewReadResponseError(req, resp.StatusCode, err)
- }
-
- err = json.Unmarshal(raw, result)
- if err != nil {
- return errutils.NewUnmarshalError(req, resp.StatusCode, raw, err)
- }
-
- return nil
-}
-
-func newJSONRequest(ctx context.Context, method string, endpoint *url.URL, payload any) (*http.Request, error) {
- buf := new(bytes.Buffer)
-
- if payload != nil {
- err := json.NewEncoder(buf).Encode(payload)
- if err != nil {
- return nil, fmt.Errorf("failed to create request JSON body: %w", err)
- }
- }
-
- req, err := http.NewRequestWithContext(ctx, method, endpoint.String(), buf)
- if err != nil {
- return nil, fmt.Errorf("unable to create request: %w", err)
- }
-
- req.Header.Set("Accept", "application/json")
-
- if payload != nil {
- req.Header.Set("Content-Type", "application/json")
- }
-
- return req, nil
-}
diff --git a/providers/dns/czechia/internal/client_test.go b/providers/dns/czechia/internal/client_test.go
deleted file mode 100644
index c6f1141c5..000000000
--- a/providers/dns/czechia/internal/client_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package internal
-
-import (
- "net/http/httptest"
- "net/url"
- "testing"
-
- "github.com/go-acme/lego/v4/platform/tester/servermock"
- "github.com/stretchr/testify/require"
-)
-
-func mockBuilder() *servermock.Builder[*Client] {
- return servermock.NewBuilder[*Client](
- func(server *httptest.Server) (*Client, error) {
- client, err := NewClient("secret")
- if err != nil {
- return nil, err
- }
-
- client.BaseURL, _ = url.Parse(server.URL)
- client.HTTPClient = server.Client()
-
- return client, nil
- },
- servermock.CheckHeader().
- WithJSONHeaders().
- With(authorizationTokenHeader, "secret"),
- )
-}
-
-func TestClient_AddTXTRecord(t *testing.T) {
- client := mockBuilder().
- Route("POST /DNS/example.com/TXT",
- servermock.Noop(),
- servermock.CheckRequestJSONBodyFromFixture("add_txt_record-request.json"),
- ).
- Build(t)
-
- record := TXTRecord{
- Hostname: "_acme-challenge",
- Text: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: 120,
- PublishZone: 1,
- }
-
- err := client.AddTXTRecord(t.Context(), "example.com", record)
- require.NoError(t, err)
-}
-
-func TestClient_DeleteTXTRecord(t *testing.T) {
- client := mockBuilder().
- Route("DELETE /DNS/example.com/TXT",
- servermock.Noop(),
- servermock.CheckRequestJSONBodyFromFixture("add_txt_record-request.json"),
- ).
- Build(t)
-
- record := TXTRecord{
- Hostname: "_acme-challenge",
- Text: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: 120,
- PublishZone: 1,
- }
-
- err := client.DeleteTXTRecord(t.Context(), "example.com", record)
- require.NoError(t, err)
-}
diff --git a/providers/dns/czechia/internal/fixtures/add_txt_record-request.json b/providers/dns/czechia/internal/fixtures/add_txt_record-request.json
deleted file mode 100644
index ed5830093..000000000
--- a/providers/dns/czechia/internal/fixtures/add_txt_record-request.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "hostName": "_acme-challenge",
- "text": "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- "ttl": 120,
- "publishZone": 1
-}
diff --git a/providers/dns/czechia/internal/fixtures/delete_txt_record-request.json b/providers/dns/czechia/internal/fixtures/delete_txt_record-request.json
deleted file mode 100644
index ed5830093..000000000
--- a/providers/dns/czechia/internal/fixtures/delete_txt_record-request.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "hostName": "_acme-challenge",
- "text": "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- "ttl": 120,
- "publishZone": 1
-}
diff --git a/providers/dns/czechia/internal/types.go b/providers/dns/czechia/internal/types.go
deleted file mode 100644
index f4a9bfef7..000000000
--- a/providers/dns/czechia/internal/types.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package internal
-
-type TXTRecord struct {
- Hostname string `json:"hostName,omitempty"`
- Text string `json:"text,omitempty"`
- TTL int `json:"ttl,omitempty"`
- PublishZone int `json:"publishZone,omitempty"`
-}
diff --git a/providers/dns/eurodns/eurodns.go b/providers/dns/eurodns/eurodns.go
deleted file mode 100644
index 21ff3c3a9..000000000
--- a/providers/dns/eurodns/eurodns.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Package eurodns implements a DNS provider for solving the DNS-01 challenge using EuroDNS.
-package eurodns
-
-import (
- "context"
- "errors"
- "fmt"
- "net/http"
- "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/eurodns/internal"
- "github.com/go-acme/lego/v4/providers/dns/internal/clientdebug"
-)
-
-// Environment variables names.
-const (
- envNamespace = "EURODNS_"
-
- EnvApplicationID = envNamespace + "APP_ID"
- EnvAPIKey = envNamespace + "API_KEY"
-
- EnvTTL = envNamespace + "TTL"
- EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
- EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
- EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
-)
-
-// Config is used to configure the creation of the DNSProvider.
-type Config struct {
- ApplicationID string
- APIKey string
-
- PropagationTimeout time.Duration
- PollingInterval time.Duration
- TTL int
- HTTPClient *http.Client
-}
-
-// NewDefaultConfig returns a default configuration for the DNSProvider.
-func NewDefaultConfig() *Config {
- return &Config{
- TTL: env.GetOrDefaultInt(EnvTTL, internal.DefaultTTL),
- PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
- PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
- HTTPClient: &http.Client{
- Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
- },
- }
-}
-
-// DNSProvider implements the challenge.Provider interface.
-type DNSProvider struct {
- config *Config
- client *internal.Client
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for EuroDNS.
-func NewDNSProvider() (*DNSProvider, error) {
- values, err := env.Get(EnvApplicationID, EnvAPIKey)
- if err != nil {
- return nil, fmt.Errorf("eurodns: %w", err)
- }
-
- config := NewDefaultConfig()
- config.ApplicationID = values[EnvApplicationID]
- config.APIKey = values[EnvAPIKey]
-
- return NewDNSProviderConfig(config)
-}
-
-// NewDNSProviderConfig return a DNSProvider instance configured for EuroDNS.
-func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
- if config == nil {
- return nil, errors.New("eurodns: the configuration of the DNS provider is nil")
- }
-
- client, err := internal.NewClient(config.ApplicationID, config.APIKey)
- if err != nil {
- return nil, fmt.Errorf("eurodns: %w", err)
- }
-
- if config.HTTPClient != nil {
- client.HTTPClient = config.HTTPClient
- }
-
- client.HTTPClient = clientdebug.Wrap(client.HTTPClient)
-
- return &DNSProvider{
- config: config,
- client: client,
- }, nil
-}
-
-// Present creates a TXT record using the specified parameters.
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- ctx := context.Background()
- info := dns01.GetChallengeInfo(domain, keyAuth)
-
- authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
- if err != nil {
- return fmt.Errorf("eurodns: could not find zone for domain %q: %w", domain, err)
- }
-
- subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
- if err != nil {
- return fmt.Errorf("eurodns: %w", err)
- }
-
- authZone = dns01.UnFqdn(authZone)
-
- zone, err := d.client.GetZone(ctx, authZone)
- if err != nil {
- return fmt.Errorf("eurodns: get zone: %w", err)
- }
-
- zone.Records = append(zone.Records, internal.Record{
- Type: "TXT",
- Host: subDomain,
- TTL: internal.TTLRounder(d.config.TTL),
- RData: info.Value,
- })
-
- validation, err := d.client.ValidateZone(ctx, authZone, zone)
- if err != nil {
- return fmt.Errorf("eurodns: validate zone: %w", err)
- }
-
- if validation.Report != nil && !validation.Report.IsValid {
- return fmt.Errorf("eurodns: validation report: %w", validation.Report)
- }
-
- err = d.client.SaveZone(ctx, authZone, zone)
- if err != nil {
- return fmt.Errorf("eurodns: save zone: %w", err)
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- ctx := context.Background()
- info := dns01.GetChallengeInfo(domain, keyAuth)
-
- authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
- if err != nil {
- return fmt.Errorf("eurodns: could not find zone for domain %q: %w", domain, err)
- }
-
- subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
- if err != nil {
- return fmt.Errorf("eurodns: %w", err)
- }
-
- authZone = dns01.UnFqdn(authZone)
-
- zone, err := d.client.GetZone(ctx, authZone)
- if err != nil {
- return fmt.Errorf("eurodns: get zone: %w", err)
- }
-
- var recordsToKeep []internal.Record
-
- for _, record := range zone.Records {
- if record.Type == "TXT" && record.Host == subDomain && record.RData == info.Value {
- continue
- }
-
- recordsToKeep = append(recordsToKeep, record)
- }
-
- zone.Records = recordsToKeep
-
- validation, err := d.client.ValidateZone(ctx, authZone, zone)
- if err != nil {
- return fmt.Errorf("eurodns: validate zone: %w", err)
- }
-
- if validation.Report != nil && !validation.Report.IsValid {
- return fmt.Errorf("eurodns: validation report: %w", validation.Report)
- }
-
- err = d.client.SaveZone(ctx, authZone, zone)
- if err != nil {
- return fmt.Errorf("eurodns: save zone: %w", err)
- }
-
- return nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS propagation.
-// Adjusting here to cope with spikes in propagation times.
-func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return d.config.PropagationTimeout, d.config.PollingInterval
-}
diff --git a/providers/dns/eurodns/eurodns.toml b/providers/dns/eurodns/eurodns.toml
deleted file mode 100644
index 302b15d00..000000000
--- a/providers/dns/eurodns/eurodns.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-Name = "EuroDNS"
-Description = ''''''
-URL = "https://www.eurodns.com/"
-Code = "eurodns"
-Since = "v4.33.0"
-
-Example = '''
-EURODNS_APP_ID="xxx" \
-EURODNS_API_KEY="yyy" \
-lego --dns eurodns -d '*.example.com' -d example.com run
-'''
-
-[Configuration]
- [Configuration.Credentials]
- EURODNS_APP_ID = "Application ID"
- EURODNS_API_KEY = "API key"
- [Configuration.Additional]
- EURODNS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)"
- EURODNS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)"
- EURODNS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)"
- EURODNS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)"
-
-[Links]
- API = "https://docapi.eurodns.com/"
diff --git a/providers/dns/eurodns/eurodns_test.go b/providers/dns/eurodns/eurodns_test.go
deleted file mode 100644
index abbb4717e..000000000
--- a/providers/dns/eurodns/eurodns_test.go
+++ /dev/null
@@ -1,215 +0,0 @@
-package eurodns
-
-import (
- "net/http"
- "net/http/httptest"
- "net/url"
- "testing"
-
- "github.com/go-acme/lego/v4/platform/tester"
- "github.com/go-acme/lego/v4/platform/tester/servermock"
- "github.com/go-acme/lego/v4/providers/dns/eurodns/internal"
- "github.com/stretchr/testify/require"
-)
-
-const envDomain = envNamespace + "DOMAIN"
-
-var envTest = tester.NewEnvTest(EnvApplicationID, EnvAPIKey).WithDomain(envDomain)
-
-func TestNewDNSProvider(t *testing.T) {
- testCases := []struct {
- desc string
- envVars map[string]string
- expected string
- }{
- {
- desc: "success",
- envVars: map[string]string{
- EnvApplicationID: "abc",
- EnvAPIKey: "secret",
- },
- },
- {
- desc: "missing application ID",
- envVars: map[string]string{
- EnvApplicationID: "",
- EnvAPIKey: "secret",
- },
- expected: "eurodns: some credentials information are missing: EURODNS_APP_ID",
- },
- {
- desc: "missing API secret",
- envVars: map[string]string{
- EnvApplicationID: "",
- EnvAPIKey: "secret",
- },
- expected: "eurodns: some credentials information are missing: EURODNS_APP_ID",
- },
- {
- desc: "missing credentials",
- envVars: map[string]string{},
- expected: "eurodns: some credentials information are missing: EURODNS_APP_ID,EURODNS_API_KEY",
- },
- }
-
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- defer envTest.RestoreEnv()
-
- envTest.ClearEnv()
-
- envTest.Apply(test.envVars)
-
- p, err := NewDNSProvider()
-
- if test.expected == "" {
- require.NoError(t, err)
- require.NotNil(t, p)
- require.NotNil(t, p.config)
- require.NotNil(t, p.client)
- } else {
- require.EqualError(t, err, test.expected)
- }
- })
- }
-}
-
-func TestNewDNSProviderConfig(t *testing.T) {
- testCases := []struct {
- desc string
- appID string
- apiKey string
- expected string
- }{
- {
- desc: "success",
- appID: "abc",
- apiKey: "secret",
- },
- {
- desc: "missing application ID",
- expected: "eurodns: credentials missing",
- apiKey: "secret",
- },
- {
- desc: "missing API secret",
- expected: "eurodns: credentials missing",
- appID: "abc",
- },
- {
- desc: "missing credentials",
- expected: "eurodns: credentials missing",
- },
- }
-
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- config := NewDefaultConfig()
- config.ApplicationID = test.appID
- config.APIKey = test.apiKey
-
- p, err := NewDNSProviderConfig(config)
-
- if test.expected == "" {
- require.NoError(t, err)
- require.NotNil(t, p)
- require.NotNil(t, p.config)
- require.NotNil(t, p.client)
- } else {
- require.EqualError(t, err, test.expected)
- }
- })
- }
-}
-
-func TestLivePresent(t *testing.T) {
- if !envTest.IsLiveTest() {
- t.Skip("skipping live test")
- }
-
- envTest.RestoreEnv()
-
- provider, err := NewDNSProvider()
- require.NoError(t, err)
-
- err = provider.Present(envTest.GetDomain(), "", "123d==")
- require.NoError(t, err)
-}
-
-func TestLiveCleanUp(t *testing.T) {
- if !envTest.IsLiveTest() {
- t.Skip("skipping live test")
- }
-
- envTest.RestoreEnv()
-
- provider, err := NewDNSProvider()
- require.NoError(t, err)
-
- err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
- require.NoError(t, err)
-}
-
-func mockBuilder() *servermock.Builder[*DNSProvider] {
- return servermock.NewBuilder(
- func(server *httptest.Server) (*DNSProvider, error) {
- config := NewDefaultConfig()
- config.APIKey = "secret"
- config.ApplicationID = "abc"
- config.HTTPClient = server.Client()
-
- provider, err := NewDNSProviderConfig(config)
- if err != nil {
- return nil, err
- }
-
- provider.client.BaseURL, _ = url.Parse(server.URL)
-
- return provider, nil
- },
- servermock.CheckHeader().
- WithJSONHeaders().
- With(internal.HeaderAppID, "abc").
- With(internal.HeaderAPIKey, "secret"),
- )
-}
-
-func TestDNSProvider_Present(t *testing.T) {
- provider := mockBuilder().
- Route("GET /example.com",
- servermock.ResponseFromInternal("zone_get.json"),
- ).
- Route("POST /example.com/check",
- servermock.ResponseFromInternal("zone_add_validate_ok.json"),
- servermock.CheckRequestJSONBodyFromInternal("zone_add.json"),
- ).
- Route("PUT /example.com",
- servermock.Noop().
- WithStatusCode(http.StatusNoContent),
- servermock.CheckRequestJSONBodyFromInternal("zone_add.json"),
- ).
- Build(t)
-
- err := provider.Present("example.com", "abc", "123d==")
- require.NoError(t, err)
-}
-
-func TestDNSProvider_CleanUp(t *testing.T) {
- provider := mockBuilder().
- Route("GET /example.com",
- servermock.ResponseFromInternal("zone_add.json"),
- ).
- Route("POST /example.com/check",
- servermock.ResponseFromInternal("zone_remove.json"),
- servermock.CheckRequestJSONBodyFromInternal("zone_remove.json"),
- ).
- Route("PUT /example.com",
- servermock.Noop().
- WithStatusCode(http.StatusNoContent),
- servermock.CheckRequestJSONBodyFromInternal("zone_remove.json"),
- ).
- Build(t)
-
- err := provider.CleanUp("example.com", "abc", "123d==")
- require.NoError(t, err)
-}
diff --git a/providers/dns/eurodns/internal/client.go b/providers/dns/eurodns/internal/client.go
deleted file mode 100644
index 1ebf8d143..000000000
--- a/providers/dns/eurodns/internal/client.go
+++ /dev/null
@@ -1,199 +0,0 @@
-package internal
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "time"
-
- "github.com/go-acme/lego/v4/providers/dns/internal/errutils"
-)
-
-const defaultBaseURL = "https://rest-api.eurodns.com/dns-zones/"
-
-const (
- HeaderAppID = "X-APP-ID"
- HeaderAPIKey = "X-API-KEY"
-)
-
-// Client the EuroDNS API client.
-type Client struct {
- appID string
- apiKey string
-
- BaseURL *url.URL
- HTTPClient *http.Client
-}
-
-// NewClient creates a new Client.
-func NewClient(appID, apiKey string) (*Client, error) {
- if appID == "" || apiKey == "" {
- return nil, errors.New("credentials missing")
- }
-
- baseURL, _ := url.Parse(defaultBaseURL)
-
- return &Client{
- appID: appID,
- apiKey: apiKey,
- BaseURL: baseURL,
- HTTPClient: &http.Client{Timeout: 10 * time.Second},
- }, nil
-}
-
-// GetZone gets a DNS Zone.
-// https://docapi.eurodns.com/#/dnsprovider/getdnszone
-func (c *Client) GetZone(ctx context.Context, domain string) (*Zone, error) {
- endpoint := c.BaseURL.JoinPath(domain)
-
- req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
- if err != nil {
- return nil, err
- }
-
- result := &Zone{}
-
- err = c.do(req, result)
- if err != nil {
- return nil, err
- }
-
- return result, nil
-}
-
-// SaveZone saves a DNS Zone.
-// https://docapi.eurodns.com/#/dnsprovider/savednszone
-func (c *Client) SaveZone(ctx context.Context, domain string, zone *Zone) error {
- endpoint := c.BaseURL.JoinPath(domain)
-
- if len(zone.URLForwards) == 0 {
- zone.URLForwards = make([]URLForward, 0)
- }
-
- if len(zone.MailForwards) == 0 {
- zone.MailForwards = make([]MailForward, 0)
- }
-
- req, err := newJSONRequest(ctx, http.MethodPut, endpoint, zone)
- if err != nil {
- return err
- }
-
- return c.do(req, nil)
-}
-
-// ValidateZone validates DNS Zone.
-// https://docapi.eurodns.com/#/dnsprovider/checkdnszone
-func (c *Client) ValidateZone(ctx context.Context, domain string, zone *Zone) (*Zone, error) {
- endpoint := c.BaseURL.JoinPath(domain, "check")
-
- if len(zone.URLForwards) == 0 {
- zone.URLForwards = make([]URLForward, 0)
- }
-
- if len(zone.MailForwards) == 0 {
- zone.MailForwards = make([]MailForward, 0)
- }
-
- req, err := newJSONRequest(ctx, http.MethodPost, endpoint, zone)
- if err != nil {
- return nil, err
- }
-
- result := &Zone{}
-
- err = c.do(req, result)
- if err != nil {
- return nil, err
- }
-
- return result, nil
-}
-
-func (c *Client) do(req *http.Request, result any) error {
- req.Header.Set(HeaderAppID, c.appID)
- req.Header.Set(HeaderAPIKey, c.apiKey)
-
- resp, err := c.HTTPClient.Do(req)
- if err != nil {
- return errutils.NewHTTPDoError(req, err)
- }
-
- defer func() { _ = resp.Body.Close() }()
-
- if resp.StatusCode/100 != 2 {
- return parseError(req, resp)
- }
-
- if result == nil {
- return nil
- }
-
- raw, err := io.ReadAll(resp.Body)
- if err != nil {
- return errutils.NewReadResponseError(req, resp.StatusCode, err)
- }
-
- err = json.Unmarshal(raw, result)
- if err != nil {
- return errutils.NewUnmarshalError(req, resp.StatusCode, raw, err)
- }
-
- return nil
-}
-
-func newJSONRequest(ctx context.Context, method string, endpoint *url.URL, payload any) (*http.Request, error) {
- buf := new(bytes.Buffer)
-
- if payload != nil {
- err := json.NewEncoder(buf).Encode(payload)
- if err != nil {
- return nil, fmt.Errorf("failed to create request JSON body: %w", err)
- }
- }
-
- req, err := http.NewRequestWithContext(ctx, method, endpoint.String(), buf)
- if err != nil {
- return nil, fmt.Errorf("unable to create request: %w", err)
- }
-
- req.Header.Set("Accept", "application/json")
-
- if payload != nil {
- req.Header.Set("Content-Type", "application/json")
- }
-
- return req, nil
-}
-
-func parseError(req *http.Request, resp *http.Response) error {
- raw, _ := io.ReadAll(resp.Body)
-
- var errAPI APIError
-
- err := json.Unmarshal(raw, &errAPI)
- if err != nil {
- return errutils.NewUnexpectedStatusCodeError(req, resp.StatusCode, raw)
- }
-
- return fmt.Errorf("%d: %w", resp.StatusCode, &errAPI)
-}
-
-const DefaultTTL = 600
-
-// TTLRounder rounds the given TTL in seconds to the next accepted value.
-// Accepted TTL values are: 600, 900, 1800,3600, 7200, 14400, 21600, 43200, 86400, 172800, 432000, 604800.
-func TTLRounder(ttl int) int {
- for _, validTTL := range []int{DefaultTTL, 900, 1800, 3600, 7200, 14400, 21600, 43200, 86400, 172800, 432000, 604800} {
- if ttl <= validTTL {
- return validTTL
- }
- }
-
- return DefaultTTL
-}
diff --git a/providers/dns/eurodns/internal/client_test.go b/providers/dns/eurodns/internal/client_test.go
deleted file mode 100644
index 68d1fda84..000000000
--- a/providers/dns/eurodns/internal/client_test.go
+++ /dev/null
@@ -1,310 +0,0 @@
-package internal
-
-import (
- "context"
- "net/http"
- "net/http/httptest"
- "net/url"
- "slices"
- "testing"
-
- "github.com/go-acme/lego/v4/platform/tester/servermock"
- "github.com/go-acme/lego/v4/providers/dns/internal/ptr"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func mockBuilder() *servermock.Builder[*Client] {
- return servermock.NewBuilder[*Client](
- func(server *httptest.Server) (*Client, error) {
- client, err := NewClient("abc", "secret")
- if err != nil {
- return nil, err
- }
-
- client.HTTPClient = server.Client()
- client.BaseURL, _ = url.Parse(server.URL)
-
- return client, nil
- },
- servermock.CheckHeader().
- WithJSONHeaders().
- With(HeaderAppID, "abc").
- With(HeaderAPIKey, "secret"),
- )
-}
-
-func TestClient_GetZone(t *testing.T) {
- client := mockBuilder().
- Route("GET /example.com",
- servermock.ResponseFromFixture("zone_get.json"),
- ).
- Build(t)
-
- zone, err := client.GetZone(context.Background(), "example.com")
- require.NoError(t, err)
-
- expected := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: slices.Concat([]Record{fakeARecord()}),
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- }
-
- assert.Equal(t, expected, zone)
-}
-
-func TestClient_GetZone_error(t *testing.T) {
- client := mockBuilder().
- Route("GET /example.com",
- servermock.ResponseFromFixture("error.json").
- WithStatusCode(http.StatusUnauthorized),
- ).
- Build(t)
-
- _, err := client.GetZone(context.Background(), "example.com")
- require.Error(t, err)
-
- require.EqualError(t, err, "401: INVALID_API_KEY: Invalid API Key")
-}
-
-func TestClient_SaveZone(t *testing.T) {
- client := mockBuilder().
- Route("PUT /example.com",
- servermock.Noop().
- WithStatusCode(http.StatusNoContent),
- servermock.CheckRequestJSONBodyFromFixture("zone_add.json"),
- ).
- Build(t)
-
- record := Record{
- Type: "TXT",
- Host: "_acme-challenge",
- RData: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: 600,
- }
-
- zone := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: []Record{fakeARecord(), record},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- }
-
- err := client.SaveZone(context.Background(), "example.com", zone)
- require.NoError(t, err)
-}
-
-func TestClient_SaveZone_emptyForwards(t *testing.T) {
- client := mockBuilder().
- Route("PUT /example.com",
- servermock.Noop().
- WithStatusCode(http.StatusNoContent),
- servermock.CheckRequestJSONBodyFromFixture("zone_add_empty_forwards.json"),
- ).
- Build(t)
-
- record := Record{
- Type: "TXT",
- Host: "_acme-challenge",
- RData: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: 600,
- }
-
- zone := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: slices.Concat([]Record{fakeARecord(), record}),
- }
-
- err := client.SaveZone(context.Background(), "example.com", zone)
- require.NoError(t, err)
-}
-
-func TestClient_SaveZone_error(t *testing.T) {
- client := mockBuilder().
- Route("PUT /example.com",
- servermock.ResponseFromFixture("error.json").
- WithStatusCode(http.StatusUnauthorized),
- ).
- Build(t)
-
- zone := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: []Record{fakeARecord()},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- }
-
- err := client.SaveZone(context.Background(), "example.com", zone)
- require.Error(t, err)
-
- require.EqualError(t, err, "401: INVALID_API_KEY: Invalid API Key")
-}
-
-func TestClient_ValidateZone(t *testing.T) {
- client := mockBuilder().
- Route("POST /example.com/check",
- servermock.ResponseFromFixture("zone_add_validate_ok.json"),
- servermock.CheckRequestJSONBodyFromFixture("zone_add.json"),
- ).
- Build(t)
-
- record := Record{
- Type: "TXT",
- Host: "_acme-challenge",
- RData: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: 600,
- }
-
- zone := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: []Record{fakeARecord(), record},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- }
-
- zone, err := client.ValidateZone(context.Background(), "example.com", zone)
- require.NoError(t, err)
-
- expected := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: []Record{fakeARecord(), record},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- Report: &Report{IsValid: true},
- }
-
- assert.Equal(t, expected, zone)
-}
-
-func TestClient_ValidateZone_report(t *testing.T) {
- client := mockBuilder().
- Route("POST /example.com/check",
- servermock.ResponseFromFixture("zone_add_validate_ko.json"),
- servermock.CheckRequestJSONBodyFromFixture("zone_add.json"),
- ).
- Build(t)
-
- record := Record{
- Type: "TXT",
- Host: "_acme-challenge",
- RData: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: 600,
- }
-
- zone := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: []Record{fakeARecord(), record},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- }
-
- zone, err := client.ValidateZone(context.Background(), "example.com", zone)
- require.NoError(t, err)
-
- expected := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: []Record{fakeARecord(), record},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- Report: fakeReport(),
- }
-
- assert.EqualError(t, zone.Report, `record error (ERROR): "120" is not a valid TTL, URL forward error (ERROR): string, mail forward error (ERROR): string, zone error (ERROR): string`)
-
- assert.Equal(t, expected, zone)
-}
-
-func TestClient_ValidateZone_error(t *testing.T) {
- client := mockBuilder().
- Route("POST /example.com/check",
- servermock.ResponseFromFixture("error.json").
- WithStatusCode(http.StatusUnauthorized),
- ).
- Build(t)
-
- zone := &Zone{
- Name: "example.com",
- DomainConnect: true,
- Records: []Record{fakeARecord()},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- }
-
- _, err := client.ValidateZone(context.Background(), "example.com", zone)
- require.Error(t, err)
-
- require.EqualError(t, err, "401: INVALID_API_KEY: Invalid API Key")
-}
-
-func fakeARecord() Record {
- return Record{
- ID: 1000,
- Type: "A",
- Host: "@",
- TTL: 600,
- RData: "string",
- Updated: ptr.Pointer(true),
- Locked: ptr.Pointer(true),
- IsDynDNS: ptr.Pointer(true),
- Proxy: "ON",
- }
-}
-
-func fakeURLForward() URLForward {
- return URLForward{
- ID: 2000,
- ForwardType: "FRAME",
- Host: "string",
- URL: "string",
- Title: "string",
- Keywords: "string",
- Description: "string",
- Updated: ptr.Pointer(true),
- }
-}
-
-func fakeMailForward() MailForward {
- return MailForward{
- ID: 3000,
- Source: "string",
- Destination: "string",
- Updated: ptr.Pointer(true),
- }
-}
-
-func fakeReport() *Report {
- return &Report{
- IsValid: false,
- RecordErrors: []RecordError{{
- Messages: []string{`"120" is not a valid TTL`},
- Severity: "ERROR",
- Record: fakeARecord(),
- }},
- URLForwardErrors: []URLForwardError{{
- Messages: []string{"string"},
- Severity: "ERROR",
- URLForward: fakeURLForward(),
- }},
- MailForwardErrors: []MailForwardError{{
- Messages: []string{"string"},
- MailForward: fakeMailForward(),
- Severity: "ERROR",
- }},
- ZoneErrors: []ZoneError{{
- Message: "string",
- Severity: "ERROR",
- Records: []Record{fakeARecord()},
- URLForwards: []URLForward{fakeURLForward()},
- MailForwards: []MailForward{fakeMailForward()},
- }},
- }
-}
diff --git a/providers/dns/eurodns/internal/fixtures/error.json b/providers/dns/eurodns/internal/fixtures/error.json
deleted file mode 100644
index 82a334598..000000000
--- a/providers/dns/eurodns/internal/fixtures/error.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "errors": [
- {
- "code": "INVALID_API_KEY",
- "title": "Invalid API Key"
- }
- ]
-}
diff --git a/providers/dns/eurodns/internal/fixtures/zone_add.json b/providers/dns/eurodns/internal/fixtures/zone_add.json
deleted file mode 100644
index db8142357..000000000
--- a/providers/dns/eurodns/internal/fixtures/zone_add.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": "example.com",
- "domainConnect": true,
- "records": [
- {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- },
- {
- "type": "TXT",
- "host": "_acme-challenge",
- "ttl": 600,
- "rdata": "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- "updated": null,
- "locked": null,
- "isDynDns": null
- }
- ],
- "urlForwards": [
- {
- "id": 2000,
- "forwardType": "FRAME",
- "host": "string",
- "url": "string",
- "title": "string",
- "keywords": "string",
- "description": "string",
- "updated": true
- }
- ],
- "mailForwards": [
- {
- "id": 3000,
- "source": "string",
- "destination": "string",
- "updated": true
- }
- ]
-}
diff --git a/providers/dns/eurodns/internal/fixtures/zone_add_empty_forwards.json b/providers/dns/eurodns/internal/fixtures/zone_add_empty_forwards.json
deleted file mode 100644
index 64f8530c9..000000000
--- a/providers/dns/eurodns/internal/fixtures/zone_add_empty_forwards.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "example.com",
- "domainConnect": true,
- "records": [
- {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- },
- {
- "type": "TXT",
- "host": "_acme-challenge",
- "ttl": 600,
- "rdata": "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- "updated": null,
- "locked": null,
- "isDynDns": null
- }
- ],
- "urlForwards": [],
- "mailForwards": []
-}
diff --git a/providers/dns/eurodns/internal/fixtures/zone_add_validate_ko.json b/providers/dns/eurodns/internal/fixtures/zone_add_validate_ko.json
deleted file mode 100644
index e07d42299..000000000
--- a/providers/dns/eurodns/internal/fixtures/zone_add_validate_ko.json
+++ /dev/null
@@ -1,139 +0,0 @@
-{
- "name": "example.com",
- "domainConnect": true,
- "records": [
- {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- },
- {
- "type": "TXT",
- "host": "_acme-challenge",
- "ttl": 600,
- "rdata": "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- "updated": null,
- "locked": null,
- "isDynDns": null
- }
- ],
- "urlForwards": [
- {
- "id": 2000,
- "forwardType": "FRAME",
- "host": "string",
- "url": "string",
- "title": "string",
- "keywords": "string",
- "description": "string",
- "updated": true
- }
- ],
- "mailForwards": [
- {
- "id": 3000,
- "source": "string",
- "destination": "string",
- "updated": true
- }
- ],
- "report": {
- "isValid": false,
- "recordErrors": [
- {
- "messages": [
- "\"120\" is not a valid TTL"
- ],
- "record": {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- },
- "severity": "ERROR"
- }
- ],
- "urlForwardErrors": [
- {
- "messages": [
- "string"
- ],
- "urlForward": {
- "id": 2000,
- "forwardType": "FRAME",
- "host": "string",
- "url": "string",
- "title": "string",
- "keywords": "string",
- "description": "string",
- "updated": true
- },
- "severity": "ERROR"
- }
- ],
- "mailForwardErrors": [
- {
- "messages": [
- "string"
- ],
- "mailForward": {
- "id": 3000,
- "source": "string",
- "destination": "string",
- "updated": true
- },
- "severity": "ERROR"
- }
- ],
- "zoneErrors": [
- {
- "message": "string",
- "records": [
- {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- }
- ],
- "urlForwards": [
- {
- "id": 2000,
- "forwardType": "FRAME",
- "host": "string",
- "url": "string",
- "title": "string",
- "keywords": "string",
- "description": "string",
- "updated": true
- }
- ],
- "mailForwards": [
- {
- "id": 3000,
- "source": "string",
- "destination": "string",
- "updated": true
- }
- ],
- "severity": "ERROR"
- }
- ]
- }
-}
diff --git a/providers/dns/eurodns/internal/fixtures/zone_add_validate_ok.json b/providers/dns/eurodns/internal/fixtures/zone_add_validate_ok.json
deleted file mode 100644
index ba0ddfefb..000000000
--- a/providers/dns/eurodns/internal/fixtures/zone_add_validate_ok.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "name": "example.com",
- "domainConnect": true,
- "records": [
- {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- },
- {
- "type": "TXT",
- "host": "_acme-challenge",
- "ttl": 600,
- "rdata": "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- "updated": null,
- "locked": null,
- "isDynDns": null
- }
- ],
- "urlForwards": [
- {
- "id": 2000,
- "forwardType": "FRAME",
- "host": "string",
- "url": "string",
- "title": "string",
- "keywords": "string",
- "description": "string",
- "updated": true
- }
- ],
- "mailForwards": [
- {
- "id": 3000,
- "source": "string",
- "destination": "string",
- "updated": true
- }
- ],
- "report": {
- "isValid": true
- }
-}
diff --git a/providers/dns/eurodns/internal/fixtures/zone_get.json b/providers/dns/eurodns/internal/fixtures/zone_get.json
deleted file mode 100644
index ebbc8593e..000000000
--- a/providers/dns/eurodns/internal/fixtures/zone_get.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "name": "example.com",
- "domainConnect": true,
- "records": [
- {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- }
- ],
- "urlForwards": [
- {
- "id": 2000,
- "forwardType": "FRAME",
- "host": "string",
- "url": "string",
- "title": "string",
- "keywords": "string",
- "description": "string",
- "updated": true
- }
- ],
- "mailForwards": [
- {
- "id": 3000,
- "source": "string",
- "destination": "string",
- "updated": true
- }
- ]
-}
diff --git a/providers/dns/eurodns/internal/fixtures/zone_remove.json b/providers/dns/eurodns/internal/fixtures/zone_remove.json
deleted file mode 100644
index ebbc8593e..000000000
--- a/providers/dns/eurodns/internal/fixtures/zone_remove.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "name": "example.com",
- "domainConnect": true,
- "records": [
- {
- "id": 1000,
- "type": "A",
- "host": "@",
- "ttl": 600,
- "rdata": "string",
- "updated": true,
- "locked": true,
- "isDynDns": true,
- "proxy": "ON"
- }
- ],
- "urlForwards": [
- {
- "id": 2000,
- "forwardType": "FRAME",
- "host": "string",
- "url": "string",
- "title": "string",
- "keywords": "string",
- "description": "string",
- "updated": true
- }
- ],
- "mailForwards": [
- {
- "id": 3000,
- "source": "string",
- "destination": "string",
- "updated": true
- }
- ]
-}
diff --git a/providers/dns/eurodns/internal/types.go b/providers/dns/eurodns/internal/types.go
deleted file mode 100644
index 891b02e14..000000000
--- a/providers/dns/eurodns/internal/types.go
+++ /dev/null
@@ -1,136 +0,0 @@
-package internal
-
-import (
- "fmt"
- "strings"
-)
-
-type APIError struct {
- Errors []Error `json:"errors"`
-}
-
-func (a *APIError) Error() string {
- var msg []string
-
- for _, e := range a.Errors {
- msg = append(msg, fmt.Sprintf("%s: %s", e.Code, e.Title))
- }
-
- return strings.Join(msg, ", ")
-}
-
-type Error struct {
- Code string `json:"code"`
- Title string `json:"title"`
-}
-
-type Zone struct {
- Name string `json:"name,omitempty"`
- DomainConnect bool `json:"domainConnect,omitempty"`
- Records []Record `json:"records"`
- URLForwards []URLForward `json:"urlForwards"`
- MailForwards []MailForward `json:"mailForwards"`
- Report *Report `json:"report,omitempty"`
-}
-
-type Record struct {
- ID int `json:"id,omitempty"`
- Type string `json:"type,omitempty"`
- Host string `json:"host,omitempty"`
- TTL int `json:"ttl,omitempty"`
- RData string `json:"rdata,omitempty"`
- Updated *bool `json:"updated"`
- Locked *bool `json:"locked"`
- IsDynDNS *bool `json:"isDynDns"`
- Proxy string `json:"proxy,omitempty"`
-}
-
-type URLForward struct {
- ID int `json:"id,omitempty"`
- ForwardType string `json:"forwardType,omitempty"`
- Host string `json:"host,omitempty"`
- URL string `json:"url,omitempty"`
- Title string `json:"title,omitempty"`
- Keywords string `json:"keywords,omitempty"`
- Description string `json:"description,omitempty"`
- Updated *bool `json:"updated,omitempty"`
-}
-
-type MailForward struct {
- ID int `json:"id,omitempty"`
- Source string `json:"source,omitempty"`
- Destination string `json:"destination,omitempty"`
- Updated *bool `json:"updated,omitempty"`
-}
-
-type Report struct {
- IsValid bool `json:"isValid,omitempty"`
- RecordErrors []RecordError `json:"recordErrors,omitempty"`
- URLForwardErrors []URLForwardError `json:"urlForwardErrors,omitempty"`
- MailForwardErrors []MailForwardError `json:"mailForwardErrors,omitempty"`
- ZoneErrors []ZoneError `json:"zoneErrors,omitempty"`
-}
-
-func (r *Report) Error() string {
- var msg []string
-
- for _, e := range r.RecordErrors {
- msg = append(msg, e.Error())
- }
-
- for _, e := range r.URLForwardErrors {
- msg = append(msg, e.Error())
- }
-
- for _, e := range r.MailForwardErrors {
- msg = append(msg, e.Error())
- }
-
- for _, e := range r.ZoneErrors {
- msg = append(msg, e.Error())
- }
-
- return strings.Join(msg, ", ")
-}
-
-type RecordError struct {
- Messages []string `json:"messages,omitempty"`
- Record Record `json:"record"`
- Severity string `json:"severity,omitempty"`
-}
-
-func (e *RecordError) Error() string {
- return fmt.Sprintf("record error (%s): %s", e.Severity, strings.Join(e.Messages, ", "))
-}
-
-type URLForwardError struct {
- Messages []string `json:"messages,omitempty"`
- URLForward URLForward `json:"urlForward"`
- Severity string `json:"severity,omitempty"`
-}
-
-func (e *URLForwardError) Error() string {
- return fmt.Sprintf("URL forward error (%s): %s", e.Severity, strings.Join(e.Messages, ", "))
-}
-
-type MailForwardError struct {
- Messages []string `json:"messages,omitempty"`
- MailForward MailForward `json:"mailForward"`
- Severity string `json:"severity,omitempty"`
-}
-
-func (e *MailForwardError) Error() string {
- return fmt.Sprintf("mail forward error (%s): %s", e.Severity, strings.Join(e.Messages, ", "))
-}
-
-type ZoneError struct {
- Message string `json:"message,omitempty"`
- Records []Record `json:"records,omitempty"`
- URLForwards []URLForward `json:"urlForwards,omitempty"`
- MailForwards []MailForward `json:"mailForwards,omitempty"`
- Severity string `json:"severity,omitempty"`
-}
-
-func (e *ZoneError) Error() string {
- return fmt.Sprintf("zone error (%s): %s", e.Severity, e.Message)
-}
diff --git a/providers/dns/excedo/excedo.go b/providers/dns/excedo/excedo.go
deleted file mode 100644
index ae9128b94..000000000
--- a/providers/dns/excedo/excedo.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Package excedo implements a DNS provider for solving the DNS-01 challenge using Excedo.
-package excedo
-
-import (
- "context"
- "errors"
- "fmt"
- "net/http"
- "strconv"
- "sync"
- "time"
-
- "github.com/go-acme/lego/v4/challenge"
- "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/excedo/internal"
- "github.com/go-acme/lego/v4/providers/dns/internal/clientdebug"
-)
-
-// Environment variables names.
-const (
- envNamespace = "EXCEDO_"
-
- EnvAPIURL = envNamespace + "API_URL"
- EnvAPIKey = envNamespace + "API_KEY"
-
- EnvTTL = envNamespace + "TTL"
- EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
- EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
- EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
-)
-
-var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
-
-// Config is used to configure the creation of the DNSProvider.
-type Config struct {
- APIURL string
- APIKey string
-
- PropagationTimeout time.Duration
- PollingInterval time.Duration
- TTL int
- HTTPClient *http.Client
-}
-
-// NewDefaultConfig returns a default configuration for the DNSProvider.
-func NewDefaultConfig() *Config {
- return &Config{
- TTL: env.GetOrDefaultInt(EnvTTL, 60),
- PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 5*time.Minute),
- PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, 10*time.Second),
- HTTPClient: &http.Client{
- Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
- },
- }
-}
-
-// DNSProvider implements the challenge.Provider interface.
-type DNSProvider struct {
- config *Config
- client *internal.Client
-
- recordsMu sync.Mutex
- records map[string]int64
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Excedo.
-func NewDNSProvider() (*DNSProvider, error) {
- values, err := env.Get(EnvAPIURL, EnvAPIKey)
- if err != nil {
- return nil, fmt.Errorf("excedo: %w", err)
- }
-
- config := NewDefaultConfig()
- config.APIURL = values[EnvAPIURL]
- config.APIKey = values[EnvAPIKey]
-
- return NewDNSProviderConfig(config)
-}
-
-// NewDNSProviderConfig return a DNSProvider instance configured for Excedo.
-func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
- if config == nil {
- return nil, errors.New("excedo: the configuration of the DNS provider is nil")
- }
-
- client, err := internal.NewClient(config.APIURL, config.APIKey)
- if err != nil {
- return nil, fmt.Errorf("excedo: %w", err)
- }
-
- if config.HTTPClient != nil {
- client.HTTPClient = config.HTTPClient
- }
-
- client.HTTPClient = clientdebug.Wrap(client.HTTPClient)
-
- return &DNSProvider{
- config: config,
- client: client,
- records: make(map[string]int64),
- }, nil
-}
-
-// Present creates a TXT record using the specified parameters.
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- ctx := context.Background()
-
- info := dns01.GetChallengeInfo(domain, keyAuth)
-
- authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
- if err != nil {
- return fmt.Errorf("excedo: could not find zone for domain %q: %w", domain, err)
- }
-
- subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
- if err != nil {
- return fmt.Errorf("excedo: %w", err)
- }
-
- record := internal.Record{
- DomainName: dns01.UnFqdn(authZone),
- Name: subDomain,
- Type: "TXT",
- Content: info.Value,
- TTL: strconv.Itoa(d.config.TTL),
- }
-
- recordID, err := d.client.AddRecord(ctx, record)
- if err != nil {
- return fmt.Errorf("excedo: add record: %w", err)
- }
-
- d.recordsMu.Lock()
- d.records[token] = recordID
- d.recordsMu.Unlock()
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- ctx := context.Background()
-
- info := dns01.GetChallengeInfo(domain, keyAuth)
-
- authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
- if err != nil {
- return fmt.Errorf("excedo: could not find zone for domain %q: %w", domain, err)
- }
-
- d.recordsMu.Lock()
- recordID, ok := d.records[token]
- d.recordsMu.Unlock()
-
- if !ok {
- return fmt.Errorf("excedo: unknown record ID for '%s'", info.EffectiveFQDN)
- }
-
- err = d.client.DeleteRecord(ctx, dns01.UnFqdn(authZone), strconv.FormatInt(recordID, 10))
- if err != nil {
- return fmt.Errorf("excedo: delete record: %w", err)
- }
-
- d.recordsMu.Lock()
- delete(d.records, token)
- d.recordsMu.Unlock()
-
- return nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS propagation.
-// Adjusting here to cope with spikes in propagation times.
-func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return d.config.PropagationTimeout, d.config.PollingInterval
-}
diff --git a/providers/dns/excedo/excedo.toml b/providers/dns/excedo/excedo.toml
deleted file mode 100644
index 9f9874c62..000000000
--- a/providers/dns/excedo/excedo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-Name = "Excedo"
-Description = ''''''
-URL = "https://excedo.se/"
-Code = "excedo"
-Since = "v4.33.0"
-
-Example = '''
-EXCEDO_API_KEY=your-api-key \
-EXCEDO_API_URL=your-base-url \
-lego --dns excedo -d '*.example.com' -d example.com run
-'''
-
-[Configuration]
- [Configuration.Credentials]
- EXCEDO_API_KEY = "API key"
- EXCEDO_API_URL = "API base URL"
- [Configuration.Additional]
- EXCEDO_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 10)"
- EXCEDO_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 300)"
- EXCEDO_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)"
- EXCEDO_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)"
-
-[Links]
- API = "none"
diff --git a/providers/dns/excedo/excedo_test.go b/providers/dns/excedo/excedo_test.go
deleted file mode 100644
index f2350c035..000000000
--- a/providers/dns/excedo/excedo_test.go
+++ /dev/null
@@ -1,210 +0,0 @@
-package excedo
-
-import (
- "net/http/httptest"
- "testing"
-
- "github.com/go-acme/lego/v4/platform/tester"
- "github.com/go-acme/lego/v4/platform/tester/servermock"
- "github.com/stretchr/testify/require"
-)
-
-const envDomain = envNamespace + "DOMAIN"
-
-var envTest = tester.NewEnvTest(EnvAPIURL, EnvAPIKey).WithDomain(envDomain)
-
-func TestNewDNSProvider(t *testing.T) {
- testCases := []struct {
- desc string
- envVars map[string]string
- expected string
- }{
- {
- desc: "success",
- envVars: map[string]string{
- EnvAPIURL: "https://example.com",
- EnvAPIKey: "secret",
- },
- },
- {
- desc: "missing the API key",
- envVars: map[string]string{
- EnvAPIURL: "https://example.com",
- EnvAPIKey: "",
- },
- expected: "excedo: some credentials information are missing: EXCEDO_API_KEY",
- },
- {
- desc: "missing the API URL",
- envVars: map[string]string{
- EnvAPIURL: "",
- EnvAPIKey: "secret",
- },
- expected: "excedo: some credentials information are missing: EXCEDO_API_URL",
- },
- {
- desc: "missing credentials",
- envVars: map[string]string{},
- expected: "excedo: some credentials information are missing: EXCEDO_API_URL,EXCEDO_API_KEY",
- },
- }
-
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- defer envTest.RestoreEnv()
-
- envTest.ClearEnv()
-
- envTest.Apply(test.envVars)
-
- p, err := NewDNSProvider()
-
- if test.expected == "" {
- require.NoError(t, err)
- require.NotNil(t, p)
- require.NotNil(t, p.config)
- require.NotNil(t, p.client)
- } else {
- require.EqualError(t, err, test.expected)
- }
- })
- }
-}
-
-func TestNewDNSProviderConfig(t *testing.T) {
- testCases := []struct {
- desc string
- apiURL string
- apiKey string
- expected string
- }{
- {
- desc: "success",
- apiURL: "https://example.com",
- apiKey: "secret",
- },
- {
- desc: "missing the API key",
- apiURL: "https://example.com",
- expected: "excedo: credentials missing",
- },
- {
- desc: "missing the API URL",
- apiKey: "secret",
- expected: "excedo: credentials missing",
- },
- {
- desc: "missing credentials",
- expected: "excedo: credentials missing",
- },
- }
-
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- config := NewDefaultConfig()
- config.APIURL = test.apiURL
- config.APIKey = test.apiKey
-
- p, err := NewDNSProviderConfig(config)
-
- if test.expected == "" {
- require.NoError(t, err)
- require.NotNil(t, p)
- require.NotNil(t, p.config)
- require.NotNil(t, p.client)
- } else {
- require.EqualError(t, err, test.expected)
- }
- })
- }
-}
-
-func TestLivePresent(t *testing.T) {
- if !envTest.IsLiveTest() {
- t.Skip("skipping live test")
- }
-
- envTest.RestoreEnv()
-
- provider, err := NewDNSProvider()
- require.NoError(t, err)
-
- err = provider.Present(envTest.GetDomain(), "", "123d==")
- require.NoError(t, err)
-}
-
-func TestLiveCleanUp(t *testing.T) {
- if !envTest.IsLiveTest() {
- t.Skip("skipping live test")
- }
-
- envTest.RestoreEnv()
-
- provider, err := NewDNSProvider()
- require.NoError(t, err)
-
- err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
- require.NoError(t, err)
-}
-
-func mockBuilder() *servermock.Builder[*DNSProvider] {
- return servermock.NewBuilder(
- func(server *httptest.Server) (*DNSProvider, error) {
- config := NewDefaultConfig()
- config.APIURL = server.URL
- config.APIKey = "secret"
- config.HTTPClient = server.Client()
-
- p, err := NewDNSProviderConfig(config)
- if err != nil {
- return nil, err
- }
-
- return p, nil
- },
- )
-}
-
-func TestDNSProvider_Present(t *testing.T) {
- provider := mockBuilder().
- Route("GET /authenticate/login/",
- servermock.ResponseFromInternal("login.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer secret"),
- ).
- Route("POST /dns/addrecord/",
- servermock.ResponseFromInternal("addrecord.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer session-token"),
- servermock.CheckForm().Strict().
- With("content", "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY").
- With("domainName", "example.com").
- With("name", "_acme-challenge").
- With("ttl", "60").
- With("type", "TXT"),
- ).
- Build(t)
-
- err := provider.Present("example.com", "abc", "123d==")
- require.NoError(t, err)
-}
-
-func TestDNSProvider_CleanUp(t *testing.T) {
- provider := mockBuilder().
- Route("GET /authenticate/login/",
- servermock.ResponseFromInternal("login.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer secret"),
- ).
- Route("POST /dns/deleterecord/",
- servermock.ResponseFromInternal("deleterecord.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer session-token"),
- ).
- Build(t)
-
- provider.records["abc"] = 19695822
-
- err := provider.CleanUp("example.com", "abc", "123d==")
- require.NoError(t, err)
-}
diff --git a/providers/dns/excedo/internal/client.go b/providers/dns/excedo/internal/client.go
deleted file mode 100644
index a5d8be88b..000000000
--- a/providers/dns/excedo/internal/client.go
+++ /dev/null
@@ -1,205 +0,0 @@
-package internal
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "mime/multipart"
- "net/http"
- "net/url"
- "sync"
- "time"
-
- "github.com/go-acme/lego/v4/challenge/dns01"
- "github.com/go-acme/lego/v4/providers/dns/internal/errutils"
- "github.com/go-acme/lego/v4/providers/dns/internal/useragent"
- querystring "github.com/google/go-querystring/query"
-)
-
-type responseChecker interface {
- Check() error
-}
-
-// Client the Excedo API client.
-type Client struct {
- apiKey string
-
- baseURL *url.URL
- HTTPClient *http.Client
-
- token *ExpirableToken
- muToken sync.Mutex
-}
-
-// NewClient creates a new Client.
-func NewClient(apiURL, apiKey string) (*Client, error) {
- if apiURL == "" || apiKey == "" {
- return nil, errors.New("credentials missing")
- }
-
- baseURL, err := url.Parse(apiURL)
- if err != nil {
- return nil, err
- }
-
- return &Client{
- apiKey: apiKey,
- baseURL: baseURL,
- HTTPClient: &http.Client{Timeout: 10 * time.Second},
- }, nil
-}
-
-func (c *Client) AddRecord(ctx context.Context, record Record) (int64, error) {
- payload, err := querystring.Values(record)
- if err != nil {
- return 0, err
- }
-
- endpoint := c.baseURL.JoinPath("/dns/addrecord/")
-
- req, err := newFormRequest(ctx, http.MethodPost, endpoint, payload)
- if err != nil {
- return 0, err
- }
-
- result := new(AddRecordResponse)
-
- err = c.doAuthenticated(ctx, req, result)
- if err != nil {
- return 0, err
- }
-
- return result.RecordID, nil
-}
-
-func (c *Client) DeleteRecord(ctx context.Context, zone, recordID string) error {
- endpoint := c.baseURL.JoinPath("/dns/deleterecord/")
-
- data := map[string]string{
- "domainname": dns01.UnFqdn(zone),
- "recordid": recordID,
- }
-
- req, err := newMultipartRequest(ctx, http.MethodPost, endpoint, data)
- if err != nil {
- return err
- }
-
- result := new(BaseResponse)
-
- err = c.doAuthenticated(ctx, req, result)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (c *Client) GetRecords(ctx context.Context, zone string) (map[string]Zone, error) {
- endpoint := c.baseURL.JoinPath("/dns/getrecords/")
-
- query := endpoint.Query()
- query.Set("domainname", zone)
-
- endpoint.RawQuery = query.Encode()
-
- req, err := newFormRequest(ctx, http.MethodGet, endpoint, nil)
- if err != nil {
- return nil, err
- }
-
- result := new(GetRecordsResponse)
-
- err = c.doAuthenticated(ctx, req, result)
- if err != nil {
- return nil, err
- }
-
- return result.DNS, nil
-}
-
-func (c *Client) do(req *http.Request, result responseChecker) error {
- useragent.SetHeader(req.Header)
-
- resp, err := c.HTTPClient.Do(req)
- if err != nil {
- return errutils.NewHTTPDoError(req, err)
- }
-
- defer func() { _ = resp.Body.Close() }()
-
- if resp.StatusCode/100 != 2 {
- raw, _ := io.ReadAll(resp.Body)
-
- return errutils.NewUnexpectedStatusCodeError(req, resp.StatusCode, raw)
- }
-
- if result == nil {
- return nil
- }
-
- raw, err := io.ReadAll(resp.Body)
- if err != nil {
- return errutils.NewReadResponseError(req, resp.StatusCode, err)
- }
-
- err = json.Unmarshal(raw, result)
- if err != nil {
- return errutils.NewUnmarshalError(req, resp.StatusCode, raw, err)
- }
-
- return result.Check()
-}
-
-func newMultipartRequest(ctx context.Context, method string, endpoint *url.URL, data map[string]string) (*http.Request, error) {
- buf := new(bytes.Buffer)
-
- writer := multipart.NewWriter(buf)
-
- for k, v := range data {
- err := writer.WriteField(k, v)
- if err != nil {
- return nil, err
- }
- }
-
- err := writer.Close()
- if err != nil {
- return nil, err
- }
-
- body := bytes.NewReader(buf.Bytes())
-
- req, err := http.NewRequestWithContext(ctx, method, endpoint.String(), body)
- if err != nil {
- return nil, fmt.Errorf("unable to create request: %w", err)
- }
-
- req.Header.Set("Content-Type", writer.FormDataContentType())
-
- return req, nil
-}
-
-func newFormRequest(ctx context.Context, method string, endpoint *url.URL, form url.Values) (*http.Request, error) {
- var body io.Reader
-
- if len(form) > 0 {
- body = bytes.NewReader([]byte(form.Encode()))
- } else {
- body = http.NoBody
- }
-
- req, err := http.NewRequestWithContext(ctx, method, endpoint.String(), body)
- if err != nil {
- return nil, fmt.Errorf("unable to create request: %w", err)
- }
-
- if method == http.MethodPost {
- req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- }
-
- return req, nil
-}
diff --git a/providers/dns/excedo/internal/client_test.go b/providers/dns/excedo/internal/client_test.go
deleted file mode 100644
index f4fd52c00..000000000
--- a/providers/dns/excedo/internal/client_test.go
+++ /dev/null
@@ -1,137 +0,0 @@
-package internal
-
-import (
- "net/http/httptest"
- "testing"
- "time"
-
- "github.com/go-acme/lego/v4/platform/tester/servermock"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func mockBuilder() *servermock.Builder[*Client] {
- return servermock.NewBuilder[*Client](
- func(server *httptest.Server) (*Client, error) {
- client, err := NewClient(server.URL, "secret")
- if err != nil {
- return nil, err
- }
-
- client.HTTPClient = server.Client()
-
- return client, nil
- },
- )
-}
-
-func TestClient_AddRecord(t *testing.T) {
- client := mockBuilder().
- Route("POST /dns/addrecord/",
- servermock.ResponseFromFixture("addrecord.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer session-token"),
- servermock.CheckForm().Strict().
- With("content", "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY").
- With("domainName", "example.com").
- With("name", "_acme-challenge").
- With("ttl", "60").
- With("type", "TXT"),
- ).
- Build(t)
-
- client.token = &ExpirableToken{
- Token: "session-token",
- Expires: time.Now().Add(6 * time.Hour),
- }
-
- record := Record{
- DomainName: "example.com",
- Name: "_acme-challenge",
- Type: "TXT",
- Content: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: "60",
- }
-
- recordID, err := client.AddRecord(t.Context(), record)
- require.NoError(t, err)
-
- assert.EqualValues(t, 19695822, recordID)
-}
-
-func TestClient_AddRecord_error(t *testing.T) {
- client := mockBuilder().
- Route("POST /dns/addrecord/",
- servermock.ResponseFromFixture("error.json"),
- ).
- Build(t)
-
- client.token = &ExpirableToken{
- Token: "session-token",
- Expires: time.Now().Add(6 * time.Hour),
- }
-
- record := Record{
- DomainName: "example.com",
- Name: "_acme-challenge",
- Type: "TXT",
- Content: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY",
- TTL: "60",
- }
-
- _, err := client.AddRecord(t.Context(), record)
- require.EqualError(t, err, "2003: Required parameter missing")
-}
-
-func TestClient_DeleteRecord(t *testing.T) {
- client := mockBuilder().
- Route("POST /dns/deleterecord/",
- servermock.ResponseFromFixture("deleterecord.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer session-token"),
- ).
- Build(t)
-
- client.token = &ExpirableToken{
- Token: "session-token",
- Expires: time.Now().Add(6 * time.Hour),
- }
-
- err := client.DeleteRecord(t.Context(), "example.com", "19695822")
- require.NoError(t, err)
-}
-
-func TestClient_GetRecords(t *testing.T) {
- client := mockBuilder().
- Route("GET /dns/getrecords/",
- servermock.ResponseFromFixture("getrecords.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer session-token"),
- servermock.CheckQueryParameter().Strict().
- With("domainname", "example.com"),
- ).
- Build(t)
-
- client.token = &ExpirableToken{
- Token: "session-token",
- Expires: time.Now().Add(6 * time.Hour),
- }
-
- zones, err := client.GetRecords(t.Context(), "example.com")
- require.NoError(t, err)
-
- expected := map[string]Zone{
- "example.com": {
- DNSType: "type",
- Records: []Record{{
- RecordID: "1234",
- Name: "_acme-challenge.example.com",
- Type: "TXT",
- Content: "txt-value",
- TTL: "60",
- }},
- },
- }
-
- assert.Equal(t, expected, zones)
-}
diff --git a/providers/dns/excedo/internal/fixtures/addrecord.json b/providers/dns/excedo/internal/fixtures/addrecord.json
deleted file mode 100644
index f1f7bf958..000000000
--- a/providers/dns/excedo/internal/fixtures/addrecord.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "code": 1000,
- "desc": "Command completed successfully",
- "recordid": 19695822,
- "session": {
- "accID": "1234",
- "usrID": "1234",
- "status": "active",
- "expire": {
- "date": "2026-03-10 19:03:18",
- "seconds": 5678
- }
- },
- "runtime": 0.2852
-}
diff --git a/providers/dns/excedo/internal/fixtures/deleterecord.json b/providers/dns/excedo/internal/fixtures/deleterecord.json
deleted file mode 100644
index 5c2431b1c..000000000
--- a/providers/dns/excedo/internal/fixtures/deleterecord.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "code": 1000,
- "desc": "Command completed successfully",
- "session": {
- "accID": "1234",
- "usrID": "1234",
- "status": "active",
- "expire": {
- "date": "2026-03-10 19:03:18",
- "seconds": 5678
- }
- },
- "runtime": 0.2852
-}
diff --git a/providers/dns/excedo/internal/fixtures/error.json b/providers/dns/excedo/internal/fixtures/error.json
deleted file mode 100644
index 5a24ec247..000000000
--- a/providers/dns/excedo/internal/fixtures/error.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "code": 2003,
- "desc": "Required parameter missing",
- "missing": [
- "domainname",
- "recordid"
- ],
- "session": {
- "accID": "1234",
- "usrID": "1234",
- "status": "active",
- "expire": {
- "date": "2026-03-10 19:03:18",
- "seconds": 5485
- }
- },
- "runtime": 0.0534
-}
diff --git a/providers/dns/excedo/internal/fixtures/getrecords.json b/providers/dns/excedo/internal/fixtures/getrecords.json
deleted file mode 100644
index 215a8abb2..000000000
--- a/providers/dns/excedo/internal/fixtures/getrecords.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "code": 1000,
- "desc": "Command completed successfully",
- "dns": {
- "example.com": {
- "dnstype": "type",
- "recordusage": {
- "used": 74
- },
- "records": [
- {
- "recordid": "1234",
- "name": "_acme-challenge.example.com",
- "type": "TXT",
- "content": "txt-value",
- "ttl": "60",
- "prio": null,
- "change_date": null
- }
- ]
- }
- }
-}
diff --git a/providers/dns/excedo/internal/fixtures/login.json b/providers/dns/excedo/internal/fixtures/login.json
deleted file mode 100644
index 2defb9843..000000000
--- a/providers/dns/excedo/internal/fixtures/login.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "code": 1000,
- "desc": "Command completed successfully",
- "parameters": {
- "token": "session-token"
- }
-}
diff --git a/providers/dns/excedo/internal/identity.go b/providers/dns/excedo/internal/identity.go
deleted file mode 100644
index 5c9ca119d..000000000
--- a/providers/dns/excedo/internal/identity.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package internal
-
-import (
- "context"
- "fmt"
- "net/http"
- "time"
-)
-
-type ExpirableToken struct {
- Token string
- Expires time.Time
-}
-
-func (t *ExpirableToken) IsExpired() bool {
- return time.Now().After(t.Expires)
-}
-
-func (c *Client) Login(ctx context.Context) (string, error) {
- endpoint := c.baseURL.JoinPath("/authenticate/login/")
-
- req, err := newFormRequest(ctx, http.MethodGet, endpoint, nil)
- if err != nil {
- return "", err
- }
-
- req.Header.Set("Authorization", "Bearer "+c.apiKey)
-
- result := new(LoginResponse)
-
- err = c.do(req, result)
- if err != nil {
- return "", err
- }
-
- if result.Code != 1000 && result.Code != 1300 {
- return "", fmt.Errorf("%d: %s", result.Code, result.Description)
- }
-
- return result.Parameters.Token, nil
-}
-
-func (c *Client) authenticate(ctx context.Context) (string, error) {
- c.muToken.Lock()
- defer c.muToken.Unlock()
-
- if c.token == nil || c.token.IsExpired() {
- token, err := c.Login(ctx)
- if err != nil {
- return "", err
- }
-
- c.token = &ExpirableToken{
- Token: token,
- Expires: time.Now().Add(2*time.Hour - time.Minute),
- }
-
- return token, nil
- }
-
- return c.token.Token, nil
-}
-
-func (c *Client) doAuthenticated(ctx context.Context, req *http.Request, result responseChecker) error {
- token, err := c.authenticate(ctx)
- if err != nil {
- return err
- }
-
- if token != "" {
- req.Header.Set("Authorization", "Bearer "+token)
- }
-
- return c.do(req, result)
-}
diff --git a/providers/dns/excedo/internal/identity_test.go b/providers/dns/excedo/internal/identity_test.go
deleted file mode 100644
index 86b7eb9d8..000000000
--- a/providers/dns/excedo/internal/identity_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package internal
-
-import (
- "testing"
-
- "github.com/go-acme/lego/v4/platform/tester/servermock"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func TestClient_Login(t *testing.T) {
- client := mockBuilder().
- Route("GET /authenticate/login/",
- servermock.ResponseFromFixture("login.json"),
- servermock.CheckHeader().
- WithAuthorization("Bearer secret"),
- ).
- Build(t)
-
- token, err := client.Login(t.Context())
- require.NoError(t, err)
-
- assert.Equal(t, "session-token", token)
-}
-
-func TestClient_Login_error(t *testing.T) {
- client := mockBuilder().
- Route("GET /authenticate/login/",
- servermock.ResponseFromFixture("error.json"),
- ).
- Build(t)
-
- _, err := client.Login(t.Context())
- require.EqualError(t, err, "2003: Required parameter missing")
-}
diff --git a/providers/dns/excedo/internal/types.go b/providers/dns/excedo/internal/types.go
deleted file mode 100644
index eb6ce8462..000000000
--- a/providers/dns/excedo/internal/types.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package internal
-
-import "fmt"
-
-type BaseResponse struct {
- Code int `json:"code"`
- Description string `json:"desc"`
-}
-
-func (r BaseResponse) Check() error {
- // Response codes:
- // - 1000: Command completed successfully
- // - 1300: Command completed successfully; no messages
- // - 2001: Command syntax error
- // - 2002: Command use error
- // - 2003: Required parameter missing
- // - 2004: Parameter value range error
- // - 2104: Billing failure
- // - 2200: Authentication error
- // - 2201: Authorization error
- // - 2303: Object does not exist
- // - 2304: Object status prohibits operation
- // - 2309: Object duplicate found
- // - 2400: Command failed
- // - 2500: Command failed; server closing connection
- if r.Code != 1000 && r.Code != 1300 {
- return fmt.Errorf("%d: %s", r.Code, r.Description)
- }
-
- return nil
-}
-
-type GetRecordsResponse struct {
- BaseResponse
-
- DNS map[string]Zone `json:"dns"`
-}
-
-type Zone struct {
- DNSType string `json:"dnstype"`
- Records []Record `json:"records"`
-}
-
-type Record struct {
- DomainName string `json:"domainName,omitempty" url:"domainName,omitempty"`
- RecordID string `json:"recordid,omitempty" url:"recordid,omitempty"`
- Name string `json:"name,omitempty" url:"name,omitempty"`
- Type string `json:"type,omitempty" url:"type,omitempty"`
- Content string `json:"content,omitempty" url:"content,omitempty"`
- TTL string `json:"ttl,omitempty" url:"ttl,omitempty"`
-}
-
-type AddRecordResponse struct {
- BaseResponse
-
- RecordID int64 `json:"recordid"`
-}
-
-type LoginResponse struct {
- BaseResponse
-
- Parameters struct {
- Token string `json:"token"`
- } `json:"parameters"`
-}
diff --git a/providers/dns/gigahostno/internal/client_test.go b/providers/dns/gigahostno/internal/client_test.go
index 8d1298947..aac65bceb 100644
--- a/providers/dns/gigahostno/internal/client_test.go
+++ b/providers/dns/gigahostno/internal/client_test.go
@@ -38,25 +38,55 @@ func TestClient_GetZones(t *testing.T) {
expected := []Zone{
{
- ID: "123",
- Name: "example.com",
- NameDisplay: "example.com",
- Type: "NATIVE",
- Active: "1",
+ ID: "123",
+ Name: "example.com",
+ NameDisplay: "example.com",
+ Type: "NATIVE",
+ Active: "1",
+ Protected: "1",
+ IsRegistered: "1",
+ Updated: false,
+ CustomerID: "16030",
+ DomainRegistrar: "norid",
+ DomainStatus: "active",
+ DomainExpiryDate: "2026-11-23 15:17:38",
+ DomainAutoRenew: "1",
+ ExternalDNS: "0",
+ RecordCount: 4,
},
{
- ID: "226",
- Name: "example.org",
- NameDisplay: "example.org",
- Type: "NATIVE",
- Active: "1",
+ ID: "226",
+ Name: "example.org",
+ NameDisplay: "example.org",
+ Type: "NATIVE",
+ Active: "1",
+ Protected: "1",
+ IsRegistered: "1",
+ Updated: false,
+ CustomerID: "16030",
+ DomainRegistrar: "norid",
+ DomainStatus: "active",
+ DomainExpiryDate: "2026-11-23 14:15:01",
+ DomainAutoRenew: "1",
+ ExternalDNS: "0",
+ RecordCount: 5,
},
{
- ID: "229",
- Name: "example.xn--zckzah",
- NameDisplay: "example.テスト",
- Type: "NATIVE",
- Active: "1",
+ ID: "229",
+ Name: "example.xn--zckzah",
+ NameDisplay: "example.テスト",
+ Type: "NATIVE",
+ Active: "1",
+ Protected: "1",
+ IsRegistered: "1",
+ Updated: false,
+ CustomerID: "16030",
+ DomainRegistrar: "norid",
+ DomainStatus: "active",
+ DomainExpiryDate: "2026-12-01 12:40:48",
+ DomainAutoRenew: "1",
+ ExternalDNS: "0",
+ RecordCount: 4,
},
}
diff --git a/providers/dns/gigahostno/internal/fixtures/zones.json b/providers/dns/gigahostno/internal/fixtures/zones.json
index d45b0ac49..f4d927335 100644
--- a/providers/dns/gigahostno/internal/fixtures/zones.json
+++ b/providers/dns/gigahostno/internal/fixtures/zones.json
@@ -30,7 +30,7 @@
"domain_dnssec_data": null,
"domain_protected_email": null,
"zone_created": "2025-11-23 16:17:29",
- "zone_updated": 1700000000,
+ "zone_updated": false,
"external_dns": "0",
"record_count": 4,
"zone_name_display": "example.com"
@@ -59,7 +59,7 @@
"domain_dnssec_data": null,
"domain_protected_email": null,
"zone_created": "2025-11-23 15:13:27",
- "zone_updated": 1700000000,
+ "zone_updated": false,
"external_dns": "0",
"record_count": 5,
"zone_name_display": "example.org"
@@ -88,7 +88,7 @@
"domain_dnssec_data": null,
"domain_protected_email": null,
"zone_created": "2025-11-23 16:37:15",
- "zone_updated": 1700000000,
+ "zone_updated": false,
"external_dns": "0",
"record_count": 4,
"zone_name_display": "example.\u30C6\u30B9\u30C8"
diff --git a/providers/dns/gigahostno/internal/types.go b/providers/dns/gigahostno/internal/types.go
index e998dc084..cbb7b8b23 100644
--- a/providers/dns/gigahostno/internal/types.go
+++ b/providers/dns/gigahostno/internal/types.go
@@ -26,11 +26,21 @@ type APIResponse[T any] struct {
}
type Zone struct {
- ID string `json:"zone_id,omitempty"`
- Name string `json:"zone_name,omitempty"`
- NameDisplay string `json:"zone_name_display,omitempty"`
- Type string `json:"zone_type,omitempty"`
- Active string `json:"zone_active,omitempty"`
+ ID string `json:"zone_id,omitempty"`
+ Name string `json:"zone_name,omitempty"`
+ NameDisplay string `json:"zone_name_display,omitempty"`
+ Type string `json:"zone_type,omitempty"`
+ Active string `json:"zone_active,omitempty"`
+ Protected string `json:"zone_protected,omitempty"`
+ IsRegistered string `json:"zone_is_registered,omitempty"`
+ Updated bool `json:"zone_updated,omitempty"`
+ CustomerID string `json:"cust_id,omitempty"`
+ DomainRegistrar string `json:"domain_registrar,omitempty"`
+ DomainStatus string `json:"domain_status,omitempty"`
+ DomainExpiryDate string `json:"domain_expiry_date,omitempty"`
+ DomainAutoRenew string `json:"domain_auto_renew,omitempty"`
+ ExternalDNS string `json:"external_dns,omitempty"`
+ RecordCount int `json:"record_count,omitempty"`
}
type Record struct {
diff --git a/providers/dns/internal/useragent/useragent.go b/providers/dns/internal/useragent/useragent.go
index 090c9109a..43e77b23d 100644
--- a/providers/dns/internal/useragent/useragent.go
+++ b/providers/dns/internal/useragent/useragent.go
@@ -15,7 +15,7 @@ const (
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
// values: detach|release
// NOTE: Update this with each tagged release.
- ourUserAgentComment = "detach"
+ ourUserAgentComment = "release"
)
// Get builds and returns the User-Agent string.
diff --git a/providers/dns/liara/internal/client.go b/providers/dns/liara/internal/client.go
index 95c39695b..93cdcf7c8 100644
--- a/providers/dns/liara/internal/client.go
+++ b/providers/dns/liara/internal/client.go
@@ -20,23 +20,17 @@ const defaultBaseURL = "https://dns-service.iran.liara.ir"
type Client struct {
baseURL *url.URL
httpClient *http.Client
-
- teamID string
}
// NewClient creates a new Client.
-func NewClient(hc *http.Client, teamID string) *Client {
+func NewClient(hc *http.Client) *Client {
baseURL, _ := url.Parse(defaultBaseURL)
if hc == nil {
hc = &http.Client{Timeout: 10 * time.Second}
}
- return &Client{
- httpClient: hc,
- baseURL: baseURL,
- teamID: teamID,
- }
+ return &Client{httpClient: hc, baseURL: baseURL}
}
// GetRecords gets the records of a domain.
@@ -44,7 +38,7 @@ func NewClient(hc *http.Client, teamID string) *Client {
func (c *Client) GetRecords(ctx context.Context, domainName string) ([]Record, error) {
endpoint := c.baseURL.JoinPath("api", "v1", "zones", domainName, "dns-records")
- req, err := c.newJSONRequest(ctx, http.MethodGet, endpoint, nil)
+ req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
@@ -79,7 +73,7 @@ func (c *Client) GetRecords(ctx context.Context, domainName string) ([]Record, e
func (c *Client) CreateRecord(ctx context.Context, domainName string, record Record) (*Record, error) {
endpoint := c.baseURL.JoinPath("api", "v1", "zones", domainName, "dns-records")
- req, err := c.newJSONRequest(ctx, http.MethodPost, endpoint, record)
+ req, err := newJSONRequest(ctx, http.MethodPost, endpoint, record)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
@@ -114,7 +108,7 @@ func (c *Client) CreateRecord(ctx context.Context, domainName string, record Rec
func (c *Client) GetRecord(ctx context.Context, domainName, recordID string) (*Record, error) {
endpoint := c.baseURL.JoinPath("api", "v1", "zones", domainName, "dns-records", recordID)
- req, err := c.newJSONRequest(ctx, http.MethodGet, endpoint, nil)
+ req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
@@ -149,7 +143,7 @@ func (c *Client) GetRecord(ctx context.Context, domainName, recordID string) (*R
func (c *Client) DeleteRecord(ctx context.Context, domainName, recordID string) error {
endpoint := c.baseURL.JoinPath("api", "v1", "zones", domainName, "dns-records", recordID)
- req, err := c.newJSONRequest(ctx, http.MethodDelete, endpoint, nil)
+ req, err := newJSONRequest(ctx, http.MethodDelete, endpoint, nil)
if err != nil {
return fmt.Errorf("create request: %w", err)
}
@@ -168,14 +162,7 @@ func (c *Client) DeleteRecord(ctx context.Context, domainName, recordID string)
return nil
}
-func (c *Client) newJSONRequest(ctx context.Context, method string, endpoint *url.URL, payload any) (*http.Request, error) {
- if c.teamID != "" {
- query := endpoint.Query()
- query.Set("teamID", c.teamID)
-
- endpoint.RawQuery = query.Encode()
- }
-
+func newJSONRequest(ctx context.Context, method string, endpoint *url.URL, payload any) (*http.Request, error) {
buf := new(bytes.Buffer)
if payload != nil {
diff --git a/providers/dns/liara/internal/client_test.go b/providers/dns/liara/internal/client_test.go
index b6d007046..57ac7e8b3 100644
--- a/providers/dns/liara/internal/client_test.go
+++ b/providers/dns/liara/internal/client_test.go
@@ -13,10 +13,10 @@ import (
const apiKey = "key"
-func mockBuilder(teamID string) *servermock.Builder[*Client] {
+func mockBuilder() *servermock.Builder[*Client] {
return servermock.NewBuilder[*Client](
func(server *httptest.Server) (*Client, error) {
- client := NewClient(OAuthStaticAccessToken(server.Client(), apiKey), teamID)
+ client := NewClient(OAuthStaticAccessToken(server.Client(), apiKey))
client.baseURL, _ = url.Parse(server.URL)
return client, nil
@@ -26,7 +26,7 @@ func mockBuilder(teamID string) *servermock.Builder[*Client] {
}
func TestClient_GetRecords(t *testing.T) {
- client := mockBuilder("").
+ client := mockBuilder().
Route("GET /api/v1/zones/example.com/dns-records", servermock.ResponseFromFixture("RecordsResponse.json")).
Build(t)
@@ -50,7 +50,7 @@ func TestClient_GetRecords(t *testing.T) {
}
func TestClient_GetRecord(t *testing.T) {
- client := mockBuilder("").
+ client := mockBuilder().
Route("GET /api/v1/zones/example.com/dns-records/123", servermock.ResponseFromFixture("RecordResponse.json")).
Build(t)
@@ -72,7 +72,7 @@ func TestClient_GetRecord(t *testing.T) {
}
func TestClient_CreateRecord(t *testing.T) {
- client := mockBuilder("").
+ client := mockBuilder().
Route("POST /api/v1/zones/example.com/dns-records",
servermock.ResponseFromFixture("RecordResponse.json").
WithStatusCode(http.StatusCreated),
@@ -108,47 +108,8 @@ func TestClient_CreateRecord(t *testing.T) {
assert.Equal(t, expected, record)
}
-func TestClient_CreateRecord_withTeamID(t *testing.T) {
- client := mockBuilder("123").
- Route("POST /api/v1/zones/example.com/dns-records",
- servermock.ResponseFromFixture("RecordResponse.json").
- WithStatusCode(http.StatusCreated),
- servermock.CheckRequestJSONBody(`{"name":"string","type":"string","ttl":3600,"contents":[{"text":"string"}]}`),
- servermock.CheckQueryParameter().Strict().With("teamID", "123"),
- ).
- Build(t)
-
- data := Record{
- Type: "string",
- Name: "string",
- Contents: []Content{
- {
- Text: "string",
- },
- },
- TTL: 3600,
- }
-
- record, err := client.CreateRecord(t.Context(), "example.com", data)
- require.NoError(t, err)
-
- expected := &Record{
- ID: "string",
- Type: "string",
- Name: "string",
- Contents: []Content{
- {
- Text: "string",
- },
- },
- TTL: 3600,
- }
-
- assert.Equal(t, expected, record)
-}
-
func TestClient_DeleteRecord(t *testing.T) {
- client := mockBuilder("").
+ client := mockBuilder().
Route("DELETE /api/v1/zones/example.com/dns-records/123",
servermock.Noop().
WithStatusCode(http.StatusNoContent)).
@@ -159,7 +120,7 @@ func TestClient_DeleteRecord(t *testing.T) {
}
func TestClient_DeleteRecord_NotFound_Response(t *testing.T) {
- client := mockBuilder("").
+ client := mockBuilder().
Route("DELETE /api/v1/zones/example.com/dns-records/123",
servermock.Noop().
WithStatusCode(http.StatusNotFound)).
@@ -170,7 +131,7 @@ func TestClient_DeleteRecord_NotFound_Response(t *testing.T) {
}
func TestClient_DeleteRecord_error(t *testing.T) {
- client := mockBuilder("").
+ client := mockBuilder().
Route("DELETE /api/v1/zones/example.com/dns-records/123",
servermock.ResponseFromFixture("error.json").
WithStatusCode(http.StatusUnauthorized)).
diff --git a/providers/dns/liara/liara.go b/providers/dns/liara/liara.go
index c7e403eed..b91b004cc 100644
--- a/providers/dns/liara/liara.go
+++ b/providers/dns/liara/liara.go
@@ -23,7 +23,6 @@ const (
envNamespace = "LIARA_"
EnvAPIKey = envNamespace + "API_KEY"
- EnvTeamID = envNamespace + "TEAM_ID"
EnvTTL = envNamespace + "TTL"
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
@@ -40,9 +39,7 @@ var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
// Config is used to configure the creation of the DNSProvider.
type Config struct {
- APIKey string
- TeamID string
-
+ APIKey string
TTL int
PropagationTimeout time.Duration
PollingInterval time.Duration
@@ -80,7 +77,6 @@ func NewDNSProvider() (*DNSProvider, error) {
config := NewDefaultConfig()
config.APIKey = values[EnvAPIKey]
- config.TeamID = env.GetOrFile(EnvTeamID)
return NewDNSProviderConfig(config)
}
@@ -116,7 +112,6 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
clientdebug.Wrap(
internal.OAuthStaticAccessToken(retryClient.StandardClient(), config.APIKey),
),
- config.TeamID,
)
return &DNSProvider{
diff --git a/providers/dns/liara/liara.toml b/providers/dns/liara/liara.toml
index f471de04e..4ed53ec75 100644
--- a/providers/dns/liara/liara.toml
+++ b/providers/dns/liara/liara.toml
@@ -13,7 +13,6 @@ lego --dns liara -d '*.example.com' -d example.com run
[Configuration.Credentials]
LIARA_API_KEY = "The API key"
[Configuration.Additional]
- LIARA_TEAM_ID = "The team ID to access services in a team"
LIARA_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)"
LIARA_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)"
LIARA_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)"
diff --git a/providers/dns/safedns/internal/client.go b/providers/dns/safedns/internal/client.go
index 628618032..51b12e99d 100644
--- a/providers/dns/safedns/internal/client.go
+++ b/providers/dns/safedns/internal/client.go
@@ -19,7 +19,7 @@ const defaultBaseURL = "https://api.ukfast.io/safedns/v1"
const authorizationHeader = "Authorization"
-// Client the ANS SafeDNS client.
+// Client the UKFast SafeDNS client.
type Client struct {
authToken string
diff --git a/providers/dns/safedns/safedns.go b/providers/dns/safedns/safedns.go
index 154cfc5ee..be8ca4fe6 100644
--- a/providers/dns/safedns/safedns.go
+++ b/providers/dns/safedns/safedns.go
@@ -1,4 +1,4 @@
-// Package safedns implements a DNS provider for solving the DNS-01 challenge using ANS SafeDNS.
+// Package safedns implements a DNS provider for solving the DNS-01 challenge using UKFast SafeDNS.
package safedns
import (
@@ -75,7 +75,7 @@ func NewDNSProvider() (*DNSProvider, error) {
return NewDNSProviderConfig(config)
}
-// NewDNSProviderConfig return a DNSProvider instance configured for ANS SafeDNS.
+// NewDNSProviderConfig return a DNSProvider instance configured for UKFast SafeDNS.
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, errors.New("safedns: supplied configuration was nil")
diff --git a/providers/dns/safedns/safedns.toml b/providers/dns/safedns/safedns.toml
index f387f2535..188db66a4 100644
--- a/providers/dns/safedns/safedns.toml
+++ b/providers/dns/safedns/safedns.toml
@@ -1,6 +1,6 @@
-Name = "ANS SafeDNS"
+Name = "UKFast SafeDNS"
Description = ''''''
-URL = "https://www.ans.co.uk/"
+URL = "https://www.ukfast.co.uk/dns-hosting.html"
Code = "safedns"
Since = "v4.6.0"
diff --git a/providers/dns/zz_gen_dns_providers.go b/providers/dns/zz_gen_dns_providers.go
index 9c4bc9e61..e1b2cc989 100644
--- a/providers/dns/zz_gen_dns_providers.go
+++ b/providers/dns/zz_gen_dns_providers.go
@@ -43,7 +43,6 @@ import (
"github.com/go-acme/lego/v4/providers/dns/constellix"
"github.com/go-acme/lego/v4/providers/dns/corenetworks"
"github.com/go-acme/lego/v4/providers/dns/cpanel"
- "github.com/go-acme/lego/v4/providers/dns/czechia"
"github.com/go-acme/lego/v4/providers/dns/ddnss"
"github.com/go-acme/lego/v4/providers/dns/derak"
"github.com/go-acme/lego/v4/providers/dns/desec"
@@ -68,8 +67,6 @@ import (
"github.com/go-acme/lego/v4/providers/dns/edgeone"
"github.com/go-acme/lego/v4/providers/dns/efficientip"
"github.com/go-acme/lego/v4/providers/dns/epik"
- "github.com/go-acme/lego/v4/providers/dns/eurodns"
- "github.com/go-acme/lego/v4/providers/dns/excedo"
"github.com/go-acme/lego/v4/providers/dns/exec"
"github.com/go-acme/lego/v4/providers/dns/exoscale"
"github.com/go-acme/lego/v4/providers/dns/f5xc"
@@ -276,8 +273,6 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return corenetworks.NewDNSProvider()
case "cpanel":
return cpanel.NewDNSProvider()
- case "czechia":
- return czechia.NewDNSProvider()
case "ddnss":
return ddnss.NewDNSProvider()
case "derak":
@@ -326,10 +321,6 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return efficientip.NewDNSProvider()
case "epik":
return epik.NewDNSProvider()
- case "eurodns":
- return eurodns.NewDNSProvider()
- case "excedo":
- return excedo.NewDNSProvider()
case "exec":
return exec.NewDNSProvider()
case "exoscale":