Skip to content

Commit 591a7b2

Browse files
authored
GCLOUD: Enable support for AutoDNSSEC (#4118)
## Release changelog section * GCLOUD: Enable AUTODNSSEC
1 parent 9d893dc commit 591a7b2

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

documentation/provider/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ Jump to a table:
355355
| [`DNSMADEEASY`](dnsmadeeasy.md) ||||
356356
| [`DOMAINNAMESHOP`](domainnameshop.md) ||||
357357
| [`GANDI_V5`](gandiv5.md) ||||
358+
| [`GCLOUD`](gcloud.md) ||||
358359
| [`GCORE`](gcore.md) ||||
359360
| [`GIDINET`](gidinet.md) ||||
360361
| [`HEDNS`](hedns.md) ||||

providers/gcloud/dnssec.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package gcloud
2+
3+
import (
4+
"time"
5+
6+
"github.com/StackExchange/dnscontrol/v4/models"
7+
gdns "google.golang.org/api/dns/v1"
8+
)
9+
10+
func (g *gcloudProvider) getDnssecCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
11+
enabled, err := g.isDnssecEnabled(dc.Name)
12+
if err != nil {
13+
return nil, err
14+
}
15+
if enabled && dc.AutoDNSSEC == "off" {
16+
return []*models.Correction{
17+
{
18+
Msg: "Disable DNSSEC",
19+
F: func() error { err := g.disableDnssec(dc.Name); return err },
20+
},
21+
}, nil
22+
}
23+
24+
if !enabled && dc.AutoDNSSEC == "on" {
25+
return []*models.Correction{
26+
{
27+
Msg: "Enable DNSSEC",
28+
F: func() error { err := g.enableDnssec(dc.Name); return err },
29+
},
30+
}, nil
31+
}
32+
33+
return nil, nil
34+
}
35+
36+
func (g *gcloudProvider) isDnssecEnabled(domain string) (bool, error) {
37+
// Zones that never had DNSSEC enabled will have nil in the DnssecConfig field
38+
if g.zones[domain+"."].DnssecConfig == nil {
39+
return false, nil
40+
}
41+
if g.zones[domain+"."].DnssecConfig.State == "on" {
42+
return true, nil
43+
}
44+
// Google Cloud DNS has a "transfer" state for DNSSEC. We treat it as "on".
45+
// It basically means that DNSSEC is enabled, but Google won't rotate ZSKs.
46+
if g.zones[domain+"."].DnssecConfig.State == "transfer" {
47+
return true, nil
48+
}
49+
return false, nil
50+
}
51+
52+
func (g *gcloudProvider) enableDnssec(domain string) error {
53+
dnssecPatch := &gdns.ManagedZone{
54+
DnssecConfig: &gdns.ManagedZoneDnsSecConfig{
55+
State: "on",
56+
},
57+
}
58+
resp, err := g.client.ManagedZones.Patch(g.project, g.zones[domain+"."].Name, dnssecPatch).Do()
59+
if err != nil {
60+
return err
61+
}
62+
if resp.Status != "done" {
63+
// Should we have a timeout here?
64+
for {
65+
checkOperation, err := g.client.ManagedZoneOperations.Get(g.project, g.zones[domain+"."].Name, resp.Id).Do()
66+
if err != nil {
67+
return err
68+
}
69+
if checkOperation.Status == "done" {
70+
return nil
71+
}
72+
time.Sleep(2 * time.Second)
73+
}
74+
}
75+
76+
return nil
77+
}
78+
79+
func (g *gcloudProvider) disableDnssec(domain string) error {
80+
dnssecPatch := &gdns.ManagedZone{
81+
DnssecConfig: &gdns.ManagedZoneDnsSecConfig{
82+
State: "off",
83+
},
84+
}
85+
resp, err := g.client.ManagedZones.Patch(g.project, g.zones[domain+"."].Name, dnssecPatch).Do()
86+
if err != nil {
87+
return err
88+
}
89+
if resp.Status != "done" {
90+
// Should we have a timeout here?
91+
for {
92+
checkOperation, err := g.client.ManagedZoneOperations.Get(g.project, g.zones[domain+"."].Name, resp.Id).Do()
93+
if err != nil {
94+
return err
95+
}
96+
if checkOperation.Status == "done" {
97+
return nil
98+
}
99+
time.Sleep(2 * time.Second)
100+
}
101+
}
102+
103+
return nil
104+
}

providers/gcloud/gcloudProvider.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const selfLinkBasePath = "https://www.googleapis.com/compute/v1/projects/"
2424
var features = providers.DocumentationNotes{
2525
// The default for unlisted capabilities is 'Cannot'.
2626
// See providers/capabilities.go for the entire list of capabilities.
27+
providers.CanAutoDNSSEC: providers.Can(),
2728
providers.CanGetZones: providers.Can(),
2829
providers.CanConcur: providers.Can(),
2930
providers.CanUseAlias: providers.Can(),
@@ -241,15 +242,25 @@ func (g *gcloudProvider) getZoneSets(domain string) (models.Records, error) {
241242

242243
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
243244
func (g *gcloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
245+
dnssecFixes, err := g.getDnssecCorrections(dc)
246+
if err != nil {
247+
return nil, 0, err
248+
}
249+
244250
changes, actualChangeCount, err := diff2.ByRecordSet(existingRecords, dc, nil)
245251
if err != nil {
246252
return nil, 0, err
247253
}
248-
if len(changes) == 0 {
254+
if len(changes) == 0 && len(dnssecFixes) == 0 {
249255
return nil, 0, nil
250256
}
251257

252258
var corrections []*models.Correction
259+
// Inject the dnssec correction if we have one
260+
if len(dnssecFixes) != 0 {
261+
actualChangeCount += len(dnssecFixes)
262+
corrections = append(corrections, dnssecFixes...)
263+
}
253264
batch := &gdns.Change{Kind: "dns#change"}
254265
var accumlatedMsgs []string
255266
var newMsgs []string

0 commit comments

Comments
 (0)