mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-02-25 16:13:04 +08:00
HOSTINGDE: Implement AutoDNSSEC (#2022)
Co-authored-by: Yannik Sembritzki <yannik@sembritzki.org>
This commit is contained in:
parent
1073e04577
commit
83299e178e
3 changed files with 120 additions and 54 deletions
|
@ -125,50 +125,7 @@ func (hp *hostingdeProvider) updateNameservers(nss []string, domain string) func
|
|||
}
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) getRecords(domain string) ([]*record, error) {
|
||||
zc, err := hp.getZoneConfig(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records := []*record{}
|
||||
page := uint(1)
|
||||
for {
|
||||
params := request{
|
||||
Filter: &filter{
|
||||
Field: "ZoneConfigId",
|
||||
Value: zc.ID,
|
||||
},
|
||||
Limit: 1000,
|
||||
Page: page,
|
||||
}
|
||||
|
||||
resp, err := hp.get("dns", "recordsFind", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newRecords := []*record{}
|
||||
if err := json.Unmarshal(resp.Data, &newRecords); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records = append(records, newRecords...)
|
||||
|
||||
if page >= resp.TotalPages {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) updateRecords(domain string, create, del, mod diff.Changeset) error {
|
||||
zc, err := hp.getZoneConfig(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) updateZone(zc *zoneConfig, DnsSecOptions *dnsSecOptions, create, del, mod diff.Changeset) error {
|
||||
toAdd := []*record{}
|
||||
for _, c := range create {
|
||||
r := recordToNative(c.Desired)
|
||||
|
@ -194,15 +151,46 @@ func (hp *hostingdeProvider) updateRecords(domain string, create, del, mod diff.
|
|||
RecordsToAdd: toAdd,
|
||||
RecordsToDelete: toDelete,
|
||||
RecordsToModify: toModify,
|
||||
DNSSECOptions: DnsSecOptions,
|
||||
}
|
||||
|
||||
_, err = hp.get("dns", "zoneUpdate", params)
|
||||
_, err := hp.get("dns", "zoneUpdate", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) getZone(domain string) (*zone, error) {
|
||||
t, err := idna.ToASCII(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params := request{
|
||||
Filter: &filter{
|
||||
Field: "ZoneName",
|
||||
Value: t,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := hp.get("dns", "zonesFind", params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get zone config: %w", err)
|
||||
}
|
||||
|
||||
zones := []*zone{}
|
||||
if err := json.Unmarshal(resp.Data, &zones); err != nil {
|
||||
return nil, fmt.Errorf("could not parse response: %w", err)
|
||||
}
|
||||
|
||||
if len(zones) == 0 {
|
||||
return nil, errZoneNotFound
|
||||
}
|
||||
|
||||
return zones[0], nil
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) getZoneConfig(domain string) (*zoneConfig, error) {
|
||||
t, err := idna.ToASCII(domain)
|
||||
if err != nil {
|
||||
|
@ -233,6 +221,31 @@ func (hp *hostingdeProvider) getZoneConfig(domain string) (*zoneConfig, error) {
|
|||
return zc[0], nil
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) getDNSSECOptions(zoneConfigId string) (*dnsSecOptions, error) {
|
||||
params := request{
|
||||
Filter: &filter{
|
||||
Field: "zoneConfigId",
|
||||
Value: zoneConfigId,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := hp.get("dns", "dnsSecOptionsFind", params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get dnssec options: %w", err)
|
||||
}
|
||||
|
||||
dnsSecOptions := []*dnsSecOptions{}
|
||||
if err := json.Unmarshal(resp.Data, &dnsSecOptions); err != nil {
|
||||
return nil, fmt.Errorf("could not parse response: %w", err)
|
||||
}
|
||||
|
||||
if len(dnsSecOptions) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return dnsSecOptions[0], nil
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) get(service, method string, params request) (*responseData, error) {
|
||||
params.AuthToken = hp.authToken
|
||||
params.OwnerAccountID = hp.ownerAccountID
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
var defaultNameservers = []string{"ns1.hosting.de.", "ns2.hosting.de.", "ns3.hosting.de."}
|
||||
|
||||
var features = providers.DocumentationNotes{
|
||||
providers.CanAutoDNSSEC: providers.Unimplemented("Supported but not implemented yet."),
|
||||
providers.CanAutoDNSSEC: providers.Can(),
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanUseAlias: providers.Can(),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
|
@ -91,11 +91,14 @@ func (hp *hostingdeProvider) GetNameservers(domain string) ([]*models.Nameserver
|
|||
}
|
||||
|
||||
func (hp *hostingdeProvider) GetZoneRecords(domain string) (models.Records, error) {
|
||||
src, err := hp.getRecords(domain)
|
||||
zone, err := hp.getZone(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hp.ApiRecordsToStandardRecordsModel(domain, zone.Records), nil
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) ApiRecordsToStandardRecordsModel(domain string, src []record) models.Records {
|
||||
records := []*models.RecordConfig{}
|
||||
for _, r := range src {
|
||||
if r.Type == "SOA" {
|
||||
|
@ -104,7 +107,7 @@ func (hp *hostingdeProvider) GetZoneRecords(domain string) (models.Records, erro
|
|||
records = append(records, r.nativeToRecord(domain))
|
||||
}
|
||||
|
||||
return records, nil
|
||||
return records
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
|
@ -122,12 +125,13 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
|
|||
r.TTL = 31556926
|
||||
}
|
||||
}
|
||||
|
||||
records, err := hp.GetZoneRecords(dc.Name)
|
||||
zone, err := hp.getZone(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records := hp.ApiRecordsToStandardRecordsModel(dc.Name, zone.Records)
|
||||
|
||||
var create, del, mod diff.Changeset
|
||||
if !diff2.EnableDiff2 {
|
||||
_, create, del, mod, err = diff.New(dc).IncrementalDiff(records)
|
||||
|
@ -148,7 +152,37 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
|
|||
msg = append(msg, c.String())
|
||||
}
|
||||
|
||||
if len(create) == 0 && len(del) == 0 && len(mod) == 0 {
|
||||
existingAutoDNSSecEnabled := zone.ZoneConfig.DNSSECMode == "automatic"
|
||||
desiredAutoDNSSecEnabled := dc.AutoDNSSEC == "on"
|
||||
|
||||
var DnsSecOptions *dnsSecOptions = nil
|
||||
|
||||
// ensure that publishKsk is set for domains with AutoDNSSec
|
||||
if existingAutoDNSSecEnabled == desiredAutoDNSSecEnabled == true {
|
||||
CurrentDnsSecOptions, err := hp.getDNSSECOptions(zone.ZoneConfig.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !CurrentDnsSecOptions.PublishKSK {
|
||||
msg = append(msg, "Enabling publishKsk for AutoDNSSec")
|
||||
DnsSecOptions = CurrentDnsSecOptions
|
||||
DnsSecOptions.PublishKSK = true
|
||||
}
|
||||
}
|
||||
|
||||
if !existingAutoDNSSecEnabled && desiredAutoDNSSecEnabled {
|
||||
msg = append(msg, "Enable AutoDNSSEC")
|
||||
DnsSecOptions = &dnsSecOptions{
|
||||
NSECMode: "nsec3",
|
||||
PublishKSK: true,
|
||||
}
|
||||
zone.ZoneConfig.DNSSECMode = "automatic"
|
||||
} else if existingAutoDNSSecEnabled && !desiredAutoDNSSecEnabled {
|
||||
msg = append(msg, "Disable AutoDNSSEC")
|
||||
zone.ZoneConfig.DNSSECMode = "off"
|
||||
}
|
||||
|
||||
if len(create) == 0 && len(del) == 0 && len(mod) == 0 && existingAutoDNSSecEnabled == desiredAutoDNSSecEnabled && DnsSecOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -157,7 +191,7 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
|
|||
Msg: fmt.Sprintf("\n%s", strings.Join(msg, "\n")),
|
||||
F: func() error {
|
||||
for i := 0; i < 10; i++ {
|
||||
err := hp.updateRecords(dc.Name, create, del, mod)
|
||||
err := hp.updateZone(&zone.ZoneConfig, DnsSecOptions, create, del, mod)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -209,8 +243,6 @@ func (hp *hostingdeProvider) GetRegistrarCorrections(dc *models.DomainConfig) ([
|
|||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
// TODO: Handle AutoDNSSEC
|
||||
}
|
||||
|
||||
func (hp *hostingdeProvider) EnsureDomainExists(domain string) error {
|
||||
|
|
|
@ -33,6 +33,8 @@ type request struct {
|
|||
|
||||
// Domain
|
||||
Domain *domainConfig `json:"domain"`
|
||||
|
||||
DNSSECOptions *dnsSecOptions `json:"dnsSecOptions,omitempty"`
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
|
@ -71,6 +73,25 @@ type zoneConfig struct {
|
|||
ZoneTransferWhitelist []string `json:"zoneTransferWhitelist"`
|
||||
}
|
||||
|
||||
type zone struct {
|
||||
ZoneConfig zoneConfig `json:"zoneConfig"`
|
||||
Records []record `json:"records"`
|
||||
}
|
||||
|
||||
type dnsSecOptions struct {
|
||||
Keys []dnsSecKey `json:"flags,omitempty"`
|
||||
Algorithms []string `json:"algorithms,omitempty"`
|
||||
NSECMode string `json:"nsecMode"`
|
||||
PublishKSK bool `json:"publishKsk"`
|
||||
}
|
||||
|
||||
type dnsSecKey struct {
|
||||
Flags uint32 `json:"flags"`
|
||||
Protocol uint32 `json:"protocol"`
|
||||
Algorithm uint32 `json:"algorithm"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
}
|
||||
|
||||
type record struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
|
Loading…
Reference in a new issue