From f6bc823675f8eefe8b255031d8d7ac12b3487e8a Mon Sep 17 00:00:00 2001 From: mihhalj Date: Fri, 13 Sep 2024 23:19:07 +0200 Subject: [PATCH] Add new compute-firewall-policy-with-rules resource (#11525) --- .../compute/FirewallPolicyWithRules.yaml | 452 ++++++++++++++++++ ..._compute_firewall_policy_with_rules.go.erb | 51 ++ ..._compute_firewall_policy_with_rules.go.erb | 16 + ..._compute_firewall_policy_with_rules.go.erb | 3 + ...ute_firewall_policy_with_rules_full.tf.erb | 92 ++++ ..._compute_firewall_policy_with_rules.go.erb | 56 +++ ..._compute_firewall_policy_with_rules.go.erb | 10 + ..._compute_firewall_policy_with_rules.go.erb | 10 + ..._compute_firewall_policy_with_rules.go.erb | 11 + ...ute_firewall_policy_with_rules_test.go.erb | 222 +++++++++ 10 files changed, 923 insertions(+) create mode 100644 mmv1/products/compute/FirewallPolicyWithRules.yaml create mode 100644 mmv1/templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.erb create mode 100644 mmv1/templates/terraform/decoders/resource_compute_firewall_policy_with_rules.go.erb create mode 100644 mmv1/templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.erb create mode 100644 mmv1/templates/terraform/examples/compute_firewall_policy_with_rules_full.tf.erb create mode 100644 mmv1/templates/terraform/post_create/resource_compute_firewall_policy_with_rules.go.erb create mode 100644 mmv1/templates/terraform/post_delete/resource_compute_firewall_policy_with_rules.go.erb create mode 100644 mmv1/templates/terraform/post_update/resource_compute_firewall_policy_with_rules.go.erb create mode 100644 mmv1/templates/terraform/update_encoder/resource_compute_firewall_policy_with_rules.go.erb create mode 100644 mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_with_rules_test.go.erb diff --git a/mmv1/products/compute/FirewallPolicyWithRules.yaml b/mmv1/products/compute/FirewallPolicyWithRules.yaml new file mode 100644 index 000000000000..b13d1fac6e62 --- /dev/null +++ b/mmv1/products/compute/FirewallPolicyWithRules.yaml @@ -0,0 +1,452 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the License); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: FirewallPolicyWithRules +min_version: beta +base_url: 'locations/global/firewallPolicies?parentId={{parent}}' +self_link: 'locations/global/firewallPolicies/{{policy_id}}' +create_url: 'locations/global/firewallPolicies?parentId={{parent}}' +update_verb: :PATCH +description: | + The Compute FirewallPolicy with rules resource. It declaratively manges all + rules in the firewall policy. +id_format: 'locations/global/firewallPolicies/{{policy_id}}' +import_format: ['locations/global/firewallPolicies/{{policy_id}}'] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'compute_firewall_policy_with_rules_full' + primary_resource_id: 'firewall-policy-with-rules' + vars: + policy_name: 'tf-fw-org-policy-with-rules' + address_group_name: 'tf-address-group' + security_profile_group_name: 'tf-security-profile-group' + security_profile_name: 'tf-security-profile' + test_env_vars: + org_id: :ORG_ID +custom_code: !ruby/object:Provider::Terraform::CustomCode + constants: templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.erb + encoder: templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.erb + update_encoder: templates/terraform/update_encoder/resource_compute_firewall_policy_with_rules.go.erb + decoder: templates/terraform/decoders/resource_compute_firewall_policy_with_rules.go.erb + post_create: templates/terraform/post_create/resource_compute_firewall_policy_with_rules.go.erb + post_update: templates/terraform/post_update/resource_compute_firewall_policy_with_rules.go.erb + post_delete: templates/terraform/post_delete/resource_compute_firewall_policy_with_rules.go.erb +parameters: + - !ruby/object:Api::Type::String + name: parent + description: | + The parent of this FirewallPolicy in the Cloud Resource Hierarchy. + Format: organizations/{organization_id} or folders/{folder_id} + required: true + immutable: true +properties: + - !ruby/object:Api::Type::String + name: creationTimestamp + description: Creation timestamp in RFC3339 text format. + output: true + - !ruby/object:Api::Type::String + name: shortName + description: A textual name of the security policy. + immutable: true + required: true + - !ruby/object:Api::Type::String + name: policyId + description: The unique identifier for the resource. This identifier is defined by the server. + output: true + api_name: id + - !ruby/object:Api::Type::String + name: description + description: An optional description of this resource. + - !ruby/object:Api::Type::Array + name: 'rule' + api_name: 'rules' + description: A list of firewall policy rules. + required: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'description' + description: | + A description of the rule. + - !ruby/object:Api::Type::String + name: 'ruleName' + description: | + An optional name for the rule. This field is not a unique identifier + and can be updated. + - !ruby/object:Api::Type::Integer + name: 'priority' + description: | + An integer indicating the priority of a rule in the list. The priority must be a value + between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the + highest priority and 2147483647 is the lowest priority. + required: true + - !ruby/object:Api::Type::NestedObject + name: 'match' + description: + A match condition that incoming traffic is evaluated against. If it + evaluates to true, the corresponding 'action' is enforced. + required: true + properties: + - !ruby/object:Api::Type::Array + name: 'srcIpRanges' + description: | + Source IP address range in CIDR format. Required for + INGRESS rules. + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + name: 'destIpRanges' + description: | + Destination IP address range in CIDR format. Required for + EGRESS rules. + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcAddressGroups' + description: | + Address groups which should be matched against the traffic source. + Maximum number of source address groups is 10. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destAddressGroups' + description: | + Address groups which should be matched against the traffic destination. + Maximum number of destination address groups is 10. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcFqdns' + description: | + Fully Qualified Domain Name (FQDN) which should be matched against + traffic source. Maximum number of source fqdn allowed is 100. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destFqdns' + description: | + Fully Qualified Domain Name (FQDN) which should be matched against + traffic destination. Maximum number of destination fqdn allowed is 100. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcRegionCodes' + description: | + Region codes whose IP addresses will be used to match for source + of traffic. Should be specified as 2 letter country code defined as per + ISO 3166 alpha-2 country codes. ex."US" + Maximum number of source region codes allowed is 5000. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destRegionCodes' + description: | + Region codes whose IP addresses will be used to match for destination + of traffic. Should be specified as 2 letter country code defined as per + ISO 3166 alpha-2 country codes. ex."US" + Maximum number of destination region codes allowed is 5000. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcThreatIntelligences' + description: | + Names of Network Threat Intelligence lists. + The IPs in these lists will be matched against traffic source. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destThreatIntelligences' + description: | + Names of Network Threat Intelligence lists. + The IPs in these lists will be matched against traffic destination. + - !ruby/object:Api::Type::Array + name: 'layer4Config' + api_name: 'layer4Configs' + description: | + Pairs of IP protocols and ports that the rule should match. + required: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'ipProtocol' + description: | + The IP protocol to which this rule applies. The protocol + type is required when creating a firewall rule. + This value can either be one of the following well + known protocol strings (tcp, udp, icmp, esp, ah, ipip, sctp), + or the IP protocol number. + required: true + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'ports' + description: | + An optional list of ports to which this rule applies. This field + is only applicable for UDP or TCP protocol. Each entry must be + either an integer or a range. If not specified, this rule + applies to connections through any port. + Example inputs include: ["22"], ["80","443"], and + ["12345-12349"]. + - !ruby/object:Api::Type::String + name: 'action' + description: | + The Action to perform when the client connection triggers the rule. Can currently be either + "allow", "deny", "apply_security_profile_group" or "goto_next". + required: true + - !ruby/object:Api::Type::Enum + name: 'direction' + description: | + The direction in which this rule applies. If unspecified an INGRESS rule is created. + values: + - :INGRESS + - :EGRESS + - !ruby/object:Api::Type::Boolean + name: 'enableLogging' + description: | + Denotes whether to enable logging for a particular rule. + If logging is enabled, logs will be exported to the + configured export destination in Stackdriver. + send_empty_value: true + - !ruby/object:Api::Type::Array + name: 'targetServiceAccounts' + description: | + A list of service accounts indicating the sets of + instances that are applied with this rule. + item_type: Api::Type::String + - !ruby/object:Api::Type::String + name: 'securityProfileGroup' + description: | + A fully-qualified URL of a SecurityProfile resource instance. + Example: + https://networksecurity.googleapis.com/v1/projects/{project}/locations/{location}/securityProfileGroups/my-security-profile-group + Must be specified if action is 'apply_security_profile_group'. + - !ruby/object:Api::Type::Boolean + name: 'tlsInspect' + description: | + Boolean flag indicating if the traffic should be TLS decrypted. + It can be set only if action = 'apply_security_profile_group' and cannot be set for other actions. + - !ruby/object:Api::Type::Array + name: 'targetResources' + item_type: Api::Type::String + description: | + A list of network resource URLs to which this rule applies. + This field allows you to control which network's VMs get + this rule. If this field is left blank, all VMs + within the organization will receive the rule. + - !ruby/object:Api::Type::Boolean + name: 'disabled' + description: | + Denotes whether the firewall policy rule is disabled. When set to true, + the firewall policy rule is not enforced and traffic behaves as if it did + not exist. If this is unspecified, the firewall policy rule will be + enabled. + - !ruby/object:Api::Type::Array + name: 'predefinedRules' + description: A list of pre-define firewall policy rules. + output: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'description' + output: true + description: | + A description of the rule. + - !ruby/object:Api::Type::String + name: 'ruleName' + output: true + description: | + An optional name for the rule. This field is not a unique identifier + and can be updated. + - !ruby/object:Api::Type::Integer + name: 'priority' + output: true + description: | + An integer indicating the priority of a rule in the list. The priority must be a value + between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the + highest priority and 2147483647 is the lowest priority. + - !ruby/object:Api::Type::NestedObject + name: 'match' + output: true + description: + A match condition that incoming traffic is evaluated against. If it + evaluates to true, the corresponding 'action' is enforced. + properties: + - !ruby/object:Api::Type::Array + name: 'srcIpRanges' + output: true + description: | + Source IP address range in CIDR format. Required for + INGRESS rules. + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + name: 'destIpRanges' + output: true + description: | + Destination IP address range in CIDR format. Required for + EGRESS rules. + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcAddressGroups' + output: true + description: | + Address groups which should be matched against the traffic source. + Maximum number of source address groups is 10. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destAddressGroups' + output: true + description: | + Address groups which should be matched against the traffic destination. + Maximum number of destination address groups is 10. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcFqdns' + output: true + description: | + Fully Qualified Domain Name (FQDN) which should be matched against + traffic source. Maximum number of source fqdn allowed is 100. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destFqdns' + output: true + description: | + Fully Qualified Domain Name (FQDN) which should be matched against + traffic destination. Maximum number of destination fqdn allowed is 100. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcRegionCodes' + output: true + description: | + Region codes whose IP addresses will be used to match for source + of traffic. Should be specified as 2 letter country code defined as per + ISO 3166 alpha-2 country codes. ex."US" + Maximum number of source region codes allowed is 5000. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destRegionCodes' + output: true + description: | + Region codes whose IP addresses will be used to match for destination + of traffic. Should be specified as 2 letter country code defined as per + ISO 3166 alpha-2 country codes. ex."US" + Maximum number of destination region codes allowed is 5000. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'srcThreatIntelligences' + output: true + description: | + Names of Network Threat Intelligence lists. + The IPs in these lists will be matched against traffic source. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'destThreatIntelligences' + output: true + description: | + Names of Network Threat Intelligence lists. + The IPs in these lists will be matched against traffic destination. + - !ruby/object:Api::Type::Array + name: 'layer4Config' + api_name: 'layer4Configs' + output: true + description: | + Pairs of IP protocols and ports that the rule should match. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'ipProtocol' + output: true + description: | + The IP protocol to which this rule applies. The protocol + type is required when creating a firewall rule. + This value can either be one of the following well + known protocol strings (tcp, udp, icmp, esp, ah, ipip, sctp), + or the IP protocol number. + - !ruby/object:Api::Type::Array + item_type: Api::Type::String + name: 'ports' + output: true + description: | + An optional list of ports to which this rule applies. This field + is only applicable for UDP or TCP protocol. Each entry must be + either an integer or a range. If not specified, this rule + applies to connections through any port. + Example inputs include: ["22"], ["80","443"], and + ["12345-12349"]. + - !ruby/object:Api::Type::String + name: 'action' + output: true + description: | + The Action to perform when the client connection triggers the rule. Can currently be either + "allow", "deny", "apply_security_profile_group" or "goto_next". + - !ruby/object:Api::Type::Enum + name: 'direction' + output: true + description: | + The direction in which this rule applies. If unspecified an INGRESS rule is created. + values: + - :INGRESS + - :EGRESS + - !ruby/object:Api::Type::Boolean + name: 'enableLogging' + output: true + description: | + Denotes whether to enable logging for a particular rule. + If logging is enabled, logs will be exported to the + configured export destination in Stackdriver. + - !ruby/object:Api::Type::Array + name: 'targetServiceAccounts' + output: true + description: | + A list of service accounts indicating the sets of + instances that are applied with this rule. + item_type: Api::Type::String + - !ruby/object:Api::Type::String + name: 'securityProfileGroup' + output: true + description: | + A fully-qualified URL of a SecurityProfile resource instance. + Example: + https://networksecurity.googleapis.com/v1/projects/{project}/locations/{location}/securityProfileGroups/my-security-profile-group + Must be specified if action is 'apply_security_profile_group'. + - !ruby/object:Api::Type::Boolean + name: 'tlsInspect' + output: true + description: | + Boolean flag indicating if the traffic should be TLS decrypted. + It can be set only if action = 'apply_security_profile_group' and cannot be set for other actions. + - !ruby/object:Api::Type::Array + name: 'targetResources' + output: true + item_type: Api::Type::String + description: | + A list of network resource URLs to which this rule applies. + This field allows you to control which network's VMs get + this rule. If this field is left blank, all VMs + within the organization will receive the rule. + - !ruby/object:Api::Type::Boolean + name: 'disabled' + output: true + description: | + Denotes whether the firewall policy rule is disabled. When set to true, + the firewall policy rule is not enforced and traffic behaves as if it did + not exist. If this is unspecified, the firewall policy rule will be + enabled. + - !ruby/object:Api::Type::Fingerprint + name: fingerprint + description: Fingerprint of the resource. This field is used internally during updates of this resource. + output: true + - !ruby/object:Api::Type::String + name: selfLink + description: Server-defined URL for the resource. + output: true + - !ruby/object:Api::Type::String + name: selfLinkWithId + description: Server-defined URL for this resource with the resource id. + output: true + - !ruby/object:Api::Type::Integer + name: ruleTupleCount + description: Total count of all firewall policy rule tuples. A firewall policy can not exceed a set number of tuples. + output: true diff --git a/mmv1/templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.erb b/mmv1/templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.erb new file mode 100644 index 000000000000..43f7fd30e2c3 --- /dev/null +++ b/mmv1/templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.erb @@ -0,0 +1,51 @@ +func firewallPolicyWithRulesConvertPriorityToInt(v interface {}) (int64, error) { + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal, nil + } + } + + if intVal, ok := v.(int64); ok { + return intVal, nil + } + + if floatVal, ok := v.(float64); ok { + intVal := int64(floatVal) + return intVal, nil + } + + return 0, fmt.Errorf("Incorrect rule priority: %s. Priority must be a number", v) +} + +func firewallPolicyWithRulesIsPredefinedRule(rule map[string]interface{}) (bool, error) { + // Priorities from 2147483548 to 2147483647 are reserved and cannot be modified by the user. + const ReservedPriorityStart = 2147483548 + + priority := rule["priority"] + priorityInt, err := firewallPolicyWithRulesConvertPriorityToInt(priority) + + if err != nil { + return false, err + } + + return priorityInt >= ReservedPriorityStart, nil +} + +func firewallPolicyWithRulesSplitPredefinedRules(allRules []interface{}) ([]interface{}, []interface{}, error) { + predefinedRules := make([]interface{}, 0) + rules := make([]interface{}, 0) + for _, rule := range allRules { + isPredefined, err := firewallPolicyWithRulesIsPredefinedRule(rule.(map[string]interface{})) + if err != nil { + return nil, nil, err + } + + if isPredefined { + predefinedRules = append(predefinedRules, rule) + } else { + rules = append(rules, rule) + } + } + return rules, predefinedRules, nil +} + diff --git a/mmv1/templates/terraform/decoders/resource_compute_firewall_policy_with_rules.go.erb b/mmv1/templates/terraform/decoders/resource_compute_firewall_policy_with_rules.go.erb new file mode 100644 index 000000000000..6d09c0cac422 --- /dev/null +++ b/mmv1/templates/terraform/decoders/resource_compute_firewall_policy_with_rules.go.erb @@ -0,0 +1,16 @@ +rules, predefinedRules, err := firewallPolicyWithRulesSplitPredefinedRules(res["rules"].([]interface{})) + +if err != nil { + return nil, fmt.Errorf("Error occurred while splitting pre-defined rules: %s", err) +} + +res["rules"] = rules +res["predefinedRules"] = predefinedRules + +config := meta.(*transport_tpg.Config) + +if err := d.Set("predefined_rules", flattenComputeFirewallPolicyWithRulesPredefinedRules(predefinedRules, d, config)); err != nil { + return nil, fmt.Errorf("Error occurred while setting pre-defined rules: %s", err) +} + +return res, nil diff --git a/mmv1/templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.erb b/mmv1/templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.erb new file mode 100644 index 000000000000..939b22280811 --- /dev/null +++ b/mmv1/templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.erb @@ -0,0 +1,3 @@ +delete(obj, "rules") // Rules are not supported in the create API +return obj, nil + diff --git a/mmv1/templates/terraform/examples/compute_firewall_policy_with_rules_full.tf.erb b/mmv1/templates/terraform/examples/compute_firewall_policy_with_rules_full.tf.erb new file mode 100644 index 000000000000..c6212aab8cbb --- /dev/null +++ b/mmv1/templates/terraform/examples/compute_firewall_policy_with_rules_full.tf.erb @@ -0,0 +1,92 @@ +data "google_project" "project" { + provider = google-beta +} + +resource "google_compute_firewall_policy_with_rules" "<%= ctx[:primary_resource_id] %>" { + short_name = "<%= ctx[:vars]['policy_name'] %>" + description = "Terraform test" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + provider = google-beta + + rule { + description = "tcp rule" + priority = 1000 + enable_logging = true + action = "allow" + direction = "EGRESS" + match { + layer4_config { + ip_protocol = "tcp" + ports = [8080, 7070] + } + dest_ip_ranges = ["11.100.0.1/32"] + dest_fqdns = ["www.yyy.com", "www.zzz.com"] + dest_region_codes = ["HK", "IN"] + dest_threat_intelligences = ["iplist-search-engines-crawlers", "iplist-tor-exit-nodes"] + dest_address_groups = [google_network_security_address_group.address_group_1.id] + } + target_resources = ["https://www.googleapis.com/compute/beta/projects/${data.google_project.project.name}/global/networks/default"] + } + rule { + description = "udp rule" + priority = 2000 + enable_logging = false + action = "deny" + direction = "INGRESS" + match { + layer4_config { + ip_protocol = "udp" + } + src_ip_ranges = ["0.0.0.0/0"] + src_fqdns = ["www.abc.com", "www.def.com"] + src_region_codes = ["US", "CA"] + src_threat_intelligences = ["iplist-known-malicious-ips", "iplist-public-clouds"] + src_address_groups = [google_network_security_address_group.address_group_1.id] + } + disabled = true + } + rule { + description = "security profile group rule" + rule_name = "tcp rule" + priority = 3000 + enable_logging = false + action = "apply_security_profile_group" + direction = "INGRESS" + match { + layer4_config { + ip_protocol = "tcp" + } + src_ip_ranges = ["0.0.0.0/0"] + } + target_service_accounts = ["test@google.com"] + security_profile_group = "//networksecurity.googleapis.com/${google_network_security_security_profile_group.security_profile_group_1.id}" + tls_inspect = true + } +} + +resource "google_network_security_address_group" "address_group_1" { + provider = google-beta + name = "<%= ctx[:vars]['address_group_name'] %>" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + description = "Global address group" + location = "global" + items = ["208.80.154.224/32"] + type = "IPV4" + capacity = 100 +} + +resource "google_network_security_security_profile_group" "security_profile_group_1" { + provider = google-beta + name = "<%= ctx[:vars]['security_profile_group_name'] %>" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + description = "my description" + threat_prevention_profile = google_network_security_security_profile.security_profile_1.id +} + +resource "google_network_security_security_profile" "security_profile_1" { + provider = google-beta + name = "<%= ctx[:vars]['security_profile_name'] %>" + type = "THREAT_PREVENTION" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + location = "global" +} diff --git a/mmv1/templates/terraform/post_create/resource_compute_firewall_policy_with_rules.go.erb b/mmv1/templates/terraform/post_create/resource_compute_firewall_policy_with_rules.go.erb new file mode 100644 index 000000000000..07f879af397a --- /dev/null +++ b/mmv1/templates/terraform/post_create/resource_compute_firewall_policy_with_rules.go.erb @@ -0,0 +1,56 @@ +parent := d.Get("parent").(string) +var opRes map[string]interface{} +err = ComputeOrgOperationWaitTimeWithResponse( + config, res, &opRes, parent, "Creating FirewallPolicy", userAgent, + d.Timeout(schema.TimeoutCreate)) + +if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create FirewallPolicy: %s", err) +} + +policyId, ok := opRes["targetId"] +if !ok { + return fmt.Errorf("Create response didn't contain targetId. Create may not have succeeded.") +} +if err := d.Set("policy_id", policyId.(string)); err != nil { + return fmt.Errorf("Error setting policy_id: %s", err) +} + +// Store the ID now. +id, err = tpgresource.ReplaceVars(d, config, "locations/global/firewallPolicies/{{policy_id}}") +if err != nil { + return fmt.Errorf("Error constructing id: %s", err) +} +d.SetId(id) + +url, err = tpgresource.ReplaceVarsForId(d, config, "{{ComputeBasePath}}locations/global/firewallPolicies/{{policy_id}}") +if err != nil { + return err +} + +headers = make(http.Header) +res, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Headers: headers, +}) +if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ComputeFirewallPolicyWithRules %q", d.Id())) +} + +if err := d.Set("fingerprint", flattenComputeFirewallPolicyWithRulesFingerprint(res["fingerprint"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallPolicyWithRules: %s", err) +} + +res, err = resourceComputeFirewallPolicyWithRulesDecoder(d, meta, res) +if err != nil { + return err +} + +log.Printf("[DEBUG] Updating FirewallPolicyWithRules %q", d.Id()) +return resourceComputeFirewallPolicyWithRulesUpdate(d, meta) diff --git a/mmv1/templates/terraform/post_delete/resource_compute_firewall_policy_with_rules.go.erb b/mmv1/templates/terraform/post_delete/resource_compute_firewall_policy_with_rules.go.erb new file mode 100644 index 000000000000..7aafd3d08c77 --- /dev/null +++ b/mmv1/templates/terraform/post_delete/resource_compute_firewall_policy_with_rules.go.erb @@ -0,0 +1,10 @@ +parent := d.Get("parent").(string) +var opRes map[string]interface{} +err = ComputeOrgOperationWaitTimeWithResponse( + config, res, &opRes, parent, "Deleting FirewallPolicy", userAgent, + d.Timeout(schema.TimeoutCreate)) + +if err != nil { + // The resource didn't actually delete + return fmt.Errorf("Error waiting to delete FirewallPolicy: %s", err) +} diff --git a/mmv1/templates/terraform/post_update/resource_compute_firewall_policy_with_rules.go.erb b/mmv1/templates/terraform/post_update/resource_compute_firewall_policy_with_rules.go.erb new file mode 100644 index 000000000000..e2f74c48342f --- /dev/null +++ b/mmv1/templates/terraform/post_update/resource_compute_firewall_policy_with_rules.go.erb @@ -0,0 +1,10 @@ +parent := d.Get("parent").(string) +var opRes map[string]interface{} +err = ComputeOrgOperationWaitTimeWithResponse( + config, res, &opRes, parent, "Updating FirewallPolicy", userAgent, +d.Timeout(schema.TimeoutCreate)) + +if err != nil { + // The resource didn't actually update + return fmt.Errorf("Error waiting to update FirewallPolicy: %s", err) +} diff --git a/mmv1/templates/terraform/update_encoder/resource_compute_firewall_policy_with_rules.go.erb b/mmv1/templates/terraform/update_encoder/resource_compute_firewall_policy_with_rules.go.erb new file mode 100644 index 000000000000..1e3c847c6c09 --- /dev/null +++ b/mmv1/templates/terraform/update_encoder/resource_compute_firewall_policy_with_rules.go.erb @@ -0,0 +1,11 @@ +config := meta.(*transport_tpg.Config) + +predefinedRulesProp, err := expandComputeFirewallPolicyWithRulesRule(d.Get("predefined_rules"), d, config) +if err != nil { + return nil, err +} + +rules := obj["rules"].([]interface{}) +obj["rules"] = append(rules, predefinedRulesProp) + +return obj, nil diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_with_rules_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_with_rules_test.go.erb new file mode 100644 index 000000000000..cd39b027cf5d --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_with_rules_test.go.erb @@ -0,0 +1,222 @@ +<% autogen_exception -%> +package compute_test +<% unless version == 'ga' -%> +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccComputeFirewallPolicyWithRules_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckComputeFirewallPolicyWithRulesDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeFirewallPolicyWithRules_full(context), + }, + { + ResourceName: "google_compute_firewall_policy_with_rules.firewall-policy-with-rules", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeFirewallPolicyWithRules_update(context), + }, + { + ResourceName: "google_compute_firewall_policy_with_rules.firewall-policy-with-rules", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeFirewallPolicyWithRules_full(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_project" "project" { + provider = google-beta +} + +resource "google_compute_firewall_policy_with_rules" "firewall-policy-with-rules" { + short_name = "tf-test-tf-fw-org-policy-with-rules%{random_suffix}" + description = "Terraform test" + parent = "organizations/%{org_id}" + provider = google-beta + + rule { + description = "tcp rule" + priority = 1000 + enable_logging = true + action = "allow" + direction = "EGRESS" + match { + layer4_config { + ip_protocol = "tcp" + ports = [8080, 7070] + } + dest_ip_ranges = ["11.100.0.1/32"] + dest_fqdns = ["www.yyy.com", "www.zzz.com"] + dest_region_codes = ["HK", "IN"] + dest_threat_intelligences = ["iplist-search-engines-crawlers", "iplist-tor-exit-nodes"] + dest_address_groups = [google_network_security_address_group.address_group_1.id] + } + target_resources = ["https://www.googleapis.com/compute/beta/projects/${data.google_project.project.name}/global/networks/default"] + } + rule { + description = "udp rule" + priority = 2000 + enable_logging = false + action = "deny" + direction = "INGRESS" + match { + layer4_config { + ip_protocol = "udp" + } + src_ip_ranges = ["0.0.0.0/0"] + src_fqdns = ["www.abc.com", "www.def.com"] + src_region_codes = ["US", "CA"] + src_threat_intelligences = ["iplist-known-malicious-ips", "iplist-public-clouds"] + src_address_groups = [google_network_security_address_group.address_group_1.id] + } + disabled = true + } + rule { + description = "security profile group rule" + rule_name = "tcp rule" + priority = 3000 + enable_logging = false + action = "apply_security_profile_group" + direction = "INGRESS" + match { + layer4_config { + ip_protocol = "tcp" + } + src_ip_ranges = ["0.0.0.0/0"] + } + target_service_accounts = ["test@google.com"] + security_profile_group = "//networksecurity.googleapis.com/${google_network_security_security_profile_group.security_profile_group_1.id}" + tls_inspect = true + } +} + +resource "google_network_security_address_group" "address_group_1" { + provider = google-beta + name = "tf-test-tf-address-group%{random_suffix}" + parent = "organizations/%{org_id}" + description = "Global address group" + location = "global" + items = ["208.80.154.224/32"] + type = "IPV4" + capacity = 100 +} + +resource "google_network_security_security_profile_group" "security_profile_group_1" { + provider = google-beta + name = "tf-test-tf-security-profile-group%{random_suffix}" + parent = "organizations/%{org_id}" + description = "my description" + threat_prevention_profile = google_network_security_security_profile.security_profile_1.id +} + +resource "google_network_security_security_profile" "security_profile_1" { + provider = google-beta + name = "tf-test-tf-security-profile%{random_suffix}" + type = "THREAT_PREVENTION" + parent = "organizations/%{org_id}" + location = "global" +} +`, context) +} + +func testAccComputeFirewallPolicyWithRules_update(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_project" "project" { + provider = google-beta +} + +resource "google_compute_firewall_policy_with_rules" "firewall-policy-with-rules" { + short_name = "tf-test-tf-fw-org-policy-with-rules%{random_suffix}" + description = "Terraform test - update" + parent = "organizations/%{org_id}" + provider = google-beta + + rule { + description = "tcp rule - update" + rule_name = "udp rule" + priority = 1000 + enable_logging = false + action = "deny" + direction = "INGRESS" + match { + layer4_config { + ip_protocol = "udp" + ports = [8080] + } + src_ip_ranges = ["11.100.0.1/32", "0.0.0.0/0"] + src_fqdns = ["www.yyy.com"] + src_region_codes = ["HK"] + src_threat_intelligences = ["iplist-search-engines-crawlers"] + } + } + rule { + description = "udp rule" + priority = 3000 + enable_logging = false + action = "deny" + direction = "INGRESS" + match { + layer4_config { + ip_protocol = "all" + } + src_ip_ranges = ["0.0.0.0/0"] + src_fqdns = ["www.abc.com", "www.xyz.com"] + src_region_codes = ["US", "CA", "FR"] + src_threat_intelligences = ["iplist-known-malicious-ips", "iplist-public-clouds"] + src_address_groups = [google_network_security_address_group.address_group_1.id] + } + disabled = false + } +} + +resource "google_network_security_address_group" "address_group_1" { + provider = google-beta + name = "tf-test-tf-address-group%{random_suffix}" + parent = "organizations/%{org_id}" + description = "Global address group" + location = "global" + items = ["208.80.154.224/32"] + type = "IPV4" + capacity = 100 +} + +resource "google_network_security_security_profile_group" "security_profile_group_1" { + provider = google-beta + name = "tf-test-tf-security-profile-group%{random_suffix}" + parent = "organizations/%{org_id}" + description = "my description" + threat_prevention_profile = google_network_security_security_profile.security_profile_1.id +} + +resource "google_network_security_security_profile" "security_profile_1" { + provider = google-beta + name = "tf-test-tf-security-profile%{random_suffix}" + type = "THREAT_PREVENTION" + parent = "organizations/%{org_id}" + location = "global" +} +`, context) +} +<% end -%> +