From 61749e5b5f136328fc54bbad8491f51d8621698b Mon Sep 17 00:00:00 2001 From: Neeran Gul Date: Mon, 14 May 2018 17:41:09 +0100 Subject: [PATCH 1/6] adding iprestrictions --- azurerm/data_source_app_service.go | 22 ++++ azurerm/data_source_app_service_test.go | 32 ++++++ azurerm/import_arm_app_service_test.go | 23 +++++ azurerm/resource_arm_app_service.go | 61 +++++++++++- azurerm/resource_arm_app_service_test.go | 122 +++++++++++++++++++++++ 5 files changed, 259 insertions(+), 1 deletion(-) diff --git a/azurerm/data_source_app_service.go b/azurerm/data_source_app_service.go index 67f3e9bb9473..c7382e1ddea2 100644 --- a/azurerm/data_source_app_service.go +++ b/azurerm/data_source_app_service.go @@ -123,6 +123,23 @@ func dataSourceArmAppService() *schema.Resource { Computed: true, }, + "ip_restriction": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_address": { + Type: schema.TypeString, + Computed: true, + }, + "subnet_mask": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "https_only": { Type: schema.TypeBool, Computed: true, @@ -284,6 +301,11 @@ func dataSourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error return err } + ipSecurityRestrictions := configResp.SiteConfig.IPSecurityRestrictions + if ipSecurityRestrictions != nil { + d.Set("ip_restriction", flattenAppServiceIpRestrictions(ipSecurityRestrictions)) + } + scm := flattenAppServiceSourceControl(scmResp.SiteSourceControlProperties) if err := d.Set("source_control", scm); err != nil { return err diff --git a/azurerm/data_source_app_service_test.go b/azurerm/data_source_app_service_test.go index cc5e10e5cbbb..e6cd6788ba9f 100644 --- a/azurerm/data_source_app_service_test.go +++ b/azurerm/data_source_app_service_test.go @@ -126,6 +126,26 @@ func TestAccDataSourceAzureRMAppService_connectionString(t *testing.T) { }) } +func TestAccDataSourceAzureRMAppService_ipRestriction(t *testing.T) { + dataSourceName := "data.azurerm_app_service.test" + rInt := acctest.RandInt() + location := testLocation() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAppService_ipRestriction(rInt, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "ip_restriction.0.ip_address", "10.10.10.10"), + resource.TestCheckResourceAttr(dataSourceName, "ip_restriction.0.subnet_mask", "255.255.255.255"), + ), + }, + }, + }) +} + func TestAccDataSourceAzureRMAppService_http2Enabled(t *testing.T) { dataSourceName := "data.azurerm_app_service.test" rInt := acctest.RandInt() @@ -217,6 +237,18 @@ data "azurerm_app_service" "test" { `, config) } +func testAccDataSourceAppService_ipRestriction(rInt int, location string) string { + config := testAccAzureRMAppService_oneIpRestriction(rInt, location) + return fmt.Sprintf(` +%s + +data "azurerm_app_service" "test" { + name = "${azurerm_app_service.test.name}" + resource_group_name = "${azurerm_app_service.test.resource_group_name}" +} +`, config) +} + func testAccDataSourceAppService_http2Enabled(rInt int, location string) string { config := testAccAzureRMAppService_http2Enabled(rInt, location) return fmt.Sprintf(` diff --git a/azurerm/import_arm_app_service_test.go b/azurerm/import_arm_app_service_test.go index e2bacbcbae5e..b1740342612f 100644 --- a/azurerm/import_arm_app_service_test.go +++ b/azurerm/import_arm_app_service_test.go @@ -145,6 +145,29 @@ func TestAccAzureRMAppService_importConnectionStrings(t *testing.T) { }) } +func TestAccAzureRMAppService_importIpRestriction(t *testing.T) { + resourceName := "azurerm_app_service.test" + + ri := acctest.RandInt() + config := testAccAzureRMAppService_oneIpRestriction(ri, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: config, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMAppService_importDefaultDocuments(t *testing.T) { resourceName := "azurerm_app_service.test" diff --git a/azurerm/resource_arm_app_service.go b/azurerm/resource_arm_app_service.go index 7c5af8ef2682..96c50a0f5cf5 100644 --- a/azurerm/resource_arm_app_service.go +++ b/azurerm/resource_arm_app_service.go @@ -214,6 +214,25 @@ func resourceArmAppService() *schema.Resource { Computed: true, }, + "ip_restriction": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_address": { + Type: schema.TypeString, + Required: true, + }, + "subnet_mask": { + Type: schema.TypeString, + Optional: true, + Default: "255.255.255.255", + }, + }, + }, + }, + "https_only": { Type: schema.TypeBool, Optional: true, @@ -432,7 +451,7 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error return err } - if d.HasChange("site_config") { + if d.HasChange("site_config") || d.HasChange("ip_restriction") { // update the main configuration siteConfig := expandAppServiceSiteConfig(d) siteConfigResource := web.SiteConfigResource{ @@ -594,6 +613,11 @@ func resourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error { return err } + ipSecurityRestrictions := configResp.SiteConfig.IPSecurityRestrictions + if ipSecurityRestrictions != nil { + d.Set("ip_restrictions", flattenAppServiceIpRestrictions(ipSecurityRestrictions)) + } + scm := flattenAppServiceSourceControl(scmResp.SiteSourceControlProperties) if err := d.Set("source_control", scm); err != nil { return err @@ -643,6 +667,9 @@ func expandAppServiceSiteConfig(d *schema.ResourceData) web.SiteConfig { configs := d.Get("site_config").([]interface{}) siteConfig := web.SiteConfig{} + ipRestrictions := expandIpRestrictions(d) + siteConfig.IPSecurityRestrictions = ipRestrictions + if len(configs) == 0 { return siteConfig } @@ -852,6 +879,25 @@ func expandAppServiceConnectionStrings(d *schema.ResourceData) map[string]*web.C return output } +func expandIpRestrictions(d *schema.ResourceData) *[]web.IPSecurityRestriction { + ipSecurityRestrictions := d.Get("ip_restriction").([]interface{}) + restrictions := make([]web.IPSecurityRestriction, 0) + + for _, ipSecurityRestriction := range ipSecurityRestrictions { + restriction := ipSecurityRestriction.(map[string]interface{}) + + ip_address := restriction["ip_address"].(string) + subnet_mask := restriction["subnet_mask"].(string) + + restrictions = append(restrictions, web.IPSecurityRestriction{ + IPAddress: &ip_address, + SubnetMask: &subnet_mask, + }) + } + + return &restrictions +} + func flattenAppServiceConnectionStrings(input map[string]*web.ConnStringValueTypePair) interface{} { results := make([]interface{}, 0) @@ -866,6 +912,19 @@ func flattenAppServiceConnectionStrings(input map[string]*web.ConnStringValueTyp return results } +func flattenAppServiceIpRestrictions(input *[]web.IPSecurityRestriction) interface{} { + results := make([]interface{}, 0) + + for _, ip_restriction := range *input { + result := make(map[string]interface{}, 0) + result["ip_address"] = *ip_restriction.IPAddress + result["subnet_mask"] = *ip_restriction.SubnetMask + results = append(results, result) + } + + return results +} + func flattenAppServiceAppSettings(input map[string]*string) map[string]string { output := make(map[string]string, 0) for k, v := range input { diff --git a/azurerm/resource_arm_app_service_test.go b/azurerm/resource_arm_app_service_test.go index f46c4e0f933b..ac3ced464b35 100644 --- a/azurerm/resource_arm_app_service_test.go +++ b/azurerm/resource_arm_app_service_test.go @@ -371,6 +371,54 @@ func TestAccAzureRMAppService_connectionStrings(t *testing.T) { }) } +func TestAccAzureRMAppService_oneIpRestriction(t *testing.T) { + resourceName := "azurerm_app_service.test" + ri := acctest.RandInt() + config := testAccAzureRMAppService_oneIpRestriction(ri, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.0.ip_address", "10.10.10.10"), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.0.subnet_mask", "255.255.255.255"), + ), + }, + }, + }) +} + +func TestAccAzureRMAppService_manyIpRestrictions(t *testing.T) { + resourceName := "azurerm_app_service.test" + ri := acctest.RandInt() + config := testAccAzureRMAppService_manyIpRestrictions(ri, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.0.ip_address", "10.10.10.10"), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.0.subnet_mask", "255.255.255.255"), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.1.ip_address", "20.20.20.0"), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.1.subnet_mask", "255.255.255.0"), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.2.ip_address", "30.30.0.0"), + resource.TestCheckResourceAttr(resourceName, "ip_restriction.2.subnet_mask", "255.255.0.0"), + ), + }, + }, + }) +} + func TestAccAzureRMAppService_defaultDocuments(t *testing.T) { resourceName := "azurerm_app_service.test" ri := acctest.RandInt() @@ -1153,6 +1201,80 @@ resource "azurerm_app_service" "test" { `, rInt, location, rInt, rInt) } +func testAccAzureRMAppService_oneIpRestriction(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_app_service_plan" "test" { + name = "acctestASP-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + tier = "Standard" + size = "S1" + } +} + +resource "azurerm_app_service" "test" { + name = "acctestAS-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + app_service_plan_id = "${azurerm_app_service_plan.test.id}" + + ip_restriction { + ip_address = "10.10.10.10" + subnet_mask = "255.255.255.255" + } +} +`, rInt, location, rInt, rInt) +} + +func testAccAzureRMAppService_manyIpRestrictions(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_app_service_plan" "test" { + name = "acctestASP-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + tier = "Standard" + size = "S1" + } +} + +resource "azurerm_app_service" "test" { + name = "acctestAS-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + app_service_plan_id = "${azurerm_app_service_plan.test.id}" + + ip_restriction { + ip_address = "10.10.10.10" + subnet_mask = "255.255.255.255" + } + + ip_restriction { + ip_address = "20.20.20.0" + subnet_mask = "255.255.255.0" + } + + ip_restriction { + ip_address = "30.30.0.0" + subnet_mask = "255.255.0.0" + } +} +`, rInt, location, rInt, rInt) +} + func testAccAzureRMAppService_defaultDocuments(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { From 681a9509fb89a5668b3cb05949922fababcb9f8b Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 14 May 2018 13:55:19 -0700 Subject: [PATCH 2/6] Documenting the `ip_restriction` fields --- website/docs/d/app_service.html.markdown | 12 +++++++++++- website/docs/r/app_service.html.markdown | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/website/docs/d/app_service.html.markdown b/website/docs/d/app_service.html.markdown index 7927b08508dd..d8c24f8ad2fe 100644 --- a/website/docs/d/app_service.html.markdown +++ b/website/docs/d/app_service.html.markdown @@ -47,7 +47,9 @@ output "app_service_id" { * `https_only` - Can the App Service only be accessed via HTTPS? -* `site_config` - A `site_config` object as defined below. +* `ip_restriction` - A `ip_restriction` block as defined below. + +* `site_config` - A `site_config` block as defined below. * `tags` - A mapping of tags to assign to the resource. @@ -63,6 +65,14 @@ output "app_service_id" { --- +`ip_restriction` exports the following: + +* `ip_address` - The IP Address used for this IP Restriction. + +* `subnet_mask` - The Subnet mask used for this IP Restriction. + +--- + `site_config` supports the following: * `always_on` - Is the app be loaded at all times? diff --git a/website/docs/r/app_service.html.markdown b/website/docs/r/app_service.html.markdown index 3fcfb8ace2be..98a344a6a61b 100644 --- a/website/docs/r/app_service.html.markdown +++ b/website/docs/r/app_service.html.markdown @@ -127,7 +127,9 @@ The following arguments are supported: * `https_only` - (Optional) Can the App Service only be accessed via HTTPS? Defaults to `false`. -* `site_config` - (Optional) A `site_config` object as defined below. +* `ip_restriction` - (Optional) A `ip_restriction` block as defined below. + +* `site_config` - (Optional) A `site_config` block as defined below. * `tags` - (Optional) A mapping of tags to assign to the resource. @@ -151,6 +153,14 @@ The following arguments are supported: --- +`ip_restriction` supports the following: + +* `ip_address` - (Required) The IP Address used for this IP Restriction. + +* `subnet_mask` - (Optional) The Subnet mask used for this IP Restriction. Defaults to `255.255.255.255`. + +--- + `site_config` supports the following: * `always_on` - (Optional) Should the app be loaded at all times? Defaults to `false`. From b2d402cf3bdca15c9bb683663df1e244faaba495 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 14 May 2018 13:55:35 -0700 Subject: [PATCH 3/6] Ensuring we always set `ip_restriction` --- azurerm/resource_arm_app_service.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/azurerm/resource_arm_app_service.go b/azurerm/resource_arm_app_service.go index 96c50a0f5cf5..de4b5d7cf348 100644 --- a/azurerm/resource_arm_app_service.go +++ b/azurerm/resource_arm_app_service.go @@ -613,9 +613,9 @@ func resourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error { return err } - ipSecurityRestrictions := configResp.SiteConfig.IPSecurityRestrictions - if ipSecurityRestrictions != nil { - d.Set("ip_restrictions", flattenAppServiceIpRestrictions(ipSecurityRestrictions)) + restrictions := flattenAppServiceIpRestrictions(configResp.SiteConfig.IPSecurityRestrictions) + if err := d.Set("ip_restrictions", restrictions); err != nil { + return fmt.Errorf("Error flattening `ip_restrictions`: %s", err) } scm := flattenAppServiceSourceControl(scmResp.SiteSourceControlProperties) @@ -915,11 +915,13 @@ func flattenAppServiceConnectionStrings(input map[string]*web.ConnStringValueTyp func flattenAppServiceIpRestrictions(input *[]web.IPSecurityRestriction) interface{} { results := make([]interface{}, 0) - for _, ip_restriction := range *input { - result := make(map[string]interface{}, 0) - result["ip_address"] = *ip_restriction.IPAddress - result["subnet_mask"] = *ip_restriction.SubnetMask - results = append(results, result) + if input != nil { + for _, v := range *input { + result := make(map[string]interface{}, 0) + result["ip_address"] = *v.IPAddress + result["subnet_mask"] = *v.SubnetMask + results = append(results, result) + } } return results From 765fc6f79d2c9468863f07825b72eb7737f99ade Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 14 May 2018 13:56:41 -0700 Subject: [PATCH 4/6] Always setting the IP Restriction block for the Data Source --- azurerm/data_source_app_service.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/data_source_app_service.go b/azurerm/data_source_app_service.go index c7382e1ddea2..ab575d8206ac 100644 --- a/azurerm/data_source_app_service.go +++ b/azurerm/data_source_app_service.go @@ -301,9 +301,9 @@ func dataSourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error return err } - ipSecurityRestrictions := configResp.SiteConfig.IPSecurityRestrictions - if ipSecurityRestrictions != nil { - d.Set("ip_restriction", flattenAppServiceIpRestrictions(ipSecurityRestrictions)) + restrictions := flattenAppServiceIpRestrictions(configResp.SiteConfig.IPSecurityRestrictions) + if err := d.Set("ip_restriction", restrictions); err != nil { + return fmt.Errorf("Error setting `ip_restriction`: %s", err) } scm := flattenAppServiceSourceControl(scmResp.SiteSourceControlProperties) From 85a940903339ce071a0eb9dc802e1537c41744e0 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 14 May 2018 13:59:38 -0700 Subject: [PATCH 5/6] Removing the explicit assignment of default values --- azurerm/resource_arm_app_service_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/azurerm/resource_arm_app_service_test.go b/azurerm/resource_arm_app_service_test.go index ac3ced464b35..ddeed68f14be 100644 --- a/azurerm/resource_arm_app_service_test.go +++ b/azurerm/resource_arm_app_service_test.go @@ -1226,8 +1226,7 @@ resource "azurerm_app_service" "test" { app_service_plan_id = "${azurerm_app_service_plan.test.id}" ip_restriction { - ip_address = "10.10.10.10" - subnet_mask = "255.255.255.255" + ip_address = "10.10.10.10" } } `, rInt, location, rInt, rInt) @@ -1258,8 +1257,7 @@ resource "azurerm_app_service" "test" { app_service_plan_id = "${azurerm_app_service_plan.test.id}" ip_restriction { - ip_address = "10.10.10.10" - subnet_mask = "255.255.255.255" + ip_address = "10.10.10.10" } ip_restriction { From fb92e745d3bd518896a9e7585be32e33fd3f65ee Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 14 May 2018 14:05:36 -0700 Subject: [PATCH 6/6] Fixing a typo --- azurerm/resource_arm_app_service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_app_service.go b/azurerm/resource_arm_app_service.go index de4b5d7cf348..6ebc59e7134e 100644 --- a/azurerm/resource_arm_app_service.go +++ b/azurerm/resource_arm_app_service.go @@ -614,7 +614,7 @@ func resourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error { } restrictions := flattenAppServiceIpRestrictions(configResp.SiteConfig.IPSecurityRestrictions) - if err := d.Set("ip_restrictions", restrictions); err != nil { + if err := d.Set("ip_restriction", restrictions); err != nil { return fmt.Errorf("Error flattening `ip_restrictions`: %s", err) }