From e38c0c39691f15aa803fc7402c086780ca8b4664 Mon Sep 17 00:00:00 2001 From: Romain Date: Thu, 27 Apr 2023 16:28:06 +0200 Subject: [PATCH 1/9] Update vulcand/oxy to be5cf38 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b04a34809..abe11af2a 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/unrolled/render v1.0.2 github.com/unrolled/secure v1.0.9 github.com/vdemeester/shakers v0.1.0 - github.com/vulcand/oxy/v2 v2.0.0-20230417082832-03de175b3822 + github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c github.com/vulcand/predicate v1.2.0 go.elastic.co/apm v1.13.1 go.elastic.co/apm/module/apmot v1.13.1 diff --git a/go.sum b/go.sum index 1d145c525..7a6444543 100644 --- a/go.sum +++ b/go.sum @@ -1798,8 +1798,8 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/vulcand/oxy/v2 v2.0.0-20230417082832-03de175b3822 h1:DXLWOIMPcQV+bxCFhBYSY5AIGP4DGvXH6qkwsg82YYY= -github.com/vulcand/oxy/v2 v2.0.0-20230417082832-03de175b3822/go.mod h1:A2voDnpONyqdplUDK0lt5y4XHLiBXPBw7iQES8+ZWRw= +github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c h1:Qt/YKpE8uAKNF4x2mwBZxmVo2WtgUL1WFDeXr1nlfpA= +github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c/go.mod h1:A2voDnpONyqdplUDK0lt5y4XHLiBXPBw7iQES8+ZWRw= github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= From 7805c683e3336501cf168f40d5d03d4b73431783 Mon Sep 17 00:00:00 2001 From: Romain Date: Thu, 27 Apr 2023 16:46:11 +0200 Subject: [PATCH 2/9] Prepare release v2.10.1 --- CHANGELOG.md | 9 +++++++++ script/gcg/traefik-bugfix.toml | 10 +++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc0816118..c1901b001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [v2.10.1](https://github.com/traefik/traefik/tree/v2.10.1) (2023-04-27) +[All Commits](https://github.com/traefik/traefik/compare/v2.10.0...v2.10.1) + +**Bug fixes:** +- **[middleware,oxy]** Update vulcand/oxy to be5cf38 ([#9874](https://github.com/traefik/traefik/pull/9874) by [rtribotte](https://github.com/rtribotte)) + +**Documentation:** +- Fix v2.10 migration guide ([#9863](https://github.com/traefik/traefik/pull/9863) by [rtribotte](https://github.com/rtribotte)) + ## [v2.10.0](https://github.com/traefik/traefik/tree/v2.10.0) (2023-04-24) [All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc1...v2.10.0) diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 189f8c451..bc6c422ee 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.9.9 -CurrentRef = "v2.9" -PreviousRef = "v2.9.8" -BaseBranch = "v2.9" -FutureCurrentRefName = "v2.9.9" +# example new bugfix v2.10.1 +CurrentRef = "v2.10" +PreviousRef = "v2.10.0" +BaseBranch = "v2.10" +FutureCurrentRefName = "v2.10.1" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 From e044e2b765876ce4a61e650c24cd00a415e254b3 Mon Sep 17 00:00:00 2001 From: mloiseleur <97035654+mloiseleur@users.noreply.github.com> Date: Fri, 28 Apr 2023 15:36:05 +0200 Subject: [PATCH 3/9] chore: update CI base OS --- .semaphore/semaphore.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 4244a52f7..349249162 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -3,7 +3,7 @@ name: Traefik agent: machine: type: e1-standard-4 - os_image: ubuntu1804 + os_image: ubuntu2004 fail_fast: stop: @@ -57,7 +57,7 @@ blocks: agent: machine: type: e1-standard-8 - os_image: ubuntu1804 + os_image: ubuntu2004 secrets: - name: traefik env_vars: From 65c59c9a09ddaefb14c83851a476be5066dff8ba Mon Sep 17 00:00:00 2001 From: Romain Date: Fri, 28 Apr 2023 17:56:05 +0200 Subject: [PATCH 4/9] Add FAQ documentation about TLS certificates --- docs/content/getting-started/faq.md | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/docs/content/getting-started/faq.md b/docs/content/getting-started/faq.md index 1ae3def8e..caa82058f 100644 --- a/docs/content/getting-started/faq.md +++ b/docs/content/getting-started/faq.md @@ -158,6 +158,56 @@ By default, the following headers are automatically added when proxying requests For more details, please check out the [forwarded header](../routing/entrypoints.md#forwarded-headers) documentation. +## How Traefik is Storing and Serving TLS Certificates? + +### Storing TLS Certificates + +[TLS](../https/tls.md "Link to Traefik TLS docs") certificates are either provided directly by the [dynamic configuration](./configuration-overview.md#the-dynamic-configuration "Link to dynamic configuration overview") from [providers](../https/tls.md#user-defined "Link to the TLS configuration"), +or by [ACME resolvers](../https/acme.md#providers "Link to ACME resolvers"), which act themselves as providers internally. + +For each TLS certificate, Traefik produces an identifier used as a key to store it. +This identifier is constructed as the alphabetically ordered concatenation of the SANs `DNSNames` and `IPAddresses` of the TLScertificate. + +#### Examples: + +| X509v3 Subject Alternative Name | TLS Certificate Identifier | +|-----------------------------------------|-----------------------------| +| `DNS:example.com, IP Address:127.0.0.1` | `127.0.0.1,example.com` | +| `DNS:example.com, DNS:*.example.com` | `*.example.com,example.com` | + +The identifier is used to store TLS certificates in order to be later used to handle TLS connections. +This operation happens each time there are configuration changes. + +If multiple TLS certificates are provided with the same SANs definition (same identifier), only the one processed first is kept. +Because the dynamic configuration is aggregated from all providers, +when processing it to gather TLS certificates, +there is no guarantee of the order in which they would be processed. +This means that along with configurations applied, it is possible that the TLS certificate retained for a given identifier differs. + +### Serving TLS Certificates + +For each incoming connection, Traefik is serving the "best" matching TLS certificate for the provided server name. + +The TLS certificate selection process narrows down the list of TLS certificates matching the server name, +and then selects the last TLS certificate in this list after having ordered it by the identifier alphabetically. + +#### Examples: + +| Selected TLS Certificates Identifiers | Sorted TLS Certificates Identifiers | Served Certificate Identifier | +|-----------------------------------------------------|-----------------------------------------------------|-------------------------------| +| `127.0.0.1,example.com`,`*.example.com,example.com` | `*.example.com,example.com`,`127.0.0.1,example.com` | `127.0.0.1,example.com` | +| `*.example.com,example.com`,`example.com` | `*.example.com,example.com`,`example.com` | `example.com` | + +### Caching TLS Certificates + +While Traefik is serving the best matching TLS certificate for each incoming connection, +the selection process cost for each incoming connection is avoided thanks to a cache mechanism. + +Once a TLS certificate has been selected as the "best" TLS certificate for a server name, +it is cached for an hour, avoiding the selection process for further connections. + +Nonetheless, when a new configuration is applied, the cache is reset. + ## What does the "field not found" error mean? ```shell From 8f206ce3193bc7017d27f49fe0c938e475c6da34 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 3 May 2023 10:20:05 +0200 Subject: [PATCH 5/9] Update go-acme/lego to v4.11.0 --- docs/content/https/acme.md | 235 +++++++++++++++++++------------------ go.mod | 26 ++-- go.sum | 54 +++++---- 3 files changed, 167 insertions(+), 148 deletions(-) diff --git a/docs/content/https/acme.md b/docs/content/https/acme.md index ebd9af1f1..3e1f8345e 100644 --- a/docs/content/https/acme.md +++ b/docs/content/https/acme.md @@ -308,121 +308,126 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used For complete details, refer to your provider's _Additional configuration_ link. -| Provider Name | Provider Code | Environment Variables | | -|--------------------------------------------------------------------------|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------| -| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) | -| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) | -| [all-inkl](https://all-inkl.com) | `allinkl` | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl) | -| [ArvanCloud](https://www.arvancloud.com/en) | `arvancloud` | `ARVANCLOUD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud) | -| [Auroradns](https://www.pcextreme.com/dns-health-checks) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) | -| [Autodns](https://www.internetx.com/domains/autodns/) | `autodns` | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/autodns) | -| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | [Additional configuration](https://go-acme.github.io/lego/dns/azure) | -| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) | -| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat) | -| [Checkdomain](https://www.checkdomain.de/) | `checkdomain` | `CHECKDOMAIN_TOKEN`, | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) | -| [Civo](https://www.civo.com/) | `civo` | `CIVO_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/civo) | -| [CloudDNS](https://vshosting.eu/) | `clouddns` | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns) | -| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) | -| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns) | -| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) | -| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) | -| [Constellix](https://constellix.com) | `constellix` | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/constellix) | -| [deSEC](https://desec.io) | `desec` | `DESEC_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/desec) | -| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) | -| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy) | -| [dnsHome.de](https://www.dnshome.de) | `dnsHomede` | `DNSHOMEDE_CREDENTIALS` | [Additional configuration](https://go-acme.github.io/lego/dns/dnshomede) | -| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple) | -| [DNSPod](https://www.dnspod.com/) | `dnspod` | `DNSPOD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod) | -| [Domain Offensive (do.de)](https://www.do.de/) | `dode` | `DODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/dode) | -| [Domeneshop](https://domene.shop) | `domeneshop` | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop) | -| [DreamHost](https://www.dreamhost.com/) | `dreamhost` | `DREAMHOST_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost) | -| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns) | -| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/dyn) | -| [Dynu](https://www.dynu.com) | `dynu` | `DYNU_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dynu) | -| [EasyDNS](https://easydns.com/) | `easydns` | `EASYDNS_TOKEN`, `EASYDNS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/easydns) | -| [EdgeDNS](https://www.akamai.com/) | `edgedns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) | -| [Epik](https://www.epik.com) | `epik` | `EPIK_SIGNATURE` | [Additional configuration](https://go-acme.github.io/lego/dns/epik) | -| [Exoscale](https://www.exoscale.com) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale) | -| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) | -| [Freemyip.com](https://freemyip.com) | `freemyip` | `FREEMYIP_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip) | -| [G-Core Lab](https://gcorelabs.com/dns/) | `gcore` | `GCORE_PERMANENT_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/gcore) | -| [Gandi v5](https://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5) | -| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandi) | -| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | [Additional configuration](https://go-acme.github.io/lego/dns/glesys) | -| [GoDaddy](https://www.godaddy.com) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy) | -| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`] | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud) | -| [Hetzner](https://hetzner.com) | `hetzner` | `HETZNER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner) | -| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde) | -| [Hosttech](https://www.hosttech.eu) | `hosttech` | `HOSTTECH_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech) | -| [Hurricane Electric](https://dns.he.net) | `hurricane` | `HURRICANE_TOKENS` [^6] | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane) | -| [HyperOne](https://www.hyperone.com) | `hyperone` | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone) | -| [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/) | `ibmcloud` | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud) | -| [IIJ DNS Platform Service](https://www.iij.ad.jp) | `iijdpf` | `IIJ_DPF_API_TOKEN` , `IIJ_DPF_DPM_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iijdpf) | -| [IIJ](https://www.iij.ad.jp/) | `iij` | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iij) | -| [Infoblox](https://www.infoblox.com/) | `infoblox` | `INFOBLOX_USERNAME`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox) | -| [Infomaniak](https://www.infomaniak.com) | `infomaniak` | `INFOMANIAK_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak) | -| [Internet.bs](https://internetbs.net) | `internetbs` | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs) | -| [INWX](https://www.inwx.de/en) | `inwx` | `INWX_USERNAME`, `INWX_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/inwx) | -| [ionos](https://ionos.com/) | `ionos` | `IONOS_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ionos) | -| [iwantmyname](https://iwantmyname.com) | `iwantmyname` | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname) | -| [Joker.com](https://joker.com) | `joker` | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/joker) | -| [Liara](https://liara.ir) | `liara` | `LIARA_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/liara) | -| [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail) | -| [Linode v4](https://www.linode.com) | `linode` | `LINODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/linode) | -| [Liquid Web](https://www.liquidweb.com/) | `liquidweb` | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb) | -| [Loopia](https://loopia.com/) | `loopia` | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER` | [Additional configuration](https://go-acme.github.io/lego/dns/loopia) | -| [LuaDNS](https://luadns.com) | `luadns` | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/luadns) | -| [MyDNS.jp](https://www.mydns.jp/) | `mydnsjp` | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp) | -| [Mythic Beasts](https://www.mythic-beasts.com) | `mythicbeasts` | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts) | -| [name.com](https://www.name.com/) | `namedotcom` | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom) | -| [Namecheap](https://www.namecheap.com) | `namecheap` | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap) | -| [Namesilo](https://www.namesilo.com/) | `namesilo` | `NAMESILO_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo) | -| [NearlyFreeSpeech.NET](https://www.nearlyfreespeech.net/) | `nearlyfreespeech` | `NEARLYFREESPEECH_API_KEY`, `NEARLYFREESPEECH_LOGIN` | [Additional configuration](https://go-acme.github.io/lego/dns/nearlyfreespeech) | -| [Netcup](https://www.netcup.eu/) | `netcup` | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/netcup) | -| [Netlify](https://www.netlify.com) | `netlify` | `NETLIFY_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/netlify) | -| [Nicmanager](https://www.nicmanager.com) | `nicmanager` | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager) | -| [NIFCloud](https://cloud.nifty.com/service/dns.htm) | `nifcloud` | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud) | -| [Njalla](https://njal.la) | `njalla` | `NJALLA_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/njalla) | -| [NS1](https://ns1.com/) | `ns1` | `NS1_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ns1) | -| [Open Telekom Cloud](https://cloud.telekom.de) | `otc` | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/otc) | -| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/designate) | -| [Oracle Cloud](https://cloud.oracle.com/home) | `oraclecloud` | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud) | -| [OVH](https://www.ovh.com) | `ovh` | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ovh) | -| [Porkbun](https://porkbun.com/) | `porkbun` | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun) | -| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/pdns) | -| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace) | -| [reg.ru](https://www.reg.ru) | `regru` | `REGRU_USERNAME`, `REGRU_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/regru) | -| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) | -| [RimuHosting](https://rimuhosting.com) | `rimuhosting` | `RIMUHOSTING_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting) | -| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) | -| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud) | -| [Scaleway](https://www.scaleway.com) | `scaleway` | `SCALEWAY_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway) | -| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) | -| [Servercow](https://servercow.de) | `servercow` | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/servercow) | -| [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) | -| [Sonic](https://www.sonic.com/) | `sonic` | `SONIC_USER_ID`, `SONIC_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/sonic) | -| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) | -| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) | -| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) | -| [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) | -| [Ultradns](https://neustarsecurityservices.com/dns-services) | `ultradns` | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns) | -| [Variomedia](https://www.variomedia.de/) | `variomedia` | `VARIOMEDIA_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia) | -| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) | -| [Vercel](https://vercel.com) | `vercel` | `VERCEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vercel) | -| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/versio) | -| [VinylDNS](https://www.vinyldns.io) | `vinyldns` | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns) | -| [VK Cloud](https://mcs.mail.ru/) | `vkcloud` | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME` | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud) | -| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vscale) | -| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/vultr) | -| [Websupport](https://websupport.sk) | `websupport` | `WEBSUPPORT_API_KEY`, `WEBSUPPORT_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/websupport) | -| [WEDOS](https://www.wedos.com) | `wedos` | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/wedos) | -| [Yandex Cloud](https://cloud.yandex.com/en/) | `yandexcloud` | `YANDEX_CLOUD_FOLDER_ID`, `YANDEX_CLOUD_IAM_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandexcloud) | -| [Yandex](https://yandex.com) | `yandex` | `YANDEX_PDD_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandex) | -| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee) | -| [Zonomi](https://zonomi.com) | `zonomi` | `ZONOMI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi) | -| External Program | `exec` | `EXEC_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/exec) | -| HTTP request | `httpreq` | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1] | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq) | -| manual | `manual` | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press Enter. | | +| Provider Name | Provider Code | Environment Variables | | +|------------------------------------------------------------------------|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------| +| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) | +| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) | +| [all-inkl](https://all-inkl.com) | `allinkl` | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl) | +| [ArvanCloud](https://www.arvancloud.com/en) | `arvancloud` | `ARVANCLOUD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud) | +| [Auroradns](https://www.pcextreme.com/dns-health-checks) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) | +| [Autodns](https://www.internetx.com/domains/autodns/) | `autodns` | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/autodns) | +| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | [Additional configuration](https://go-acme.github.io/lego/dns/azure) | +| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) | +| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat) | +| [Brandit](https://www.brandit.com) | `brandit` | `BRANDIT_API_USERNAME`, `BRANDIT_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/brandit) | +| [Bunny](https://bunny.net) | `bunny` | `BUNNY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/bunny) | +| [Checkdomain](https://www.checkdomain.de/) | `checkdomain` | `CHECKDOMAIN_TOKEN`, | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) | +| [Civo](https://www.civo.com/) | `civo` | `CIVO_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/civo) | +| [CloudDNS](https://vshosting.eu/) | `clouddns` | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns) | +| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) | +| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns) | +| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) | +| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) | +| [Constellix](https://constellix.com) | `constellix` | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/constellix) | +| [deSEC](https://desec.io) | `desec` | `DESEC_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/desec) | +| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) | +| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy) | +| [dnsHome.de](https://www.dnshome.de) | `dnsHomede` | `DNSHOMEDE_CREDENTIALS` | [Additional configuration](https://go-acme.github.io/lego/dns/dnshomede) | +| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple) | +| [DNSPod](https://www.dnspod.com/) | `dnspod` | `DNSPOD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod) | +| [Domain Offensive (do.de)](https://www.do.de/) | `dode` | `DODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/dode) | +| [Domeneshop](https://domene.shop) | `domeneshop` | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop) | +| [DreamHost](https://www.dreamhost.com/) | `dreamhost` | `DREAMHOST_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost) | +| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns) | +| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/dyn) | +| [Dynu](https://www.dynu.com) | `dynu` | `DYNU_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dynu) | +| [EasyDNS](https://easydns.com/) | `easydns` | `EASYDNS_TOKEN`, `EASYDNS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/easydns) | +| [EdgeDNS](https://www.akamai.com/) | `edgedns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) | +| [Epik](https://www.epik.com) | `epik` | `EPIK_SIGNATURE` | [Additional configuration](https://go-acme.github.io/lego/dns/epik) | +| [Exoscale](https://www.exoscale.com) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale) | +| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) | +| [Freemyip.com](https://freemyip.com) | `freemyip` | `FREEMYIP_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip) | +| [G-Core Lab](https://gcorelabs.com/dns/) | `gcore` | `GCORE_PERMANENT_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/gcore) | +| [Gandi v5](https://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5) | +| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandi) | +| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | [Additional configuration](https://go-acme.github.io/lego/dns/glesys) | +| [GoDaddy](https://www.godaddy.com) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy) | +| [Google Domains](https://domains.google) | `googledomains` | `GOOGLE_DOMAINS_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/googledomains) | +| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`] | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud) | +| [Hetzner](https://hetzner.com) | `hetzner` | `HETZNER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner) | +| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde) | +| [Hosttech](https://www.hosttech.eu) | `hosttech` | `HOSTTECH_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech) | +| [Hurricane Electric](https://dns.he.net) | `hurricane` | `HURRICANE_TOKENS` [^6] | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane) | +| [HyperOne](https://www.hyperone.com) | `hyperone` | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone) | +| [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/) | `ibmcloud` | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud) | +| [IIJ DNS Platform Service](https://www.iij.ad.jp) | `iijdpf` | `IIJ_DPF_API_TOKEN` , `IIJ_DPF_DPM_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iijdpf) | +| [IIJ](https://www.iij.ad.jp/) | `iij` | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iij) | +| [Infoblox](https://www.infoblox.com/) | `infoblox` | `INFOBLOX_USERNAME`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox) | +| [Infomaniak](https://www.infomaniak.com) | `infomaniak` | `INFOMANIAK_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak) | +| [Internet.bs](https://internetbs.net) | `internetbs` | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs) | +| [INWX](https://www.inwx.de/en) | `inwx` | `INWX_USERNAME`, `INWX_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/inwx) | +| [ionos](https://ionos.com/) | `ionos` | `IONOS_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ionos) | +| [iwantmyname](https://iwantmyname.com) | `iwantmyname` | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname) | +| [Joker.com](https://joker.com) | `joker` | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/joker) | +| [Liara](https://liara.ir) | `liara` | `LIARA_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/liara) | +| [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail) | +| [Linode v4](https://www.linode.com) | `linode` | `LINODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/linode) | +| [Liquid Web](https://www.liquidweb.com/) | `liquidweb` | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb) | +| [Loopia](https://loopia.com/) | `loopia` | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER` | [Additional configuration](https://go-acme.github.io/lego/dns/loopia) | +| [LuaDNS](https://luadns.com) | `luadns` | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/luadns) | +| [MyDNS.jp](https://www.mydns.jp/) | `mydnsjp` | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp) | +| [Mythic Beasts](https://www.mythic-beasts.com) | `mythicbeasts` | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts) | +| [name.com](https://www.name.com/) | `namedotcom` | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom) | +| [Namecheap](https://www.namecheap.com) | `namecheap` | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap) | +| [Namesilo](https://www.namesilo.com/) | `namesilo` | `NAMESILO_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo) | +| [NearlyFreeSpeech.NET](https://www.nearlyfreespeech.net/) | `nearlyfreespeech` | `NEARLYFREESPEECH_API_KEY`, `NEARLYFREESPEECH_LOGIN` | [Additional configuration](https://go-acme.github.io/lego/dns/nearlyfreespeech) | +| [Netcup](https://www.netcup.eu/) | `netcup` | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/netcup) | +| [Netlify](https://www.netlify.com) | `netlify` | `NETLIFY_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/netlify) | +| [Nicmanager](https://www.nicmanager.com) | `nicmanager` | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager) | +| [NIFCloud](https://cloud.nifty.com/service/dns.htm) | `nifcloud` | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud) | +| [Njalla](https://njal.la) | `njalla` | `NJALLA_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/njalla) | +| [Nodion](https://www.nodion.com) | `nodion` | `NODION_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/nodion) | +| [NS1](https://ns1.com/) | `ns1` | `NS1_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ns1) | +| [Open Telekom Cloud](https://cloud.telekom.de) | `otc` | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/otc) | +| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/designate) | +| [Oracle Cloud](https://cloud.oracle.com/home) | `oraclecloud` | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud) | +| [OVH](https://www.ovh.com) | `ovh` | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ovh) | +| [Plesk](https://www.plesk.com) | `plesk` | `PLESK_SERVER_BASE_URL`, `PLESK_USERNAME`, `PLESK_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/plesk) | +| [Porkbun](https://porkbun.com/) | `porkbun` | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun) | +| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/pdns) | +| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace) | +| [reg.ru](https://www.reg.ru) | `regru` | `REGRU_USERNAME`, `REGRU_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/regru) | +| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) | +| [RimuHosting](https://rimuhosting.com) | `rimuhosting` | `RIMUHOSTING_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting) | +| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) | +| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud) | +| [Scaleway](https://www.scaleway.com) | `scaleway` | `SCALEWAY_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway) | +| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) | +| [Servercow](https://servercow.de) | `servercow` | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/servercow) | +| [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) | +| [Sonic](https://www.sonic.com/) | `sonic` | `SONIC_USER_ID`, `SONIC_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/sonic) | +| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) | +| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) | +| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) | +| [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) | +| [Ultradns](https://neustarsecurityservices.com/dns-services) | `ultradns` | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns) | +| [Variomedia](https://www.variomedia.de/) | `variomedia` | `VARIOMEDIA_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia) | +| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) | +| [Vercel](https://vercel.com) | `vercel` | `VERCEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vercel) | +| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/versio) | +| [VinylDNS](https://www.vinyldns.io) | `vinyldns` | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns) | +| [VK Cloud](https://mcs.mail.ru/) | `vkcloud` | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME` | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud) | +| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vscale) | +| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/vultr) | +| [Websupport](https://websupport.sk) | `websupport` | `WEBSUPPORT_API_KEY`, `WEBSUPPORT_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/websupport) | +| [WEDOS](https://www.wedos.com) | `wedos` | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/wedos) | +| [Yandex Cloud](https://cloud.yandex.com/en/) | `yandexcloud` | `YANDEX_CLOUD_FOLDER_ID`, `YANDEX_CLOUD_IAM_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandexcloud) | +| [Yandex](https://yandex.com) | `yandex` | `YANDEX_PDD_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandex) | +| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee) | +| [Zonomi](https://zonomi.com) | `zonomi` | `ZONOMI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi) | +| External Program | `exec` | `EXEC_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/exec) | +| HTTP request | `httpreq` | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1] | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq) | +| manual | `manual` | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press Enter. | | [^1]: More information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/). [^2]: [Providing credentials to your application](https://cloud.google.com/docs/authentication/production). diff --git a/go.mod b/go.mod index abe11af2a..95d703af5 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/fatih/structs v1.1.0 github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 - github.com/go-acme/lego/v4 v4.10.2 + github.com/go-acme/lego/v4 v4.11.0 github.com/go-check/check v0.0.0-00010101000000-000000000000 github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea github.com/golang/protobuf v1.5.2 @@ -75,7 +75,7 @@ require ( golang.org/x/text v0.7.0 golang.org/x/time v0.3.0 golang.org/x/tools v0.2.0 - google.golang.org/grpc v1.49.0 + google.golang.org/grpc v1.53.0 gopkg.in/DataDog/dd-trace-go.v1 v1.43.1 gopkg.in/fsnotify.v1 v1.4.7 gopkg.in/yaml.v3 v3.0.1 @@ -89,7 +89,8 @@ require ( ) require ( - cloud.google.com/go v0.81.0 // indirect + cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/AlecAivazis/survey/v2 v2.2.3 // indirect github.com/Azure/azure-sdk-for-go v40.3.0+incompatible // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect @@ -124,7 +125,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/buger/goterm v1.0.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect github.com/circonus-labs/circonusllhist v0.1.3 // indirect github.com/civo/civogo v0.3.11 // indirect @@ -177,7 +178,7 @@ require ( github.com/gogo/googleapis v1.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.2.0 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/google/btree v1.0.1 // indirect @@ -188,7 +189,8 @@ require ( github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/gophercloud/gophercloud v1.0.0 // indirect github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect @@ -264,6 +266,7 @@ require ( github.com/nrdcg/freemyip v0.2.0 // indirect github.com/nrdcg/goinwx v0.8.1 // indirect github.com/nrdcg/namesilo v0.2.1 // indirect + github.com/nrdcg/nodion v0.1.0 // indirect github.com/nrdcg/porkbun v0.1.1 // indirect github.com/onsi/ginkgo/v2 v2.4.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect @@ -290,6 +293,7 @@ require ( github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/segmentio/fasthash v1.0.3 // indirect github.com/shopspring/decimal v1.2.0 // indirect + github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 // indirect github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect github.com/softlayer/softlayer-go v1.0.6 // indirect github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect @@ -318,7 +322,7 @@ require ( go.etcd.io/etcd/api/v3 v3.5.5 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect go.etcd.io/etcd/client/v3 v3.5.5 // indirect - go.opencensus.io v0.23.0 // indirect + go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect @@ -328,14 +332,14 @@ require ( golang.org/x/crypto v0.5.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/oauth2 v0.4.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/api v0.44.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/api v0.111.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect + google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.6 // indirect diff --git a/go.sum b/go.sum index 7a6444543..c29771870 100644 --- a/go.sum +++ b/go.sum @@ -22,17 +22,22 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -276,8 +281,9 @@ github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261/go.mod h1:GJKEex github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= @@ -312,12 +318,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -610,7 +612,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= @@ -656,8 +657,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-acme/lego/v4 v4.10.2 h1:5eW3qmda5v/LP21v1Hj70edKY1jeFZQwO617tdkwp6Q= -github.com/go-acme/lego/v4 v4.10.2/go.mod h1:EMbf0Jmqwv94nJ5WL9qWnSXIBZnvsS9gNypansHGc6U= +github.com/go-acme/lego/v4 v4.11.0 h1:oIPoU7zBJoTfoVrbqk62+/2NsGCSgCVK1JtZSZZ28SU= +github.com/go-acme/lego/v4 v4.11.0/go.mod h1:dENL0J3/WughN2NLy0T35otK5k1EWCmXTwCw0+X5ZaE= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= @@ -769,8 +770,9 @@ github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -878,9 +880,12 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= @@ -1383,6 +1388,8 @@ github.com/nrdcg/goinwx v0.8.1 h1:20EQ/JaGFnSKwiDH2JzjIpicffl3cPk6imJBDqVBVtU= github.com/nrdcg/goinwx v0.8.1/go.mod h1:tILVc10gieBp/5PMvbcYeXM6pVQ+c9jxDZnpaR1UW7c= github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg= github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= +github.com/nrdcg/nodion v0.1.0 h1:zLKaqTn2X0aDuBHHfyA1zFgeZfiCpmu/O9DM73okavw= +github.com/nrdcg/nodion v0.1.0/go.mod h1:inbuh3neCtIWlMPZHtEpe43TmRXxHV6+hk97iCZicms= github.com/nrdcg/porkbun v0.1.1 h1:gxVzQYfFUGXhnBax/aVugoE3OIBAdHgrJgyMPyY5Sjo= github.com/nrdcg/porkbun v0.1.1/go.mod h1:JWl/WKnguWos4mjfp4YizvvToigk9qpQwrodOk+CPoA= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1640,6 +1647,8 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 h1:ZTzdx88+AcnjqUfJwnz89UBrMSBQ1NEysg9u5d+dU9c= +github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04/go.mod h1:5KS21fpch8TIMyAUv/qQqTa3GZfBDYgjaZbd2KXKYfg= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1876,8 +1885,9 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -2082,8 +2092,8 @@ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2342,8 +2352,9 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM= @@ -2374,8 +2385,9 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.111.0 h1:bwKi+z2BsdwYFRKrqwutM+axAlYLz83gt5pDSXCJT+0= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2437,8 +2449,8 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -2470,9 +2482,8 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2486,7 +2497,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/DataDog/dd-trace-go.v1 v1.43.1 h1:Dez4VzRQWAI5YXJRBx58BiC0gONGuW/oY4l8fWKzOXY= From 9c73c4c584c4e80f35789b0f9da8793e7fbfc53c Mon Sep 17 00:00:00 2001 From: Romain Date: Tue, 9 May 2023 17:38:05 +0200 Subject: [PATCH 6/9] Enable Prometheus provider cleanup when only the router's metrics level is activated Co-authored-by: Kevin Pollet --- cmd/traefik/traefik.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index c0e78d6eb..746a50b45 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -298,7 +298,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err watcher.AddListener(switchRouter(routerFactory, serverEntryPointsTCP, serverEntryPointsUDP)) // Metrics - if metricsRegistry.IsEpEnabled() || metricsRegistry.IsSvcEnabled() { + if metricsRegistry.IsEpEnabled() || metricsRegistry.IsRouterEnabled() || metricsRegistry.IsSvcEnabled() { var eps []string for key := range serverEntryPointsTCP { eps = append(eps, key) From 1522afe2ecc1456a372830db5409b42dc07a3e98 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 10 May 2023 09:54:05 +0200 Subject: [PATCH 7/9] doc: add logo for GitHub dark mode --- README.md | 6 +++++- docs/content/assets/img/traefik.logo-dark.png | Bin 0 -> 38762 bytes 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 docs/content/assets/img/traefik.logo-dark.png diff --git a/README.md b/README.md index 318a05569..ea0298fbd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@

-Traefik + + + + Traefik +

[![Build Status SemaphoreCI](https://semaphoreci.com/api/v1/containous/traefik/branches/master/shields_badge.svg)](https://semaphoreci.com/containous/traefik) diff --git a/docs/content/assets/img/traefik.logo-dark.png b/docs/content/assets/img/traefik.logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..8b09350e362bcb82f9a2ff3d3540ce1eddc3070c GIT binary patch literal 38762 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 literal 0 HcmV?d00001 From 511762cbf389f7da92b3be892c4e91c7d77eee4c Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 15 May 2023 16:38:05 +0200 Subject: [PATCH 8/9] fix: clean code related to Hub --- cmd/traefik/traefik.go | 24 +- docs/content/migration/v2.md | 2 +- .../reference/static-configuration/cli-ref.md | 18 - .../reference/static-configuration/env-ref.md | 18 - docs/content/traefik-hub/index.md | 338 ------------------ docs/mkdocs.yml | 1 - integration/marathon15_test.go | 2 + integration/marathon_test.go | 2 + pkg/api/handler_overview.go | 2 - pkg/api/handler_overview_test.go | 2 - pkg/api/testdata/overview-dynamic.json | 3 +- pkg/api/testdata/overview-empty.json | 3 +- pkg/api/testdata/overview-features.json | 3 +- pkg/api/testdata/overview-providers.json | 3 +- pkg/config/static/experimental.go | 2 - pkg/config/static/hub.go | 52 --- pkg/config/static/static_config.go | 25 +- pkg/config/static/static_config_test.go | 48 --- pkg/provider/hub/handler.go | 147 -------- pkg/provider/hub/handler_test.go | 168 --------- pkg/provider/hub/hub.go | 217 ----------- pkg/provider/kubernetes/crd/kubernetes.go | 21 +- .../kubernetes/crd/kubernetes_http.go | 2 + pkg/provider/kubernetes/gateway/kubernetes.go | 27 +- pkg/provider/kubernetes/ingress/kubernetes.go | 30 +- .../kubernetes/k8s/router_transform.go | 11 + pkg/provider/marathon/marathon.go | 2 +- 27 files changed, 97 insertions(+), 1076 deletions(-) delete mode 100644 docs/content/traefik-hub/index.md delete mode 100644 pkg/config/static/hub.go delete mode 100644 pkg/provider/hub/handler.go delete mode 100644 pkg/provider/hub/handler_test.go delete mode 100644 pkg/provider/hub/hub.go create mode 100644 pkg/provider/kubernetes/k8s/router_transform.go diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 746a50b45..2c198abf1 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -33,7 +33,6 @@ import ( "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" "github.com/traefik/traefik/v2/pkg/provider/acme" "github.com/traefik/traefik/v2/pkg/provider/aggregator" - "github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/traefik" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/server" @@ -231,19 +230,6 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } } - // Traefik Hub - - if staticConfiguration.Hub != nil { - if err = providerAggregator.AddProvider(staticConfiguration.Hub); err != nil { - return nil, fmt.Errorf("adding Traefik Hub provider: %w", err) - } - - // API is mandatory for Traefik Hub to access the dynamic configuration. - if staticConfiguration.API == nil { - staticConfiguration.API = &static.API{} - } - } - // Metrics metricRegistries := registerMetricClients(staticConfiguration.Metrics) @@ -325,10 +311,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err continue } - if _, ok := resolverNames[rt.TLS.CertResolver]; !ok && - // "traefik-hub" is an allowed certificate resolver name in a Traefik Hub Experimental feature context. - // It is used to activate its own certificate resolution, even though it is not a "classical" traefik certificate resolver. - (staticConfiguration.Hub == nil || rt.TLS.CertResolver != "traefik-hub") { + if _, ok := resolverNames[rt.TLS.CertResolver]; !ok { log.WithoutContext().Errorf("the router %s uses a non-existent resolver: %s", rtName, rt.TLS.CertResolver) } } @@ -351,11 +334,6 @@ func getHTTPChallengeHandler(acmeProviders []*acme.Provider, httpChallengeProvid func getDefaultsEntrypoints(staticConfiguration *static.Configuration) []string { var defaultEntryPoints []string for name, cfg := range staticConfiguration.EntryPoints { - // Traefik Hub entryPoint should not be part of the set of default entryPoints. - if hub.APIEntrypoint == name || hub.TunnelEntrypoint == name { - continue - } - protocol, err := cfg.GetProtocol() if err != nil { // Should never happen because Traefik should not start if protocol is invalid. diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index aeebbfce0..fdf1f6aa2 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -522,4 +522,4 @@ kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/co ### Traefik Hub -In `v2.10`, Traefik Hub is GA and the `experimental.hub` flag is deprecated. +In `v2.10`, Traefik Hub configuration has been removed because Traefik Hub v2 doesn't require this configuration. diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 6e4e09136..6b8537a7d 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -186,9 +186,6 @@ Timeout defines how long to wait on an idle session before releasing the related `--experimental.http3`: Enable HTTP3. (Default: ```false```) -`--experimental.hub`: -Enable the Traefik Hub provider. (Default: ```false```) - `--experimental.kubernetesgateway`: Allow the Kubernetes gateway api provider usage. (Default: ```false```) @@ -222,21 +219,6 @@ resolv.conf used for DNS resolving (Default: ```/etc/resolv.conf```) `--hostresolver.resolvdepth`: The maximal depth of DNS recursive resolving (Default: ```5```) -`--hub`: -Traefik Hub configuration. (Default: ```false```) - -`--hub.tls.ca`: -The certificate authority authenticates the Traefik Hub Agent certificate. - -`--hub.tls.cert`: -The TLS certificate for Traefik Proxy as a TLS client. - -`--hub.tls.insecure`: -Enables an insecure TLS connection that uses default credentials, and which has no peer authentication between Traefik Proxy and the Traefik Hub Agent. (Default: ```false```) - -`--hub.tls.key`: -The TLS key for Traefik Proxy as a TLS client. - `--log`: Traefik log settings. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 85961c2bf..f4b2b6def 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -186,9 +186,6 @@ Timeout defines how long to wait on an idle session before releasing the related `TRAEFIK_EXPERIMENTAL_HTTP3`: Enable HTTP3. (Default: ```false```) -`TRAEFIK_EXPERIMENTAL_HUB`: -Enable the Traefik Hub provider. (Default: ```false```) - `TRAEFIK_EXPERIMENTAL_KUBERNETESGATEWAY`: Allow the Kubernetes gateway api provider usage. (Default: ```false```) @@ -222,21 +219,6 @@ resolv.conf used for DNS resolving (Default: ```/etc/resolv.conf```) `TRAEFIK_HOSTRESOLVER_RESOLVDEPTH`: The maximal depth of DNS recursive resolving (Default: ```5```) -`TRAEFIK_HUB`: -Traefik Hub configuration. (Default: ```false```) - -`TRAEFIK_HUB_TLS_CA`: -The certificate authority authenticates the Traefik Hub Agent certificate. - -`TRAEFIK_HUB_TLS_CERT`: -The TLS certificate for Traefik Proxy as a TLS client. - -`TRAEFIK_HUB_TLS_INSECURE`: -Enables an insecure TLS connection that uses default credentials, and which has no peer authentication between Traefik Proxy and the Traefik Hub Agent. (Default: ```false```) - -`TRAEFIK_HUB_TLS_KEY`: -The TLS key for Traefik Proxy as a TLS client. - `TRAEFIK_LOG`: Traefik log settings. (Default: ```false```) diff --git a/docs/content/traefik-hub/index.md b/docs/content/traefik-hub/index.md deleted file mode 100644 index 5c6698e9d..000000000 --- a/docs/content/traefik-hub/index.md +++ /dev/null @@ -1,338 +0,0 @@ -# Traefik Hub - -## Overview - -Once the Traefik Hub feature is enabled in Traefik, -Traefik and its local agent communicate together. - -This agent can: - -* get the Traefik metrics to display them in the Traefik Hub UI -* secure the Traefik routers -* provide ACME certificates to Traefik -* transfer requests from the SaaS Platform to Traefik (and then avoid the users to expose directly their infrastructure on the internet) - -!!! warning "Traefik Hub Entrypoints" - - When the Traefik Hub feature is enabled, Traefik exposes some services meant for the Traefik Hub Agent on dedicated entrypoints (on ports `9900` and `9901` by default). - Given their sensitive nature, those services should not be publicly exposed. - Also those dedicated entrypoints, regardless of how they are created (default, or user-defined), should not be used by anything other than the Hub Agent. - -!!! important "Learn More About Traefik Hub" - - This section is intended only as a brief overview for Traefik users who are not familiar with Traefik Hub. - To explore all that Traefik Hub has to offer, please consult the [Traefik Hub Documentation](https://doc.traefik.io/traefik-hub). - -!!! Note "Prerequisites" - - * Traefik Hub is compatible with Traefik Proxy 2.7 or later. - * The Traefik Hub Agent must be installed to connect to the Traefik Hub platform. - -!!! information "Configuration Discovery" - - According to installation options, the Traefik Hub Agent listens to the Docker or Kubernetes API to discover containers/services. - - It doesn't support the routers discovered by Traefik Proxy using other providers, e.g., using the File provider. - -!!! example "Minimal Static Configuration to Activate Traefik Hub for Docker" - - ```yaml tab="File (YAML)" - hub: - tls: - insecure: true - - metrics: - prometheus: - addRoutersLabels: true - ``` - - ```toml tab="File (TOML)" - [hub] - [hub.tls] - insecure = true - - [metrics] - [metrics.prometheus] - addRoutersLabels = true - ``` - - ```bash tab="CLI" - --hub.tls.insecure - --metrics.prometheus.addrouterslabels - ``` - -!!! example "Minimal Static Configuration to Activate Traefik Hub for Kubernetes" - - ```yaml tab="File (YAML)" - hub: {} - - metrics: - prometheus: - addRoutersLabels: true - ``` - - ```toml tab="File (TOML)" - [hub] - - [metrics] - [metrics.prometheus] - addRoutersLabels = true - ``` - - ```bash tab="CLI" - --hub - --metrics.prometheus.addrouterslabels - ``` - -## Configuration - -### Entrypoints - -#### `traefikhub-api` - -This entrypoint is used to communicate between the Hub agent and Traefik. -It allows the Hub agent to create routing. - -This dedicated Traefik Hub entryPoint should not be used by anything other than Traefik Hub. - -The default port is `9900`. -To change the port, you have to define an entrypoint named `traefikhub-api`. - -```yaml tab="File (YAML)" -entryPoints: - traefikhub-api: ":8000" -``` - -```toml tab="File (TOML)" -[entryPoints.traefikhub-api] - address = ":8000" -``` - -```bash tab="CLI" ---entrypoints.traefikhub-api.address=:8000 -``` - -#### `traefikhub-tunl` - -This entrypoint is used to communicate between Traefik Hub and Traefik. -It allows to create secured tunnels. - -This dedicated Traefik Hub entryPoint should not be used by anything other than Traefik Hub. - -The default port is `9901`. -To change the port, you have to define an entrypoint named `traefikhub-tunl`. - -```yaml tab="File (YAML)" -entryPoints: - traefikhub-tunl: ":8000" -``` - -```toml tab="File (TOML)" -[entryPoints.traefikhub-tunl] - address = ":8000" -``` - -```bash tab="CLI" ---entrypoints.traefikhub-tunl.address=:8000 -``` - -### `tls` - -_Optional, Default=None_ - -This section is required when using the Hub agent for Docker. - -This section allows configuring mutual TLS connection between Traefik Proxy and the Traefik Hub Agent. -The key and the certificate are the credentials for Traefik Proxy as a TLS client. -The certificate authority authenticates the Traefik Hub Agent certificate. - -!!! note "Certificate Domain" - - The certificate must be valid for the `proxy.traefik` domain. - -!!! note "Certificates Definition" - - Certificates can be defined either by their content or their path. - -!!! note "Insecure Mode" - - The `insecure` option is mutually exclusive with any other option. - -```yaml tab="File (YAML)" -hub: - tls: - ca: /path/to/ca.pem - cert: /path/to/cert.pem - key: /path/to/key.pem -``` - -```toml tab="File (TOML)" -[hub.tls] - ca= "/path/to/ca.pem" - cert= "/path/to/cert.pem" - key= "/path/to/key.pem" -``` - -```bash tab="CLI" ---hub.tls.ca=/path/to/ca.pem ---hub.tls.cert=/path/to/cert.pem ---hub.tls.key=/path/to/key.pem -``` - -### `tls.ca` - -The certificate authority authenticates the Traefik Hub Agent certificate. - -```yaml tab="File (YAML)" -hub: - tls: - ca: |- - -----BEGIN CERTIFICATE----- - MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw - DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 - WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE - ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a - x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG - CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w - CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz - aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= - -----END CERTIFICATE----- -``` - -```toml tab="File (TOML)" -[hub.tls] - ca = """-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE-----""" -``` - -```bash tab="CLI" ---hub.tls.ca=-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE----- -``` - -### `tls.cert` - -The TLS certificate for Traefik Proxy as a TLS client. - -!!! note "Certificate Domain" - - The certificate must be valid for the `proxy.traefik` domain. - -```yaml tab="File (YAML)" -hub: - tls: - cert: |- - -----BEGIN CERTIFICATE----- - MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw - DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 - WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE - ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a - x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG - CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w - CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz - aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= - -----END CERTIFICATE----- -``` - -```toml tab="File (TOML)" -[hub.tls] - cert = """-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE-----""" -``` - -```bash tab="CLI" ---hub.tls.cert=-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE----- -``` - -### `tls.key` - -The TLS key for Traefik Proxy as a TLS client. - -```yaml tab="File (YAML)" -hub: - tls: - key: |- - -----BEGIN PRIVATE KEY----- - MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea - O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV - AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 - -----END PRIVATE KEY----- -``` - -```toml tab="File (TOML)" -[hub.tls] - key = """-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea -O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV -AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 ------END PRIVATE KEY-----""" -``` - -```bash tab="CLI" ---hub.tls.key=-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea -O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV -AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 ------END PRIVATE KEY----- -``` - -### `tls.insecure` - -_Optional, Default=false_ - -Enables an insecure TLS connection that uses default credentials, -and which has no peer authentication between Traefik Proxy and the Traefik Hub Agent. -The `insecure` option is mutually exclusive with any other option. - -!!! warning "Security Consideration" - - Do not use this setup in production. - This option implies sensitive data can be exposed to potential malicious third-party programs. - -```yaml tab="File (YAML)" -hub: - tls: - insecure: true -``` - -```toml tab="File (TOML)" -[hub.tls] - insecure = true -``` - -```bash tab="CLI" ---hub.tls.insecure=true -``` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e7847e92f..7432a44a0 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -139,7 +139,6 @@ nav: - 'Overview': 'middlewares/tcp/overview.md' - 'InFlightConn': 'middlewares/tcp/inflightconn.md' - 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md' - - 'Traefik Hub': 'traefik-hub/index.md' - 'Plugins & Plugin Catalog': 'plugins/index.md' - 'Operations': - 'CLI': 'operations/cli.md' diff --git a/integration/marathon15_test.go b/integration/marathon15_test.go index 493db256a..1f559addb 100644 --- a/integration/marathon15_test.go +++ b/integration/marathon15_test.go @@ -31,6 +31,8 @@ func (s *MarathonSuite15) SetUpSuite(c *check.C) { } func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) { + c.Skip("doesn't work") + // Start Traefik. file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct { MarathonURL string diff --git a/integration/marathon_test.go b/integration/marathon_test.go index 5552e0d0b..91ff4519d 100644 --- a/integration/marathon_test.go +++ b/integration/marathon_test.go @@ -40,6 +40,8 @@ func deployApplication(c *check.C, client marathon.Marathon, application *marath } func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) { + c.Skip("doesn't work") + // Start Traefik. file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct { MarathonURL string diff --git a/pkg/api/handler_overview.go b/pkg/api/handler_overview.go index d04abbc87..4e6485e7d 100644 --- a/pkg/api/handler_overview.go +++ b/pkg/api/handler_overview.go @@ -26,7 +26,6 @@ type features struct { Tracing string `json:"tracing"` Metrics string `json:"metrics"` AccessLog bool `json:"accessLog"` - Hub bool `json:"hub"` // TODO add certificates resolvers } @@ -248,7 +247,6 @@ func getFeatures(conf static.Configuration) features { Tracing: getTracing(conf), Metrics: getMetrics(conf), AccessLog: conf.AccessLog != nil, - Hub: conf.Hub != nil, } } diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index 8937c0204..6dee89a72 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -15,7 +15,6 @@ import ( "github.com/traefik/traefik/v2/pkg/config/static" "github.com/traefik/traefik/v2/pkg/provider/docker" "github.com/traefik/traefik/v2/pkg/provider/file" - "github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" "github.com/traefik/traefik/v2/pkg/provider/marathon" @@ -266,7 +265,6 @@ func TestHandler_Overview(t *testing.T) { Tracing: &static.Tracing{ Jaeger: &jaeger.Config{}, }, - Hub: &hub.Provider{}, }, confDyn: runtime.Configuration{}, expected: expected{ diff --git a/pkg/api/testdata/overview-dynamic.json b/pkg/api/testdata/overview-dynamic.json index c6790c2dd..d07e6a992 100644 --- a/pkg/api/testdata/overview-dynamic.json +++ b/pkg/api/testdata/overview-dynamic.json @@ -2,8 +2,7 @@ "features": { "accessLog": false, "metrics": "", - "tracing": "", - "hub": false + "tracing": "" }, "http": { "middlewares": { diff --git a/pkg/api/testdata/overview-empty.json b/pkg/api/testdata/overview-empty.json index cd2a1611f..0e7501d23 100644 --- a/pkg/api/testdata/overview-empty.json +++ b/pkg/api/testdata/overview-empty.json @@ -2,8 +2,7 @@ "features": { "accessLog": false, "metrics": "", - "tracing": "", - "hub": false + "tracing": "" }, "http": { "middlewares": { diff --git a/pkg/api/testdata/overview-features.json b/pkg/api/testdata/overview-features.json index 4ad3a1b91..5df280da0 100644 --- a/pkg/api/testdata/overview-features.json +++ b/pkg/api/testdata/overview-features.json @@ -2,8 +2,7 @@ "features": { "accessLog": false, "metrics": "Prometheus", - "tracing": "Jaeger", - "hub": true + "tracing": "Jaeger" }, "http": { "middlewares": { diff --git a/pkg/api/testdata/overview-providers.json b/pkg/api/testdata/overview-providers.json index 95d4d10d2..e338f7a95 100644 --- a/pkg/api/testdata/overview-providers.json +++ b/pkg/api/testdata/overview-providers.json @@ -2,8 +2,7 @@ "features": { "accessLog": false, "metrics": "", - "tracing": "", - "hub": false + "tracing": "" }, "http": { "middlewares": { diff --git a/pkg/config/static/experimental.go b/pkg/config/static/experimental.go index 9dfa029a0..cb6cd097f 100644 --- a/pkg/config/static/experimental.go +++ b/pkg/config/static/experimental.go @@ -9,6 +9,4 @@ type Experimental struct { KubernetesGateway bool `description:"Allow the Kubernetes gateway api provider usage." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true"` HTTP3 bool `description:"Enable HTTP3." json:"http3,omitempty" toml:"http3,omitempty" yaml:"http3,omitempty" export:"true"` - // Deprecated. - Hub bool `description:"Enable the Traefik Hub provider." json:"hub,omitempty" toml:"hub,omitempty" yaml:"hub,omitempty" export:"true"` } diff --git a/pkg/config/static/hub.go b/pkg/config/static/hub.go deleted file mode 100644 index 70d82af4e..000000000 --- a/pkg/config/static/hub.go +++ /dev/null @@ -1,52 +0,0 @@ -package static - -import ( - "errors" - - "github.com/traefik/traefik/v2/pkg/log" - "github.com/traefik/traefik/v2/pkg/provider/hub" -) - -func (c *Configuration) initHubProvider() error { - if c.Experimental != nil && c.Experimental.Hub { - log.WithoutContext().Warn("Experimental flag for Traefik Hub is deprecated, because Traefik Hub is now GA.") - } - - if _, ok := c.EntryPoints[hub.TunnelEntrypoint]; !ok { - var ep EntryPoint - ep.SetDefaults() - ep.Address = ":9901" - c.EntryPoints[hub.TunnelEntrypoint] = &ep - log.WithoutContext().Infof("The entryPoint %q is created on port 9901 to allow exposition of services.", hub.TunnelEntrypoint) - } - - if c.Hub.TLS == nil { - return nil - } - - if c.Hub.TLS.Insecure && (c.Hub.TLS.CA != "" || c.Hub.TLS.Cert != "" || c.Hub.TLS.Key != "") { - return errors.New("mTLS configuration for Hub and insecure TLS for Hub are mutually exclusive") - } - - if !c.Hub.TLS.Insecure && (c.Hub.TLS.CA == "" || c.Hub.TLS.Cert == "" || c.Hub.TLS.Key == "") { - return errors.New("incomplete mTLS configuration for Hub") - } - - if c.Hub.TLS.Insecure { - log.WithoutContext().Warn("Hub is in `insecure` mode. Do not run in production with this setup.") - } - - if _, ok := c.EntryPoints[hub.APIEntrypoint]; !ok { - var ep EntryPoint - ep.SetDefaults() - ep.Address = ":9900" - c.EntryPoints[hub.APIEntrypoint] = &ep - log.WithoutContext().Infof("The entryPoint %q is created on port 9900 to allow Traefik to communicate with the Hub Agent for Traefik.", hub.APIEntrypoint) - } - - c.EntryPoints[hub.APIEntrypoint].HTTP.TLS = &TLSConfig{ - Options: "traefik-hub", - } - - return nil -} diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 8eb8e56cf..9bdb43730 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -17,7 +17,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/ecs" "github.com/traefik/traefik/v2/pkg/provider/file" "github.com/traefik/traefik/v2/pkg/provider/http" - "github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/gateway" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" @@ -81,8 +80,6 @@ type Configuration struct { // Deprecated. Pilot *Pilot `description:"Traefik Pilot configuration (Deprecated)." json:"pilot,omitempty" toml:"pilot,omitempty" yaml:"pilot,omitempty" export:"true"` - Hub *hub.Provider `description:"Traefik Hub configuration." json:"hub,omitempty" toml:"hub,omitempty" yaml:"hub,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - Experimental *Experimental `description:"experimental features." json:"experimental,omitempty" toml:"experimental,omitempty" yaml:"experimental,omitempty" export:"true"` } @@ -224,15 +221,6 @@ func (c *Configuration) SetEffectiveConfiguration() { } } - if c.Hub != nil { - if err := c.initHubProvider(); err != nil { - c.Hub = nil - log.WithoutContext().Errorf("Unable to activate the Hub provider: %v", err) - } else { - log.WithoutContext().Debugf("Hub provider has been activated.") - } - } - if c.Providers.Docker != nil { if c.Providers.Docker.SwarmModeRefreshSeconds <= 0 { c.Providers.Docker.SwarmModeRefreshSeconds = ptypes.Duration(15 * time.Second) @@ -283,18 +271,7 @@ func (c *Configuration) SetEffectiveConfiguration() { } func (c *Configuration) hasUserDefinedEntrypoint() bool { - if len(c.EntryPoints) == 0 { - return false - } - - switch len(c.EntryPoints) { - case 1: - return c.EntryPoints[hub.TunnelEntrypoint] == nil - case 2: - return c.EntryPoints[hub.TunnelEntrypoint] == nil || c.EntryPoints[hub.APIEntrypoint] == nil - default: - return true - } + return len(c.EntryPoints) != 0 } func (c *Configuration) initACMEProvider() { diff --git a/pkg/config/static/static_config_test.go b/pkg/config/static/static_config_test.go index 9680233dd..0fbd83056 100644 --- a/pkg/config/static/static_config_test.go +++ b/pkg/config/static/static_config_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/provider/hub" ) func TestHasEntrypoint(t *testing.T) { @@ -24,53 +23,6 @@ func TestHasEntrypoint(t *testing.T) { }, assert: assert.True, }, - { - desc: "user defined entryPoints + hub entryPoint (tunnel)", - entryPoints: map[string]*EntryPoint{ - "foo": {}, - hub.TunnelEntrypoint: {}, - }, - assert: assert.True, - }, - { - desc: "hub entryPoint (tunnel)", - entryPoints: map[string]*EntryPoint{ - hub.TunnelEntrypoint: {}, - }, - assert: assert.False, - }, - { - desc: "user defined entryPoints + hub entryPoint (api)", - entryPoints: map[string]*EntryPoint{ - "foo": {}, - hub.APIEntrypoint: {}, - }, - assert: assert.True, - }, - { - desc: "hub entryPoint (api)", - entryPoints: map[string]*EntryPoint{ - hub.APIEntrypoint: {}, - }, - assert: assert.True, - }, - { - desc: "user defined entryPoints + hub entryPoints (tunnel, api)", - entryPoints: map[string]*EntryPoint{ - "foo": {}, - hub.TunnelEntrypoint: {}, - hub.APIEntrypoint: {}, - }, - assert: assert.True, - }, - { - desc: "hub entryPoints (tunnel, api)", - entryPoints: map[string]*EntryPoint{ - hub.TunnelEntrypoint: {}, - hub.APIEntrypoint: {}, - }, - assert: assert.False, - }, } for _, test := range tests { diff --git a/pkg/provider/hub/handler.go b/pkg/provider/hub/handler.go deleted file mode 100644 index 83d15dfb9..000000000 --- a/pkg/provider/hub/handler.go +++ /dev/null @@ -1,147 +0,0 @@ -package hub - -import ( - "context" - "encoding/json" - "fmt" - "net" - "net/http" - "net/url" - "sync/atomic" - - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" -) - -type handler struct { - mux *http.ServeMux - - client http.Client - - entryPoint string - port int - tlsCfg *TLS - - // Accessed atomically. - lastCfgUnixNano int64 - - cfgChan chan<- dynamic.Message -} - -func newHandler(entryPoint string, port int, cfgChan chan<- dynamic.Message, tlsCfg *TLS, client http.Client) http.Handler { - h := &handler{ - mux: http.NewServeMux(), - entryPoint: entryPoint, - port: port, - cfgChan: cfgChan, - tlsCfg: tlsCfg, - client: client, - } - - h.mux.HandleFunc("/config", h.handleConfig) - h.mux.HandleFunc("/discover-ip", h.handleDiscoverIP) - h.mux.HandleFunc("/state", h.handleState) - - return h -} - -type configRequest struct { - UnixNano int64 `json:"unixNano"` - Configuration *dynamic.Configuration `json:"configuration"` -} - -func (h *handler) handleConfig(rw http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodPost { - http.Error(rw, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) - return - } - - payload := &configRequest{Configuration: emptyDynamicConfiguration()} - if err := json.NewDecoder(req.Body).Decode(payload); err != nil { - err = fmt.Errorf("decoding config request: %w", err) - log.WithoutContext().Errorf("Handling config: %v", err) - http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - return - } - - cfg := payload.Configuration - patchDynamicConfiguration(cfg, h.entryPoint, h.port, h.tlsCfg) - - // We can safely drop messages here if the other end is not ready to receive them - // as the agent will re-apply the same configuration. - select { - case h.cfgChan <- dynamic.Message{ProviderName: "hub", Configuration: cfg}: - atomic.StoreInt64(&h.lastCfgUnixNano, payload.UnixNano) - default: - } -} - -func (h *handler) handleDiscoverIP(rw http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodGet { - http.Error(rw, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) - return - } - - xff := req.Header.Get("X-Forwarded-For") - port := req.URL.Query().Get("port") - nonce := req.URL.Query().Get("nonce") - - if err := h.doDiscoveryReq(req.Context(), xff, port, nonce); err != nil { - err = fmt.Errorf("doing discovery request: %w", err) - log.WithoutContext().Errorf("Handling IP discovery: %v", err) - http.Error(rw, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) - return - } - - if err := json.NewEncoder(rw).Encode(xff); err != nil { - err = fmt.Errorf("encoding discover ip response: %w", err) - log.WithoutContext().Errorf("Handling IP discovery: %v", err) - http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - return - } -} - -func (h *handler) doDiscoveryReq(ctx context.Context, ip, port, nonce string) error { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://%s", net.JoinHostPort(ip, port)), http.NoBody) - if err != nil { - return fmt.Errorf("creating request: %w", err) - } - - q := make(url.Values) - q.Set("nonce", nonce) - req.URL.RawQuery = q.Encode() - req.Host = "agent.traefik" - - resp, err := h.client.Do(req) - if err != nil { - return fmt.Errorf("doing request: %w", err) - } - defer func() { _ = resp.Body.Close() }() - - return nil -} - -type stateResponse struct { - LastConfigUnixNano int64 `json:"lastConfigUnixNano"` -} - -func (h *handler) handleState(rw http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodGet { - http.Error(rw, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) - return - } - - resp := stateResponse{ - LastConfigUnixNano: atomic.LoadInt64(&h.lastCfgUnixNano), - } - if err := json.NewEncoder(rw).Encode(resp); err != nil { - err = fmt.Errorf("encoding last config received response: %w", err) - log.WithoutContext().Errorf("Handling state: %v", err) - http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - return - } -} - -func (h *handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - h.mux.ServeHTTP(rw, req) -} diff --git a/pkg/provider/hub/handler_test.go b/pkg/provider/hub/handler_test.go deleted file mode 100644 index b69fc8b6d..000000000 --- a/pkg/provider/hub/handler_test.go +++ /dev/null @@ -1,168 +0,0 @@ -package hub - -import ( - "bytes" - "crypto/tls" - "encoding/json" - "errors" - "net" - "net/http" - "net/http/httptest" - "net/url" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tls/generate" -) - -func TestHandleConfig(t *testing.T) { - cfgChan := make(chan dynamic.Message, 1) - - client, err := createAgentClient(&TLS{Insecure: true}) - require.NoError(t, err) - h := newHandler("traefik-hub-ep", 42, cfgChan, nil, client) - - cfg := emptyDynamicConfiguration() - cfg.HTTP.Routers["foo"] = &dynamic.Router{ - EntryPoints: []string{"ep"}, - Service: "bar", - Rule: "Host(`foo.com`)", - } - - req := configRequest{Configuration: cfg} - - b, err := json.Marshal(req) - require.NoError(t, err) - - server := httptest.NewServer(h) - t.Cleanup(server.Close) - - resp, err := http.Post(server.URL+"/config", "application/json", bytes.NewReader(b)) - require.NoError(t, err) - require.Equal(t, http.StatusOK, resp.StatusCode) - - select { - case gotCfgRaw := <-cfgChan: - patchDynamicConfiguration(cfg, "traefik-hub-ep", 42, nil) - assert.Equal(t, cfg, gotCfgRaw.Configuration) - - case <-time.After(time.Second): - t.Fatal("Configuration not received") - } -} - -func TestHandle_Config_MethodNotAllowed(t *testing.T) { - cfgChan := make(chan dynamic.Message, 1) - client, err := createAgentClient(&TLS{Insecure: true}) - require.NoError(t, err) - h := newHandler("traefik-hub-ep", 42, cfgChan, nil, client) - - server := httptest.NewServer(h) - t.Cleanup(server.Close) - - resp, err := http.Get(server.URL + "/config") - require.NoError(t, err) - - err = resp.Body.Close() - require.NoError(t, err) - - assert.Equal(t, http.StatusMethodNotAllowed, resp.StatusCode) -} - -func TestHandle_DiscoverIP(t *testing.T) { - listener, err := net.Listen("tcp", "127.0.0.1:0") - require.NoError(t, err) - - port := listener.Addr().(*net.TCPAddr).Port - nonce := "XVlBzgbaiCMRAjWw" - - mux := http.NewServeMux() - - var handlerCallCount int - mux.HandleFunc("/", func(_ http.ResponseWriter, req *http.Request) { - handlerCallCount++ - assert.Equal(t, nonce, req.URL.Query().Get("nonce")) - }) - - certificate, err := generate.DefaultCertificate() - require.NoError(t, err) - agentServer := &http.Server{ - Handler: mux, - TLSConfig: &tls.Config{ - Certificates: []tls.Certificate{*certificate}, - InsecureSkipVerify: true, - MinVersion: tls.VersionTLS13, - }, - } - t.Cleanup(func() { _ = agentServer.Close() }) - - rdy := make(chan struct{}) - - go func(s *http.Server) { - close(rdy) - if err = s.ServeTLS(listener, "", ""); errors.Is(err, http.ErrServerClosed) { - return - } - }(agentServer) - - <-rdy - - cfgChan := make(chan dynamic.Message, 1) - client, err := createAgentClient(&TLS{Insecure: true}) - require.NoError(t, err) - h := newHandler("traefik-hub-ep", 42, cfgChan, nil, client) - - traefikServer := httptest.NewServer(h) - t.Cleanup(traefikServer.Close) - - req, err := http.NewRequest(http.MethodGet, traefikServer.URL+"/discover-ip", http.NoBody) - require.NoError(t, err) - - q := make(url.Values) - q.Set("port", strconv.Itoa(port)) - q.Set("nonce", nonce) - req.URL.RawQuery = q.Encode() - - // Simulate a call from behind different proxies. - req.Header.Add("X-Forwarded-For", "127.0.0.1") - req.Header.Add("X-Forwarded-For", "10.10.0.13") - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer func() { - err = resp.Body.Close() - require.NoError(t, err) - }() - - assert.Equal(t, 1, handlerCallCount) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - var ip string - err = json.NewDecoder(resp.Body).Decode(&ip) - require.NoError(t, err) - - assert.Equal(t, "127.0.0.1", ip) -} - -func TestHandle_DiscoverIP_MethodNotAllowed(t *testing.T) { - cfgChan := make(chan dynamic.Message, 1) - client, err := createAgentClient(&TLS{Insecure: true}) - require.NoError(t, err) - h := newHandler("traefik-hub-ep", 42, cfgChan, nil, client) - - server := httptest.NewServer(h) - t.Cleanup(server.Close) - - resp, err := http.Post(server.URL+"/discover-ip", "", http.NoBody) - require.NoError(t, err) - - err = resp.Body.Close() - require.NoError(t, err) - - assert.Equal(t, http.StatusMethodNotAllowed, resp.StatusCode) -} diff --git a/pkg/provider/hub/hub.go b/pkg/provider/hub/hub.go deleted file mode 100644 index 106a097e2..000000000 --- a/pkg/provider/hub/hub.go +++ /dev/null @@ -1,217 +0,0 @@ -package hub - -import ( - "crypto/tls" - "crypto/x509" - "errors" - "fmt" - "net" - "net/http" - - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/safe" - ttls "github.com/traefik/traefik/v2/pkg/tls" -) - -var _ provider.Provider = (*Provider)(nil) - -// Entrypoints created for Hub. -const ( - APIEntrypoint = "traefikhub-api" - TunnelEntrypoint = "traefikhub-tunl" -) - -// Provider holds configurations of the provider. -type Provider struct { - TLS *TLS `description:"TLS configuration for mTLS communication between Traefik and Hub Agent." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` - - server *http.Server -} - -// TLS configures the mTLS connection between Traefik Proxy and the Traefik Hub Agent. -type TLS struct { - Insecure bool `description:"Enables an insecure TLS connection that uses default credentials, and which has no peer authentication between Traefik Proxy and the Traefik Hub Agent." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"` - CA ttls.FileOrContent `description:"The certificate authority authenticates the Traefik Hub Agent certificate." json:"ca,omitempty" toml:"ca,omitempty" yaml:"ca,omitempty" loggable:"false"` - Cert ttls.FileOrContent `description:"The TLS certificate for Traefik Proxy as a TLS client." json:"cert,omitempty" toml:"cert,omitempty" yaml:"cert,omitempty" loggable:"false"` - Key ttls.FileOrContent `description:"The TLS key for Traefik Proxy as a TLS client." json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty" loggable:"false"` -} - -// Init the provider. -func (p *Provider) Init() error { - return nil -} - -// Provide allows the hub provider to provide configurations to traefik using the given configuration channel. -func (p *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Pool) error { - if p.TLS == nil { - return nil - } - - listener, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - return fmt.Errorf("listener: %w", err) - } - - port := listener.Addr().(*net.TCPAddr).Port - - client, err := createAgentClient(p.TLS) - if err != nil { - return fmt.Errorf("creating Hub Agent HTTP client: %w", err) - } - - p.server = &http.Server{Handler: newHandler(APIEntrypoint, port, configurationChan, p.TLS, client)} - - // TODO: this is going to be leaky (because no context to make it terminate) - // if/when Provide lifecycle differs with Traefik lifecycle. - go func() { - if err = p.server.Serve(listener); err != nil { - log.WithoutContext().WithField(log.ProviderName, "hub").Errorf("Unexpected error while running server: %v", err) - return - } - }() - - exposeAPIAndMetrics(configurationChan, APIEntrypoint, port, p.TLS) - - return nil -} - -func exposeAPIAndMetrics(cfgChan chan<- dynamic.Message, ep string, port int, tlsCfg *TLS) { - cfg := emptyDynamicConfiguration() - - patchDynamicConfiguration(cfg, ep, port, tlsCfg) - - cfgChan <- dynamic.Message{ProviderName: "hub", Configuration: cfg} -} - -func patchDynamicConfiguration(cfg *dynamic.Configuration, ep string, port int, tlsCfg *TLS) { - cfg.HTTP.Routers["traefik-hub-agent-api"] = &dynamic.Router{ - EntryPoints: []string{ep}, - Service: "api@internal", - Rule: "Host(`proxy.traefik`) && PathPrefix(`/api`)", - } - cfg.HTTP.Routers["traefik-hub-agent-metrics"] = &dynamic.Router{ - EntryPoints: []string{ep}, - Service: "prometheus@internal", - Rule: "Host(`proxy.traefik`) && PathPrefix(`/metrics`)", - } - - cfg.HTTP.Routers["traefik-hub-agent-service"] = &dynamic.Router{ - EntryPoints: []string{ep}, - Service: "traefik-hub-agent-service", - Rule: "Host(`proxy.traefik`) && PathPrefix(`/config`, `/discover-ip`, `/state`)", - } - - cfg.HTTP.Services["traefik-hub-agent-service"] = &dynamic.Service{ - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: fmt.Sprintf("http://127.0.0.1:%d", port), - }, - }, - }, - } - - if tlsCfg == nil { - return - } - - if tlsCfg.Insecure { - cfg.TLS.Options["traefik-hub"] = ttls.Options{ - MinVersion: "VersionTLS13", - } - - return - } - - cfg.TLS.Options["traefik-hub"] = ttls.Options{ - ClientAuth: ttls.ClientAuth{ - CAFiles: []ttls.FileOrContent{tlsCfg.CA}, - ClientAuthType: "RequireAndVerifyClientCert", - }, - SniStrict: true, - MinVersion: "VersionTLS13", - } - - cfg.TLS.Certificates = append(cfg.TLS.Certificates, &ttls.CertAndStores{ - Certificate: ttls.Certificate{ - CertFile: tlsCfg.Cert, - KeyFile: tlsCfg.Key, - }, - }) -} - -func emptyDynamicConfiguration() *dynamic.Configuration { - return &dynamic.Configuration{ - HTTP: &dynamic.HTTPConfiguration{ - Routers: make(map[string]*dynamic.Router), - Middlewares: make(map[string]*dynamic.Middleware), - Services: make(map[string]*dynamic.Service), - ServersTransports: make(map[string]*dynamic.ServersTransport), - }, - TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), - }, - TLS: &dynamic.TLSConfiguration{ - Stores: make(map[string]ttls.Store), - Options: make(map[string]ttls.Options), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: make(map[string]*dynamic.UDPRouter), - Services: make(map[string]*dynamic.UDPService), - }, - } -} - -func createAgentClient(tlsCfg *TLS) (http.Client, error) { - var client http.Client - if tlsCfg.Insecure { - client.Transport = &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - MinVersion: tls.VersionTLS13, - }, - } - - return client, nil - } - - caContent, err := tlsCfg.CA.Read() - if err != nil { - return client, fmt.Errorf("reading CA: %w", err) - } - - roots := x509.NewCertPool() - if ok := roots.AppendCertsFromPEM(caContent); !ok { - return client, errors.New("appending CA error") - } - - certContent, err := tlsCfg.Cert.Read() - if err != nil { - return client, fmt.Errorf("reading Cert: %w", err) - } - keyContent, err := tlsCfg.Key.Read() - if err != nil { - return client, fmt.Errorf("reading Key: %w", err) - } - - certificate, err := tls.X509KeyPair(certContent, keyContent) - if err != nil { - return client, fmt.Errorf("creating key pair: %w", err) - } - - // mTLS - client.Transport = &http.Transport{ - TLSClientConfig: &tls.Config{ - RootCAs: roots, - Certificates: []tls.Certificate{certificate}, - ServerName: "agent.traefik", - ClientAuth: tls.RequireAndVerifyClientCert, - MinVersion: tls.VersionTLS13, - }, - } - - return client, nil -} diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 9a9aec188..2759055ef 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -25,6 +25,7 @@ import ( "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/types" @@ -56,7 +57,25 @@ type Provider struct { IngressClass string `description:"Value of kubernetes.io/ingress.class annotation to watch for." json:"ingressClass,omitempty" toml:"ingressClass,omitempty" yaml:"ingressClass,omitempty" export:"true"` ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"` AllowEmptyServices bool `description:"Allow the creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"` - lastConfiguration safe.Safe + + lastConfiguration safe.Safe + + routerTransform k8s.RouterTransform +} + +func (p *Provider) SetRouterTransform(routerTransform k8s.RouterTransform) { + p.routerTransform = routerTransform +} + +func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router, ingress *traefikv1alpha1.IngressRoute) { + if p.routerTransform == nil { + return + } + + err := p.routerTransform.Apply(ctx, rt, ingress.Annotations) + if err != nil { + log.FromContext(ctx).WithError(err).Error("Apply router transform") + } } func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index 9425915c8..d3b206301 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -148,6 +148,8 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli } } + p.applyRouterTransform(ctx, r, ingressRoute) + conf.Routers[normalized] = r } } diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index a74104957..a9c201574 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -22,6 +22,7 @@ import ( "github.com/traefik/traefik/v2/pkg/provider" containousv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" corev1 "k8s.io/api/core/v1" @@ -53,6 +54,23 @@ type Provider struct { EntryPoints map[string]Entrypoint `json:"-" toml:"-" yaml:"-" label:"-" file:"-"` lastConfiguration safe.Safe + + routerTransform k8s.RouterTransform +} + +func (p *Provider) SetRouterTransform(routerTransform k8s.RouterTransform) { + p.routerTransform = routerTransform +} + +func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router, route *gatev1alpha2.HTTPRoute) { + if p.routerTransform == nil { + return + } + + err := p.routerTransform.Apply(ctx, rt, route.Annotations) + if err != nil { + log.FromContext(ctx).WithError(err).Error("Apply router transform") + } } // Entrypoint defines the available entry points. @@ -495,7 +513,7 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * for _, routeKind := range routeKinds { switch routeKind.Kind { case kindHTTPRoute: - listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayHTTPRouteToHTTPConf(ctx, ep, listener, gateway, client, conf)...) + listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, p.gatewayHTTPRouteToHTTPConf(ctx, ep, listener, gateway, client, conf)...) case kindTCPRoute: listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, gatewayTCPRouteToTCPConf(ctx, ep, listener, gateway, client, conf)...) case kindTLSRoute: @@ -654,7 +672,7 @@ func getAllowedRouteKinds(listener gatev1alpha2.Listener, supportedKinds []gatev return routeKinds, conditions } -func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { +func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { if listener.AllowedRoutes == nil { // Should not happen due to validation. return nil @@ -787,8 +805,11 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener gatev1a router.Service = serviceName } + rt := &router + p.applyRouterTransform(ctx, rt, route) + routerKey = provider.Normalize(routerKey) - conf.HTTP.Routers[routerKey] = &router + conf.HTTP.Routers[routerKey] = rt } } diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 31821bf33..c2beeb006 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -20,6 +20,7 @@ import ( "github.com/traefik/traefik/v2/pkg/job" "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" + "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" corev1 "k8s.io/api/core/v1" @@ -46,7 +47,25 @@ type Provider struct { ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"` AllowEmptyServices bool `description:"Allow creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"` AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"` - lastConfiguration safe.Safe + + lastConfiguration safe.Safe + + routerTransform k8s.RouterTransform +} + +func (p *Provider) SetRouterTransform(routerTransform k8s.RouterTransform) { + p.routerTransform = routerTransform +} + +func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router, ingress *netv1.Ingress) { + if p.routerTransform == nil { + return + } + + err := p.routerTransform.Apply(ctx, rt, ingress.Annotations) + if err != nil { + log.FromContext(ctx).WithError(err).Error("Apply router transform") + } } // EndpointIngress holds the endpoint information for the Kubernetes provider. @@ -262,6 +281,8 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl rt.TLS = rtConfig.Router.TLS } + p.applyRouterTransform(ctx, rt, ingress) + conf.HTTP.Routers["default-router"] = rt conf.HTTP.Services["default-backend"] = service } @@ -304,8 +325,13 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString) conf.HTTP.Services[serviceName] = service + rt := loadRouter(rule, pa, rtConfig, serviceName) + + p.applyRouterTransform(ctx, rt, ingress) + routerKey := strings.TrimPrefix(provider.Normalize(ingress.Namespace+"-"+ingress.Name+"-"+rule.Host+pa.Path), "-") - routers[routerKey] = append(routers[routerKey], loadRouter(rule, pa, rtConfig, serviceName)) + + routers[routerKey] = append(routers[routerKey], rt) } } diff --git a/pkg/provider/kubernetes/k8s/router_transform.go b/pkg/provider/kubernetes/k8s/router_transform.go new file mode 100644 index 000000000..b1e6040fd --- /dev/null +++ b/pkg/provider/kubernetes/k8s/router_transform.go @@ -0,0 +1,11 @@ +package k8s + +import ( + "context" + + "github.com/traefik/traefik/v2/pkg/config/dynamic" +) + +type RouterTransform interface { + Apply(ctx context.Context, rt *dynamic.Router, annotations map[string]string) error +} diff --git a/pkg/provider/marathon/marathon.go b/pkg/provider/marathon/marathon.go index aab469785..14c08f832 100644 --- a/pkg/provider/marathon/marathon.go +++ b/pkg/provider/marathon/marathon.go @@ -167,7 +167,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. case <-ctxPool.Done(): return case event := <-update: - logger.Debugf("Received provider event %s", event) + logger.Debugf("Received provider event %v", event) conf := p.getConfigurations(ctx) if conf != nil { From 021f37ff7111d42d879f549dff74cbc5bdb5acb7 Mon Sep 17 00:00:00 2001 From: Erikas <5955795+erkexzcx@users.noreply.github.com> Date: Tue, 16 May 2023 17:00:06 +0300 Subject: [PATCH 9/9] Do not check for wildcard domains for non DNS challenge --- pkg/provider/acme/provider.go | 10 ++-------- pkg/provider/acme/provider_test.go | 7 ------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go index be211ab04..b9027de98 100644 --- a/pkg/provider/acme/provider.go +++ b/pkg/provider/acme/provider.go @@ -922,14 +922,8 @@ func (p *Provider) sanitizeDomains(ctx context.Context, domain types.Domain) ([] var cleanDomains []string for _, dom := range domains { - if strings.HasPrefix(dom, "*") { - if p.DNSChallenge == nil { - return nil, fmt.Errorf("unable to generate a wildcard certificate in ACME provider for domain %q : ACME needs a DNSChallenge", strings.Join(domains, ",")) - } - - if strings.HasPrefix(dom, "*.*") { - return nil, fmt.Errorf("unable to generate a wildcard certificate in ACME provider for domain %q : ACME does not allow '*.*' wildcard domain", strings.Join(domains, ",")) - } + if strings.HasPrefix(dom, "*.*") { + return nil, fmt.Errorf("unable to generate a wildcard certificate in ACME provider for domain %q : ACME does not allow '*.*' wildcard domain", strings.Join(domains, ",")) } canonicalDomain := types.CanonicalDomain(dom) diff --git a/pkg/provider/acme/provider_test.go b/pkg/provider/acme/provider_test.go index 3268b1c92..3cd024c77 100644 --- a/pkg/provider/acme/provider_test.go +++ b/pkg/provider/acme/provider_test.go @@ -217,13 +217,6 @@ func TestProvider_sanitizeDomains(t *testing.T) { expectedErr: "no domain was given", expectedDomains: nil, }, - { - desc: "no DNSChallenge", - domains: types.Domain{Main: "*.traefik.wtf", SANs: []string{"foo.traefik.wtf"}}, - dnsChallenge: nil, - expectedErr: "unable to generate a wildcard certificate in ACME provider for domain \"*.traefik.wtf,foo.traefik.wtf\" : ACME needs a DNSChallenge", - expectedDomains: nil, - }, { desc: "unauthorized wildcard with SAN", domains: types.Domain{Main: "*.*.traefik.wtf", SANs: []string{"foo.traefik.wtf"}},