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

New resource/datasource: SSL Policy #1247

Merged
merged 22 commits into from
Mar 26, 2018
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7857711
Add SSL Policy to provider
nickjacques Mar 21, 2018
697f803
Add resource for SSL Policy
nickjacques Mar 21, 2018
7364017
Add documentation for SSL Policy resource
nickjacques Mar 22, 2018
e68b281
Add SSL Policy data source
nickjacques Mar 21, 2018
df7dc62
Add SSL Policy datasource docs
nickjacques Mar 22, 2018
1de363e
Add test for SSL Policy datasource
nickjacques Mar 22, 2018
a6ebbdc
Add tests for SSL Policy resource
nickjacques Mar 21, 2018
825efb9
Update SSL Policy datasource docs
nickjacques Mar 23, 2018
1b0c44c
Make full update for SSL Policy resource
nickjacques Mar 23, 2018
efe226c
SSL Policy resource test multi-attrib update
nickjacques Mar 23, 2018
9a50864
Clean up SSL Policy datasource
nickjacques Mar 23, 2018
aaf6a86
Set-ify custom_features in SSL Policy resource
nickjacques Mar 23, 2018
2ed3f53
Document description ForceNew rationale
nickjacques Mar 23, 2018
e0d6ab3
Remove refs to TLS_1_3
nickjacques Mar 26, 2018
59072b5
Update docs: plural -> singular
nickjacques Mar 26, 2018
4b2513b
Remove extraneous attrs from datasource
nickjacques Mar 26, 2018
650553a
Fix update logic for custom_features and add enabled_features
nickjacques Mar 26, 2018
d7fb0b7
Update docs to include enabled_features
nickjacques Mar 26, 2018
98d06c0
Add test for updating to/from custom_features
nickjacques Mar 26, 2018
3a9f2c3
Add TLS 1.3 bug link
nickjacques Mar 26, 2018
bd84ef4
Add import between multi-step test configs
nickjacques Mar 26, 2018
5c9ff2e
Move Profile and minTlsVersion back into sslPolicy struct
nickjacques Mar 26, 2018
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
29 changes: 29 additions & 0 deletions google/data_source_google_compute_ssl_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package google

import (
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceGoogleComputeSslPolicy() *schema.Resource {
// Generate datasource schema from resource
dsSchema := datasourceSchemaFromResourceSchema(resourceComputeSslPolicy().Schema)

// Set 'Required' schema elements
addRequiredFieldsToSchema(dsSchema, "name")

// Set 'Optional' schema elements
addOptionalFieldsToSchema(dsSchema, "project")

return &schema.Resource{
Read: datasourceComputeSslPolicyRead,
Schema: dsSchema,
}
}

func datasourceComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) error {
policyName := d.Get("name").(string)

d.SetId(policyName)

return resourceComputeSslPolicyRead(d, meta)
}
83 changes: 83 additions & 0 deletions google/data_source_google_compute_ssl_policy_test.go
Original file line number Diff line number Diff line change
@@ -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"))
}
2 changes: 2 additions & 0 deletions google/provider.go
Original file line number Diff line number Diff line change
@@ -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(),
@@ -130,6 +131,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(),
239 changes: 239 additions & 0 deletions google/resource_compute_ssl_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
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{

"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"custom_features": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true, // currently, the beta patch API call does not allow updating the description
},

"min_tls_version": &schema.Schema{
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. Open bug for this:
// https://issuetracker.google.com/issues/76433946
ValidateFunc: validation.StringInSlice([]string{"TLS_1_0", "TLS_1_1", "TLS_1_2"}, false),
},

"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,
},

"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,
},

"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: convertStringSet(d.Get("custom_features").(*schema.Set)),
}

op, err := config.clientComputeBeta.SslPolicies.Insert(project, sslPolicy).Do()
if err != nil {
return fmt.Errorf("Error creating SSL Policy: %s", err)
}

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
}

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.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))
d.Set("enabled_features", convertStringArrToInterface(sslPolicy.EnabledFeatures))
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)

sslPolicy := &computeBeta.SslPolicy{
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 {
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()
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
}

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
}
402 changes: 402 additions & 0 deletions google/resource_compute_ssl_policy_test.go

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions website/docs/d/datasource_compute_ssl_policy.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
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\_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).

## 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:

* `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.

* `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 empty.

* `fingerprint` - Fingerprint of this resource.

* `self_link` - The URI of the created resource.
84 changes: 84 additions & 0 deletions website/docs/r/compute_ssl_policy.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
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\_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)
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`, or `TLS_1_2`.
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:

* `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.

## 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
```
7 changes: 7 additions & 0 deletions website/google.erb
Original file line number Diff line number Diff line change
@@ -44,6 +44,9 @@
<li<%= sidebar_current("docs-google-datasource-project") %>>
<a href="/docs/providers/google/d/google_project.html">google_project</a>
</li>
<li<%= sidebar_current("docs-google-datasource-compute-ssl-policy") %>>
<a href="/docs/providers/google/d/datasource_compute_ssl_policy.html">google_compute_ssl_policy</a>
</li>
<li<%= sidebar_current("docs-google-datasource-compute-subnetwork") %>>
<a href="/docs/providers/google/d/datasource_compute_subnetwork.html">google_compute_subnetwork</a>
</li>
@@ -346,6 +349,10 @@
<a href="/docs/providers/google/r/compute_ssl_certificate.html">google_compute_ssl_certificate</a>
</li>

<li<%= sidebar_current("docs-google-compute-ssl-policy") %>>
<a href="/docs/providers/google/r/compute_ssl_policy.html">google_compute_ssl_policy</a>
</li>

<li<%= sidebar_current("docs-google-compute-subnetwork") %>>
<a href="/docs/providers/google/r/compute_subnetwork.html">google_compute_subnetwork</a>
</li>