diff --git a/azurerm/internal/services/web/resource_arm_function_app.go b/azurerm/internal/services/web/resource_arm_function_app.go index 6042c3c9176f..77902cee5db6 100644 --- a/azurerm/internal/services/web/resource_arm_function_app.go +++ b/azurerm/internal/services/web/resource_arm_function_app.go @@ -254,6 +254,75 @@ func resourceArmFunctionApp() *schema.Resource { Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "priority": { + Type: schema.TypeInt, + Optional: true, + Default: 65000, + ValidateFunc: validation.IntBetween(1, 2147483647), + }, + "action": { + Type: schema.TypeString, + Default: "Allow", + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Allow", + "Deny", + }, false), + }, + }, + }, + }, + + "scm_use_main_ip_restriction": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "scm_ip_restriction": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ConfigMode: schema.SchemaConfigModeAttr, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_address": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.CIDR, + }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "priority": { + Type: schema.TypeInt, + Optional: true, + Default: 65000, + ValidateFunc: validation.IntBetween(1, 2147483647), + }, + "action": { + Type: schema.TypeString, + Optional: true, + Default: "Allow", + ValidateFunc: validation.StringInSlice([]string{ + "Allow", + "Deny", + }, true), + }, }, }, }, @@ -881,6 +950,19 @@ func expandFunctionAppSiteConfig(d *schema.ResourceData) (web.SiteConfig, error) siteConfig.IPSecurityRestrictions = &restrictions } + if v, ok := config["scm_use_main_ip_restriction"]; ok { + siteConfig.ScmIPSecurityRestrictionsUseMain = utils.Bool(v.(bool)) + } + + if v, ok := config["scm_ip_restriction"]; ok { + scmIpSecurityRestrictions := v.(interface{}) + scmRestrictions, err := expandFunctionAppScmIpRestrictions(scmIpSecurityRestrictions) + if err != nil { + return siteConfig, err + } + siteConfig.ScmIPSecurityRestrictions = &scmRestrictions + } + if v, ok := config["min_tls_version"]; ok { siteConfig.MinTLSVersion = web.SupportedTLSVersions(v.(string)) } @@ -931,6 +1013,10 @@ func flattenFunctionAppSiteConfig(input *web.SiteConfig) []interface{} { result["ip_restriction"] = flattenFunctionAppIpRestriction(input.IPSecurityRestrictions) + result["scm_use_main_ip_restriction"] = *input.ScmIPSecurityRestrictionsUseMain + + result["scm_ip_restriction"] = flattenFunctionAppScmIpRestriction(input.ScmIPSecurityRestrictions) + result["min_tls_version"] = string(input.MinTLSVersion) result["ftps_state"] = string(input.FtpsState) @@ -972,6 +1058,9 @@ func expandFunctionAppIpRestriction(input interface{}) ([]web.IPSecurityRestrict ipAddress := restriction["ip_address"].(string) vNetSubnetID := restriction["subnet_id"].(string) + name := restriction["name"].(string) + priority := restriction["priority"].(int) + action := restriction["action"].(string) if vNetSubnetID != "" && ipAddress != "" { return nil, fmt.Errorf(fmt.Sprintf("only one of `ip_address` or `subnet_id` can set for `site_config.0.ip_restriction.%d`", i)) @@ -994,12 +1083,79 @@ func expandFunctionAppIpRestriction(input interface{}) ([]web.IPSecurityRestrict ipSecurityRestriction.VnetSubnetResourceID = &vNetSubnetID } + if name != "" { + ipSecurityRestriction.Name = &name + } + + if priority != 0 { + ipSecurityRestriction.Priority = utils.Int32(int32(priority)) + } + + if action != "" { + ipSecurityRestriction.Action = &action + } + restrictions = append(restrictions, ipSecurityRestriction) } return restrictions, nil } +func expandFunctionAppScmIpRestrictions(input interface{}) ([]web.IPSecurityRestriction, error) { + scmRestrictions := make([]web.IPSecurityRestriction, 0) + + for i, r := range input.([]interface{}) { + if r == nil { + continue + } + + scmRestriction := r.(map[string]interface{}) + + ipAddress := scmRestriction["ip_address"].(string) + vNetSubnetID := scmRestriction["subnet_id"].(string) + name := scmRestriction["name"].(string) + priority := scmRestriction["priority"].(int) + action := scmRestriction["action"].(string) + + if vNetSubnetID != "" && ipAddress != "" { + return nil, fmt.Errorf(fmt.Sprintf("only one of `ip_address` or `subnet_id` can set for `site_config.0.ip_restriction.%d`", i)) + } + + if vNetSubnetID == "" && ipAddress == "" { + return nil, fmt.Errorf(fmt.Sprintf("one of `ip_address` or `subnet_id` must be set for `site_config.0.ip_restriction.%d`", i)) + } + + scmIpSecurityRestriction := web.IPSecurityRestriction{} + if ipAddress == "Any" { + continue + } + + if ipAddress != "" { + scmIpSecurityRestriction.IPAddress = &ipAddress + } + + if vNetSubnetID != "" { + scmIpSecurityRestriction.VnetSubnetResourceID = &vNetSubnetID + } + + if name != "" { + scmIpSecurityRestriction.Name = &name + } + + if priority != 0 { + scmIpSecurityRestriction.Priority = utils.Int32(int32(priority)) + } + + if action != "" { + scmIpSecurityRestriction.Action = &action + } + + scmRestrictions = append(scmRestrictions, scmIpSecurityRestriction) + } + + return scmRestrictions, nil +} + func flattenFunctionAppConnectionStrings(input map[string]*web.ConnStringValueTypePair) interface{} { results := make([]interface{}, 0) @@ -1038,28 +1194,72 @@ func flattenFunctionAppIpRestriction(input *[]web.IPSecurityRestriction) []inter restrictions := make([]interface{}, 0) if input == nil { + log.Printf("[DEBUG] SiteConfig is nil") return restrictions } for _, v := range *input { - ipAddress := "" - if v.IPAddress != nil { - ipAddress = *v.IPAddress - if ipAddress == "Any" { + block := make(map[string]interface{}) + + if ip := v.IPAddress; ip != nil { + if *ip == "Any" { continue + } else { + block["ip_address"] = *ip } } + if vNetSubnetID := v.VnetSubnetResourceID; vNetSubnetID != nil { + block["subnet_id"] = *vNetSubnetID + } + if name := v.Name; name != nil { + block["name"] = *name + } + if priority := v.Priority; priority != nil { + block["priority"] = *priority + } - subnetId := "" - if v.VnetSubnetResourceID != nil { - subnetId = *v.VnetSubnetResourceID + if action := v.Action; action != nil { + block["action"] = *action } - restrictions = append(restrictions, map[string]interface{}{ - "ip_address": ipAddress, - "subnet_id": subnetId, - }) + restrictions = append(restrictions, block) } - return restrictions } + +func flattenFunctionAppScmIpRestriction(input *[]web.IPSecurityRestriction) []interface{} { + scmRestrictions := make([]interface{}, 0) + + if input == nil { + log.Printf("[DEBUG] SiteConfig is nil") + return scmRestrictions + } + + for _, v := range *input { + block := make(map[string]interface{}) + + if ip := v.IPAddress; ip != nil { + if *ip == "Any" { + continue + } else { + block["ip_address"] = *ip + } + } + if vNetSubnetID := v.VnetSubnetResourceID; vNetSubnetID != nil { + block["subnet_id"] = *vNetSubnetID + } + if name := v.Name; name != nil { + block["name"] = *name + } + if priority := v.Priority; priority != nil { + block["priority"] = *priority + } + + if action := v.Action; action != nil { + block["action"] = *action + } + + scmRestrictions = append(scmRestrictions, block) + } + return scmRestrictions +} diff --git a/azurerm/internal/services/web/resource_arm_function_app_slot.go b/azurerm/internal/services/web/resource_arm_function_app_slot.go index 8f4a2c2df6ea..b715e75be6e7 100644 --- a/azurerm/internal/services/web/resource_arm_function_app_slot.go +++ b/azurerm/internal/services/web/resource_arm_function_app_slot.go @@ -241,6 +241,75 @@ func resourceArmFunctionAppSlot() *schema.Resource { Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "priority": { + Type: schema.TypeInt, + Optional: true, + Default: 65000, + ValidateFunc: validation.IntBetween(1, 2147483647), + }, + "action": { + Type: schema.TypeString, + Default: "Allow", + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Allow", + "Deny", + }, false), + }, + }, + }, + }, + + "scm_use_main_ip_restriction": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "scm_ip_restriction": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ConfigMode: schema.SchemaConfigModeAttr, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_address": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.CIDR, + }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "priority": { + Type: schema.TypeInt, + Optional: true, + Default: 65000, + ValidateFunc: validation.IntBetween(1, 2147483647), + }, + "action": { + Type: schema.TypeString, + Optional: true, + Default: "Allow", + ValidateFunc: validation.StringInSlice([]string{ + "Allow", + "Deny", + }, true), + }, }, }, }, @@ -820,6 +889,19 @@ func expandFunctionAppSlotSiteConfig(d *schema.ResourceData) (web.SiteConfig, er siteConfig.IPSecurityRestrictions = &restrictions } + if v, ok := config["scm_use_main_ip_restriction"]; ok { + siteConfig.ScmIPSecurityRestrictionsUseMain = utils.Bool(v.(bool)) + } + + if v, ok := config["scm_ip_restriction"]; ok { + scmIpSecurityRestrictions := v.(interface{}) + scmRestrictions, err := expandFunctionAppSlotScmIpRestrictions(scmIpSecurityRestrictions) + if err != nil { + return siteConfig, err + } + siteConfig.ScmIPSecurityRestrictions = &scmRestrictions + } + if v, ok := config["min_tls_version"]; ok { siteConfig.MinTLSVersion = web.SupportedTLSVersions(v.(string)) } @@ -870,6 +952,10 @@ func flattenFunctionAppSlotSiteConfig(input *web.SiteConfig) []interface{} { result["ip_restriction"] = flattenFunctionAppSlotIPRestriction(input.IPSecurityRestrictions) + result["scm_use_main_ip_restriction"] = *input.ScmIPSecurityRestrictionsUseMain + + result["scm_ip_restriction"] = flattenFunctionAppSlotScmIpRestriction(input.ScmIPSecurityRestrictions) + result["min_tls_version"] = string(input.MinTLSVersion) result["ftps_state"] = string(input.FtpsState) @@ -911,6 +997,9 @@ func expandFunctionAppSlotIPRestriction(input interface{}) ([]web.IPSecurityRest ipAddress := restriction["ip_address"].(string) vNetSubnetID := restriction["subnet_id"].(string) + name := restriction["name"].(string) + priority := restriction["priority"].(int) + action := restriction["action"].(string) if vNetSubnetID != "" && ipAddress != "" { return nil, fmt.Errorf(fmt.Sprintf("only one of `ip_address` or `subnet_id` can set for `site_config.0.ip_restriction.%d`", i)) @@ -933,12 +1022,79 @@ func expandFunctionAppSlotIPRestriction(input interface{}) ([]web.IPSecurityRest ipSecurityRestriction.VnetSubnetResourceID = &vNetSubnetID } + if name != "" { + ipSecurityRestriction.Name = &name + } + + if priority != 0 { + ipSecurityRestriction.Priority = utils.Int32(int32(priority)) + } + + if action != "" { + ipSecurityRestriction.Action = &action + } + restrictions = append(restrictions, ipSecurityRestriction) } return restrictions, nil } +func expandFunctionAppSlotScmIpRestrictions(input interface{}) ([]web.IPSecurityRestriction, error) { + scmRestrictions := make([]web.IPSecurityRestriction, 0) + + for i, r := range input.([]interface{}) { + if r == nil { + continue + } + + scmRestriction := r.(map[string]interface{}) + + ipAddress := scmRestriction["ip_address"].(string) + vNetSubnetID := scmRestriction["subnet_id"].(string) + name := scmRestriction["name"].(string) + priority := scmRestriction["priority"].(int) + action := scmRestriction["action"].(string) + + if vNetSubnetID != "" && ipAddress != "" { + return nil, fmt.Errorf(fmt.Sprintf("only one of `ip_address` or `subnet_id` can set for `site_config.0.ip_restriction.%d`", i)) + } + + if vNetSubnetID == "" && ipAddress == "" { + return nil, fmt.Errorf(fmt.Sprintf("one of `ip_address` or `subnet_id` must be set for `site_config.0.ip_restriction.%d`", i)) + } + + scmIpSecurityRestriction := web.IPSecurityRestriction{} + if ipAddress == "Any" { + continue + } + + if ipAddress != "" { + scmIpSecurityRestriction.IPAddress = &ipAddress + } + + if vNetSubnetID != "" { + scmIpSecurityRestriction.VnetSubnetResourceID = &vNetSubnetID + } + + if name != "" { + scmIpSecurityRestriction.Name = &name + } + + if priority != 0 { + scmIpSecurityRestriction.Priority = utils.Int32(int32(priority)) + } + + if action != "" { + scmIpSecurityRestriction.Action = &action + } + + scmRestrictions = append(scmRestrictions, scmIpSecurityRestriction) + } + + return scmRestrictions, nil +} + func flattenFunctionAppSlotConnectionStrings(input map[string]*web.ConnStringValueTypePair) interface{} { results := make([]interface{}, 0) @@ -977,28 +1133,72 @@ func flattenFunctionAppSlotIPRestriction(input *[]web.IPSecurityRestriction) []i restrictions := make([]interface{}, 0) if input == nil { + log.Printf("[DEBUG] SiteConfig is nil") return restrictions } for _, v := range *input { - ipAddress := "" - if v.IPAddress != nil { - ipAddress = *v.IPAddress - if ipAddress == "Any" { + block := make(map[string]interface{}) + + if ip := v.IPAddress; ip != nil { + if *ip == "Any" { continue + } else { + block["ip_address"] = *ip } } + if vNetSubnetID := v.VnetSubnetResourceID; vNetSubnetID != nil { + block["subnet_id"] = *vNetSubnetID + } + if name := v.Name; name != nil { + block["name"] = *name + } + if priority := v.Priority; priority != nil { + block["priority"] = *priority + } - subnetID := "" - if v.VnetSubnetResourceID != nil { - subnetID = *v.VnetSubnetResourceID + if action := v.Action; action != nil { + block["action"] = *action } - restrictions = append(restrictions, map[string]interface{}{ - "ip_address": ipAddress, - "subnet_id": subnetID, - }) + restrictions = append(restrictions, block) } - return restrictions } + +func flattenFunctionAppSlotScmIpRestriction(input *[]web.IPSecurityRestriction) []interface{} { + scmRestrictions := make([]interface{}, 0) + + if input == nil { + log.Printf("[DEBUG] SiteConfig is nil") + return scmRestrictions + } + + for _, v := range *input { + block := make(map[string]interface{}) + + if ip := v.IPAddress; ip != nil { + if *ip == "Any" { + continue + } else { + block["ip_address"] = *ip + } + } + if vNetSubnetID := v.VnetSubnetResourceID; vNetSubnetID != nil { + block["subnet_id"] = *vNetSubnetID + } + if name := v.Name; name != nil { + block["name"] = *name + } + if priority := v.Priority; priority != nil { + block["priority"] = *priority + } + + if action := v.Action; action != nil { + block["action"] = *action + } + + scmRestrictions = append(scmRestrictions, block) + } + return scmRestrictions +} diff --git a/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go b/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go index e62805c626ee..fd611396a42f 100644 --- a/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go +++ b/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go @@ -212,6 +212,7 @@ func TestAccAzureRMFunctionAppSlot_corsSettings(t *testing.T) { }, }) } + func TestAccAzureRMFunctionAppSlot_authSettings(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") @@ -373,6 +374,47 @@ func TestAccAzureRMFunctionAppSlot_oneIpRestriction(t *testing.T) { }) } +func TestAccAzureRMFunctionAppSlot_oneScmIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppSlotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionAppSlot_oneScmIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.ip_address", "10.10.10.10/32"), + ), + }, + }, + }) +} + +func TestAccAzureRMFunctionAppSlot_completeIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppSlotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionAppSlot_completeIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.ip_address", "10.10.10.10/32"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.name", "test-restriction"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.priority", "123"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.action", "Allow"), + ), + }, + }, + }) +} + func TestAccAzureRMFunctionAppSlot_oneVNetSubnetIpRestriction(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") @@ -392,6 +434,47 @@ func TestAccAzureRMFunctionAppSlot_oneVNetSubnetIpRestriction(t *testing.T) { }) } +func TestAccAzureRMFunctionAppSlot_oneScmVNetSubnetIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppSlotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionAppSlot_oneScmVNetSubnetIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMFunctionAppSlot_completeVNetSubnetIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppSlotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionAppSlot_completeVNetSubnetIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.name", "testing-deny"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.priority", "200"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.action", "Deny"), + ), + }, + data.ImportStep(), + }, + }) +} + func TestAccAzureRMFunctionAppSlot_zeroedIpRestriction(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") @@ -428,6 +511,42 @@ func TestAccAzureRMFunctionAppSlot_zeroedIpRestriction(t *testing.T) { }) } +func TestAccAzureRMFunctionAppSlot_zeroedScmIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppSlotDestroy, + Steps: []resource.TestStep{ + { + // This configuration includes a single explicit ip_restriction + Config: testAccAzureRMFunctionAppSlot_oneScmIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.#", "1"), + ), + }, + { + // This configuration has no site_config blocks at all. + Config: testAccAzureRMFunctionAppSlot_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.#", "1"), + ), + }, + { + // This configuration explicitly sets ip_restriction to [] using attribute syntax. + Config: testAccAzureRMFunctionAppSlot_zeroedScmIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.#", "0"), + ), + }, + }, + }) +} + func TestAccAzureRMFunctionAppSlot_manyIpRestrictions(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") @@ -450,6 +569,59 @@ func TestAccAzureRMFunctionAppSlot_manyIpRestrictions(t *testing.T) { }) } +func TestAccAzureRMFunctionAppSlot_manyCompleteIpRestrictions(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppSlotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionAppSlot_manyCompleteIpRestrictions(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.ip_address", "10.10.10.10/32"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.name", "test-restriction"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.priority", "123"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.action", "Allow"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.1.ip_address", "20.20.20.0/24"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.1.name", "test-restriction"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.1.priority", "1234"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.1.action", "Deny"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.2.ip_address", "30.30.0.0/16"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.2.name", "test-restriction"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.2.priority", "12345"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.2.action", "Allow"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.3.ip_address", "192.168.1.2/24"), + ), + }, + }, + }) +} + +func TestAccAzureRMFunctionAppSlot_manyScmIpRestrictions(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppSlotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionAppSlot_manyScmIpRestrictions(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppSlotExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.ip_address", "10.10.10.10/32"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.1.ip_address", "20.20.20.0/24"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.2.ip_address", "30.30.0.0/16"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.3.ip_address", "192.168.1.2/24"), + ), + }, + }, + }) +} + func TestAccAzureRMFunctionAppSlot_tagsUpdate(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app_slot", "test") @@ -1659,6 +1831,469 @@ resource "azurerm_function_app_slot" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) } +func testAccAzureRMFunctionAppSlot_completeIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_function_app" "test" { + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key +} + +resource "azurerm_function_app_slot" "test" { + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + ip_restriction { + ip_address = "10.10.10.10/32" + action = "Allow" + priority = 123 + name = "test-restriction" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionAppSlot_completeVNetSubnetIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +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_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_function_app" "test" { + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key +} + +resource "azurerm_function_app_slot" "test" { + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + ip_restriction { + subnet_id = azurerm_subnet.test.id + action = "Deny" + priority = 200 + name = "testing-deny" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionAppSlot_manyCompleteIpRestrictions(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_function_app" "test" { + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key +} + +resource "azurerm_function_app_slot" "test" { + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + ip_restriction { + ip_address = "10.10.10.10/32" + name = "test-restriction" + priority = 123 + action = "Allow" + } + + ip_restriction { + ip_address = "20.20.20.0/24" + name = "test-restriction" + priority = 1234 + action = "Deny" + } + + ip_restriction { + ip_address = "30.30.0.0/16" + name = "test-restriction" + priority = 12345 + action = "Allow" + } + + ip_restriction { + ip_address = "192.168.1.2/24" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionAppSlot_oneScmIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_function_app" "test" { + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key +} + +resource "azurerm_function_app_slot" "test" { + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + ip_address = "10.10.10.10/32" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionAppSlot_oneScmVNetSubnetIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +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_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_function_app" "test" { + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key +} + +resource "azurerm_function_app_slot" "test" { + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + subnet_id = azurerm_subnet.test.id + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionAppSlot_zeroedScmIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_function_app" "test" { + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key +} + +resource "azurerm_function_app_slot" "test" { + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction = [] + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionAppSlot_manyScmIpRestrictions(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_function_app" "test" { + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key +} + +resource "azurerm_function_app_slot" "test" { + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + ip_address = "10.10.10.10/32" + } + + scm_ip_restriction { + ip_address = "20.20.20.0/24" + } + + scm_ip_restriction { + ip_address = "30.30.0.0/16" + } + + scm_ip_restriction { + ip_address = "192.168.1.2/24" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} func testAccAzureRMFunctionAppSlot_tags(data acceptance.TestData) string { return fmt.Sprintf(` diff --git a/azurerm/internal/services/web/tests/resource_arm_function_app_test.go b/azurerm/internal/services/web/tests/resource_arm_function_app_test.go index f05ba6f727d4..463f30f622ab 100644 --- a/azurerm/internal/services/web/tests/resource_arm_function_app_test.go +++ b/azurerm/internal/services/web/tests/resource_arm_function_app_test.go @@ -751,6 +751,7 @@ func TestAccAzureRMFunctionApp_oneIpRestriction(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMFunctionAppExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.ip_address", "10.10.10.10/32"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.action", "Allow"), ), }, data.ImportStep(), @@ -777,6 +778,89 @@ func TestAccAzureRMFunctionApp_oneVNetSubnetIpRestriction(t *testing.T) { }) } +func TestAccAzureRMFunctionApp_completeVNetSubnetIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_completeVNetSubnetIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.name", "test-subnet-restriction"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.action", "Allow"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.ip_restriction.0.priority", "123"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMFunctionApp_oneScmVNetSubnetIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_oneScmVNetSubnetIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMFunctionApp_completeScmVNetSubnetIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_completeScmVNetSubnetIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.name", "test-subnet-restriction"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.action", "Allow"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.priority", "123"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMFunctionApp_useMainScmVNetSubnetIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_useMainScmVNetSubnetIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_use_main_ip_restriction", "true"), + ), + }, + data.ImportStep(), + }, + }) +} + func TestAccAzureRMFunctionApp_ipRestrictionRemoved(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app", "test") @@ -836,6 +920,66 @@ func TestAccAzureRMFunctionApp_manyIpRestrictions(t *testing.T) { }) } +func TestAccAzureRMFunctionApp_scmOneIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_scmOneIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.ip_address", "10.10.10.10/32"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.action", "Allow"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMFunctionApp_scmCompleteIpRestriction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_scmOneIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.ip_address", "10.10.10.10/32"), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMFunctionApp_scmManyIpRestrictions(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.ip_address", "10.10.10.10/32"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.1.ip_address", "20.20.20.0/24"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.2.ip_address", "30.30.30.0/24"), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMFunctionApp_scmCompleteIpRestriction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.ip_address", "10.10.10.10/32"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.name", "test-restriction"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.priority", "123"), + resource.TestCheckResourceAttr(data.ResourceName, "site_config.0.scm_ip_restriction.0.action", "Allow"), + ), + }, + data.ImportStep(), + }, + }) +} + func TestAccAzureRMFunctionApp_updateStorageAccountKey(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app", "test") @@ -2282,6 +2426,7 @@ resource "azurerm_function_app" "test" { site_config { ip_restriction { ip_address = "10.10.10.10/32" + action = "Allow" } } } @@ -2349,6 +2494,260 @@ resource "azurerm_function_app" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) } +func testAccAzureRMFunctionApp_completeVNetSubnetIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +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_function_app" "test" { + name = "acctest-%d-func" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + ip_restriction { + subnet_id = azurerm_subnet.test.id + action = "Allow" + priority = 123 + name = "test-subnet-restriction" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionApp_oneScmVNetSubnetIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +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_function_app" "test" { + name = "acctest-%d-func" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + subnet_id = azurerm_subnet.test.id + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionApp_completeScmVNetSubnetIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +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_function_app" "test" { + name = "acctest-%d-func" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + subnet_id = azurerm_subnet.test.id + action = "Allow" + priority = 123 + name = "test-subnet-restriction" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionApp_useMainScmVNetSubnetIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +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_function_app" "test" { + name = "acctest-%d-func" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + ip_restriction { + subnet_id = azurerm_subnet.test.id + action = "Allow" + priority = 123 + name = "test-subnet-restriction" + } + scm_use_main_ip_restriction = true + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) +} + func testAccAzureRMFunctionApp_manyIpRestrictions(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { @@ -2390,10 +2789,16 @@ resource "azurerm_function_app" "test" { site_config { ip_restriction { ip_address = "10.10.10.10/32" + name = "test-restriction" + priority = 123 + action = "Allow" } ip_restriction { ip_address = "20.20.20.0/24" + name = "test-restriction-2" + priority = 1234 + action = "Deny" } ip_restriction { @@ -2408,6 +2813,166 @@ resource "azurerm_function_app" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) } +func testAccAzureRMFunctionApp_scmOneIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +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_function_app" "test" { + name = "acctest-%d-func" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + ip_address = "10.10.10.10/32" + action = "Allow" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionApp_scmManyIpRestrictions(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +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_function_app" "test" { + name = "acctest-%d-func" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + ip_address = "10.10.10.10/32" + name = "test-restriction" + priority = 123 + action = "Allow" + } + scm_ip_restriction { + ip_address = "20.20.20.0/24" + name = "test-restriction-2" + priority = 1234 + action = "Deny" + } + scm_ip_restriction { + ip_address = "30.30.30.0/24" + name = "test-restriction-3" + priority = 12345 + action = "Allow" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionApp_scmCompleteIpRestriction(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +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_function_app" "test" { + name = "acctest-%d-func" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + scm_ip_restriction { + ip_address = "10.10.10.10/32" + name = "test-restriction" + priority = 123 + action = "Allow" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) +} + func testAccAzureRMFunctionApp_ipRestrictionRemoved(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/r/function_app.html.markdown b/website/docs/r/function_app.html.markdown index e25de334087c..aae76cdab402 100644 --- a/website/docs/r/function_app.html.markdown +++ b/website/docs/r/function_app.html.markdown @@ -206,6 +206,13 @@ The following arguments are supported: -> **NOTE** User has to explicitly set `ip_restriction` to empty slice (`[]`) to remove it. +* `scm_use_main_ip_restriction` - (Optional) IP security restrictions for scm to use main. Defaults to false. + +-> **NOTE** Any `scm_ip_restriction` blocks configured are ignored by the service when `scm_use_main_ip_restriction` is set to `true`. Any scm restrictions will become active if this is subsequently set to `false` or removed. + +* `scm_ip_restriction` - (Optional) A [List of objects](/docs/configuration/attr-as-blocks.html) representing ip restrictions as defined below. + +-> **NOTE** User has to explicitly set `scm_ip_restriction` to empty slice (`[]`) to remove it. --- A `cors` block supports the following: @@ -302,12 +309,36 @@ A `microsoft` block supports the following: A `ip_restriction` block supports the following: -* `ip_address` - (Optional) The IP Address CIDR notation used for this IP Restriction. +* `ip_address` - (Optional) The IP Address used for this IP Restriction in CIDR notation. + +* `subnet_id` - (Optional) The Virtual Network Subnet ID used for this IP Restriction. + +-> **NOTE:** One of either `ip_address` or `subnet_id` must be specified + +* `name` - (Optional) The name for this IP Restriction. + +* `priority` - (Optional) The priority for this IP Restriction. Restrictions are enforced in priority order. By default, priority is set to 65000 if not specified. + +* `action` - (Optional) Does this restriction `Allow` or `Deny` access for this IP range. Defaults to `Allow`. -* `subnet_id` - (Optional) The Subnet ID used for this IP Restriction. +--- + +A `scm_ip_restriction` block supports the following: + +* `ip_address` - (Optional) The IP Address used for this IP Restriction in CIDR notation. + +* `subnet_id` - (Optional) The Virtual Network Subnet ID used for this IP Restriction. -> **NOTE:** One of either `ip_address` or `subnet_id` must be specified +* `name` - (Optional) The name for this IP Restriction. + +* `priority` - (Optional) The priority for this IP Restriction. Restrictions are enforced in priority order. By default, priority is set to 65000 if not specified. + +* `action` - (Optional) Allow or Deny access for this IP range. Defaults to Allow. + +--- + ## Attributes Reference The following attributes are exported: diff --git a/website/docs/r/function_app_slot.html.markdown b/website/docs/r/function_app_slot.html.markdown index e71f24322847..cbd2b2b871d9 100644 --- a/website/docs/r/function_app_slot.html.markdown +++ b/website/docs/r/function_app_slot.html.markdown @@ -138,7 +138,17 @@ The following arguments are supported: * `cors` - (Optional) A `cors` block as defined below. -* `ip_restriction` - (Optional) A [List of objects](/docs/configuration/attr-as-blocks.html) representing ip restrictions as defined below. +* `ip_restriction` - (Optional) A [List of objects](/docs/configuration/attr-as-blocks.html) representing ip restrictions as defined below. + +-> **NOTE** User has to explicitly set `ip_restriction` to empty slice (`[]`) to remove it. + +* `scm_use_main_ip_restriction` - (Optional) IP security restrictions for scm to use main. Defaults to false. + +-> **NOTE** Any `scm_ip_restriction` blocks configured are ignored by the service when `scm_use_main_ip_restriction` is set to `true`. Any scm restrictions will become active if this is subsequently set to `false` or removed. + +* `scm_ip_restriction` - (Optional) A [List of objects](/docs/configuration/attr-as-blocks.html) representing ip restrictions as defined below. + +-> **NOTE** User has to explicitly set `scm_ip_restriction` to empty slice (`[]`) to remove it. --- @@ -236,12 +246,36 @@ A `microsoft` block supports the following: A `ip_restriction` block supports the following: -* `ip_address` - (Optional) The IP Address CIDR notation used for this IP Restriction. +* `ip_address` - (Optional) The IP Address used for this IP Restriction in CIDR notation. + +* `subnet_id` - (Optional) The Virtual Network Subnet ID used for this IP Restriction. + +-> **NOTE:** One of either `ip_address` or `subnet_id` must be specified + +* `name` - (Optional) The name for this IP Restriction. + +* `priority` - (Optional) The priority for this IP Restriction. Restrictions are enforced in priority order. By default, priority is set to 65000 if not specified. -* `subnet_id` - (Optional) The Subnet ID used for this IP Restriction. +* `action` - (Optional) Does this restriction `Allow` or `Deny` access for this IP range. Defaults to `Allow`. + +--- + +A `scm_ip_restriction` block supports the following: + +* `ip_address` - (Optional) The IP Address used for this IP Restriction in CIDR notation. + +* `subnet_id` - (Optional) The Virtual Network Subnet ID used for this IP Restriction. -> **NOTE:** One of either `ip_address` or `subnet_id` must be specified +* `name` - (Optional) The name for this IP Restriction. + +* `priority` - (Optional) The priority for this IP Restriction. Restrictions are enforced in priority order. By default, priority is set to 65000 if not specified. + +* `action` - (Optional) Allow or Deny access for this IP range. Defaults to Allow. + +--- + ## Attributes Reference The following attributes are exported: