mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
MSDNS: Improve reliability of zone dump (#1179)
* MSDNS: Improve reliability of zone dump * Update tests
This commit is contained in:
@ -97,50 +97,62 @@ func generatePSZoneAll(dnsserver string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (psh *psHandle) GetDNSZoneRecords(dnsserver, domain string) ([]nativeRecord, error) {
|
func (psh *psHandle) GetDNSZoneRecords(dnsserver, domain string) ([]nativeRecord, error) {
|
||||||
|
|
||||||
tmpfile, err := ioutil.TempFile("", "zonerecords.*.json")
|
tmpfile, err := ioutil.TempFile("", "zonerecords.*.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
filename := tmpfile.Name()
|
||||||
tmpfile.Close()
|
tmpfile.Close()
|
||||||
|
|
||||||
stdout, stderr, err := psh.shell.Execute(generatePSZoneDump(dnsserver, domain))
|
stdout, stderr, err := psh.shell.Execute(generatePSZoneDump(dnsserver, domain, filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if stdout != "" {
|
|
||||||
//writing all stdout from powershell to file
|
|
||||||
ioutil.WriteFile(tmpfile.Name(), []byte(stdout), 0)
|
|
||||||
}
|
|
||||||
if stderr != "" {
|
if stderr != "" {
|
||||||
fmt.Printf("STDERROR = %q\n", stderr)
|
fmt.Printf("STDERROR = %q\n", stderr)
|
||||||
return nil, fmt.Errorf("unexpected stderr from PSZoneDump: %q", stderr)
|
return nil, fmt.Errorf("unexpected stderr from PSZoneDump: %q", stderr)
|
||||||
}
|
}
|
||||||
|
if stdout != "" {
|
||||||
|
fmt.Printf("STDOUT = %q\n", stdout)
|
||||||
|
}
|
||||||
|
|
||||||
contents, err := utfutil.ReadFile(tmpfile.Name(), utfutil.UTF8)
|
contents, err := utfutil.ReadFile(filename, utfutil.UTF8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
os.Remove(tmpfile.Name())
|
os.Remove(filename) // TODO(tlim): There should be a debug flag that leaves the tmp file around.
|
||||||
|
|
||||||
var records []nativeRecord
|
var records []nativeRecord
|
||||||
json.Unmarshal([]byte(contents), &records)
|
err = json.Unmarshal(contents, &records)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("PSZoneDump json error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return records, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// powerShellDump runs a PowerShell command to get a dump of all records in a DNS zone.
|
// powerShellDump runs a PowerShell command to get a dump of all records in a DNS zone.
|
||||||
func generatePSZoneDump(dnsserver, domainname string) string {
|
func generatePSZoneDump(dnsserver, domainname, filename string) string {
|
||||||
|
// @dnsserver: Hostname of the DNS server.
|
||||||
|
// @domainname: Name of the domain.
|
||||||
|
// @filename: Where to write the resulting JSON file.
|
||||||
|
// NB(tlim): On Windows PowerShell, the JSON file will be UTF8 with
|
||||||
|
// a BOM. A UTF-8 file shouldn't have a BOM, but Microsoft messed up.
|
||||||
|
// When we switch to PowerShell Core, the BOM will disappear.
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
fmt.Fprintf(&b, `$OutputEncoding = [Text.UTF8Encoding]::UTF8 ; `)
|
||||||
fmt.Fprintf(&b, `Get-DnsServerResourceRecord`)
|
fmt.Fprintf(&b, `Get-DnsServerResourceRecord`)
|
||||||
if dnsserver != "" {
|
if dnsserver != "" {
|
||||||
fmt.Fprintf(&b, ` -ComputerName "%v"`, dnsserver)
|
fmt.Fprintf(&b, ` -ComputerName "%v"`, dnsserver)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(&b, ` -ZoneName "%v"`, domainname)
|
fmt.Fprintf(&b, ` -ZoneName "%v"`, domainname)
|
||||||
fmt.Fprintf(&b, ` | `)
|
fmt.Fprintf(&b, ` | `)
|
||||||
|
fmt.Fprintf(&b, `Select-Object -Property * -ExcludeProperty Cim*`)
|
||||||
|
fmt.Fprintf(&b, ` | `)
|
||||||
fmt.Fprintf(&b, `ConvertTo-Json -depth 4`) // Tested with 3 (causes errors). 4 and larger work.
|
fmt.Fprintf(&b, `ConvertTo-Json -depth 4`) // Tested with 3 (causes errors). 4 and larger work.
|
||||||
// All file writing via dnsserver or pssession should be handled outside this function
|
fmt.Fprintf(&b, ` | `)
|
||||||
//fmt.Fprintf(&b, ` > %s`, filename)
|
fmt.Fprintf(&b, `Out-File "%s" -Encoding utf8`, filename)
|
||||||
//fmt.Printf("DEBUG PSZoneDump CMD = (\n%s\n)\n", b.String())
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,17 +49,17 @@ func Test_generatePSZoneDump(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "local",
|
name: "local",
|
||||||
args: args{domainname: "example.com"},
|
args: args{domainname: "example.com"},
|
||||||
want: `Get-DnsServerResourceRecord -ZoneName "example.com" | ConvertTo-Json -depth 4`,
|
want: `$OutputEncoding = [Text.UTF8Encoding]::UTF8 ; Get-DnsServerResourceRecord -ZoneName "example.com" | Select-Object -Property * -ExcludeProperty Cim* | ConvertTo-Json -depth 4 | Out-File "foo" -Encoding utf8`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "remote",
|
name: "remote",
|
||||||
args: args{domainname: "example.com", dnsserver: "mydnsserver"},
|
args: args{domainname: "example.com", dnsserver: "mydnsserver"},
|
||||||
want: `Get-DnsServerResourceRecord -ComputerName "mydnsserver" -ZoneName "example.com" | ConvertTo-Json -depth 4`,
|
want: `$OutputEncoding = [Text.UTF8Encoding]::UTF8 ; Get-DnsServerResourceRecord -ComputerName "mydnsserver" -ZoneName "example.com" | Select-Object -Property * -ExcludeProperty Cim* | ConvertTo-Json -depth 4 | Out-File "foo" -Encoding utf8`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := generatePSZoneDump(tt.args.dnsserver, tt.args.domainname); got != tt.want {
|
if got := generatePSZoneDump(tt.args.dnsserver, tt.args.domainname, "foo"); got != tt.want {
|
||||||
t.Errorf("generatePSZoneDump() = got=(\n%s\n) want=(\n%s\n)", got, tt.want)
|
t.Errorf("generatePSZoneDump() = got=(\n%s\n) want=(\n%s\n)", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user