diff --git a/google/provider/provider_mmv1_resources.go b/google/provider/provider_mmv1_resources.go index cddbfdffca7..f8316739e33 100644 --- a/google/provider/provider_mmv1_resources.go +++ b/google/provider/provider_mmv1_resources.go @@ -405,9 +405,9 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{ } // Resources -// Generated resources: 404 +// Generated resources: 409 // Generated IAM resources: 234 -// Total generated resources: 638 +// Total generated resources: 643 var generatedResources = map[string]*schema.Resource{ "google_folder_access_approval_settings": accessapproval.ResourceAccessApprovalFolderSettings(), "google_organization_access_approval_settings": accessapproval.ResourceAccessApprovalOrganizationSettings(), @@ -900,11 +900,16 @@ var generatedResources = map[string]*schema.Resource{ "google_network_connectivity_service_connection_policy": networkconnectivity.ResourceNetworkConnectivityServiceConnectionPolicy(), "google_network_management_connectivity_test": networkmanagement.ResourceNetworkManagementConnectivityTest(), "google_network_security_address_group": networksecurity.ResourceNetworkSecurityAddressGroup(), + "google_network_security_firewall_endpoint": networksecurity.ResourceNetworkSecurityFirewallEndpoint(), + "google_network_security_firewall_endpoint_association": networksecurity.ResourceNetworkSecurityFirewallEndpointAssociation(), "google_network_security_gateway_security_policy": networksecurity.ResourceNetworkSecurityGatewaySecurityPolicy(), "google_network_security_gateway_security_policy_rule": networksecurity.ResourceNetworkSecurityGatewaySecurityPolicyRule(), "google_network_security_address_group_iam_binding": tpgiamresource.ResourceIamBinding(networksecurity.NetworkSecurityProjectAddressGroupIamSchema, networksecurity.NetworkSecurityProjectAddressGroupIamUpdaterProducer, networksecurity.NetworkSecurityProjectAddressGroupIdParseFunc), "google_network_security_address_group_iam_member": tpgiamresource.ResourceIamMember(networksecurity.NetworkSecurityProjectAddressGroupIamSchema, networksecurity.NetworkSecurityProjectAddressGroupIamUpdaterProducer, networksecurity.NetworkSecurityProjectAddressGroupIdParseFunc), "google_network_security_address_group_iam_policy": tpgiamresource.ResourceIamPolicy(networksecurity.NetworkSecurityProjectAddressGroupIamSchema, networksecurity.NetworkSecurityProjectAddressGroupIamUpdaterProducer, networksecurity.NetworkSecurityProjectAddressGroupIdParseFunc), + "google_network_security_security_profile": networksecurity.ResourceNetworkSecuritySecurityProfile(), + "google_network_security_security_profile_group": networksecurity.ResourceNetworkSecuritySecurityProfileGroup(), + "google_network_security_tls_inspection_policy": networksecurity.ResourceNetworkSecurityTlsInspectionPolicy(), "google_network_security_url_lists": networksecurity.ResourceNetworkSecurityUrlLists(), "google_network_services_edge_cache_keyset": networkservices.ResourceNetworkServicesEdgeCacheKeyset(), "google_network_services_edge_cache_origin": networkservices.ResourceNetworkServicesEdgeCacheOrigin(), diff --git a/google/services/networksecurity/resource_network_security_firewall_endpoint.go b/google/services/networksecurity/resource_network_security_firewall_endpoint.go new file mode 100644 index 00000000000..3f3b0c859b9 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_firewall_endpoint.go @@ -0,0 +1,510 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "fmt" + "log" + "net/http" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func ResourceNetworkSecurityFirewallEndpoint() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkSecurityFirewallEndpointCreate, + Read: resourceNetworkSecurityFirewallEndpointRead, + Update: resourceNetworkSecurityFirewallEndpointUpdate, + Delete: resourceNetworkSecurityFirewallEndpointDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkSecurityFirewallEndpointImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(60 * time.Minute), + Update: schema.DefaultTimeout(60 * time.Minute), + Delete: schema.DefaultTimeout(60 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, + ), + + Schema: map[string]*schema.Schema{ + "billing_project_id": { + Type: schema.TypeString, + Required: true, + Description: `Project to bill on endpoint uptime usage.`, + }, + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The location (zone) of the firewall endpoint.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the firewall endpoint resource.`, + }, + "parent": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the parent this firewall endpoint belongs to. +Format: organizations/{organization_id}.`, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `A map of key/value label pairs to assign to the resource. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "associated_networks": { + Type: schema.TypeList, + Computed: true, + Description: `List of networks that are associated with this endpoint in the local zone. +This is a projection of the FirewallEndpointAssociations pointing at this +endpoint. A network will only appear in this list after traffic routing is +fully configured. Format: projects/{project}/global/networks/{name}.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the firewall endpoint was created in UTC.`, + }, + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "reconciling": { + Type: schema.TypeBool, + Computed: true, + Description: `Whether reconciling is in progress, recommended per https://google.aip.dev/128.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `Server-defined URL of this resource.`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `The current state of the endpoint.`, + }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource + and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the firewall endpoint was updated in UTC.`, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkSecurityFirewallEndpointCreate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + billingProjectIdProp, err := expandNetworkSecurityFirewallEndpointBillingProjectId(d.Get("billing_project_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("billing_project_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(billingProjectIdProp)) && (ok || !reflect.DeepEqual(v, billingProjectIdProp)) { + obj["billingProjectId"] = billingProjectIdProp + } + labelsProp, err := expandNetworkSecurityFirewallEndpointEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpoints?firewallEndpointId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new FirewallEndpoint: %#v", obj) + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating FirewallEndpoint: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/firewallEndpoints/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Creating FirewallEndpoint", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create FirewallEndpoint: %s", err) + } + + log.Printf("[DEBUG] Finished creating FirewallEndpoint %q: %#v", d.Id(), res) + + return resourceNetworkSecurityFirewallEndpointRead(d, meta) +} + +func resourceNetworkSecurityFirewallEndpointRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpoints/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + 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("NetworkSecurityFirewallEndpoint %q", d.Id())) + } + + if err := d.Set("labels", flattenNetworkSecurityFirewallEndpointLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("self_link", flattenNetworkSecurityFirewallEndpointSelfLink(res["selfLink"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("create_time", flattenNetworkSecurityFirewallEndpointCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("update_time", flattenNetworkSecurityFirewallEndpointUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("reconciling", flattenNetworkSecurityFirewallEndpointReconciling(res["reconciling"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("associated_networks", flattenNetworkSecurityFirewallEndpointAssociatedNetworks(res["associatedNetworks"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("state", flattenNetworkSecurityFirewallEndpointState(res["state"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("billing_project_id", flattenNetworkSecurityFirewallEndpointBillingProjectId(res["billingProjectId"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("terraform_labels", flattenNetworkSecurityFirewallEndpointTerraformLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + if err := d.Set("effective_labels", flattenNetworkSecurityFirewallEndpointEffectiveLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpoint: %s", err) + } + + return nil +} + +func resourceNetworkSecurityFirewallEndpointUpdate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + obj := make(map[string]interface{}) + billingProjectIdProp, err := expandNetworkSecurityFirewallEndpointBillingProjectId(d.Get("billing_project_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("billing_project_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, billingProjectIdProp)) { + obj["billingProjectId"] = billingProjectIdProp + } + labelsProp, err := expandNetworkSecurityFirewallEndpointEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpoints/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating FirewallEndpoint %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("billing_project_id") { + updateMask = append(updateMask, "billingProjectId") + } + + if d.HasChange("effective_labels") { + updateMask = append(updateMask, "labels") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + Headers: headers, + }) + + if err != nil { + return fmt.Errorf("Error updating FirewallEndpoint %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating FirewallEndpoint %q: %#v", d.Id(), res) + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Updating FirewallEndpoint", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceNetworkSecurityFirewallEndpointRead(d, meta) +} + +func resourceNetworkSecurityFirewallEndpointDelete(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpoints/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting FirewallEndpoint %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "FirewallEndpoint") + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Deleting FirewallEndpoint", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting FirewallEndpoint %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkSecurityFirewallEndpointImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^(?P.+)/locations/(?P[^/]+)/firewallEndpoints/(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/firewallEndpoints/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkSecurityFirewallEndpointLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecurityFirewallEndpointSelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointReconciling(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociatedNetworks(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointBillingProjectId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("terraform_labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecurityFirewallEndpointEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNetworkSecurityFirewallEndpointBillingProjectId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityFirewallEndpointEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} diff --git a/google/services/networksecurity/resource_network_security_firewall_endpoint_association.go b/google/services/networksecurity/resource_network_security_firewall_endpoint_association.go new file mode 100644 index 00000000000..22d6e335612 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_firewall_endpoint_association.go @@ -0,0 +1,592 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "fmt" + "log" + "net/http" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func ResourceNetworkSecurityFirewallEndpointAssociation() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkSecurityFirewallEndpointAssociationCreate, + Read: resourceNetworkSecurityFirewallEndpointAssociationRead, + Update: resourceNetworkSecurityFirewallEndpointAssociationUpdate, + Delete: resourceNetworkSecurityFirewallEndpointAssociationDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkSecurityFirewallEndpointAssociationImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, + ), + + Schema: map[string]*schema.Schema{ + "firewall_endpoint": { + Type: schema.TypeString, + Required: true, + Description: `The URL of the firewall endpoint that is being associated.`, + }, + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The location (zone) of the firewall endpoint association.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the firewall endpoint association resource.`, + }, + "network": { + Type: schema.TypeString, + Required: true, + Description: `The URL of the network that is being associated.`, + }, + "disabled": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether the association is disabled. True indicates that traffic will not be intercepted. + +~> **Note:** The API will reject the request if this value is set to true when creating the resource, +otherwise on an update the association can be disabled.`, + Default: false, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `A map of key/value label pairs to assign to the resource. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "parent": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The name of the parent this firewall endpoint association belongs to. +Format: projects/{project_id}.`, + }, + "tls_inspection_policy": { + Type: schema.TypeString, + Optional: true, + Description: `The URL of the TlsInspectionPolicy that is being associated.`, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the firewall endpoint was created in UTC.`, + }, + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "reconciling": { + Type: schema.TypeBool, + Computed: true, + Description: `Whether reconciling is in progress, recommended per https://google.aip.dev/128.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `Server-defined URL of this resource.`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `The current state of the endpoint.`, + }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource + and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the firewall endpoint was updated in UTC.`, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkSecurityFirewallEndpointAssociationCreate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + firewallEndpointProp, err := expandNetworkSecurityFirewallEndpointAssociationFirewallEndpoint(d.Get("firewall_endpoint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("firewall_endpoint"); !tpgresource.IsEmptyValue(reflect.ValueOf(firewallEndpointProp)) && (ok || !reflect.DeepEqual(v, firewallEndpointProp)) { + obj["firewallEndpoint"] = firewallEndpointProp + } + networkProp, err := expandNetworkSecurityFirewallEndpointAssociationNetwork(d.Get("network"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("network"); !tpgresource.IsEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } + tlsInspectionPolicyProp, err := expandNetworkSecurityFirewallEndpointAssociationTlsInspectionPolicy(d.Get("tls_inspection_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("tls_inspection_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(tlsInspectionPolicyProp)) && (ok || !reflect.DeepEqual(v, tlsInspectionPolicyProp)) { + obj["tlsInspectionPolicy"] = tlsInspectionPolicyProp + } + disabledProp, err := expandNetworkSecurityFirewallEndpointAssociationDisabled(d.Get("disabled"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("disabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(disabledProp)) && (ok || !reflect.DeepEqual(v, disabledProp)) { + obj["disabled"] = disabledProp + } + labelsProp, err := expandNetworkSecurityFirewallEndpointAssociationEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpointAssociations?firewallEndpointAssociationId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new FirewallEndpointAssociation: %#v", obj) + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating FirewallEndpointAssociation: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Creating FirewallEndpointAssociation", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create FirewallEndpointAssociation: %s", err) + } + + log.Printf("[DEBUG] Finished creating FirewallEndpointAssociation %q: %#v", d.Id(), res) + + return resourceNetworkSecurityFirewallEndpointAssociationRead(d, meta) +} + +func resourceNetworkSecurityFirewallEndpointAssociationRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + 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("NetworkSecurityFirewallEndpointAssociation %q", d.Id())) + } + + if err := d.Set("firewall_endpoint", flattenNetworkSecurityFirewallEndpointAssociationFirewallEndpoint(res["firewallEndpoint"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("network", flattenNetworkSecurityFirewallEndpointAssociationNetwork(res["network"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("tls_inspection_policy", flattenNetworkSecurityFirewallEndpointAssociationTlsInspectionPolicy(res["tlsInspectionPolicy"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("labels", flattenNetworkSecurityFirewallEndpointAssociationLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("disabled", flattenNetworkSecurityFirewallEndpointAssociationDisabled(res["disabled"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("self_link", flattenNetworkSecurityFirewallEndpointAssociationSelfLink(res["selfLink"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("create_time", flattenNetworkSecurityFirewallEndpointAssociationCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("update_time", flattenNetworkSecurityFirewallEndpointAssociationUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("reconciling", flattenNetworkSecurityFirewallEndpointAssociationReconciling(res["reconciling"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("state", flattenNetworkSecurityFirewallEndpointAssociationState(res["state"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("terraform_labels", flattenNetworkSecurityFirewallEndpointAssociationTerraformLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + if err := d.Set("effective_labels", flattenNetworkSecurityFirewallEndpointAssociationEffectiveLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading FirewallEndpointAssociation: %s", err) + } + + return nil +} + +func resourceNetworkSecurityFirewallEndpointAssociationUpdate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + obj := make(map[string]interface{}) + firewallEndpointProp, err := expandNetworkSecurityFirewallEndpointAssociationFirewallEndpoint(d.Get("firewall_endpoint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("firewall_endpoint"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, firewallEndpointProp)) { + obj["firewallEndpoint"] = firewallEndpointProp + } + networkProp, err := expandNetworkSecurityFirewallEndpointAssociationNetwork(d.Get("network"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("network"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } + tlsInspectionPolicyProp, err := expandNetworkSecurityFirewallEndpointAssociationTlsInspectionPolicy(d.Get("tls_inspection_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("tls_inspection_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, tlsInspectionPolicyProp)) { + obj["tlsInspectionPolicy"] = tlsInspectionPolicyProp + } + disabledProp, err := expandNetworkSecurityFirewallEndpointAssociationDisabled(d.Get("disabled"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("disabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, disabledProp)) { + obj["disabled"] = disabledProp + } + labelsProp, err := expandNetworkSecurityFirewallEndpointAssociationEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating FirewallEndpointAssociation %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("firewall_endpoint") { + updateMask = append(updateMask, "firewallEndpoint") + } + + if d.HasChange("network") { + updateMask = append(updateMask, "network") + } + + if d.HasChange("tls_inspection_policy") { + updateMask = append(updateMask, "tlsInspectionPolicy") + } + + if d.HasChange("disabled") { + updateMask = append(updateMask, "disabled") + } + + if d.HasChange("effective_labels") { + updateMask = append(updateMask, "labels") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + Headers: headers, + }) + + if err != nil { + return fmt.Errorf("Error updating FirewallEndpointAssociation %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating FirewallEndpointAssociation %q: %#v", d.Id(), res) + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Updating FirewallEndpointAssociation", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceNetworkSecurityFirewallEndpointAssociationRead(d, meta) +} + +func resourceNetworkSecurityFirewallEndpointAssociationDelete(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting FirewallEndpointAssociation %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "FirewallEndpointAssociation") + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Deleting FirewallEndpointAssociation", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting FirewallEndpointAssociation %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkSecurityFirewallEndpointAssociationImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^(?P.+)/locations/(?P[^/]+)/firewallEndpointAssociations/(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkSecurityFirewallEndpointAssociationFirewallEndpoint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationTlsInspectionPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecurityFirewallEndpointAssociationDisabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationSelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationReconciling(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityFirewallEndpointAssociationTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("terraform_labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecurityFirewallEndpointAssociationEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNetworkSecurityFirewallEndpointAssociationFirewallEndpoint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityFirewallEndpointAssociationNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityFirewallEndpointAssociationTlsInspectionPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityFirewallEndpointAssociationDisabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityFirewallEndpointAssociationEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} diff --git a/google/services/networksecurity/resource_network_security_firewall_endpoint_association_sweeper.go b/google/services/networksecurity/resource_network_security_firewall_endpoint_association_sweeper.go new file mode 100644 index 00000000000..32cbc70c4e3 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_firewall_endpoint_association_sweeper.go @@ -0,0 +1,139 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkSecurityFirewallEndpointAssociation", testSweepNetworkSecurityFirewallEndpointAssociation) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkSecurityFirewallEndpointAssociation(region string) error { + resourceName := "NetworkSecurityFirewallEndpointAssociation" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}/firewallEndpointAssociations", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["firewallEndpointAssociations"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/google/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go b/google/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go index 8380ac5af78..f36f9bc0799 100644 --- a/google/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go +++ b/google/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go @@ -1,3 +1,222 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package networksecurity_test + +import ( + "fmt" + "strconv" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccNetworkSecurityFirewallEndpointAssociations_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "orgId": envvar.GetTestOrgFromEnv(t), + "randomSuffix": acctest.RandString(t, 10), + "billingProjectId": envvar.GetTestProjectFromEnv(), + "disabled": strconv.FormatBool(false), + } + + testResourceName := "google_network_security_firewall_endpoint_association.foobar" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_basic(context), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_update(context), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + +func TestAccNetworkSecurityFirewallEndpointAssociations_disabled(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "orgId": envvar.GetTestOrgFromEnv(t), + "randomSuffix": acctest.RandString(t, 10), + "billingProjectId": envvar.GetTestProjectFromEnv(), + } + + testResourceName := "google_network_security_firewall_endpoint_association.foobar" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(testResourceName, "disabled", "false"), + ), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_update(testContextMapDisabledField(context, true)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(testResourceName, "disabled", "true"), + ), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_update(testContextMapDisabledField(context, false)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(testResourceName, "disabled", "false"), + ), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + +func testContextMapDisabledField(context map[string]interface{}, disabled bool) map[string]interface{} { + context["disabled"] = strconv.FormatBool(disabled) + return context +} + +func testAccNetworkSecurityFirewallEndpointAssociation_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "foobar" { + provider = google-beta + name = "tf-test-my-vpc%{randomSuffix}" + auto_create_subnetworks = false +} + +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%{randomSuffix}" + parent = "organizations/%{orgId}" + location = "us-central1-a" + billing_project_id = "%{billingProjectId}" +} + +# TODO: add tlsInspectionPolicy once resource is ready +resource "google_network_security_firewall_endpoint_association" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint-association%{randomSuffix}" + parent = "projects/%{billingProjectId}" + location = "us-central1-a" + firewall_endpoint = google_network_security_firewall_endpoint.foobar.id + network = google_compute_network.foobar.id + + labels = { + foo = "bar" + } +} +`, context) +} + +func testAccNetworkSecurityFirewallEndpointAssociation_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "foobar" { + provider = google-beta + name = "tf-test-my-vpc%{randomSuffix}" + auto_create_subnetworks = false +} + +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%{randomSuffix}" + parent = "organizations/%{orgId}" + location = "us-central1-a" + billing_project_id = "%{billingProjectId}" +} + +# TODO: add tlsInspectionPolicy once resource is ready +resource "google_network_security_firewall_endpoint_association" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint-association%{randomSuffix}" + parent = "projects/%{billingProjectId}" + location = "us-central1-a" + firewall_endpoint = google_network_security_firewall_endpoint.foobar.id + network = google_compute_network.foobar.id + disabled = "%{disabled}" + + labels = { + foo = "bar-updated" + } +} +`, context) +} + +func testAccCheckNetworkSecurityFirewallEndpointAssociationDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_network_security_firewall_endpoint_association" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("NetworkSecurityFirewallEndpointAssociation still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/services/networksecurity/resource_network_security_firewall_endpoint_sweeper.go b/google/services/networksecurity/resource_network_security_firewall_endpoint_sweeper.go new file mode 100644 index 00000000000..ac2815565b6 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_firewall_endpoint_sweeper.go @@ -0,0 +1,139 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkSecurityFirewallEndpoint", testSweepNetworkSecurityFirewallEndpoint) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkSecurityFirewallEndpoint(region string) error { + resourceName := "NetworkSecurityFirewallEndpoint" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}/firewallEndpoints", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["firewallEndpoints"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}/firewallEndpoints/{{name}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/google/services/networksecurity/resource_network_security_firewall_endpoint_test.go b/google/services/networksecurity/resource_network_security_firewall_endpoint_test.go index 8380ac5af78..842b0acedda 100644 --- a/google/services/networksecurity/resource_network_security_firewall_endpoint_test.go +++ b/google/services/networksecurity/resource_network_security_firewall_endpoint_test.go @@ -1,3 +1,125 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package networksecurity_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + billingProjectId := envvar.GetTestProjectFromEnv() + orgId := envvar.GetTestOrgFromEnv(t) + randomSuffix := acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityFirewallEndpoints_basic(orgId, billingProjectId, randomSuffix), + }, + { + ResourceName: "google_network_security_firewall_endpoint.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecurityFirewallEndpoints_update(orgId, billingProjectId, randomSuffix), + }, + { + ResourceName: "google_network_security_firewall_endpoint.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecurityFirewallEndpoints_basic(orgId string, billingProjectId string, randomSuffix string) string { + return fmt.Sprintf(` +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar" + } +} +`, randomSuffix, orgId, billingProjectId) +} + +func testAccNetworkSecurityFirewallEndpoints_update(orgId string, billingProjectId string, randomSuffix string) string { + return fmt.Sprintf(` +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar-updated" + } +} +`, randomSuffix, orgId, billingProjectId) +} + +func testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_network_security_firewall_endpoint" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpoints/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("NetworkSecurityFirewallEndpoint still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/services/networksecurity/resource_network_security_security_profile.go b/google/services/networksecurity/resource_network_security_security_profile.go new file mode 100644 index 00000000000..ccbaf772c91 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_security_profile.go @@ -0,0 +1,771 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "fmt" + "log" + "net/http" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/verify" +) + +func ResourceNetworkSecuritySecurityProfile() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkSecuritySecurityProfileCreate, + Read: resourceNetworkSecuritySecurityProfileRead, + Update: resourceNetworkSecuritySecurityProfileUpdate, + Delete: resourceNetworkSecuritySecurityProfileDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkSecuritySecurityProfileImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, + ), + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the security profile resource.`, + }, + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"THREAT_PREVENTION"}), + Description: `The type of security profile. Possible values: ["THREAT_PREVENTION"]`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `An optional description of the security profile. The Max length is 512 characters.`, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `A map of key/value label pairs to assign to the resource. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "location": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The location of the security profile. +The default value is 'global'.`, + Default: "global", + }, + "parent": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The name of the parent this security profile belongs to. +Format: organizations/{organization_id}.`, + }, + "threat_prevention_profile": { + Type: schema.TypeList, + Optional: true, + Description: `The threat prevention configuration for the security profile.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "severity_overrides": { + Type: schema.TypeList, + Optional: true, + Description: `The configuration for overriding threats actions by severity match.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"ALERT", "ALLOW", "DEFAULT_ACTION", "DENY"}), + Description: `Threat action override. Possible values: ["ALERT", "ALLOW", "DEFAULT_ACTION", "DENY"]`, + }, + "severity": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"CRITICAL", "HIGH", "INFORMATIONAL", "LOW", "MEDIUM"}), + Description: `Severity level to match. Possible values: ["CRITICAL", "HIGH", "INFORMATIONAL", "LOW", "MEDIUM"]`, + }, + }, + }, + }, + "threat_overrides": { + Type: schema.TypeList, + Optional: true, + Description: `The configuration for overriding threats actions by threat id match. +If a threat is matched both by configuration provided in severity overrides +and threat overrides, the threat overrides action is applied.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"ALERT", "ALLOW", "DEFAULT_ACTION", "DENY"}), + Description: `Threat action. Possible values: ["ALERT", "ALLOW", "DEFAULT_ACTION", "DENY"]`, + }, + "threat_id": { + Type: schema.TypeString, + Required: true, + Description: `Vendor-specific ID of a threat to override.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `Type of threat.`, + }, + }, + }, + }, + }, + }, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the security profile was created in UTC.`, + }, + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "etag": { + Type: schema.TypeString, + Computed: true, + Description: `This checksum is computed by the server based on the value of other fields, +and may be sent on update and delete requests to ensure the client has an up-to-date +value before proceeding.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `Server-defined URL of this resource.`, + }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource + and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the security profile was updated in UTC.`, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkSecuritySecurityProfileCreate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkSecuritySecurityProfileDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + threatPreventionProfileProp, err := expandNetworkSecuritySecurityProfileThreatPreventionProfile(d.Get("threat_prevention_profile"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("threat_prevention_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(threatPreventionProfileProp)) && (ok || !reflect.DeepEqual(v, threatPreventionProfileProp)) { + obj["threatPreventionProfile"] = threatPreventionProfileProp + } + typeProp, err := expandNetworkSecuritySecurityProfileType(d.Get("type"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("type"); !tpgresource.IsEmptyValue(reflect.ValueOf(typeProp)) && (ok || !reflect.DeepEqual(v, typeProp)) { + obj["type"] = typeProp + } + labelsProp, err := expandNetworkSecuritySecurityProfileEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfiles?securityProfileId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new SecurityProfile: %#v", obj) + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating SecurityProfile: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/securityProfiles/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Creating SecurityProfile", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create SecurityProfile: %s", err) + } + + log.Printf("[DEBUG] Finished creating SecurityProfile %q: %#v", d.Id(), res) + + return resourceNetworkSecuritySecurityProfileRead(d, meta) +} + +func resourceNetworkSecuritySecurityProfileRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfiles/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + 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("NetworkSecuritySecurityProfile %q", d.Id())) + } + + if err := d.Set("self_link", flattenNetworkSecuritySecurityProfileSelfLink(res["selfLink"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("create_time", flattenNetworkSecuritySecurityProfileCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("update_time", flattenNetworkSecuritySecurityProfileUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("etag", flattenNetworkSecuritySecurityProfileEtag(res["etag"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("description", flattenNetworkSecuritySecurityProfileDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("labels", flattenNetworkSecuritySecurityProfileLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("threat_prevention_profile", flattenNetworkSecuritySecurityProfileThreatPreventionProfile(res["threatPreventionProfile"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("type", flattenNetworkSecuritySecurityProfileType(res["type"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("terraform_labels", flattenNetworkSecuritySecurityProfileTerraformLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + if err := d.Set("effective_labels", flattenNetworkSecuritySecurityProfileEffectiveLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfile: %s", err) + } + + return nil +} + +func resourceNetworkSecuritySecurityProfileUpdate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkSecuritySecurityProfileDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + threatPreventionProfileProp, err := expandNetworkSecuritySecurityProfileThreatPreventionProfile(d.Get("threat_prevention_profile"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("threat_prevention_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, threatPreventionProfileProp)) { + obj["threatPreventionProfile"] = threatPreventionProfileProp + } + labelsProp, err := expandNetworkSecuritySecurityProfileEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfiles/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating SecurityProfile %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("threat_prevention_profile") { + updateMask = append(updateMask, "threatPreventionProfile") + } + + if d.HasChange("effective_labels") { + updateMask = append(updateMask, "labels") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + Headers: headers, + }) + + if err != nil { + return fmt.Errorf("Error updating SecurityProfile %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating SecurityProfile %q: %#v", d.Id(), res) + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Updating SecurityProfile", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceNetworkSecuritySecurityProfileRead(d, meta) +} + +func resourceNetworkSecuritySecurityProfileDelete(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfiles/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting SecurityProfile %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "SecurityProfile") + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Deleting SecurityProfile", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting SecurityProfile %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkSecuritySecurityProfileImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^(?P.+)/locations/(?P[^/]+)/securityProfiles/(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/securityProfiles/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkSecuritySecurityProfileSelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileEtag(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecuritySecurityProfileThreatPreventionProfile(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["severity_overrides"] = + flattenNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverrides(original["severityOverrides"], d, config) + transformed["threat_overrides"] = + flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverrides(original["threatOverrides"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverrides(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "action": flattenNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesAction(original["action"], d, config), + "severity": flattenNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesSeverity(original["severity"], d, config), + }) + } + return transformed +} +func flattenNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesAction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesSeverity(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverrides(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "action": flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesAction(original["action"], d, config), + "threat_id": flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesThreatId(original["threatId"], d, config), + "type": flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesType(original["type"], d, config), + }) + } + return transformed +} +func flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesAction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesThreatId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("terraform_labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecuritySecurityProfileEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNetworkSecuritySecurityProfileDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfile(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedSeverityOverrides, err := expandNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverrides(original["severity_overrides"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSeverityOverrides); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["severityOverrides"] = transformedSeverityOverrides + } + + transformedThreatOverrides, err := expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverrides(original["threat_overrides"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedThreatOverrides); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["threatOverrides"] = transformedThreatOverrides + } + + return transformed, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverrides(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAction, err := expandNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesAction(original["action"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAction); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["action"] = transformedAction + } + + transformedSeverity, err := expandNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesSeverity(original["severity"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSeverity); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["severity"] = transformedSeverity + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesAction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfileSeverityOverridesSeverity(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverrides(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAction, err := expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesAction(original["action"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAction); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["action"] = transformedAction + } + + transformedThreatId, err := expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesThreatId(original["threat_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedThreatId); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["threatId"] = transformedThreatId + } + + transformedType, err := expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesType(original["type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["type"] = transformedType + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesAction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesThreatId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileThreatPreventionProfileThreatOverridesType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} diff --git a/google/services/networksecurity/resource_network_security_security_profile_generated_test.go b/google/services/networksecurity/resource_network_security_security_profile_generated_test.go new file mode 100644 index 00000000000..f4cb8df8e02 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_security_profile_generated_test.go @@ -0,0 +1,166 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileBasicExample(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.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkSecuritySecurityProfileDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileBasicExample(context), + }, + { + ResourceName: "google_network_security_security_profile.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "parent", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_network_security_security_profile" "default" { + name = "tf-test-my-security-profile%{random_suffix}" + parent = "organizations/%{org_id}" + description = "my description" + type = "THREAT_PREVENTION" + + labels = { + foo = "bar" + } +} +`, context) +} + +func TestAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileOverridesExample(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.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkSecuritySecurityProfileDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileOverridesExample(context), + }, + { + ResourceName: "google_network_security_security_profile.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "parent", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileOverridesExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_network_security_security_profile" "default" { + name = "tf-test-my-security-profile%{random_suffix}" + parent = "organizations/%{org_id}" + description = "my description" + type = "THREAT_PREVENTION" + + threat_prevention_profile { + severity_overrides { + action = "ALLOW" + severity = "INFORMATIONAL" + } + + severity_overrides { + action = "DENY" + severity = "HIGH" + } + + threat_overrides { + action = "ALLOW" + threat_id = "280647" + } + } +} +`, context) +} + +func testAccCheckNetworkSecuritySecurityProfileDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_network_security_security_profile" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfiles/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("NetworkSecuritySecurityProfile still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/services/networksecurity/resource_network_security_security_profile_group.go b/google/services/networksecurity/resource_network_security_security_profile_group.go new file mode 100644 index 00000000000..2df369da9d7 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_security_profile_group.go @@ -0,0 +1,504 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "fmt" + "log" + "net/http" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func ResourceNetworkSecuritySecurityProfileGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkSecuritySecurityProfileGroupCreate, + Read: resourceNetworkSecuritySecurityProfileGroupRead, + Update: resourceNetworkSecuritySecurityProfileGroupUpdate, + Delete: resourceNetworkSecuritySecurityProfileGroupDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkSecuritySecurityProfileGroupImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, + ), + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the security profile group resource.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `An optional description of the profile. The Max length is 512 characters.`, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `A map of key/value label pairs to assign to the resource. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "location": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The location of the security profile group. +The default value is 'global'.`, + Default: "global", + }, + "parent": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The name of the parent this security profile group belongs to. +Format: organizations/{organization_id}.`, + }, + "threat_prevention_profile": { + Type: schema.TypeString, + Optional: true, + Description: `Reference to a SecurityProfile with the threat prevention configuration for the SecurityProfileGroup.`, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the security profile group was created in UTC.`, + }, + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "etag": { + Type: schema.TypeString, + Computed: true, + Description: `This checksum is computed by the server based on the value of other fields, +and may be sent on update and delete requests to ensure the client has an up-to-date +value before proceeding.`, + }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource + and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the security profile group was updated in UTC.`, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkSecuritySecurityProfileGroupCreate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkSecuritySecurityProfileGroupDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + threatPreventionProfileProp, err := expandNetworkSecuritySecurityProfileGroupThreatPreventionProfile(d.Get("threat_prevention_profile"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("threat_prevention_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(threatPreventionProfileProp)) && (ok || !reflect.DeepEqual(v, threatPreventionProfileProp)) { + obj["threatPreventionProfile"] = threatPreventionProfileProp + } + labelsProp, err := expandNetworkSecuritySecurityProfileGroupEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfileGroups?securityProfileGroupId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new SecurityProfileGroup: %#v", obj) + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating SecurityProfileGroup: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/securityProfileGroups/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Creating SecurityProfileGroup", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create SecurityProfileGroup: %s", err) + } + + log.Printf("[DEBUG] Finished creating SecurityProfileGroup %q: %#v", d.Id(), res) + + return resourceNetworkSecuritySecurityProfileGroupRead(d, meta) +} + +func resourceNetworkSecuritySecurityProfileGroupRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfileGroups/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + 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("NetworkSecuritySecurityProfileGroup %q", d.Id())) + } + + if err := d.Set("create_time", flattenNetworkSecuritySecurityProfileGroupCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + if err := d.Set("update_time", flattenNetworkSecuritySecurityProfileGroupUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + if err := d.Set("etag", flattenNetworkSecuritySecurityProfileGroupEtag(res["etag"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + if err := d.Set("description", flattenNetworkSecuritySecurityProfileGroupDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + if err := d.Set("labels", flattenNetworkSecuritySecurityProfileGroupLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + if err := d.Set("threat_prevention_profile", flattenNetworkSecuritySecurityProfileGroupThreatPreventionProfile(res["threatPreventionProfile"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + if err := d.Set("terraform_labels", flattenNetworkSecuritySecurityProfileGroupTerraformLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + if err := d.Set("effective_labels", flattenNetworkSecuritySecurityProfileGroupEffectiveLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading SecurityProfileGroup: %s", err) + } + + return nil +} + +func resourceNetworkSecuritySecurityProfileGroupUpdate(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkSecuritySecurityProfileGroupDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + threatPreventionProfileProp, err := expandNetworkSecuritySecurityProfileGroupThreatPreventionProfile(d.Get("threat_prevention_profile"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("threat_prevention_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, threatPreventionProfileProp)) { + obj["threatPreventionProfile"] = threatPreventionProfileProp + } + labelsProp, err := expandNetworkSecuritySecurityProfileGroupEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfileGroups/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating SecurityProfileGroup %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("threat_prevention_profile") { + updateMask = append(updateMask, "threatPreventionProfile") + } + + if d.HasChange("effective_labels") { + updateMask = append(updateMask, "labels") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + Headers: headers, + }) + + if err != nil { + return fmt.Errorf("Error updating SecurityProfileGroup %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating SecurityProfileGroup %q: %#v", d.Id(), res) + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Updating SecurityProfileGroup", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceNetworkSecuritySecurityProfileGroupRead(d, meta) +} + +func resourceNetworkSecuritySecurityProfileGroupDelete(d *schema.ResourceData, meta interface{}) error { + var project string + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfileGroups/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting SecurityProfileGroup %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "SecurityProfileGroup") + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Deleting SecurityProfileGroup", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting SecurityProfileGroup %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkSecuritySecurityProfileGroupImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^(?P.+)/locations/(?P[^/]+)/securityProfileGroups/(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/locations/{{location}}/securityProfileGroups/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkSecuritySecurityProfileGroupCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileGroupUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileGroupEtag(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileGroupDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileGroupLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecuritySecurityProfileGroupThreatPreventionProfile(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecuritySecurityProfileGroupTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("terraform_labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkSecuritySecurityProfileGroupEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNetworkSecuritySecurityProfileGroupDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileGroupThreatPreventionProfile(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecuritySecurityProfileGroupEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} diff --git a/google/services/networksecurity/resource_network_security_security_profile_group_generated_test.go b/google/services/networksecurity/resource_network_security_security_profile_group_generated_test.go new file mode 100644 index 00000000000..3fc76e8e9b2 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_security_profile_group_generated_test.go @@ -0,0 +1,119 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccNetworkSecuritySecurityProfileGroup_networkSecuritySecurityProfileGroupBasicExample(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.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkSecuritySecurityProfileGroupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecuritySecurityProfileGroup_networkSecuritySecurityProfileGroupBasicExample(context), + }, + { + ResourceName: "google_network_security_security_profile_group.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "parent", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecuritySecurityProfileGroup_networkSecuritySecurityProfileGroupBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_network_security_security_profile_group" "default" { + name = "tf-test-sec-profile-group%{random_suffix}" + parent = "organizations/%{org_id}" + description = "my description" + threat_prevention_profile = google_network_security_security_profile.security_profile.id + + labels = { + foo = "bar" + } +} + +resource "google_network_security_security_profile" "security_profile" { + name = "tf-test-sec-profile%{random_suffix}" + type = "THREAT_PREVENTION" + parent = "organizations/%{org_id}" + location = "global" +} +`, context) +} + +func testAccCheckNetworkSecuritySecurityProfileGroupDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_network_security_security_profile_group" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/securityProfileGroups/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("NetworkSecuritySecurityProfileGroup still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/services/networksecurity/resource_network_security_security_profile_group_sweeper.go b/google/services/networksecurity/resource_network_security_security_profile_group_sweeper.go new file mode 100644 index 00000000000..bce207dd1a5 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_security_profile_group_sweeper.go @@ -0,0 +1,139 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkSecuritySecurityProfileGroup", testSweepNetworkSecuritySecurityProfileGroup) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkSecuritySecurityProfileGroup(region string) error { + resourceName := "NetworkSecuritySecurityProfileGroup" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}securityProfileGroups", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["securityProfileGroups"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}/securityProfileGroups/{{name}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/google/services/networksecurity/resource_network_security_security_profile_group_test.go b/google/services/networksecurity/resource_network_security_security_profile_group_test.go index 8380ac5af78..fdca60f226b 100644 --- a/google/services/networksecurity/resource_network_security_security_profile_group_test.go +++ b/google/services/networksecurity/resource_network_security_security_profile_group_test.go @@ -1,3 +1,103 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package networksecurity_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccNetworkSecuritySecurityProfileGroups_update(t *testing.T) { + t.Parallel() + + orgId := envvar.GetTestOrgFromEnv(t) + randomSuffix := acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkSecuritySecurityProfileGroupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecuritySecurityProfileGroups_basic(orgId, randomSuffix), + }, + { + ResourceName: "google_network_security_security_profile_group.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecuritySecurityProfileGroups_update(orgId, randomSuffix), + }, + { + ResourceName: "google_network_security_security_profile_group.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecuritySecurityProfileGroups_basic(orgId string, randomSuffix string) string { + return fmt.Sprintf(` +resource "google_network_security_security_profile" "foobar" { + provider = google-beta + name = "tf-test-my-security-profile%s" + type = "THREAT_PREVENTION" + parent = "organizations/%s" + location = "global" +} + +resource "google_network_security_security_profile_group" "foobar" { + provider = google-beta + name = "tf-test-my-security-profile-group%s" + parent = "organizations/%s" + location = "global" + description = "My security profile group." + threat_prevention_profile = google_network_security_security_profile.foobar.id + + labels = { + foo = "bar" + } +} +`, randomSuffix, orgId, randomSuffix, orgId) +} + +func testAccNetworkSecuritySecurityProfileGroups_update(orgId string, randomSuffix string) string { + return fmt.Sprintf(` +resource "google_network_security_security_profile" "foobar" { + provider = google-beta + name = "tf-test-my-security-profile%s" + type = "THREAT_PREVENTION" + parent = "organizations/%s" + location = "global" +} + +resource "google_network_security_security_profile" "foobar_updated" { + provider = google-beta + name = "tf-test-my-security-profile-updated%s" + type = "THREAT_PREVENTION" + parent = "organizations/%s" + location = "global" +} + +resource "google_network_security_security_profile_group" "foobar" { + provider = google-beta + name = "tf-test-my-security-profile-group%s" + parent = "organizations/%s" + location = "global" + description = "My security profile group. Update" + threat_prevention_profile = google_network_security_security_profile.foobar_updated.id + + labels = { + foo = "foo" + } +} +`, randomSuffix, orgId, randomSuffix, orgId, randomSuffix, orgId) +} diff --git a/google/services/networksecurity/resource_network_security_security_profile_sweeper.go b/google/services/networksecurity/resource_network_security_security_profile_sweeper.go new file mode 100644 index 00000000000..b338ec9dee5 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_security_profile_sweeper.go @@ -0,0 +1,139 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkSecuritySecurityProfile", testSweepNetworkSecuritySecurityProfile) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkSecuritySecurityProfile(region string) error { + resourceName := "NetworkSecuritySecurityProfile" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}/securityProfiles", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["securityProfiles"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://networksecurity.googleapis.com/v1/{{parent}}/locations/{{location}}/securityProfiles/{{name}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/google/services/networksecurity/resource_network_security_security_profile_test.go b/google/services/networksecurity/resource_network_security_security_profile_test.go index 8380ac5af78..d7550b60ed2 100644 --- a/google/services/networksecurity/resource_network_security_security_profile_test.go +++ b/google/services/networksecurity/resource_network_security_security_profile_test.go @@ -1,3 +1,91 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package networksecurity_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccNetworkSecuritySecurityProfiles_update(t *testing.T) { + t.Parallel() + + orgId := envvar.GetTestOrgFromEnv(t) + randomSuffix := acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkSecuritySecurityProfileDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecuritySecurityProfiles_basic(orgId, randomSuffix), + }, + { + ResourceName: "google_network_security_security_profile.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecuritySecurityProfiles_update(orgId, randomSuffix), + }, + { + ResourceName: "google_network_security_security_profile.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecuritySecurityProfiles_basic(orgId string, randomSuffix string) string { + return fmt.Sprintf(` +resource "google_network_security_security_profile" "foobar" { + provider = google-beta + name = "tf-test-my-security-profile%s" + parent = "organizations/%s" + location = "global" + description = "My security profile." + type = "THREAT_PREVENTION" + + labels = { + foo = "bar" + } +} +`, randomSuffix, orgId) +} + +func testAccNetworkSecuritySecurityProfiles_update(orgId string, randomSuffix string) string { + return fmt.Sprintf(` +resource "google_network_security_security_profile" "foobar" { + provider = google-beta + name = "tf-test-my-security-profile%s" + parent = "organizations/%s" + location = "global" + description = "My security profile. Update" + type = "THREAT_PREVENTION" + + labels = { + foo = "foo" + } + + threat_prevention_profile { + severity_overrides { + action = "ALLOW" + severity = "INFORMATIONAL" + } + + severity_overrides { + action = "DENY" + severity = "HIGH" + } + } +} +`, randomSuffix, orgId) +} diff --git a/google/services/networksecurity/resource_network_security_tls_inspection_policy.go b/google/services/networksecurity/resource_network_security_tls_inspection_policy.go new file mode 100644 index 00000000000..ebdfa7cdeb0 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_tls_inspection_policy.go @@ -0,0 +1,451 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "fmt" + "log" + "net/http" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func ResourceNetworkSecurityTlsInspectionPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkSecurityTlsInspectionPolicyCreate, + Read: resourceNetworkSecurityTlsInspectionPolicyRead, + Update: resourceNetworkSecurityTlsInspectionPolicyUpdate, + Delete: resourceNetworkSecurityTlsInspectionPolicyDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkSecurityTlsInspectionPolicyImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + + Schema: map[string]*schema.Schema{ + "ca_pool": { + Type: schema.TypeString, + Required: true, + Description: `A CA pool resource used to issue interception certificates.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: `Short name of the TlsInspectionPolicy resource to be created.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `Free-text description of the resource.`, + }, + "exclude_public_ca_set": { + Type: schema.TypeBool, + Optional: true, + Description: `If FALSE (the default), use our default set of public CAs in addition to any CAs specified in trustConfig. These public CAs are currently based on the Mozilla Root Program and are subject to change over time. If TRUE, do not accept our default set of public CAs. Only CAs specified in trustConfig will be accepted.`, + }, + "location": { + Type: schema.TypeString, + Optional: true, + Description: `The location of the tls inspection policy.`, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `The timestamp when the resource was created.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `The timestamp when the resource was updated.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkSecurityTlsInspectionPolicyCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkSecurityTlsInspectionPolicyDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + caPoolProp, err := expandNetworkSecurityTlsInspectionPolicyCaPool(d.Get("ca_pool"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ca_pool"); !tpgresource.IsEmptyValue(reflect.ValueOf(caPoolProp)) && (ok || !reflect.DeepEqual(v, caPoolProp)) { + obj["caPool"] = caPoolProp + } + excludePublicCaSetProp, err := expandNetworkSecurityTlsInspectionPolicyExcludePublicCaSet(d.Get("exclude_public_ca_set"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("exclude_public_ca_set"); !tpgresource.IsEmptyValue(reflect.ValueOf(excludePublicCaSetProp)) && (ok || !reflect.DeepEqual(v, excludePublicCaSetProp)) { + obj["excludePublicCaSet"] = excludePublicCaSetProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/tlsInspectionPolicies?tlsInspectionPolicyId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new TlsInspectionPolicy: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for TlsInspectionPolicy: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating TlsInspectionPolicy: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/tlsInspectionPolicies/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Creating TlsInspectionPolicy", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create TlsInspectionPolicy: %s", err) + } + + log.Printf("[DEBUG] Finished creating TlsInspectionPolicy %q: %#v", d.Id(), res) + + return resourceNetworkSecurityTlsInspectionPolicyRead(d, meta) +} + +func resourceNetworkSecurityTlsInspectionPolicyRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/tlsInspectionPolicies/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for TlsInspectionPolicy: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + 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("NetworkSecurityTlsInspectionPolicy %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading TlsInspectionPolicy: %s", err) + } + + if err := d.Set("create_time", flattenNetworkSecurityTlsInspectionPolicyCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading TlsInspectionPolicy: %s", err) + } + if err := d.Set("update_time", flattenNetworkSecurityTlsInspectionPolicyUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading TlsInspectionPolicy: %s", err) + } + if err := d.Set("description", flattenNetworkSecurityTlsInspectionPolicyDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading TlsInspectionPolicy: %s", err) + } + if err := d.Set("ca_pool", flattenNetworkSecurityTlsInspectionPolicyCaPool(res["caPool"], d, config)); err != nil { + return fmt.Errorf("Error reading TlsInspectionPolicy: %s", err) + } + if err := d.Set("exclude_public_ca_set", flattenNetworkSecurityTlsInspectionPolicyExcludePublicCaSet(res["excludePublicCaSet"], d, config)); err != nil { + return fmt.Errorf("Error reading TlsInspectionPolicy: %s", err) + } + + return nil +} + +func resourceNetworkSecurityTlsInspectionPolicyUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for TlsInspectionPolicy: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkSecurityTlsInspectionPolicyDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + caPoolProp, err := expandNetworkSecurityTlsInspectionPolicyCaPool(d.Get("ca_pool"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ca_pool"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, caPoolProp)) { + obj["caPool"] = caPoolProp + } + excludePublicCaSetProp, err := expandNetworkSecurityTlsInspectionPolicyExcludePublicCaSet(d.Get("exclude_public_ca_set"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("exclude_public_ca_set"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, excludePublicCaSetProp)) { + obj["excludePublicCaSet"] = excludePublicCaSetProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/tlsInspectionPolicies/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating TlsInspectionPolicy %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("ca_pool") { + updateMask = append(updateMask, "caPool") + } + + if d.HasChange("exclude_public_ca_set") { + updateMask = append(updateMask, "excludePublicCaSet") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + Headers: headers, + }) + + if err != nil { + return fmt.Errorf("Error updating TlsInspectionPolicy %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating TlsInspectionPolicy %q: %#v", d.Id(), res) + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Updating TlsInspectionPolicy", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceNetworkSecurityTlsInspectionPolicyRead(d, meta) +} + +func resourceNetworkSecurityTlsInspectionPolicyDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for TlsInspectionPolicy: %s", err) + } + billingProject = project + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/tlsInspectionPolicies/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting TlsInspectionPolicy %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "TlsInspectionPolicy") + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Deleting TlsInspectionPolicy", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting TlsInspectionPolicy %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkSecurityTlsInspectionPolicyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/locations/(?P[^/]+)/tlsInspectionPolicies/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/tlsInspectionPolicies/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkSecurityTlsInspectionPolicyCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityTlsInspectionPolicyUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityTlsInspectionPolicyDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityTlsInspectionPolicyCaPool(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityTlsInspectionPolicyExcludePublicCaSet(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNetworkSecurityTlsInspectionPolicyDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityTlsInspectionPolicyCaPool(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityTlsInspectionPolicyExcludePublicCaSet(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/google/services/networksecurity/resource_network_security_tls_inspection_policy_generated_test.go b/google/services/networksecurity/resource_network_security_tls_inspection_policy_generated_test.go new file mode 100644 index 00000000000..a3c73686963 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_tls_inspection_policy_generated_test.go @@ -0,0 +1,177 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccNetworkSecurityTlsInspectionPolicy_networkSecurityTlsInspectionPolicyBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkSecurityTlsInspectionPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityTlsInspectionPolicy_networkSecurityTlsInspectionPolicyBasicExample(context), + }, + { + ResourceName: "google_network_security_tls_inspection_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccNetworkSecurityTlsInspectionPolicy_networkSecurityTlsInspectionPolicyBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_privateca_ca_pool" "default" { + name = "tf-test-my-basic-ca-pool%{random_suffix}" + location = "us-central1" + tier = "DEVOPS" + publishing_options { + publish_ca_cert = false + publish_crl = false + } + issuance_policy { + maximum_lifetime = "1209600s" + baseline_values { + ca_options { + is_ca = false + } + key_usage { + base_key_usage {} + extended_key_usage { + server_auth = true + } + } + } + } +} + +resource "google_privateca_certificate_authority" "default" { + pool = google_privateca_ca_pool.default.name + certificate_authority_id = "tf-test-my-basic-certificate-authority%{random_suffix}" + location = "us-central1" + lifetime = "86400s" + type = "SELF_SIGNED" + deletion_protection = false + skip_grace_period = true + ignore_active_certificates_on_deletion = true + config { + subject_config { + subject { + organization = "Test LLC" + common_name = "my-ca" + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = false + } + } + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } +} + +resource "google_project_service_identity" "ns_sa" { + service = "networksecurity.googleapis.com" +} + +resource "google_privateca_ca_pool_iam_member" "tls_inspection_permission" { + ca_pool = google_privateca_ca_pool.default.id + role = "roles/privateca.certificateManager" + member = "serviceAccount:${google_project_service_identity.ns_sa.email}" +} + +resource "google_network_security_tls_inspection_policy" "default" { + name = "tf-test-my-tls-inspection-policy%{random_suffix}" + location = "us-central1" + ca_pool = google_privateca_ca_pool.default.id + exclude_public_ca_set = false + depends_on = [google_privateca_ca_pool.default, google_privateca_certificate_authority.default, google_privateca_ca_pool_iam_member.tls_inspection_permission] +} +`, context) +} + +func testAccCheckNetworkSecurityTlsInspectionPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_network_security_tls_inspection_policy" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/tlsInspectionPolicies/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("NetworkSecurityTlsInspectionPolicy still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/services/networksecurity/resource_network_security_tls_inspection_policy_sweeper.go b/google/services/networksecurity/resource_network_security_tls_inspection_policy_sweeper.go new file mode 100644 index 00000000000..b40bbf51085 --- /dev/null +++ b/google/services/networksecurity/resource_network_security_tls_inspection_policy_sweeper.go @@ -0,0 +1,139 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networksecurity + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkSecurityTlsInspectionPolicy", testSweepNetworkSecurityTlsInspectionPolicy) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkSecurityTlsInspectionPolicy(region string) error { + resourceName := "NetworkSecurityTlsInspectionPolicy" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://networksecurity.googleapis.com/v1/projects/{{project}}/locations/{{location}}/tlsInspectionPolicies", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["tlsInspectionPolicies"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://networksecurity.googleapis.com/v1/projects/{{project}}/locations/{{location}}/tlsInspectionPolicies/{{name}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/google/services/networksecurity/resource_network_security_tls_inspection_policy_test.go b/google/services/networksecurity/resource_network_security_tls_inspection_policy_test.go index 8380ac5af78..43329f757da 100644 --- a/google/services/networksecurity/resource_network_security_tls_inspection_policy_test.go +++ b/google/services/networksecurity/resource_network_security_tls_inspection_policy_test.go @@ -1,3 +1,208 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package networksecurity_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccNetworkSecurityTlsInspectionPolicy_update(t *testing.T) { + t.Parallel() + + tlsInspectionPolicyName := fmt.Sprintf("tf-test-tls-inspection-policy-%s", acctest.RandString(t, 10)) + caPoolName := fmt.Sprintf("tf-test-tls-ca-pool-%s", acctest.RandString(t, 10)) + certificateAuthorityName := fmt.Sprintf("tf-test-tls-certificate-authority-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkSecurityTlsInspectionPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityTlsInspectionPolicy_basic(caPoolName, certificateAuthorityName, tlsInspectionPolicyName), + }, + { + ResourceName: "google_network_security_tls_inspection_policy.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccNetworkSecurityTlsInspectionPolicy_update(caPoolName, certificateAuthorityName, tlsInspectionPolicyName), + }, + { + ResourceName: "google_network_security_tls_inspection_policy.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccNetworkSecurityTlsInspectionPolicy_basic(caPoolName, certificateAuthorityName, tlsInspectionPolicyName string) string { + return fmt.Sprintf(` +resource "google_privateca_ca_pool" "default" { + name = "%s" + location = "us-central1" + tier = "DEVOPS" + publishing_options { + publish_ca_cert = false + publish_crl = false + } + issuance_policy { + maximum_lifetime = "1209600s" + baseline_values { + ca_options { + is_ca = false + } + key_usage { + base_key_usage {} + extended_key_usage { + server_auth = true + } + } + } + } +} + + +resource "google_privateca_certificate_authority" "default" { + pool = google_privateca_ca_pool.default.name + certificate_authority_id = "%s" + location = "us-central1" + lifetime = "86400s" + type = "SELF_SIGNED" + deletion_protection = false + skip_grace_period = true + ignore_active_certificates_on_deletion = true + config { + subject_config { + subject { + organization = "Test LLC" + common_name = "my-ca" + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = false + } + } + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } +} + +resource "google_project_service_identity" "ns_sa" { + service = "networksecurity.googleapis.com" +} + +resource "google_privateca_ca_pool_iam_member" "tls_inspection_permission" { + ca_pool = google_privateca_ca_pool.default.id + role = "roles/privateca.certificateManager" + member = "serviceAccount:${google_project_service_identity.ns_sa.email}" +} + +resource "google_network_security_tls_inspection_policy" "foobar" { + name = "%s" + location = "us-central1" + ca_pool = google_privateca_ca_pool.default.id + depends_on = [google_privateca_ca_pool.default, google_privateca_certificate_authority.default, google_privateca_ca_pool_iam_member.tls_inspection_permission] +} +`, caPoolName, certificateAuthorityName, tlsInspectionPolicyName) +} + +func testAccNetworkSecurityTlsInspectionPolicy_update(caPoolName, certificateAuthorityName, tlsInspectionPolicyName string) string { + return fmt.Sprintf(` +resource "google_privateca_ca_pool" "default" { + name = "%s" + location = "us-central1" + tier = "DEVOPS" + publishing_options { + publish_ca_cert = false + publish_crl = false + } + issuance_policy { + maximum_lifetime = "1209600s" + baseline_values { + ca_options { + is_ca = false + } + key_usage { + base_key_usage {} + extended_key_usage { + server_auth = true + } + } + } + } +} + + +resource "google_privateca_certificate_authority" "default" { + pool = google_privateca_ca_pool.default.name + certificate_authority_id = "%s" + location = "us-central1" + lifetime = "86400s" + type = "SELF_SIGNED" + deletion_protection = false + skip_grace_period = true + ignore_active_certificates_on_deletion = true + config { + subject_config { + subject { + organization = "Test LLC" + common_name = "my-ca" + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = false + } + } + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } +} + +resource "google_project_service_identity" "ns_sa" { + service = "networksecurity.googleapis.com" +} + +resource "google_privateca_ca_pool_iam_member" "tls_inspection_permission" { + ca_pool = google_privateca_ca_pool.default.id + role = "roles/privateca.certificateManager" + member = "serviceAccount:${google_project_service_identity.ns_sa.email}" +} + +resource "google_network_security_tls_inspection_policy" "foobar" { + name = "%s" + location = "us-central1" + description = "my tls inspection policy updated" + ca_pool = google_privateca_ca_pool.default.id + depends_on = [google_privateca_ca_pool.default, google_privateca_certificate_authority.default, google_privateca_ca_pool_iam_member.tls_inspection_permission] +} +`, caPoolName, certificateAuthorityName, tlsInspectionPolicyName) +} diff --git a/website/docs/r/network_security_firewall_endpoint.html.markdown b/website/docs/r/network_security_firewall_endpoint.html.markdown index bea7e4a1631..b638a4c99ee 100644 --- a/website/docs/r/network_security_firewall_endpoint.html.markdown +++ b/website/docs/r/network_security_firewall_endpoint.html.markdown @@ -25,12 +25,10 @@ A Firewall endpoint is a Cloud Firewall resource that enables layer 7 advanced protection capabilities, such as intrusion prevention, in your network. -~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. To get more information about FirewallEndpoint, see: -* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/organizations.locations.firewallEndpoints) +* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1/organizations.locations.firewallEndpoints) * How-to Guides * [Firewall endpoint overview](https://cloud.google.com/firewall/docs/about-firewall-endpoints) * [Create and associate firewall endpoints](https://cloud.google.com/firewall/docs/configure-firewall-endpoints) @@ -46,7 +44,6 @@ Your account must have the `serviceusage.services.use` permission on the ```hcl resource "google_network_security_firewall_endpoint" "default" { - provider = google-beta name = "my-firewall-endpoint" parent = "organizations/123456789" location = "us-central1-a" diff --git a/website/docs/r/network_security_firewall_endpoint_association.html.markdown b/website/docs/r/network_security_firewall_endpoint_association.html.markdown index b4228f39ae0..c7389bd061c 100644 --- a/website/docs/r/network_security_firewall_endpoint_association.html.markdown +++ b/website/docs/r/network_security_firewall_endpoint_association.html.markdown @@ -25,12 +25,10 @@ the same zone. After you define this association, Cloud Firewall forwards the zonal workload traffic in your VPC network that requires layer 7 inspection to the attached firewall endpoint. -~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. To get more information about FirewallEndpointAssociation, see: -* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/projects.locations.firewallEndpointAssociations#FirewallEndpointAssociation) +* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1/projects.locations.firewallEndpointAssociations#FirewallEndpointAssociation) * How-to Guides * [Firewall endpoint overview](https://cloud.google.com/firewall/docs/about-firewall-endpoints) * [Create and associate firewall endpoints](https://cloud.google.com/firewall/docs/configure-firewall-endpoints) @@ -40,7 +38,6 @@ To get more information about FirewallEndpointAssociation, see: ```hcl resource "google_network_security_firewall_endpoint" "default" { - provider = google-beta name = "my-firewall-endpoint" parent = "organizations/123456789" location = "us-central1-a" @@ -51,7 +48,6 @@ resource "google_network_security_firewall_endpoint" "default" { } resource "google_network_security_firewall_endpoint_association" "default_association" { - provider = google-beta name = "my-firewall-endpoint-association" parent = "projects/my-project-name" location = "us-central1-a" diff --git a/website/docs/r/network_security_security_profile.html.markdown b/website/docs/r/network_security_security_profile.html.markdown index 850f86c4277..cc98a28667b 100644 --- a/website/docs/r/network_security_security_profile.html.markdown +++ b/website/docs/r/network_security_security_profile.html.markdown @@ -21,12 +21,10 @@ description: |- A security profile defines the behavior associated to a profile type. -~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. To get more information about SecurityProfile, see: -* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/projects.locations.securityProfiles) +* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1/projects.locations.securityProfiles) * How-to Guides * [Create and manage security profiles](https://cloud.google.com/firewall/docs/configure-security-profiles) @@ -35,7 +33,6 @@ To get more information about SecurityProfile, see: ```hcl resource "google_network_security_security_profile" "default" { - provider = google-beta name = "my-security-profile" parent = "organizations/123456789" description = "my description" @@ -51,7 +48,6 @@ resource "google_network_security_security_profile" "default" { ```hcl resource "google_network_security_security_profile" "default" { - provider = google-beta name = "my-security-profile" parent = "organizations/123456789" description = "my description" diff --git a/website/docs/r/network_security_security_profile_group.html.markdown b/website/docs/r/network_security_security_profile_group.html.markdown index a64b636278b..d91080ca0f7 100644 --- a/website/docs/r/network_security_security_profile_group.html.markdown +++ b/website/docs/r/network_security_security_profile_group.html.markdown @@ -21,12 +21,10 @@ description: |- A security profile group defines a container for security profiles. -~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. To get more information about SecurityProfileGroup, see: -* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/organizations.locations.securityProfileGroups) +* [API documentation](https://cloud.google.com/firewall/docs/reference/network-security/rest/v1/organizations.locations.securityProfileGroups) * How-to Guides * [Security profile groups overview](https://cloud.google.com/firewall/docs/about-security-profile-groups) * [Create and manage security profile groups](https://cloud.google.com/firewall/docs/configure-security-profile-groups) @@ -36,7 +34,6 @@ To get more information about SecurityProfileGroup, see: ```hcl resource "google_network_security_security_profile_group" "default" { - provider = google-beta name = "sec-profile-group" parent = "organizations/123456789" description = "my description" @@ -48,7 +45,6 @@ resource "google_network_security_security_profile_group" "default" { } resource "google_network_security_security_profile" "security_profile" { - provider = google-beta name = "sec-profile" type = "THREAT_PREVENTION" parent = "organizations/123456789" diff --git a/website/docs/r/network_security_tls_inspection_policy.html.markdown b/website/docs/r/network_security_tls_inspection_policy.html.markdown index 4d272638699..2849bf418a4 100644 --- a/website/docs/r/network_security_tls_inspection_policy.html.markdown +++ b/website/docs/r/network_security_tls_inspection_policy.html.markdown @@ -21,12 +21,10 @@ description: |- The TlsInspectionPolicy resource contains references to CA pools in Certificate Authority Service and associated metadata. -~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. To get more information about TlsInspectionPolicy, see: -* [API documentation](https://cloud.google.com/secure-web-proxy/docs/reference/network-security/rest/v1beta1/projects.locations.tlsInspectionPolicies) +* [API documentation](https://cloud.google.com/secure-web-proxy/docs/reference/network-security/rest/v1/projects.locations.tlsInspectionPolicies) * How-to Guides * [Use TlsInspectionPolicy](https://cloud.google.com/secure-web-proxy/docs/tls-inspection-overview) @@ -40,7 +38,6 @@ To get more information about TlsInspectionPolicy, see: ```hcl resource "google_privateca_ca_pool" "default" { - provider = google-beta name = "my-basic-ca-pool" location = "us-central1" tier = "DEVOPS" @@ -64,22 +61,20 @@ resource "google_privateca_ca_pool" "default" { } } - resource "google_privateca_certificate_authority" "default" { - provider = google-beta - pool = google_privateca_ca_pool.default.name - certificate_authority_id = "my-basic-certificate-authority" - location = "us-central1" - lifetime = "86400s" - type = "SELF_SIGNED" - deletion_protection = false - skip_grace_period = true + pool = google_privateca_ca_pool.default.name + certificate_authority_id = "my-basic-certificate-authority" + location = "us-central1" + lifetime = "86400s" + type = "SELF_SIGNED" + deletion_protection = false + skip_grace_period = true ignore_active_certificates_on_deletion = true config { subject_config { subject { organization = "Test LLC" - common_name = "my-ca" + common_name = "my-ca" } } x509_config { @@ -89,7 +84,7 @@ resource "google_privateca_certificate_authority" "default" { key_usage { base_key_usage { cert_sign = true - crl_sign = true + crl_sign = true } extended_key_usage { server_auth = false @@ -103,26 +98,21 @@ resource "google_privateca_certificate_authority" "default" { } resource "google_project_service_identity" "ns_sa" { - provider = google-beta - service = "networksecurity.googleapis.com" } resource "google_privateca_ca_pool_iam_member" "tls_inspection_permission" { - provider = google-beta - ca_pool = google_privateca_ca_pool.default.id - role = "roles/privateca.certificateManager" - member = "serviceAccount:${google_project_service_identity.ns_sa.email}" + role = "roles/privateca.certificateManager" + member = "serviceAccount:${google_project_service_identity.ns_sa.email}" } resource "google_network_security_tls_inspection_policy" "default" { - provider = google-beta - name = "my-tls-inspection-policy" - location = "us-central1" - ca_pool = google_privateca_ca_pool.default.id + name = "my-tls-inspection-policy" + location = "us-central1" + ca_pool = google_privateca_ca_pool.default.id exclude_public_ca_set = false - depends_on = [google_privateca_ca_pool.default, google_privateca_certificate_authority.default, google_privateca_ca_pool_iam_member.tls_inspection_permission] + depends_on = [google_privateca_ca_pool.default, google_privateca_certificate_authority.default, google_privateca_ca_pool_iam_member.tls_inspection_permission] } ```