Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNSSec on Managed Zones #3677

Merged
merged 1 commit into from
May 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 255 additions & 0 deletions google/resource_dns_managed_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"log"
"reflect"
"strconv"
"time"

"github.com/hashicorp/terraform/helper/hashcode"
Expand Down Expand Up @@ -59,6 +60,66 @@ func resourceDnsManagedZone() *schema.Resource {
Optional: true,
Default: "Managed by Terraform",
},
"dnssec_config": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"default_key_specs": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"algorithm": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"ecdsap256sha256", "ecdsap384sha384", "rsasha1", "rsasha256", "rsasha512", ""}, false),
},
"key_length": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"key_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"keySigning", "zoneSigning", ""}, false),
},
"kind": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: "dns#dnsKeySpec",
},
},
},
},
"kind": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: "dns#managedZoneDnsSecConfig",
},
"non_existence": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"nsec", "nsec3", ""}, false),
},
"state": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"off", "on", "transfer", ""}, false),
},
},
},
},
"labels": {
Type: schema.TypeMap,
Optional: true,
Expand Down Expand Up @@ -140,6 +201,12 @@ func resourceDnsManagedZoneCreate(d *schema.ResourceData, meta interface{}) erro
} else if v, ok := d.GetOkExists("dns_name"); !isEmptyValue(reflect.ValueOf(dnsNameProp)) && (ok || !reflect.DeepEqual(v, dnsNameProp)) {
obj["dnsName"] = dnsNameProp
}
dnssecConfigProp, err := expandDnsManagedZoneDnssecConfig(d.Get("dnssec_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("dnssec_config"); !isEmptyValue(reflect.ValueOf(dnssecConfigProp)) && (ok || !reflect.DeepEqual(v, dnssecConfigProp)) {
obj["dnssecConfig"] = dnssecConfigProp
}
nameProp, err := expandDnsManagedZoneName(d.Get("name"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -215,6 +282,9 @@ func resourceDnsManagedZoneRead(d *schema.ResourceData, meta interface{}) error
if err := d.Set("dns_name", flattenDnsManagedZoneDnsName(res["dnsName"], d)); err != nil {
return fmt.Errorf("Error reading ManagedZone: %s", err)
}
if err := d.Set("dnssec_config", flattenDnsManagedZoneDnssecConfig(res["dnssecConfig"], d)); err != nil {
return fmt.Errorf("Error reading ManagedZone: %s", err)
}
if err := d.Set("name", flattenDnsManagedZoneName(res["name"], d)); err != nil {
return fmt.Errorf("Error reading ManagedZone: %s", err)
}
Expand Down Expand Up @@ -322,6 +392,80 @@ func flattenDnsManagedZoneDnsName(v interface{}, d *schema.ResourceData) interfa
return v
}

func flattenDnsManagedZoneDnssecConfig(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["kind"] =
flattenDnsManagedZoneDnssecConfigKind(original["kind"], d)
transformed["non_existence"] =
flattenDnsManagedZoneDnssecConfigNonExistence(original["nonExistence"], d)
transformed["state"] =
flattenDnsManagedZoneDnssecConfigState(original["state"], d)
transformed["default_key_specs"] =
flattenDnsManagedZoneDnssecConfigDefaultKeySpecs(original["defaultKeySpecs"], d)
return []interface{}{transformed}
}
func flattenDnsManagedZoneDnssecConfigKind(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenDnsManagedZoneDnssecConfigNonExistence(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenDnsManagedZoneDnssecConfigState(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenDnsManagedZoneDnssecConfigDefaultKeySpecs(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"algorithm": flattenDnsManagedZoneDnssecConfigDefaultKeySpecsAlgorithm(original["algorithm"], d),
"key_length": flattenDnsManagedZoneDnssecConfigDefaultKeySpecsKeyLength(original["keyLength"], d),
"key_type": flattenDnsManagedZoneDnssecConfigDefaultKeySpecsKeyType(original["keyType"], d),
"kind": flattenDnsManagedZoneDnssecConfigDefaultKeySpecsKind(original["kind"], d),
})
}
return transformed
}
func flattenDnsManagedZoneDnssecConfigDefaultKeySpecsAlgorithm(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenDnsManagedZoneDnssecConfigDefaultKeySpecsKeyLength(v interface{}, d *schema.ResourceData) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
return intVal
} // let terraform core handle it if we can't convert the string to an int.
}
return v
}

func flattenDnsManagedZoneDnssecConfigDefaultKeySpecsKeyType(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenDnsManagedZoneDnssecConfigDefaultKeySpecsKind(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func flattenDnsManagedZoneName(v interface{}, d *schema.ResourceData) interface{} {
return v
}
Expand Down Expand Up @@ -392,6 +536,117 @@ func expandDnsManagedZoneDnsName(v interface{}, d TerraformResourceData, config
return v, nil
}

func expandDnsManagedZoneDnssecConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedKind, err := expandDnsManagedZoneDnssecConfigKind(original["kind"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKind); val.IsValid() && !isEmptyValue(val) {
transformed["kind"] = transformedKind
}

transformedNonExistence, err := expandDnsManagedZoneDnssecConfigNonExistence(original["non_existence"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedNonExistence); val.IsValid() && !isEmptyValue(val) {
transformed["nonExistence"] = transformedNonExistence
}

transformedState, err := expandDnsManagedZoneDnssecConfigState(original["state"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedState); val.IsValid() && !isEmptyValue(val) {
transformed["state"] = transformedState
}

transformedDefaultKeySpecs, err := expandDnsManagedZoneDnssecConfigDefaultKeySpecs(original["default_key_specs"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedDefaultKeySpecs); val.IsValid() && !isEmptyValue(val) {
transformed["defaultKeySpecs"] = transformedDefaultKeySpecs
}

return transformed, nil
}

func expandDnsManagedZoneDnssecConfigKind(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandDnsManagedZoneDnssecConfigNonExistence(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandDnsManagedZoneDnssecConfigState(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandDnsManagedZoneDnssecConfigDefaultKeySpecs(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedAlgorithm, err := expandDnsManagedZoneDnssecConfigDefaultKeySpecsAlgorithm(original["algorithm"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAlgorithm); val.IsValid() && !isEmptyValue(val) {
transformed["algorithm"] = transformedAlgorithm
}

transformedKeyLength, err := expandDnsManagedZoneDnssecConfigDefaultKeySpecsKeyLength(original["key_length"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKeyLength); val.IsValid() && !isEmptyValue(val) {
transformed["keyLength"] = transformedKeyLength
}

transformedKeyType, err := expandDnsManagedZoneDnssecConfigDefaultKeySpecsKeyType(original["key_type"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKeyType); val.IsValid() && !isEmptyValue(val) {
transformed["keyType"] = transformedKeyType
}

transformedKind, err := expandDnsManagedZoneDnssecConfigDefaultKeySpecsKind(original["kind"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKind); val.IsValid() && !isEmptyValue(val) {
transformed["kind"] = transformedKind
}

req = append(req, transformed)
}
return req, nil
}

func expandDnsManagedZoneDnssecConfigDefaultKeySpecsAlgorithm(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandDnsManagedZoneDnssecConfigDefaultKeySpecsKeyLength(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandDnsManagedZoneDnssecConfigDefaultKeySpecsKeyType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandDnsManagedZoneDnssecConfigDefaultKeySpecsKind(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandDnsManagedZoneName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}
Expand Down
8 changes: 8 additions & 0 deletions google/resource_dns_managed_zone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ resource "google_dns_managed_zone" "private" {
networks {
network_url = "${google_compute_network.%s.self_link}"
}
dnssec_config {
state = "on"
default_key_specs {
algorithm = "rsasha1"
key_length = "128"
key_type = "zoneSigning"
}
}
}
}

Expand Down
41 changes: 41 additions & 0 deletions website/docs/r/dns_managed_zone.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ The following arguments are supported:
(Optional)
A textual description field. Defaults to 'Managed by Terraform'.

* `dnssec_config` -
(Optional)
DNSSEC configuration Structure is documented below.

* `labels` -
(Optional)
A set of key/value label pairs to assign to this ManagedZone.
Expand All @@ -231,6 +235,43 @@ The following arguments are supported:
If it is not provided, the provider project is used.


The `dnssec_config` block supports:

* `kind` -
(Optional)
Identifies what kind of resource this is

* `non_existence` -
(Optional)
Specifies the mechanism used to provide authenticated denial-of-existence responses. Output only while state is not OFF.

* `state` -
(Optional)
Specifies whether DNSSEC is enabled, and what mode it is in

* `default_key_specs` -
(Optional)
Specifies parameters that will be used for generating initial DnsKeys for this ManagedZone. Output only while state is not OFF Structure is documented below.


The `default_key_specs` block supports:

* `algorithm` -
(Optional)
String mnemonic specifying the DNSSEC algorithm of this key

* `key_length` -
(Optional)
Length of the keys in bits

* `key_type` -
(Optional)
Specifies whether this is a key signing key (KSK) or a zone signing key (ZSK). Key signing keys have the Secure Entry Point flag set and, when active, will only be used to sign resource record sets of type DNSKEY. Zone signing keys do not have the Secure Entry Point flag set and will be used to sign all other types of resource record sets.

* `kind` -
(Optional)
Identifies what kind of resource this is

The `private_visibility_config` block supports:

* `networks` -
Expand Down