mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
NEW PROVIDER: Mythic Beasts DNS (#2528)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
@ -33,7 +33,7 @@ changelog:
|
|||||||
regexp: "(?i)^.*(major|new provider|feature)[(\\w)]*:+.*$"
|
regexp: "(?i)^.*(major|new provider|feature)[(\\w)]*:+.*$"
|
||||||
order: 1
|
order: 1
|
||||||
- title: 'Provider-specific changes:'
|
- title: 'Provider-specific changes:'
|
||||||
regexp: "(?i)((akamaiedge|autodns|axfrd|azure|bind|cloudflare|cloudflareapi_old|cloudns|cscglobal|desec|digitalocean|dnsimple|dnsmadeeasy|doh|domainnameshop|easyname|exoscale|gandi|gcloud|gcore|hedns|hetzner|hexonet|hostingde|inwx|linode|loopia|luadns|msdns|namecheap|namedotcom|netcup|netlify|ns1|opensrs|oracle|ovh|packetframe|porkbun|powerdns|route53|rwth|softlayer|transip|vultr).*:)+.*"
|
regexp: "(?i)((akamaiedge|autodns|axfrd|azure|bind|cloudflare|cloudflareapi_old|cloudns|cscglobal|desec|digitalocean|dnsimple|dnsmadeeasy|doh|domainnameshop|easyname|exoscale|gandi|gcloud|gcore|hedns|hetzner|hexonet|hostingde|inwx|linode|loopia|luadns|msdns|mythicbeasts|namecheap|namedotcom|netcup|netlify|ns1|opensrs|oracle|ovh|packetframe|porkbun|powerdns|route53|rwth|softlayer|transip|vultr).*:)+.*"
|
||||||
order: 2
|
order: 2
|
||||||
- title: 'Deprecation warnings:'
|
- title: 'Deprecation warnings:'
|
||||||
regexp: "(?i)^.*Deprecate[(\\w)]*:+.*$"
|
regexp: "(?i)^.*Deprecate[(\\w)]*:+.*$"
|
||||||
|
1
OWNERS
1
OWNERS
@ -27,6 +27,7 @@ providers/linode @koesie10
|
|||||||
providers/loopia @systemcrash
|
providers/loopia @systemcrash
|
||||||
providers/luadns @riku22
|
providers/luadns @riku22
|
||||||
providers/msdns @tlimoncelli
|
providers/msdns @tlimoncelli
|
||||||
|
providers/mythicbeasts @tomfitzhenry
|
||||||
providers/namecheap @willpower232
|
providers/namecheap @willpower232
|
||||||
# providers/namedotcom NEEDS VOLUNTEER
|
# providers/namedotcom NEEDS VOLUNTEER
|
||||||
providers/netcup @kordianbruck
|
providers/netcup @kordianbruck
|
||||||
|
@ -42,6 +42,7 @@ Currently supported DNS providers:
|
|||||||
- Loopia
|
- Loopia
|
||||||
- LuaDNS
|
- LuaDNS
|
||||||
- Microsoft Windows Server DNS Server
|
- Microsoft Windows Server DNS Server
|
||||||
|
- Mythic Beasts
|
||||||
- Namecheap
|
- Namecheap
|
||||||
- Name.com
|
- Name.com
|
||||||
- Netcup
|
- Netcup
|
||||||
|
@ -124,6 +124,7 @@
|
|||||||
* [Loopia](providers/loopia.md)
|
* [Loopia](providers/loopia.md)
|
||||||
* [LuaDNS](providers/luadns.md)
|
* [LuaDNS](providers/luadns.md)
|
||||||
* [Microsoft DNS Server on Microsoft Windows Server](providers/msdns.md)
|
* [Microsoft DNS Server on Microsoft Windows Server](providers/msdns.md)
|
||||||
|
* [Mythic Beasts](providers/mythicbeasts.md)
|
||||||
* [Namecheap](providers/namecheap.md)
|
* [Namecheap](providers/namecheap.md)
|
||||||
* [Name.com](providers/namedotcom.md)
|
* [Name.com](providers/namedotcom.md)
|
||||||
* [Netcup](providers/netcup.md)
|
* [Netcup](providers/netcup.md)
|
||||||
|
@ -43,6 +43,7 @@ If a feature is definitively not supported for whatever reason, we would also li
|
|||||||
| [`LOOPIA`](providers/loopia.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ |
|
| [`LOOPIA`](providers/loopia.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ |
|
||||||
| [`LUADNS`](providers/luadns.md) | ❌ | ✅ | ❌ | ✅ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ |
|
| [`LUADNS`](providers/luadns.md) | ❌ | ✅ | ❌ | ✅ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| [`MSDNS`](providers/msdns.md) | ✅ | ✅ | ❌ | ❌ | ❌ | ❔ | ❌ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ✅ |
|
| [`MSDNS`](providers/msdns.md) | ✅ | ✅ | ❌ | ❌ | ❌ | ❔ | ❌ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ✅ |
|
||||||
|
| [`MYTHICBEASTS`](providers/mythicbeasts.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ❔ | ✅ | ❔ | ✅ | ❌ | ✅ | ✅ |
|
||||||
| [`NAMECHEAP`](providers/namecheap.md) | ❌ | ✅ | ✅ | ✅ | ✅ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❌ | ❌ | ✅ |
|
| [`NAMECHEAP`](providers/namecheap.md) | ❌ | ✅ | ✅ | ✅ | ✅ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❔ | ❌ | ❌ | ❌ | ✅ |
|
||||||
| [`NAMEDOTCOM`](providers/namedotcom.md) | ❌ | ✅ | ✅ | ✅ | ❔ | ❔ | ❌ | ❔ | ❌ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ❌ | ✅ | ✅ |
|
| [`NAMEDOTCOM`](providers/namedotcom.md) | ❌ | ✅ | ✅ | ✅ | ❔ | ❔ | ❌ | ❔ | ❌ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ❌ | ✅ | ✅ |
|
||||||
| [`NETCUP`](providers/netcup.md) | ❌ | ✅ | ❌ | ❔ | ✅ | ❔ | ❌ | ❔ | ❌ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❌ |
|
| [`NETCUP`](providers/netcup.md) | ❌ | ✅ | ❌ | ❔ | ✅ | ❔ | ❌ | ❔ | ❌ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❌ |
|
||||||
|
39
documentation/providers/mythicbeasts.md
Normal file
39
documentation/providers/mythicbeasts.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
This is the provider for [Mythic Beasts](https://www.mythic-beasts.com/) using its [Primary DNS API v2](https://www.mythic-beasts.com/support/api/dnsv2).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
To use this provider, add an entry to `creds.json` with `TYPE` set to `MYTHICBEASTS` along with a Mythic Beasts API key ID and secret.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
{% code title="creds.json" %}
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mythicbeasts": {
|
||||||
|
"TYPE": "MYTHICBEASTS",
|
||||||
|
"keyID": "xxxxxxx",
|
||||||
|
"secret": "xxxxxx"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{% endcode %}
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
For each domain:
|
||||||
|
|
||||||
|
* Domains must be added in the [web UI](https://www.mythic-beasts.com/customer/domains), and have DNS enabled.
|
||||||
|
* In Mythic Beasts' DNS management web UI, new domains will have set a default DNS template of "Mythic Beasts nameservers only". You must set this to "None".
|
||||||
|
|
||||||
|
An example configuration:
|
||||||
|
|
||||||
|
{% code title="dnsconfig.js" %}
|
||||||
|
```javascript
|
||||||
|
var REG_NONE = NewRegistrar("none");
|
||||||
|
var DSP_MYTHIC = NewDnsProvider("mythicbeasts");
|
||||||
|
|
||||||
|
D("example.com", REG_NONE, DnsProvider(DSP_MYTHIC),
|
||||||
|
A("test", "1.2.3.4")
|
||||||
|
);
|
||||||
|
```
|
||||||
|
{% endcode %}
|
@ -179,6 +179,12 @@
|
|||||||
"domain": "$MSDNS_DOMAIN",
|
"domain": "$MSDNS_DOMAIN",
|
||||||
"pssession": "$MSDNS_PSSESSION"
|
"pssession": "$MSDNS_PSSESSION"
|
||||||
},
|
},
|
||||||
|
"MYTHICBEASTS": {
|
||||||
|
"TYPE": "MYTHICBEASTS",
|
||||||
|
"keyID": "$MYTHICBEASTS_KEYID",
|
||||||
|
"secret": "$MYTHICBEASTS_SECRET",
|
||||||
|
"domain": "$MYTHICBEASTS_DOMAIN"
|
||||||
|
},
|
||||||
"NAMECHEAP": {
|
"NAMECHEAP": {
|
||||||
"BaseURL": "$NAMECHEAP_BASEURL",
|
"BaseURL": "$NAMECHEAP_BASEURL",
|
||||||
"TYPE": "NAMECHEAP",
|
"TYPE": "NAMECHEAP",
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
_ "github.com/StackExchange/dnscontrol/v4/providers/loopia"
|
_ "github.com/StackExchange/dnscontrol/v4/providers/loopia"
|
||||||
_ "github.com/StackExchange/dnscontrol/v4/providers/luadns"
|
_ "github.com/StackExchange/dnscontrol/v4/providers/luadns"
|
||||||
_ "github.com/StackExchange/dnscontrol/v4/providers/msdns"
|
_ "github.com/StackExchange/dnscontrol/v4/providers/msdns"
|
||||||
|
_ "github.com/StackExchange/dnscontrol/v4/providers/mythicbeasts"
|
||||||
_ "github.com/StackExchange/dnscontrol/v4/providers/namecheap"
|
_ "github.com/StackExchange/dnscontrol/v4/providers/namecheap"
|
||||||
_ "github.com/StackExchange/dnscontrol/v4/providers/namedotcom"
|
_ "github.com/StackExchange/dnscontrol/v4/providers/namedotcom"
|
||||||
_ "github.com/StackExchange/dnscontrol/v4/providers/netcup"
|
_ "github.com/StackExchange/dnscontrol/v4/providers/netcup"
|
||||||
|
15
providers/mythicbeasts/auditrecords.go
Normal file
15
providers/mythicbeasts/auditrecords.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package mythicbeasts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/StackExchange/dnscontrol/v4/models"
|
||||||
|
"github.com/StackExchange/dnscontrol/v4/pkg/rejectif"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuditRecords returns a list of errors corresponding to the records
|
||||||
|
// that aren't supported by this provider. If all records are
|
||||||
|
// supported, an empty list is returned.
|
||||||
|
func AuditRecords(records []*models.RecordConfig) []error {
|
||||||
|
a := rejectif.Auditor{}
|
||||||
|
a.Add("TXT", rejectif.TxtHasDoubleQuotes)
|
||||||
|
return nil
|
||||||
|
}
|
147
providers/mythicbeasts/mythicbeastsProvider.go
Normal file
147
providers/mythicbeasts/mythicbeastsProvider.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// Package mythicbeasts provides a provider for managing zones in Mythic Beasts.
|
||||||
|
//
|
||||||
|
// This package uses the Primary DNS API v2, as described in https://www.mythic-beasts.com/support/api/dnsv2
|
||||||
|
package mythicbeasts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/StackExchange/dnscontrol/v4/models"
|
||||||
|
"github.com/StackExchange/dnscontrol/v4/pkg/diff2"
|
||||||
|
"github.com/StackExchange/dnscontrol/v4/providers"
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// mythicBeastsDefaultNS lists the default nameservers, per https://www.mythic-beasts.com/support/domains/nameservers.
|
||||||
|
var mythicBeastsDefaultNS = []string{
|
||||||
|
"ns1.mythic-beasts.com",
|
||||||
|
"ns2.mythic-beasts.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
// mythicBeastsProvider is the handle for this provider.
|
||||||
|
type mythicBeastsProvider struct {
|
||||||
|
secret string
|
||||||
|
keyID string
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
var features = providers.DocumentationNotes{
|
||||||
|
providers.CanGetZones: providers.Can(),
|
||||||
|
providers.CanUseAlias: providers.Cannot(),
|
||||||
|
providers.CanUseCAA: providers.Can(),
|
||||||
|
providers.CanUseLOC: providers.Cannot(),
|
||||||
|
providers.CanUsePTR: providers.Can(),
|
||||||
|
providers.CanUseSRV: providers.Can(),
|
||||||
|
providers.CanUseTLSA: providers.Can(),
|
||||||
|
providers.DocCreateDomains: providers.Cannot("Requires domain registered through Web UI"),
|
||||||
|
providers.DocDualHost: providers.Can(),
|
||||||
|
providers.DocOfficiallySupported: providers.Cannot(),
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
fns := providers.DspFuncs{
|
||||||
|
Initializer: newDsp,
|
||||||
|
RecordAuditor: AuditRecords,
|
||||||
|
}
|
||||||
|
providers.RegisterDomainServiceProviderType("MYTHICBEASTS", fns, features)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDsp(conf map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||||
|
if conf["keyID"] == "" {
|
||||||
|
return nil, fmt.Errorf("missing Mythic Beasts auth keyID")
|
||||||
|
}
|
||||||
|
if conf["secret"] == "" {
|
||||||
|
return nil, fmt.Errorf("missing Mythic Beasts auth secret")
|
||||||
|
}
|
||||||
|
return &mythicBeastsProvider{
|
||||||
|
keyID: conf["keyID"],
|
||||||
|
secret: conf["secret"],
|
||||||
|
client: &http.Client{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *mythicBeastsProvider) httpRequest(method, url string, body io.Reader) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest(method, "https://api.mythic-beasts.com/dns/v2"+url, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// https://www.mythic-beasts.com/support/api/auth
|
||||||
|
req.SetBasicAuth(n.keyID, n.secret)
|
||||||
|
req.Header.Add("Content-Type", "text/dns")
|
||||||
|
req.Header.Add("Accept", "text/dns")
|
||||||
|
return n.client.Do(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
|
||||||
|
func (n *mythicBeastsProvider) GetZoneRecords(domain string, meta map[string]string) (models.Records, error) {
|
||||||
|
resp, err := n.httpRequest("GET", "/zones/"+domain+"/records", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if got, want := resp.StatusCode, 200; got != want {
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
return nil, fmt.Errorf("got HTTP %v, want %v: %v", got, want, string(body))
|
||||||
|
}
|
||||||
|
return zoneFileToRecords(resp.Body, domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
func zoneFileToRecords(r io.Reader, origin string) (models.Records, error) {
|
||||||
|
zp := dns.NewZoneParser(r, origin, origin)
|
||||||
|
var records []*models.RecordConfig
|
||||||
|
for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
|
||||||
|
rec, err := models.RRtoRC(rr, origin)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
records = append(records, &rec)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := zp.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing zone for %v: %w", origin, err)
|
||||||
|
}
|
||||||
|
return records, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
|
||||||
|
func (n *mythicBeastsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) {
|
||||||
|
msgs, changes, err := diff2.ByZone(actual, dc, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var corrections []*models.Correction
|
||||||
|
if changes {
|
||||||
|
corrections = append(corrections,
|
||||||
|
&models.Correction{
|
||||||
|
Msg: strings.Join(msgs, "\n"),
|
||||||
|
F: func() error {
|
||||||
|
var b strings.Builder
|
||||||
|
for _, rr := range dc.Records {
|
||||||
|
fmt.Fprintf(&b, "%v\n", rr.ToRR().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := n.httpRequest("PUT", "/zones/"+dc.Name+"/records", strings.NewReader(b.String()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if got, want := resp.StatusCode, 200; got != want {
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
return fmt.Errorf("got HTTP %v, want %v: %v", got, want, string(body))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return corrections, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNameservers returns the nameservers for a domain.
|
||||||
|
func (n *mythicBeastsProvider) GetNameservers(domainName string) ([]*models.Nameserver, error) {
|
||||||
|
return models.ToNameservers(mythicBeastsDefaultNS)
|
||||||
|
}
|
Reference in New Issue
Block a user