mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-12-09 05:36:27 +08:00
ALIDNS: Implement domain TTL validation
This commit is contained in:
parent
820cde51d1
commit
53fce265d0
3 changed files with 80 additions and 14 deletions
|
|
@ -49,7 +49,14 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type aliDnsDsp struct {
|
type aliDnsDsp struct {
|
||||||
client *alidns.Client
|
client *alidns.Client
|
||||||
|
domainVersionCache map[string]*domainVersionInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type domainVersionInfo struct {
|
||||||
|
versionCode string
|
||||||
|
minTTL uint32
|
||||||
|
maxTTL uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAliDnsDsp(config map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
func newAliDnsDsp(config map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||||
|
|
@ -80,7 +87,10 @@ func newAliDnsDsp(config map[string]string, metadata json.RawMessage) (providers
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &aliDnsDsp{client}, nil
|
return &aliDnsDsp{
|
||||||
|
client: client,
|
||||||
|
domainVersionCache: make(map[string]*domainVersionInfo),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetZoneRecords returns an array of RecordConfig structs for a zone.
|
// GetZoneRecords returns an array of RecordConfig structs for a zone.
|
||||||
|
|
@ -124,7 +134,33 @@ func deduplicateNameServerTargets(newRecs models.Records) models.Records {
|
||||||
return deduped
|
return deduped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateRecordTTLs checks that all records in the domain config have valid TTL values
|
||||||
|
// according to the Alibaba Cloud DNS version constraints.
|
||||||
|
func (a *aliDnsDsp) validateRecordTTLs(dc *models.DomainConfig) error {
|
||||||
|
versionInfo, err := a.getDomainVersionInfo(dc.Name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get domain version info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rec := range dc.Records {
|
||||||
|
if rec.TTL < versionInfo.minTTL {
|
||||||
|
return fmt.Errorf("record %s has TTL %d which is below the minimum %d for this domain version (%s)",
|
||||||
|
rec.GetLabelFQDN(), rec.TTL, versionInfo.minTTL, versionInfo.versionCode)
|
||||||
|
}
|
||||||
|
if rec.TTL > versionInfo.maxTTL {
|
||||||
|
return fmt.Errorf("record %s has TTL %d which exceeds the maximum %d (24 hours)",
|
||||||
|
rec.GetLabelFQDN(), rec.TTL, versionInfo.maxTTL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *aliDnsDsp) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
|
func (a *aliDnsDsp) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
|
||||||
|
// Validate TTL constraints for all records
|
||||||
|
if err := a.validateRecordTTLs(dc); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
var corrections []*models.Correction
|
var corrections []*models.Correction
|
||||||
|
|
||||||
// Azure is a "ByRecordSet" API.
|
// Azure is a "ByRecordSet" API.
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,45 @@ import (
|
||||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
|
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (a *aliDnsDsp) getDomainVersionInfo(domain string) (*domainVersionInfo, error) {
|
||||||
|
// Check cache first
|
||||||
|
if info, ok := a.domainVersionCache[domain]; ok {
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
req := alidns.CreateDescribeDomainInfoRequest()
|
||||||
|
req.DomainName = domain
|
||||||
|
|
||||||
|
resp, err := a.client.DescribeDomainInfo(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine minTTL based on VersionCode
|
||||||
|
var minTTL uint32
|
||||||
|
switch resp.VersionCode {
|
||||||
|
case "version_enterprise_advanced":
|
||||||
|
minTTL = 1 // Enterprise Ultimate Edition
|
||||||
|
case "version_personal", "mianfei":
|
||||||
|
minTTL = 600 // Personal Edition and Free Edition
|
||||||
|
default:
|
||||||
|
// Use MinTtl from API if available, otherwise default to 600
|
||||||
|
if resp.MinTtl > 0 {
|
||||||
|
minTTL = uint32(resp.MinTtl)
|
||||||
|
} else {
|
||||||
|
minTTL = 600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info := &domainVersionInfo{
|
||||||
|
versionCode: resp.VersionCode,
|
||||||
|
minTTL: minTTL,
|
||||||
|
maxTTL: 86400,
|
||||||
|
}
|
||||||
|
a.domainVersionCache[domain] = info
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *aliDnsDsp) GetNameservers(domain string) ([]*models.Nameserver, error) {
|
func (a *aliDnsDsp) GetNameservers(domain string) ([]*models.Nameserver, error) {
|
||||||
req := alidns.CreateDescribeDomainInfoRequest()
|
req := alidns.CreateDescribeDomainInfoRequest()
|
||||||
req.DomainName = domain
|
req.DomainName = domain
|
||||||
|
|
|
||||||
|
|
@ -41,21 +41,13 @@ func targetConstraint(rc *models.RecordConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ttlConstraint checks that TTL is within Alibaba Cloud's allowed range (600-86400 seconds).
|
|
||||||
func ttlConstraint(rc *models.RecordConfig) error {
|
|
||||||
if rc.TTL < 600 {
|
|
||||||
return errors.New("TTL must be at least 600 seconds")
|
|
||||||
}
|
|
||||||
if rc.TTL > 86400 {
|
|
||||||
return errors.New("TTL must not exceed 86400 seconds (24 hours)")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuditRecords returns a list of errors corresponding to the records
|
// AuditRecords returns a list of errors corresponding to the records
|
||||||
// that aren't supported by this provider. If all records are
|
// that aren't supported by this provider. If all records are
|
||||||
// supported, an empty list is returned.
|
// supported, an empty list is returned.
|
||||||
func AuditRecords(records []*models.RecordConfig) []error {
|
func AuditRecords(records []*models.RecordConfig) []error {
|
||||||
|
// Note: We can't get domain version info here because AuditRecords
|
||||||
|
// is called without provider context. TTL validation will be done
|
||||||
|
// at the provider level in GetZoneRecordsCorrections.
|
||||||
a := rejectif.Auditor{}
|
a := rejectif.Auditor{}
|
||||||
|
|
||||||
a.Add("MX", rejectif.MxNull) // Last verified at 2025-12-03
|
a.Add("MX", rejectif.MxNull) // Last verified at 2025-12-03
|
||||||
|
|
@ -65,7 +57,6 @@ func AuditRecords(records []*models.RecordConfig) []error {
|
||||||
a.Add("TXT", rejectif.TxtHasTrailingSpace) // Last verified at 2025-12-03: Alibaba strips trailing spaces
|
a.Add("TXT", rejectif.TxtHasTrailingSpace) // Last verified at 2025-12-03: Alibaba strips trailing spaces
|
||||||
a.Add("TXT", rejectif.TxtHasUnpairedBackslash) // Last verified at 2025-12-03: Alibaba mishandles odd backslashes
|
a.Add("TXT", rejectif.TxtHasUnpairedBackslash) // Last verified at 2025-12-03: Alibaba mishandles odd backslashes
|
||||||
a.Add("*", labelConstraint) // Last verified at 2025-12-03: Alibaba only allows ASCII + Chinese, rejects other Unicode
|
a.Add("*", labelConstraint) // Last verified at 2025-12-03: Alibaba only allows ASCII + Chinese, rejects other Unicode
|
||||||
a.Add("*", ttlConstraint) // Last verified at 2025-12-03: Alibaba requires TTL 600-86400
|
|
||||||
a.Add("CNAME", targetConstraint) // Last verified at 2025-12-03: CNAME target must be ASCII or Chinese
|
a.Add("CNAME", targetConstraint) // Last verified at 2025-12-03: CNAME target must be ASCII or Chinese
|
||||||
a.Add("SRV", rejectif.SrvHasNullTarget) // Last verified at 2025-12-03: SRV target must not be null
|
a.Add("SRV", rejectif.SrvHasNullTarget) // Last verified at 2025-12-03: SRV target must not be null
|
||||||
a.Add("SRV", rejectif.SrvHasEmptyTarget) // Last verified at 2025-12-03: SRV target must not be empty
|
a.Add("SRV", rejectif.SrvHasEmptyTarget) // Last verified at 2025-12-03: SRV target must not be empty
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue