From 7857711c5ccdbb77e1a3cfe919f67a03949f5ad1 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Tue, 20 Mar 2018 22:08:24 -0500 Subject: [PATCH 01/22] Add SSL Policy to provider --- google/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/google/provider.go b/google/provider.go index 1100d1b1f3d..03c33df002d 100644 --- a/google/provider.go +++ b/google/provider.go @@ -130,6 +130,7 @@ func Provider() terraform.ResourceProvider { "google_compute_shared_vpc_host_project": resourceComputeSharedVpcHostProject(), "google_compute_shared_vpc_service_project": resourceComputeSharedVpcServiceProject(), "google_compute_ssl_certificate": resourceComputeSslCertificate(), + "google_compute_ssl_policy": resourceComputeSslPolicy(), "google_compute_subnetwork": resourceComputeSubnetwork(), "google_compute_target_http_proxy": resourceComputeTargetHttpProxy(), "google_compute_target_https_proxy": resourceComputeTargetHttpsProxy(), From 697f803ebb858c9820ef78f1b4113dc9614d36d1 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Wed, 21 Mar 2018 01:19:13 -0500 Subject: [PATCH 02/22] Add resource for SSL Policy --- google/resource_compute_ssl_policy.go | 281 ++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 google/resource_compute_ssl_policy.go diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go new file mode 100644 index 00000000000..6fdd3d18d50 --- /dev/null +++ b/google/resource_compute_ssl_policy.go @@ -0,0 +1,281 @@ +package google + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + computeBeta "google.golang.org/api/compute/v0.beta" +) + +func resourceComputeSslPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceComputeSslPolicyCreate, + Read: resourceComputeSslPolicyRead, + Update: resourceComputeSslPolicyUpdate, + Delete: resourceComputeSslPolicyDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(2 * time.Minute), + Update: schema.DefaultTimeout(2 * time.Minute), + Delete: schema.DefaultTimeout(2 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + + "custom_features": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "fingerprint": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "min_tls_version": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "TLS_1_0", + ValidateFunc: validation.StringInSlice([]string{"TLS_1_0", "TLS_1_1", "TLS_1_2", "TLS_1_3"}, false), + }, + + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "profile": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "COMPATIBLE", + ValidateFunc: validation.StringInSlice([]string{"COMPATIBLE", "MODERN", "RESTRICTED", "CUSTOM"}, false), + }, + + "project": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + + "self_link": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + + CustomizeDiff: func(diff *schema.ResourceDiff, v interface{}) error { + profile := diff.Get("profile") + customFeaturesCount := diff.Get("custom_features.#") + + // Validate that policy configs aren't incompatible during all phases + // CUSTOM profile demands non-zero custom_features, and other profiles (i.e., not CUSTOM) demand zero custom_features + if diff.HasChange("profile") || diff.HasChange("custom_features") { + if profile.(string) == "CUSTOM" { + if customFeaturesCount.(int) == 0 { + return fmt.Errorf("Error in SSL Policy %s: the profile is set to %s but no custom_features are set.", diff.Get("name"), profile.(string)) + } + } else { + if customFeaturesCount != 0 { + return fmt.Errorf("Error in SSL Policy %s: the profile is set to %s but using custom_features requires the profile to be CUSTOM.", diff.Get("name"), profile.(string)) + } + } + return nil + } + return nil + }, + } +} + +func resourceComputeSslPolicyCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + sslPolicy := &computeBeta.SslPolicy{ + Name: d.Get("name").(string), + Description: d.Get("description").(string), + Profile: d.Get("profile").(string), + MinTlsVersion: d.Get("min_tls_version").(string), + CustomFeatures: convCustomFeaturesListToSlice(d.Get("custom_features").([]interface{})), + } + + op, err := config.clientComputeBeta.SslPolicies.Insert(project, sslPolicy).Do() + if err != nil { + return fmt.Errorf("Error creating SSL Policy: %s", err) + } + + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutDelete).Minutes()), "Creating SSL Policy") + if err != nil { + return err + } + + d.SetId(sslPolicy.Name) + + return resourceComputeSslPolicyRead(d, meta) +} + +func resourceComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + name := d.Get("name").(string) + + // handle resource inputs when only the resource id (name) is given + if name == "" { + name = d.Id() + } + + sslPolicy, err := config.clientComputeBeta.SslPolicies.Get(project, name).Do() + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("SSL Policy %q", name)) + } + + d.Set("name", sslPolicy.Name) + d.Set("description", sslPolicy.Description) + d.Set("min_tls_version", sslPolicy.MinTlsVersion) + d.Set("profile", sslPolicy.Profile) + d.Set("fingerprint", sslPolicy.Fingerprint) + d.Set("project", project) + d.Set("self_link", ConvertSelfLinkToV1(sslPolicy.SelfLink)) + + if sslPolicy.CustomFeatures != nil { + d.Set("custom_features", convertStringArrToInterface(sslPolicy.CustomFeatures)) + } + + d.SetId(sslPolicy.Name) + + return nil +} + +func resourceComputeSslPolicyUpdate(d *schema.ResourceData, meta interface{}) error { + + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + name := d.Get("name").(string) + + d.Partial(true) + + if d.HasChange("min_tls_version") { + sslPolicy := &computeBeta.SslPolicy{ + MinTlsVersion: d.Get("min_tls_version").(string), + Fingerprint: d.Get("fingerprint").(string), + } + + op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() + if err != nil { + return fmt.Errorf("Error updating SSL Policy: %s", err) + } + + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "Updating SSL Policy") + if err != nil { + return err + } + + d.SetPartial("min_tls_version") + } + + if d.HasChange("profile") { + sslPolicy := &computeBeta.SslPolicy{ + Profile: d.Get("profile").(string), + Fingerprint: d.Get("fingerprint").(string), + } + + op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() + if err != nil { + return fmt.Errorf("Error updating SSL Policy: %s", err) + } + + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "Updating SSL Policy") + if err != nil { + return err + } + + d.SetPartial("profile") + } + + if d.HasChange("custom_features") { + sslPolicy := &computeBeta.SslPolicy{ + CustomFeatures: convCustomFeaturesListToSlice(d.Get("custom_features").([]interface{})), + Fingerprint: d.Get("fingerprint").(string), + } + + op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() + if err != nil { + return fmt.Errorf("Error updating SSL Policy: %s", err) + } + + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "Updating SSL Policy") + if err != nil { + return err + } + + d.SetPartial("custom_features") + } + + d.Partial(false) + + return resourceComputeSslPolicyRead(d, meta) +} + +func resourceComputeSslPolicyDelete(d *schema.ResourceData, meta interface{}) error { + + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + name := d.Get("name").(string) + + op, err := config.clientComputeBeta.SslPolicies.Delete(project, name).Do() + if err != nil { + return fmt.Errorf("Error deleting SSL Policy: %s", err) + } + + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutDelete).Minutes()), "Deleting Subnetwork") + if err != nil { + return err + } + + d.SetId("") + + return nil +} + +func convCustomFeaturesListToSlice(customFeaturesList []interface{}) []string { + customFeaturesSlice := make([]string, 0, len(customFeaturesList)) + + for _, v := range customFeaturesList { + customFeaturesSlice = append(customFeaturesSlice, v.(string)) + } + + return customFeaturesSlice +} From 73640170315d12be488df5a5a29fda6cd268192a Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Wed, 21 Mar 2018 20:40:02 -0500 Subject: [PATCH 03/22] Add documentation for SSL Policy resource --- .../docs/r/compute_ssl_policy.html.markdown | 82 +++++++++++++++++++ website/google.erb | 4 + 2 files changed, 86 insertions(+) create mode 100644 website/docs/r/compute_ssl_policy.html.markdown diff --git a/website/docs/r/compute_ssl_policy.html.markdown b/website/docs/r/compute_ssl_policy.html.markdown new file mode 100644 index 00000000000..eef5108f094 --- /dev/null +++ b/website/docs/r/compute_ssl_policy.html.markdown @@ -0,0 +1,82 @@ +--- +layout: "google" +page_title: "Google: google_compute_ssl_policy" +sidebar_current: "docs-google-compute-ssl-policy" +description: |- + Manages an SSL Policy within GCE, for use with Target HTTPS and Target SSL Proxies. +--- + +# google\_compute\_ssl\_policies + +Manages an SSL Policy within GCE, for use with Target HTTPS and Target SSL Proxies. For more information see +[the official documentation](https://cloud.google.com/compute/docs/load-balancing/ssl-policies) +and +[API](https://cloud.google.com/compute/docs/reference/rest/beta/sslPolicies). + +## Example Usage + +```hcl +resource "google_compute_ssl_policy" "prod-ssl-policy" { + name = "production-ssl-policy" + profile = "MODERN" +} + +resource "google_compute_ssl_policy" "nonprod-ssl-policy" { + name = "nonprod-ssl-policy" + profile = "MODERN" + min_tls_version = "TLS_1_2" +} + +resource "google_compute_ssl_policy" "custom-ssl-policy" { + name = "custom-ssl-policy" + min_tls_version = "TLS_1_2" + profile = "CUSTOM" + custom_features = ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) A unique name for the resource, required by GCE. + Changing this forces a new resource to be created. + +- - - + +* `description` - (Optional) Description of this subnetwork. Changing this forces a new resource to be created. + +* `project` - (Optional) The ID of the project in which the resource belongs. If it + is not provided, the provider project is used. + +* `min_tls_version` - (Optional) The minimum TLS version to support. Must be one of `TLS_1_0`, `TLS_1_1`, `TLS_1_2`, or `TLS_1_3`. + Default is `TLS_1_0`. + +* `profile` - (Optional) The Google-curated SSL profile to use. Must be one of `COMPATIBLE`, `MODERN`, + `RESTRICTED`, or `CUSTOM`. See the + [official documentation](https://cloud.google.com/compute/docs/load-balancing/ssl-policies#profilefeaturesupport) + for information on what cipher suites each profile provides. If `CUSTOM` is used, the `custom_features` attribute + **must be set**. Default is `COMPATIBLE`. + +* `custom_features` - (Required with `CUSTOM` profile) The specific encryption ciphers to use. See the + [official documentation](https://cloud.google.com/compute/docs/load-balancing/ssl-policies#profilefeaturesupport) + for which ciphers are available to use. **Note**: this argument *must* be present when using the `CUSTOM` profile. + This argument *must not* be present when using any other profile. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are +exported: + +* `fingerprint` - Fingerprint of this resource. + +* `self_link` - The URI of the created resource. + +## Import + +SSL Policies can be imported using the GCP canonical `name` of the Policy. For example, an SSL Policy named `production-ssl-policy` + would be imported by running: + +```bash +$ terraform import google_compute_ssl_policy.my-policy production-ssl-policy +``` diff --git a/website/google.erb b/website/google.erb index f5807d93187..c20e1d51623 100644 --- a/website/google.erb +++ b/website/google.erb @@ -346,6 +346,10 @@ google_compute_ssl_certificate + > + google_compute_ssl_policy + + > google_compute_subnetwork From e68b281282f8cb063ed19ade06e9d04b0ef083e9 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Wed, 21 Mar 2018 18:50:29 -0500 Subject: [PATCH 04/22] Add SSL Policy data source --- .../data_source_google_compute_ssl_policy.go | 87 +++++++++++++++++++ google/provider.go | 1 + 2 files changed, 88 insertions(+) create mode 100644 google/data_source_google_compute_ssl_policy.go diff --git a/google/data_source_google_compute_ssl_policy.go b/google/data_source_google_compute_ssl_policy.go new file mode 100644 index 00000000000..28c2e1d666a --- /dev/null +++ b/google/data_source_google_compute_ssl_policy.go @@ -0,0 +1,87 @@ +package google + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceGoogleComputeSslPolicy() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleComputeSslPolicyRead, + + Schema: map[string]*schema.Schema{ + + "custom_features": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "description": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "fingerprint": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "min_tls_version": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "profile": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "project": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "self_link": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceGoogleComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + name := d.Get("name").(string) + + sslPolicy, err := config.clientComputeBeta.SslPolicies.Get(project, name).Do() + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("SSL Policy %q", name)) + } + + d.Set("name", sslPolicy.Name) + d.Set("description", sslPolicy.Description) + d.Set("min_tls_version", sslPolicy.MinTlsVersion) + d.Set("profile", sslPolicy.Profile) + d.Set("fingerprint", sslPolicy.Fingerprint) + d.Set("project", project) + d.Set("self_link", ConvertSelfLinkToV1(sslPolicy.SelfLink)) + + if sslPolicy.CustomFeatures != nil { + d.Set("custom_features", convertStringArrToInterface(sslPolicy.CustomFeatures)) + } + d.SetId(sslPolicy.Name) + return nil +} diff --git a/google/provider.go b/google/provider.go index 03c33df002d..9db7c7bb44e 100644 --- a/google/provider.go +++ b/google/provider.go @@ -78,6 +78,7 @@ func Provider() terraform.ResourceProvider { "google_compute_region_instance_group": dataSourceGoogleComputeRegionInstanceGroup(), "google_compute_vpn_gateway": dataSourceGoogleComputeVpnGateway(), "google_compute_forwarding_rule": dataSourceGoogleComputeForwardingRule(), + "google_compute_ssl_policy": dataSourceGoogleComputeSslPolicy(), "google_container_cluster": dataSourceGoogleContainerCluster(), "google_container_engine_versions": dataSourceGoogleContainerEngineVersions(), "google_container_registry_repository": dataSourceGoogleContainerRepo(), From df7dc62833c3304f15a76d6bbdb746d324517f43 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Wed, 21 Mar 2018 21:04:53 -0500 Subject: [PATCH 05/22] Add SSL Policy datasource docs --- ...atasource_compute_ssl_policy.html.markdown | 50 +++++++++++++++++++ website/google.erb | 3 ++ 2 files changed, 53 insertions(+) create mode 100644 website/docs/d/datasource_compute_ssl_policy.html.markdown diff --git a/website/docs/d/datasource_compute_ssl_policy.html.markdown b/website/docs/d/datasource_compute_ssl_policy.html.markdown new file mode 100644 index 00000000000..46fd1d51a69 --- /dev/null +++ b/website/docs/d/datasource_compute_ssl_policy.html.markdown @@ -0,0 +1,50 @@ + +--- +layout: "google" +page_title: "Google: google_compute_ssl_policy" +sidebar_current: "docs-google-datasource-compute-ssl-policy" +description: |- + Gets an SSL Policy within GCE, for use with Target HTTPS and Target SSL Proxies. +--- + +# google\_compute\_ssl\_policies + +Gets an SSL Policy within GCE from its name, for use with Target HTTPS and Target SSL Proxies. + For more information see [the official documentation](https://cloud.google.com/compute/docs/load-balancing/ssl-policies). + +## Example Usage + +```tf +data "google_compute_ssl_policy" "my-ssl-policy" { + name = "production-ssl-policy" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the SSL Policy. + +- - - + +* `project` - (Optional) The ID of the project in which the resource belongs. If it + is not provided, the provider project is used. + +## Attributes Reference + +In addition to the arguments listed above, the following attributes are exported: + +* `description` - Description of this SSL Policy. + +* `min_tls_version` - The minimum supported TLS version of this policy. + +* `profile` - The Google-curated or custom profile used by this policy. + +* `custom_features` - If the `profile` is `CUSTOM`, these are the custom encryption + ciphers supported by the profile. If the `profile` is *not* `CUSTOM`, this + attribute will be nil. + +* `fingerprint` - Fingerprint of this resource. + +* `self_link` - The URI of the created resource. \ No newline at end of file diff --git a/website/google.erb b/website/google.erb index c20e1d51623..d86bd3a1401 100644 --- a/website/google.erb +++ b/website/google.erb @@ -44,6 +44,9 @@ > google_project + > + google_compute_ssl_policy + > google_compute_subnetwork From 1de363e54a042c6d062a75269eca30f3a9fd7f8d Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Thu, 22 Mar 2018 11:13:43 -0500 Subject: [PATCH 06/22] Add test for SSL Policy datasource --- ...a_source_google_compute_ssl_policy_test.go | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 google/data_source_google_compute_ssl_policy_test.go diff --git a/google/data_source_google_compute_ssl_policy_test.go b/google/data_source_google_compute_ssl_policy_test.go new file mode 100644 index 00000000000..8b7462dba3e --- /dev/null +++ b/google/data_source_google_compute_ssl_policy_test.go @@ -0,0 +1,83 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccDataSourceGoogleSslPolicy(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccDataSourceGoogleSslPolicy(), + Check: resource.ComposeTestCheckFunc( + testAccDataSourceGoogleSslPolicyCheck("data.google_compute_ssl_policy.ssl_policy", "google_compute_ssl_policy.foobar"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleSslPolicyCheck(data_source_name string, resource_name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + ds, ok := s.RootModule().Resources[data_source_name] + if !ok { + return fmt.Errorf("root module has no resource called %s", data_source_name) + } + + rs, ok := s.RootModule().Resources[resource_name] + if !ok { + return fmt.Errorf("can't find %s in state", resource_name) + } + + ds_attr := ds.Primary.Attributes + rs_attr := rs.Primary.Attributes + + ssl_policy_attrs_to_test := []string{ + "id", + "self_link", + "name", + "description", + "min_tls_version", + "profile", + "custom_features", + } + + for _, attr_to_check := range ssl_policy_attrs_to_test { + if ds_attr[attr_to_check] != rs_attr[attr_to_check] { + return fmt.Errorf( + "%s is %s; want %s", + attr_to_check, + ds_attr[attr_to_check], + rs_attr[attr_to_check], + ) + } + } + + return nil + } +} + +func testAccDataSourceGoogleSslPolicy() string { + return fmt.Sprintf(` + +resource "google_compute_ssl_policy" "foobar" { + name = "%s" + description = "my-description" + min_tls_version = "TLS_1_2" + profile = "MODERN" +} + +data "google_compute_ssl_policy" "ssl_policy" { + name = "${google_compute_ssl_policy.foobar.name}" +} +`, acctest.RandomWithPrefix("test-ssl-policy")) +} From a6ebbdcc697f8617e574a94dc4dcb6d8c478bee4 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Wed, 21 Mar 2018 18:51:38 -0500 Subject: [PATCH 07/22] Add tests for SSL Policy resource --- google/resource_compute_ssl_policy_test.go | 308 +++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 google/resource_compute_ssl_policy_test.go diff --git a/google/resource_compute_ssl_policy_test.go b/google/resource_compute_ssl_policy_test.go new file mode 100644 index 00000000000..a34632a691f --- /dev/null +++ b/google/resource_compute_ssl_policy_test.go @@ -0,0 +1,308 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + computeBeta "google.golang.org/api/compute/v0.beta" +) + +func TestAccComputeSslPolicy_basic(t *testing.T) { + t.Parallel() + + var sslPolicy computeBeta.SslPolicy + sslPolicyName := fmt.Sprintf("test-ssl-policy-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSslPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSslPolicyBasic(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.basic", &sslPolicy), + // test attribute default values + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.basic", "profile", "COMPATIBLE"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.basic", "min_tls_version", "TLS_1_0"), + ), + }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.basic", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeSslPolicy_profile(t *testing.T) { + t.Parallel() + + var sslPolicy computeBeta.SslPolicy + sslPolicyName := fmt.Sprintf("test-ssl-policy-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSslPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSslPolicyProfile(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.profile", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.profile", "profile", "MODERN"), + ), + }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.profile", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeSslPolicy_update(t *testing.T) { + t.Parallel() + + var sslPolicy computeBeta.SslPolicy + sslPolicyName := fmt.Sprintf("test-ssl-policy-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSslPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSslUpdate1(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.update", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "profile", "MODERN"), + //resource.TestCheckResourceAttr( + //"google_compute_ssl_policy.update", "min_tls_version", "TLS_1_0"), + ), + }, + resource.TestStep{ + Config: testAccComputeSslUpdate2(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.update", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "profile", "RESTRICTED"), + //resource.TestCheckResourceAttr( + //"google_compute_ssl_policy.update", "min_tls_version", "TLS_1_2"), + ), + }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.update", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeSslPolicy_tls_version(t *testing.T) { + t.Parallel() + + var sslPolicy computeBeta.SslPolicy + sslPolicyName := fmt.Sprintf("test-ssl-policy-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSslPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSslPolicyTlsVersion(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.tlsversion", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.tlsversion", "min_tls_version", "TLS_1_2"), + ), + }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.tlsversion", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeSslPolicy_custom(t *testing.T) { + t.Parallel() + + var sslPolicy computeBeta.SslPolicy + sslPolicyName := fmt.Sprintf("test-ssl-policy-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSslPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSslPolicyCustom(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.custom", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.custom", "min_tls_version", "TLS_1_2"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.custom", "profile", "CUSTOM"), + testAccCheckComputeSslPolicyCustomFeatures(&sslPolicy, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"), + ), + }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.custom", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckComputeSslPolicyExists(n string, sslPolicy *computeBeta.SslPolicy) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + + project, err := getTestProject(rs.Primary, config) + if err != nil { + return err + } + + name := rs.Primary.Attributes["name"] + + found, err := config.clientComputeBeta.SslPolicies.Get( + project, name).Do() + if err != nil { + return fmt.Errorf("Error Reading SSL Policy %s: %s", name, err) + } + + if found.Name != rs.Primary.ID { + return fmt.Errorf("SSL Policy not found") + } + + *sslPolicy = *found + + return nil + } +} + +func testAccCheckComputeSslPolicyDestroy(s *terraform.State) error { + config := testAccProvider.Meta().(*Config) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_ssl_policy" { + continue + } + + _, err := config.clientComputeBeta.SslPolicies.Get( + config.Project, rs.Primary.ID).Do() + if err == nil { + return fmt.Errorf("SSL Policy still exists") + } + } + + return nil +} + +func testAccCheckComputeSslPolicyCustomFeatures(sslPolicy *computeBeta.SslPolicy, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if sslPolicy.CustomFeatures == nil { + return fmt.Errorf("no custom_features") + } + + for _, k := range sslPolicy.CustomFeatures { + if k == n { + return nil + } + } + + return fmt.Errorf("custom_features not found: %s", n) + } +} + +func testAccComputeSslPolicyBasic(resourceName string) string { + return fmt.Sprintf(` +resource "google_compute_ssl_policy" "basic" { + name = "%s" + description = "Generated by TF provider acceptance test" +} +`, resourceName) +} + +func testAccComputeSslPolicyProfile(resourceName string) string { + return fmt.Sprintf(` +resource "google_compute_ssl_policy" "profile" { + name = "%s" + description = "Generated by TF provider acceptance test" + profile = "MODERN" +} +`, resourceName) +} + +func testAccComputeSslUpdate1(resourceName string) string { + return fmt.Sprintf(` +resource "google_compute_ssl_policy" "update" { + name = "%s" + description = "Generated by TF provider acceptance test" +# min_tls_version = "TLS_1_0" + profile = "MODERN" +} +`, resourceName) +} + +func testAccComputeSslUpdate2(resourceName string) string { + return fmt.Sprintf(` +resource "google_compute_ssl_policy" "update" { + name = "%s" + description = "Generated by TF provider acceptance test" +# min_tls_version = "TLS_1_2" + profile = "RESTRICTED" +} +`, resourceName) +} + +func testAccComputeSslPolicyTlsVersion(resourceName string) string { + return fmt.Sprintf(` +resource "google_compute_ssl_policy" "tlsversion" { + name = "%s" + description = "Generated by TF provider acceptance test" + min_tls_version = "TLS_1_2" +} +`, resourceName) +} + +func testAccComputeSslPolicyCustom(resourceName string) string { + return fmt.Sprintf(` +resource "google_compute_ssl_policy" "custom" { + name = "%s" + description = "Generated by TF provider acceptance test" + min_tls_version = "TLS_1_2" + profile = "CUSTOM" + custom_features = ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"] +} +`, resourceName) +} From 825efb9c88f807c1573182272d1c19a8ae60e433 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Fri, 23 Mar 2018 13:06:57 -0500 Subject: [PATCH 08/22] Update SSL Policy datasource docs --- website/docs/d/datasource_compute_ssl_policy.html.markdown | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/website/docs/d/datasource_compute_ssl_policy.html.markdown b/website/docs/d/datasource_compute_ssl_policy.html.markdown index 46fd1d51a69..6a3aa1ca013 100644 --- a/website/docs/d/datasource_compute_ssl_policy.html.markdown +++ b/website/docs/d/datasource_compute_ssl_policy.html.markdown @@ -1,4 +1,3 @@ - --- layout: "google" page_title: "Google: google_compute_ssl_policy" @@ -16,7 +15,7 @@ Gets an SSL Policy within GCE from its name, for use with Target HTTPS and Targe ```tf data "google_compute_ssl_policy" "my-ssl-policy" { - name = "production-ssl-policy" + name = "production-ssl-policy" } ``` @@ -43,7 +42,7 @@ In addition to the arguments listed above, the following attributes are exported * `custom_features` - If the `profile` is `CUSTOM`, these are the custom encryption ciphers supported by the profile. If the `profile` is *not* `CUSTOM`, this - attribute will be nil. + attribute will be empty. * `fingerprint` - Fingerprint of this resource. From 1b0c44cd82bf38b206dc82fddb36853bbcf0db4e Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Fri, 23 Mar 2018 13:24:02 -0500 Subject: [PATCH 09/22] Make full update for SSL Policy resource --- google/resource_compute_ssl_policy.go | 80 ++++++--------------------- 1 file changed, 16 insertions(+), 64 deletions(-) diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go index 6fdd3d18d50..d043c565955 100644 --- a/google/resource_compute_ssl_policy.go +++ b/google/resource_compute_ssl_policy.go @@ -122,13 +122,14 @@ func resourceComputeSslPolicyCreate(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Error creating SSL Policy: %s", err) } - err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutDelete).Minutes()), "Creating SSL Policy") + d.SetId(sslPolicy.Name) + + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutCreate).Minutes()), "Creating SSL Policy") if err != nil { + d.SetId("") // if insert fails, remove from state return err } - d.SetId(sslPolicy.Name) - return resourceComputeSslPolicyRead(d, meta) } @@ -140,12 +141,7 @@ func resourceComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) erro return err } - name := d.Get("name").(string) - - // handle resource inputs when only the resource id (name) is given - if name == "" { - name = d.Id() - } + name := d.Id() sslPolicy, err := config.clientComputeBeta.SslPolicies.Get(project, name).Do() if err != nil { @@ -180,67 +176,23 @@ func resourceComputeSslPolicyUpdate(d *schema.ResourceData, meta interface{}) er name := d.Get("name").(string) - d.Partial(true) - - if d.HasChange("min_tls_version") { - sslPolicy := &computeBeta.SslPolicy{ - MinTlsVersion: d.Get("min_tls_version").(string), - Fingerprint: d.Get("fingerprint").(string), - } - - op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() - if err != nil { - return fmt.Errorf("Error updating SSL Policy: %s", err) - } - - err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "Updating SSL Policy") - if err != nil { - return err - } - - d.SetPartial("min_tls_version") + sslPolicy := &computeBeta.SslPolicy{ + Fingerprint: d.Get("fingerprint").(string), + Profile: d.Get("profile").(string), + MinTlsVersion: d.Get("min_tls_version").(string), + CustomFeatures: convCustomFeaturesListToSlice(d.Get("custom_features").([]interface{})), } - if d.HasChange("profile") { - sslPolicy := &computeBeta.SslPolicy{ - Profile: d.Get("profile").(string), - Fingerprint: d.Get("fingerprint").(string), - } - - op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() - if err != nil { - return fmt.Errorf("Error updating SSL Policy: %s", err) - } - - err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "Updating SSL Policy") - if err != nil { - return err - } - - d.SetPartial("profile") + op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() + if err != nil { + return fmt.Errorf("Error updating SSL Policy: %s", err) } - if d.HasChange("custom_features") { - sslPolicy := &computeBeta.SslPolicy{ - CustomFeatures: convCustomFeaturesListToSlice(d.Get("custom_features").([]interface{})), - Fingerprint: d.Get("fingerprint").(string), - } - - op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() - if err != nil { - return fmt.Errorf("Error updating SSL Policy: %s", err) - } - - err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "Updating SSL Policy") - if err != nil { - return err - } - - d.SetPartial("custom_features") + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutCreate).Minutes()), "Updating SSL Policy") + if err != nil { + return err } - d.Partial(false) - return resourceComputeSslPolicyRead(d, meta) } From efe226c0f30d467d672da6aa5b48cc7df820e0ad Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Fri, 23 Mar 2018 13:26:51 -0500 Subject: [PATCH 10/22] SSL Policy resource test multi-attrib update --- google/resource_compute_ssl_policy_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/google/resource_compute_ssl_policy_test.go b/google/resource_compute_ssl_policy_test.go index a34632a691f..34744dc8503 100644 --- a/google/resource_compute_ssl_policy_test.go +++ b/google/resource_compute_ssl_policy_test.go @@ -89,8 +89,8 @@ func TestAccComputeSslPolicy_update(t *testing.T) { "google_compute_ssl_policy.update", &sslPolicy), resource.TestCheckResourceAttr( "google_compute_ssl_policy.update", "profile", "MODERN"), - //resource.TestCheckResourceAttr( - //"google_compute_ssl_policy.update", "min_tls_version", "TLS_1_0"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_0"), ), }, resource.TestStep{ @@ -100,8 +100,8 @@ func TestAccComputeSslPolicy_update(t *testing.T) { "google_compute_ssl_policy.update", &sslPolicy), resource.TestCheckResourceAttr( "google_compute_ssl_policy.update", "profile", "RESTRICTED"), - //resource.TestCheckResourceAttr( - //"google_compute_ssl_policy.update", "min_tls_version", "TLS_1_2"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_2"), ), }, resource.TestStep{ @@ -268,7 +268,7 @@ func testAccComputeSslUpdate1(resourceName string) string { resource "google_compute_ssl_policy" "update" { name = "%s" description = "Generated by TF provider acceptance test" -# min_tls_version = "TLS_1_0" + min_tls_version = "TLS_1_0" profile = "MODERN" } `, resourceName) @@ -279,7 +279,7 @@ func testAccComputeSslUpdate2(resourceName string) string { resource "google_compute_ssl_policy" "update" { name = "%s" description = "Generated by TF provider acceptance test" -# min_tls_version = "TLS_1_2" + min_tls_version = "TLS_1_2" profile = "RESTRICTED" } `, resourceName) From 9a50864cef7dbb2be32d59fa617a7a56f5c45141 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Fri, 23 Mar 2018 14:38:00 -0500 Subject: [PATCH 11/22] Clean up SSL Policy datasource --- .../data_source_google_compute_ssl_policy.go | 84 +++---------------- 1 file changed, 13 insertions(+), 71 deletions(-) diff --git a/google/data_source_google_compute_ssl_policy.go b/google/data_source_google_compute_ssl_policy.go index 28c2e1d666a..81e75ed313e 100644 --- a/google/data_source_google_compute_ssl_policy.go +++ b/google/data_source_google_compute_ssl_policy.go @@ -1,87 +1,29 @@ package google import ( - "fmt" "github.com/hashicorp/terraform/helper/schema" ) func dataSourceGoogleComputeSslPolicy() *schema.Resource { - return &schema.Resource{ - Read: dataSourceGoogleComputeSslPolicyRead, - - Schema: map[string]*schema.Schema{ - - "custom_features": &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - - "description": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - - "fingerprint": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - - "min_tls_version": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - - "name": &schema.Schema{ - Type: schema.TypeString, - Required: true, - }, + // Generate datasource schema from resource + dsSchema := datasourceSchemaFromResourceSchema(resourceComputeSslPolicy().Schema) - "profile": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, + // Set 'Required' schema elements + addRequiredFieldsToSchema(dsSchema, "name") - "project": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Computed: true, - }, + // Set 'Optional' schema elements + addOptionalFieldsToSchema(dsSchema, "custom_features", "description", "min_tls_version", "profile", "project") - "self_link": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - }, + return &schema.Resource{ + Read: datasourceComputeSslPolicyRead, + Schema: dsSchema, } } -func dataSourceGoogleComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - project, err := getProject(d, config) - if err != nil { - return err - } +func datasourceComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) error { + policyName := d.Get("name").(string) - name := d.Get("name").(string) + d.SetId(policyName) - sslPolicy, err := config.clientComputeBeta.SslPolicies.Get(project, name).Do() - if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("SSL Policy %q", name)) - } - - d.Set("name", sslPolicy.Name) - d.Set("description", sslPolicy.Description) - d.Set("min_tls_version", sslPolicy.MinTlsVersion) - d.Set("profile", sslPolicy.Profile) - d.Set("fingerprint", sslPolicy.Fingerprint) - d.Set("project", project) - d.Set("self_link", ConvertSelfLinkToV1(sslPolicy.SelfLink)) - - if sslPolicy.CustomFeatures != nil { - d.Set("custom_features", convertStringArrToInterface(sslPolicy.CustomFeatures)) - } - d.SetId(sslPolicy.Name) - return nil + return resourceComputeSslPolicyRead(d, meta) } From aaf6a864e1603c44bca35aecd82fd247e18920a1 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Fri, 23 Mar 2018 14:38:39 -0500 Subject: [PATCH 12/22] Set-ify custom_features in SSL Policy resource --- google/resource_compute_ssl_policy.go | 39 +++++++++++---------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go index d043c565955..c5eaffb01b1 100644 --- a/google/resource_compute_ssl_policy.go +++ b/google/resource_compute_ssl_policy.go @@ -28,10 +28,17 @@ func resourceComputeSslPolicy() *schema.Resource { Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "custom_features": &schema.Schema{ - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, }, "description": &schema.Schema{ @@ -40,11 +47,6 @@ func resourceComputeSslPolicy() *schema.Resource { ForceNew: true, }, - "fingerprint": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - "min_tls_version": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -52,12 +54,6 @@ func resourceComputeSslPolicy() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"TLS_1_0", "TLS_1_1", "TLS_1_2", "TLS_1_3"}, false), }, - "name": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "profile": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -72,6 +68,11 @@ func resourceComputeSslPolicy() *schema.Resource { ForceNew: true, }, + "fingerprint": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "self_link": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -114,7 +115,7 @@ func resourceComputeSslPolicyCreate(d *schema.ResourceData, meta interface{}) er Description: d.Get("description").(string), Profile: d.Get("profile").(string), MinTlsVersion: d.Get("min_tls_version").(string), - CustomFeatures: convCustomFeaturesListToSlice(d.Get("custom_features").([]interface{})), + CustomFeatures: convertStringSet(d.Get("custom_features").(*schema.Set)), } op, err := config.clientComputeBeta.SslPolicies.Insert(project, sslPolicy).Do() @@ -180,7 +181,7 @@ func resourceComputeSslPolicyUpdate(d *schema.ResourceData, meta interface{}) er Fingerprint: d.Get("fingerprint").(string), Profile: d.Get("profile").(string), MinTlsVersion: d.Get("min_tls_version").(string), - CustomFeatures: convCustomFeaturesListToSlice(d.Get("custom_features").([]interface{})), + CustomFeatures: convertStringSet(d.Get("custom_features").(*schema.Set)), } op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() @@ -221,13 +222,3 @@ func resourceComputeSslPolicyDelete(d *schema.ResourceData, meta interface{}) er return nil } - -func convCustomFeaturesListToSlice(customFeaturesList []interface{}) []string { - customFeaturesSlice := make([]string, 0, len(customFeaturesList)) - - for _, v := range customFeaturesList { - customFeaturesSlice = append(customFeaturesSlice, v.(string)) - } - - return customFeaturesSlice -} From 2ed3f538b2e799dfa5260a91e21404e00488edea Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Fri, 23 Mar 2018 14:49:54 -0500 Subject: [PATCH 13/22] Document description ForceNew rationale --- google/resource_compute_ssl_policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go index c5eaffb01b1..128651bb444 100644 --- a/google/resource_compute_ssl_policy.go +++ b/google/resource_compute_ssl_policy.go @@ -44,7 +44,7 @@ func resourceComputeSslPolicy() *schema.Resource { "description": &schema.Schema{ Type: schema.TypeString, Optional: true, - ForceNew: true, + ForceNew: true, // currently, the beta patch API call does not allow updating the description }, "min_tls_version": &schema.Schema{ From e0d6ab3568f34ae770634978f715e673dd9c07ab Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 10:25:47 -0500 Subject: [PATCH 14/22] Remove refs to TLS_1_3 --- google/resource_compute_ssl_policy.go | 10 ++++++---- website/docs/r/compute_ssl_policy.html.markdown | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go index 128651bb444..086e5e26b5c 100644 --- a/google/resource_compute_ssl_policy.go +++ b/google/resource_compute_ssl_policy.go @@ -48,10 +48,12 @@ func resourceComputeSslPolicy() *schema.Resource { }, "min_tls_version": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Default: "TLS_1_0", - ValidateFunc: validation.StringInSlice([]string{"TLS_1_0", "TLS_1_1", "TLS_1_2", "TLS_1_3"}, false), + Type: schema.TypeString, + Optional: true, + Default: "TLS_1_0", + // Although compute-gen.go says that TLS_1_3 is a valid value, the API currently (26 Mar 2018) + // responds with an HTTP 200 but doesn't actually create/update the policy. + ValidateFunc: validation.StringInSlice([]string{"TLS_1_0", "TLS_1_1", "TLS_1_2"}, false), }, "profile": &schema.Schema{ diff --git a/website/docs/r/compute_ssl_policy.html.markdown b/website/docs/r/compute_ssl_policy.html.markdown index eef5108f094..d2c91956011 100644 --- a/website/docs/r/compute_ssl_policy.html.markdown +++ b/website/docs/r/compute_ssl_policy.html.markdown @@ -49,7 +49,7 @@ The following arguments are supported: * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. -* `min_tls_version` - (Optional) The minimum TLS version to support. Must be one of `TLS_1_0`, `TLS_1_1`, `TLS_1_2`, or `TLS_1_3`. +* `min_tls_version` - (Optional) The minimum TLS version to support. Must be one of `TLS_1_0`, `TLS_1_1`, or `TLS_1_2`. Default is `TLS_1_0`. * `profile` - (Optional) The Google-curated SSL profile to use. Must be one of `COMPATIBLE`, `MODERN`, From 59072b5da435d1de06e548e9f4e7ed2b9e8bb09d Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 14:51:16 -0500 Subject: [PATCH 15/22] Update docs: plural -> singular --- website/docs/d/datasource_compute_ssl_policy.html.markdown | 2 +- website/docs/r/compute_ssl_policy.html.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/d/datasource_compute_ssl_policy.html.markdown b/website/docs/d/datasource_compute_ssl_policy.html.markdown index 6a3aa1ca013..2d8a9786b93 100644 --- a/website/docs/d/datasource_compute_ssl_policy.html.markdown +++ b/website/docs/d/datasource_compute_ssl_policy.html.markdown @@ -6,7 +6,7 @@ description: |- Gets an SSL Policy within GCE, for use with Target HTTPS and Target SSL Proxies. --- -# google\_compute\_ssl\_policies +# google\_compute\_ssl\_policy Gets an SSL Policy within GCE from its name, for use with Target HTTPS and Target SSL Proxies. For more information see [the official documentation](https://cloud.google.com/compute/docs/load-balancing/ssl-policies). diff --git a/website/docs/r/compute_ssl_policy.html.markdown b/website/docs/r/compute_ssl_policy.html.markdown index d2c91956011..e14c94cf876 100644 --- a/website/docs/r/compute_ssl_policy.html.markdown +++ b/website/docs/r/compute_ssl_policy.html.markdown @@ -6,7 +6,7 @@ description: |- Manages an SSL Policy within GCE, for use with Target HTTPS and Target SSL Proxies. --- -# google\_compute\_ssl\_policies +# google\_compute\_ssl\_policy Manages an SSL Policy within GCE, for use with Target HTTPS and Target SSL Proxies. For more information see [the official documentation](https://cloud.google.com/compute/docs/load-balancing/ssl-policies) From 4b2513b1822964df73fc23198979e0969de0592e Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 15:20:51 -0500 Subject: [PATCH 16/22] Remove extraneous attrs from datasource --- google/data_source_google_compute_ssl_policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google/data_source_google_compute_ssl_policy.go b/google/data_source_google_compute_ssl_policy.go index 81e75ed313e..020c852c2c9 100644 --- a/google/data_source_google_compute_ssl_policy.go +++ b/google/data_source_google_compute_ssl_policy.go @@ -12,7 +12,7 @@ func dataSourceGoogleComputeSslPolicy() *schema.Resource { addRequiredFieldsToSchema(dsSchema, "name") // Set 'Optional' schema elements - addOptionalFieldsToSchema(dsSchema, "custom_features", "description", "min_tls_version", "profile", "project") + addOptionalFieldsToSchema(dsSchema, "project") return &schema.Resource{ Read: datasourceComputeSslPolicyRead, From 650553aa82c7ab094248c7b98fdf8be898569dd6 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 15:22:31 -0500 Subject: [PATCH 17/22] Fix update logic for custom_features and add enabled_features --- google/resource_compute_ssl_policy.go | 36 ++++++++++++++++++++------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go index 086e5e26b5c..9b150a486d9 100644 --- a/google/resource_compute_ssl_policy.go +++ b/google/resource_compute_ssl_policy.go @@ -70,6 +70,13 @@ func resourceComputeSslPolicy() *schema.Resource { ForceNew: true, }, + "enabled_features": &schema.Schema{ + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "fingerprint": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -158,10 +165,8 @@ func resourceComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) erro d.Set("fingerprint", sslPolicy.Fingerprint) d.Set("project", project) d.Set("self_link", ConvertSelfLinkToV1(sslPolicy.SelfLink)) - - if sslPolicy.CustomFeatures != nil { - d.Set("custom_features", convertStringArrToInterface(sslPolicy.CustomFeatures)) - } + d.Set("enabled_features", convertStringArrToInterface(sslPolicy.EnabledFeatures)) + d.Set("custom_features", convertStringArrToInterface(sslPolicy.CustomFeatures)) d.SetId(sslPolicy.Name) @@ -180,10 +185,23 @@ func resourceComputeSslPolicyUpdate(d *schema.ResourceData, meta interface{}) er name := d.Get("name").(string) sslPolicy := &computeBeta.SslPolicy{ - Fingerprint: d.Get("fingerprint").(string), - Profile: d.Get("profile").(string), - MinTlsVersion: d.Get("min_tls_version").(string), - CustomFeatures: convertStringSet(d.Get("custom_features").(*schema.Set)), + Fingerprint: d.Get("fingerprint").(string), + } + + if v, ok := d.GetOk("profile"); ok { + sslPolicy.Profile = v.(string) + } + + if v, ok := d.GetOk("min_tls_version"); ok { + sslPolicy.MinTlsVersion = v.(string) + } + + if v, ok := d.Get("custom_features").(*schema.Set); ok { + if v.Len() > 0 { + sslPolicy.CustomFeatures = convertStringSet(v) + } else { + sslPolicy.NullFields = append(sslPolicy.NullFields, "CustomFeatures") + } } op, err := config.clientComputeBeta.SslPolicies.Patch(project, name, sslPolicy).Do() @@ -191,7 +209,7 @@ func resourceComputeSslPolicyUpdate(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Error updating SSL Policy: %s", err) } - err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutCreate).Minutes()), "Updating SSL Policy") + err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutUpdate).Minutes()), "Updating SSL Policy") if err != nil { return err } From d7fb0b78070fd514f247b423a62478fa77f51809 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 15:27:25 -0500 Subject: [PATCH 18/22] Update docs to include enabled_features --- website/docs/d/datasource_compute_ssl_policy.html.markdown | 2 ++ website/docs/r/compute_ssl_policy.html.markdown | 2 ++ 2 files changed, 4 insertions(+) diff --git a/website/docs/d/datasource_compute_ssl_policy.html.markdown b/website/docs/d/datasource_compute_ssl_policy.html.markdown index 2d8a9786b93..d7c7e5a2467 100644 --- a/website/docs/d/datasource_compute_ssl_policy.html.markdown +++ b/website/docs/d/datasource_compute_ssl_policy.html.markdown @@ -34,6 +34,8 @@ The following arguments are supported: In addition to the arguments listed above, the following attributes are exported: +* `enabled_features` - The set of enabled encryption ciphers as a result of the policy config + * `description` - Description of this SSL Policy. * `min_tls_version` - The minimum supported TLS version of this policy. diff --git a/website/docs/r/compute_ssl_policy.html.markdown b/website/docs/r/compute_ssl_policy.html.markdown index e14c94cf876..9fcb53ff014 100644 --- a/website/docs/r/compute_ssl_policy.html.markdown +++ b/website/docs/r/compute_ssl_policy.html.markdown @@ -68,6 +68,8 @@ The following arguments are supported: In addition to the arguments listed above, the following computed attributes are exported: +* `enabled_features` - The set of enabled encryption ciphers as a result of the policy config + * `fingerprint` - Fingerprint of this resource. * `self_link` - The URI of the created resource. From 98d06c097f49ab8dbfc42fcf4bfa3d2ddeb73838 Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 15:49:05 -0500 Subject: [PATCH 19/22] Add test for updating to/from custom_features --- google/resource_compute_ssl_policy_test.go | 115 +++++++++++++++++---- 1 file changed, 97 insertions(+), 18 deletions(-) diff --git a/google/resource_compute_ssl_policy_test.go b/google/resource_compute_ssl_policy_test.go index 34744dc8503..4d305229f52 100644 --- a/google/resource_compute_ssl_policy_test.go +++ b/google/resource_compute_ssl_policy_test.go @@ -162,7 +162,6 @@ func TestAccComputeSslPolicy_custom(t *testing.T) { "google_compute_ssl_policy.custom", "min_tls_version", "TLS_1_2"), resource.TestCheckResourceAttr( "google_compute_ssl_policy.custom", "profile", "CUSTOM"), - testAccCheckComputeSslPolicyCustomFeatures(&sslPolicy, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"), ), }, resource.TestStep{ @@ -174,6 +173,90 @@ func TestAccComputeSslPolicy_custom(t *testing.T) { }) } +func TestAccComputeSslPolicy_update_to_custom(t *testing.T) { + t.Parallel() + + var sslPolicy computeBeta.SslPolicy + sslPolicyName := fmt.Sprintf("test-ssl-policy-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSslPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSslUpdate1(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.update", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "profile", "MODERN"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_0"), + ), + }, + resource.TestStep{ + Config: testAccComputeSslUpdate3(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.update", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "profile", "CUSTOM"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_1"), + ), + }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.update", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeSslPolicy_update_from_custom(t *testing.T) { + t.Parallel() + + var sslPolicy computeBeta.SslPolicy + sslPolicyName := fmt.Sprintf("test-ssl-policy-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSslPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSslUpdate3(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.update", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "profile", "CUSTOM"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_1"), + ), + }, + resource.TestStep{ + Config: testAccComputeSslUpdate1(sslPolicyName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSslPolicyExists( + "google_compute_ssl_policy.update", &sslPolicy), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "profile", "MODERN"), + resource.TestCheckResourceAttr( + "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_0"), + ), + }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.update", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckComputeSslPolicyExists(n string, sslPolicy *computeBeta.SslPolicy) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -228,22 +311,6 @@ func testAccCheckComputeSslPolicyDestroy(s *terraform.State) error { return nil } -func testAccCheckComputeSslPolicyCustomFeatures(sslPolicy *computeBeta.SslPolicy, n string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if sslPolicy.CustomFeatures == nil { - return fmt.Errorf("no custom_features") - } - - for _, k := range sslPolicy.CustomFeatures { - if k == n { - return nil - } - } - - return fmt.Errorf("custom_features not found: %s", n) - } -} - func testAccComputeSslPolicyBasic(resourceName string) string { return fmt.Sprintf(` resource "google_compute_ssl_policy" "basic" { @@ -285,6 +352,18 @@ resource "google_compute_ssl_policy" "update" { `, resourceName) } +func testAccComputeSslUpdate3(resourceName string) string { + return fmt.Sprintf(` +resource "google_compute_ssl_policy" "update" { + name = "%s" + description = "Generated by TF provider acceptance test" + min_tls_version = "TLS_1_1" + profile = "CUSTOM" + custom_features = ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"] +} +`, resourceName) +} + func testAccComputeSslPolicyTlsVersion(resourceName string) string { return fmt.Sprintf(` resource "google_compute_ssl_policy" "tlsversion" { @@ -302,7 +381,7 @@ resource "google_compute_ssl_policy" "custom" { description = "Generated by TF provider acceptance test" min_tls_version = "TLS_1_2" profile = "CUSTOM" - custom_features = ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"] + custom_features = ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"] } `, resourceName) } From 3a9f2c3152f572475da35ec90810b952d03a9ffc Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 17:31:11 -0500 Subject: [PATCH 20/22] Add TLS 1.3 bug link --- google/resource_compute_ssl_policy.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go index 9b150a486d9..30dce3ec5b7 100644 --- a/google/resource_compute_ssl_policy.go +++ b/google/resource_compute_ssl_policy.go @@ -52,7 +52,8 @@ func resourceComputeSslPolicy() *schema.Resource { Optional: true, Default: "TLS_1_0", // Although compute-gen.go says that TLS_1_3 is a valid value, the API currently (26 Mar 2018) - // responds with an HTTP 200 but doesn't actually create/update the policy. + // responds with an HTTP 200 but doesn't actually create/update the policy. Open bug for this: + // https://issuetracker.google.com/issues/76433946 ValidateFunc: validation.StringInSlice([]string{"TLS_1_0", "TLS_1_1", "TLS_1_2"}, false), }, From bd84ef4a075c2623efd4f9b12929f7db7269b93d Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 18:02:34 -0500 Subject: [PATCH 21/22] Add import between multi-step test configs --- google/resource_compute_ssl_policy_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/google/resource_compute_ssl_policy_test.go b/google/resource_compute_ssl_policy_test.go index 4d305229f52..28461ffcf56 100644 --- a/google/resource_compute_ssl_policy_test.go +++ b/google/resource_compute_ssl_policy_test.go @@ -93,6 +93,11 @@ func TestAccComputeSslPolicy_update(t *testing.T) { "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_0"), ), }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.update", + ImportState: true, + ImportStateVerify: true, + }, resource.TestStep{ Config: testAccComputeSslUpdate2(sslPolicyName), Check: resource.ComposeTestCheckFunc( @@ -195,6 +200,11 @@ func TestAccComputeSslPolicy_update_to_custom(t *testing.T) { "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_0"), ), }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.update", + ImportState: true, + ImportStateVerify: true, + }, resource.TestStep{ Config: testAccComputeSslUpdate3(sslPolicyName), Check: resource.ComposeTestCheckFunc( @@ -237,6 +247,11 @@ func TestAccComputeSslPolicy_update_from_custom(t *testing.T) { "google_compute_ssl_policy.update", "min_tls_version", "TLS_1_1"), ), }, + resource.TestStep{ + ResourceName: "google_compute_ssl_policy.update", + ImportState: true, + ImportStateVerify: true, + }, resource.TestStep{ Config: testAccComputeSslUpdate1(sslPolicyName), Check: resource.ComposeTestCheckFunc( From 5c9ff2ef3f6341e798172476d16496187089b00e Mon Sep 17 00:00:00 2001 From: Nick Jacques Date: Mon, 26 Mar 2018 18:02:57 -0500 Subject: [PATCH 22/22] Move Profile and minTlsVersion back into sslPolicy struct --- google/resource_compute_ssl_policy.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/google/resource_compute_ssl_policy.go b/google/resource_compute_ssl_policy.go index 30dce3ec5b7..a39f6e53987 100644 --- a/google/resource_compute_ssl_policy.go +++ b/google/resource_compute_ssl_policy.go @@ -186,15 +186,9 @@ func resourceComputeSslPolicyUpdate(d *schema.ResourceData, meta interface{}) er name := d.Get("name").(string) sslPolicy := &computeBeta.SslPolicy{ - Fingerprint: d.Get("fingerprint").(string), - } - - if v, ok := d.GetOk("profile"); ok { - sslPolicy.Profile = v.(string) - } - - if v, ok := d.GetOk("min_tls_version"); ok { - sslPolicy.MinTlsVersion = v.(string) + Fingerprint: d.Get("fingerprint").(string), + Profile: d.Get("profile").(string), + MinTlsVersion: d.Get("min_tls_version").(string), } if v, ok := d.Get("custom_features").(*schema.Set); ok {