HOSTINGDE: Implement SOA record (fixes #1972) (#2023)

Co-authored-by: Yannik Sembritzki <yannik@sembritzki.org>
This commit is contained in:
Yannik Sembritzki 2023-02-06 21:04:31 +07:00 committed by GitHub
parent f58bab22d6
commit 222666414a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 14 deletions

View file

@ -19,6 +19,7 @@ type hostingdeProvider struct {
filterAccountId string
baseURL string
nameservers []string
defaultSoa soaValues
}
func (hp *hostingdeProvider) getDomainConfig(domain string) (*domainConfig, error) {

View file

@ -21,6 +21,7 @@ var features = providers.DocumentationNotes{
providers.CanGetZones: providers.Can(),
providers.CanUseAlias: providers.Can(),
providers.CanUseCAA: providers.Can(),
providers.CanUseSOA: providers.Can(),
providers.CanUseDS: providers.Can(),
providers.CanUseNAPTR: providers.Cannot(),
providers.CanUsePTR: providers.Can(),
@ -111,12 +112,18 @@ func (hp *hostingdeProvider) ApiRecordsToStandardRecordsModel(domain string, src
return records
}
func soaToString(s soaValues) string {
return fmt.Sprintf("refresh=%d retry=%d expire=%d negativettl=%d ttl=%d", s.Refresh, s.Retry, s.Expire, s.NegativeTTL, s.TTL)
}
func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
err := dc.Punycode()
if err != nil {
return nil, err
}
zoneChanged := false
// TTL must be between (inclusive) 1m and 1y (in fact, a little bit more)
for _, r := range dc.Records {
if r.TTL < 60 {
@ -148,11 +155,65 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
del = []diff.Correlation{}
}
// remove SOA record from corrections as it is handled separately
for i, r := range create {
if r.Desired.Type == "SOA" {
create = append(create[:i], create[i+1:]...)
break
}
}
if len(create) != 0 || len(del) != 0 || len(mod) != 0 {
zoneChanged = true
}
msg := []string{}
for _, c := range append(del, append(create, mod...)...) {
msg = append(msg, c.String())
}
var desiredSoa *models.RecordConfig
for _, r := range dc.Records {
if r.Type == "SOA" && r.Name == "@" {
desiredSoa = r
break
}
}
if desiredSoa == nil {
desiredSoa = &models.RecordConfig{}
}
defaultSoa := &hp.defaultSoa
if defaultSoa == nil {
defaultSoa = &soaValues{}
}
newSOA := soaValues{
Refresh: firstNonZero(desiredSoa.SoaRefresh, defaultSoa.Refresh, 86400),
Retry: firstNonZero(desiredSoa.SoaRetry, defaultSoa.Retry, 7200),
Expire: firstNonZero(desiredSoa.SoaExpire, defaultSoa.Expire, 3600000),
NegativeTTL: firstNonZero(desiredSoa.SoaMinttl, defaultSoa.NegativeTTL, 900),
TTL: firstNonZero(desiredSoa.TTL, defaultSoa.TTL, 86400),
}
if zone.ZoneConfig.SOAValues != newSOA {
msg = append(msg, fmt.Sprintf("Updating SOARecord from (%s) to (%s)", soaToString(zone.ZoneConfig.SOAValues), soaToString(newSOA)))
zone.ZoneConfig.SOAValues = newSOA
zoneChanged = true
}
if desiredSoa.SoaMbox != "" {
var desiredMail string = ""
if desiredSoa.SoaMbox[len(desiredSoa.SoaMbox)-1] != '.' {
desiredMail = desiredSoa.SoaMbox + "@" + dc.Name
}
if desiredMail != "" && zone.ZoneConfig.EmailAddress != desiredMail {
msg = append(msg, fmt.Sprintf("Changing SOA Mail from %s to %s", zone.ZoneConfig.EmailAddress, desiredMail))
zone.ZoneConfig.EmailAddress = desiredMail
zoneChanged = true
}
}
existingAutoDNSSecEnabled := zone.ZoneConfig.DNSSECMode == "automatic"
desiredAutoDNSSecEnabled := dc.AutoDNSSEC == "on"
@ -168,6 +229,7 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
msg = append(msg, "Enabling publishKsk for AutoDNSSec")
DnsSecOptions = CurrentDnsSecOptions
DnsSecOptions.PublishKSK = true
zoneChanged = true
}
}
@ -178,12 +240,14 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
PublishKSK: true,
}
zone.ZoneConfig.DNSSECMode = "automatic"
zoneChanged = true
} else if existingAutoDNSSecEnabled && !desiredAutoDNSSecEnabled {
msg = append(msg, "Disable AutoDNSSEC")
zone.ZoneConfig.DNSSECMode = "off"
zoneChanged = true
}
if len(create) == 0 && len(del) == 0 && len(mod) == 0 && existingAutoDNSSecEnabled == desiredAutoDNSSecEnabled && DnsSecOptions == nil {
if !zoneChanged {
return nil, nil
}
@ -213,6 +277,15 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
return corrections, nil
}
func firstNonZero(items ...uint32) uint32 {
for _, item := range items {
if item != 0 {
return item
}
}
return 999
}
func (hp *hostingdeProvider) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
err := dc.Punycode()
if err != nil {

View file

@ -56,24 +56,26 @@ type domainConfig struct {
}
type zoneConfig struct {
ID string `json:"id"`
DNSSECMode string `json:"dnsSecMode"`
EmailAddress string `json:"emailAddress,omitempty"`
MasterIP string `json:"masterIp"`
Name string `json:"name"` // Not required per docs, but required IRL
NameUnicode string `json:"nameUnicode"`
// SOAValues struct {
// Refresh uint32 `json:"refresh"`
// Retry uint32 `json:"retry"`
// Expire uint32 `json:"expire"`
// TTL uint32 `json:"ttl"`
// NegativeTTL uint32 `json:"negativeTtl"`
// } `json:"soaValues,omitempty"`
ID string `json:"id"`
DNSSECMode string `json:"dnsSecMode"`
EmailAddress string `json:"emailAddress,omitempty"`
MasterIP string `json:"masterIp"`
Name string `json:"name"` // Not required per docs, but required IRL
NameUnicode string `json:"nameUnicode"`
SOAValues soaValues `json:"soaValues,omitempty"`
Type string `json:"type"`
TemplateValues json.RawMessage `json:"templateValues,omitempty"`
ZoneTransferWhitelist []string `json:"zoneTransferWhitelist"`
}
type soaValues struct {
Refresh uint32 `json:"refresh"`
Retry uint32 `json:"retry"`
Expire uint32 `json:"expire"`
NegativeTTL uint32 `json:"negativeTtl"`
TTL uint32 `json:"ttl"`
}
type zone struct {
ZoneConfig zoneConfig `json:"zoneConfig"`
Records []record `json:"records"`