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

Added support for adaptive protection to google_compute_security_policy #4846

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
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import (
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
<% if version == 'ga' -%>
"google.golang.org/api/compute/v1"
<% else -%>
"google.golang.org/api/compute/v0.beta"
<% end -%>
)

func resourceComputeSecurityPolicy() *schema.Resource {
Expand Down Expand Up @@ -166,7 +170,43 @@ func resourceComputeSecurityPolicy() *schema.Resource {
Computed: true,
Description: `The URI of the created resource.`,
},

<% unless version == 'ga' -%>
"adaptive_protection_config": {
Type: schema.TypeList,
Optional: true,
Description: `Adaptive Protection Config of this security policy.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"layer_7_ddos_defense_config": {
Type: schema.TypeList,
Description: `Layer 7 DDoS Defense Config of this security policy`,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enable": {
Type: schema.TypeBool,
Optional: true,
Description: `If set to true, enables CAAP for L7 DDoS detection.`,
},
"rule_visibility": {
Type: schema.TypeString,
Optional: true,
Default: "STANDARD",
ValidateFunc: validation.StringInSlice([]string{"STANDARD", "PREMIUM"}, false),
Description: `Rule visibility. Supported values include: "STANDARD", "PREMIUM".`,
},
},
},
},
},
},
},
<% end -%>
},

UseJSONNumber: true,
}
}
Expand Down Expand Up @@ -208,9 +248,21 @@ func resourceComputeSecurityPolicyCreate(d *schema.ResourceData, meta interface{
securityPolicy.Rules = expandSecurityPolicyRules(v.(*schema.Set).List())
}

<% unless version == 'ga' -%>
if v, ok := d.GetOk("adaptive_protection_config"); ok{
securityPolicy.AdaptiveProtectionConfig = expandSecurityPolicyAdaptiveProtectionConfig(v.([]interface{}))
}
<% end -%>

log.Printf("[DEBUG] SecurityPolicy insert request: %#v", securityPolicy)

op, err := config.NewComputeClient(userAgent).SecurityPolicies.Insert(project, securityPolicy).Do()
<% if version == 'ga' -%>
client := config.NewComputeClient(userAgent)
<% else -%>
client := config.NewComputeBetaClient(userAgent)
<% end -%>

op, err := client.SecurityPolicies.Insert(project, securityPolicy).Do()

if err != nil {
return errwrap.Wrapf("Error creating SecurityPolicy: {{err}}", err)
Expand Down Expand Up @@ -243,7 +295,14 @@ func resourceComputeSecurityPolicyRead(d *schema.ResourceData, meta interface{})
}

sp := d.Get("name").(string)
securityPolicy, err := config.NewComputeClient(userAgent).SecurityPolicies.Get(project, sp).Do()

<% if version == 'ga' -%>
client := config.NewComputeClient(userAgent)
<% else -%>
client := config.NewComputeBetaClient(userAgent)
<% end -%>

securityPolicy, err := client.SecurityPolicies.Get(project, sp).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("SecurityPolicy %q", d.Id()))
}
Expand All @@ -266,6 +325,11 @@ func resourceComputeSecurityPolicyRead(d *schema.ResourceData, meta interface{})
if err := d.Set("self_link", ConvertSelfLinkToV1(securityPolicy.SelfLink)); err != nil {
return fmt.Errorf("Error setting self_link: %s", err)
}
<% unless version == 'ga' -%>
if err := d.Set("adaptive_protection_config", flattenSecurityPolicyAdaptiveProtectionConfig(securityPolicy.AdaptiveProtectionConfig)); err != nil {
return fmt.Errorf("Error setting adaptive_protection_config: %s", err)
}
<% end -%>

return nil
}
Expand All @@ -290,7 +354,14 @@ func resourceComputeSecurityPolicyUpdate(d *schema.ResourceData, meta interface{
Fingerprint: d.Get("fingerprint").(string),
ForceSendFields: []string{"Description"},
}
op, err := config.NewComputeClient(userAgent).SecurityPolicies.Patch(project, sp, securityPolicy).Do()

<% if version == 'ga' -%>
client := config.NewComputeClient(userAgent)
<% else -%>
client := config.NewComputeBetaClient(userAgent)
<% end -%>

op, err := client.SecurityPolicies.Patch(project, sp, securityPolicy).Do()

if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Error updating SecurityPolicy %q: {{err}}", sp), err)
Expand All @@ -317,8 +388,14 @@ func resourceComputeSecurityPolicyUpdate(d *schema.ResourceData, meta interface{
priority := int64(rule.(map[string]interface{})["priority"].(int))
nPriorities[priority] = true
if !oPriorities[priority] {
<% if version == 'ga' -%>
client := config.NewComputeClient(userAgent)
<% else -%>
client := config.NewComputeBetaClient(userAgent)
<% end -%>

// If the rule is in new and its priority does not exist in old, then add it.
op, err := config.NewComputeClient(userAgent).SecurityPolicies.AddRule(project, sp, expandSecurityPolicyRule(rule)).Do()
op, err := client.SecurityPolicies.AddRule(project, sp, expandSecurityPolicyRule(rule)).Do()

if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Error updating SecurityPolicy %q: {{err}}", sp), err)
Expand All @@ -329,8 +406,14 @@ func resourceComputeSecurityPolicyUpdate(d *schema.ResourceData, meta interface{
return err
}
} else if !oSet.Contains(rule) {
<% if version == 'ga' -%>
client := config.NewComputeClient(userAgent)
<% else -%>
client := config.NewComputeBetaClient(userAgent)
<% end -%>

// If the rule is in new, and its priority is in old, but its hash is different than the one in old, update it.
op, err := config.NewComputeClient(userAgent).SecurityPolicies.PatchRule(project, sp, expandSecurityPolicyRule(rule)).Priority(priority).Do()
op, err := client.SecurityPolicies.PatchRule(project, sp, expandSecurityPolicyRule(rule)).Priority(priority).Do()

if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Error updating SecurityPolicy %q: {{err}}", sp), err)
Expand All @@ -346,8 +429,14 @@ func resourceComputeSecurityPolicyUpdate(d *schema.ResourceData, meta interface{
for _, rule := range oSet.List() {
priority := int64(rule.(map[string]interface{})["priority"].(int))
if !nPriorities[priority] {
<% if version == 'ga' -%>
client := config.NewComputeClient(userAgent)
<% else -%>
client := config.NewComputeBetaClient(userAgent)
<% end -%>

// If the rule's priority is in old but not new, remove it.
op, err := config.NewComputeClient(userAgent).SecurityPolicies.RemoveRule(project, sp).Priority(priority).Do()
op, err := client.SecurityPolicies.RemoveRule(project, sp).Priority(priority).Do()

if err != nil {
return errwrap.Wrapf(fmt.Sprintf("Error updating SecurityPolicy %q: {{err}}", sp), err)
Expand Down Expand Up @@ -376,8 +465,14 @@ func resourceComputeSecurityPolicyDelete(d *schema.ResourceData, meta interface{
return err
}

<% if version == 'ga' -%>
client := config.NewComputeClient(userAgent)
<% else -%>
client := config.NewComputeBetaClient(userAgent)
<% end -%>

// Delete the SecurityPolicy
op, err := config.NewComputeClient(userAgent).SecurityPolicies.Delete(project, d.Get("name").(string)).Do()
op, err := client.SecurityPolicies.Delete(project, d.Get("name").(string)).Do()
if err != nil {
return errwrap.Wrapf("Error deleting SecurityPolicy: {{err}}", err)
}
Expand Down Expand Up @@ -508,6 +603,56 @@ func flattenMatchExpr(match *compute.SecurityPolicyRuleMatcher) []map[string]int
return []map[string]interface{}{data}
}

<% unless version == 'ga' -%>
func expandSecurityPolicyAdaptiveProtectionConfig(configured []interface{}) *compute.SecurityPolicyAdaptiveProtectionConfig {
if len(configured) == 0 || configured[0] == nil {
return nil
}

data := configured[0].(map[string]interface{})
return &compute.SecurityPolicyAdaptiveProtectionConfig{
Layer7DdosDefenseConfig: expandLayer7DdosDefenseConfig(data["layer_7_ddos_defense_config"].([]interface{})),
}
}

func expandLayer7DdosDefenseConfig(configured []interface{}) *compute.SecurityPolicyAdaptiveProtectionConfigLayer7DdosDefenseConfig {
if len(configured) == 0 || configured[0] == nil {
return nil
}

data := configured[0].(map[string]interface{})
return &compute.SecurityPolicyAdaptiveProtectionConfigLayer7DdosDefenseConfig{
Enable: data["enable"].(bool),
RuleVisibility: data["rule_visibility"].(string),
}
}

func flattenSecurityPolicyAdaptiveProtectionConfig(conf *compute.SecurityPolicyAdaptiveProtectionConfig) []map[string]interface{} {
if conf == nil {
return nil
}

data := map[string]interface{}{
"layer_7_ddos_defense_config": flattenLayer7DdosDefenseConfig(conf.Layer7DdosDefenseConfig),
}

return []map[string]interface{}{data}
}

func flattenLayer7DdosDefenseConfig(conf *compute.SecurityPolicyAdaptiveProtectionConfigLayer7DdosDefenseConfig) []map[string]interface{} {
if conf == nil {
return nil
}

data := map[string]interface{}{
"enable": conf.Enable,
"rule_visibility": conf.RuleVisibility,
}

return []map[string]interface{}{data}
}
<% end -%>

func resourceSecurityPolicyStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
if err := parseImportId([]string{"projects/(?P<project>[^/]+)/global/securityPolicies/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,30 @@ func TestAccComputeSecurityPolicy_update(t *testing.T) {
})
}

<% unless version == 'ga' -%>
func TestAccComputeSecurityPolicy_withAdaptiveProtection(t *testing.T) {
t.Parallel()

spName := fmt.Sprintf("tf-test-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeSecurityPolicyDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeSecurityPolicy_withAdaptiveProtection(spName),
},
{
ResourceName: "google_compute_security_policy.policy",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
<% end -%>

func testAccCheckComputeSecurityPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
config := googleProviderConfig(t)
Expand Down Expand Up @@ -313,3 +337,21 @@ resource "google_compute_security_policy" "policy" {
`, spName)
}
<% end -%>

<% unless version == 'ga' -%>
func testAccComputeSecurityPolicy_withAdaptiveProtection(spName string) string {
return fmt.Sprintf(`
resource "google_compute_security_policy" "policy" {
name = "%s"
description = "updated description"

adaptive_protection_config {
layer_7_ddos_defense_config {
enable = true
rule_visibility = "STANDARD"
}
}
}
`, spName)
}
<% end -%>
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ The following arguments are supported:
rule (rule with priority 2147483647 and match "\*"). If no rules are provided when creating a
security policy, a default rule with action "allow" will be added. Structure is documented below.

* `adaptive_protection_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Configuration for [Google Cloud Armor Adaptive Protection](https://cloud.google.com/armor/docs/adaptive-protection-overview?hl=en). Structure is documented below.

The `rule` block supports:

* `action` - (Required) Action to take when `match` matches the request. Valid values:
Expand Down Expand Up @@ -106,6 +108,16 @@ The `expr` block supports:
* `expression` - (Required) Textual representation of an expression in Common Expression Language syntax.
The application context of the containing message determines which well-known feature set of CEL is supported.

The `adaptive_protection_config` block supports:

* `layer_7_ddos_defense_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Configuration for [Google Cloud Armor Adaptive Protection Layer 7 DDoS Defense](https://cloud.google.com/armor/docs/adaptive-protection-overview?hl=en). Structure is documented below.

The `layer_7_ddos_defense_config` block supports:

* `enable` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) If set to true, enables CAAP for L7 DDoS detection.

* `rule_visibility` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Rule visibility can be one of the following: STANDARD - opaque rules. (default) PREMIUM - transparent rules.

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are
Expand Down