mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-10 17:38:13 +08:00
BIND: Implement AutoDNSSEC (#648)
There's a philosophy issue here around what is the Bind output meant to do. Since AFAIK we're not integrating into Bind's catalog zones or the like, we're just targeting the zonefiles, we're not in a position to do _anything_ relating to registrar options such as setting up DS glue. So at one level, enabling AutoDNSSEC for Bind is a lie. But without this, folks can't target a Bind zone as a secondary provider for their domain, to get debug dumps of the zone output, because the checks for "Can" block it. So I think this commit achieves a happy compromise: we write a comment into the Bind zonefile, indicating that DNSSEC was requested. Actually: we add support for arbitrary zone comments to be written into a zonefile via a slightly ugly "can be `nil`" parameter. We then write in a generation timestamp comment, and if AutoDNSSEC was requested we then write that in too.
This commit is contained in:
parent
7384743f6d
commit
3c41a39252
6 changed files with 41 additions and 12 deletions
|
@ -151,11 +151,11 @@ func GetZone(args GetZoneArgs) error {
|
|||
for i, recs := range zoneRecs {
|
||||
zoneName := zones[i]
|
||||
|
||||
z := prettyzone.PrettySort(recs, zoneName, 0)
|
||||
z := prettyzone.PrettySort(recs, zoneName, 0, nil)
|
||||
switch args.OutputFormat {
|
||||
case "pretty":
|
||||
fmt.Fprintf(w, "$ORIGIN %s.\n", zoneName)
|
||||
prettyzone.WriteZoneFileRC(w, z.Records, zoneName)
|
||||
prettyzone.WriteZoneFileRC(w, z.Records, zoneName, nil)
|
||||
fmt.Fprintln(w)
|
||||
case "dsl":
|
||||
|
||||
|
|
|
@ -313,7 +313,9 @@
|
|||
<th class="row-header" style="text-decoration: underline;" data-toggle="tooltip" data-container="body" data-placement="top" title="Provider can automatically manage DNSSEC">AUTODNSSEC</th>
|
||||
<td><i class="fa fa-minus dim"></i></td>
|
||||
<td><i class="fa fa-minus dim"></i></td>
|
||||
<td><i class="fa fa-minus dim"></i></td>
|
||||
<td class="success" data-toggle="tooltip" data-container="body" data-placement="top" title="Just writes out a comment indicating DNSSEC was requested">
|
||||
<i class="fa has-tooltip fa-check text-success" aria-hidden="true"></i>
|
||||
</td>
|
||||
<td><i class="fa fa-minus dim"></i></td>
|
||||
<td><i class="fa fa-minus dim"></i></td>
|
||||
<td><i class="fa fa-minus dim"></i></td>
|
||||
|
@ -981,8 +983,8 @@
|
|||
<td class="info">
|
||||
<i class="fa fa-circle-o text-info" aria-hidden="true"></i>
|
||||
</td>
|
||||
<td class="info">
|
||||
<i class="fa fa-circle-o text-info" aria-hidden="true"></i>
|
||||
<td class="success">
|
||||
<i class="fa fa-check text-success" aria-hidden="true"></i>
|
||||
</td>
|
||||
<td><i class="fa fa-minus dim"></i></td>
|
||||
<td class="info">
|
||||
|
|
|
@ -45,11 +45,11 @@ func mostCommonTTL(records models.Records) uint32 {
|
|||
|
||||
// WriteZoneFileRR is a helper for when you have []dns.RR instead of models.Records
|
||||
func WriteZoneFileRR(w io.Writer, records []dns.RR, origin string, serial uint32) error {
|
||||
return WriteZoneFileRC(w, models.RRstoRCs(records, origin, serial), origin)
|
||||
return WriteZoneFileRC(w, models.RRstoRCs(records, origin, serial), origin, nil)
|
||||
}
|
||||
|
||||
// WriteZoneFileRC writes a beautifully formatted zone file.
|
||||
func WriteZoneFileRC(w io.Writer, records models.Records, origin string) error {
|
||||
func WriteZoneFileRC(w io.Writer, records models.Records, origin string, comments []string) error {
|
||||
// This function prioritizes beauty over output size.
|
||||
// * The zone records are sorted by label, grouped by subzones to
|
||||
// be easy to read and pleasant to the eye.
|
||||
|
@ -61,18 +61,19 @@ func WriteZoneFileRC(w io.Writer, records models.Records, origin string) error {
|
|||
// * $TTL is used to eliminate clutter. The most common TTL value is used.
|
||||
// * "@" is used instead of the apex domain name.
|
||||
|
||||
z := PrettySort(records, origin, mostCommonTTL(records))
|
||||
z := PrettySort(records, origin, mostCommonTTL(records), comments)
|
||||
|
||||
return z.generateZoneFileHelper(w)
|
||||
}
|
||||
|
||||
func PrettySort(records models.Records, origin string, defaultTTL uint32) *zoneGenData {
|
||||
func PrettySort(records models.Records, origin string, defaultTTL uint32, comments []string) *zoneGenData {
|
||||
if defaultTTL == 0 {
|
||||
defaultTTL = mostCommonTTL(records)
|
||||
}
|
||||
z := &zoneGenData{
|
||||
Origin: origin + ".",
|
||||
DefaultTTL: defaultTTL,
|
||||
Comments: comments,
|
||||
}
|
||||
z.Records = nil
|
||||
for _, r := range records {
|
||||
|
@ -88,6 +89,13 @@ func (z *zoneGenData) generateZoneFileHelper(w io.Writer) error {
|
|||
|
||||
sort.Sort(z)
|
||||
fmt.Fprintln(w, "$TTL", z.DefaultTTL)
|
||||
for _, comment := range z.Comments {
|
||||
for _, line := range strings.Split(comment, "\n") {
|
||||
if line != "" {
|
||||
fmt.Fprintln(w, ";", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, rr := range z.Records {
|
||||
|
||||
// Fake types are commented out.
|
||||
|
|
|
@ -295,8 +295,12 @@ func TestWriteZoneFileSynth(t *testing.T) {
|
|||
recs = append(recs, rsynz)
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
WriteZoneFileRC(buf, recs, "bosun.org")
|
||||
WriteZoneFileRC(buf, recs, "bosun.org", []string{"c1", "c2", "c3\nc4"})
|
||||
expected := `$TTL 300
|
||||
; c1
|
||||
; c2
|
||||
; c3
|
||||
; c4
|
||||
@ IN A 192.30.252.153
|
||||
IN A 192.30.252.154
|
||||
;myalias IN R53_ALIAS type= zone_id=
|
||||
|
|
|
@ -16,6 +16,7 @@ type zoneGenData struct {
|
|||
Origin string
|
||||
DefaultTTL uint32
|
||||
Records models.Records
|
||||
Comments []string
|
||||
}
|
||||
|
||||
func (z *zoneGenData) Len() int { return len(z.Records) }
|
||||
|
|
|
@ -3,7 +3,7 @@ package bind
|
|||
/*
|
||||
|
||||
bind -
|
||||
Generate zonefiles suitiable for BIND.
|
||||
Generate zonefiles suitable for BIND.
|
||||
|
||||
The zonefiles are read and written to the directory -bind_dir
|
||||
|
||||
|
@ -21,6 +21,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
|
||||
|
@ -38,6 +39,7 @@ var features = providers.DocumentationNotes{
|
|||
providers.CanUseSSHFP: providers.Can(),
|
||||
providers.CanUseTLSA: providers.Can(),
|
||||
providers.CanUseTXTMulti: providers.Can(),
|
||||
providers.CanAutoDNSSEC: providers.Can("Just writes out a comment indicating DNSSEC was requested"),
|
||||
providers.CantUseNOPURGE: providers.Cannot(),
|
||||
providers.DocCreateDomains: providers.Can("Driver just maintains list of zone files. It should automatically add missing ones."),
|
||||
providers.DocDualHost: providers.Can(),
|
||||
|
@ -214,10 +216,19 @@ func (c *Bind) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correcti
|
|||
// foundDiffRecords < foundRecords
|
||||
// diff.Inc...(foundDiffRecords, expectedDiffRecords )
|
||||
|
||||
comments := make([]string, 0, 5)
|
||||
|
||||
comments = append(comments,
|
||||
fmt.Sprintf("generated with dnscontrol %s", time.Now().Format(time.RFC3339)),
|
||||
)
|
||||
|
||||
foundRecords, err := c.GetZoneRecords(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if dc.AutoDNSSEC {
|
||||
comments = append(comments, "Automatic DNSSEC signing requested")
|
||||
}
|
||||
|
||||
// Normalize
|
||||
models.PostProcessRecords(foundRecords)
|
||||
|
@ -262,7 +273,10 @@ func (c *Bind) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correcti
|
|||
if err != nil {
|
||||
log.Fatalf("Could not create zonefile: %v", err)
|
||||
}
|
||||
err = prettyzone.WriteZoneFileRC(zf, dc.Records, dc.Name)
|
||||
// Beware that if there are any fake types, then they will
|
||||
// be commented out on write, but we don't reverse that when
|
||||
// reading, so there will be a diff on every invocation.
|
||||
err = prettyzone.WriteZoneFileRC(zf, dc.Records, dc.Name, comments)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("WriteZoneFile error: %v\n", err)
|
||||
|
|
Loading…
Reference in a new issue