mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
MSDNS: Adopt diff2 (#2046)
This commit is contained in:
@ -11,21 +11,23 @@ import (
|
|||||||
func AuditRecords(records []*models.RecordConfig) []error {
|
func AuditRecords(records []*models.RecordConfig) []error {
|
||||||
a := rejectif.Auditor{}
|
a := rejectif.Auditor{}
|
||||||
|
|
||||||
a.Add("MX", rejectif.MxNull) // Last verified 2020-12-28
|
a.Add("MX", rejectif.MxNull) // Last verified 2023-02-02
|
||||||
|
|
||||||
a.Add("SRV", rejectif.SrvHasNullTarget) // Last verified 2020-12-28
|
a.Add("SRV", rejectif.SrvHasNullTarget) // Last verified 20-0212-28
|
||||||
|
|
||||||
a.Add("TXT", rejectif.TxtHasBackticks) // Last verified 2021-03-01
|
a.Add("TXT", rejectif.TxtHasBackticks) // Last verified 2023-02-02
|
||||||
|
|
||||||
a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2021-03-01
|
a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2023-02-02
|
||||||
|
|
||||||
a.Add("TXT", rejectif.TxtHasMultipleSegments) // Last verified 2021-03-01
|
a.Add("TXT", rejectif.TxtHasMultipleSegments) // Last verified 2023-02-02
|
||||||
|
|
||||||
a.Add("TXT", rejectif.TxtHasSegmentLen256orLonger)
|
a.Add("TXT", rejectif.TxtHasSegmentLen256orLonger) // Last verified 2023-02-02
|
||||||
|
|
||||||
a.Add("TXT", rejectif.TxtHasSingleQuotes) // Last verified 2021-03-01
|
a.Add("TXT", rejectif.TxtHasSingleQuotes) // Last verified 2023-02-02
|
||||||
|
|
||||||
a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2021-03-01
|
a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2023-02-02
|
||||||
|
|
||||||
|
a.Add("TXT", rejectif.TxtIsExactlyLen255) // Last verified 2023-02-02
|
||||||
|
|
||||||
a.Add("TXT", rejectif.TxtIsExactlyLen255) // Last verified 2023-02-02
|
a.Add("TXT", rejectif.TxtIsExactlyLen255) // Last verified 2023-02-02
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package msdns
|
package msdns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/StackExchange/dnscontrol/v3/models"
|
"github.com/StackExchange/dnscontrol/v3/models"
|
||||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||||
@ -20,26 +22,79 @@ func (client *msdnsProvider) GenerateDomainCorrections(dc *models.DomainConfig,
|
|||||||
if !diff2.EnableDiff2 {
|
if !diff2.EnableDiff2 {
|
||||||
differ := diff.New(dc)
|
differ := diff.New(dc)
|
||||||
_, creates, dels, modifications, err = differ.IncrementalDiff(foundRecords)
|
_, creates, dels, modifications, err = differ.IncrementalDiff(foundRecords)
|
||||||
} else {
|
if err != nil {
|
||||||
differ := diff.NewCompat(dc)
|
return nil, err
|
||||||
_, creates, dels, modifications, err = differ.IncrementalDiff(foundRecords)
|
}
|
||||||
|
|
||||||
|
// Generate changes.
|
||||||
|
for _, del := range dels {
|
||||||
|
corrections = append(corrections, client.deleteRec(client.dnsserver, dc.Name, del))
|
||||||
|
}
|
||||||
|
for _, cre := range creates {
|
||||||
|
corrections = append(corrections, client.createRec(client.dnsserver, dc.Name, cre)...)
|
||||||
|
}
|
||||||
|
for _, m := range modifications {
|
||||||
|
corrections = append(corrections, client.modifyRec(client.dnsserver, dc.Name, m))
|
||||||
|
}
|
||||||
|
return corrections, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changes, err := diff2.ByRecord(foundRecords, dc, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate changes.
|
var corr *models.Correction
|
||||||
for _, del := range dels {
|
for _, change := range changes {
|
||||||
corrections = append(corrections, client.deleteRec(client.dnsserver, dc.Name, del))
|
msgsJoined := change.MsgsJoined
|
||||||
}
|
switch change.Type {
|
||||||
for _, cre := range creates {
|
case diff2.REPORT:
|
||||||
corrections = append(corrections, client.createRec(client.dnsserver, dc.Name, cre)...)
|
corr = &models.Correction{Msg: msgsJoined}
|
||||||
}
|
case diff2.CREATE:
|
||||||
for _, m := range modifications {
|
newrec := change.New[0]
|
||||||
corrections = append(corrections, client.modifyRec(client.dnsserver, dc.Name, m))
|
corr = &models.Correction{
|
||||||
}
|
Msg: msgsJoined,
|
||||||
return corrections, nil
|
F: func() error {
|
||||||
|
return client.createOneRecord(client.dnsserver, dc.Name, newrec)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case diff2.CHANGE:
|
||||||
|
oldrec := change.Old[0]
|
||||||
|
newrec := change.New[0]
|
||||||
|
corr = &models.Correction{
|
||||||
|
Msg: msgsJoined,
|
||||||
|
F: func() error {
|
||||||
|
return client.modifyOneRecord(client.dnsserver, dc.Name, oldrec, newrec)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case diff2.DELETE:
|
||||||
|
oldrec := change.Old[0]
|
||||||
|
corr = &models.Correction{
|
||||||
|
Msg: msgsJoined,
|
||||||
|
F: func() error {
|
||||||
|
return client.deleteOneRecord(client.dnsserver, dc.Name, oldrec)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unhandled change.Type %s", change.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
corrections = append(corrections, corr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return corrections, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *msdnsProvider) deleteOneRecord(dnsserver, zonename string, oldrec *models.RecordConfig) error {
|
||||||
|
return client.shell.RecordDelete(dnsserver, zonename, oldrec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *msdnsProvider) createOneRecord(dnsserver, zonename string, newrec *models.RecordConfig) error {
|
||||||
|
return client.shell.RecordCreate(dnsserver, zonename, newrec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *msdnsProvider) modifyOneRecord(dnsserver, zonename string, oldrec, newrec *models.RecordConfig) error {
|
||||||
|
return client.shell.RecordModify(dnsserver, zonename, oldrec, newrec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *msdnsProvider) deleteRec(dnsserver, domainname string, cor diff.Correlation) *models.Correction {
|
func (client *msdnsProvider) deleteRec(dnsserver, domainname string, cor diff.Correlation) *models.Correction {
|
||||||
|
@ -19,6 +19,13 @@ type psHandle struct {
|
|||||||
shell ps.Shell
|
shell ps.Shell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func eLog(s string) {
|
||||||
|
// f, _ := os.OpenFile("powershell.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
// f.WriteString(s)
|
||||||
|
// f.WriteString("\n")
|
||||||
|
// f.Close()
|
||||||
|
// }
|
||||||
|
|
||||||
func newPowerShell(config map[string]string) (*psHandle, error) {
|
func newPowerShell(config map[string]string) (*psHandle, error) {
|
||||||
|
|
||||||
back := &backend.Local{}
|
back := &backend.Local{}
|
||||||
@ -200,8 +207,10 @@ func (psh *psHandle) RecordDelete(dnsserver, domain string, rec *models.RecordCo
|
|||||||
c = generatePSDelete(dnsserver, domain, rec)
|
c = generatePSDelete(dnsserver, domain, rec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//eLog(c)
|
||||||
_, stderr, err := psh.shell.Execute(c)
|
_, stderr, err := psh.shell.Execute(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
printer.Printf("PowerShell code was:\nSTART\n%s\nEND\n", c)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if stderr != "" {
|
if stderr != "" {
|
||||||
@ -215,7 +224,7 @@ func (psh *psHandle) RecordDelete(dnsserver, domain string, rec *models.RecordCo
|
|||||||
func generatePSDelete(dnsserver, domain string, rec *models.RecordConfig) string {
|
func generatePSDelete(dnsserver, domain string, rec *models.RecordConfig) string {
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
fmt.Fprintf(&b, `echo DELETE "%s" "%s" "..."`, rec.Type, rec.Name)
|
fmt.Fprintf(&b, `echo DELETE "%s" "%s" "[target]"`, rec.Type, rec.Name)
|
||||||
fmt.Fprintf(&b, " ; ")
|
fmt.Fprintf(&b, " ; ")
|
||||||
|
|
||||||
if rec.Type == "NAPTR" {
|
if rec.Type == "NAPTR" {
|
||||||
@ -229,13 +238,13 @@ func generatePSDelete(dnsserver, domain string, rec *models.RecordConfig) string
|
|||||||
fmt.Fprintf(&b, ` -ComputerName "%s"`, dnsserver)
|
fmt.Fprintf(&b, ` -ComputerName "%s"`, dnsserver)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(&b, ` -Force`)
|
fmt.Fprintf(&b, ` -Force`)
|
||||||
fmt.Fprintf(&b, ` -ZoneName "%s"`, domain)
|
fmt.Fprintf(&b, ` -ZoneName %q`, domain)
|
||||||
fmt.Fprintf(&b, ` -Name "%s"`, rec.Name)
|
fmt.Fprintf(&b, ` -Name %q`, rec.Name)
|
||||||
fmt.Fprintf(&b, ` -RRType "%s"`, rec.Type)
|
fmt.Fprintf(&b, ` -RRType "%s"`, rec.Type)
|
||||||
if rec.Type == "MX" {
|
if rec.Type == "MX" {
|
||||||
fmt.Fprintf(&b, ` -RecordData %d,"%s"`, rec.MxPreference, rec.GetTargetField())
|
fmt.Fprintf(&b, ` -RecordData %d,%q`, rec.MxPreference, rec.GetTargetField())
|
||||||
} else if rec.Type == "TXT" {
|
} else if rec.Type == "TXT" {
|
||||||
fmt.Fprintf(&b, ` -RecordData %s`, rec.GetTargetField())
|
fmt.Fprintf(&b, ` -RecordData %q`, rec.GetTargetTXTJoined())
|
||||||
} else if rec.Type == "SRV" {
|
} else if rec.Type == "SRV" {
|
||||||
// https://www.gitmemory.com/issue/MicrosoftDocs/windows-powershell-docs/1149/511916884
|
// https://www.gitmemory.com/issue/MicrosoftDocs/windows-powershell-docs/1149/511916884
|
||||||
fmt.Fprintf(&b, ` -RecordData %d,%d,%d,"%s"`, rec.SrvPriority, rec.SrvWeight, rec.SrvPort, rec.GetTargetField())
|
fmt.Fprintf(&b, ` -RecordData %d,%d,%d,"%s"`, rec.SrvPriority, rec.SrvWeight, rec.SrvPort, rec.GetTargetField())
|
||||||
@ -257,6 +266,7 @@ func (psh *psHandle) RecordCreate(dnsserver, domain string, rec *models.RecordCo
|
|||||||
//printer.Printf("DEBUG: PScreate\n")
|
//printer.Printf("DEBUG: PScreate\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//eLog(c)
|
||||||
stdout, stderr, err := psh.shell.Execute(c)
|
stdout, stderr, err := psh.shell.Execute(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printer.Printf("PowerShell code was:\nSTART\n%s\nEND\n", c)
|
printer.Printf("PowerShell code was:\nSTART\n%s\nEND\n", c)
|
||||||
@ -265,6 +275,7 @@ func (psh *psHandle) RecordCreate(dnsserver, domain string, rec *models.RecordCo
|
|||||||
if stderr != "" {
|
if stderr != "" {
|
||||||
printer.Printf("STDOUT RecordCreate = %s\n", stdout)
|
printer.Printf("STDOUT RecordCreate = %s\n", stdout)
|
||||||
printer.Printf("STDERROR RecordCreate = %q\n", stderr)
|
printer.Printf("STDERROR RecordCreate = %q\n", stderr)
|
||||||
|
printer.Printf("PowerShell code was:\nSTART\n%s\nEND\n", c)
|
||||||
return fmt.Errorf("unexpected stderr from PSCreate: %q", stderr)
|
return fmt.Errorf("unexpected stderr from PSCreate: %q", stderr)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -272,7 +283,7 @@ func (psh *psHandle) RecordCreate(dnsserver, domain string, rec *models.RecordCo
|
|||||||
|
|
||||||
func generatePSCreate(dnsserver, domain string, rec *models.RecordConfig) string {
|
func generatePSCreate(dnsserver, domain string, rec *models.RecordConfig) string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
fmt.Fprintf(&b, `echo CREATE "%s" "%s" "..."`, rec.Type, rec.Name)
|
fmt.Fprintf(&b, `echo CREATE "%s" "%s" "[target]"`, rec.Type, rec.Name)
|
||||||
fmt.Fprintf(&b, " ; ")
|
fmt.Fprintf(&b, " ; ")
|
||||||
|
|
||||||
if rec.Type == "NAPTR" {
|
if rec.Type == "NAPTR" {
|
||||||
@ -339,6 +350,7 @@ func generatePSCreate(dnsserver, domain string, rec *models.RecordConfig) string
|
|||||||
|
|
||||||
func (psh *psHandle) RecordModify(dnsserver, domain string, old, rec *models.RecordConfig) error {
|
func (psh *psHandle) RecordModify(dnsserver, domain string, old, rec *models.RecordConfig) error {
|
||||||
c := generatePSModify(dnsserver, domain, old, rec)
|
c := generatePSModify(dnsserver, domain, old, rec)
|
||||||
|
//eLog(c)
|
||||||
_, stderr, err := psh.shell.Execute(c)
|
_, stderr, err := psh.shell.Execute(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printer.Printf("PowerShell code was:\nSTART\n%s\nEND\n", c)
|
printer.Printf("PowerShell code was:\nSTART\n%s\nEND\n", c)
|
||||||
|
@ -146,16 +146,16 @@ func Test_generatePSModify(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{name: "A", args: args{domain: "example.com", dnsserver: "", old: recA1, rec: recA2},
|
{name: "A", args: args{domain: "example.com", dnsserver: "", old: recA1, rec: recA2},
|
||||||
want: `echo DELETE "A" "@" "..." ; Remove-DnsServerResourceRecord -Force -ZoneName "example.com" -Name "@" -RRType "A" -RecordData "1.2.3.4" ; echo CREATE "A" "@" "..." ; Add-DnsServerResourceRecord -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -A -IPv4Address "10.20.30.40"`,
|
want: `echo DELETE "A" "@" "[target]" ; Remove-DnsServerResourceRecord -Force -ZoneName "example.com" -Name "@" -RRType "A" -RecordData "1.2.3.4" ; echo CREATE "A" "@" "[target]" ; Add-DnsServerResourceRecord -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -A -IPv4Address "10.20.30.40"`,
|
||||||
},
|
},
|
||||||
{name: "MX1", args: args{domain: "example.com", dnsserver: "", old: recMX1, rec: recMX2},
|
{name: "MX1", args: args{domain: "example.com", dnsserver: "", old: recMX1, rec: recMX2},
|
||||||
want: `echo DELETE "MX" "@" "..." ; Remove-DnsServerResourceRecord -Force -ZoneName "example.com" -Name "@" -RRType "MX" -RecordData 5,"foo.com." ; echo CREATE "MX" "@" "..." ; Add-DnsServerResourceRecord -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -MX -MailExchange "foo2.com." -Preference 50`,
|
want: `echo DELETE "MX" "@" "[target]" ; Remove-DnsServerResourceRecord -Force -ZoneName "example.com" -Name "@" -RRType "MX" -RecordData 5,"foo.com." ; echo CREATE "MX" "@" "[target]" ; Add-DnsServerResourceRecord -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -MX -MailExchange "foo2.com." -Preference 50`,
|
||||||
},
|
},
|
||||||
{name: "A-remote", args: args{domain: "example.com", dnsserver: "myremote", old: recA1, rec: recA2},
|
{name: "A-remote", args: args{domain: "example.com", dnsserver: "myremote", old: recA1, rec: recA2},
|
||||||
want: `echo DELETE "A" "@" "..." ; Remove-DnsServerResourceRecord -ComputerName "myremote" -Force -ZoneName "example.com" -Name "@" -RRType "A" -RecordData "1.2.3.4" ; echo CREATE "A" "@" "..." ; Add-DnsServerResourceRecord -ComputerName "myremote" -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -A -IPv4Address "10.20.30.40"`,
|
want: `echo DELETE "A" "@" "[target]" ; Remove-DnsServerResourceRecord -ComputerName "myremote" -Force -ZoneName "example.com" -Name "@" -RRType "A" -RecordData "1.2.3.4" ; echo CREATE "A" "@" "[target]" ; Add-DnsServerResourceRecord -ComputerName "myremote" -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -A -IPv4Address "10.20.30.40"`,
|
||||||
},
|
},
|
||||||
{name: "MX1-remote", args: args{domain: "example.com", dnsserver: "yourremote", old: recMX1, rec: recMX2},
|
{name: "MX1-remote", args: args{domain: "example.com", dnsserver: "yourremote", old: recMX1, rec: recMX2},
|
||||||
want: `echo DELETE "MX" "@" "..." ; Remove-DnsServerResourceRecord -ComputerName "yourremote" -Force -ZoneName "example.com" -Name "@" -RRType "MX" -RecordData 5,"foo.com." ; echo CREATE "MX" "@" "..." ; Add-DnsServerResourceRecord -ComputerName "yourremote" -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -MX -MailExchange "foo2.com." -Preference 50`,
|
want: `echo DELETE "MX" "@" "[target]" ; Remove-DnsServerResourceRecord -ComputerName "yourremote" -Force -ZoneName "example.com" -Name "@" -RRType "MX" -RecordData 5,"foo.com." ; echo CREATE "MX" "@" "[target]" ; Add-DnsServerResourceRecord -ComputerName "yourremote" -ZoneName "example.com" -Name "@" -TimeToLive $(New-TimeSpan -Seconds 0) -MX -MailExchange "foo2.com." -Preference 50`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
Reference in New Issue
Block a user