forked from TrueCloudLab/lego
Add Brandit.com as DNS provider (#1890)
This commit is contained in:
parent
3b70a85cf7
commit
9db046581b
15 changed files with 1050 additions and 28 deletions
55
README.md
55
README.md
|
@ -51,33 +51,34 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
|
|||
|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
|
||||
| [Akamai EdgeDNS](https://go-acme.github.io/lego/dns/edgedns/) | [Alibaba Cloud DNS](https://go-acme.github.io/lego/dns/alidns/) | [all-inkl](https://go-acme.github.io/lego/dns/allinkl/) | [Amazon Lightsail](https://go-acme.github.io/lego/dns/lightsail/) |
|
||||
| [Amazon Route 53](https://go-acme.github.io/lego/dns/route53/) | [ArvanCloud](https://go-acme.github.io/lego/dns/arvancloud/) | [Aurora DNS](https://go-acme.github.io/lego/dns/auroradns/) | [Autodns](https://go-acme.github.io/lego/dns/autodns/) |
|
||||
| [Azure](https://go-acme.github.io/lego/dns/azure/) | [Bindman](https://go-acme.github.io/lego/dns/bindman/) | [Bluecat](https://go-acme.github.io/lego/dns/bluecat/) | [Bunny](https://go-acme.github.io/lego/dns/bunny/) |
|
||||
| [Checkdomain](https://go-acme.github.io/lego/dns/checkdomain/) | [Civo](https://go-acme.github.io/lego/dns/civo/) | [CloudDNS](https://go-acme.github.io/lego/dns/clouddns/) | [Cloudflare](https://go-acme.github.io/lego/dns/cloudflare/) |
|
||||
| [ClouDNS](https://go-acme.github.io/lego/dns/cloudns/) | [CloudXNS](https://go-acme.github.io/lego/dns/cloudxns/) | [ConoHa](https://go-acme.github.io/lego/dns/conoha/) | [Constellix](https://go-acme.github.io/lego/dns/constellix/) |
|
||||
| [deSEC.io](https://go-acme.github.io/lego/dns/desec/) | [Designate DNSaaS for Openstack](https://go-acme.github.io/lego/dns/designate/) | [Digital Ocean](https://go-acme.github.io/lego/dns/digitalocean/) | [DNS Made Easy](https://go-acme.github.io/lego/dns/dnsmadeeasy/) |
|
||||
| [dnsHome.de](https://go-acme.github.io/lego/dns/dnshomede/) | [DNSimple](https://go-acme.github.io/lego/dns/dnsimple/) | [DNSPod (deprecated)](https://go-acme.github.io/lego/dns/dnspod/) | [Domain Offensive (do.de)](https://go-acme.github.io/lego/dns/dode/) |
|
||||
| [Domeneshop](https://go-acme.github.io/lego/dns/domeneshop/) | [DreamHost](https://go-acme.github.io/lego/dns/dreamhost/) | [Duck DNS](https://go-acme.github.io/lego/dns/duckdns/) | [Dyn](https://go-acme.github.io/lego/dns/dyn/) |
|
||||
| [Dynu](https://go-acme.github.io/lego/dns/dynu/) | [EasyDNS](https://go-acme.github.io/lego/dns/easydns/) | [Epik](https://go-acme.github.io/lego/dns/epik/) | [Exoscale](https://go-acme.github.io/lego/dns/exoscale/) |
|
||||
| [External program](https://go-acme.github.io/lego/dns/exec/) | [freemyip.com](https://go-acme.github.io/lego/dns/freemyip/) | [G-Core Labs](https://go-acme.github.io/lego/dns/gcore/) | [Gandi Live DNS (v5)](https://go-acme.github.io/lego/dns/gandiv5/) |
|
||||
| [Gandi](https://go-acme.github.io/lego/dns/gandi/) | [Glesys](https://go-acme.github.io/lego/dns/glesys/) | [Go Daddy](https://go-acme.github.io/lego/dns/godaddy/) | [Google Cloud](https://go-acme.github.io/lego/dns/gcloud/) |
|
||||
| [Google Domains](https://go-acme.github.io/lego/dns/googledomains/) | [Hetzner](https://go-acme.github.io/lego/dns/hetzner/) | [Hosting.de](https://go-acme.github.io/lego/dns/hostingde/) | [Hosttech](https://go-acme.github.io/lego/dns/hosttech/) |
|
||||
| [HTTP request](https://go-acme.github.io/lego/dns/httpreq/) | [Hurricane Electric DNS](https://go-acme.github.io/lego/dns/hurricane/) | [HyperOne](https://go-acme.github.io/lego/dns/hyperone/) | [IBM Cloud (SoftLayer)](https://go-acme.github.io/lego/dns/ibmcloud/) |
|
||||
| [IIJ DNS Platform Service](https://go-acme.github.io/lego/dns/iijdpf/) | [Infoblox](https://go-acme.github.io/lego/dns/infoblox/) | [Infomaniak](https://go-acme.github.io/lego/dns/infomaniak/) | [Internet Initiative Japan](https://go-acme.github.io/lego/dns/iij/) |
|
||||
| [Internet.bs](https://go-acme.github.io/lego/dns/internetbs/) | [INWX](https://go-acme.github.io/lego/dns/inwx/) | [Ionos](https://go-acme.github.io/lego/dns/ionos/) | [iwantmyname](https://go-acme.github.io/lego/dns/iwantmyname/) |
|
||||
| [Joker](https://go-acme.github.io/lego/dns/joker/) | [Joohoi's ACME-DNS](https://go-acme.github.io/lego/dns/acme-dns/) | [Liara](https://go-acme.github.io/lego/dns/liara/) | [Linode (v4)](https://go-acme.github.io/lego/dns/linode/) |
|
||||
| [Liquid Web](https://go-acme.github.io/lego/dns/liquidweb/) | [Loopia](https://go-acme.github.io/lego/dns/loopia/) | [LuaDNS](https://go-acme.github.io/lego/dns/luadns/) | [Manual](https://go-acme.github.io/lego/dns/manual/) |
|
||||
| [MyDNS.jp](https://go-acme.github.io/lego/dns/mydnsjp/) | [MythicBeasts](https://go-acme.github.io/lego/dns/mythicbeasts/) | [Name.com](https://go-acme.github.io/lego/dns/namedotcom/) | [Namecheap](https://go-acme.github.io/lego/dns/namecheap/) |
|
||||
| [Namesilo](https://go-acme.github.io/lego/dns/namesilo/) | [NearlyFreeSpeech.NET](https://go-acme.github.io/lego/dns/nearlyfreespeech/) | [Netcup](https://go-acme.github.io/lego/dns/netcup/) | [Netlify](https://go-acme.github.io/lego/dns/netlify/) |
|
||||
| [Nicmanager](https://go-acme.github.io/lego/dns/nicmanager/) | [NIFCloud](https://go-acme.github.io/lego/dns/nifcloud/) | [Njalla](https://go-acme.github.io/lego/dns/njalla/) | [Nodion](https://go-acme.github.io/lego/dns/nodion/) |
|
||||
| [NS1](https://go-acme.github.io/lego/dns/ns1/) | [Open Telekom Cloud](https://go-acme.github.io/lego/dns/otc/) | [Oracle Cloud](https://go-acme.github.io/lego/dns/oraclecloud/) | [OVH](https://go-acme.github.io/lego/dns/ovh/) |
|
||||
| [plesk.com](https://go-acme.github.io/lego/dns/plesk/) | [Porkbun](https://go-acme.github.io/lego/dns/porkbun/) | [PowerDNS](https://go-acme.github.io/lego/dns/pdns/) | [Rackspace](https://go-acme.github.io/lego/dns/rackspace/) |
|
||||
| [reg.ru](https://go-acme.github.io/lego/dns/regru/) | [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/) | [RimuHosting](https://go-acme.github.io/lego/dns/rimuhosting/) | [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/) |
|
||||
| [Scaleway](https://go-acme.github.io/lego/dns/scaleway/) | [Selectel](https://go-acme.github.io/lego/dns/selectel/) | [Servercow](https://go-acme.github.io/lego/dns/servercow/) | [Simply.com](https://go-acme.github.io/lego/dns/simply/) |
|
||||
| [Sonic](https://go-acme.github.io/lego/dns/sonic/) | [Stackpath](https://go-acme.github.io/lego/dns/stackpath/) | [Tencent Cloud DNS](https://go-acme.github.io/lego/dns/tencentcloud/) | [TransIP](https://go-acme.github.io/lego/dns/transip/) |
|
||||
| [UKFast SafeDNS](https://go-acme.github.io/lego/dns/safedns/) | [Ultradns](https://go-acme.github.io/lego/dns/ultradns/) | [Variomedia](https://go-acme.github.io/lego/dns/variomedia/) | [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/) |
|
||||
| [Vercel](https://go-acme.github.io/lego/dns/vercel/) | [Versio.[nl/eu/uk]](https://go-acme.github.io/lego/dns/versio/) | [VinylDNS](https://go-acme.github.io/lego/dns/vinyldns/) | [VK Cloud](https://go-acme.github.io/lego/dns/vkcloud/) |
|
||||
| [Vscale](https://go-acme.github.io/lego/dns/vscale/) | [Vultr](https://go-acme.github.io/lego/dns/vultr/) | [Websupport](https://go-acme.github.io/lego/dns/websupport/) | [WEDOS](https://go-acme.github.io/lego/dns/wedos/) |
|
||||
| [Yandex Cloud](https://go-acme.github.io/lego/dns/yandexcloud/) | [Yandex PDD](https://go-acme.github.io/lego/dns/yandex/) | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/) | [Zonomi](https://go-acme.github.io/lego/dns/zonomi/) |
|
||||
| [Azure](https://go-acme.github.io/lego/dns/azure/) | [Bindman](https://go-acme.github.io/lego/dns/bindman/) | [Bluecat](https://go-acme.github.io/lego/dns/bluecat/) | [BRANDIT](https://go-acme.github.io/lego/dns/brandit/) |
|
||||
| [Bunny](https://go-acme.github.io/lego/dns/bunny/) | [Checkdomain](https://go-acme.github.io/lego/dns/checkdomain/) | [Civo](https://go-acme.github.io/lego/dns/civo/) | [CloudDNS](https://go-acme.github.io/lego/dns/clouddns/) |
|
||||
| [Cloudflare](https://go-acme.github.io/lego/dns/cloudflare/) | [ClouDNS](https://go-acme.github.io/lego/dns/cloudns/) | [CloudXNS](https://go-acme.github.io/lego/dns/cloudxns/) | [ConoHa](https://go-acme.github.io/lego/dns/conoha/) |
|
||||
| [Constellix](https://go-acme.github.io/lego/dns/constellix/) | [deSEC.io](https://go-acme.github.io/lego/dns/desec/) | [Designate DNSaaS for Openstack](https://go-acme.github.io/lego/dns/designate/) | [Digital Ocean](https://go-acme.github.io/lego/dns/digitalocean/) |
|
||||
| [DNS Made Easy](https://go-acme.github.io/lego/dns/dnsmadeeasy/) | [dnsHome.de](https://go-acme.github.io/lego/dns/dnshomede/) | [DNSimple](https://go-acme.github.io/lego/dns/dnsimple/) | [DNSPod (deprecated)](https://go-acme.github.io/lego/dns/dnspod/) |
|
||||
| [Domain Offensive (do.de)](https://go-acme.github.io/lego/dns/dode/) | [Domeneshop](https://go-acme.github.io/lego/dns/domeneshop/) | [DreamHost](https://go-acme.github.io/lego/dns/dreamhost/) | [Duck DNS](https://go-acme.github.io/lego/dns/duckdns/) |
|
||||
| [Dyn](https://go-acme.github.io/lego/dns/dyn/) | [Dynu](https://go-acme.github.io/lego/dns/dynu/) | [EasyDNS](https://go-acme.github.io/lego/dns/easydns/) | [Epik](https://go-acme.github.io/lego/dns/epik/) |
|
||||
| [Exoscale](https://go-acme.github.io/lego/dns/exoscale/) | [External program](https://go-acme.github.io/lego/dns/exec/) | [freemyip.com](https://go-acme.github.io/lego/dns/freemyip/) | [G-Core Labs](https://go-acme.github.io/lego/dns/gcore/) |
|
||||
| [Gandi Live DNS (v5)](https://go-acme.github.io/lego/dns/gandiv5/) | [Gandi](https://go-acme.github.io/lego/dns/gandi/) | [Glesys](https://go-acme.github.io/lego/dns/glesys/) | [Go Daddy](https://go-acme.github.io/lego/dns/godaddy/) |
|
||||
| [Google Cloud](https://go-acme.github.io/lego/dns/gcloud/) | [Google Domains](https://go-acme.github.io/lego/dns/googledomains/) | [Hetzner](https://go-acme.github.io/lego/dns/hetzner/) | [Hosting.de](https://go-acme.github.io/lego/dns/hostingde/) |
|
||||
| [Hosttech](https://go-acme.github.io/lego/dns/hosttech/) | [HTTP request](https://go-acme.github.io/lego/dns/httpreq/) | [Hurricane Electric DNS](https://go-acme.github.io/lego/dns/hurricane/) | [HyperOne](https://go-acme.github.io/lego/dns/hyperone/) |
|
||||
| [IBM Cloud (SoftLayer)](https://go-acme.github.io/lego/dns/ibmcloud/) | [IIJ DNS Platform Service](https://go-acme.github.io/lego/dns/iijdpf/) | [Infoblox](https://go-acme.github.io/lego/dns/infoblox/) | [Infomaniak](https://go-acme.github.io/lego/dns/infomaniak/) |
|
||||
| [Internet Initiative Japan](https://go-acme.github.io/lego/dns/iij/) | [Internet.bs](https://go-acme.github.io/lego/dns/internetbs/) | [INWX](https://go-acme.github.io/lego/dns/inwx/) | [Ionos](https://go-acme.github.io/lego/dns/ionos/) |
|
||||
| [iwantmyname](https://go-acme.github.io/lego/dns/iwantmyname/) | [Joker](https://go-acme.github.io/lego/dns/joker/) | [Joohoi's ACME-DNS](https://go-acme.github.io/lego/dns/acme-dns/) | [Liara](https://go-acme.github.io/lego/dns/liara/) |
|
||||
| [Linode (v4)](https://go-acme.github.io/lego/dns/linode/) | [Liquid Web](https://go-acme.github.io/lego/dns/liquidweb/) | [Loopia](https://go-acme.github.io/lego/dns/loopia/) | [LuaDNS](https://go-acme.github.io/lego/dns/luadns/) |
|
||||
| [Manual](https://go-acme.github.io/lego/dns/manual/) | [MyDNS.jp](https://go-acme.github.io/lego/dns/mydnsjp/) | [MythicBeasts](https://go-acme.github.io/lego/dns/mythicbeasts/) | [Name.com](https://go-acme.github.io/lego/dns/namedotcom/) |
|
||||
| [Namecheap](https://go-acme.github.io/lego/dns/namecheap/) | [Namesilo](https://go-acme.github.io/lego/dns/namesilo/) | [NearlyFreeSpeech.NET](https://go-acme.github.io/lego/dns/nearlyfreespeech/) | [Netcup](https://go-acme.github.io/lego/dns/netcup/) |
|
||||
| [Netlify](https://go-acme.github.io/lego/dns/netlify/) | [Nicmanager](https://go-acme.github.io/lego/dns/nicmanager/) | [NIFCloud](https://go-acme.github.io/lego/dns/nifcloud/) | [Njalla](https://go-acme.github.io/lego/dns/njalla/) |
|
||||
| [Nodion](https://go-acme.github.io/lego/dns/nodion/) | [NS1](https://go-acme.github.io/lego/dns/ns1/) | [Open Telekom Cloud](https://go-acme.github.io/lego/dns/otc/) | [Oracle Cloud](https://go-acme.github.io/lego/dns/oraclecloud/) |
|
||||
| [OVH](https://go-acme.github.io/lego/dns/ovh/) | [plesk.com](https://go-acme.github.io/lego/dns/plesk/) | [Porkbun](https://go-acme.github.io/lego/dns/porkbun/) | [PowerDNS](https://go-acme.github.io/lego/dns/pdns/) |
|
||||
| [Rackspace](https://go-acme.github.io/lego/dns/rackspace/) | [reg.ru](https://go-acme.github.io/lego/dns/regru/) | [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/) | [RimuHosting](https://go-acme.github.io/lego/dns/rimuhosting/) |
|
||||
| [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/) | [Scaleway](https://go-acme.github.io/lego/dns/scaleway/) | [Selectel](https://go-acme.github.io/lego/dns/selectel/) | [Servercow](https://go-acme.github.io/lego/dns/servercow/) |
|
||||
| [Simply.com](https://go-acme.github.io/lego/dns/simply/) | [Sonic](https://go-acme.github.io/lego/dns/sonic/) | [Stackpath](https://go-acme.github.io/lego/dns/stackpath/) | [Tencent Cloud DNS](https://go-acme.github.io/lego/dns/tencentcloud/) |
|
||||
| [TransIP](https://go-acme.github.io/lego/dns/transip/) | [UKFast SafeDNS](https://go-acme.github.io/lego/dns/safedns/) | [Ultradns](https://go-acme.github.io/lego/dns/ultradns/) | [Variomedia](https://go-acme.github.io/lego/dns/variomedia/) |
|
||||
| [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/) | [Vercel](https://go-acme.github.io/lego/dns/vercel/) | [Versio.[nl/eu/uk]](https://go-acme.github.io/lego/dns/versio/) | [VinylDNS](https://go-acme.github.io/lego/dns/vinyldns/) |
|
||||
| [VK Cloud](https://go-acme.github.io/lego/dns/vkcloud/) | [Vscale](https://go-acme.github.io/lego/dns/vscale/) | [Vultr](https://go-acme.github.io/lego/dns/vultr/) | [Websupport](https://go-acme.github.io/lego/dns/websupport/) |
|
||||
| [WEDOS](https://go-acme.github.io/lego/dns/wedos/) | [Yandex Cloud](https://go-acme.github.io/lego/dns/yandexcloud/) | [Yandex PDD](https://go-acme.github.io/lego/dns/yandex/) | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/) |
|
||||
| [Zonomi](https://go-acme.github.io/lego/dns/zonomi/) | | | |
|
||||
|
||||
<!-- END DNS PROVIDERS LIST -->
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ func allDNSCodes() string {
|
|||
"azure",
|
||||
"bindman",
|
||||
"bluecat",
|
||||
"brandit",
|
||||
"bunny",
|
||||
"checkdomain",
|
||||
"civo",
|
||||
|
@ -332,6 +333,27 @@ func displayDNSHelp(w io.Writer, name string) error {
|
|||
ew.writeln()
|
||||
ew.writeln(`More information: https://go-acme.github.io/lego/dns/bluecat`)
|
||||
|
||||
case "brandit":
|
||||
// generated from: providers/dns/brandit/brandit.toml
|
||||
ew.writeln(`Configuration for BRANDIT.`)
|
||||
ew.writeln(`Code: 'brandit'`)
|
||||
ew.writeln(`Since: 'v4.11.0'`)
|
||||
ew.writeln()
|
||||
|
||||
ew.writeln(`Credentials:`)
|
||||
ew.writeln(` - "BRANDIT_API_KEY": The API key`)
|
||||
ew.writeln(` - "BRANDIT_API_USERNAME": The API username`)
|
||||
ew.writeln()
|
||||
|
||||
ew.writeln(`Additional Configuration:`)
|
||||
ew.writeln(` - "BRANDIT_HTTP_TIMEOUT": API request timeout`)
|
||||
ew.writeln(` - "BRANDIT_POLLING_INTERVAL": Time between DNS propagation check`)
|
||||
ew.writeln(` - "BRANDIT_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
|
||||
ew.writeln(` - "BRANDIT_TTL": The TTL of the TXT record used for the DNS challenge`)
|
||||
|
||||
ew.writeln()
|
||||
ew.writeln(`More information: https://go-acme.github.io/lego/dns/brandit`)
|
||||
|
||||
case "bunny":
|
||||
// generated from: providers/dns/bunny/bunny.toml
|
||||
ew.writeln(`Configuration for Bunny.`)
|
||||
|
|
69
docs/content/dns/zz_gen_brandit.md
Normal file
69
docs/content/dns/zz_gen_brandit.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
title: "BRANDIT"
|
||||
date: 2019-03-03T16:39:46+01:00
|
||||
draft: false
|
||||
slug: brandit
|
||||
dnsprovider:
|
||||
since: "v4.11.0"
|
||||
code: "brandit"
|
||||
url: "https://www.brandit.com/"
|
||||
---
|
||||
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||
<!-- providers/dns/brandit/brandit.toml -->
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||
|
||||
|
||||
Configuration for [BRANDIT](https://www.brandit.com/).
|
||||
|
||||
|
||||
<!--more-->
|
||||
|
||||
- Code: `brandit`
|
||||
- Since: v4.11.0
|
||||
|
||||
|
||||
Here is an example bash command using the BRANDIT provider:
|
||||
|
||||
```bash
|
||||
BRANDIT_API_KEY=xxxxxxxxxxxxxxxxxxxxx \
|
||||
BRANDIT_API_USERNAME=yyyyyyyyyyyyyyyyyyyy \
|
||||
lego --email myemail@example.com --dns brandit --domains my.example.org run
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Credentials
|
||||
|
||||
| Environment Variable Name | Description |
|
||||
|-----------------------|-------------|
|
||||
| `BRANDIT_API_KEY` | The API key |
|
||||
| `BRANDIT_API_USERNAME` | The API username |
|
||||
|
||||
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
|
||||
More information [here]({{< ref "dns#configuration-and-credentials" >}}).
|
||||
|
||||
|
||||
## Additional Configuration
|
||||
|
||||
| Environment Variable Name | Description |
|
||||
|--------------------------------|-------------|
|
||||
| `BRANDIT_HTTP_TIMEOUT` | API request timeout |
|
||||
| `BRANDIT_POLLING_INTERVAL` | Time between DNS propagation check |
|
||||
| `BRANDIT_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
|
||||
| `BRANDIT_TTL` | The TTL of the TXT record used for the DNS challenge |
|
||||
|
||||
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
|
||||
More information [here]({{< ref "dns#configuration-and-credentials" >}}).
|
||||
|
||||
|
||||
|
||||
|
||||
## More information
|
||||
|
||||
- [API documentation](https://portal.brandit.com/apidocv3)
|
||||
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||
<!-- providers/dns/brandit/brandit.toml -->
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
|
@ -125,7 +125,7 @@ To display the documentation for a specific DNS provider, run:
|
|||
$ lego dnshelp -c code
|
||||
|
||||
Supported DNS providers:
|
||||
acme-dns, alidns, allinkl, arvancloud, auroradns, autodns, azure, bindman, bluecat, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudxns, conoha, constellix, desec, designate, digitalocean, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dynu, easydns, edgedns, epik, exec, exoscale, freemyip, gandi, gandiv5, gcloud, gcore, glesys, godaddy, googledomains, hetzner, hostingde, hosttech, httpreq, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, iwantmyname, joker, liara, lightsail, linode, liquidweb, loopia, luadns, manual, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nifcloud, njalla, nodion, ns1, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, servercow, simply, sonic, stackpath, tencentcloud, transip, ultradns, variomedia, vegadns, vercel, versio, vinyldns, vkcloud, vscale, vultr, websupport, wedos, yandex, yandexcloud, zoneee, zonomi
|
||||
acme-dns, alidns, allinkl, arvancloud, auroradns, autodns, azure, bindman, bluecat, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudxns, conoha, constellix, desec, designate, digitalocean, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dynu, easydns, edgedns, epik, exec, exoscale, freemyip, gandi, gandiv5, gcloud, gcore, glesys, godaddy, googledomains, hetzner, hostingde, hosttech, httpreq, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, iwantmyname, joker, liara, lightsail, linode, liquidweb, loopia, luadns, manual, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nifcloud, njalla, nodion, ns1, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, servercow, simply, sonic, stackpath, tencentcloud, transip, ultradns, variomedia, vegadns, vercel, versio, vinyldns, vkcloud, vscale, vultr, websupport, wedos, yandex, yandexcloud, zoneee, zonomi
|
||||
|
||||
More information: https://go-acme.github.io/lego/dns
|
||||
"""
|
||||
|
|
197
providers/dns/brandit/brandit.go
Normal file
197
providers/dns/brandit/brandit.go
Normal file
|
@ -0,0 +1,197 @@
|
|||
package brandit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
"github.com/go-acme/lego/v4/providers/dns/brandit/internal"
|
||||
)
|
||||
|
||||
const defaultTTL = 600
|
||||
|
||||
// Environment variables names.
|
||||
const (
|
||||
envNamespace = "BRANDIT_"
|
||||
|
||||
EnvAPIKey = envNamespace + "API_KEY"
|
||||
EnvAPIUsername = envNamespace + "API_USERNAME"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
||||
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
|
||||
DefaultBrandItPropagationTimeout = 600 * time.Second
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider.
|
||||
type Config struct {
|
||||
APIKey string
|
||||
APIUsername string
|
||||
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider.
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
TTL: env.GetOrDefaultInt(EnvTTL, defaultTTL),
|
||||
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, DefaultBrandItPropagationTimeout),
|
||||
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DNSProvider implements the challenge.Provider interface.
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
client *internal.Client
|
||||
|
||||
records map[string]string
|
||||
recordsMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for BrandIT.
|
||||
// Credentials must be passed in the environment variables: BRANDIT_API_KEY, BRANDIT_API_USERNAME.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvAPIKey, EnvAPIUsername)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("brandit: %w", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.APIKey = values[EnvAPIKey]
|
||||
config.APIUsername = values[EnvAPIUsername]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
// NewDNSProviderConfig return a DNSProvider instance configured for BrandIT.
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("brandit: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(config.APIUsername, config.APIKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("brandit: %w", err)
|
||||
}
|
||||
|
||||
if config.HTTPClient != nil {
|
||||
client.HTTPClient = config.HTTPClient
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
config: config,
|
||||
client: client,
|
||||
records: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record using the specified parameters.
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: %w", err)
|
||||
}
|
||||
|
||||
subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: %w", err)
|
||||
}
|
||||
|
||||
record := internal.Record{
|
||||
Type: "TXT",
|
||||
Name: subDomain,
|
||||
Content: info.Value,
|
||||
TTL: d.config.TTL,
|
||||
}
|
||||
|
||||
// find the account associated with the domain
|
||||
account, err := d.client.StatusDomain(dns01.UnFqdn(authZone))
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: status domain: %w", err)
|
||||
}
|
||||
|
||||
// Find the next record id
|
||||
recordID, err := d.client.ListRecords(account.Response.Registrar[0], dns01.UnFqdn(authZone))
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: list records: %w", err)
|
||||
}
|
||||
|
||||
result, err := d.client.AddRecord(dns01.UnFqdn(authZone), account.Response.Registrar[0], fmt.Sprint(recordID.Response.Total[0]), record)
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: add record: %w", err)
|
||||
}
|
||||
|
||||
d.recordsMu.Lock()
|
||||
d.records[token] = result.Record
|
||||
d.recordsMu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: %w", err)
|
||||
}
|
||||
|
||||
// gets the record's unique ID
|
||||
d.recordsMu.Lock()
|
||||
dnsRecord, ok := d.records[token]
|
||||
d.recordsMu.Unlock()
|
||||
if !ok {
|
||||
return fmt.Errorf("brandit: unknown record ID for '%s' '%s'", info.EffectiveFQDN, token)
|
||||
}
|
||||
|
||||
// find the account associated with the domain
|
||||
account, err := d.client.StatusDomain(dns01.UnFqdn(authZone))
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: status domain: %w", err)
|
||||
}
|
||||
|
||||
records, err := d.client.ListRecords(account.Response.Registrar[0], dns01.UnFqdn(authZone))
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: list records: %w", err)
|
||||
}
|
||||
|
||||
var recordID int
|
||||
for i, r := range records.Response.RR {
|
||||
if r == dnsRecord {
|
||||
recordID = i
|
||||
}
|
||||
}
|
||||
|
||||
_, err = d.client.DeleteRecord(dns01.UnFqdn(authZone), account.Response.Registrar[0], dnsRecord, fmt.Sprint(recordID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("brandit: delete record: %w", err)
|
||||
}
|
||||
|
||||
// deletes record ID from map
|
||||
d.recordsMu.Lock()
|
||||
delete(d.records, token)
|
||||
d.recordsMu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
||||
// Adjusting here to cope with spikes in propagation times.
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
24
providers/dns/brandit/brandit.toml
Normal file
24
providers/dns/brandit/brandit.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
Name = "BRANDIT"
|
||||
Description = ''''''
|
||||
URL = "https://www.brandit.com/"
|
||||
Code = "brandit"
|
||||
Since = "v4.11.0"
|
||||
|
||||
Example = '''
|
||||
BRANDIT_API_KEY=xxxxxxxxxxxxxxxxxxxxx \
|
||||
BRANDIT_API_USERNAME=yyyyyyyyyyyyyyyyyyyy \
|
||||
lego --email myemail@example.com --dns brandit --domains my.example.org run
|
||||
'''
|
||||
|
||||
[Configuration]
|
||||
[Configuration.Credentials]
|
||||
BRANDIT_API_KEY = "The API key"
|
||||
BRANDIT_API_USERNAME = "The API username"
|
||||
[Configuration.Additional]
|
||||
BRANDIT_POLLING_INTERVAL = "Time between DNS propagation check"
|
||||
BRANDIT_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||
BRANDIT_TTL = "The TTL of the TXT record used for the DNS challenge"
|
||||
BRANDIT_HTTP_TIMEOUT = "API request timeout"
|
||||
|
||||
[Links]
|
||||
API = "https://portal.brandit.com/apidocv3"
|
141
providers/dns/brandit/brandit_test.go
Normal file
141
providers/dns/brandit/brandit_test.go
Normal file
|
@ -0,0 +1,141 @@
|
|||
package brandit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-acme/lego/v4/platform/tester"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const envDomain = envNamespace + "DOMAIN"
|
||||
|
||||
var envTest = tester.NewEnvTest(EnvAPIKey, EnvAPIUsername).WithDomain(envDomain)
|
||||
|
||||
func TestNewDNSProvider(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
envVars map[string]string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
envVars: map[string]string{
|
||||
EnvAPIKey: "key",
|
||||
EnvAPIUsername: "test_user",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "missing API key",
|
||||
envVars: map[string]string{
|
||||
EnvAPIUsername: "test_user",
|
||||
},
|
||||
expected: "brandit: some credentials information are missing: BRANDIT_API_KEY",
|
||||
},
|
||||
{
|
||||
desc: "missing secret",
|
||||
envVars: map[string]string{
|
||||
EnvAPIKey: "key",
|
||||
},
|
||||
expected: "brandit: some credentials information are missing: BRANDIT_API_USERNAME",
|
||||
},
|
||||
{
|
||||
desc: "missing credentials",
|
||||
envVars: map[string]string{},
|
||||
expected: "brandit: some credentials information are missing: BRANDIT_API_KEY,BRANDIT_API_USERNAME",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
defer envTest.RestoreEnv()
|
||||
envTest.ClearEnv()
|
||||
|
||||
envTest.Apply(test.envVars)
|
||||
|
||||
p, err := NewDNSProvider()
|
||||
|
||||
if test.expected == "" {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NotNil(t, p.config)
|
||||
require.NotNil(t, p.client)
|
||||
} else {
|
||||
require.EqualError(t, err, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDNSProviderConfig(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
apiKey string
|
||||
user string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
apiKey: "key",
|
||||
user: "test_user",
|
||||
},
|
||||
{
|
||||
desc: "missing API key",
|
||||
user: "test_user",
|
||||
expected: "brandit: credentials missing",
|
||||
},
|
||||
{
|
||||
desc: "missing secret",
|
||||
apiKey: "key",
|
||||
expected: "brandit: credentials missing",
|
||||
},
|
||||
{
|
||||
desc: "missing credentials",
|
||||
expected: "brandit: credentials missing",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
config := NewDefaultConfig()
|
||||
config.APIKey = test.apiKey
|
||||
config.APIUsername = test.user
|
||||
|
||||
p, err := NewDNSProviderConfig(config)
|
||||
|
||||
if test.expected == "" {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NotNil(t, p.config)
|
||||
require.NotNil(t, p.client)
|
||||
} else {
|
||||
require.EqualError(t, err, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLivePresent(t *testing.T) {
|
||||
if !envTest.IsLiveTest() {
|
||||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
envTest.RestoreEnv()
|
||||
provider, err := NewDNSProvider()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = provider.Present(envTest.GetDomain(), "", "123d==")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestLiveCleanUp(t *testing.T) {
|
||||
if !envTest.IsLiveTest() {
|
||||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
envTest.RestoreEnv()
|
||||
provider, err := NewDNSProvider()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
|
||||
require.NoError(t, err)
|
||||
}
|
198
providers/dns/brandit/internal/client.go
Normal file
198
providers/dns/brandit/internal/client.go
Normal file
|
@ -0,0 +1,198 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const defaultBaseURL = "https://portal.brandit.com/api/v3/"
|
||||
|
||||
// Client a BrandIT DNS API client.
|
||||
type Client struct {
|
||||
apiUsername string
|
||||
apiKey string
|
||||
BaseURL string
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewClient creates a new Client.
|
||||
func NewClient(apiUsername, apiKey string) (*Client, error) {
|
||||
if apiKey == "" || apiUsername == "" {
|
||||
return nil, errors.New("credentials missing")
|
||||
}
|
||||
|
||||
return &Client{
|
||||
apiUsername: apiUsername,
|
||||
apiKey: apiKey,
|
||||
BaseURL: defaultBaseURL,
|
||||
HTTPClient: &http.Client{Timeout: 10 * time.Second},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListRecords lists all records.
|
||||
// https://portal.brandit.com/apidocv3#listDNSRR
|
||||
func (c *Client) ListRecords(account, dnsZone string) (*ListRecords, error) {
|
||||
// Create a new query
|
||||
query := url.Values{}
|
||||
query.Add("command", "listDNSRR")
|
||||
query.Add("account", account)
|
||||
query.Add("dnszone", dnsZone)
|
||||
|
||||
result := &ListRecords{}
|
||||
|
||||
err := c.do(query, result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("do: %w", err)
|
||||
}
|
||||
|
||||
for len(result.Response.RR) < result.Response.Total[0] {
|
||||
query.Add("first", fmt.Sprint(result.Response.Last[0]+1))
|
||||
|
||||
tmp := &ListRecords{}
|
||||
err := c.do(query, tmp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("do: %w", err)
|
||||
}
|
||||
|
||||
result.Response.RR = append(result.Response.RR, tmp.Response.RR...)
|
||||
result.Response.Last = tmp.Response.Last
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// AddRecord adds a DNS record.
|
||||
// https://portal.brandit.com/apidocv3#addDNSRR
|
||||
func (c *Client) AddRecord(domainName, account, newRecordID string, record Record) (*AddRecord, error) {
|
||||
// Create a new query
|
||||
|
||||
query := url.Values{}
|
||||
query.Add("command", "addDNSRR")
|
||||
query.Add("account", account)
|
||||
query.Add("dnszone", domainName)
|
||||
query.Add("rrdata", strings.Join([]string{record.Name, fmt.Sprint(record.TTL), "IN", record.Type, record.Content}, " "))
|
||||
query.Add("key", newRecordID)
|
||||
|
||||
result := &AddRecord{}
|
||||
|
||||
err := c.do(query, result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("do: %w", err)
|
||||
}
|
||||
result.Record = strings.Join([]string{record.Name, fmt.Sprint(record.TTL), "IN", record.Type, record.Content}, " ")
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DeleteRecord deletes a DNS record.
|
||||
// https://portal.brandit.com/apidocv3#deleteDNSRR
|
||||
func (c *Client) DeleteRecord(domainName, account, dnsRecord, recordID string) (*DeleteRecord, error) {
|
||||
// Create a new query
|
||||
query := url.Values{}
|
||||
query.Add("command", "deleteDNSRR")
|
||||
query.Add("account", account)
|
||||
query.Add("dnszone", domainName)
|
||||
query.Add("rrdata", dnsRecord)
|
||||
query.Add("key", recordID)
|
||||
|
||||
result := &DeleteRecord{}
|
||||
|
||||
err := c.do(query, result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("do: %w", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// StatusDomain returns the status of a domain and account associated with it.
|
||||
// https://portal.brandit.com/apidocv3#statusDomain
|
||||
func (c *Client) StatusDomain(domain string) (*StatusDomain, error) {
|
||||
// Create a new query
|
||||
query := url.Values{}
|
||||
|
||||
query.Add("command", "statusDomain")
|
||||
query.Add("domain", domain)
|
||||
|
||||
result := &StatusDomain{}
|
||||
|
||||
err := c.do(query, result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("do: %w", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Client) do(query url.Values, result any) error {
|
||||
// Add signature
|
||||
v, err := sign(c.apiUsername, c.apiKey, query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("signature: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.PostForm(c.BaseURL, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
raw, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read response body: %w", err)
|
||||
}
|
||||
|
||||
// Unmarshal the error response, because the API returns a 200 OK even if there is an error.
|
||||
var apiError APIError
|
||||
err = json.Unmarshal(raw, &apiError)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unmarshal error response: %w %s", err, string(raw))
|
||||
}
|
||||
|
||||
if apiError.Code > 299 || apiError.Status != "success" {
|
||||
return apiError
|
||||
}
|
||||
|
||||
err = json.Unmarshal(raw, result)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unmarshal response body: %w %s", err, string(raw))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sign(apiUsername, apiKey string, query url.Values) (url.Values, error) {
|
||||
location, err := time.LoadLocation("GMT")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("time location: %w", err)
|
||||
}
|
||||
|
||||
timestamp := time.Now().In(location).Format("2006-01-02T15:04:05Z")
|
||||
|
||||
canonicalRequest := fmt.Sprintf("%s%s%s", apiUsername, timestamp, defaultBaseURL)
|
||||
|
||||
mac := hmac.New(sha256.New, []byte(apiKey))
|
||||
_, err = mac.Write([]byte(canonicalRequest))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hashed := mac.Sum(nil)
|
||||
signature := hex.EncodeToString(hashed)
|
||||
|
||||
query.Add("user", apiUsername)
|
||||
query.Add("timestamp", timestamp)
|
||||
query.Add("signature", signature)
|
||||
|
||||
return query, nil
|
||||
}
|
149
providers/dns/brandit/internal/client_test.go
Normal file
149
providers/dns/brandit/internal/client_test.go
Normal file
|
@ -0,0 +1,149 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setupTest(t *testing.T, file string) *Client {
|
||||
t.Helper()
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
open, err := os.Open(file)
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() { _ = open.Close() }()
|
||||
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
_, err = io.Copy(rw, open)
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client, err := NewClient("test_user", "apiKey")
|
||||
require.NoError(t, err)
|
||||
|
||||
client.HTTPClient = server.Client()
|
||||
client.BaseURL = server.URL
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func TestClient_StatusDomain(t *testing.T) {
|
||||
client := setupTest(t, "./fixtures/status-domain.json")
|
||||
|
||||
domain, err := client.StatusDomain("example.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := &StatusDomain{
|
||||
Response: StatusResponse{
|
||||
RenewalMode: []string{"DEFAULT"},
|
||||
Status: []string{"clientTransferProhibited"},
|
||||
TransferLock: []int{1},
|
||||
Registrar: []string{"brandit"},
|
||||
PaidUntilDate: []string{"2021-12-15 05:00:00.0"},
|
||||
Nameserver: []string{"NS1.RRPPROXY.NET", "NS2.RRPPROXY.NET"},
|
||||
RegistrationExpirationDate: []string{"2021-12-15 05:00:00.0"},
|
||||
Domain: []string{"example.com"},
|
||||
RenewalDate: []string{"2024-01-19 05:00:00.0"},
|
||||
UpdatedDate: []string{"2022-12-16 08:01:27.0"},
|
||||
BillingContact: []string{"example"},
|
||||
XDomainRoID: []string{"example"},
|
||||
AdminContact: []string{"example"},
|
||||
TechContact: []string{"example"},
|
||||
DomainIDN: []string{"example.com"},
|
||||
CreatedDate: []string{"2016-12-16 05:00:00.0"},
|
||||
RegistrarTransferDate: []string{"2021-12-09 05:17:42.0"},
|
||||
Zone: []string{"com"},
|
||||
Auth: []string{"example"},
|
||||
UpdatedBy: []string{"example"},
|
||||
RoID: []string{"example"},
|
||||
OwnerContact: []string{"example"},
|
||||
CreatedBy: []string{"example"},
|
||||
TransferMode: []string{"auto"},
|
||||
},
|
||||
Code: 200,
|
||||
Status: "success",
|
||||
Error: "",
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, domain)
|
||||
}
|
||||
|
||||
func TestClient_ListRecords(t *testing.T) {
|
||||
client := setupTest(t, "./fixtures/list-records.json")
|
||||
|
||||
resp, err := client.ListRecords("example", "example.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := &ListRecords{
|
||||
Response: ListRecordsResponse{
|
||||
Limit: []int{100},
|
||||
Column: []string{"rr"},
|
||||
Count: []int{1},
|
||||
First: []int{0},
|
||||
Total: []int{1},
|
||||
RR: []string{"example.com. 600 IN TXT txttxttxt"},
|
||||
Last: []int{0},
|
||||
},
|
||||
Code: 200,
|
||||
Status: "success",
|
||||
Error: "",
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, resp)
|
||||
}
|
||||
|
||||
func TestClient_AddRecord(t *testing.T) {
|
||||
client := setupTest(t, "./fixtures/add-record.json")
|
||||
|
||||
testRecord := Record{
|
||||
ID: 2565,
|
||||
Type: "TXT",
|
||||
Name: "example.com",
|
||||
Content: "txttxttxt",
|
||||
TTL: 600,
|
||||
}
|
||||
resp, err := client.AddRecord("example.com", "test", "2565", testRecord)
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := &AddRecord{
|
||||
Response: AddRecordResponse{
|
||||
ZoneType: []string{"com"},
|
||||
Signed: []int{1},
|
||||
},
|
||||
Record: "example.com 600 IN TXT txttxttxt",
|
||||
Code: 200,
|
||||
Status: "success",
|
||||
Error: "",
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, resp)
|
||||
}
|
||||
|
||||
func TestClient_DeleteRecord(t *testing.T) {
|
||||
client := setupTest(t, "./fixtures/delete-record.json")
|
||||
|
||||
resp, err := client.DeleteRecord("example.com", "test", "example.com 600 IN TXT txttxttxt", "2374")
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := &DeleteRecord{
|
||||
Code: 200,
|
||||
Status: "success",
|
||||
Error: "",
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, resp)
|
||||
}
|
14
providers/dns/brandit/internal/fixtures/add-record.json
Normal file
14
providers/dns/brandit/internal/fixtures/add-record.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"response": {
|
||||
"zonetype": [
|
||||
"com"
|
||||
],
|
||||
"signed": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"record": "example.com. 600 IN TXT txttxttxt",
|
||||
"code": 200,
|
||||
"status": "success",
|
||||
"error": ""
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"code": 200,
|
||||
"status": "success",
|
||||
"error": ""
|
||||
}
|
28
providers/dns/brandit/internal/fixtures/list-records.json
Normal file
28
providers/dns/brandit/internal/fixtures/list-records.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"response": {
|
||||
"limit": [
|
||||
100
|
||||
],
|
||||
"column": [
|
||||
"rr"
|
||||
],
|
||||
"count": [
|
||||
1
|
||||
],
|
||||
"first": [
|
||||
0
|
||||
],
|
||||
"total": [
|
||||
1
|
||||
],
|
||||
"rr": [
|
||||
"example.com. 600 IN TXT txttxttxt"
|
||||
],
|
||||
"last": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"code": 200,
|
||||
"status": "success",
|
||||
"error": ""
|
||||
}
|
80
providers/dns/brandit/internal/fixtures/status-domain.json
Normal file
80
providers/dns/brandit/internal/fixtures/status-domain.json
Normal file
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"response": {
|
||||
"renewalmode": [
|
||||
"DEFAULT"
|
||||
],
|
||||
"status": [
|
||||
"clientTransferProhibited"
|
||||
],
|
||||
"transferlock": [
|
||||
1
|
||||
],
|
||||
"registrar": [
|
||||
"brandit"
|
||||
],
|
||||
"paiduntildate": [
|
||||
"2021-12-15 05:00:00.0"
|
||||
],
|
||||
"nameserver": [
|
||||
"NS1.RRPPROXY.NET",
|
||||
"NS2.RRPPROXY.NET"
|
||||
],
|
||||
"registrationexpirationdate": [
|
||||
"2021-12-15 05:00:00.0"
|
||||
],
|
||||
"domain": [
|
||||
"example.com"
|
||||
],
|
||||
"renewaldate": [
|
||||
"2024-01-19 05:00:00.0"
|
||||
],
|
||||
"updateddate": [
|
||||
"2022-12-16 08:01:27.0"
|
||||
],
|
||||
"billingcontact": [
|
||||
"example"
|
||||
],
|
||||
"x-domain-roid": [
|
||||
"example"
|
||||
],
|
||||
"admincontact": [
|
||||
"example"
|
||||
],
|
||||
"techcontact": [
|
||||
"example"
|
||||
],
|
||||
"domainidn": [
|
||||
"example.com"
|
||||
],
|
||||
"createddate": [
|
||||
"2016-12-16 05:00:00.0"
|
||||
],
|
||||
"registrartransferdate": [
|
||||
"2021-12-09 05:17:42.0"
|
||||
],
|
||||
"zone": [
|
||||
"com"
|
||||
],
|
||||
"auth": [
|
||||
"example"
|
||||
],
|
||||
"updatedby": [
|
||||
"example"
|
||||
],
|
||||
"roid": [
|
||||
"example"
|
||||
],
|
||||
"ownercontact": [
|
||||
"example"
|
||||
],
|
||||
"createdby": [
|
||||
"example"
|
||||
],
|
||||
"transfermode": [
|
||||
"auto"
|
||||
]
|
||||
},
|
||||
"code": 200,
|
||||
"status": "success",
|
||||
"error": ""
|
||||
}
|
91
providers/dns/brandit/internal/types.go
Normal file
91
providers/dns/brandit/internal/types.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package internal
|
||||
|
||||
import "fmt"
|
||||
|
||||
type StatusDomain struct {
|
||||
Response StatusResponse `json:"response,omitempty"`
|
||||
Code int `json:"code"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type StatusResponse struct {
|
||||
RenewalMode []string `json:"renewalmode"`
|
||||
Status []string `json:"status"`
|
||||
TransferLock []int `json:"transferlock"`
|
||||
Registrar []string `json:"registrar"`
|
||||
PaidUntilDate []string `json:"paiduntildate"`
|
||||
Nameserver []string `json:"nameserver"`
|
||||
RegistrationExpirationDate []string `json:"registrationexpirationdate"`
|
||||
Domain []string `json:"domain"`
|
||||
RenewalDate []string `json:"renewaldate"`
|
||||
UpdatedDate []string `json:"updateddate"`
|
||||
BillingContact []string `json:"billingcontact"`
|
||||
XDomainRoID []string `json:"x-domain-roid"`
|
||||
AdminContact []string `json:"admincontact"`
|
||||
TechContact []string `json:"techcontact"`
|
||||
DomainIDN []string `json:"domainidn"`
|
||||
CreatedDate []string `json:"createddate"`
|
||||
RegistrarTransferDate []string `json:"registrartransferdate"`
|
||||
Zone []string `json:"zone"`
|
||||
Auth []string `json:"auth"`
|
||||
UpdatedBy []string `json:"updatedby"`
|
||||
RoID []string `json:"roid"`
|
||||
OwnerContact []string `json:"ownercontact"`
|
||||
CreatedBy []string `json:"createdby"`
|
||||
TransferMode []string `json:"transfermode"`
|
||||
}
|
||||
|
||||
type ListRecords struct {
|
||||
Response ListRecordsResponse `json:"response,omitempty"`
|
||||
Code int `json:"code"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type ListRecordsResponse struct {
|
||||
Limit []int `json:"limit,omitempty"`
|
||||
Column []string `json:"column,omitempty"`
|
||||
Count []int `json:"count,omitempty"`
|
||||
First []int `json:"first,omitempty"`
|
||||
Total []int `json:"total,omitempty"`
|
||||
RR []string `json:"rr,omitempty"`
|
||||
Last []int `json:"last,omitempty"`
|
||||
}
|
||||
|
||||
type APIError struct {
|
||||
Code int `json:"code"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"error"`
|
||||
}
|
||||
|
||||
func (a APIError) Error() string {
|
||||
return fmt.Sprintf("code: %d, status: %s, message: %s", a.Code, a.Status, a.Message)
|
||||
}
|
||||
|
||||
type AddRecord struct {
|
||||
Response AddRecordResponse `json:"response"`
|
||||
Record string `json:"record"`
|
||||
Code int `json:"code"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type AddRecordResponse struct {
|
||||
ZoneType []string `json:"zonetype"`
|
||||
Signed []int `json:"signed"`
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Name string `json:"name,omitempty"` // subdomain name or @ if you don't want subdomain
|
||||
Content string `json:"content,omitempty"`
|
||||
TTL int `json:"ttl,omitempty"` // default 600
|
||||
}
|
||||
|
||||
type DeleteRecord struct {
|
||||
Code int `json:"code"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"`
|
||||
}
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/go-acme/lego/v4/providers/dns/azure"
|
||||
"github.com/go-acme/lego/v4/providers/dns/bindman"
|
||||
"github.com/go-acme/lego/v4/providers/dns/bluecat"
|
||||
"github.com/go-acme/lego/v4/providers/dns/brandit"
|
||||
"github.com/go-acme/lego/v4/providers/dns/bunny"
|
||||
"github.com/go-acme/lego/v4/providers/dns/checkdomain"
|
||||
"github.com/go-acme/lego/v4/providers/dns/civo"
|
||||
|
@ -143,6 +144,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
|
|||
return bindman.NewDNSProvider()
|
||||
case "bluecat":
|
||||
return bluecat.NewDNSProvider()
|
||||
case "brandit":
|
||||
return brandit.NewDNSProvider()
|
||||
case "bunny":
|
||||
return bunny.NewDNSProvider()
|
||||
case "checkdomain":
|
||||
|
|
Loading…
Reference in a new issue