Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_app_service: Adds support for CORS settings #2870

Merged
85 changes: 85 additions & 0 deletions azurerm/helpers/azure/app_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func SchemaAppServiceCorsSettings() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"allowed_origins": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"support_credentials": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
},
}
}

func SchemaAppServiceSiteConfig() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Expand Down Expand Up @@ -207,11 +230,63 @@ func SchemaAppServiceSiteConfig() *schema.Schema {
Type: schema.TypeString,
Optional: true,
},

"cors": SchemaAppServiceCorsSettings(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this schema is also shared with the App Service Slot resource, could we add the same acceptance test / docs for that resource too?

},
},
}
}

func ExpandAppServiceCorsSettings(input interface{}) web.CorsSettings {
settings := input.([]interface{})
corsSettings := web.CorsSettings{}

if len(settings) == 0 {
return corsSettings
}

setting := settings[0].(map[string]interface{})

if v, ok := setting["allowed_origins"]; ok {
input := v.([]interface{})

allowedOrigins := make([]string, 0)
for _, param := range input {
allowedOrigins = append(allowedOrigins, param.(string))
}

corsSettings.AllowedOrigins = &allowedOrigins
}

if v, ok := setting["support_credentials"]; ok {
corsSettings.SupportCredentials = utils.Bool(v.(bool))
}

return corsSettings
}

func FlattenAppServiceCorsSettings(input *web.CorsSettings) []interface{} {
results := make([]interface{}, 0)
result := make(map[string]interface{})

if input == nil {
log.Printf("[DEBUG] CorsSettings is nil")
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
return results
}

allowedOrigins := make([]string, 0)
if s := input.AllowedOrigins; s != nil {
allowedOrigins = *s
}
result["allowed_origins"] = allowedOrigins

if input.SupportCredentials != nil {
result["support_credentials"] = *input.SupportCredentials
}

return append(results, result)
}

func ExpandAppServiceSiteConfig(input interface{}) web.SiteConfig {
configs := input.([]interface{})
siteConfig := web.SiteConfig{}
Expand Down Expand Up @@ -340,6 +415,12 @@ func ExpandAppServiceSiteConfig(input interface{}) web.SiteConfig {
siteConfig.VnetName = utils.String(v.(string))
}

if v, ok := config["cors"]; ok {
corsSettings := v.(interface{})
expand := ExpandAppServiceCorsSettings(corsSettings)
siteConfig.Cors = &expand
}

return siteConfig
}

Expand Down Expand Up @@ -451,5 +532,9 @@ func FlattenAppServiceSiteConfig(input *web.SiteConfig) []interface{} {
result["ftps_state"] = string(input.FtpsState)
result["min_tls_version"] = string(input.MinTLSVersion)

if input.Cors != nil {
result["cors"] = FlattenAppServiceCorsSettings(input.Cors)
}
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved

return append(results, result)
}
68 changes: 68 additions & 0 deletions azurerm/resource_arm_app_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,36 @@ func TestAccAzureRMAppService_minTls(t *testing.T) {
})
}

func TestAccAzureRMAppService_corsSettings(t *testing.T) {
resourceName := "azurerm_app_service.test"
ri := tf.AccRandTimeInt()
config := testAccAzureRMAppService_corsSettings(ri, testLocation())

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMAppServiceDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMAppServiceExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "site_config.0.cors.#", "1"),
resource.TestCheckResourceAttr(resourceName, "site_config.0.cors.0.support_credentials", "true"),
resource.TestCheckResourceAttr(resourceName, "site_config.0.cors.0.allowed_origins.#", "3"),
resource.TestCheckResourceAttr(resourceName, "site_config.0.cors.0.allowed_origins.0", "http://www.contoso.com"),
resource.TestCheckResourceAttr(resourceName, "site_config.0.cors.0.allowed_origins.1", "www.contoso.com"),
resource.TestCheckResourceAttr(resourceName, "site_config.0.cors.0.allowed_origins.2", "contoso.com"),
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
)},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testCheckAzureRMAppServiceDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*ArmClient).appServicesClient

Expand Down Expand Up @@ -2412,3 +2442,41 @@ resource "azurerm_app_service" "test" {
}
`, rInt, location, rInt, rInt, tlsVersion)
}

func testAccAzureRMAppService_corsSettings(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}"

site_config {
cors {
allowed_origins = [
"http://www.contoso.com",
"www.contoso.com",
"contoso.com"
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
]
support_credentials = true
}
}
}
`, rInt, location, rInt, rInt)
}
10 changes: 10 additions & 0 deletions website/docs/r/app_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ The following arguments are supported:

* `websockets_enabled` - (Optional) Should WebSockets be enabled?

* `cors` - A `cors` block as defined below.

---

`ip_restriction` supports the following:
Expand Down Expand Up @@ -243,6 +245,14 @@ The following attributes are exported:
* `repo_url` - URL of the Git repository for this App Service.
* `branch` - Branch name of the Git repository for this App Service.

---

`cors` supports the following:

* `allowed_origins` - (Required) List of allowed origins

* `support_credentials` - (Optional) Should credential headers be allowed? Defaults to `false`.

## Import

App Services can be imported using the `resource id`, e.g.
Expand Down