Add DNS provider for Efficient IP (#1945)

This commit is contained in:
Ludovic Fernandez 2023-07-01 12:37:40 +02:00 committed by GitHub
parent 2d4dc8fb38
commit b4a2913a62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1761 additions and 22 deletions

View file

@ -62,27 +62,27 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
| [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/) | | [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/) | | [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/) | | [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/) | | [Efficient IP](https://go-acme.github.io/lego/dns/efficientip/) | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [PowerDNS](https://go-acme.github.io/lego/dns/pdns/) | [Rackspace](https://go-acme.github.io/lego/dns/rackspace/) | [RcodeZero](https://go-acme.github.io/lego/dns/rcodezero/) | [reg.ru](https://go-acme.github.io/lego/dns/regru/) | | [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/) | [RcodeZero](https://go-acme.github.io/lego/dns/rcodezero/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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/) |
| [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/) | | [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 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/) | | | [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 --> <!-- END DNS PROVIDERS LIST -->

View file

@ -49,6 +49,7 @@ func allDNSCodes() string {
"dynu", "dynu",
"easydns", "easydns",
"edgedns", "edgedns",
"efficientip",
"epik", "epik",
"exec", "exec",
"exoscale", "exoscale",
@ -889,6 +890,30 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln() ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/edgedns`) ew.writeln(`More information: https://go-acme.github.io/lego/dns/edgedns`)
case "efficientip":
// generated from: providers/dns/efficientip/efficientip.toml
ew.writeln(`Configuration for Efficient IP.`)
ew.writeln(`Code: 'efficientip'`)
ew.writeln(`Since: 'v4.13.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "EFFICIENTIP_DNS_NAME": DNS name (ex: dns.smart)`)
ew.writeln(` - "EFFICIENTIP_HOSTNAME": Hostname (ex: foo.example.com)`)
ew.writeln(` - "EFFICIENTIP_PASSWORD": Password`)
ew.writeln(` - "EFFICIENTIP_USERNAME": Username`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "EFFICIENTIP_HTTP_TIMEOUT": API request timeout`)
ew.writeln(` - "EFFICIENTIP_POLLING_INTERVAL": Time between DNS propagation check`)
ew.writeln(` - "EFFICIENTIP_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
ew.writeln(` - "EFFICIENTIP_TTL": The TTL of the TXT record used for the DNS challenge`)
ew.writeln(` - "EFFICIENTIP_VIEW_NAME": View name (ex: external)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/efficientip`)
case "epik": case "epik":
// generated from: providers/dns/epik/epik.toml // generated from: providers/dns/epik/epik.toml
ew.writeln(`Configuration for Epik.`) ew.writeln(`Configuration for Epik.`)

View file

@ -0,0 +1,71 @@
---
title: "Efficient IP"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: efficientip
dnsprovider:
since: "v4.13.0"
code: "efficientip"
url: "https://efficientip.com/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/efficientip/efficientip.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [Efficient IP](https://efficientip.com/).
<!--more-->
- Code: `efficientip`
- Since: v4.13.0
Here is an example bash command using the Efficient IP provider:
```bash
EFFICIENTIP_USERNAME="user" \
EFFICIENTIP_PASSWORD="secret" \
EFFICIENTIP_HOSTNAME="ipam.example.org" \
EFFICIENTIP_DNS_NAME="dns.smart" \
lego --email you@example.com --dns efficientip --domains my.example.org run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `EFFICIENTIP_DNS_NAME` | DNS name (ex: dns.smart) |
| `EFFICIENTIP_HOSTNAME` | Hostname (ex: foo.example.com) |
| `EFFICIENTIP_PASSWORD` | Password |
| `EFFICIENTIP_USERNAME` | 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 |
|--------------------------------|-------------|
| `EFFICIENTIP_HTTP_TIMEOUT` | API request timeout |
| `EFFICIENTIP_POLLING_INTERVAL` | Time between DNS propagation check |
| `EFFICIENTIP_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
| `EFFICIENTIP_TTL` | The TTL of the TXT record used for the DNS challenge |
| `EFFICIENTIP_VIEW_NAME` | View name (ex: external) |
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" >}}).
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/efficientip/efficientip.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -136,7 +136,7 @@ To display the documentation for a specific DNS provider, run:
$ lego dnshelp -c code $ lego dnshelp -c code
Supported DNS providers: Supported DNS providers:
acme-dns, alidns, allinkl, arvancloud, auroradns, autodns, azure, bindman, bluecat, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudxns, conoha, constellix, derak, 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, rcodezero, 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, derak, desec, designate, digitalocean, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dynu, easydns, edgedns, efficientip, 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, rcodezero, 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 More information: https://go-acme.github.io/lego/dns
""" """

View file

@ -40,6 +40,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/dynu" "github.com/go-acme/lego/v4/providers/dns/dynu"
"github.com/go-acme/lego/v4/providers/dns/easydns" "github.com/go-acme/lego/v4/providers/dns/easydns"
"github.com/go-acme/lego/v4/providers/dns/edgedns" "github.com/go-acme/lego/v4/providers/dns/edgedns"
"github.com/go-acme/lego/v4/providers/dns/efficientip"
"github.com/go-acme/lego/v4/providers/dns/epik" "github.com/go-acme/lego/v4/providers/dns/epik"
"github.com/go-acme/lego/v4/providers/dns/exec" "github.com/go-acme/lego/v4/providers/dns/exec"
"github.com/go-acme/lego/v4/providers/dns/exoscale" "github.com/go-acme/lego/v4/providers/dns/exoscale"
@ -198,6 +199,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return easydns.NewDNSProvider() return easydns.NewDNSProvider()
case "edgedns", "fastdns": // "fastdns" is for compatibility with v3, must be dropped in v5 case "edgedns", "fastdns": // "fastdns" is for compatibility with v3, must be dropped in v5
return edgedns.NewDNSProvider() return edgedns.NewDNSProvider()
case "efficientip":
return efficientip.NewDNSProvider()
case "epik": case "epik":
return epik.NewDNSProvider() return epik.NewDNSProvider()
case "exec": case "exec":

View file

@ -0,0 +1,152 @@
// Package efficientip implements a DNS provider for solving the DNS-01 challenge using Efficient IP.
package efficientip
import (
"context"
"errors"
"fmt"
"net/http"
"time"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/platform/config/env"
"github.com/go-acme/lego/v4/providers/dns/efficientip/internal"
)
// Environment variables names.
const (
envNamespace = "EFFICIENTIP_"
EnvUsername = envNamespace + "USERNAME"
EnvPassword = envNamespace + "PASSWORD"
EnvHostname = envNamespace + "HOSTNAME"
EnvDNSName = envNamespace + "DNS_NAME"
EnvViewName = envNamespace + "VIEW_NAME"
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
)
// Config is used to configure the creation of the DNSProvider.
type Config struct {
Username string
Password string
Hostname string
DNSName string
ViewName string
PropagationTimeout time.Duration
PollingInterval time.Duration
HTTPClient *http.Client
}
// NewDefaultConfig returns a default configuration for the DNSProvider.
func NewDefaultConfig() *Config {
return &Config{
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
HTTPClient: &http.Client{
Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 10*time.Second),
},
}
}
// DNSProvider implements the challenge.Provider interface.
type DNSProvider struct {
config *Config
client *internal.Client
}
// NewDNSProvider returns a new DNS provider
// using environment variable EFFICIENTIP_API_KEY for adding and removing the DNS record.
func NewDNSProvider() (*DNSProvider, error) {
values, err := env.Get(EnvUsername, EnvPassword, EnvHostname, EnvDNSName)
if err != nil {
return nil, fmt.Errorf("efficientip: %w", err)
}
config := NewDefaultConfig()
config.Username = values[EnvUsername]
config.Password = values[EnvPassword]
config.Hostname = values[EnvHostname]
config.DNSName = values[EnvDNSName]
config.ViewName = env.GetOrDefaultString(EnvViewName, "")
return NewDNSProviderConfig(config)
}
// NewDNSProviderConfig return a DNSProvider instance configured for Efficient IP.
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, errors.New("efficientip: the configuration of the DNS provider is nil")
}
if config.Username == "" {
return nil, errors.New("efficientip: missing username")
}
if config.Password == "" {
return nil, errors.New("efficientip: missing password")
}
if config.Hostname == "" {
return nil, errors.New("efficientip: missing hostname")
}
if config.DNSName == "" {
return nil, errors.New("efficientip: missing dnsname")
}
client := internal.NewClient(config.Hostname, config.Username, config.Password)
if config.HTTPClient != nil {
client.HTTPClient = config.HTTPClient
}
return &DNSProvider{config: config, client: client}, nil
}
func (d *DNSProvider) Present(domain, _, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
ctx := context.Background()
r := internal.ResourceRecord{
RRName: dns01.UnFqdn(info.EffectiveFQDN),
RRType: "TXT",
Value1: info.Value,
DNSName: d.config.DNSName,
DNSViewName: d.config.ViewName,
}
_, err := d.client.AddRecord(ctx, r)
if err != nil {
return fmt.Errorf("efficientip: add record: %w", err)
}
return nil
}
func (d *DNSProvider) CleanUp(domain, _, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
ctx := context.Background()
params := internal.DeleteInputParameters{
RRName: dns01.UnFqdn(info.EffectiveFQDN),
RRType: "TXT",
RRValue1: info.Value,
DNSName: d.config.DNSName,
DNSViewName: d.config.ViewName,
}
_, err := d.client.DeleteRecord(ctx, params)
if err != nil {
return fmt.Errorf("efficientip: delete record: %w", err)
}
return nil
}
// Timeout returns the timeout and interval to use when checking for DNS propagation.
// Adjusting here to cope with spikes in propagation times.
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}

View file

@ -0,0 +1,26 @@
Name = "Efficient IP"
Description = ''''''
URL = "https://efficientip.com/"
Code = "efficientip"
Since = "v4.13.0"
Example = '''
EFFICIENTIP_USERNAME="user" \
EFFICIENTIP_PASSWORD="secret" \
EFFICIENTIP_HOSTNAME="ipam.example.org" \
EFFICIENTIP_DNS_NAME="dns.smart" \
lego --email you@example.com --dns efficientip --domains my.example.org run
'''
[Configuration]
[Configuration.Credentials]
EFFICIENTIP_USERNAME = "Username"
EFFICIENTIP_PASSWORD = "Password"
EFFICIENTIP_HOSTNAME = "Hostname (ex: foo.example.com)"
EFFICIENTIP_DNS_NAME = "DNS name (ex: dns.smart)"
[Configuration.Additional]
EFFICIENTIP_VIEW_NAME = "View name (ex: external)"
EFFICIENTIP_POLLING_INTERVAL = "Time between DNS propagation check"
EFFICIENTIP_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
EFFICIENTIP_TTL = "The TTL of the TXT record used for the DNS challenge"
EFFICIENTIP_HTTP_TIMEOUT = "API request timeout"

View file

@ -0,0 +1,201 @@
package efficientip
import (
"testing"
"time"
"github.com/go-acme/lego/v4/platform/tester"
"github.com/stretchr/testify/require"
)
const envDomain = envNamespace + "DOMAIN"
var envTest = tester.NewEnvTest(
EnvUsername,
EnvPassword,
EnvHostname,
EnvDNSName,
EnvViewName,
).WithDomain(envDomain)
func TestNewDNSProvider(t *testing.T) {
testCases := []struct {
desc string
envVars map[string]string
expected string
}{
{
desc: "success",
envVars: map[string]string{
EnvUsername: "user",
EnvPassword: "secret",
EnvHostname: "example.com",
EnvDNSName: "dns.smart",
},
},
{
desc: "missing username",
envVars: map[string]string{
EnvUsername: "",
EnvPassword: "secret",
EnvHostname: "example.com",
EnvDNSName: "dns.smart",
},
expected: "efficientip: some credentials information are missing: EFFICIENTIP_USERNAME",
},
{
desc: "missing password",
envVars: map[string]string{
EnvUsername: "user",
EnvPassword: "",
EnvHostname: "example.com",
EnvDNSName: "dns.smart",
},
expected: "efficientip: some credentials information are missing: EFFICIENTIP_PASSWORD",
},
{
desc: "missing hostname",
envVars: map[string]string{
EnvUsername: "user",
EnvPassword: "secret",
EnvHostname: "",
EnvDNSName: "dns.smart",
},
expected: "efficientip: some credentials information are missing: EFFICIENTIP_HOSTNAME",
},
{
desc: "missing DNS name",
envVars: map[string]string{
EnvUsername: "user",
EnvPassword: "secret",
EnvHostname: "example.com",
EnvDNSName: "",
},
expected: "efficientip: some credentials information are missing: EFFICIENTIP_DNS_NAME",
},
{
desc: "missing credentials",
envVars: map[string]string{},
expected: "efficientip: some credentials information are missing: EFFICIENTIP_USERNAME,EFFICIENTIP_PASSWORD,EFFICIENTIP_HOSTNAME,EFFICIENTIP_DNS_NAME",
},
}
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)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestNewDNSProviderConfig(t *testing.T) {
testCases := []struct {
desc string
username string
password string
hostname string
dnsName string
expected string
}{
{
desc: "success",
username: "user",
password: "secret",
hostname: "example.com",
dnsName: "dns.smart",
},
{
desc: "missing username",
password: "secret",
hostname: "example.com",
dnsName: "dns.smart",
expected: "efficientip: missing username",
},
{
desc: "missing password",
username: "user",
hostname: "example.com",
dnsName: "dns.smart",
expected: "efficientip: missing password",
},
{
desc: "missing hostname",
username: "user",
password: "secret",
dnsName: "dns.smart",
expected: "efficientip: missing hostname",
},
{
desc: "missing dnsName",
username: "user",
password: "secret",
hostname: "example.com",
expected: "efficientip: missing dnsname",
},
{
desc: "missing all",
expected: "efficientip: missing username",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
config := NewDefaultConfig()
config.Username = test.username
config.Password = test.password
config.Hostname = test.hostname
config.DNSName = test.dnsName
p, err := NewDNSProviderConfig(config)
if test.expected == "" {
require.NoError(t, err)
require.NotNil(t, p)
require.NotNil(t, p.config)
} 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)
time.Sleep(1 * time.Second)
err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
require.NoError(t, err)
}

View file

@ -0,0 +1,209 @@
package internal
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
querystring "github.com/google/go-querystring/query"
)
type Client struct {
baseURL *url.URL
HTTPClient *http.Client
username string
password string
}
func NewClient(hostname string, username string, password string) *Client {
baseURL, _ := url.Parse(fmt.Sprintf("https://%s/rest/", hostname))
return &Client{
HTTPClient: &http.Client{Timeout: 5 * time.Second},
baseURL: baseURL,
username: username,
password: password,
}
}
func (c Client) ListRecords(ctx context.Context) ([]ResourceRecord, error) {
endpoint := c.baseURL.JoinPath("dns_rr_list")
req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return nil, err
}
var result []ResourceRecord
err = c.do(req, &result)
if err != nil {
return nil, err
}
return result, nil
}
func (c Client) GetRecord(ctx context.Context, id string) (*ResourceRecord, error) {
endpoint := c.baseURL.JoinPath("dns_rr_info")
query := endpoint.Query()
query.Set("rr_id", id)
endpoint.RawQuery = query.Encode()
req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return nil, err
}
var result []ResourceRecord
err = c.do(req, &result)
if err != nil {
return nil, err
}
if len(result) == 0 {
return nil, nil
}
return &result[0], nil
}
func (c Client) AddRecord(ctx context.Context, record ResourceRecord) (*BaseOutput, error) {
endpoint := c.baseURL.JoinPath("dns_rr_add")
req, err := newJSONRequest(ctx, http.MethodPost, endpoint, record)
if err != nil {
return nil, err
}
var result []BaseOutput
err = c.do(req, &result)
if err != nil {
return nil, err
}
if len(result) == 0 {
return nil, nil
}
return &result[0], nil
}
func (c Client) DeleteRecord(ctx context.Context, params DeleteInputParameters) (*BaseOutput, error) {
endpoint := c.baseURL.JoinPath("dns_rr_delete")
// (rr_id || (rr_name && (dns_id || dns_name || hostaddr)))
v, err := querystring.Values(params)
if err != nil {
return nil, fmt.Errorf("query parameters: %w", err)
}
endpoint.RawQuery = v.Encode()
req, err := newJSONRequest(ctx, http.MethodDelete, endpoint, nil)
if err != nil {
return nil, err
}
var result []BaseOutput
err = c.do(req, &result)
if err != nil {
return nil, err
}
if len(result) == 0 {
return nil, nil
}
return &result[0], nil
}
func (c Client) do(req *http.Request, result any) error {
req.SetBasicAuth(c.username, c.password)
req.Header.Set("cache-control", "no-cache")
resp, err := c.HTTPClient.Do(req)
if err != nil {
return errutils.NewHTTPDoError(req, err)
}
defer func() { _ = resp.Body.Close() }()
switch req.Method {
case http.MethodPost:
if resp.StatusCode != http.StatusCreated {
return parseError(req, resp)
}
default:
if resp.StatusCode == http.StatusNoContent {
return nil
}
if resp.StatusCode != http.StatusOK {
return parseError(req, resp)
}
}
if result == nil {
return nil
}
raw, err := io.ReadAll(resp.Body)
if err != nil {
return errutils.NewReadResponseError(req, resp.StatusCode, err)
}
err = json.Unmarshal(raw, result)
if err != nil {
return errutils.NewUnmarshalError(req, resp.StatusCode, raw, err)
}
return nil
}
func newJSONRequest(ctx context.Context, method string, endpoint *url.URL, payload any) (*http.Request, error) {
buf := new(bytes.Buffer)
if payload != nil {
err := json.NewEncoder(buf).Encode(payload)
if err != nil {
return nil, fmt.Errorf("failed to create request JSON body: %w", err)
}
}
req, err := http.NewRequestWithContext(ctx, method, endpoint.String(), buf)
if err != nil {
return nil, fmt.Errorf("unable to create request: %w", err)
}
req.Header.Set("Accept", "application/json")
if payload != nil {
req.Header.Set("Content-Type", "application/json")
}
return req, nil
}
func parseError(req *http.Request, resp *http.Response) error {
raw, _ := io.ReadAll(resp.Body)
var response APIError
err := json.Unmarshal(raw, &response)
if err != nil {
return errutils.NewUnexpectedStatusCodeError(req, resp.StatusCode, raw)
}
return fmt.Errorf("[status code %d] %w", resp.StatusCode, response)
}

View file

@ -0,0 +1,427 @@
package internal
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func setupTest(t *testing.T, method, pattern string, status int, file string) *Client {
t.Helper()
mux := http.NewServeMux()
server := httptest.NewServer(mux)
t.Cleanup(server.Close)
mux.HandleFunc(pattern, func(rw http.ResponseWriter, req *http.Request) {
if req.Method != method {
http.Error(rw, fmt.Sprintf("unsupported method %s", req.Method), http.StatusBadRequest)
return
}
username, password, ok := req.BasicAuth()
if !ok {
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
if username != "user" {
http.Error(rw, fmt.Sprintf("username: want %s got %s", username, "user"), http.StatusUnauthorized)
return
}
if password != "secret" {
http.Error(rw, fmt.Sprintf("password: want %s got %s", password, "secret"), http.StatusUnauthorized)
return
}
open, err := os.Open(filepath.Join("fixtures", file))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
defer func() { _ = open.Close() }()
rw.WriteHeader(status)
_, err = io.Copy(rw, open)
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
})
srvURL, _ := url.Parse(server.URL)
client := NewClient(srvURL.Host, "user", "secret")
client.HTTPClient = server.Client()
client.baseURL, _ = url.Parse(server.URL)
return client
}
func TestListRecords(t *testing.T) {
client := setupTest(t, http.MethodGet, "/dns_rr_list", http.StatusOK, "dns_rr_list.json")
ctx := context.Background()
records, err := client.ListRecords(ctx)
require.NoError(t, err)
expected := []ResourceRecord{
{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "test1",
RRAuthGsstsig: "0",
RRFullName: "test.lego.example.com",
RRFullNameUTF: "test.lego.example.com",
RRGlue: "test",
RRGlueID: "21",
RRID: "239",
RRNameID: "26",
RRType: "TXT",
RRTypeID: "6",
RRValueID: "274",
TTL: "3600",
Value1: "test1",
VDNSParentID: "0",
VDNSParentName: "#",
},
{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "test2",
RRAuthGsstsig: "0",
RRFullName: "test.lego.example.com",
RRFullNameUTF: "test.lego.example.com",
RRGlue: "test",
RRGlueID: "21",
RRID: "241",
RRNameID: "26",
RRType: "TXT",
RRTypeID: "6",
RRValueID: "275",
TTL: "3600",
Value1: "test2",
VDNSParentID: "0",
VDNSParentName: "#",
},
{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "test1",
RRAuthGsstsig: "0",
RRFullName: "lego.example.com",
RRFullNameUTF: "lego.example.com",
RRGlue: ".",
RRGlueID: "3",
RRID: "245",
RRNameID: "21",
RRType: "TXT",
RRTypeID: "6",
RRValueID: "274",
TTL: "3600",
Value1: "test1",
VDNSParentID: "0",
VDNSParentName: "#",
},
{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "test2",
RRAuthGsstsig: "0",
RRFullName: "lego.example.com",
RRFullNameUTF: "lego.example.com",
RRGlue: ".",
RRGlueID: "3",
RRID: "247",
RRNameID: "21",
RRType: "TXT",
RRTypeID: "6",
RRValueID: "275",
TTL: "3600",
Value1: "test2",
VDNSParentID: "0",
VDNSParentName: "#",
},
{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "dns.smart, root@lego.example.com, 2023062719, 1200, 600, 1209600, 3600",
RRAuthGsstsig: "0",
RRFullName: "lego.example.com",
RRFullNameUTF: "lego.example.com",
RRGlue: ".",
RRGlueID: "3",
RRID: "201",
RRNameID: "21",
RRType: "SOA",
RRTypeID: "2",
RRValueID: "282",
TTL: "3600",
Value1: "dns.smart",
Value2: "root@lego.example.com",
Value3: "2023062719",
Value4: "1200",
Value5: "600",
Value6: "1209600",
Value7: "3600",
VDNSParentID: "0",
VDNSParentName: "#",
},
{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "dns.smart",
RRAuthGsstsig: "0",
RRFullName: "lego.example.com",
RRFullNameUTF: "lego.example.com",
RRGlue: ".",
RRGlueID: "3",
RRID: "200",
RRNameID: "21",
RRType: "NS",
RRTypeID: "1",
RRValueID: "10",
TTL: "3600",
Value1: "dns.smart",
VDNSParentID: "0",
VDNSParentName: "#",
},
{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "127.0.0.1",
RRAuthGsstsig: "0",
RRFullName: "loopback.lego.example.com",
RRFullNameUTF: "loopback.lego.example.com",
RRGlue: "loopback",
RRGlueID: "17",
RRID: "208",
RRNameID: "22",
RRType: "A",
RRTypeID: "3",
RRValueID: "237",
RRValueIP4Addr: "7f000001",
RRValueIPAddr: "7f000001",
TTL: "3600",
Value1: "127.0.0.1",
VDNSParentID: "0",
VDNSParentName: "#",
},
}
assert.Equal(t, expected, records)
}
func TestGetRecord(t *testing.T) {
client := setupTest(t, http.MethodGet, "/dns_rr_info", http.StatusOK, "dns_rr_info.json")
ctx := context.Background()
record, err := client.GetRecord(ctx, "239")
require.NoError(t, err)
expected := &ResourceRecord{
ErrorCode: "0",
DelayedCreateTime: "0",
DelayedDeleteTime: "0",
DelayedTime: "0",
DNSCloud: "0",
DNSID: "3",
DNSName: "dns.smart",
DNSType: "vdns",
DNSViewID: "0",
DNSViewName: "#",
DNSZoneID: "9",
DNSZoneIsReverse: "0",
DNSZoneIsRpz: "0",
DNSZoneName: "lego.example.com",
DNSZoneNameUTF: "lego.example.com",
DNSZoneSiteName: "#",
DNSZoneSortZone: "lego.example.com",
DNSZoneType: "master",
RRAllValue: "test1",
RRAuthGsstsig: "0",
RRFullName: "test.lego.example.com",
RRFullNameUTF: "test.lego.example.com",
RRGlue: "test",
RRGlueID: "21",
RRID: "239",
RRNameID: "26",
RRType: "TXT",
RRTypeID: "6",
RRValueID: "274",
TTL: "3600",
Value1: "test1",
VDNSParentID: "0",
VDNSParentName: "#",
}
assert.Equal(t, expected, record)
}
func TestAddRecord(t *testing.T) {
client := setupTest(t, http.MethodPost, "/dns_rr_add", http.StatusCreated, "dns_rr_add.json")
ctx := context.Background()
r := ResourceRecord{
RRName: "test.example.com",
RRType: "TXT",
Value1: "test",
DNSName: "dns.smart",
DNSViewName: "external",
}
resp, err := client.AddRecord(ctx, r)
require.NoError(t, err)
expected := &BaseOutput{RetOID: "239"}
assert.Equal(t, expected, resp)
}
func TestDeleteRecord(t *testing.T) {
client := setupTest(t, http.MethodDelete, "/dns_rr_delete", http.StatusOK, "dns_rr_delete.json")
ctx := context.Background()
resp, err := client.DeleteRecord(ctx, DeleteInputParameters{RRID: "251"})
require.NoError(t, err)
expected := &BaseOutput{RetOID: "251"}
assert.Equal(t, expected, resp)
}
func TestDeleteRecord_error(t *testing.T) {
client := setupTest(t, http.MethodDelete, "/dns_rr_delete", http.StatusBadRequest, "dns_rr_delete-error.json")
ctx := context.Background()
_, err := client.DeleteRecord(ctx, DeleteInputParameters{RRID: "251"})
require.ErrorAs(t, err, &APIError{})
}

View file

@ -0,0 +1,5 @@
[
{
"ret_oid": "239"
}
]

View file

@ -0,0 +1,6 @@
{
"errno": "20117",
"errmsg": "This RR does not exist",
"severity": "error",
"category": "dns_rr_delete"
}

View file

@ -0,0 +1,5 @@
[
{
"ret_oid": "251"
}
]

View file

@ -0,0 +1,64 @@
[
{
"errno": "0",
"rr_all_value": "test1",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "test.lego.example.com",
"rr_full_name_utf": "test.lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "",
"rr_value_ip4_addr": "",
"rr_glue": "test",
"rr_type": "TXT",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "test1",
"value2": "",
"value3": "",
"value4": "",
"value5": "",
"value6": "",
"value7": "",
"dnszone_id": "9",
"rr_id": "239",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "26",
"rr_value_id": "274",
"rr_type_id": "6",
"rr_glue_id": "21",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
}
]

View file

@ -0,0 +1,436 @@
[
{
"errno": "0",
"rr_all_value": "test1",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "test.lego.example.com",
"rr_full_name_utf": "test.lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "",
"rr_value_ip4_addr": "",
"rr_glue": "test",
"rr_type": "TXT",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "test1",
"value2": "",
"value3": "",
"value4": "",
"value5": "",
"value6": "",
"value7": "",
"dnszone_id": "9",
"rr_id": "239",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "26",
"rr_value_id": "274",
"rr_type_id": "6",
"rr_glue_id": "21",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
},
{
"errno": "0",
"rr_all_value": "test2",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "test.lego.example.com",
"rr_full_name_utf": "test.lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "",
"rr_value_ip4_addr": "",
"rr_glue": "test",
"rr_type": "TXT",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "test2",
"value2": "",
"value3": "",
"value4": "",
"value5": "",
"value6": "",
"value7": "",
"dnszone_id": "9",
"rr_id": "241",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "26",
"rr_value_id": "275",
"rr_type_id": "6",
"rr_glue_id": "21",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
},
{
"errno": "0",
"rr_all_value": "test1",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "lego.example.com",
"rr_full_name_utf": "lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "",
"rr_value_ip4_addr": "",
"rr_glue": ".",
"rr_type": "TXT",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "test1",
"value2": "",
"value3": "",
"value4": "",
"value5": "",
"value6": "",
"value7": "",
"dnszone_id": "9",
"rr_id": "245",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "21",
"rr_value_id": "274",
"rr_type_id": "6",
"rr_glue_id": "3",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
},
{
"errno": "0",
"rr_all_value": "test2",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "lego.example.com",
"rr_full_name_utf": "lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "",
"rr_value_ip4_addr": "",
"rr_glue": ".",
"rr_type": "TXT",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "test2",
"value2": "",
"value3": "",
"value4": "",
"value5": "",
"value6": "",
"value7": "",
"dnszone_id": "9",
"rr_id": "247",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "21",
"rr_value_id": "275",
"rr_type_id": "6",
"rr_glue_id": "3",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
},
{
"errno": "0",
"rr_all_value": "dns.smart, root@lego.example.com, 2023062719, 1200, 600, 1209600, 3600",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "lego.example.com",
"rr_full_name_utf": "lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "",
"rr_value_ip4_addr": "",
"rr_glue": ".",
"rr_type": "SOA",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "dns.smart",
"value2": "root@lego.example.com",
"value3": "2023062719",
"value4": "1200",
"value5": "600",
"value6": "1209600",
"value7": "3600",
"dnszone_id": "9",
"rr_id": "201",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "21",
"rr_value_id": "282",
"rr_type_id": "2",
"rr_glue_id": "3",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
},
{
"errno": "0",
"rr_all_value": "dns.smart",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "lego.example.com",
"rr_full_name_utf": "lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "",
"rr_value_ip4_addr": "",
"rr_glue": ".",
"rr_type": "NS",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "dns.smart",
"value2": "",
"value3": "",
"value4": "",
"value5": "",
"value6": "",
"value7": "",
"dnszone_id": "9",
"rr_id": "200",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "21",
"rr_value_id": "10",
"rr_type_id": "1",
"rr_glue_id": "3",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
},
{
"errno": "0",
"rr_all_value": "127.0.0.1",
"dnszone_sort_zone": "lego.example.com",
"dnszone_is_rpz": "0",
"dnszone_type": "master",
"rr_full_name": "loopback.lego.example.com",
"rr_full_name_utf": "loopback.lego.example.com",
"rr_name_ip_addr": "",
"rr_name_ip4_addr": "",
"rr_value_ip_addr": "7f000001",
"rr_value_ip4_addr": "7f000001",
"rr_glue": "loopback",
"rr_type": "A",
"ttl": "3600",
"delayed_time": "0",
"rr_class_name": "",
"value1": "127.0.0.1",
"value2": "",
"value3": "",
"value4": "",
"value5": "",
"value6": "",
"value7": "",
"dnszone_id": "9",
"rr_id": "208",
"dns_id": "3",
"dnszone_name_utf": "lego.example.com",
"dnszone_name": "lego.example.com",
"dns_name": "dns.smart",
"dns_type": "vdns",
"dns_cloud": "0",
"vdns_parent_id": "0",
"dnsview_name": "#",
"dnsview_class_name": "",
"dnsview_id": "0",
"dnszone_site_name": "#",
"dnszone_is_reverse": "0",
"dnszone_masters": "",
"vdns_parent_name": "#",
"dnszone_forwarders": "",
"dns_class_name": "",
"dnszone_class_name": "",
"dns_version": "",
"dns_comment": "",
"delayed_create_time": "0",
"delayed_delete_time": "0",
"multistatus": "",
"rr_auth_gsstsig": "0",
"rr_last_update_time": "",
"rr_last_update_days": "",
"rr_name_id": "22",
"rr_value_id": "237",
"rr_type_id": "3",
"rr_glue_id": "17",
"dnsview_class_parameters": "",
"dnsview_class_parameters_properties": "",
"dnsview_class_parameters_inheritance_source": "",
"rr_class_parameters": "",
"rr_class_parameters_properties": "",
"rr_class_parameters_inheritance_source": ""
}
]

View file

@ -0,0 +1,109 @@
package internal
import "fmt"
type ResourceRecord struct {
ErrorCode string `json:"errno,omitempty"`
DelayedCreateTime string `json:"delayed_create_time,omitempty"`
DelayedDeleteTime string `json:"delayed_delete_time,omitempty"`
DelayedTime string `json:"delayed_time,omitempty"`
DNSClassName string `json:"dns_class_name,omitempty"`
DNSCloud string `json:"dns_cloud,omitempty"`
DNSComment string `json:"dns_comment,omitempty"`
DNSID string `json:"dns_id,omitempty"`
DNSName string `json:"dns_name,omitempty"`
DNSType string `json:"dns_type,omitempty"`
DNSVersion string `json:"dns_version,omitempty"`
DNSViewClassName string `json:"dnsview_class_name,omitempty"`
DNSViewClassParameters string `json:"dnsview_class_parameters,omitempty"`
DNSViewClassParametersInheritanceSource string `json:"dnsview_class_parameters_inheritance_source,omitempty"`
DNSViewClassParametersProperties string `json:"dnsview_class_parameters_properties,omitempty"`
DNSViewID string `json:"dnsview_id,omitempty"`
DNSViewName string `json:"dnsview_name,omitempty"`
DNSZoneClassName string `json:"dnszone_class_name,omitempty"`
DNSZoneForwarders string `json:"dnszone_forwarders,omitempty"`
DNSZoneID string `json:"dnszone_id,omitempty"`
DNSZoneIsReverse string `json:"dnszone_is_reverse,omitempty"`
DNSZoneIsRpz string `json:"dnszone_is_rpz,omitempty"`
DNSZoneMasters string `json:"dnszone_masters,omitempty"`
DNSZoneName string `json:"dnszone_name,omitempty"`
DNSZoneNameUTF string `json:"dnszone_name_utf,omitempty"`
DNSZoneSiteName string `json:"dnszone_site_name,omitempty"`
DNSZoneSortZone string `json:"dnszone_sort_zone,omitempty"`
DNSZoneType string `json:"dnszone_type,omitempty"`
MultiStatus string `json:"multistatus,omitempty"`
RRAllValue string `json:"rr_all_value,omitempty"`
RRAuthGsstsig string `json:"rr_auth_gsstsig,omitempty"`
RRClassName string `json:"rr_class_name,omitempty"`
RRClassParameters string `json:"rr_class_parameters,omitempty"`
RRClassParametersInheritanceSource string `json:"rr_class_parameters_inheritance_source,omitempty"`
RRClassParametersProperties string `json:"rr_class_parameters_properties,omitempty"`
RRFullName string `json:"rr_full_name,omitempty"`
RRFullNameUTF string `json:"rr_full_name_utf,omitempty"`
RRGlue string `json:"rr_glue,omitempty"`
RRGlueID string `json:"rr_glue_id,omitempty"`
RRID string `json:"rr_id,omitempty"`
RRLastUpdateDays string `json:"rr_last_update_days,omitempty"`
RRLastUpdateTime string `json:"rr_last_update_time,omitempty"`
RRName string `json:"rr_name,omitempty"`
RRNameID string `json:"rr_name_id,omitempty"`
RRNameIP4Addr string `json:"rr_name_ip4_addr,omitempty"`
RRNameIPAddr string `json:"rr_name_ip_addr,omitempty"`
RRType string `json:"rr_type,omitempty"`
RRTypeID string `json:"rr_type_id,omitempty"`
RRValueID string `json:"rr_value_id,omitempty"`
RRValueIP4Addr string `json:"rr_value_ip4_addr,omitempty"`
RRValueIPAddr string `json:"rr_value_ip_addr,omitempty"`
TTL string `json:"ttl,omitempty"`
Value1 string `json:"value1,omitempty"`
Value2 string `json:"value2,omitempty"`
Value3 string `json:"value3,omitempty"`
Value4 string `json:"value4,omitempty"`
Value5 string `json:"value5,omitempty"`
Value6 string `json:"value6,omitempty"`
Value7 string `json:"value7,omitempty"`
VDNSParentID string `json:"vdns_parent_id,omitempty"`
VDNSParentName string `json:"vdns_parent_name,omitempty"`
}
type DeleteInputParameters struct {
RRID string `url:"rr_id,omitempty"`
DNSName string `url:"dns_name,omitempty"`
DNSViewName string `url:"dnsview_name,omitempty"`
RRName string `url:"rr_name,omitempty"`
RRType string `url:"rr_type,omitempty"`
RRValue1 string `url:"rr_value1,omitempty"`
}
type BaseOutput struct {
RetOID string `json:"ret_oid,omitempty"`
}
type APIError struct {
ErrorCode string `json:"errno,omitempty"`
ErrMsg string `json:"errmsg,omitempty"`
Severity string `json:"severity,omitempty"`
Category string `json:"category,omitempty"`
Parameters string `json:"parameters,omitempty"`
ParamFormat string `json:"param_format,omitempty"`
ParamValue string `json:"param_value,omitempty"`
}
func (a APIError) Error() string {
msg := fmt.Sprintf("%s: %s %s %s", a.Category, a.Severity, a.ErrorCode, a.ErrMsg)
if a.Parameters != "" {
msg += fmt.Sprintf(" parameters: %s", a.Parameters)
}
if a.ParamFormat != "" {
msg += fmt.Sprintf(" param_format: %s", a.ParamFormat)
}
if a.ParamValue != "" {
msg += fmt.Sprintf(" param_value: %s", a.ParamValue)
}
return msg
}