diff --git a/.changelog/12379.txt b/.changelog/12379.txt new file mode 100644 index 0000000000..60ffe29bdc --- /dev/null +++ b/.changelog/12379.txt @@ -0,0 +1,6 @@ +```release-note:new-resource +networksecurity: Added new resource `google_network_security_authz_policy` +``` +```release-note:new-resource +networkservices: Added new resource `google_network_services_authz_extension` +``` \ No newline at end of file diff --git a/google-beta/provider/provider_mmv1_resources.go b/google-beta/provider/provider_mmv1_resources.go index ca9c5d0ab9..abcb92f1f9 100644 --- a/google-beta/provider/provider_mmv1_resources.go +++ b/google-beta/provider/provider_mmv1_resources.go @@ -509,9 +509,9 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{ } // Resources -// Generated resources: 564 +// Generated resources: 566 // Generated IAM resources: 294 -// Total generated resources: 858 +// Total generated resources: 860 var generatedResources = map[string]*schema.Resource{ "google_folder_access_approval_settings": accessapproval.ResourceAccessApprovalFolderSettings(), "google_organization_access_approval_settings": accessapproval.ResourceAccessApprovalOrganizationSettings(), @@ -1137,6 +1137,7 @@ var generatedResources = map[string]*schema.Resource{ "google_network_management_vpc_flow_logs_config": networkmanagement.ResourceNetworkManagementVpcFlowLogsConfig(), "google_network_security_address_group": networksecurity.ResourceNetworkSecurityAddressGroup(), "google_network_security_authorization_policy": networksecurity.ResourceNetworkSecurityAuthorizationPolicy(), + "google_network_security_authz_policy": networksecurity.ResourceNetworkSecurityAuthzPolicy(), "google_network_security_client_tls_policy": networksecurity.ResourceNetworkSecurityClientTlsPolicy(), "google_network_security_firewall_endpoint": networksecurity.ResourceNetworkSecurityFirewallEndpoint(), "google_network_security_firewall_endpoint_association": networksecurity.ResourceNetworkSecurityFirewallEndpointAssociation(), @@ -1154,6 +1155,7 @@ var generatedResources = map[string]*schema.Resource{ "google_network_security_server_tls_policy": networksecurity.ResourceNetworkSecurityServerTlsPolicy(), "google_network_security_tls_inspection_policy": networksecurity.ResourceNetworkSecurityTlsInspectionPolicy(), "google_network_security_url_lists": networksecurity.ResourceNetworkSecurityUrlLists(), + "google_network_services_authz_extension": networkservices.ResourceNetworkServicesAuthzExtension(), "google_network_services_edge_cache_keyset": networkservices.ResourceNetworkServicesEdgeCacheKeyset(), "google_network_services_edge_cache_origin": networkservices.ResourceNetworkServicesEdgeCacheOrigin(), "google_network_services_edge_cache_service": networkservices.ResourceNetworkServicesEdgeCacheService(), diff --git a/google-beta/services/networksecurity/resource_network_security_authz_policy.go b/google-beta/services/networksecurity/resource_network_security_authz_policy.go new file mode 100644 index 0000000000..dd64811d30 --- /dev/null +++ b/google-beta/services/networksecurity/resource_network_security_authz_policy.go @@ -0,0 +1,2640 @@ +// 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-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" +) + +func ResourceNetworkSecurityAuthzPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkSecurityAuthzPolicyCreate, + Read: resourceNetworkSecurityAuthzPolicyRead, + Update: resourceNetworkSecurityAuthzPolicyUpdate, + Delete: resourceNetworkSecurityAuthzPolicyDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkSecurityAuthzPolicyImport, + }, + + 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.SetLabelsDiff, + tpgresource.DefaultProviderProject, + ), + + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"ALLOW", "DENY", "CUSTOM"}), + Description: `When the action is CUSTOM, customProvider must be specified. +When the action is ALLOW, only requests matching the policy will be allowed. +When the action is DENY, only requests matching the policy will be denied. + +When a request arrives, the policies are evaluated in the following order: +1. If there is a CUSTOM policy that matches the request, the CUSTOM policy is evaluated using the custom authorization providers and the request is denied if the provider rejects the request. +2. If there are any DENY policies that match the request, the request is denied. +3. If there are no ALLOW policies for the resource or if any of the ALLOW policies match the request, the request is allowed. +4. Else the request is denied by default if none of the configured AuthzPolicies with ALLOW action match the request. Possible values: ["ALLOW", "DENY", "CUSTOM"]`, + }, + "location": { + Type: schema.TypeString, + Required: true, + Description: `The location of the resource.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: `Identifier. Name of the AuthzPolicy resource.`, + }, + "target": { + Type: schema.TypeList, + Required: true, + Description: `Specifies the set of resources to which this policy should be applied to.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "load_balancing_scheme": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"INTERNAL_MANAGED", "EXTERNAL_MANAGED", "INTERNAL_SELF_MANAGED"}), + Description: `All gateways and forwarding rules referenced by this policy and extensions must share the same load balancing scheme. +For more information, refer to [Backend services overview](https://cloud.google.com/load-balancing/docs/backend-service). Possible values: ["INTERNAL_MANAGED", "EXTERNAL_MANAGED", "INTERNAL_SELF_MANAGED"]`, + }, + "resources": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: tpgresource.ProjectNumberDiffSuppress, + Description: `A list of references to the Forwarding Rules on which this policy will be applied.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "custom_provider": { + Type: schema.TypeList, + Optional: true, + Description: `Required if the action is CUSTOM. Allows delegating authorization decisions to Cloud IAP or to Service Extensions. One of cloudIap or authzExtension must be specified.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "authz_extension": { + Type: schema.TypeList, + Optional: true, + Description: `Delegate authorization decision to user authored Service Extension. Only one of cloudIap or authzExtension can be specified.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resources": { + Type: schema.TypeList, + Required: true, + DiffSuppressFunc: tpgresource.ProjectNumberDiffSuppress, + Description: `A list of references to authorization extensions that will be invoked for requests matching this policy. Limited to 1 custom provider.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "cloud_iap": { + Type: schema.TypeList, + Optional: true, + Description: `Delegates authorization decisions to Cloud IAP. Applicable only for managed load balancers. Enabling Cloud IAP at the AuthzPolicy level is not compatible with Cloud IAP settings in the BackendService. Enabling IAP in both places will result in request failure. Ensure that IAP is enabled in either the AuthzPolicy or the BackendService but not in both places.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Enable Cloud IAP at the AuthzPolicy level.`, + }, + }, + }, + }, + }, + }, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `A human-readable description of the resource.`, + }, + "http_rules": { + Type: schema.TypeList, + Optional: true, + Description: `A list of authorization HTTP rules to match against the incoming request.A policy match occurs when at least one HTTP rule matches the request or when no HTTP rules are specified in the policy. At least one HTTP Rule is required for Allow or Deny Action. +Limited to 5 rules.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "from": { + Type: schema.TypeList, + Optional: true, + Description: `Describes properties of one or more sources of a request.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "not_sources": { + Type: schema.TypeList, + Optional: true, + Description: `Describes the properties of a request's sources. At least one of sources or notSources must be specified. Limited to 5 sources. A match occurs when ANY source (in sources or notSources) matches the request. Within a single source, the match follows AND semantics across fields and OR semantics within a single field, i.e. a match occurs when ANY principal matches AND ANY ipBlocks match.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "principals": { + Type: schema.TypeList, + Optional: true, + Description: `A list of identities derived from the client's certificate. This field will not match on a request unless mutual TLS is enabled for the Forwarding rule or Gateway. Each identity is a string whose value is matched against the URI SAN, or DNS SAN or the subject field in the client's certificate. The match can be exact, prefix, suffix or a substring match. One of exact, prefix, suffix or contains must be specified. +Limited to 5 principals.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contains": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc.def`, + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must match exactly the string specified here. +Examples: +* abc only matches the value abc.`, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true.`, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value abc.xyz`, + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc`, + }, + }, + }, + }, + "resources": { + Type: schema.TypeList, + Optional: true, + Description: `A list of resources to match against the resource of the source VM of a request. +Limited to 5 resources.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "iam_service_account": { + Type: schema.TypeList, + Optional: true, + Description: `An IAM service account to match against the source service account of the VM sending the request.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contains": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc.def`, + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must match exactly the string specified here. +Examples: +* abc only matches the value abc.`, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true.`, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value abc.xyz`, + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc`, + }, + }, + }, + }, + "tag_value_id_set": { + Type: schema.TypeList, + Optional: true, + Description: `A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ids": { + Type: schema.TypeList, + Optional: true, + Description: `A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request. The match follows AND semantics which means all the ids must match. +Limited to 5 matches.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "sources": { + Type: schema.TypeList, + Optional: true, + Description: `Describes the properties of a request's sources. At least one of sources or notSources must be specified. Limited to 5 sources. A match occurs when ANY source (in sources or notSources) matches the request. Within a single source, the match follows AND semantics across fields and OR semantics within a single field, i.e. a match occurs when ANY principal matches AND ANY ipBlocks match.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "principals": { + Type: schema.TypeList, + Optional: true, + Description: `A list of identities derived from the client's certificate. This field will not match on a request unless mutual TLS is enabled for the Forwarding rule or Gateway. Each identity is a string whose value is matched against the URI SAN, or DNS SAN or the subject field in the client's certificate. The match can be exact, prefix, suffix or a substring match. One of exact, prefix, suffix or contains must be specified. +Limited to 5 principals.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contains": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc.def`, + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must match exactly the string specified here. +Examples: +* abc only matches the value abc.`, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true.`, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value abc.xyz`, + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc`, + }, + }, + }, + }, + "resources": { + Type: schema.TypeList, + Optional: true, + Description: `A list of resources to match against the resource of the source VM of a request. +Limited to 5 resources.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "iam_service_account": { + Type: schema.TypeList, + Optional: true, + Description: `An IAM service account to match against the source service account of the VM sending the request.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contains": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc.def`, + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must match exactly the string specified here. +Examples: +* abc only matches the value abc.`, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true.`, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value abc.xyz`, + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc`, + }, + }, + }, + }, + "tag_value_id_set": { + Type: schema.TypeList, + Optional: true, + Description: `A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ids": { + Type: schema.TypeList, + Optional: true, + Description: `A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request. The match follows AND semantics which means all the ids must match. +Limited to 5 matches.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "to": { + Type: schema.TypeList, + Optional: true, + Description: `Describes properties of one or more targets of a request`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operations": { + Type: schema.TypeList, + Optional: true, + Description: `Describes properties of one or more targets of a request. At least one of operations or notOperations must be specified. Limited to 5 operations. A match occurs when ANY operation (in operations or notOperations) matches. Within an operation, the match follows AND semantics across fields and OR semantics within a field, i.e. a match occurs when ANY path matches AND ANY header matches and ANY method matches.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_set": { + Type: schema.TypeList, + Optional: true, + Description: `A list of headers to match against in http header.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "headers": { + Type: schema.TypeList, + Optional: true, + Description: `A list of headers to match against in http header. The match can be one of exact, prefix, suffix, or contains (substring match). The match follows AND semantics which means all the headers must match. Matches are always case sensitive unless the ignoreCase is set. Limited to 5 matches.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the name of the header in the request.`, + }, + "value": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies how the header match will be performed.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contains": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc.def`, + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must match exactly the string specified here. +Examples: +* abc only matches the value abc.`, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true.`, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value abc.xyz`, + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "hosts": { + Type: schema.TypeList, + Optional: true, + Description: `A list of HTTP Hosts to match against. The match can be one of exact, prefix, suffix, or contains (substring match). Matches are always case sensitive unless the ignoreCase is set. +Limited to 5 matches.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contains": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc.def`, + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must match exactly the string specified here. +Examples: +* abc only matches the value abc.`, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true.`, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value abc.xyz`, + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc`, + }, + }, + }, + }, + "methods": { + Type: schema.TypeList, + Optional: true, + Description: `A list of HTTP methods to match against. Each entry must be a valid HTTP method name (GET, PUT, POST, HEAD, PATCH, DELETE, OPTIONS). It only allows exact match and is always case sensitive.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "paths": { + Type: schema.TypeList, + Optional: true, + Description: `A list of paths to match against. The match can be one of exact, prefix, suffix, or contains (substring match). Matches are always case sensitive unless the ignoreCase is set. +Limited to 5 matches. +Note that this path match includes the query parameters. For gRPC services, this should be a fully-qualified name of the form /package.service/method.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "contains": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc.def`, + }, + "exact": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must match exactly the string specified here. +Examples: +* abc only matches the value abc.`, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true.`, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value abc.xyz`, + }, + "suffix": { + Type: schema.TypeString, + Optional: true, + Description: `The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. +Examples: +* abc matches the value xyz.abc`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "when": { + Type: schema.TypeString, + Optional: true, + Description: `CEL expression that describes the conditions to be satisfied for the action. The result of the CEL expression is ANDed with the from and to. Refer to the CEL language reference for a list of available attributes.`, + }, + }, + }, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `Set of labels associated with the AuthzExtension 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}, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `The timestamp when the resource was created.`, + }, + "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}, + }, + "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: `The timestamp when the resource was updated.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkSecurityAuthzPolicyCreate(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 := expandNetworkSecurityAuthzPolicyDescription(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 + } + targetProp, err := expandNetworkSecurityAuthzPolicyTarget(d.Get("target"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("target"); !tpgresource.IsEmptyValue(reflect.ValueOf(targetProp)) && (ok || !reflect.DeepEqual(v, targetProp)) { + obj["target"] = targetProp + } + httpRulesProp, err := expandNetworkSecurityAuthzPolicyHttpRules(d.Get("http_rules"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http_rules"); !tpgresource.IsEmptyValue(reflect.ValueOf(httpRulesProp)) && (ok || !reflect.DeepEqual(v, httpRulesProp)) { + obj["httpRules"] = httpRulesProp + } + actionProp, err := expandNetworkSecurityAuthzPolicyAction(d.Get("action"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("action"); !tpgresource.IsEmptyValue(reflect.ValueOf(actionProp)) && (ok || !reflect.DeepEqual(v, actionProp)) { + obj["action"] = actionProp + } + customProviderProp, err := expandNetworkSecurityAuthzPolicyCustomProvider(d.Get("custom_provider"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("custom_provider"); !tpgresource.IsEmptyValue(reflect.ValueOf(customProviderProp)) && (ok || !reflect.DeepEqual(v, customProviderProp)) { + obj["customProvider"] = customProviderProp + } + labelsProp, err := expandNetworkSecurityAuthzPolicyEffectiveLabels(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 + } + nameProp, err := expandNetworkSecurityAuthzPolicyName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/authzPolicies?authzPolicyId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new AuthzPolicy: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for AuthzPolicy: %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 AuthzPolicy: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/authzPolicies/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Creating AuthzPolicy", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create AuthzPolicy: %s", err) + } + + log.Printf("[DEBUG] Finished creating AuthzPolicy %q: %#v", d.Id(), res) + + return resourceNetworkSecurityAuthzPolicyRead(d, meta) +} + +func resourceNetworkSecurityAuthzPolicyRead(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}}/authzPolicies/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for AuthzPolicy: %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("NetworkSecurityAuthzPolicy %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + + if err := d.Set("create_time", flattenNetworkSecurityAuthzPolicyCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("update_time", flattenNetworkSecurityAuthzPolicyUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("description", flattenNetworkSecurityAuthzPolicyDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("labels", flattenNetworkSecurityAuthzPolicyLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("target", flattenNetworkSecurityAuthzPolicyTarget(res["target"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("http_rules", flattenNetworkSecurityAuthzPolicyHttpRules(res["httpRules"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("action", flattenNetworkSecurityAuthzPolicyAction(res["action"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("custom_provider", flattenNetworkSecurityAuthzPolicyCustomProvider(res["customProvider"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("terraform_labels", flattenNetworkSecurityAuthzPolicyTerraformLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("effective_labels", flattenNetworkSecurityAuthzPolicyEffectiveLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + if err := d.Set("name", flattenNetworkSecurityAuthzPolicyName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzPolicy: %s", err) + } + + return nil +} + +func resourceNetworkSecurityAuthzPolicyUpdate(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 AuthzPolicy: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkSecurityAuthzPolicyDescription(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 + } + targetProp, err := expandNetworkSecurityAuthzPolicyTarget(d.Get("target"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("target"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, targetProp)) { + obj["target"] = targetProp + } + httpRulesProp, err := expandNetworkSecurityAuthzPolicyHttpRules(d.Get("http_rules"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http_rules"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, httpRulesProp)) { + obj["httpRules"] = httpRulesProp + } + actionProp, err := expandNetworkSecurityAuthzPolicyAction(d.Get("action"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("action"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, actionProp)) { + obj["action"] = actionProp + } + customProviderProp, err := expandNetworkSecurityAuthzPolicyCustomProvider(d.Get("custom_provider"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("custom_provider"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, customProviderProp)) { + obj["customProvider"] = customProviderProp + } + labelsProp, err := expandNetworkSecurityAuthzPolicyEffectiveLabels(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 + } + nameProp, err := expandNetworkSecurityAuthzPolicyName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/authzPolicies/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating AuthzPolicy %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("target") { + updateMask = append(updateMask, "target") + } + + if d.HasChange("http_rules") { + updateMask = append(updateMask, "httpRules") + } + + if d.HasChange("action") { + updateMask = append(updateMask, "action") + } + + if d.HasChange("custom_provider") { + updateMask = append(updateMask, "customProvider") + } + + if d.HasChange("effective_labels") { + updateMask = append(updateMask, "labels") + } + + if d.HasChange("name") { + updateMask = append(updateMask, "name") + } + // 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 AuthzPolicy %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating AuthzPolicy %q: %#v", d.Id(), res) + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Updating AuthzPolicy", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceNetworkSecurityAuthzPolicyRead(d, meta) +} + +func resourceNetworkSecurityAuthzPolicyDelete(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 AuthzPolicy: %s", err) + } + billingProject = project + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/authzPolicies/{{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 AuthzPolicy %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, "AuthzPolicy") + } + + err = NetworkSecurityOperationWaitTime( + config, res, project, "Deleting AuthzPolicy", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting AuthzPolicy %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkSecurityAuthzPolicyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/locations/(?P[^/]+)/authzPolicies/(?P[^/]+)$", + "^(?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}}/authzPolicies/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkSecurityAuthzPolicyCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyLabels(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 flattenNetworkSecurityAuthzPolicyTarget(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["load_balancing_scheme"] = + flattenNetworkSecurityAuthzPolicyTargetLoadBalancingScheme(original["loadBalancingScheme"], d, config) + transformed["resources"] = + flattenNetworkSecurityAuthzPolicyTargetResources(original["resources"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyTargetLoadBalancingScheme(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyTargetResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRules(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{}{ + "from": flattenNetworkSecurityAuthzPolicyHttpRulesFrom(original["from"], d, config), + "to": flattenNetworkSecurityAuthzPolicyHttpRulesTo(original["to"], d, config), + "when": flattenNetworkSecurityAuthzPolicyHttpRulesWhen(original["when"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFrom(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["sources"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromSources(original["sources"], d, config) + transformed["not_sources"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSources(original["notSources"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSources(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{}{ + "principals": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipals(original["principals"], d, config), + "resources": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResources(original["resources"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipals(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{}{ + "ignore_case": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsIgnoreCase(original["ignoreCase"], d, config), + "exact": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsExact(original["exact"], d, config), + "prefix": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsPrefix(original["prefix"], d, config), + "suffix": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsSuffix(original["suffix"], d, config), + "contains": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsContains(original["contains"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsIgnoreCase(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsExact(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsPrefix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsSuffix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsContains(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResources(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{}{ + "tag_value_id_set": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSet(original["tagValueIdSet"], d, config), + "iam_service_account": flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccount(original["iamServiceAccount"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSet(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["ids"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSetIds(original["ids"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSetIds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccount(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["ignore_case"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountIgnoreCase(original["ignoreCase"], d, config) + transformed["exact"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountExact(original["exact"], d, config) + transformed["prefix"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountPrefix(original["prefix"], d, config) + transformed["suffix"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountSuffix(original["suffix"], d, config) + transformed["contains"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountContains(original["contains"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountIgnoreCase(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountExact(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountPrefix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountSuffix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountContains(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSources(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{}{ + "principals": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipals(original["principals"], d, config), + "resources": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResources(original["resources"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipals(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{}{ + "ignore_case": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsIgnoreCase(original["ignoreCase"], d, config), + "exact": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsExact(original["exact"], d, config), + "prefix": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsPrefix(original["prefix"], d, config), + "suffix": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsSuffix(original["suffix"], d, config), + "contains": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsContains(original["contains"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsIgnoreCase(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsExact(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsPrefix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsSuffix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsContains(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResources(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{}{ + "tag_value_id_set": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSet(original["tagValueIdSet"], d, config), + "iam_service_account": flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccount(original["iamServiceAccount"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSet(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["ids"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSetIds(original["ids"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSetIds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccount(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["ignore_case"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountIgnoreCase(original["ignoreCase"], d, config) + transformed["exact"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountExact(original["exact"], d, config) + transformed["prefix"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountPrefix(original["prefix"], d, config) + transformed["suffix"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountSuffix(original["suffix"], d, config) + transformed["contains"] = + flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountContains(original["contains"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountIgnoreCase(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountExact(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountPrefix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountSuffix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountContains(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesTo(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["operations"] = + flattenNetworkSecurityAuthzPolicyHttpRulesToOperations(original["operations"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperations(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{}{ + "header_set": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSet(original["headerSet"], d, config), + "hosts": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHosts(original["hosts"], d, config), + "paths": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPaths(original["paths"], d, config), + "methods": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsMethods(original["methods"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSet(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["headers"] = + flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeaders(original["headers"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeaders(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{}{ + "name": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersName(original["name"], d, config), + "value": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValue(original["value"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValue(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["ignore_case"] = + flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueIgnoreCase(original["ignoreCase"], d, config) + transformed["exact"] = + flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueExact(original["exact"], d, config) + transformed["prefix"] = + flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValuePrefix(original["prefix"], d, config) + transformed["suffix"] = + flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueSuffix(original["suffix"], d, config) + transformed["contains"] = + flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueContains(original["contains"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueIgnoreCase(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueExact(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValuePrefix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueSuffix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueContains(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHosts(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{}{ + "ignore_case": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsIgnoreCase(original["ignoreCase"], d, config), + "exact": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsExact(original["exact"], d, config), + "prefix": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsPrefix(original["prefix"], d, config), + "suffix": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsSuffix(original["suffix"], d, config), + "contains": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsContains(original["contains"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsIgnoreCase(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsExact(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsPrefix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsSuffix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsContains(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPaths(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{}{ + "ignore_case": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsIgnoreCase(original["ignoreCase"], d, config), + "exact": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsExact(original["exact"], d, config), + "prefix": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsPrefix(original["prefix"], d, config), + "suffix": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsSuffix(original["suffix"], d, config), + "contains": flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsContains(original["contains"], d, config), + }) + } + return transformed +} +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsIgnoreCase(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsExact(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsPrefix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsSuffix(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsContains(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesToOperationsMethods(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyHttpRulesWhen(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyAction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyCustomProvider(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["cloud_iap"] = + flattenNetworkSecurityAuthzPolicyCustomProviderCloudIap(original["cloudIap"], d, config) + transformed["authz_extension"] = + flattenNetworkSecurityAuthzPolicyCustomProviderAuthzExtension(original["authzExtension"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyCustomProviderCloudIap(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + transformed := make(map[string]interface{}) + transformed["enabled"] = true + return []interface{}{transformed} +} + +func flattenNetworkSecurityAuthzPolicyCustomProviderAuthzExtension(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["resources"] = + flattenNetworkSecurityAuthzPolicyCustomProviderAuthzExtensionResources(original["resources"], d, config) + return []interface{}{transformed} +} +func flattenNetworkSecurityAuthzPolicyCustomProviderAuthzExtensionResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyTerraformLabels(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 flattenNetworkSecurityAuthzPolicyEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkSecurityAuthzPolicyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return tpgresource.NameFromSelfLinkStateFunc(v) +} + +func expandNetworkSecurityAuthzPolicyDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyTarget(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{}) + + transformedLoadBalancingScheme, err := expandNetworkSecurityAuthzPolicyTargetLoadBalancingScheme(original["load_balancing_scheme"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLoadBalancingScheme); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loadBalancingScheme"] = transformedLoadBalancingScheme + } + + transformedResources, err := expandNetworkSecurityAuthzPolicyTargetResources(original["resources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["resources"] = transformedResources + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyTargetLoadBalancingScheme(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyTargetResources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRules(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{}) + + transformedFrom, err := expandNetworkSecurityAuthzPolicyHttpRulesFrom(original["from"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFrom); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["from"] = transformedFrom + } + + transformedTo, err := expandNetworkSecurityAuthzPolicyHttpRulesTo(original["to"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTo); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["to"] = transformedTo + } + + transformedWhen, err := expandNetworkSecurityAuthzPolicyHttpRulesWhen(original["when"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedWhen); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["when"] = transformedWhen + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFrom(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{}) + + transformedSources, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSources(original["sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sources"] = transformedSources + } + + transformedNotSources, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSources(original["not_sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNotSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["notSources"] = transformedNotSources + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSources(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{}) + + transformedPrincipals, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipals(original["principals"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrincipals); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["principals"] = transformedPrincipals + } + + transformedResources, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResources(original["resources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["resources"] = transformedResources + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipals(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{}) + + transformedIgnoreCase, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedExact, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsExact(original["exact"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExact); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["exact"] = transformedExact + } + + transformedPrefix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsPrefix(original["prefix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["prefix"] = transformedPrefix + } + + transformedSuffix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsSuffix(original["suffix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["suffix"] = transformedSuffix + } + + transformedContains, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsContains(original["contains"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContains); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["contains"] = transformedContains + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsIgnoreCase(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsExact(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsPrefix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsSuffix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesPrincipalsContains(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResources(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{}) + + transformedTagValueIdSet, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSet(original["tag_value_id_set"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTagValueIdSet); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["tagValueIdSet"] = transformedTagValueIdSet + } + + transformedIamServiceAccount, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccount(original["iam_service_account"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIamServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["iamServiceAccount"] = transformedIamServiceAccount + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSet(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{}) + + transformedIds, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSetIds(original["ids"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIds); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ids"] = transformedIds + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesTagValueIdSetIds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccount(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{}) + + transformedIgnoreCase, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedExact, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountExact(original["exact"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExact); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["exact"] = transformedExact + } + + transformedPrefix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountPrefix(original["prefix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["prefix"] = transformedPrefix + } + + transformedSuffix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountSuffix(original["suffix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["suffix"] = transformedSuffix + } + + transformedContains, err := expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountContains(original["contains"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContains); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["contains"] = transformedContains + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountIgnoreCase(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountExact(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountPrefix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountSuffix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromSourcesResourcesIamServiceAccountContains(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSources(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{}) + + transformedPrincipals, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipals(original["principals"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrincipals); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["principals"] = transformedPrincipals + } + + transformedResources, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResources(original["resources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["resources"] = transformedResources + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipals(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{}) + + transformedIgnoreCase, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedExact, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsExact(original["exact"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExact); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["exact"] = transformedExact + } + + transformedPrefix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsPrefix(original["prefix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["prefix"] = transformedPrefix + } + + transformedSuffix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsSuffix(original["suffix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["suffix"] = transformedSuffix + } + + transformedContains, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsContains(original["contains"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContains); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["contains"] = transformedContains + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsIgnoreCase(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsExact(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsPrefix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsSuffix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesPrincipalsContains(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResources(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{}) + + transformedTagValueIdSet, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSet(original["tag_value_id_set"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTagValueIdSet); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["tagValueIdSet"] = transformedTagValueIdSet + } + + transformedIamServiceAccount, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccount(original["iam_service_account"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIamServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["iamServiceAccount"] = transformedIamServiceAccount + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSet(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{}) + + transformedIds, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSetIds(original["ids"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIds); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ids"] = transformedIds + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesTagValueIdSetIds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccount(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{}) + + transformedIgnoreCase, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedExact, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountExact(original["exact"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExact); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["exact"] = transformedExact + } + + transformedPrefix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountPrefix(original["prefix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["prefix"] = transformedPrefix + } + + transformedSuffix, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountSuffix(original["suffix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["suffix"] = transformedSuffix + } + + transformedContains, err := expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountContains(original["contains"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContains); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["contains"] = transformedContains + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountIgnoreCase(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountExact(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountPrefix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountSuffix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesFromNotSourcesResourcesIamServiceAccountContains(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesTo(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{}) + + transformedOperations, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperations(original["operations"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedOperations); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["operations"] = transformedOperations + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperations(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{}) + + transformedHeaderSet, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSet(original["header_set"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderSet); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerSet"] = transformedHeaderSet + } + + transformedHosts, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHosts(original["hosts"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHosts); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["hosts"] = transformedHosts + } + + transformedPaths, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPaths(original["paths"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPaths); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["paths"] = transformedPaths + } + + transformedMethods, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsMethods(original["methods"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMethods); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["methods"] = transformedMethods + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSet(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{}) + + transformedHeaders, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeaders(original["headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headers"] = transformedHeaders + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeaders(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{}) + + transformedName, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["name"] = transformedName + } + + transformedValue, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValue(original["value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedValue); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["value"] = transformedValue + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValue(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{}) + + transformedIgnoreCase, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedExact, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueExact(original["exact"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExact); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["exact"] = transformedExact + } + + transformedPrefix, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValuePrefix(original["prefix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["prefix"] = transformedPrefix + } + + transformedSuffix, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueSuffix(original["suffix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["suffix"] = transformedSuffix + } + + transformedContains, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueContains(original["contains"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContains); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["contains"] = transformedContains + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueIgnoreCase(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueExact(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValuePrefix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueSuffix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHeaderSetHeadersValueContains(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHosts(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{}) + + transformedIgnoreCase, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedExact, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsExact(original["exact"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExact); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["exact"] = transformedExact + } + + transformedPrefix, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsPrefix(original["prefix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["prefix"] = transformedPrefix + } + + transformedSuffix, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsSuffix(original["suffix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["suffix"] = transformedSuffix + } + + transformedContains, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsContains(original["contains"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContains); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["contains"] = transformedContains + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsIgnoreCase(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsExact(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsPrefix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsSuffix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsHostsContains(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPaths(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{}) + + transformedIgnoreCase, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedExact, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsExact(original["exact"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExact); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["exact"] = transformedExact + } + + transformedPrefix, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsPrefix(original["prefix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["prefix"] = transformedPrefix + } + + transformedSuffix, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsSuffix(original["suffix"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffix); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["suffix"] = transformedSuffix + } + + transformedContains, err := expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsContains(original["contains"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContains); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["contains"] = transformedContains + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsIgnoreCase(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsExact(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsPrefix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsSuffix(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsPathsContains(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesToOperationsMethods(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyHttpRulesWhen(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyAction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyCustomProvider(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{}) + + transformedCloudIap, err := expandNetworkSecurityAuthzPolicyCustomProviderCloudIap(original["cloud_iap"], d, config) + if err != nil { + return nil, err + } else { + transformed["cloudIap"] = transformedCloudIap + } + + transformedAuthzExtension, err := expandNetworkSecurityAuthzPolicyCustomProviderAuthzExtension(original["authz_extension"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAuthzExtension); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["authzExtension"] = transformedAuthzExtension + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyCustomProviderCloudIap(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{}) + if isEnabled, ok := original["enabled"]; ok { + if !isEnabled.(bool) { + return nil, nil + } + } + transformed := make(map[string]interface{}) + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyCustomProviderAuthzExtension(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{}) + + transformedResources, err := expandNetworkSecurityAuthzPolicyCustomProviderAuthzExtensionResources(original["resources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["resources"] = transformedResources + } + + return transformed, nil +} + +func expandNetworkSecurityAuthzPolicyCustomProviderAuthzExtensionResources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkSecurityAuthzPolicyEffectiveLabels(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 +} + +func expandNetworkSecurityAuthzPolicyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return fmt.Sprintf("projects/%s/locations/%s/authzPolicies/%s", d.Get("project"), d.Get("location"), v), nil +} diff --git a/google-beta/services/networksecurity/resource_network_security_authz_policy_generated_meta.yaml b/google-beta/services/networksecurity/resource_network_security_authz_policy_generated_meta.yaml new file mode 100644 index 0000000000..6bc16f3639 --- /dev/null +++ b/google-beta/services/networksecurity/resource_network_security_authz_policy_generated_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_network_security_authz_policy' +generation_type: 'mmv1' +api_service_name: 'networksecurity.googleapis.com' +api_version: 'v1beta1' +api_resource_type_kind: 'AuthzPolicy' diff --git a/google-beta/services/networksecurity/resource_network_security_authz_policy_generated_test.go b/google-beta/services/networksecurity/resource_network_security_authz_policy_generated_test.go new file mode 100644 index 0000000000..e114e3fd7e --- /dev/null +++ b/google-beta/services/networksecurity/resource_network_security_authz_policy_generated_test.go @@ -0,0 +1,225 @@ +// 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-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func TestAccNetworkSecurityAuthzPolicy_networkServicesAuthzPolicyAdvancedExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkSecurityAuthzPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityAuthzPolicy_networkServicesAuthzPolicyAdvancedExample(context), + }, + { + ResourceName: "google_network_security_authz_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "location", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecurityAuthzPolicy_networkServicesAuthzPolicyAdvancedExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + name = "tf-test-lb-network%{random_suffix}" + project = "%{project}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + name = "tf-test-backend-subnet%{random_suffix}" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.1.2.0/24" + network = google_compute_network.default.id +} + +resource "google_compute_subnetwork" "proxy_only" { + name = "tf-test-proxy-only-subnet%{random_suffix}" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.129.0.0/23" + purpose = "REGIONAL_MANAGED_PROXY" + role = "ACTIVE" + network = google_compute_network.default.id +} + +resource "google_compute_address" "default" { + name = "tf-test-l7-ilb-ip-address%{random_suffix}" + project = "%{project}" + region = "us-west1" + subnetwork = google_compute_subnetwork.default.id + address_type = "INTERNAL" + purpose = "GCE_ENDPOINT" +} + +resource "google_compute_region_health_check" "default" { + name = "tf-test-l7-ilb-basic-check%{random_suffix}" + project = "%{project}" + region = "us-west1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} + +resource "google_compute_region_backend_service" "url_map" { + name = "tf-test-l7-ilb-backend-service%{random_suffix}" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_url_map" "default" { + name = "tf-test-l7-ilb-map%{random_suffix}" + project = "%{project}" + region = "us-west1" + default_service = google_compute_region_backend_service.url_map.id +} + +resource "google_compute_region_target_http_proxy" "default" { + name = "tf-test-l7-ilb-proxy%{random_suffix}" + project = "%{project}" + region = "us-west1" + url_map = google_compute_region_url_map.default.id +} + +resource "google_compute_forwarding_rule" "default" { + name = "tf-test-l7-ilb-forwarding-rule%{random_suffix}" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + ip_protocol = "TCP" + port_range = "80" + target = google_compute_region_target_http_proxy.default.id + ip_address = google_compute_address.default.id + + depends_on = [google_compute_subnetwork.proxy_only] +} + +resource "google_compute_region_backend_service" "authz_extension" { + name = "tf-test-authz-service%{random_suffix}" + project = "%{project}" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_network_services_authz_extension" "default" { + name = "tf-test-my-authz-ext%{random_suffix}" + project = "%{project}" + location = "us-west1" + + description = "my description" + load_balancing_scheme = "INTERNAL_MANAGED" + authority = "ext11.com" + service = google_compute_region_backend_service.authz_extension.self_link + timeout = "0.1s" + fail_open = false + forward_headers = ["Authorization"] +} + +resource "google_network_security_authz_policy" "default" { + name = "tf-test-my-authz-policy%{random_suffix}" + project = "%{project}" + location = "us-west1" + description = "my description" + + target { + load_balancing_scheme = "INTERNAL_MANAGED" + resources = [ google_compute_forwarding_rule.default.self_link ] + } + + action = "CUSTOM" + custom_provider { + authz_extension { + resources = [ google_network_services_authz_extension.default.id ] + } + } +} +`, context) +} + +func testAccCheckNetworkSecurityAuthzPolicyDestroyProducer(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_authz_policy" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}projects/{{project}}/locations/{{location}}/authzPolicies/{{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("NetworkSecurityAuthzPolicy still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/services/networksecurity/resource_network_security_authz_policy_sweeper.go b/google-beta/services/networksecurity/resource_network_security_authz_policy_sweeper.go new file mode 100644 index 0000000000..5d56c8f46b --- /dev/null +++ b/google-beta/services/networksecurity/resource_network_security_authz_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-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/sweeper" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkSecurityAuthzPolicy", testSweepNetworkSecurityAuthzPolicy) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkSecurityAuthzPolicy(region string) error { + resourceName := "NetworkSecurityAuthzPolicy" + 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/v1beta1/projects/{{project}}/locations/{{location}}/authzPolicies", "?")[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["authzPolicies"] + 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/v1beta1/projects/{{project}}/locations/{{location}}/authzPolicies/{{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-beta/services/networksecurity/resource_network_services_authz_policy_test.go b/google-beta/services/networksecurity/resource_network_services_authz_policy_test.go new file mode 100644 index 0000000000..b8d70c3436 --- /dev/null +++ b/google-beta/services/networksecurity/resource_network_services_authz_policy_test.go @@ -0,0 +1,367 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package networksecurity_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" +) + +func TestAccNetworkSecurityAuthzPolicy_networkServicesAuthzPolicyHttpRules(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkSecurityAuthzPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityAuthzPolicy_networkServicesAuthzPolicyHttpRules(context), + }, + { + ResourceName: "google_network_security_authz_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "location", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecurityAuthzPolicy_networkServicesAuthzPolicyHttpRules(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + name = "lb-network-%{random_suffix}" + project = "%{project}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + name = "backend-subnet-%{random_suffix}" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.1.2.0/24" + network = google_compute_network.default.id +} + +resource "google_compute_subnetwork" "proxy_only" { + name = "proxy-only-subnet-%{random_suffix}" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.129.0.0/23" + purpose = "REGIONAL_MANAGED_PROXY" + role = "ACTIVE" + network = google_compute_network.default.id +} + +resource "google_compute_address" "default" { + name = "l7-ilb-ip-address-%{random_suffix}" + project = "%{project}" + region = "us-west1" + subnetwork = google_compute_subnetwork.default.id + address_type = "INTERNAL" + purpose = "GCE_ENDPOINT" +} + +resource "google_compute_region_health_check" "default" { + name = "l7-ilb-basic-check-%{random_suffix}" + project = "%{project}" + region = "us-west1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} + +resource "google_compute_region_backend_service" "url_map" { + name = "l7-ilb-backend-service-%{random_suffix}" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_url_map" "default" { + name = "l7-ilb-map-%{random_suffix}" + project = "%{project}" + region = "us-west1" + default_service = google_compute_region_backend_service.url_map.id +} + +resource "google_compute_region_target_http_proxy" "default" { + name = "l7-ilb-proxy-%{random_suffix}" + project = "%{project}" + region = "us-west1" + url_map = google_compute_region_url_map.default.id +} + +resource "google_compute_forwarding_rule" "default" { + name = "l7-ilb-forwarding-rule-%{random_suffix}" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + ip_protocol = "TCP" + port_range = "80" + target = google_compute_region_target_http_proxy.default.id + ip_address = google_compute_address.default.id + + depends_on = [google_compute_subnetwork.proxy_only] +} + +resource "google_compute_region_backend_service" "authz_extension" { + name = "authz-service-%{random_suffix}" + project = "%{project}" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_network_services_authz_extension" "default" { + name = "my-authz-ext-%{random_suffix}" + project = "%{project}" + location = "us-west1" + + description = "my description" + load_balancing_scheme = "INTERNAL_MANAGED" + authority = "ext11.com" + service = google_compute_region_backend_service.authz_extension.self_link + timeout = "0.1s" + fail_open = false + forward_headers = ["Authorization"] +} + +resource "google_network_security_authz_policy" "default" { + name = "tf-test-my-authz-policy-%{random_suffix}" + project = "%{project}" + location = "us-west1" + description = "my description" + + target { + load_balancing_scheme = "INTERNAL_MANAGED" + resources = [ google_compute_forwarding_rule.default.self_link ] + } + + action = "CUSTOM" + custom_provider { + authz_extension { + resources = [ google_network_services_authz_extension.default.id ] + } + } + + http_rules { + from { + not_sources { + # Prefix + principals { + ignore_case = false + prefix = "prefix" + } + resources { + iam_service_account { + ignore_case = false + prefix = "prefix" + } + tag_value_id_set { + ids = ["1"] + } + } + # Suffix / Ignore case + principals { + ignore_case = true + suffix = "suffix" + } + resources { + iam_service_account { + ignore_case = true + suffix = "suffix" + } + tag_value_id_set { + ids = ["2"] + } + } + # Exact + principals { + ignore_case = true + exact = "exact" + } + resources { + iam_service_account { + ignore_case = true + exact = "exact" + } + tag_value_id_set { + ids = ["3"] + } + } + # Contains / Ignore case + principals { + ignore_case = true + contains = "contains" + } + resources { + iam_service_account { + ignore_case = true + contains = "contains" + } + tag_value_id_set { + ids = ["4"] + } + } + } + sources { + # Prefix + principals { + ignore_case = false + prefix = "prefix" + } + resources { + iam_service_account { + ignore_case = false + prefix = "prefix" + } + tag_value_id_set { + ids = ["1"] + } + } + # Suffix / Ignore case + principals { + ignore_case = true + suffix = "suffix" + } + resources { + iam_service_account { + ignore_case = true + suffix = "suffix" + } + tag_value_id_set { + ids = ["2"] + } + } + # Exact + principals { + exact = "exact" + ignore_case = false + } + resources { + iam_service_account { + exact = "exact" + ignore_case = false + } + tag_value_id_set { + ids = ["3"] + } + } + # Contains / Ignore case + principals { + contains = "contains" + ignore_case = true + } + resources { + iam_service_account { + contains = "contains" + ignore_case = true + } + tag_value_id_set { + ids = ["4"] + } + } + } + } + to { + operations { + methods = ["GET", "PUT", "POST", "HEAD", "PATCH", "DELETE", "OPTIONS"] + header_set { + # Prefix + headers { + name = "PrefixHeader" + value { + ignore_case = false + prefix = "prefix" + } + } + # Suffix / Ignore case + headers { + name = "SuffixHeader" + value { + ignore_case = true + suffix = "suffix" + } + } + # Exact + headers { + name = "ExactHeader" + value { + exact = "exact" + ignore_case = false + } + } + # Contains / Ignore case + headers { + name = "ContainsHeader" + value { + contains = "contains" + ignore_case = true + } + } + } + # Prefix + hosts { + ignore_case = false + prefix = "prefix" + } + paths { + ignore_case = false + prefix = "prefix" + } + # Suffix / Ignore case + hosts { + ignore_case = true + suffix = "suffix" + } + paths { + ignore_case = true + suffix = "suffix" + } + # Exact + hosts { + exact = "exact" + ignore_case = false + } + paths { + exact = "exact" + ignore_case = false + } + # Contains / Ignore case + hosts { + contains = "contains" + ignore_case = true + } + paths { + contains = "contains" + ignore_case = true + } + } + } + when = "request.host.endsWith('.example.com')" + } + + labels = { + foo = "bar" + } +} +`, context) +} diff --git a/google-beta/services/networkservices/resource_network_services_authz_extension.go b/google-beta/services/networkservices/resource_network_services_authz_extension.go new file mode 100644 index 0000000000..45f40fbed2 --- /dev/null +++ b/google-beta/services/networkservices/resource_network_services_authz_extension.go @@ -0,0 +1,801 @@ +// 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 networkservices + +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-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" +) + +func ResourceNetworkServicesAuthzExtension() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkServicesAuthzExtensionCreate, + Read: resourceNetworkServicesAuthzExtensionRead, + Update: resourceNetworkServicesAuthzExtensionUpdate, + Delete: resourceNetworkServicesAuthzExtensionDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkServicesAuthzExtensionImport, + }, + + 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.SetLabelsDiff, + tpgresource.DefaultProviderProject, + ), + + Schema: map[string]*schema.Schema{ + "authority": { + Type: schema.TypeString, + Required: true, + Description: `The :authority header in the gRPC request sent from Envoy to the extension service.`, + }, + "load_balancing_scheme": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"INTERNAL_MANAGED", "EXTERNAL_MANAGED"}), + Description: `All backend services and forwarding rules referenced by this extension must share the same load balancing scheme. +For more information, refer to [Backend services overview](https://cloud.google.com/load-balancing/docs/backend-service). Possible values: ["INTERNAL_MANAGED", "EXTERNAL_MANAGED"]`, + }, + "location": { + Type: schema.TypeString, + Required: true, + Description: `The location of the resource.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: `Identifier. Name of the AuthzExtension resource.`, + }, + "service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: tpgresource.ProjectNumberDiffSuppress, + Description: `The reference to the service that runs the extension. +To configure a callout extension, service must be a fully-qualified reference to a [backend service](https://cloud.google.com/compute/docs/reference/rest/v1/backendServices) in the format: +https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/backendServices/{backendService} or https://www.googleapis.com/compute/v1/projects/{project}/global/backendServices/{backendService}.`, + }, + "timeout": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: tpgresource.DurationDiffSuppress, + Description: `Specifies the timeout for each individual message on the stream. The timeout must be between 10-10000 milliseconds.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `A human-readable description of the resource.`, + }, + "fail_open": { + Type: schema.TypeBool, + Computed: true, + Optional: true, + Description: `Determines how the proxy behaves if the call to the extension fails or times out. +When set to TRUE, request or response processing continues without error. Any subsequent extensions in the extension chain are also executed. When set to FALSE or the default setting of FALSE is used, one of the following happens: +* If response headers have not been delivered to the downstream client, a generic 500 error is returned to the client. The error response can be tailored by configuring a custom error response in the load balancer. +* If response headers have been delivered, then the HTTP stream to the downstream client is reset.`, + }, + "forward_headers": { + Type: schema.TypeList, + Optional: true, + Description: `List of the HTTP headers to forward to the extension (from the client). If omitted, all headers are sent. Each element is a string indicating the header name.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `Set of labels associated with the AuthzExtension 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}, + }, + "metadata": { + Type: schema.TypeMap, + Optional: true, + Description: `The metadata provided here is included as part of the metadata_context (of type google.protobuf.Struct) in the ProcessingRequest message sent to the extension server. The metadata is available under the namespace com.google.authz_extension.. The following variables are supported in the metadata Struct: + +{forwarding_rule_id} - substituted with the forwarding rule's fully qualified resource name.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "wire_format": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"WIRE_FORMAT_UNSPECIFIED", "EXT_PROC_GRPC", ""}), + Description: `The format of communication supported by the callout extension. Default value: "EXT_PROC_GRPC" Possible values: ["WIRE_FORMAT_UNSPECIFIED", "EXT_PROC_GRPC"]`, + Default: "EXT_PROC_GRPC", + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `The timestamp when the resource was created.`, + }, + "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}, + }, + "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: `The timestamp when the resource was updated.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkServicesAuthzExtensionCreate(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 := expandNetworkServicesAuthzExtensionDescription(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 + } + loadBalancingSchemeProp, err := expandNetworkServicesAuthzExtensionLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("load_balancing_scheme"); !tpgresource.IsEmptyValue(reflect.ValueOf(loadBalancingSchemeProp)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) { + obj["loadBalancingScheme"] = loadBalancingSchemeProp + } + authorityProp, err := expandNetworkServicesAuthzExtensionAuthority(d.Get("authority"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("authority"); !tpgresource.IsEmptyValue(reflect.ValueOf(authorityProp)) && (ok || !reflect.DeepEqual(v, authorityProp)) { + obj["authority"] = authorityProp + } + serviceProp, err := expandNetworkServicesAuthzExtensionService(d.Get("service"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("service"); !tpgresource.IsEmptyValue(reflect.ValueOf(serviceProp)) && (ok || !reflect.DeepEqual(v, serviceProp)) { + obj["service"] = serviceProp + } + timeoutProp, err := expandNetworkServicesAuthzExtensionTimeout(d.Get("timeout"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("timeout"); !tpgresource.IsEmptyValue(reflect.ValueOf(timeoutProp)) && (ok || !reflect.DeepEqual(v, timeoutProp)) { + obj["timeout"] = timeoutProp + } + failOpenProp, err := expandNetworkServicesAuthzExtensionFailOpen(d.Get("fail_open"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fail_open"); ok || !reflect.DeepEqual(v, failOpenProp) { + obj["failOpen"] = failOpenProp + } + metadataProp, err := expandNetworkServicesAuthzExtensionMetadata(d.Get("metadata"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("metadata"); !tpgresource.IsEmptyValue(reflect.ValueOf(metadataProp)) && (ok || !reflect.DeepEqual(v, metadataProp)) { + obj["metadata"] = metadataProp + } + forwardHeadersProp, err := expandNetworkServicesAuthzExtensionForwardHeaders(d.Get("forward_headers"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("forward_headers"); !tpgresource.IsEmptyValue(reflect.ValueOf(forwardHeadersProp)) && (ok || !reflect.DeepEqual(v, forwardHeadersProp)) { + obj["forwardHeaders"] = forwardHeadersProp + } + wireFormatProp, err := expandNetworkServicesAuthzExtensionWireFormat(d.Get("wire_format"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("wire_format"); !tpgresource.IsEmptyValue(reflect.ValueOf(wireFormatProp)) && (ok || !reflect.DeepEqual(v, wireFormatProp)) { + obj["wireFormat"] = wireFormatProp + } + labelsProp, err := expandNetworkServicesAuthzExtensionEffectiveLabels(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 + } + nameProp, err := expandNetworkServicesAuthzExtensionName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkServicesBasePath}}projects/{{project}}/locations/{{location}}/authzExtensions?authzExtensionId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new AuthzExtension: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for AuthzExtension: %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 AuthzExtension: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/authzExtensions/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkServicesOperationWaitTime( + config, res, project, "Creating AuthzExtension", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create AuthzExtension: %s", err) + } + + log.Printf("[DEBUG] Finished creating AuthzExtension %q: %#v", d.Id(), res) + + return resourceNetworkServicesAuthzExtensionRead(d, meta) +} + +func resourceNetworkServicesAuthzExtensionRead(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, "{{NetworkServicesBasePath}}projects/{{project}}/locations/{{location}}/authzExtensions/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for AuthzExtension: %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("NetworkServicesAuthzExtension %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + + if err := d.Set("create_time", flattenNetworkServicesAuthzExtensionCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("update_time", flattenNetworkServicesAuthzExtensionUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("description", flattenNetworkServicesAuthzExtensionDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("labels", flattenNetworkServicesAuthzExtensionLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("load_balancing_scheme", flattenNetworkServicesAuthzExtensionLoadBalancingScheme(res["loadBalancingScheme"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("authority", flattenNetworkServicesAuthzExtensionAuthority(res["authority"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("service", flattenNetworkServicesAuthzExtensionService(res["service"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("timeout", flattenNetworkServicesAuthzExtensionTimeout(res["timeout"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("fail_open", flattenNetworkServicesAuthzExtensionFailOpen(res["failOpen"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("metadata", flattenNetworkServicesAuthzExtensionMetadata(res["metadata"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("forward_headers", flattenNetworkServicesAuthzExtensionForwardHeaders(res["forwardHeaders"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("wire_format", flattenNetworkServicesAuthzExtensionWireFormat(res["wireFormat"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("terraform_labels", flattenNetworkServicesAuthzExtensionTerraformLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("effective_labels", flattenNetworkServicesAuthzExtensionEffectiveLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + if err := d.Set("name", flattenNetworkServicesAuthzExtensionName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading AuthzExtension: %s", err) + } + + return nil +} + +func resourceNetworkServicesAuthzExtensionUpdate(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 AuthzExtension: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkServicesAuthzExtensionDescription(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 + } + loadBalancingSchemeProp, err := expandNetworkServicesAuthzExtensionLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("load_balancing_scheme"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) { + obj["loadBalancingScheme"] = loadBalancingSchemeProp + } + authorityProp, err := expandNetworkServicesAuthzExtensionAuthority(d.Get("authority"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("authority"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, authorityProp)) { + obj["authority"] = authorityProp + } + serviceProp, err := expandNetworkServicesAuthzExtensionService(d.Get("service"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("service"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, serviceProp)) { + obj["service"] = serviceProp + } + timeoutProp, err := expandNetworkServicesAuthzExtensionTimeout(d.Get("timeout"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("timeout"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, timeoutProp)) { + obj["timeout"] = timeoutProp + } + failOpenProp, err := expandNetworkServicesAuthzExtensionFailOpen(d.Get("fail_open"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fail_open"); ok || !reflect.DeepEqual(v, failOpenProp) { + obj["failOpen"] = failOpenProp + } + metadataProp, err := expandNetworkServicesAuthzExtensionMetadata(d.Get("metadata"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("metadata"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, metadataProp)) { + obj["metadata"] = metadataProp + } + forwardHeadersProp, err := expandNetworkServicesAuthzExtensionForwardHeaders(d.Get("forward_headers"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("forward_headers"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, forwardHeadersProp)) { + obj["forwardHeaders"] = forwardHeadersProp + } + wireFormatProp, err := expandNetworkServicesAuthzExtensionWireFormat(d.Get("wire_format"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("wire_format"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, wireFormatProp)) { + obj["wireFormat"] = wireFormatProp + } + labelsProp, err := expandNetworkServicesAuthzExtensionEffectiveLabels(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 + } + nameProp, err := expandNetworkServicesAuthzExtensionName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkServicesBasePath}}projects/{{project}}/locations/{{location}}/authzExtensions/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating AuthzExtension %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("load_balancing_scheme") { + updateMask = append(updateMask, "loadBalancingScheme") + } + + if d.HasChange("authority") { + updateMask = append(updateMask, "authority") + } + + if d.HasChange("service") { + updateMask = append(updateMask, "service") + } + + if d.HasChange("timeout") { + updateMask = append(updateMask, "timeout") + } + + if d.HasChange("fail_open") { + updateMask = append(updateMask, "failOpen") + } + + if d.HasChange("metadata") { + updateMask = append(updateMask, "metadata") + } + + if d.HasChange("forward_headers") { + updateMask = append(updateMask, "forwardHeaders") + } + + if d.HasChange("wire_format") { + updateMask = append(updateMask, "wireFormat") + } + + if d.HasChange("effective_labels") { + updateMask = append(updateMask, "labels") + } + + if d.HasChange("name") { + updateMask = append(updateMask, "name") + } + // 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 AuthzExtension %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating AuthzExtension %q: %#v", d.Id(), res) + } + + err = NetworkServicesOperationWaitTime( + config, res, project, "Updating AuthzExtension", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceNetworkServicesAuthzExtensionRead(d, meta) +} + +func resourceNetworkServicesAuthzExtensionDelete(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 AuthzExtension: %s", err) + } + billingProject = project + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkServicesBasePath}}projects/{{project}}/locations/{{location}}/authzExtensions/{{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 AuthzExtension %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, "AuthzExtension") + } + + err = NetworkServicesOperationWaitTime( + config, res, project, "Deleting AuthzExtension", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting AuthzExtension %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkServicesAuthzExtensionImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/locations/(?P[^/]+)/authzExtensions/(?P[^/]+)$", + "^(?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}}/authzExtensions/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkServicesAuthzExtensionCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionLabels(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 flattenNetworkServicesAuthzExtensionLoadBalancingScheme(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionAuthority(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionService(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return tpgresource.ConvertSelfLinkToV1(v.(string)) +} + +func flattenNetworkServicesAuthzExtensionTimeout(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionFailOpen(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionMetadata(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionForwardHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionWireFormat(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil || tpgresource.IsEmptyValue(reflect.ValueOf(v)) { + return "EXT_PROC_GRPC" + } + + return v +} + +func flattenNetworkServicesAuthzExtensionTerraformLabels(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 flattenNetworkServicesAuthzExtensionEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesAuthzExtensionName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return tpgresource.NameFromSelfLinkStateFunc(v) +} + +func expandNetworkServicesAuthzExtensionDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionLoadBalancingScheme(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionAuthority(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionService(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionTimeout(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionFailOpen(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionMetadata(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 +} + +func expandNetworkServicesAuthzExtensionForwardHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionWireFormat(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesAuthzExtensionEffectiveLabels(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 +} + +func expandNetworkServicesAuthzExtensionName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return fmt.Sprintf("projects/%s/locations/%s/authzExtensions/%s", d.Get("project"), d.Get("location"), v), nil +} diff --git a/google-beta/services/networkservices/resource_network_services_authz_extension_generated_meta.yaml b/google-beta/services/networkservices/resource_network_services_authz_extension_generated_meta.yaml new file mode 100644 index 0000000000..e03e3880ed --- /dev/null +++ b/google-beta/services/networkservices/resource_network_services_authz_extension_generated_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_network_services_authz_extension' +generation_type: 'mmv1' +api_service_name: 'networkservices.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'AuthzExtension' diff --git a/google-beta/services/networkservices/resource_network_services_authz_extension_generated_test.go b/google-beta/services/networkservices/resource_network_services_authz_extension_generated_test.go new file mode 100644 index 0000000000..b0a1fe5cc2 --- /dev/null +++ b/google-beta/services/networkservices/resource_network_services_authz_extension_generated_test.go @@ -0,0 +1,125 @@ +// 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 networkservices_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func TestAccNetworkServicesAuthzExtension_networkServicesAuthzExtensionBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkServicesAuthzExtensionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkServicesAuthzExtension_networkServicesAuthzExtensionBasicExample(context), + }, + { + ResourceName: "google_network_services_authz_extension.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "location", "service", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkServicesAuthzExtension_networkServicesAuthzExtensionBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_region_backend_service" "default" { + name = "tf-test-authz-service%{random_suffix}" + project = "%{project}" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_network_services_authz_extension" "default" { + name = "tf-test-my-authz-ext%{random_suffix}" + project = "%{project}" + location = "us-west1" + + description = "my description" + load_balancing_scheme = "INTERNAL_MANAGED" + authority = "ext11.com" + service = google_compute_region_backend_service.default.self_link + timeout = "0.1s" + fail_open = false + forward_headers = ["Authorization"] +} +`, context) +} + +func testAccCheckNetworkServicesAuthzExtensionDestroyProducer(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_services_authz_extension" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkServicesBasePath}}projects/{{project}}/locations/{{location}}/authzExtensions/{{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("NetworkServicesAuthzExtension still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/services/networkservices/resource_network_services_authz_extension_sweeper.go b/google-beta/services/networkservices/resource_network_services_authz_extension_sweeper.go new file mode 100644 index 0000000000..dbc3a20431 --- /dev/null +++ b/google-beta/services/networkservices/resource_network_services_authz_extension_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 networkservices + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/sweeper" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkServicesAuthzExtension", testSweepNetworkServicesAuthzExtension) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkServicesAuthzExtension(region string) error { + resourceName := "NetworkServicesAuthzExtension" + 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://networkservices.googleapis.com/v1/projects/{{project}}/locations/{{location}}/authzExtensions", "?")[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["authzExtensions"] + 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://networkservices.googleapis.com/v1/projects/{{project}}/locations/{{location}}/authzExtensions/{{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-beta/services/networkservices/resource_network_services_authz_extension_test.go b/google-beta/services/networkservices/resource_network_services_authz_extension_test.go new file mode 100644 index 0000000000..4c8b1e42f8 --- /dev/null +++ b/google-beta/services/networkservices/resource_network_services_authz_extension_test.go @@ -0,0 +1,295 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package networkservices_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" +) + +func TestAccNetworkServicesAuthzExtension_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkServicesAuthzExtensionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkServicesAuthzExtension_start(context), + }, + { + ResourceName: "google_network_services_authz_extension.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "location", "service", "terraform_labels"}, + }, + { + Config: testAccNetworkServicesAuthzExtension_update(context), + }, + { + ResourceName: "google_network_services_authz_extension.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "location", "service", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkServicesAuthzExtension_start(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + name = "lb-network" + project = "%{project}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + name = "backend-subnet" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.1.2.0/24" + network = google_compute_network.default.id +} + +resource "google_compute_subnetwork" "proxy_only" { + name = "proxy-only-subnet" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.129.0.0/23" + purpose = "REGIONAL_MANAGED_PROXY" + role = "ACTIVE" + network = google_compute_network.default.id +} + +resource "google_compute_address" "default" { + name = "l7-ilb-ip-address" + project = "%{project}" + region = "us-west1" + subnetwork = google_compute_subnetwork.default.id + address_type = "INTERNAL" + purpose = "GCE_ENDPOINT" +} + + +resource "google_compute_region_health_check" "default" { + name = "l7-ilb-basic-check" + project = "%{project}" + region = "us-west1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} + +resource "google_compute_region_backend_service" "url_map" { + name = "l7-ilb-backend-service" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_forwarding_rule" "default" { + name = "l7-ilb-forwarding-rule" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + ip_protocol = "TCP" + port_range = "80" + target = google_compute_region_target_http_proxy.default.id + ip_address = google_compute_address.default.id + + depends_on = [google_compute_subnetwork.proxy_only] +} + +resource "google_compute_region_url_map" "default" { + name = "l7-ilb-map" + project = "%{project}" + region = "us-west1" + default_service = google_compute_region_backend_service.url_map.id +} + +resource "google_compute_region_target_http_proxy" "default" { + name = "l7-ilb-proxy" + project = "%{project}" + region = "us-west1" + url_map = google_compute_region_url_map.default.id +} + +resource "google_compute_region_backend_service" "default" { + name = "authz-service" + project = "%{project}" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_compute_region_backend_service" "updated" { + name = "authz-service-updated" + project = "%{project}" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_network_services_authz_extension" "default" { + name = "tf-test-my-authz-ext%{random_suffix}" + project = "%{project}" + location = "us-west1" + + description = "my description" + load_balancing_scheme = "INTERNAL_MANAGED" + authority = "ext11.com" + service = google_compute_region_backend_service.default.self_link + timeout = "0.1s" + fail_open = false + forward_headers = ["Authorization"] +} +`, context) +} + +func testAccNetworkServicesAuthzExtension_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + name = "lb-network" + project = "%{project}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + name = "backend-subnet" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.1.2.0/24" + network = google_compute_network.default.id +} + +resource "google_compute_subnetwork" "proxy_only" { + name = "proxy-only-subnet" + project = "%{project}" + region = "us-west1" + ip_cidr_range = "10.129.0.0/23" + purpose = "REGIONAL_MANAGED_PROXY" + role = "ACTIVE" + network = google_compute_network.default.id +} + +resource "google_compute_address" "default" { + name = "l7-ilb-ip-address" + project = "%{project}" + region = "us-west1" + subnetwork = google_compute_subnetwork.default.id + address_type = "INTERNAL" + purpose = "GCE_ENDPOINT" +} + +resource "google_compute_region_health_check" "default" { + name = "l7-ilb-basic-check" + project = "%{project}" + region = "us-west1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} + +resource "google_compute_region_backend_service" "url_map" { + name = "l7-ilb-backend-service" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_forwarding_rule" "default" { + name = "l7-ilb-forwarding-rule" + project = "%{project}" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + ip_protocol = "TCP" + port_range = "80" + target = google_compute_region_target_http_proxy.default.id + ip_address = google_compute_address.default.id + + depends_on = [google_compute_subnetwork.proxy_only] +} + +resource "google_compute_region_url_map" "default" { + name = "l7-ilb-map" + project = "%{project}" + region = "us-west1" + default_service = google_compute_region_backend_service.url_map.id +} + +resource "google_compute_region_target_http_proxy" "default" { + name = "l7-ilb-proxy" + project = "%{project}" + region = "us-west1" + url_map = google_compute_region_url_map.default.id +} + +resource "google_compute_region_backend_service" "default" { + name = "authz-service" + project = "%{project}" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_compute_region_backend_service" "updated" { + name = "authz-service-updated" + project = "%{project}" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_network_services_authz_extension" "default" { + name = "tf-test-my-authz-ext%{random_suffix}" + project = "%{project}" + location = "us-west1" + + description = "updated description" + load_balancing_scheme = "INTERNAL_MANAGED" + authority = "ext11.com" + service = google_compute_region_backend_service.updated.self_link + timeout = "0.1s" + fail_open = false + forward_headers = ["Authorization"] + wire_format = "EXT_PROC_GRPC" + + metadata = { + forwarding_rule_id = google_compute_forwarding_rule.default.id + } + + labels = { + foo = "bar" + } +} +`, context) +} diff --git a/website/docs/r/network_security_authz_policy.html.markdown b/website/docs/r/network_security_authz_policy.html.markdown new file mode 100644 index 0000000000..a8ed640ce8 --- /dev/null +++ b/website/docs/r/network_security_authz_policy.html.markdown @@ -0,0 +1,678 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** 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. +# +# ---------------------------------------------------------------------------- +subcategory: "Network security" +description: |- + AuthzPolicy is a resource that allows to forward traffic to a callout backend designed to scan the traffic for security purposes. +--- + +# google_network_security_authz_policy + +AuthzPolicy is a resource that allows to forward traffic to a callout backend designed to scan the traffic for security purposes. + + +To get more information about AuthzPolicy, see: + +* [API documentation](https://cloud.google.com/load-balancing/docs/reference/network-security/rest/v1beta1/projects.locations.authzPolicies) + +## Example Usage - Network Services Authz Policy Advanced + + +```hcl +resource "google_compute_network" "default" { + name = "lb-network" + project = "my-project-name" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + name = "backend-subnet" + project = "my-project-name" + region = "us-west1" + ip_cidr_range = "10.1.2.0/24" + network = google_compute_network.default.id +} + +resource "google_compute_subnetwork" "proxy_only" { + name = "proxy-only-subnet" + project = "my-project-name" + region = "us-west1" + ip_cidr_range = "10.129.0.0/23" + purpose = "REGIONAL_MANAGED_PROXY" + role = "ACTIVE" + network = google_compute_network.default.id +} + +resource "google_compute_address" "default" { + name = "l7-ilb-ip-address" + project = "my-project-name" + region = "us-west1" + subnetwork = google_compute_subnetwork.default.id + address_type = "INTERNAL" + purpose = "GCE_ENDPOINT" +} + +resource "google_compute_region_health_check" "default" { + name = "l7-ilb-basic-check" + project = "my-project-name" + region = "us-west1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} + +resource "google_compute_region_backend_service" "url_map" { + name = "l7-ilb-backend-service" + project = "my-project-name" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_url_map" "default" { + name = "l7-ilb-map" + project = "my-project-name" + region = "us-west1" + default_service = google_compute_region_backend_service.url_map.id +} + +resource "google_compute_region_target_http_proxy" "default" { + name = "l7-ilb-proxy" + project = "my-project-name" + region = "us-west1" + url_map = google_compute_region_url_map.default.id +} + +resource "google_compute_forwarding_rule" "default" { + name = "l7-ilb-forwarding-rule" + project = "my-project-name" + region = "us-west1" + load_balancing_scheme = "INTERNAL_MANAGED" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + ip_protocol = "TCP" + port_range = "80" + target = google_compute_region_target_http_proxy.default.id + ip_address = google_compute_address.default.id + + depends_on = [google_compute_subnetwork.proxy_only] +} + +resource "google_compute_region_backend_service" "authz_extension" { + name = "authz-service" + project = "my-project-name" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_network_services_authz_extension" "default" { + name = "my-authz-ext" + project = "my-project-name" + location = "us-west1" + + description = "my description" + load_balancing_scheme = "INTERNAL_MANAGED" + authority = "ext11.com" + service = google_compute_region_backend_service.authz_extension.self_link + timeout = "0.1s" + fail_open = false + forward_headers = ["Authorization"] +} + +resource "google_network_security_authz_policy" "default" { + name = "my-authz-policy" + project = "my-project-name" + location = "us-west1" + description = "my description" + + target { + load_balancing_scheme = "INTERNAL_MANAGED" + resources = [ google_compute_forwarding_rule.default.self_link ] + } + + action = "CUSTOM" + custom_provider { + authz_extension { + resources = [ google_network_services_authz_extension.default.id ] + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `target` - + (Required) + Specifies the set of resources to which this policy should be applied to. + Structure is [documented below](#nested_target). + +* `action` - + (Required) + When the action is CUSTOM, customProvider must be specified. + When the action is ALLOW, only requests matching the policy will be allowed. + When the action is DENY, only requests matching the policy will be denied. + When a request arrives, the policies are evaluated in the following order: + 1. If there is a CUSTOM policy that matches the request, the CUSTOM policy is evaluated using the custom authorization providers and the request is denied if the provider rejects the request. + 2. If there are any DENY policies that match the request, the request is denied. + 3. If there are no ALLOW policies for the resource or if any of the ALLOW policies match the request, the request is allowed. + 4. Else the request is denied by default if none of the configured AuthzPolicies with ALLOW action match the request. + Possible values are: `ALLOW`, `DENY`, `CUSTOM`. + +* `name` - + (Required) + Identifier. Name of the AuthzPolicy resource. + +* `location` - + (Required) + The location of the resource. + + +The `target` block supports: + +* `load_balancing_scheme` - + (Required) + All gateways and forwarding rules referenced by this policy and extensions must share the same load balancing scheme. + For more information, refer to [Backend services overview](https://cloud.google.com/load-balancing/docs/backend-service). + Possible values are: `INTERNAL_MANAGED`, `EXTERNAL_MANAGED`, `INTERNAL_SELF_MANAGED`. + +* `resources` - + (Optional) + A list of references to the Forwarding Rules on which this policy will be applied. + +- - - + + +* `description` - + (Optional) + A human-readable description of the resource. + +* `labels` - + (Optional) + Set of labels associated with the AuthzExtension 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. + +* `http_rules` - + (Optional) + A list of authorization HTTP rules to match against the incoming request.A policy match occurs when at least one HTTP rule matches the request or when no HTTP rules are specified in the policy. At least one HTTP Rule is required for Allow or Deny Action. + Limited to 5 rules. + Structure is [documented below](#nested_http_rules). + +* `custom_provider` - + (Optional) + Required if the action is CUSTOM. Allows delegating authorization decisions to Cloud IAP or to Service Extensions. One of cloudIap or authzExtension must be specified. + Structure is [documented below](#nested_custom_provider). + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `http_rules` block supports: + +* `from` - + (Optional) + Describes properties of one or more sources of a request. + Structure is [documented below](#nested_from). + +* `to` - + (Optional) + Describes properties of one or more targets of a request + Structure is [documented below](#nested_to). + +* `when` - + (Optional) + CEL expression that describes the conditions to be satisfied for the action. The result of the CEL expression is ANDed with the from and to. Refer to the CEL language reference for a list of available attributes. + + +The `from` block supports: + +* `sources` - + (Optional) + Describes the properties of a request's sources. At least one of sources or notSources must be specified. Limited to 5 sources. A match occurs when ANY source (in sources or notSources) matches the request. Within a single source, the match follows AND semantics across fields and OR semantics within a single field, i.e. a match occurs when ANY principal matches AND ANY ipBlocks match. + Structure is [documented below](#nested_sources). + +* `not_sources` - + (Optional) + Describes the properties of a request's sources. At least one of sources or notSources must be specified. Limited to 5 sources. A match occurs when ANY source (in sources or notSources) matches the request. Within a single source, the match follows AND semantics across fields and OR semantics within a single field, i.e. a match occurs when ANY principal matches AND ANY ipBlocks match. + Structure is [documented below](#nested_not_sources). + + +The `sources` block supports: + +* `principals` - + (Optional) + A list of identities derived from the client's certificate. This field will not match on a request unless mutual TLS is enabled for the Forwarding rule or Gateway. Each identity is a string whose value is matched against the URI SAN, or DNS SAN or the subject field in the client's certificate. The match can be exact, prefix, suffix or a substring match. One of exact, prefix, suffix or contains must be specified. + Limited to 5 principals. + Structure is [documented below](#nested_principals). + +* `resources` - + (Optional) + A list of resources to match against the resource of the source VM of a request. + Limited to 5 resources. + Structure is [documented below](#nested_resources). + + +The `principals` block supports: + +* `ignore_case` - + (Optional) + If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true. + +* `exact` - + (Optional) + The input string must match exactly the string specified here. + Examples: + * abc only matches the value abc. + +* `prefix` - + (Optional) + The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value abc.xyz + +* `suffix` - + (Optional) + The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc + +* `contains` - + (Optional) + The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc.def + +The `resources` block supports: + +* `tag_value_id_set` - + (Optional) + A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request. + Structure is [documented below](#nested_tag_value_id_set). + +* `iam_service_account` - + (Optional) + An IAM service account to match against the source service account of the VM sending the request. + Structure is [documented below](#nested_iam_service_account). + + +The `tag_value_id_set` block supports: + +* `ids` - + (Optional) + A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request. The match follows AND semantics which means all the ids must match. + Limited to 5 matches. + +The `iam_service_account` block supports: + +* `ignore_case` - + (Optional) + If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true. + +* `exact` - + (Optional) + The input string must match exactly the string specified here. + Examples: + * abc only matches the value abc. + +* `prefix` - + (Optional) + The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value abc.xyz + +* `suffix` - + (Optional) + The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc + +* `contains` - + (Optional) + The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc.def + +The `not_sources` block supports: + +* `principals` - + (Optional) + A list of identities derived from the client's certificate. This field will not match on a request unless mutual TLS is enabled for the Forwarding rule or Gateway. Each identity is a string whose value is matched against the URI SAN, or DNS SAN or the subject field in the client's certificate. The match can be exact, prefix, suffix or a substring match. One of exact, prefix, suffix or contains must be specified. + Limited to 5 principals. + Structure is [documented below](#nested_principals). + +* `resources` - + (Optional) + A list of resources to match against the resource of the source VM of a request. + Limited to 5 resources. + Structure is [documented below](#nested_resources). + + +The `principals` block supports: + +* `ignore_case` - + (Optional) + If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true. + +* `exact` - + (Optional) + The input string must match exactly the string specified here. + Examples: + * abc only matches the value abc. + +* `prefix` - + (Optional) + The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value abc.xyz + +* `suffix` - + (Optional) + The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc + +* `contains` - + (Optional) + The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc.def + +The `resources` block supports: + +* `tag_value_id_set` - + (Optional) + A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request. + Structure is [documented below](#nested_tag_value_id_set). + +* `iam_service_account` - + (Optional) + An IAM service account to match against the source service account of the VM sending the request. + Structure is [documented below](#nested_iam_service_account). + + +The `tag_value_id_set` block supports: + +* `ids` - + (Optional) + A list of resource tag value permanent IDs to match against the resource manager tags value associated with the source VM of a request. The match follows AND semantics which means all the ids must match. + Limited to 5 matches. + +The `iam_service_account` block supports: + +* `ignore_case` - + (Optional) + If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true. + +* `exact` - + (Optional) + The input string must match exactly the string specified here. + Examples: + * abc only matches the value abc. + +* `prefix` - + (Optional) + The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value abc.xyz + +* `suffix` - + (Optional) + The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc + +* `contains` - + (Optional) + The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc.def + +The `to` block supports: + +* `operations` - + (Optional) + Describes properties of one or more targets of a request. At least one of operations or notOperations must be specified. Limited to 5 operations. A match occurs when ANY operation (in operations or notOperations) matches. Within an operation, the match follows AND semantics across fields and OR semantics within a field, i.e. a match occurs when ANY path matches AND ANY header matches and ANY method matches. + Structure is [documented below](#nested_operations). + + +The `operations` block supports: + +* `header_set` - + (Optional) + A list of headers to match against in http header. + Structure is [documented below](#nested_header_set). + +* `hosts` - + (Optional) + A list of HTTP Hosts to match against. The match can be one of exact, prefix, suffix, or contains (substring match). Matches are always case sensitive unless the ignoreCase is set. + Limited to 5 matches. + Structure is [documented below](#nested_hosts). + +* `paths` - + (Optional) + A list of paths to match against. The match can be one of exact, prefix, suffix, or contains (substring match). Matches are always case sensitive unless the ignoreCase is set. + Limited to 5 matches. + Note that this path match includes the query parameters. For gRPC services, this should be a fully-qualified name of the form /package.service/method. + Structure is [documented below](#nested_paths). + +* `methods` - + (Optional) + A list of HTTP methods to match against. Each entry must be a valid HTTP method name (GET, PUT, POST, HEAD, PATCH, DELETE, OPTIONS). It only allows exact match and is always case sensitive. + + +The `header_set` block supports: + +* `headers` - + (Optional) + A list of headers to match against in http header. The match can be one of exact, prefix, suffix, or contains (substring match). The match follows AND semantics which means all the headers must match. Matches are always case sensitive unless the ignoreCase is set. Limited to 5 matches. + Structure is [documented below](#nested_headers). + + +The `headers` block supports: + +* `name` - + (Optional) + Specifies the name of the header in the request. + +* `value` - + (Optional) + Specifies how the header match will be performed. + Structure is [documented below](#nested_value). + + +The `value` block supports: + +* `ignore_case` - + (Optional) + If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true. + +* `exact` - + (Optional) + The input string must match exactly the string specified here. + Examples: + * abc only matches the value abc. + +* `prefix` - + (Optional) + The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value abc.xyz + +* `suffix` - + (Optional) + The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc + +* `contains` - + (Optional) + The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc.def + +The `hosts` block supports: + +* `ignore_case` - + (Optional) + If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true. + +* `exact` - + (Optional) + The input string must match exactly the string specified here. + Examples: + * abc only matches the value abc. + +* `prefix` - + (Optional) + The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value abc.xyz + +* `suffix` - + (Optional) + The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc + +* `contains` - + (Optional) + The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc.def + +The `paths` block supports: + +* `ignore_case` - + (Optional) + If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. For example, the matcher data will match both input string Data and data if set to true. + +* `exact` - + (Optional) + The input string must match exactly the string specified here. + Examples: + * abc only matches the value abc. + +* `prefix` - + (Optional) + The input string must have the prefix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value abc.xyz + +* `suffix` - + (Optional) + The input string must have the suffix specified here. Note: empty prefix is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc + +* `contains` - + (Optional) + The input string must have the substring specified here. Note: empty contains match is not allowed, please use regex instead. + Examples: + * abc matches the value xyz.abc.def + +The `custom_provider` block supports: + +* `cloud_iap` - + (Optional) + Delegates authorization decisions to Cloud IAP. Applicable only for managed load balancers. Enabling Cloud IAP at the AuthzPolicy level is not compatible with Cloud IAP settings in the BackendService. Enabling IAP in both places will result in request failure. Ensure that IAP is enabled in either the AuthzPolicy or the BackendService but not in both places. + Structure is [documented below](#nested_cloud_iap). + +* `authz_extension` - + (Optional) + Delegate authorization decision to user authored Service Extension. Only one of cloudIap or authzExtension can be specified. + Structure is [documented below](#nested_authz_extension). + + +The `cloud_iap` block supports: + +* `enabled` - + (Required) + Enable Cloud IAP at the AuthzPolicy level. + +The `authz_extension` block supports: + +* `resources` - + (Required) + A list of references to authorization extensions that will be invoked for requests matching this policy. Limited to 1 custom provider. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/authzPolicies/{{name}}` + +* `create_time` - + The timestamp when the resource was created. + +* `update_time` - + The timestamp when the resource was updated. + +* `terraform_labels` - + The combination of labels configured directly on the resource + and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 30 minutes. +- `update` - Default is 30 minutes. +- `delete` - Default is 30 minutes. + +## Import + + +AuthzPolicy can be imported using any of these accepted formats: + +* `projects/{{project}}/locations/{{location}}/authzPolicies/{{name}}` +* `{{project}}/{{location}}/{{name}}` +* `{{location}}/{{name}}` +* `{{name}}` + + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import AuthzPolicy using one of the formats above. For example: + +```tf +import { + id = "projects/{{project}}/locations/{{location}}/authzPolicies/{{name}}" + to = google_network_security_authz_policy.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), AuthzPolicy can be imported using one of the formats above. For example: + +``` +$ terraform import google_network_security_authz_policy.default projects/{{project}}/locations/{{location}}/authzPolicies/{{name}} +$ terraform import google_network_security_authz_policy.default {{project}}/{{location}}/{{name}} +$ terraform import google_network_security_authz_policy.default {{location}}/{{name}} +$ terraform import google_network_security_authz_policy.default {{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override). diff --git a/website/docs/r/network_services_authz_extension.html.markdown b/website/docs/r/network_services_authz_extension.html.markdown new file mode 100644 index 0000000000..ad37a56d32 --- /dev/null +++ b/website/docs/r/network_services_authz_extension.html.markdown @@ -0,0 +1,192 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** 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. +# +# ---------------------------------------------------------------------------- +subcategory: "Network services" +description: |- + AuthzExtension is a resource that allows traffic forwarding to a callout backend service to make an authorization decision. +--- + +# google_network_services_authz_extension + +AuthzExtension is a resource that allows traffic forwarding to a callout backend service to make an authorization decision. + + +To get more information about AuthzExtension, see: + +* [API documentation](https://cloud.google.com/service-extensions/docs/reference/rest/v1beta1/projects.locations.authzExtensions) + +## Example Usage - Network Services Authz Extension Basic + + +```hcl +resource "google_compute_region_backend_service" "default" { + name = "authz-service" + project = "my-project-name" + region = "us-west1" + + protocol = "HTTP2" + load_balancing_scheme = "INTERNAL_MANAGED" + port_name = "grpc" +} + +resource "google_network_services_authz_extension" "default" { + name = "my-authz-ext" + project = "my-project-name" + location = "us-west1" + + description = "my description" + load_balancing_scheme = "INTERNAL_MANAGED" + authority = "ext11.com" + service = google_compute_region_backend_service.default.self_link + timeout = "0.1s" + fail_open = false + forward_headers = ["Authorization"] +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `load_balancing_scheme` - + (Required) + All backend services and forwarding rules referenced by this extension must share the same load balancing scheme. + For more information, refer to [Backend services overview](https://cloud.google.com/load-balancing/docs/backend-service). + Possible values are: `INTERNAL_MANAGED`, `EXTERNAL_MANAGED`. + +* `authority` - + (Required) + The :authority header in the gRPC request sent from Envoy to the extension service. + +* `service` - + (Required) + The reference to the service that runs the extension. + To configure a callout extension, service must be a fully-qualified reference to a [backend service](https://cloud.google.com/compute/docs/reference/rest/v1/backendServices) in the format: + https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/backendServices/{backendService} or https://www.googleapis.com/compute/v1/projects/{project}/global/backendServices/{backendService}. + +* `timeout` - + (Required) + Specifies the timeout for each individual message on the stream. The timeout must be between 10-10000 milliseconds. + +* `name` - + (Required) + Identifier. Name of the AuthzExtension resource. + +* `location` - + (Required) + The location of the resource. + + +- - - + + +* `description` - + (Optional) + A human-readable description of the resource. + +* `labels` - + (Optional) + Set of labels associated with the AuthzExtension 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. + +* `fail_open` - + (Optional) + Determines how the proxy behaves if the call to the extension fails or times out. + When set to TRUE, request or response processing continues without error. Any subsequent extensions in the extension chain are also executed. When set to FALSE or the default setting of FALSE is used, one of the following happens: + * If response headers have not been delivered to the downstream client, a generic 500 error is returned to the client. The error response can be tailored by configuring a custom error response in the load balancer. + * If response headers have been delivered, then the HTTP stream to the downstream client is reset. + +* `metadata` - + (Optional) + The metadata provided here is included as part of the metadata_context (of type google.protobuf.Struct) in the ProcessingRequest message sent to the extension server. The metadata is available under the namespace com.google.authz_extension.. The following variables are supported in the metadata Struct: + {forwarding_rule_id} - substituted with the forwarding rule's fully qualified resource name. + +* `forward_headers` - + (Optional) + List of the HTTP headers to forward to the extension (from the client). If omitted, all headers are sent. Each element is a string indicating the header name. + +* `wire_format` - + (Optional) + The format of communication supported by the callout extension. + Default value is `EXT_PROC_GRPC`. + Possible values are: `WIRE_FORMAT_UNSPECIFIED`, `EXT_PROC_GRPC`. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/authzExtensions/{{name}}` + +* `create_time` - + The timestamp when the resource was created. + +* `update_time` - + The timestamp when the resource was updated. + +* `terraform_labels` - + The combination of labels configured directly on the resource + and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 30 minutes. +- `update` - Default is 30 minutes. +- `delete` - Default is 30 minutes. + +## Import + + +AuthzExtension can be imported using any of these accepted formats: + +* `projects/{{project}}/locations/{{location}}/authzExtensions/{{name}}` +* `{{project}}/{{location}}/{{name}}` +* `{{location}}/{{name}}` +* `{{name}}` + + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import AuthzExtension using one of the formats above. For example: + +```tf +import { + id = "projects/{{project}}/locations/{{location}}/authzExtensions/{{name}}" + to = google_network_services_authz_extension.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), AuthzExtension can be imported using one of the formats above. For example: + +``` +$ terraform import google_network_services_authz_extension.default projects/{{project}}/locations/{{location}}/authzExtensions/{{name}} +$ terraform import google_network_services_authz_extension.default {{project}}/{{location}}/{{name}} +$ terraform import google_network_services_authz_extension.default {{location}}/{{name}} +$ terraform import google_network_services_authz_extension.default {{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override).