mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
ns1: enable autoDNSSEC capability (#1450)
* ns1: enable autoDNSSEC capability NS1's API has support for enabling or disabling DNSSEC on zones under DNSSEC-enabled accounts. This commit enables support for detecting a zone's DNSSEC state and, given the autoDNSSEC setting, pushing the right domain corrections to our corrections stack. Fixes #1444 * ns1: better comments * ns1: Handle a forgotten error * ns1: style: spacing between functions Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
|||||||
var docNotes = providers.DocumentationNotes{
|
var docNotes = providers.DocumentationNotes{
|
||||||
providers.CanGetZones: providers.Can(),
|
providers.CanGetZones: providers.Can(),
|
||||||
providers.CanUseAlias: providers.Can(),
|
providers.CanUseAlias: providers.Can(),
|
||||||
|
providers.CanAutoDNSSEC: providers.Can(),
|
||||||
providers.CanUseCAA: providers.Can(),
|
providers.CanUseCAA: providers.Can(),
|
||||||
providers.CanUseDS: providers.Can(),
|
providers.CanUseDS: providers.Can(),
|
||||||
providers.CanUseDSForChildren: providers.Can(),
|
providers.CanUseDSForChildren: providers.Can(),
|
||||||
@@ -89,6 +90,54 @@ func (n *nsone) GetZoneRecords(domain string) (models.Records, error) {
|
|||||||
return found, nil
|
return found, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetZoneDNSSEC gets DNSSEC status for zone. Returns true for enabled, false for disabled
|
||||||
|
// a domain in NS1 can be in 3 states:
|
||||||
|
// 1) DNSSEC is enabled (returns true)
|
||||||
|
// 2) DNSSEC is disabled (returns false)
|
||||||
|
// 3) some error state (return false plus the error)
|
||||||
|
func (n *nsone) GetZoneDNSSEC(domain string) (bool, error) {
|
||||||
|
_, _, err := n.DNSSEC.Get(domain)
|
||||||
|
|
||||||
|
// rest.ErrDNSECNotEnabled is our "disabled" state
|
||||||
|
if err != nil && err == rest.ErrDNSECNotEnabled {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// any other errors not expected, let's surface them
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// no errors returned, we assume DNSSEC is enabled
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDomainCorrectionsDNSSEC creates DNSSEC zone corrections based on current state and preference
|
||||||
|
func (n *nsone) getDomainCorrectionsDNSSEC(domain, toggleDNSSEC string) (*models.Correction) {
|
||||||
|
|
||||||
|
// get dnssec status from NS1 for domain
|
||||||
|
// if errors are returned, we bail out without any DNSSEC corrections
|
||||||
|
status, err := n.GetZoneDNSSEC(domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if toggleDNSSEC == "on" && !status {
|
||||||
|
// disabled, but prefer it on, let's enable DNSSEC
|
||||||
|
return &models.Correction{
|
||||||
|
Msg: "ENABLE DNSSEC",
|
||||||
|
F: func() error { return n.configureDNSSEC(domain, true) },
|
||||||
|
}
|
||||||
|
} else if toggleDNSSEC == "off" && status {
|
||||||
|
// enabled, but prefer it off, let's disable DNSSEC
|
||||||
|
return &models.Correction{
|
||||||
|
Msg: "DISABLE DNSSEC",
|
||||||
|
F: func() error { return n.configureDNSSEC(domain, false) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (n *nsone) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
func (n *nsone) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||||
dc.Punycode()
|
dc.Punycode()
|
||||||
//dc.CombineMXs()
|
//dc.CombineMXs()
|
||||||
@@ -112,7 +161,13 @@ func (n *nsone) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correct
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
corrections := []*models.Correction{}
|
corrections := []*models.Correction{}
|
||||||
|
|
||||||
|
if dnssecCorrections := n.getDomainCorrectionsDNSSEC(domain, dc.AutoDNSSEC); dnssecCorrections != nil {
|
||||||
|
corrections = append(corrections, dnssecCorrections)
|
||||||
|
}
|
||||||
|
|
||||||
// each name/type is given to the api as a unit.
|
// each name/type is given to the api as a unit.
|
||||||
for k, descs := range changedGroups {
|
for k, descs := range changedGroups {
|
||||||
key := k
|
key := k
|
||||||
@@ -158,6 +213,24 @@ func (n *nsone) modify(recs models.Records, domain string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// configureDNSSEC configures DNSSEC for a zone. Set 'enabled' to true to enable, false to disable.
|
||||||
|
// There's a cornercase, in which DNSSEC is globally disabled for the account.
|
||||||
|
// In that situation, enabling DNSSEC will always fail with:
|
||||||
|
// #1: ENABLE DNSSEC
|
||||||
|
// FAILURE! POST https://api.nsone.net/v1/zones/example.com: 400 DNSSEC support is not enabled for this account. Please contact support@ns1.com to enable it
|
||||||
|
//
|
||||||
|
// Unfortunately this is not detectable otherwise, so given that we have a nice error message, we just let this through.
|
||||||
|
//
|
||||||
|
func (n *nsone) configureDNSSEC(domain string, enabled bool) error {
|
||||||
|
z, _, err := n.Zones.Get(domain)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
z.DNSSEC = &enabled
|
||||||
|
_, err = n.Zones.Update(z)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func buildRecord(recs models.Records, domain string, id string) *dns.Record {
|
func buildRecord(recs models.Records, domain string, id string) *dns.Record {
|
||||||
r := recs[0]
|
r := recs[0]
|
||||||
rec := &dns.Record{
|
rec := &dns.Record{
|
||||||
|
Reference in New Issue
Block a user