Skip to content

Commit a4cdb25

Browse files
authoredMar 31, 2021
azurerm_web_application_firewall_policy: add http_listener_ids and path_based_rule_ids (#10860)
Fixes #10859. Not sure about the syntax in the acceptance test when referencing the path based rule IDs.
1 parent 19c81ef commit a4cdb25

13 files changed

+850
-3
lines changed
 

‎azurerm/internal/services/network/application_gateway_resource_test.go

+150
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,21 @@ func TestAccApplicationGateway_customHttpListenerFirewallPolicy(t *testing.T) {
225225
})
226226
}
227227

228+
func TestAccApplicationGateway_customHttpListenerFirewallPolicyWithAssociations(t *testing.T) {
229+
data := acceptance.BuildTestData(t, "azurerm_application_gateway", "test")
230+
r := ApplicationGatewayResource{}
231+
232+
data.ResourceTest(t, r, []resource.TestStep{
233+
{
234+
Config: r.customHttpListenerFirewallPolicyWithAssociations(data),
235+
Check: resource.ComposeTestCheckFunc(
236+
check.That(data.ResourceName).ExistsInAzure(r),
237+
),
238+
},
239+
data.ImportStep(),
240+
})
241+
}
242+
228243
// TODO required soft delete on the keyvault
229244
func TestAccApplicationGateway_trustedRootCertificate_keyvault(t *testing.T) {
230245
t.Skip()
@@ -2085,6 +2100,141 @@ resource "azurerm_application_gateway" "test" {
20852100
`, r.template(data), data.RandomInteger)
20862101
}
20872102

2103+
func (r ApplicationGatewayResource) customHttpListenerFirewallPolicyWithAssociations(data acceptance.TestData) string {
2104+
return fmt.Sprintf(`
2105+
%[1]s
2106+
2107+
# since these variables are re-used - a locals block makes this more maintainable
2108+
locals {
2109+
backend_address_pool_name = "${azurerm_virtual_network.test.name}-beap"
2110+
frontend_port_name = "${azurerm_virtual_network.test.name}-feport"
2111+
frontend_ip_configuration_name = "${azurerm_virtual_network.test.name}-feip"
2112+
http_setting_name = "${azurerm_virtual_network.test.name}-be-htst"
2113+
listener_name = "${azurerm_virtual_network.test.name}-httplstn"
2114+
request_routing_rule_name = "${azurerm_virtual_network.test.name}-rqrt"
2115+
}
2116+
2117+
resource "azurerm_public_ip" "teststd" {
2118+
name = "acctest-PubIpStd-%[2]d"
2119+
location = azurerm_resource_group.test.location
2120+
resource_group_name = azurerm_resource_group.test.name
2121+
allocation_method = "Static"
2122+
sku = "Standard"
2123+
}
2124+
2125+
resource "azurerm_application_gateway" "test" {
2126+
name = "acctestag-%[2]d"
2127+
resource_group_name = azurerm_resource_group.test.name
2128+
location = azurerm_resource_group.test.location
2129+
2130+
sku {
2131+
name = "WAF_v2"
2132+
tier = "WAF_v2"
2133+
capacity = 2
2134+
}
2135+
2136+
gateway_ip_configuration {
2137+
name = "my-gateway-ip-configuration"
2138+
subnet_id = azurerm_subnet.test.id
2139+
}
2140+
2141+
frontend_port {
2142+
name = local.frontend_port_name
2143+
port = 80
2144+
}
2145+
2146+
frontend_ip_configuration {
2147+
name = local.frontend_ip_configuration_name
2148+
public_ip_address_id = azurerm_public_ip.teststd.id
2149+
}
2150+
2151+
backend_address_pool {
2152+
name = local.backend_address_pool_name
2153+
}
2154+
2155+
backend_http_settings {
2156+
name = local.http_setting_name
2157+
cookie_based_affinity = "Disabled"
2158+
port = 443
2159+
protocol = "Https"
2160+
request_timeout = 1
2161+
2162+
pick_host_name_from_backend_address = true
2163+
}
2164+
2165+
http_listener {
2166+
name = local.listener_name
2167+
frontend_ip_configuration_name = local.frontend_ip_configuration_name
2168+
frontend_port_name = local.frontend_port_name
2169+
protocol = "Http"
2170+
firewall_policy_id = azurerm_web_application_firewall_policy.testfwp_listener.id
2171+
}
2172+
2173+
request_routing_rule {
2174+
name = local.request_routing_rule_name
2175+
rule_type = "Basic"
2176+
http_listener_name = local.listener_name
2177+
backend_address_pool_name = local.backend_address_pool_name
2178+
backend_http_settings_name = local.http_setting_name
2179+
}
2180+
2181+
url_path_map {
2182+
name = local.url_path_map_name
2183+
default_backend_address_pool_name = local.backend_address_pool_name
2184+
default_backend_http_settings_name = local.http_setting_name
2185+
2186+
path_rule {
2187+
name = local.path_rule_name
2188+
backend_address_pool_name = local.backend_address_pool_name
2189+
backend_http_settings_name = local.http_setting_name
2190+
2191+
paths = [
2192+
"/test",
2193+
]
2194+
}
2195+
}
2196+
}
2197+
2198+
resource "azurerm_web_application_firewall_policy" "testfwp" {
2199+
name = "acctest-fwp-%[2]d"
2200+
resource_group_name = azurerm_resource_group.test.name
2201+
location = azurerm_resource_group.test.location
2202+
2203+
policy_settings {
2204+
enabled = true
2205+
mode = "Prevention"
2206+
}
2207+
2208+
managed_rules {
2209+
managed_rule_set {
2210+
type = "OWASP"
2211+
version = "3.1"
2212+
}
2213+
}
2214+
}
2215+
2216+
resource "azurerm_web_application_firewall_policy" "testfwp_listener" {
2217+
name = "acctest-fwp-listener-%[2]d"
2218+
resource_group_name = azurerm_resource_group.test.name
2219+
location = azurerm_resource_group.test.location
2220+
http_listener_ids = [for v in azurerm_application_gateway.test.http_listener : v.id]
2221+
path_based_rule_ids = flatten([for v in azurerm_application_gateway.test.url_path_map : [for w in v.path_rule : w.id]])
2222+
2223+
policy_settings {
2224+
enabled = true
2225+
mode = "Prevention"
2226+
}
2227+
2228+
managed_rules {
2229+
managed_rule_set {
2230+
type = "OWASP"
2231+
version = "3.1"
2232+
}
2233+
}
2234+
}
2235+
`, r.template(data), data.RandomInteger)
2236+
}
2237+
20882238
func (r ApplicationGatewayResource) authCertificateUpdated(data acceptance.TestData) string {
20892239
return fmt.Sprintf(`
20902240
%[1]s
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package parse
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import (
6+
"fmt"
7+
"strings"
8+
9+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
10+
)
11+
12+
type ApplicationGatewayHTTPListenerId struct {
13+
SubscriptionId string
14+
ResourceGroup string
15+
ApplicationGatewayName string
16+
HttpListenerName string
17+
}
18+
19+
func NewApplicationGatewayHTTPListenerID(subscriptionId, resourceGroup, applicationGatewayName, httpListenerName string) ApplicationGatewayHTTPListenerId {
20+
return ApplicationGatewayHTTPListenerId{
21+
SubscriptionId: subscriptionId,
22+
ResourceGroup: resourceGroup,
23+
ApplicationGatewayName: applicationGatewayName,
24+
HttpListenerName: httpListenerName,
25+
}
26+
}
27+
28+
func (id ApplicationGatewayHTTPListenerId) String() string {
29+
segments := []string{
30+
fmt.Sprintf("Http Listener Name %q", id.HttpListenerName),
31+
fmt.Sprintf("Application Gateway Name %q", id.ApplicationGatewayName),
32+
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
33+
}
34+
segmentsStr := strings.Join(segments, " / ")
35+
return fmt.Sprintf("%s: (%s)", "Application Gateway H T T P Listener", segmentsStr)
36+
}
37+
38+
func (id ApplicationGatewayHTTPListenerId) ID() string {
39+
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/applicationGateways/%s/httpListeners/%s"
40+
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.ApplicationGatewayName, id.HttpListenerName)
41+
}
42+
43+
// ApplicationGatewayHTTPListenerID parses a ApplicationGatewayHTTPListener ID into an ApplicationGatewayHTTPListenerId struct
44+
func ApplicationGatewayHTTPListenerID(input string) (*ApplicationGatewayHTTPListenerId, error) {
45+
id, err := azure.ParseAzureResourceID(input)
46+
if err != nil {
47+
return nil, err
48+
}
49+
50+
resourceId := ApplicationGatewayHTTPListenerId{
51+
SubscriptionId: id.SubscriptionID,
52+
ResourceGroup: id.ResourceGroup,
53+
}
54+
55+
if resourceId.SubscriptionId == "" {
56+
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
57+
}
58+
59+
if resourceId.ResourceGroup == "" {
60+
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
61+
}
62+
63+
if resourceId.ApplicationGatewayName, err = id.PopSegment("applicationGateways"); err != nil {
64+
return nil, err
65+
}
66+
if resourceId.HttpListenerName, err = id.PopSegment("httpListeners"); err != nil {
67+
return nil, err
68+
}
69+
70+
if err := id.ValidateNoEmptySegments(input); err != nil {
71+
return nil, err
72+
}
73+
74+
return &resourceId, nil
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package parse
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import (
6+
"testing"
7+
8+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid"
9+
)
10+
11+
var _ resourceid.Formatter = ApplicationGatewayHTTPListenerId{}
12+
13+
func TestApplicationGatewayHTTPListenerIDFormatter(t *testing.T) {
14+
actual := NewApplicationGatewayHTTPListenerID("12345678-1234-9876-4563-123456789012", "resGroup1", "applicationGateway1", "httpListener1").ID()
15+
expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/httpListeners/httpListener1"
16+
if actual != expected {
17+
t.Fatalf("Expected %q but got %q", expected, actual)
18+
}
19+
}
20+
21+
func TestApplicationGatewayHTTPListenerID(t *testing.T) {
22+
testData := []struct {
23+
Input string
24+
Error bool
25+
Expected *ApplicationGatewayHTTPListenerId
26+
}{
27+
28+
{
29+
// empty
30+
Input: "",
31+
Error: true,
32+
},
33+
34+
{
35+
// missing SubscriptionId
36+
Input: "/",
37+
Error: true,
38+
},
39+
40+
{
41+
// missing value for SubscriptionId
42+
Input: "/subscriptions/",
43+
Error: true,
44+
},
45+
46+
{
47+
// missing ResourceGroup
48+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
49+
Error: true,
50+
},
51+
52+
{
53+
// missing value for ResourceGroup
54+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
55+
Error: true,
56+
},
57+
58+
{
59+
// missing ApplicationGatewayName
60+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
61+
Error: true,
62+
},
63+
64+
{
65+
// missing value for ApplicationGatewayName
66+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/",
67+
Error: true,
68+
},
69+
70+
{
71+
// missing HttpListenerName
72+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/",
73+
Error: true,
74+
},
75+
76+
{
77+
// missing value for HttpListenerName
78+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/httpListeners/",
79+
Error: true,
80+
},
81+
82+
{
83+
// valid
84+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/httpListeners/httpListener1",
85+
Expected: &ApplicationGatewayHTTPListenerId{
86+
SubscriptionId: "12345678-1234-9876-4563-123456789012",
87+
ResourceGroup: "resGroup1",
88+
ApplicationGatewayName: "applicationGateway1",
89+
HttpListenerName: "httpListener1",
90+
},
91+
},
92+
93+
{
94+
// upper-cased
95+
Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/APPLICATIONGATEWAY1/HTTPLISTENERS/HTTPLISTENER1",
96+
Error: true,
97+
},
98+
}
99+
100+
for _, v := range testData {
101+
t.Logf("[DEBUG] Testing %q", v.Input)
102+
103+
actual, err := ApplicationGatewayHTTPListenerID(v.Input)
104+
if err != nil {
105+
if v.Error {
106+
continue
107+
}
108+
109+
t.Fatalf("Expect a value but got an error: %s", err)
110+
}
111+
if v.Error {
112+
t.Fatal("Expect an error but didn't get one")
113+
}
114+
115+
if actual.SubscriptionId != v.Expected.SubscriptionId {
116+
t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
117+
}
118+
if actual.ResourceGroup != v.Expected.ResourceGroup {
119+
t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
120+
}
121+
if actual.ApplicationGatewayName != v.Expected.ApplicationGatewayName {
122+
t.Fatalf("Expected %q but got %q for ApplicationGatewayName", v.Expected.ApplicationGatewayName, actual.ApplicationGatewayName)
123+
}
124+
if actual.HttpListenerName != v.Expected.HttpListenerName {
125+
t.Fatalf("Expected %q but got %q for HttpListenerName", v.Expected.HttpListenerName, actual.HttpListenerName)
126+
}
127+
}
128+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package parse
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import (
6+
"fmt"
7+
"strings"
8+
9+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
10+
)
11+
12+
type ApplicationGatewayURLPathMapPathRuleId struct {
13+
SubscriptionId string
14+
ResourceGroup string
15+
ApplicationGatewayName string
16+
UrlPathMapName string
17+
PathRuleName string
18+
}
19+
20+
func NewApplicationGatewayURLPathMapPathRuleID(subscriptionId, resourceGroup, applicationGatewayName, urlPathMapName, pathRuleName string) ApplicationGatewayURLPathMapPathRuleId {
21+
return ApplicationGatewayURLPathMapPathRuleId{
22+
SubscriptionId: subscriptionId,
23+
ResourceGroup: resourceGroup,
24+
ApplicationGatewayName: applicationGatewayName,
25+
UrlPathMapName: urlPathMapName,
26+
PathRuleName: pathRuleName,
27+
}
28+
}
29+
30+
func (id ApplicationGatewayURLPathMapPathRuleId) String() string {
31+
segments := []string{
32+
fmt.Sprintf("Path Rule Name %q", id.PathRuleName),
33+
fmt.Sprintf("Url Path Map Name %q", id.UrlPathMapName),
34+
fmt.Sprintf("Application Gateway Name %q", id.ApplicationGatewayName),
35+
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
36+
}
37+
segmentsStr := strings.Join(segments, " / ")
38+
return fmt.Sprintf("%s: (%s)", "Application Gateway U R L Path Map Path Rule", segmentsStr)
39+
}
40+
41+
func (id ApplicationGatewayURLPathMapPathRuleId) ID() string {
42+
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/applicationGateways/%s/urlPathMaps/%s/pathRules/%s"
43+
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.ApplicationGatewayName, id.UrlPathMapName, id.PathRuleName)
44+
}
45+
46+
// ApplicationGatewayURLPathMapPathRuleID parses a ApplicationGatewayURLPathMapPathRule ID into an ApplicationGatewayURLPathMapPathRuleId struct
47+
func ApplicationGatewayURLPathMapPathRuleID(input string) (*ApplicationGatewayURLPathMapPathRuleId, error) {
48+
id, err := azure.ParseAzureResourceID(input)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
resourceId := ApplicationGatewayURLPathMapPathRuleId{
54+
SubscriptionId: id.SubscriptionID,
55+
ResourceGroup: id.ResourceGroup,
56+
}
57+
58+
if resourceId.SubscriptionId == "" {
59+
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
60+
}
61+
62+
if resourceId.ResourceGroup == "" {
63+
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
64+
}
65+
66+
if resourceId.ApplicationGatewayName, err = id.PopSegment("applicationGateways"); err != nil {
67+
return nil, err
68+
}
69+
if resourceId.UrlPathMapName, err = id.PopSegment("urlPathMaps"); err != nil {
70+
return nil, err
71+
}
72+
if resourceId.PathRuleName, err = id.PopSegment("pathRules"); err != nil {
73+
return nil, err
74+
}
75+
76+
if err := id.ValidateNoEmptySegments(input); err != nil {
77+
return nil, err
78+
}
79+
80+
return &resourceId, nil
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package parse
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import (
6+
"testing"
7+
8+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid"
9+
)
10+
11+
var _ resourceid.Formatter = ApplicationGatewayURLPathMapPathRuleId{}
12+
13+
func TestApplicationGatewayURLPathMapPathRuleIDFormatter(t *testing.T) {
14+
actual := NewApplicationGatewayURLPathMapPathRuleID("12345678-1234-9876-4563-123456789012", "resGroup1", "applicationGateway1", "urlPathMap1", "pathRule1").ID()
15+
expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/pathRules/pathRule1"
16+
if actual != expected {
17+
t.Fatalf("Expected %q but got %q", expected, actual)
18+
}
19+
}
20+
21+
func TestApplicationGatewayURLPathMapPathRuleID(t *testing.T) {
22+
testData := []struct {
23+
Input string
24+
Error bool
25+
Expected *ApplicationGatewayURLPathMapPathRuleId
26+
}{
27+
28+
{
29+
// empty
30+
Input: "",
31+
Error: true,
32+
},
33+
34+
{
35+
// missing SubscriptionId
36+
Input: "/",
37+
Error: true,
38+
},
39+
40+
{
41+
// missing value for SubscriptionId
42+
Input: "/subscriptions/",
43+
Error: true,
44+
},
45+
46+
{
47+
// missing ResourceGroup
48+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
49+
Error: true,
50+
},
51+
52+
{
53+
// missing value for ResourceGroup
54+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
55+
Error: true,
56+
},
57+
58+
{
59+
// missing ApplicationGatewayName
60+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
61+
Error: true,
62+
},
63+
64+
{
65+
// missing value for ApplicationGatewayName
66+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/",
67+
Error: true,
68+
},
69+
70+
{
71+
// missing UrlPathMapName
72+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/",
73+
Error: true,
74+
},
75+
76+
{
77+
// missing value for UrlPathMapName
78+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/",
79+
Error: true,
80+
},
81+
82+
{
83+
// missing PathRuleName
84+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/",
85+
Error: true,
86+
},
87+
88+
{
89+
// missing value for PathRuleName
90+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/pathRules/",
91+
Error: true,
92+
},
93+
94+
{
95+
// valid
96+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/pathRules/pathRule1",
97+
Expected: &ApplicationGatewayURLPathMapPathRuleId{
98+
SubscriptionId: "12345678-1234-9876-4563-123456789012",
99+
ResourceGroup: "resGroup1",
100+
ApplicationGatewayName: "applicationGateway1",
101+
UrlPathMapName: "urlPathMap1",
102+
PathRuleName: "pathRule1",
103+
},
104+
},
105+
106+
{
107+
// upper-cased
108+
Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/APPLICATIONGATEWAY1/URLPATHMAPS/URLPATHMAP1/PATHRULES/PATHRULE1",
109+
Error: true,
110+
},
111+
}
112+
113+
for _, v := range testData {
114+
t.Logf("[DEBUG] Testing %q", v.Input)
115+
116+
actual, err := ApplicationGatewayURLPathMapPathRuleID(v.Input)
117+
if err != nil {
118+
if v.Error {
119+
continue
120+
}
121+
122+
t.Fatalf("Expect a value but got an error: %s", err)
123+
}
124+
if v.Error {
125+
t.Fatal("Expect an error but didn't get one")
126+
}
127+
128+
if actual.SubscriptionId != v.Expected.SubscriptionId {
129+
t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
130+
}
131+
if actual.ResourceGroup != v.Expected.ResourceGroup {
132+
t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
133+
}
134+
if actual.ApplicationGatewayName != v.Expected.ApplicationGatewayName {
135+
t.Fatalf("Expected %q but got %q for ApplicationGatewayName", v.Expected.ApplicationGatewayName, actual.ApplicationGatewayName)
136+
}
137+
if actual.UrlPathMapName != v.Expected.UrlPathMapName {
138+
t.Fatalf("Expected %q but got %q for UrlPathMapName", v.Expected.UrlPathMapName, actual.UrlPathMapName)
139+
}
140+
if actual.PathRuleName != v.Expected.PathRuleName {
141+
t.Fatalf("Expected %q but got %q for PathRuleName", v.Expected.PathRuleName, actual.PathRuleName)
142+
}
143+
}
144+
}

‎azurerm/internal/services/network/resourceids.go

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package network
22

33
// Core bits and pieces
44
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApplicationGateway -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1
5+
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApplicationGatewayHTTPListener -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/httpListeners/httpListener1
6+
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApplicationGatewayURLPathMapPathRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/pathRules/pathRule1
57
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=IpGroup -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/ipGroups/group1
68
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=NetworkInterface -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkInterfaces/networkInterface1
79
//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=NetworkSecurityGroup -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkSecurityGroups/securityGroup1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package validate
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/parse"
9+
)
10+
11+
func ApplicationGatewayHTTPListenerID(input interface{}, key string) (warnings []string, errors []error) {
12+
v, ok := input.(string)
13+
if !ok {
14+
errors = append(errors, fmt.Errorf("expected %q to be a string", key))
15+
return
16+
}
17+
18+
if _, err := parse.ApplicationGatewayHTTPListenerID(v); err != nil {
19+
errors = append(errors, err)
20+
}
21+
22+
return
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package validate
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import "testing"
6+
7+
func TestApplicationGatewayHTTPListenerID(t *testing.T) {
8+
cases := []struct {
9+
Input string
10+
Valid bool
11+
}{
12+
13+
{
14+
// empty
15+
Input: "",
16+
Valid: false,
17+
},
18+
19+
{
20+
// missing SubscriptionId
21+
Input: "/",
22+
Valid: false,
23+
},
24+
25+
{
26+
// missing value for SubscriptionId
27+
Input: "/subscriptions/",
28+
Valid: false,
29+
},
30+
31+
{
32+
// missing ResourceGroup
33+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
34+
Valid: false,
35+
},
36+
37+
{
38+
// missing value for ResourceGroup
39+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
40+
Valid: false,
41+
},
42+
43+
{
44+
// missing ApplicationGatewayName
45+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
46+
Valid: false,
47+
},
48+
49+
{
50+
// missing value for ApplicationGatewayName
51+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/",
52+
Valid: false,
53+
},
54+
55+
{
56+
// missing HttpListenerName
57+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/",
58+
Valid: false,
59+
},
60+
61+
{
62+
// missing value for HttpListenerName
63+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/httpListeners/",
64+
Valid: false,
65+
},
66+
67+
{
68+
// valid
69+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/httpListeners/httpListener1",
70+
Valid: true,
71+
},
72+
73+
{
74+
// upper-cased
75+
Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/APPLICATIONGATEWAY1/HTTPLISTENERS/HTTPLISTENER1",
76+
Valid: false,
77+
},
78+
}
79+
for _, tc := range cases {
80+
t.Logf("[DEBUG] Testing Value %s", tc.Input)
81+
_, errors := ApplicationGatewayHTTPListenerID(tc.Input, "test")
82+
valid := len(errors) == 0
83+
84+
if tc.Valid != valid {
85+
t.Fatalf("Expected %t but got %t", tc.Valid, valid)
86+
}
87+
}
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package validate
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/parse"
9+
)
10+
11+
func ApplicationGatewayURLPathMapPathRuleID(input interface{}, key string) (warnings []string, errors []error) {
12+
v, ok := input.(string)
13+
if !ok {
14+
errors = append(errors, fmt.Errorf("expected %q to be a string", key))
15+
return
16+
}
17+
18+
if _, err := parse.ApplicationGatewayURLPathMapPathRuleID(v); err != nil {
19+
errors = append(errors, err)
20+
}
21+
22+
return
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package validate
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import "testing"
6+
7+
func TestApplicationGatewayURLPathMapPathRuleID(t *testing.T) {
8+
cases := []struct {
9+
Input string
10+
Valid bool
11+
}{
12+
13+
{
14+
// empty
15+
Input: "",
16+
Valid: false,
17+
},
18+
19+
{
20+
// missing SubscriptionId
21+
Input: "/",
22+
Valid: false,
23+
},
24+
25+
{
26+
// missing value for SubscriptionId
27+
Input: "/subscriptions/",
28+
Valid: false,
29+
},
30+
31+
{
32+
// missing ResourceGroup
33+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
34+
Valid: false,
35+
},
36+
37+
{
38+
// missing value for ResourceGroup
39+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
40+
Valid: false,
41+
},
42+
43+
{
44+
// missing ApplicationGatewayName
45+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
46+
Valid: false,
47+
},
48+
49+
{
50+
// missing value for ApplicationGatewayName
51+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/",
52+
Valid: false,
53+
},
54+
55+
{
56+
// missing UrlPathMapName
57+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/",
58+
Valid: false,
59+
},
60+
61+
{
62+
// missing value for UrlPathMapName
63+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/",
64+
Valid: false,
65+
},
66+
67+
{
68+
// missing PathRuleName
69+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/",
70+
Valid: false,
71+
},
72+
73+
{
74+
// missing value for PathRuleName
75+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/pathRules/",
76+
Valid: false,
77+
},
78+
79+
{
80+
// valid
81+
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/applicationGateways/applicationGateway1/urlPathMaps/urlPathMap1/pathRules/pathRule1",
82+
Valid: true,
83+
},
84+
85+
{
86+
// upper-cased
87+
Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/APPLICATIONGATEWAY1/URLPATHMAPS/URLPATHMAP1/PATHRULES/PATHRULE1",
88+
Valid: false,
89+
},
90+
}
91+
for _, tc := range cases {
92+
t.Logf("[DEBUG] Testing Value %s", tc.Input)
93+
_, errors := ApplicationGatewayURLPathMapPathRuleID(tc.Input, "test")
94+
valid := len(errors) == 0
95+
96+
if tc.Valid != valid {
97+
t.Fatalf("Expected %t but got %t", tc.Valid, valid)
98+
}
99+
}
100+
}

‎azurerm/internal/services/network/validate/web_application_firewall_policy.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package validate
22

3-
import "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
5+
)
46

57
var ValidateWebApplicationFirewallPolicyRuleGroupName = validation.StringInSlice([]string{
68
"crs_20_protocol_violations",

‎azurerm/internal/services/network/web_application_firewall_policy_resource.go

+29-2
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,26 @@ func resourceWebApplicationFirewallPolicy() *schema.Resource {
282282
},
283283
},
284284

285+
"http_listener_ids": {
286+
Type: schema.TypeList,
287+
Optional: true,
288+
MinItems: 1,
289+
Elem: &schema.Schema{
290+
Type: schema.TypeString,
291+
ValidateFunc: validate.ApplicationGatewayHTTPListenerID,
292+
},
293+
},
294+
295+
"path_based_rule_ids": {
296+
Type: schema.TypeList,
297+
Optional: true,
298+
MinItems: 1,
299+
Elem: &schema.Schema{
300+
Type: schema.TypeString,
301+
ValidateFunc: validate.ApplicationGatewayURLPathMapPathRuleID,
302+
},
303+
},
304+
285305
"tags": tags.Schema(),
286306
},
287307
}
@@ -310,6 +330,8 @@ func resourceWebApplicationFirewallPolicyCreateUpdate(d *schema.ResourceData, me
310330
location := azure.NormalizeLocation(d.Get("location").(string))
311331
customRules := d.Get("custom_rules").([]interface{})
312332
policySettings := d.Get("policy_settings").([]interface{})
333+
httpListenerIDs := d.Get("http_listener_ids").([]interface{})
334+
pathBasedRuleIDs := d.Get("path_based_rule_ids").([]interface{})
313335
managedRules := d.Get("managed_rules").([]interface{})
314336
t := d.Get("tags").(map[string]interface{})
315337

@@ -319,6 +341,8 @@ func resourceWebApplicationFirewallPolicyCreateUpdate(d *schema.ResourceData, me
319341
CustomRules: expandWebApplicationFirewallPolicyWebApplicationFirewallCustomRule(customRules),
320342
PolicySettings: expandWebApplicationFirewallPolicyPolicySettings(policySettings),
321343
ManagedRules: expandWebApplicationFirewallPolicyManagedRulesDefinition(managedRules),
344+
HTTPListeners: expandIDsToSubResources(httpListenerIDs),
345+
PathBasedRules: expandIDsToSubResources(pathBasedRuleIDs),
322346
},
323347
Tags: tags.Expand(t),
324348
}
@@ -376,8 +400,11 @@ func resourceWebApplicationFirewallPolicyRead(d *schema.ResourceData, meta inter
376400
if err := d.Set("managed_rules", flattenWebApplicationFirewallPolicyManagedRulesDefinition(webApplicationFirewallPolicyPropertiesFormat.ManagedRules)); err != nil {
377401
return fmt.Errorf("Error setting `managed_rules`: %+v", err)
378402
}
379-
if err := d.Set("managed_rules", flattenWebApplicationFirewallPolicyManagedRulesDefinition(webApplicationFirewallPolicyPropertiesFormat.ManagedRules)); err != nil {
380-
return fmt.Errorf("Error setting `managed_rules`: %+v", err)
403+
if err := d.Set("http_listener_ids", flattenSubResourcesToIDs(webApplicationFirewallPolicyPropertiesFormat.HTTPListeners)); err != nil {
404+
return fmt.Errorf("Error setting `http_listeners`: %+v", err)
405+
}
406+
if err := d.Set("path_based_rule_ids", flattenSubResourcesToIDs(webApplicationFirewallPolicyPropertiesFormat.PathBasedRules)); err != nil {
407+
return fmt.Errorf("Error setting `path_based_rules`: %+v", err)
381408
}
382409
}
383410

‎website/docs/r/web_application_firewall_policy.html.markdown

+4
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ The following arguments are supported:
122122

123123
* `managed_rules` - (Required) A `managed_rules` blocks as defined below.
124124

125+
* `http_listener_ids` - (Optional) A list of HTTP Listener IDs from an `azurerm_application_gateway`.
126+
127+
* `path_based_rule_ids` - (Optional) A list of URL Path Map Path Rule IDs from an `azurerm_application_gateway`.
128+
125129
* `tags` - (Optional) A mapping of tags to assign to the Web Application Firewall Policy.
126130

127131
---

0 commit comments

Comments
 (0)
Please sign in to comment.