diff --git a/.changelog/6799.txt b/.changelog/6799.txt new file mode 100644 index 0000000000..97d175fb0f --- /dev/null +++ b/.changelog/6799.txt @@ -0,0 +1,6 @@ +```release-note:new-resource +`google_compute_network_firewall_policy_rule` +``` +```release-note:new-resource +`google_compute_region_network_firewall_policy_rule` +``` diff --git a/go.mod b/go.mod index b7ca313880..62bf1d78bd 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ go 1.18 require ( cloud.google.com/go/bigtable v1.17.0 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.4 github.com/apparentlymart/go-cidr v1.1.0 github.com/client9/misspell v0.3.4 github.com/davecgh/go-spew v1.1.1 diff --git a/go.sum b/go.sum index 3c31e081eb..2a50e145f3 100644 --- a/go.sum +++ b/go.sum @@ -55,8 +55,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.0 h1:9RQhnEju2B+3njLTERnIeotRoI3GOQrN7kXA+n3iuJw= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.4 h1:nP8L2TqVbGehmlt6sfYiu4BKE0lJrGW1RrtP9/+FwfY= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.4/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -1301,5 +1301,3 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.0 h1:9RQhnEju2B+3njLTERnIeotRoI3GOQrN7kXA+n3iuJw= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.26.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= diff --git a/google/provider_dcl_resources.go b/google/provider_dcl_resources.go index 4738364a9b..9be0c77e90 100644 --- a/google/provider_dcl_resources.go +++ b/google/provider_dcl_resources.go @@ -33,6 +33,8 @@ var dclResources = map[string]*schema.Resource{ "google_compute_network_firewall_policy": resourceComputeNetworkFirewallPolicy(), "google_compute_network_firewall_policy_association": resourceComputeNetworkFirewallPolicyAssociation(), "google_compute_region_network_firewall_policy_association": resourceComputeRegionNetworkFirewallPolicyAssociation(), + "google_compute_network_firewall_policy_rule": resourceComputeNetworkFirewallPolicyRule(), + "google_compute_region_network_firewall_policy_rule": resourceComputeRegionNetworkFirewallPolicyRule(), "google_container_aws_cluster": resourceContainerAwsCluster(), "google_container_aws_node_pool": resourceContainerAwsNodePool(), "google_container_azure_client": resourceContainerAzureClient(), diff --git a/google/resource_compute_network_firewall_policy_rule.go b/google/resource_compute_network_firewall_policy_rule.go new file mode 100644 index 0000000000..7e42a9cc28 --- /dev/null +++ b/google/resource_compute_network_firewall_policy_rule.go @@ -0,0 +1,705 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: DCL *** +// +// ---------------------------------------------------------------------------- +// +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. +// +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" +) + +func resourceComputeNetworkFirewallPolicyRule() *schema.Resource { + return &schema.Resource{ + Create: resourceComputeNetworkFirewallPolicyRuleCreate, + Read: resourceComputeNetworkFirewallPolicyRuleRead, + Update: resourceComputeNetworkFirewallPolicyRuleUpdate, + Delete: resourceComputeNetworkFirewallPolicyRuleDelete, + + Importer: &schema.ResourceImporter{ + State: resourceComputeNetworkFirewallPolicyRuleImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + Description: "The Action to perform when the client connection triggers the rule. Can currently be either \"allow\" or \"deny()\" where valid values for status are 403, 404, and 502.", + }, + + "direction": { + Type: schema.TypeString, + Required: true, + Description: "The direction in which this rule applies. Possible values: INGRESS, EGRESS", + }, + + "firewall_policy": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "The firewall policy of the resource.", + }, + + "match": { + Type: schema.TypeList, + Required: true, + Description: "A match condition that incoming traffic is evaluated against. If it evaluates to true, the corresponding 'action' is enforced.", + MaxItems: 1, + Elem: ComputeNetworkFirewallPolicyRuleMatchSchema(), + }, + + "priority": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest prority.", + }, + + "description": { + Type: schema.TypeString, + Optional: true, + Description: "An optional description for this resource.", + }, + + "disabled": { + Type: schema.TypeBool, + Optional: 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.", + }, + + "enable_logging": { + Type: schema.TypeBool, + Optional: 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. Logs may be exported to BigQuery or Pub/Sub. Note: you cannot enable logging on \"goto_next\" rules.", + }, + + "project": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "The project for the resource", + }, + + "rule_name": { + Type: schema.TypeString, + Optional: true, + Description: "An optional name for the rule. This field is not a unique identifier and can be updated.", + }, + + "target_secure_tags": { + Type: schema.TypeList, + Optional: true, + Description: "A list of secure tags that controls which instances the firewall rule applies to. If targetSecureTag are specified, then the firewall rule applies only to instances in the VPC network that have one of those EFFECTIVE secure tags, if all the target_secure_tag are in INEFFECTIVE state, then this rule will be ignored. targetSecureTag may not be set at the same time as targetServiceAccounts. If neither targetServiceAccounts nor targetSecureTag are specified, the firewall rule applies to all instances on the specified network. Maximum number of target label tags allowed is 256.", + Elem: ComputeNetworkFirewallPolicyRuleTargetSecureTagsSchema(), + }, + + "target_service_accounts": { + Type: schema.TypeList, + Optional: true, + Description: "A list of service accounts indicating the sets of instances that are applied with this rule.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "kind": { + Type: schema.TypeString, + Computed: true, + Description: "Type of the resource. Always `compute#firewallPolicyRule` for firewall policy rules", + }, + + "rule_tuple_count": { + Type: schema.TypeInt, + Computed: true, + Description: "Calculation of the complexity of a single firewall policy rule.", + }, + }, + } +} + +func ComputeNetworkFirewallPolicyRuleMatchSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "layer4_configs": { + Type: schema.TypeList, + Required: true, + Description: "Pairs of IP protocols and ports that the rule should match.", + Elem: ComputeNetworkFirewallPolicyRuleMatchLayer4ConfigsSchema(), + }, + + "dest_ip_ranges": { + Type: schema.TypeList, + Optional: true, + Description: "CIDR IP address range. Maximum number of destination CIDR IP ranges allowed is 5000.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "src_ip_ranges": { + Type: schema.TypeList, + Optional: true, + Description: "CIDR IP address range. Maximum number of source CIDR IP ranges allowed is 5000.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "src_secure_tags": { + Type: schema.TypeList, + Optional: true, + Description: "List of secure tag values, which should be matched at the source of the traffic. For INGRESS rule, if all the srcSecureTag are INEFFECTIVE, and there is no srcIpRange, this rule will be ignored. Maximum number of source tag values allowed is 256.", + Elem: ComputeNetworkFirewallPolicyRuleMatchSrcSecureTagsSchema(), + }, + }, + } +} + +func ComputeNetworkFirewallPolicyRuleMatchLayer4ConfigsSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_protocol": { + Type: schema.TypeString, + Required: 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.", + }, + + "ports": { + Type: schema.TypeList, + Optional: 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: ``.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func ComputeNetworkFirewallPolicyRuleMatchSrcSecureTagsSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+", + }, + + "state": { + Type: schema.TypeString, + Computed: true, + Description: "[Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted.", + }, + }, + } +} + +func ComputeNetworkFirewallPolicyRuleTargetSecureTagsSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+", + }, + + "state": { + Type: schema.TypeString, + Computed: true, + Description: "[Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted.", + }, + }, + } +} + +func resourceComputeNetworkFirewallPolicyRuleCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + + id, err := obj.ID() + if err != nil { + return fmt.Errorf("error constructing id: %s", err) + } + d.SetId(id) + directive := CreateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutCreate)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.ApplyNetworkFirewallPolicyRule(context.Background(), obj, directive...) + + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error creating NetworkFirewallPolicyRule: %s", err) + } + + log.Printf("[DEBUG] Finished creating NetworkFirewallPolicyRule %q: %#v", d.Id(), res) + + return resourceComputeNetworkFirewallPolicyRuleRead(d, meta) +} + +func resourceComputeNetworkFirewallPolicyRuleRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutRead)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.GetNetworkFirewallPolicyRule(context.Background(), obj) + if err != nil { + resourceName := fmt.Sprintf("ComputeNetworkFirewallPolicyRule %q", d.Id()) + return handleNotFoundDCLError(err, d, resourceName) + } + + if err = d.Set("action", res.Action); err != nil { + return fmt.Errorf("error setting action in state: %s", err) + } + if err = d.Set("direction", res.Direction); err != nil { + return fmt.Errorf("error setting direction in state: %s", err) + } + if err = d.Set("firewall_policy", res.FirewallPolicy); err != nil { + return fmt.Errorf("error setting firewall_policy in state: %s", err) + } + if err = d.Set("match", flattenComputeNetworkFirewallPolicyRuleMatch(res.Match)); err != nil { + return fmt.Errorf("error setting match in state: %s", err) + } + if err = d.Set("priority", res.Priority); err != nil { + return fmt.Errorf("error setting priority in state: %s", err) + } + if err = d.Set("description", res.Description); err != nil { + return fmt.Errorf("error setting description in state: %s", err) + } + if err = d.Set("disabled", res.Disabled); err != nil { + return fmt.Errorf("error setting disabled in state: %s", err) + } + if err = d.Set("enable_logging", res.EnableLogging); err != nil { + return fmt.Errorf("error setting enable_logging in state: %s", err) + } + if err = d.Set("project", res.Project); err != nil { + return fmt.Errorf("error setting project in state: %s", err) + } + if err = d.Set("rule_name", res.RuleName); err != nil { + return fmt.Errorf("error setting rule_name in state: %s", err) + } + if err = d.Set("target_secure_tags", flattenComputeNetworkFirewallPolicyRuleTargetSecureTagsArray(res.TargetSecureTags)); err != nil { + return fmt.Errorf("error setting target_secure_tags in state: %s", err) + } + if err = d.Set("target_service_accounts", res.TargetServiceAccounts); err != nil { + return fmt.Errorf("error setting target_service_accounts in state: %s", err) + } + if err = d.Set("kind", res.Kind); err != nil { + return fmt.Errorf("error setting kind in state: %s", err) + } + if err = d.Set("rule_tuple_count", res.RuleTupleCount); err != nil { + return fmt.Errorf("error setting rule_tuple_count in state: %s", err) + } + + return nil +} +func resourceComputeNetworkFirewallPolicyRuleUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + directive := UpdateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutUpdate)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.ApplyNetworkFirewallPolicyRule(context.Background(), obj, directive...) + + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error updating NetworkFirewallPolicyRule: %s", err) + } + + log.Printf("[DEBUG] Finished creating NetworkFirewallPolicyRule %q: %#v", d.Id(), res) + + return resourceComputeNetworkFirewallPolicyRuleRead(d, meta) +} + +func resourceComputeNetworkFirewallPolicyRuleDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + + log.Printf("[DEBUG] Deleting NetworkFirewallPolicyRule %q", d.Id()) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutDelete)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + if err := client.DeleteNetworkFirewallPolicyRule(context.Background(), obj); err != nil { + return fmt.Errorf("Error deleting NetworkFirewallPolicyRule: %s", err) + } + + log.Printf("[DEBUG] Finished deleting NetworkFirewallPolicyRule %q", d.Id()) + return nil +} + +func resourceComputeNetworkFirewallPolicyRuleImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + + if err := parseImportId([]string{ + "projects/(?P[^/]+)/global/firewallPolicies/(?P[^/]+)/rules/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVarsForId(d, config, "projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/rules/{{priority}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func expandComputeNetworkFirewallPolicyRuleMatch(o interface{}) *compute.NetworkFirewallPolicyRuleMatch { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatch + } + objArr := o.([]interface{}) + if len(objArr) == 0 || objArr[0] == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatch + } + obj := objArr[0].(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleMatch{ + Layer4Configs: expandComputeNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(obj["layer4_configs"]), + DestIPRanges: expandStringArray(obj["dest_ip_ranges"]), + SrcIPRanges: expandStringArray(obj["src_ip_ranges"]), + SrcSecureTags: expandComputeNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(obj["src_secure_tags"]), + } +} + +func flattenComputeNetworkFirewallPolicyRuleMatch(obj *compute.NetworkFirewallPolicyRuleMatch) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "layer4_configs": flattenComputeNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(obj.Layer4Configs), + "dest_ip_ranges": obj.DestIPRanges, + "src_ip_ranges": obj.SrcIPRanges, + "src_secure_tags": flattenComputeNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(obj.SrcSecureTags), + } + + return []interface{}{transformed} + +} +func expandComputeNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(o interface{}) []compute.NetworkFirewallPolicyRuleMatchLayer4Configs { + if o == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchLayer4Configs, 0) + } + + objs := o.([]interface{}) + if len(objs) == 0 || objs[0] == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchLayer4Configs, 0) + } + + items := make([]compute.NetworkFirewallPolicyRuleMatchLayer4Configs, 0, len(objs)) + for _, item := range objs { + i := expandComputeNetworkFirewallPolicyRuleMatchLayer4Configs(item) + items = append(items, *i) + } + + return items +} + +func expandComputeNetworkFirewallPolicyRuleMatchLayer4Configs(o interface{}) *compute.NetworkFirewallPolicyRuleMatchLayer4Configs { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatchLayer4Configs + } + + obj := o.(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleMatchLayer4Configs{ + IPProtocol: dcl.String(obj["ip_protocol"].(string)), + Ports: expandStringArray(obj["ports"]), + } +} + +func flattenComputeNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(objs []compute.NetworkFirewallPolicyRuleMatchLayer4Configs) []interface{} { + if objs == nil { + return nil + } + + items := []interface{}{} + for _, item := range objs { + i := flattenComputeNetworkFirewallPolicyRuleMatchLayer4Configs(&item) + items = append(items, i) + } + + return items +} + +func flattenComputeNetworkFirewallPolicyRuleMatchLayer4Configs(obj *compute.NetworkFirewallPolicyRuleMatchLayer4Configs) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "ip_protocol": obj.IPProtocol, + "ports": obj.Ports, + } + + return transformed + +} +func expandComputeNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(o interface{}) []compute.NetworkFirewallPolicyRuleMatchSrcSecureTags { + if o == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchSrcSecureTags, 0) + } + + objs := o.([]interface{}) + if len(objs) == 0 || objs[0] == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchSrcSecureTags, 0) + } + + items := make([]compute.NetworkFirewallPolicyRuleMatchSrcSecureTags, 0, len(objs)) + for _, item := range objs { + i := expandComputeNetworkFirewallPolicyRuleMatchSrcSecureTags(item) + items = append(items, *i) + } + + return items +} + +func expandComputeNetworkFirewallPolicyRuleMatchSrcSecureTags(o interface{}) *compute.NetworkFirewallPolicyRuleMatchSrcSecureTags { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatchSrcSecureTags + } + + obj := o.(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleMatchSrcSecureTags{ + Name: dcl.String(obj["name"].(string)), + } +} + +func flattenComputeNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(objs []compute.NetworkFirewallPolicyRuleMatchSrcSecureTags) []interface{} { + if objs == nil { + return nil + } + + items := []interface{}{} + for _, item := range objs { + i := flattenComputeNetworkFirewallPolicyRuleMatchSrcSecureTags(&item) + items = append(items, i) + } + + return items +} + +func flattenComputeNetworkFirewallPolicyRuleMatchSrcSecureTags(obj *compute.NetworkFirewallPolicyRuleMatchSrcSecureTags) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "name": obj.Name, + "state": obj.State, + } + + return transformed + +} +func expandComputeNetworkFirewallPolicyRuleTargetSecureTagsArray(o interface{}) []compute.NetworkFirewallPolicyRuleTargetSecureTags { + if o == nil { + return make([]compute.NetworkFirewallPolicyRuleTargetSecureTags, 0) + } + + objs := o.([]interface{}) + if len(objs) == 0 || objs[0] == nil { + return make([]compute.NetworkFirewallPolicyRuleTargetSecureTags, 0) + } + + items := make([]compute.NetworkFirewallPolicyRuleTargetSecureTags, 0, len(objs)) + for _, item := range objs { + i := expandComputeNetworkFirewallPolicyRuleTargetSecureTags(item) + items = append(items, *i) + } + + return items +} + +func expandComputeNetworkFirewallPolicyRuleTargetSecureTags(o interface{}) *compute.NetworkFirewallPolicyRuleTargetSecureTags { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleTargetSecureTags + } + + obj := o.(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleTargetSecureTags{ + Name: dcl.String(obj["name"].(string)), + } +} + +func flattenComputeNetworkFirewallPolicyRuleTargetSecureTagsArray(objs []compute.NetworkFirewallPolicyRuleTargetSecureTags) []interface{} { + if objs == nil { + return nil + } + + items := []interface{}{} + for _, item := range objs { + i := flattenComputeNetworkFirewallPolicyRuleTargetSecureTags(&item) + items = append(items, i) + } + + return items +} + +func flattenComputeNetworkFirewallPolicyRuleTargetSecureTags(obj *compute.NetworkFirewallPolicyRuleTargetSecureTags) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "name": obj.Name, + "state": obj.State, + } + + return transformed + +} diff --git a/google/resource_compute_network_firewall_policy_rule_generated_test.go b/google/resource_compute_network_firewall_policy_rule_generated_test.go new file mode 100644 index 0000000000..8fcc211845 --- /dev/null +++ b/google/resource_compute_network_firewall_policy_rule_generated_test.go @@ -0,0 +1,203 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: DCL *** +// +// ---------------------------------------------------------------------------- +// +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. +// +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "context" + "fmt" + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "strings" + "testing" +) + +func TestAccComputeNetworkFirewallPolicyRule_GlobalHandWritten(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": getTestOrgFromEnv(t), + "project_name": getTestProjectFromEnv(), + "service_acct": getTestServiceAccountFromEnv(t), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeNetworkFirewallPolicyRuleDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeNetworkFirewallPolicyRule_GlobalHandWritten(context), + }, + { + ResourceName: "google_compute_network_firewall_policy_rule.primary", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeNetworkFirewallPolicyRule_GlobalHandWrittenUpdate0(context), + }, + { + ResourceName: "google_compute_network_firewall_policy_rule.primary", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeNetworkFirewallPolicyRule_GlobalHandWritten(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_network_firewall_policy" "basic_network_firewall_policy" { + name = "tf-test-policy%{random_suffix}" + project = "%{project_name}" + description = "Sample global network firewall policy" +} + +resource "google_compute_network_firewall_policy_rule" "primary" { + firewall_policy = google_compute_network_firewall_policy.basic_network_firewall_policy.name + action = "allow" + direction = "INGRESS" + priority = 1000 + rule_name = "test-rule" + description = "This is a simple rule description" +match { + src_secure_tags { + name = "tagValues/${google_tags_tag_value.basic_value.name}" + } + src_ip_ranges = ["10.100.0.1/32"] +layer4_configs { +ip_protocol = "all" + } + } + target_service_accounts = ["%{service_acct}"] + enable_logging = true + disabled = false +} +resource "google_compute_network" "basic_network" { + name = "tf-test-network%{random_suffix}" +} +resource "google_tags_tag_key" "basic_key" { + parent = "organizations/%{org_id}" + short_name = "tf-test-tagkey%{random_suffix}" + purpose = "GCE_FIREWALL" + purpose_data = { + network= "%{project_name}/${google_compute_network.basic_network.name}" + } + description = "For keyname resources." +} + + +resource "google_tags_tag_value" "basic_value" { + parent = "tagKeys/${google_tags_tag_key.basic_key.name}" + short_name = "tf-test-tagvalue%{random_suffix}" + description = "For valuename resources." +} + +`, context) +} + +func testAccComputeNetworkFirewallPolicyRule_GlobalHandWrittenUpdate0(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_network_firewall_policy" "basic_network_firewall_policy" { + name = "tf-test-policy%{random_suffix}" + project = "%{project_name}" + description = "Sample global network firewall policy" +} + +resource "google_compute_network_firewall_policy_rule" "primary" { + firewall_policy = google_compute_network_firewall_policy.basic_network_firewall_policy.name + action = "deny" + direction = "EGRESS" + priority = 1000 + rule_name = "updated-test-rule" + description = "This is an updated rule description" +match { +layer4_configs { +ip_protocol = "tcp" +ports = ["123"] + } + dest_ip_ranges = ["0.0.0.0/0"] + } + target_secure_tags { + name = "tagValues/${google_tags_tag_value.basic_value.name}" + } + enable_logging = false + disabled = true +} +resource "google_compute_network" "basic_network" { + name = "tf-test-network%{random_suffix}" +} +resource "google_tags_tag_key" "basic_key" { + parent = "organizations/%{org_id}" + short_name = "tf-test-tagkey%{random_suffix}" + purpose = "GCE_FIREWALL" + purpose_data = { + network= "%{project_name}/${google_compute_network.basic_network.name}" + } + description = "For keyname resources." +} + + +resource "google_tags_tag_value" "basic_value" { + parent = "tagKeys/${google_tags_tag_key.basic_key.name}" + short_name = "tf-test-tagvalue%{random_suffix}" + description = "For valuename resources." +} + +`, context) +} + +func testAccCheckComputeNetworkFirewallPolicyRuleDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "rs.google_compute_network_firewall_policy_rule" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + billingProject := "" + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(rs.Primary.Attributes["action"]), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(rs.Primary.Attributes["direction"]), + FirewallPolicy: dcl.String(rs.Primary.Attributes["firewall_policy"]), + Description: dcl.String(rs.Primary.Attributes["description"]), + Disabled: dcl.Bool(rs.Primary.Attributes["disabled"] == "true"), + EnableLogging: dcl.Bool(rs.Primary.Attributes["enable_logging"] == "true"), + Project: dcl.StringOrNil(rs.Primary.Attributes["project"]), + RuleName: dcl.String(rs.Primary.Attributes["rule_name"]), + Kind: dcl.StringOrNil(rs.Primary.Attributes["kind"]), + } + + client := NewDCLComputeClient(config, config.userAgent, billingProject, 0) + _, err := client.GetNetworkFirewallPolicyRule(context.Background(), obj) + if err == nil { + return fmt.Errorf("google_compute_network_firewall_policy_rule still exists %v", obj) + } + } + return nil + } +} diff --git a/google/resource_compute_region_network_firewall_policy_rule.go b/google/resource_compute_region_network_firewall_policy_rule.go new file mode 100644 index 0000000000..bfae464303 --- /dev/null +++ b/google/resource_compute_region_network_firewall_policy_rule.go @@ -0,0 +1,737 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: DCL *** +// +// ---------------------------------------------------------------------------- +// +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. +// +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" +) + +func resourceComputeRegionNetworkFirewallPolicyRule() *schema.Resource { + return &schema.Resource{ + Create: resourceComputeRegionNetworkFirewallPolicyRuleCreate, + Read: resourceComputeRegionNetworkFirewallPolicyRuleRead, + Update: resourceComputeRegionNetworkFirewallPolicyRuleUpdate, + Delete: resourceComputeRegionNetworkFirewallPolicyRuleDelete, + + Importer: &schema.ResourceImporter{ + State: resourceComputeRegionNetworkFirewallPolicyRuleImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + Description: "The Action to perform when the client connection triggers the rule. Can currently be either \"allow\" or \"deny()\" where valid values for status are 403, 404, and 502.", + }, + + "direction": { + Type: schema.TypeString, + Required: true, + Description: "The direction in which this rule applies. Possible values: INGRESS, EGRESS", + }, + + "firewall_policy": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "The firewall policy of the resource.", + }, + + "match": { + Type: schema.TypeList, + Required: true, + Description: "A match condition that incoming traffic is evaluated against. If it evaluates to true, the corresponding 'action' is enforced.", + MaxItems: 1, + Elem: ComputeRegionNetworkFirewallPolicyRuleMatchSchema(), + }, + + "priority": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest prority.", + }, + + "description": { + Type: schema.TypeString, + Optional: true, + Description: "An optional description for this resource.", + }, + + "disabled": { + Type: schema.TypeBool, + Optional: 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.", + }, + + "enable_logging": { + Type: schema.TypeBool, + Optional: 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. Logs may be exported to BigQuery or Pub/Sub. Note: you cannot enable logging on \"goto_next\" rules.", + }, + + "project": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "The project for the resource", + }, + + "region": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: "The location of this resource.", + }, + + "rule_name": { + Type: schema.TypeString, + Optional: true, + Description: "An optional name for the rule. This field is not a unique identifier and can be updated.", + }, + + "target_secure_tags": { + Type: schema.TypeList, + Optional: true, + Description: "A list of secure tags that controls which instances the firewall rule applies to. If targetSecureTag are specified, then the firewall rule applies only to instances in the VPC network that have one of those EFFECTIVE secure tags, if all the target_secure_tag are in INEFFECTIVE state, then this rule will be ignored. targetSecureTag may not be set at the same time as targetServiceAccounts. If neither targetServiceAccounts nor targetSecureTag are specified, the firewall rule applies to all instances on the specified network. Maximum number of target label tags allowed is 256.", + Elem: ComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsSchema(), + }, + + "target_service_accounts": { + Type: schema.TypeList, + Optional: true, + Description: "A list of service accounts indicating the sets of instances that are applied with this rule.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "kind": { + Type: schema.TypeString, + Computed: true, + Description: "Type of the resource. Always `compute#firewallPolicyRule` for firewall policy rules", + }, + + "rule_tuple_count": { + Type: schema.TypeInt, + Computed: true, + Description: "Calculation of the complexity of a single firewall policy rule.", + }, + }, + } +} + +func ComputeRegionNetworkFirewallPolicyRuleMatchSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "layer4_configs": { + Type: schema.TypeList, + Required: true, + Description: "Pairs of IP protocols and ports that the rule should match.", + Elem: ComputeRegionNetworkFirewallPolicyRuleMatchLayer4ConfigsSchema(), + }, + + "dest_ip_ranges": { + Type: schema.TypeList, + Optional: true, + Description: "CIDR IP address range. Maximum number of destination CIDR IP ranges allowed is 5000.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "src_ip_ranges": { + Type: schema.TypeList, + Optional: true, + Description: "CIDR IP address range. Maximum number of source CIDR IP ranges allowed is 5000.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "src_secure_tags": { + Type: schema.TypeList, + Optional: true, + Description: "List of secure tag values, which should be matched at the source of the traffic. For INGRESS rule, if all the srcSecureTag are INEFFECTIVE, and there is no srcIpRange, this rule will be ignored. Maximum number of source tag values allowed is 256.", + Elem: ComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTagsSchema(), + }, + }, + } +} + +func ComputeRegionNetworkFirewallPolicyRuleMatchLayer4ConfigsSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_protocol": { + Type: schema.TypeString, + Required: 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.", + }, + + "ports": { + Type: schema.TypeList, + Optional: 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: ``.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func ComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTagsSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+", + }, + + "state": { + Type: schema.TypeString, + Computed: true, + Description: "[Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted.", + }, + }, + } +} + +func ComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+", + }, + + "state": { + Type: schema.TypeString, + Computed: true, + Description: "[Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted.", + }, + }, + } +} + +func resourceComputeRegionNetworkFirewallPolicyRuleCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + region, err := getRegion(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeRegionNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + Location: dcl.String(region), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + + id, err := replaceVarsForId(d, config, "projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}}") + if err != nil { + return fmt.Errorf("error constructing id: %s", err) + } + d.SetId(id) + directive := CreateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutCreate)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.ApplyNetworkFirewallPolicyRule(context.Background(), obj, directive...) + + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error creating NetworkFirewallPolicyRule: %s", err) + } + + log.Printf("[DEBUG] Finished creating NetworkFirewallPolicyRule %q: %#v", d.Id(), res) + + return resourceComputeRegionNetworkFirewallPolicyRuleRead(d, meta) +} + +func resourceComputeRegionNetworkFirewallPolicyRuleRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + region, err := getRegion(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeRegionNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + Location: dcl.String(region), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutRead)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.GetNetworkFirewallPolicyRule(context.Background(), obj) + if err != nil { + resourceName := fmt.Sprintf("ComputeRegionNetworkFirewallPolicyRule %q", d.Id()) + return handleNotFoundDCLError(err, d, resourceName) + } + + if err = d.Set("action", res.Action); err != nil { + return fmt.Errorf("error setting action in state: %s", err) + } + if err = d.Set("direction", res.Direction); err != nil { + return fmt.Errorf("error setting direction in state: %s", err) + } + if err = d.Set("firewall_policy", res.FirewallPolicy); err != nil { + return fmt.Errorf("error setting firewall_policy in state: %s", err) + } + if err = d.Set("match", flattenComputeRegionNetworkFirewallPolicyRuleMatch(res.Match)); err != nil { + return fmt.Errorf("error setting match in state: %s", err) + } + if err = d.Set("priority", res.Priority); err != nil { + return fmt.Errorf("error setting priority in state: %s", err) + } + if err = d.Set("description", res.Description); err != nil { + return fmt.Errorf("error setting description in state: %s", err) + } + if err = d.Set("disabled", res.Disabled); err != nil { + return fmt.Errorf("error setting disabled in state: %s", err) + } + if err = d.Set("enable_logging", res.EnableLogging); err != nil { + return fmt.Errorf("error setting enable_logging in state: %s", err) + } + if err = d.Set("project", res.Project); err != nil { + return fmt.Errorf("error setting project in state: %s", err) + } + if err = d.Set("region", res.Location); err != nil { + return fmt.Errorf("error setting region in state: %s", err) + } + if err = d.Set("rule_name", res.RuleName); err != nil { + return fmt.Errorf("error setting rule_name in state: %s", err) + } + if err = d.Set("target_secure_tags", flattenComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsArray(res.TargetSecureTags)); err != nil { + return fmt.Errorf("error setting target_secure_tags in state: %s", err) + } + if err = d.Set("target_service_accounts", res.TargetServiceAccounts); err != nil { + return fmt.Errorf("error setting target_service_accounts in state: %s", err) + } + if err = d.Set("kind", res.Kind); err != nil { + return fmt.Errorf("error setting kind in state: %s", err) + } + if err = d.Set("rule_tuple_count", res.RuleTupleCount); err != nil { + return fmt.Errorf("error setting rule_tuple_count in state: %s", err) + } + + return nil +} +func resourceComputeRegionNetworkFirewallPolicyRuleUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + region, err := getRegion(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeRegionNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + Location: dcl.String(region), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + directive := UpdateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutUpdate)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.ApplyNetworkFirewallPolicyRule(context.Background(), obj, directive...) + + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error updating NetworkFirewallPolicyRule: %s", err) + } + + log.Printf("[DEBUG] Finished creating NetworkFirewallPolicyRule %q: %#v", d.Id(), res) + + return resourceComputeRegionNetworkFirewallPolicyRuleRead(d, meta) +} + +func resourceComputeRegionNetworkFirewallPolicyRuleDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + region, err := getRegion(d, config) + if err != nil { + return err + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(d.Get("action").(string)), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(d.Get("direction").(string)), + FirewallPolicy: dcl.String(d.Get("firewall_policy").(string)), + Match: expandComputeRegionNetworkFirewallPolicyRuleMatch(d.Get("match")), + Priority: dcl.Int64(int64(d.Get("priority").(int))), + Description: dcl.String(d.Get("description").(string)), + Disabled: dcl.Bool(d.Get("disabled").(bool)), + EnableLogging: dcl.Bool(d.Get("enable_logging").(bool)), + Project: dcl.String(project), + Location: dcl.String(region), + RuleName: dcl.String(d.Get("rule_name").(string)), + TargetSecureTags: expandComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsArray(d.Get("target_secure_tags")), + TargetServiceAccounts: expandStringArray(d.Get("target_service_accounts")), + } + + log.Printf("[DEBUG] Deleting NetworkFirewallPolicyRule %q", d.Id()) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutDelete)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + if err := client.DeleteNetworkFirewallPolicyRule(context.Background(), obj); err != nil { + return fmt.Errorf("Error deleting NetworkFirewallPolicyRule: %s", err) + } + + log.Printf("[DEBUG] Finished deleting NetworkFirewallPolicyRule %q", d.Id()) + return nil +} + +func resourceComputeRegionNetworkFirewallPolicyRuleImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + + if err := parseImportId([]string{ + "projects/(?P[^/]+)/regions/(?P[^/]+)/firewallPolicies/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVarsForId(d, config, "projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func expandComputeRegionNetworkFirewallPolicyRuleMatch(o interface{}) *compute.NetworkFirewallPolicyRuleMatch { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatch + } + objArr := o.([]interface{}) + if len(objArr) == 0 || objArr[0] == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatch + } + obj := objArr[0].(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleMatch{ + Layer4Configs: expandComputeRegionNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(obj["layer4_configs"]), + DestIPRanges: expandStringArray(obj["dest_ip_ranges"]), + SrcIPRanges: expandStringArray(obj["src_ip_ranges"]), + SrcSecureTags: expandComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(obj["src_secure_tags"]), + } +} + +func flattenComputeRegionNetworkFirewallPolicyRuleMatch(obj *compute.NetworkFirewallPolicyRuleMatch) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "layer4_configs": flattenComputeRegionNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(obj.Layer4Configs), + "dest_ip_ranges": obj.DestIPRanges, + "src_ip_ranges": obj.SrcIPRanges, + "src_secure_tags": flattenComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(obj.SrcSecureTags), + } + + return []interface{}{transformed} + +} +func expandComputeRegionNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(o interface{}) []compute.NetworkFirewallPolicyRuleMatchLayer4Configs { + if o == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchLayer4Configs, 0) + } + + objs := o.([]interface{}) + if len(objs) == 0 || objs[0] == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchLayer4Configs, 0) + } + + items := make([]compute.NetworkFirewallPolicyRuleMatchLayer4Configs, 0, len(objs)) + for _, item := range objs { + i := expandComputeRegionNetworkFirewallPolicyRuleMatchLayer4Configs(item) + items = append(items, *i) + } + + return items +} + +func expandComputeRegionNetworkFirewallPolicyRuleMatchLayer4Configs(o interface{}) *compute.NetworkFirewallPolicyRuleMatchLayer4Configs { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatchLayer4Configs + } + + obj := o.(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleMatchLayer4Configs{ + IPProtocol: dcl.String(obj["ip_protocol"].(string)), + Ports: expandStringArray(obj["ports"]), + } +} + +func flattenComputeRegionNetworkFirewallPolicyRuleMatchLayer4ConfigsArray(objs []compute.NetworkFirewallPolicyRuleMatchLayer4Configs) []interface{} { + if objs == nil { + return nil + } + + items := []interface{}{} + for _, item := range objs { + i := flattenComputeRegionNetworkFirewallPolicyRuleMatchLayer4Configs(&item) + items = append(items, i) + } + + return items +} + +func flattenComputeRegionNetworkFirewallPolicyRuleMatchLayer4Configs(obj *compute.NetworkFirewallPolicyRuleMatchLayer4Configs) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "ip_protocol": obj.IPProtocol, + "ports": obj.Ports, + } + + return transformed + +} +func expandComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(o interface{}) []compute.NetworkFirewallPolicyRuleMatchSrcSecureTags { + if o == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchSrcSecureTags, 0) + } + + objs := o.([]interface{}) + if len(objs) == 0 || objs[0] == nil { + return make([]compute.NetworkFirewallPolicyRuleMatchSrcSecureTags, 0) + } + + items := make([]compute.NetworkFirewallPolicyRuleMatchSrcSecureTags, 0, len(objs)) + for _, item := range objs { + i := expandComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTags(item) + items = append(items, *i) + } + + return items +} + +func expandComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTags(o interface{}) *compute.NetworkFirewallPolicyRuleMatchSrcSecureTags { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleMatchSrcSecureTags + } + + obj := o.(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleMatchSrcSecureTags{ + Name: dcl.String(obj["name"].(string)), + } +} + +func flattenComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTagsArray(objs []compute.NetworkFirewallPolicyRuleMatchSrcSecureTags) []interface{} { + if objs == nil { + return nil + } + + items := []interface{}{} + for _, item := range objs { + i := flattenComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTags(&item) + items = append(items, i) + } + + return items +} + +func flattenComputeRegionNetworkFirewallPolicyRuleMatchSrcSecureTags(obj *compute.NetworkFirewallPolicyRuleMatchSrcSecureTags) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "name": obj.Name, + "state": obj.State, + } + + return transformed + +} +func expandComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsArray(o interface{}) []compute.NetworkFirewallPolicyRuleTargetSecureTags { + if o == nil { + return make([]compute.NetworkFirewallPolicyRuleTargetSecureTags, 0) + } + + objs := o.([]interface{}) + if len(objs) == 0 || objs[0] == nil { + return make([]compute.NetworkFirewallPolicyRuleTargetSecureTags, 0) + } + + items := make([]compute.NetworkFirewallPolicyRuleTargetSecureTags, 0, len(objs)) + for _, item := range objs { + i := expandComputeRegionNetworkFirewallPolicyRuleTargetSecureTags(item) + items = append(items, *i) + } + + return items +} + +func expandComputeRegionNetworkFirewallPolicyRuleTargetSecureTags(o interface{}) *compute.NetworkFirewallPolicyRuleTargetSecureTags { + if o == nil { + return compute.EmptyNetworkFirewallPolicyRuleTargetSecureTags + } + + obj := o.(map[string]interface{}) + return &compute.NetworkFirewallPolicyRuleTargetSecureTags{ + Name: dcl.String(obj["name"].(string)), + } +} + +func flattenComputeRegionNetworkFirewallPolicyRuleTargetSecureTagsArray(objs []compute.NetworkFirewallPolicyRuleTargetSecureTags) []interface{} { + if objs == nil { + return nil + } + + items := []interface{}{} + for _, item := range objs { + i := flattenComputeRegionNetworkFirewallPolicyRuleTargetSecureTags(&item) + items = append(items, i) + } + + return items +} + +func flattenComputeRegionNetworkFirewallPolicyRuleTargetSecureTags(obj *compute.NetworkFirewallPolicyRuleTargetSecureTags) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "name": obj.Name, + "state": obj.State, + } + + return transformed + +} diff --git a/google/resource_compute_region_network_firewall_policy_rule_generated_test.go b/google/resource_compute_region_network_firewall_policy_rule_generated_test.go new file mode 100644 index 0000000000..ba645cd6b3 --- /dev/null +++ b/google/resource_compute_region_network_firewall_policy_rule_generated_test.go @@ -0,0 +1,211 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: DCL *** +// +// ---------------------------------------------------------------------------- +// +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. +// +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "context" + "fmt" + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "strings" + "testing" +) + +func TestAccComputeRegionNetworkFirewallPolicyRule_RegionalHandWritten(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": getTestOrgFromEnv(t), + "project_name": getTestProjectFromEnv(), + "region": getTestRegionFromEnv(), + "service_acct": getTestServiceAccountFromEnv(t), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionNetworkFirewallPolicyRuleDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionNetworkFirewallPolicyRule_RegionalHandWritten(context), + }, + { + ResourceName: "google_compute_region_network_firewall_policy_rule.primary", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeRegionNetworkFirewallPolicyRule_RegionalHandWrittenUpdate0(context), + }, + { + ResourceName: "google_compute_region_network_firewall_policy_rule.primary", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeRegionNetworkFirewallPolicyRule_RegionalHandWritten(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_network_firewall_policy" "basic_regional_network_firewall_policy" { + name = "tf-test-policy%{random_suffix}" + project = "%{project_name}" + description = "Sample regional network firewall policy" + region = "%{region}" +} + +resource "google_compute_region_network_firewall_policy_rule" "primary" { + firewall_policy = google_compute_region_network_firewall_policy.basic_regional_network_firewall_policy.name + action = "allow" + direction = "INGRESS" + priority = 1000 + rule_name = "test-rule" + description = "This is a simple rule description" +match { + src_secure_tags { + name = "tagValues/${google_tags_tag_value.basic_value.name}" + } + src_ip_ranges = ["10.100.0.1/32"] +layer4_configs { +ip_protocol = "all" + } + } + target_service_accounts = ["%{service_acct}"] + region = "%{region}" + enable_logging = true + disabled = false +} + +resource "google_compute_network" "basic_network" { + name = "tf-test-network%{random_suffix}" +} +resource "google_tags_tag_key" "basic_key" { + parent = "organizations/%{org_id}" + short_name = "tf-test-tagkey%{random_suffix}" + purpose = "GCE_FIREWALL" + purpose_data = { + network= "%{project_name}/${google_compute_network.basic_network.name}" + } + description = "For keyname resources." +} + + +resource "google_tags_tag_value" "basic_value" { + parent = "tagKeys/${google_tags_tag_key.basic_key.name}" + short_name = "tf-test-tagvalue%{random_suffix}" + description = "For valuename resources." +} + +`, context) +} + +func testAccComputeRegionNetworkFirewallPolicyRule_RegionalHandWrittenUpdate0(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_network_firewall_policy" "basic_regional_network_firewall_policy" { + name = "tf-test-policy%{random_suffix}" + project = "%{project_name}" + description = "Sample regional network firewall policy" + region = "%{region}" +} + +resource "google_compute_region_network_firewall_policy_rule" "primary" { + firewall_policy = google_compute_region_network_firewall_policy.basic_regional_network_firewall_policy.name + action = "deny" + direction = "EGRESS" + priority = 1000 + rule_name = "updated-test-rule" + description = "This is an updated rule description" +match { +layer4_configs { +ip_protocol = "tcp" +ports = ["123"] + } + dest_ip_ranges = ["0.0.0.0/0"] + } + target_secure_tags { + name = "tagValues/${google_tags_tag_value.basic_value.name}" + } + region = "%{region}" + enable_logging = false + disabled = true +} + +resource "google_compute_network" "basic_network" { + name = "tf-test-network%{random_suffix}" +} +resource "google_tags_tag_key" "basic_key" { + parent = "organizations/%{org_id}" + short_name = "tf-test-tagkey%{random_suffix}" + purpose = "GCE_FIREWALL" + purpose_data = { + network= "%{project_name}/${google_compute_network.basic_network.name}" + } + description = "For keyname resources." +} + + +resource "google_tags_tag_value" "basic_value" { + parent = "tagKeys/${google_tags_tag_key.basic_key.name}" + short_name = "tf-test-tagvalue%{random_suffix}" + description = "For valuename resources." +} + +`, context) +} + +func testAccCheckComputeRegionNetworkFirewallPolicyRuleDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "rs.google_compute_region_network_firewall_policy_rule" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + billingProject := "" + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + obj := &compute.NetworkFirewallPolicyRule{ + Action: dcl.String(rs.Primary.Attributes["action"]), + Direction: compute.NetworkFirewallPolicyRuleDirectionEnumRef(rs.Primary.Attributes["direction"]), + FirewallPolicy: dcl.String(rs.Primary.Attributes["firewall_policy"]), + Description: dcl.String(rs.Primary.Attributes["description"]), + Disabled: dcl.Bool(rs.Primary.Attributes["disabled"] == "true"), + EnableLogging: dcl.Bool(rs.Primary.Attributes["enable_logging"] == "true"), + Project: dcl.StringOrNil(rs.Primary.Attributes["project"]), + Location: dcl.StringOrNil(rs.Primary.Attributes["region"]), + RuleName: dcl.String(rs.Primary.Attributes["rule_name"]), + Kind: dcl.StringOrNil(rs.Primary.Attributes["kind"]), + } + + client := NewDCLComputeClient(config, config.userAgent, billingProject, 0) + _, err := client.GetNetworkFirewallPolicyRule(context.Background(), obj) + if err == nil { + return fmt.Errorf("google_compute_region_network_firewall_policy_rule still exists %v", obj) + } + } + return nil + } +} diff --git a/website/docs/r/compute_network_firewall_policy_rule.html.markdown b/website/docs/r/compute_network_firewall_policy_rule.html.markdown new file mode 100644 index 0000000000..392f45d444 --- /dev/null +++ b/website/docs/r/compute_network_firewall_policy_rule.html.markdown @@ -0,0 +1,212 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: DCL *** +# +# ---------------------------------------------------------------------------- +# +# This file is managed by Magic Modules (https:#github.com/GoogleCloudPlatform/magic-modules) +# and is based on the DCL (https:#github.com/GoogleCloudPlatform/declarative-resource-client-library). +# Changes will need to be made to the DCL or Magic Modules instead of here. +# +# We are not currently able to accept contributions to this file. If changes +# are required, please file an issue at https:#github.com/hashicorp/terraform-provider-google/issues/new/choose +# +# ---------------------------------------------------------------------------- +subcategory: "Compute Engine" +page_title: "Google: google_compute_network_firewall_policy_rule" +description: |- + The Compute NetworkFirewallPolicyRule resource +--- + +# google_compute_network_firewall_policy_rule + +The Compute NetworkFirewallPolicyRule resource + +## Example Usage - global +```hcl +resource "google_compute_network_firewall_policy" "basic_network_firewall_policy" { + name = "policy" + project = "my-project-name" + description = "Sample global network firewall policy" +} + +resource "google_compute_network_firewall_policy_rule" "primary" { + firewall_policy = google_compute_network_firewall_policy.basic_network_firewall_policy.name + action = "allow" + direction = "INGRESS" + priority = 1000 + rule_name = "test-rule" + description = "This is a simple rule description" +match { + src_secure_tags { + name = "tagValues/${google_tags_tag_value.basic_value.name}" + } + src_ip_ranges = ["10.100.0.1/32"] +layer4_configs { +ip_protocol = "all" + } + } + target_service_accounts = ["emailAddress:my@service-account.com"] + enable_logging = true + disabled = false +} +resource "google_compute_network" "basic_network" { + name = "network" +} +resource "google_tags_tag_key" "basic_key" { + parent = "organizations/123456789" + short_name = "tagkey" + purpose = "GCE_FIREWALL" + purpose_data = { + network= "my-project-name/${google_compute_network.basic_network.name}" + } + description = "For keyname resources." +} + + +resource "google_tags_tag_value" "basic_value" { + parent = "tagKeys/${google_tags_tag_key.basic_key.name}" + short_name = "tagvalue" + description = "For valuename resources." +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `action` - + (Required) + The Action to perform when the client connection triggers the rule. Can currently be either "allow" or "deny()" where valid values for status are 403, 404, and 502. + +* `direction` - + (Required) + The direction in which this rule applies. Possible values: INGRESS, EGRESS + +* `firewall_policy` - + (Required) + The firewall policy of the resource. + +* `match` - + (Required) + A match condition that incoming traffic is evaluated against. If it evaluates to true, the corresponding 'action' is enforced. + +* `priority` - + (Required) + An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest prority. + + + +The `match` block supports: + +* `dest_ip_ranges` - + (Optional) + CIDR IP address range. Maximum number of destination CIDR IP ranges allowed is 5000. + +* `layer4_configs` - + (Required) + Pairs of IP protocols and ports that the rule should match. + +* `src_ip_ranges` - + (Optional) + CIDR IP address range. Maximum number of source CIDR IP ranges allowed is 5000. + +* `src_secure_tags` - + (Optional) + List of secure tag values, which should be matched at the source of the traffic. For INGRESS rule, if all the srcSecureTag are INEFFECTIVE, and there is no srcIpRange, this rule will be ignored. Maximum number of source tag values allowed is 256. + +The `layer4_configs` block supports: + +* `ip_protocol` - + (Required) + 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. + +* `ports` - + (Optional) + 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: ``. + +- - - + +* `description` - + (Optional) + An optional description for this resource. + +* `disabled` - + (Optional) + 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. + +* `enable_logging` - + (Optional) + Denotes whether to enable logging for a particular rule. If logging is enabled, logs will be exported to the configured export destination in Stackdriver. Logs may be exported to BigQuery or Pub/Sub. Note: you cannot enable logging on "goto_next" rules. + +* `project` - + (Optional) + The project for the resource + +* `rule_name` - + (Optional) + An optional name for the rule. This field is not a unique identifier and can be updated. + +* `target_secure_tags` - + (Optional) + A list of secure tags that controls which instances the firewall rule applies to. If targetSecureTag are specified, then the firewall rule applies only to instances in the VPC network that have one of those EFFECTIVE secure tags, if all the target_secure_tag are in INEFFECTIVE state, then this rule will be ignored. targetSecureTag may not be set at the same time as targetServiceAccounts. If neither targetServiceAccounts nor targetSecureTag are specified, the firewall rule applies to all instances on the specified network. Maximum number of target label tags allowed is 256. + +* `target_service_accounts` - + (Optional) + A list of service accounts indicating the sets of instances that are applied with this rule. + + + +The `src_secure_tags` block supports: + +* `name` - + (Required) + Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+ + +* `state` - + [Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted. + +The `target_secure_tags` block supports: + +* `name` - + (Required) + Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+ + +* `state` - + [Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/rules/{{priority}}` + +* `kind` - + Type of the resource. Always `compute#firewallPolicyRule` for firewall policy rules + +* `rule_tuple_count` - + Calculation of the complexity of a single firewall policy rule. + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + +NetworkFirewallPolicyRule can be imported using any of these accepted formats: + +``` +$ terraform import google_compute_network_firewall_policy_rule.default projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/rules/{{priority}} +$ terraform import google_compute_network_firewall_policy_rule.default {{project}}/{{firewall_policy}}/{{priority}} +$ terraform import google_compute_network_firewall_policy_rule.default {{firewall_policy}}/{{priority}} +``` + + + diff --git a/website/docs/r/compute_region_network_firewall_policy_rule.html.markdown b/website/docs/r/compute_region_network_firewall_policy_rule.html.markdown new file mode 100644 index 0000000000..3b202cc507 --- /dev/null +++ b/website/docs/r/compute_region_network_firewall_policy_rule.html.markdown @@ -0,0 +1,220 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: DCL *** +# +# ---------------------------------------------------------------------------- +# +# This file is managed by Magic Modules (https:#github.com/GoogleCloudPlatform/magic-modules) +# and is based on the DCL (https:#github.com/GoogleCloudPlatform/declarative-resource-client-library). +# Changes will need to be made to the DCL or Magic Modules instead of here. +# +# We are not currently able to accept contributions to this file. If changes +# are required, please file an issue at https:#github.com/hashicorp/terraform-provider-google/issues/new/choose +# +# ---------------------------------------------------------------------------- +subcategory: "Compute Engine" +page_title: "Google: google_compute_region_network_firewall_policy_rule" +description: |- + The Compute NetworkFirewallPolicyRule resource +--- + +# google_compute_region_network_firewall_policy_rule + +The Compute NetworkFirewallPolicyRule resource + +## Example Usage - regional +```hcl +resource "google_compute_region_network_firewall_policy" "basic_regional_network_firewall_policy" { + name = "policy" + project = "my-project-name" + description = "Sample regional network firewall policy" + region = "us-west1" +} + +resource "google_compute_region_network_firewall_policy_rule" "primary" { + firewall_policy = google_compute_region_network_firewall_policy.basic_regional_network_firewall_policy.name + action = "allow" + direction = "INGRESS" + priority = 1000 + rule_name = "test-rule" + description = "This is a simple rule description" +match { + src_secure_tags { + name = "tagValues/${google_tags_tag_value.basic_value.name}" + } + src_ip_ranges = ["10.100.0.1/32"] +layer4_configs { +ip_protocol = "all" + } + } + target_service_accounts = ["emailAddress:my@service-account.com"] + region = "us-west1" + enable_logging = true + disabled = false +} + +resource "google_compute_network" "basic_network" { + name = "network" +} +resource "google_tags_tag_key" "basic_key" { + parent = "organizations/123456789" + short_name = "tagkey" + purpose = "GCE_FIREWALL" + purpose_data = { + network= "my-project-name/${google_compute_network.basic_network.name}" + } + description = "For keyname resources." +} + + +resource "google_tags_tag_value" "basic_value" { + parent = "tagKeys/${google_tags_tag_key.basic_key.name}" + short_name = "tagvalue" + description = "For valuename resources." +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `action` - + (Required) + The Action to perform when the client connection triggers the rule. Can currently be either "allow" or "deny()" where valid values for status are 403, 404, and 502. + +* `direction` - + (Required) + The direction in which this rule applies. Possible values: INGRESS, EGRESS + +* `firewall_policy` - + (Required) + The firewall policy of the resource. + +* `match` - + (Required) + A match condition that incoming traffic is evaluated against. If it evaluates to true, the corresponding 'action' is enforced. + +* `priority` - + (Required) + An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest prority. + + + +The `match` block supports: + +* `dest_ip_ranges` - + (Optional) + CIDR IP address range. Maximum number of destination CIDR IP ranges allowed is 5000. + +* `layer4_configs` - + (Required) + Pairs of IP protocols and ports that the rule should match. + +* `src_ip_ranges` - + (Optional) + CIDR IP address range. Maximum number of source CIDR IP ranges allowed is 5000. + +* `src_secure_tags` - + (Optional) + List of secure tag values, which should be matched at the source of the traffic. For INGRESS rule, if all the srcSecureTag are INEFFECTIVE, and there is no srcIpRange, this rule will be ignored. Maximum number of source tag values allowed is 256. + +The `layer4_configs` block supports: + +* `ip_protocol` - + (Required) + 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. + +* `ports` - + (Optional) + 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: ``. + +- - - + +* `description` - + (Optional) + An optional description for this resource. + +* `disabled` - + (Optional) + 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. + +* `enable_logging` - + (Optional) + Denotes whether to enable logging for a particular rule. If logging is enabled, logs will be exported to the configured export destination in Stackdriver. Logs may be exported to BigQuery or Pub/Sub. Note: you cannot enable logging on "goto_next" rules. + +* `region` - + (Optional) + The location of this resource. + +* `project` - + (Optional) + The project for the resource + +* `rule_name` - + (Optional) + An optional name for the rule. This field is not a unique identifier and can be updated. + +* `target_secure_tags` - + (Optional) + A list of secure tags that controls which instances the firewall rule applies to. If targetSecureTag are specified, then the firewall rule applies only to instances in the VPC network that have one of those EFFECTIVE secure tags, if all the target_secure_tag are in INEFFECTIVE state, then this rule will be ignored. targetSecureTag may not be set at the same time as targetServiceAccounts. If neither targetServiceAccounts nor targetSecureTag are specified, the firewall rule applies to all instances on the specified network. Maximum number of target label tags allowed is 256. + +* `target_service_accounts` - + (Optional) + A list of service accounts indicating the sets of instances that are applied with this rule. + + + +The `src_secure_tags` block supports: + +* `name` - + (Required) + Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+ + +* `state` - + [Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted. + +The `target_secure_tags` block supports: + +* `name` - + (Required) + Name of the secure tag, created with TagManager's TagValue API. @pattern tagValues/[0-9]+ + +* `state` - + [Output Only] State of the secure tag, either `EFFECTIVE` or `INEFFECTIVE`. A secure tag is `INEFFECTIVE` when it is deleted or its network is deleted. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}}` + +* `kind` - + Type of the resource. Always `compute#firewallPolicyRule` for firewall policy rules + +* `rule_tuple_count` - + Calculation of the complexity of a single firewall policy rule. + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + +NetworkFirewallPolicyRule can be imported using any of these accepted formats: + +``` +$ terraform import google_compute_region_network_firewall_policy_rule.default projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}} +$ terraform import google_compute_region_network_firewall_policy_rule.default {{project}}/{{region}}/{{firewall_policy}}/{{priority}} +$ terraform import google_compute_region_network_firewall_policy_rule.default {{region}}/{{firewall_policy}}/{{priority}} +$ terraform import google_compute_region_network_firewall_policy_rule.default {{firewall_policy}}/{{priority}} +``` + + +