Skip to content

Commit d756156

Browse files
Added new profile type "URL_FILTERING" for SecurityProfile (#13342) (#10829)
[upstream:571484033a581bd2b8289ba6b8da527012f4db95] Signed-off-by: Modular Magician <[email protected]>
1 parent 4afeb66 commit d756156

10 files changed

+641
-7
lines changed

.changelog/13342.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
```release-note:enhancement
2+
networksecurity: added `URL_FILTERING` option to enum field `type` for `google_network_security_security_profile` resource
3+
```
4+
```release-note:enhancement
5+
networksecurity: added `url_filtering_profile` field to `google_network_security_security_profile` resource (beta)
6+
```
7+
```release-note:enhancement
8+
networksecurity: added `url_filtering_profile` field to `google_network_security_security_profile_group` resource (beta)
9+
```

google-beta/services/networksecurity/resource_network_security_security_profile.go

Lines changed: 230 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ func ResourceNetworkSecuritySecurityProfile() *schema.Resource {
6767
Type: schema.TypeString,
6868
Required: true,
6969
ForceNew: true,
70-
ValidateFunc: verify.ValidateEnum([]string{"THREAT_PREVENTION", "CUSTOM_MIRRORING", "CUSTOM_INTERCEPT"}),
71-
Description: `The type of security profile. Possible values: ["THREAT_PREVENTION", "CUSTOM_MIRRORING", "CUSTOM_INTERCEPT"]`,
70+
ValidateFunc: verify.ValidateEnum([]string{"THREAT_PREVENTION", "URL_FILTERING", "CUSTOM_MIRRORING", "CUSTOM_INTERCEPT"}),
71+
Description: `The type of security profile. Possible values: ["THREAT_PREVENTION", "URL_FILTERING", "CUSTOM_MIRRORING", "CUSTOM_INTERCEPT"]`,
7272
},
7373
"custom_intercept_profile": {
7474
Type: schema.TypeList,
@@ -86,7 +86,7 @@ Format: projects/{project_id}/locations/global/interceptEndpointGroups/{endpoint
8686
},
8787
},
8888
},
89-
ConflictsWith: []string{"threat_prevention_profile", "custom_mirroring_profile"},
89+
ConflictsWith: []string{"threat_prevention_profile", "url_filtering_profile", "custom_mirroring_profile"},
9090
},
9191
"custom_mirroring_profile": {
9292
Type: schema.TypeList,
@@ -104,7 +104,7 @@ Format: projects/{project_id}/locations/global/mirroringEndpointGroups/{endpoint
104104
},
105105
},
106106
},
107-
ConflictsWith: []string{"threat_prevention_profile", "custom_intercept_profile"},
107+
ConflictsWith: []string{"threat_prevention_profile", "url_filtering_profile", "custom_intercept_profile"},
108108
},
109109
"description": {
110110
Type: schema.TypeString,
@@ -168,7 +168,27 @@ and threat overrides, the threat overrides action is applied.`,
168168
},
169169
},
170170
},
171-
ConflictsWith: []string{"custom_mirroring_profile", "custom_intercept_profile"},
171+
ConflictsWith: []string{"url_filtering_profile", "custom_mirroring_profile", "custom_intercept_profile"},
172+
},
173+
"url_filtering_profile": {
174+
Type: schema.TypeList,
175+
Optional: true,
176+
Description: `The url filtering configuration for the security profile.`,
177+
MaxItems: 1,
178+
Elem: &schema.Resource{
179+
Schema: map[string]*schema.Schema{
180+
"url_filters": {
181+
Type: schema.TypeSet,
182+
Optional: true,
183+
Description: `The configuration for action to take based on domain name match.
184+
A domain name would be checked for matching filters through the list in order of highest to lowest priority,
185+
and the first filter that a domain name matches with is the one whose actions gets applied.`,
186+
Elem: networksecuritySecurityProfileUrlFilteringProfileUrlFiltersSchema(),
187+
// Default schema.HashSchema is used.
188+
},
189+
},
190+
},
191+
ConflictsWith: []string{"threat_prevention_profile", "custom_mirroring_profile", "custom_intercept_profile"},
172192
},
173193
"create_time": {
174194
Type: schema.TypeString,
@@ -271,6 +291,35 @@ func networksecuritySecurityProfileThreatPreventionProfileAntivirusOverridesSche
271291
}
272292
}
273293

294+
func networksecuritySecurityProfileUrlFilteringProfileUrlFiltersSchema() *schema.Resource {
295+
return &schema.Resource{
296+
Schema: map[string]*schema.Schema{
297+
"filtering_action": {
298+
Type: schema.TypeString,
299+
Required: true,
300+
ValidateFunc: verify.ValidateEnum([]string{"ALLOW", "DENY"}),
301+
Description: `The action to take when the filter is applied. Possible values: ["ALLOW", "DENY"]`,
302+
},
303+
"priority": {
304+
Type: schema.TypeInt,
305+
Required: true,
306+
Description: `The priority of the filter within the URL filtering profile.
307+
Must be an integer from 0 and 2147483647, inclusive. Lower integers indicate higher priorities.
308+
The priority of a filter must be unique within a URL filtering profile.`,
309+
},
310+
"urls": {
311+
Type: schema.TypeList,
312+
Optional: true,
313+
Description: `A list of domain matcher strings that a domain name gets compared with to determine if the filter is applicable.
314+
A domain name must match with at least one of the strings in the list for a filter to be applicable.`,
315+
Elem: &schema.Schema{
316+
Type: schema.TypeString,
317+
},
318+
},
319+
},
320+
}
321+
}
322+
274323
func resourceNetworkSecuritySecurityProfileCreate(d *schema.ResourceData, meta interface{}) error {
275324
var project string
276325
config := meta.(*transport_tpg.Config)
@@ -292,6 +341,12 @@ func resourceNetworkSecuritySecurityProfileCreate(d *schema.ResourceData, meta i
292341
} else if v, ok := d.GetOkExists("threat_prevention_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(threatPreventionProfileProp)) && (ok || !reflect.DeepEqual(v, threatPreventionProfileProp)) {
293342
obj["threatPreventionProfile"] = threatPreventionProfileProp
294343
}
344+
urlFilteringProfileProp, err := expandNetworkSecuritySecurityProfileUrlFilteringProfile(d.Get("url_filtering_profile"), d, config)
345+
if err != nil {
346+
return err
347+
} else if v, ok := d.GetOkExists("url_filtering_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(urlFilteringProfileProp)) && (ok || !reflect.DeepEqual(v, urlFilteringProfileProp)) {
348+
obj["urlFilteringProfile"] = urlFilteringProfileProp
349+
}
295350
customMirroringProfileProp, err := expandNetworkSecuritySecurityProfileCustomMirroringProfile(d.Get("custom_mirroring_profile"), d, config)
296351
if err != nil {
297352
return err
@@ -420,6 +475,9 @@ func resourceNetworkSecuritySecurityProfileRead(d *schema.ResourceData, meta int
420475
if err := d.Set("threat_prevention_profile", flattenNetworkSecuritySecurityProfileThreatPreventionProfile(res["threatPreventionProfile"], d, config)); err != nil {
421476
return fmt.Errorf("Error reading SecurityProfile: %s", err)
422477
}
478+
if err := d.Set("url_filtering_profile", flattenNetworkSecuritySecurityProfileUrlFilteringProfile(res["urlFilteringProfile"], d, config)); err != nil {
479+
return fmt.Errorf("Error reading SecurityProfile: %s", err)
480+
}
423481
if err := d.Set("custom_mirroring_profile", flattenNetworkSecuritySecurityProfileCustomMirroringProfile(res["customMirroringProfile"], d, config)); err != nil {
424482
return fmt.Errorf("Error reading SecurityProfile: %s", err)
425483
}
@@ -462,6 +520,12 @@ func resourceNetworkSecuritySecurityProfileUpdate(d *schema.ResourceData, meta i
462520
} else if v, ok := d.GetOkExists("threat_prevention_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, threatPreventionProfileProp)) {
463521
obj["threatPreventionProfile"] = threatPreventionProfileProp
464522
}
523+
urlFilteringProfileProp, err := expandNetworkSecuritySecurityProfileUrlFilteringProfile(d.Get("url_filtering_profile"), d, config)
524+
if err != nil {
525+
return err
526+
} else if v, ok := d.GetOkExists("url_filtering_profile"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, urlFilteringProfileProp)) {
527+
obj["urlFilteringProfile"] = urlFilteringProfileProp
528+
}
465529
customMirroringProfileProp, err := expandNetworkSecuritySecurityProfileCustomMirroringProfile(d.Get("custom_mirroring_profile"), d, config)
466530
if err != nil {
467531
return err
@@ -498,6 +562,10 @@ func resourceNetworkSecuritySecurityProfileUpdate(d *schema.ResourceData, meta i
498562
updateMask = append(updateMask, "threatPreventionProfile")
499563
}
500564

565+
if d.HasChange("url_filtering_profile") {
566+
updateMask = append(updateMask, "urlFilteringProfile")
567+
}
568+
501569
if d.HasChange("custom_mirroring_profile") {
502570
updateMask = append(updateMask, "customMirroringProfile")
503571
}
@@ -759,6 +827,89 @@ func flattenNetworkSecuritySecurityProfileThreatPreventionProfileAntivirusOverri
759827
return v
760828
}
761829

830+
func flattenNetworkSecuritySecurityProfileUrlFilteringProfile(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
831+
if v == nil {
832+
return nil
833+
}
834+
original := v.(map[string]interface{})
835+
if len(original) == 0 {
836+
return nil
837+
}
838+
transformed := make(map[string]interface{})
839+
transformed["url_filters"] =
840+
flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFilters(original["urlFilters"], d, config)
841+
842+
// We check again the length after removing the default url_filter
843+
if transformed["url_filters"].(*schema.Set).Len() == 0 {
844+
return nil
845+
}
846+
return []interface{}{transformed}
847+
}
848+
func flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFilters(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
849+
if v == nil {
850+
return v
851+
}
852+
853+
// We check if the user included the default filter in his config
854+
resourceDataContainsDefaultFilter := false
855+
resourceData, ok := d.GetOk("url_filtering_profile.0.url_filters")
856+
if ok {
857+
for _, raw := range resourceData.(*schema.Set).List() {
858+
if raw.(map[string]interface{})["priority"] == 2147483647 {
859+
resourceDataContainsDefaultFilter = true
860+
break
861+
}
862+
}
863+
}
864+
865+
l := v.([]interface{})
866+
transformed := schema.NewSet(schema.HashResource(networksecuritySecurityProfileUrlFilteringProfileUrlFiltersSchema()), []interface{}{})
867+
for _, raw := range l {
868+
original := raw.(map[string]interface{})
869+
if len(original) < 1 {
870+
// Do not include empty json objects coming back from the api
871+
continue
872+
}
873+
874+
priorityFlatten := flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersPriority(original["priority"], d, config)
875+
// Do not include the auto created default url_filter coming back from the api unless the user included it in his config
876+
if priorityFlatten == 2147483647 && !resourceDataContainsDefaultFilter {
877+
continue
878+
}
879+
880+
transformed.Add(map[string]interface{}{
881+
"filtering_action": flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersFilteringAction(original["filteringAction"], d, config),
882+
"urls": flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersUrls(original["urls"], d, config),
883+
"priority": priorityFlatten,
884+
})
885+
}
886+
return transformed
887+
}
888+
func flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersFilteringAction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
889+
return v
890+
}
891+
892+
func flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersUrls(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
893+
return v
894+
}
895+
896+
func flattenNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersPriority(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
897+
// Handles the string fixed64 format
898+
if strVal, ok := v.(string); ok {
899+
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
900+
return intVal
901+
}
902+
}
903+
904+
// number values are represented as float64
905+
if floatVal, ok := v.(float64); ok {
906+
intVal := int(floatVal)
907+
return intVal
908+
}
909+
910+
return v // let terraform core handle it otherwise
911+
}
912+
762913
func flattenNetworkSecuritySecurityProfileCustomMirroringProfile(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
763914
if v == nil {
764915
return nil
@@ -990,6 +1141,80 @@ func expandNetworkSecuritySecurityProfileThreatPreventionProfileAntivirusOverrid
9901141
return v, nil
9911142
}
9921143

1144+
func expandNetworkSecuritySecurityProfileUrlFilteringProfile(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1145+
if v == nil {
1146+
return nil, nil
1147+
}
1148+
l := v.([]interface{})
1149+
if len(l) == 0 || l[0] == nil {
1150+
return nil, nil
1151+
}
1152+
raw := l[0]
1153+
original := raw.(map[string]interface{})
1154+
transformed := make(map[string]interface{})
1155+
1156+
transformedUrlFilters, err := expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFilters(original["url_filters"], d, config)
1157+
if err != nil {
1158+
return nil, err
1159+
} else if val := reflect.ValueOf(transformedUrlFilters); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1160+
transformed["urlFilters"] = transformedUrlFilters
1161+
}
1162+
1163+
return transformed, nil
1164+
}
1165+
1166+
func expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFilters(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1167+
v = v.(*schema.Set).List()
1168+
if v == nil {
1169+
return nil, nil
1170+
}
1171+
l := v.([]interface{})
1172+
req := make([]interface{}, 0, len(l))
1173+
for _, raw := range l {
1174+
if raw == nil {
1175+
continue
1176+
}
1177+
original := raw.(map[string]interface{})
1178+
transformed := make(map[string]interface{})
1179+
1180+
transformedFilteringAction, err := expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersFilteringAction(original["filtering_action"], d, config)
1181+
if err != nil {
1182+
return nil, err
1183+
} else if val := reflect.ValueOf(transformedFilteringAction); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1184+
transformed["filteringAction"] = transformedFilteringAction
1185+
}
1186+
1187+
transformedUrls, err := expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersUrls(original["urls"], d, config)
1188+
if err != nil {
1189+
return nil, err
1190+
} else if val := reflect.ValueOf(transformedUrls); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1191+
transformed["urls"] = transformedUrls
1192+
}
1193+
1194+
transformedPriority, err := expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersPriority(original["priority"], d, config)
1195+
if err != nil {
1196+
return nil, err
1197+
} else if val := reflect.ValueOf(transformedPriority); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1198+
transformed["priority"] = transformedPriority
1199+
}
1200+
1201+
req = append(req, transformed)
1202+
}
1203+
return req, nil
1204+
}
1205+
1206+
func expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersFilteringAction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1207+
return v, nil
1208+
}
1209+
1210+
func expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersUrls(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1211+
return v, nil
1212+
}
1213+
1214+
func expandNetworkSecuritySecurityProfileUrlFilteringProfileUrlFiltersPriority(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1215+
return v, nil
1216+
}
1217+
9931218
func expandNetworkSecuritySecurityProfileCustomMirroringProfile(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
9941219
if v == nil {
9951220
return nil, nil

google-beta/services/networksecurity/resource_network_security_security_profile_generated_meta.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ fields:
3131
- field: 'threat_prevention_profile.threat_overrides.type'
3232
- field: 'type'
3333
- field: 'update_time'
34+
- field: 'url_filtering_profile.url_filters.filtering_action'
35+
- field: 'url_filtering_profile.url_filters.priority'
36+
- field: 'url_filtering_profile.url_filters.urls'

google-beta/services/networksecurity/resource_network_security_security_profile_generated_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,61 @@ resource "google_network_security_security_profile" "default" {
255255
`, context)
256256
}
257257

258+
func TestAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileUrlFilteringExample(t *testing.T) {
259+
t.Parallel()
260+
261+
context := map[string]interface{}{
262+
"org_id": envvar.GetTestOrgFromEnv(t),
263+
"random_suffix": acctest.RandString(t, 10),
264+
}
265+
266+
acctest.VcrTest(t, resource.TestCase{
267+
PreCheck: func() { acctest.AccTestPreCheck(t) },
268+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
269+
CheckDestroy: testAccCheckNetworkSecuritySecurityProfileDestroyProducer(t),
270+
Steps: []resource.TestStep{
271+
{
272+
Config: testAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileUrlFilteringExample(context),
273+
},
274+
{
275+
ResourceName: "google_network_security_security_profile.default",
276+
ImportState: true,
277+
ImportStateVerify: true,
278+
ImportStateVerifyIgnore: []string{"labels", "location", "name", "parent", "terraform_labels"},
279+
},
280+
},
281+
})
282+
}
283+
284+
func testAccNetworkSecuritySecurityProfile_networkSecuritySecurityProfileUrlFilteringExample(context map[string]interface{}) string {
285+
return acctest.Nprintf(`
286+
resource "google_network_security_security_profile" "default" {
287+
provider = google-beta
288+
name = "tf-test-my-security-profile%{random_suffix}"
289+
parent = "organizations/%{org_id}"
290+
description = "my description"
291+
type = "URL_FILTERING"
292+
293+
url_filtering_profile {
294+
url_filters {
295+
priority = 1
296+
filtering_action = "ALLOW"
297+
urls = ["*example.com", "*about.example.com", "*help.example.com"]
298+
}
299+
url_filters {
300+
priority = 2
301+
filtering_action = "DENY"
302+
urls = ["*restricted.example.com"]
303+
}
304+
}
305+
306+
labels = {
307+
foo = "bar"
308+
}
309+
}
310+
`, context)
311+
}
312+
258313
func testAccCheckNetworkSecuritySecurityProfileDestroyProducer(t *testing.T) func(s *terraform.State) error {
259314
return func(s *terraform.State) error {
260315
for name, rs := range s.RootModule().Resources {

0 commit comments

Comments
 (0)