Skip to content

Terraform module composition (feature) for Azure App Service (Service Plan + WebApp)

License

Notifications You must be signed in to change notification settings

claranet/terraform-azurerm-app-service

Repository files navigation

Azure App Service Web (Linux or Windows)

Changelog Notice Apache V2 License TF Registry

This Terraform module creates an Azure Service Plan using our dedicated Terraform module and creates an Azure App Service Web (Linux or Windows) associated with an Application Insights component and activated Diagnostics Logs.

Limitations

  • Diagnostics logs only works fine for Windows for now.
  • Untested with App Service slots.
  • Using a single certificate file on multiple domains with the custom_domains variable is not supported. Use a Key Vault certificate instead.

Global versioning rule for Claranet Azure modules

Module version Terraform version AzureRM version
>= 7.x.x 1.3.x >= 3.0
>= 6.x.x 1.x >= 3.0
>= 5.x.x 0.15.x >= 2.0
>= 4.x.x 0.13.x / 0.14.x >= 2.0
>= 3.x.x 0.12.x >= 2.0
>= 2.x.x 0.12.x < 2.0
< 2.x.x 0.11.x < 2.0

Contributing

If you want to contribute to this repository, feel free to use our pre-commit git hook configuration which will help you automatically update and format some files for you by enforcing our Terraform code module best-practices.

More details are available in the CONTRIBUTING.md file.

Usage

This module is optimized to work with the Claranet terraform-wrapper tool which set some terraform variables in the environment needed by this module. More details about variables set by the terraform-wrapper available in the documentation.

module "azure_region" {
  source  = "claranet/regions/azurerm"
  version = "x.x.x"

  azure_region = var.azure_region
}

module "rg" {
  source  = "claranet/rg/azurerm"
  version = "x.x.x"

  location    = module.azure_region.location
  client_name = var.client_name
  environment = var.environment
  stack       = var.stack
}

module "logs" {
  source  = "claranet/run/azurerm//modules/logs"
  version = "x.x.x"

  client_name         = var.client_name
  environment         = var.environment
  stack               = var.stack
  location            = module.azure_region.location
  location_short      = module.azure_region.location_short
  resource_group_name = module.rg.resource_group_name
}

resource "azurerm_storage_account" "assets_storage" {
  account_replication_type = "LRS"
  account_tier             = "Standard"
  location                 = module.azure_region.location
  name                     = "appserviceassets"
  resource_group_name      = module.rg.resource_group_name
  min_tls_version          = "TLS1_2"
}

resource "azurerm_storage_share" "assets_share" {
  name                 = "assets"
  storage_account_name = azurerm_storage_account.assets_storage.name
  quota                = 50
}

module "app_service" {
  source  = "claranet/app-service/azurerm"
  version = "x.x.x"

  client_name         = var.client_name
  environment         = var.environment
  location            = module.azure_region.location
  location_short      = module.azure_region.location_short
  resource_group_name = module.rg.resource_group_name
  stack               = var.stack

  os_type  = "Linux"
  sku_name = "B2"

  app_settings = {
    FOO = "bar"
  }

  site_config = {
    application_stack = {
      php_version = "8.2"
    }

    http2_enabled = true

    # The "AcrPull" role must be assigned to the managed identity in the target Azure Container Registry
    acr_use_managed_identity_credentials = true
  }

  auth_settings = {
    enabled             = true
    token_store_enabled = true

    active_directory = {
      client_id         = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      client_secret     = "xxxxxxxxxxxxxxxxxxxxx"
      allowed_audiences = ["https://www.example.com"]
    }
  }

  custom_domains = {
    # Custom domain with SSL certificate file
    "example.com" = {
      certificate_file     = "./example.com.pfx"
      certificate_password = "xxxxxxxxx"
    }
    # Custom domain with SSL certificate stored in a keyvault
    "example2.com" = {
      certificate_keyvault_certificate_id = var.certificate_keyvault_id
    }
    # Custom domain without SSL certificate
    "example3.com" = null
    # Custom domain with an existant SSL certificate
    "exemple4.com" = {
      certificate_id = var.certificate_id
    }
  }

  authorized_ips = ["1.2.3.4/32", "4.3.2.1/32"]

  ip_restriction_headers = {
    x_forwarded_host = ["myhost1.fr", "myhost2.fr"]
  }
  scm_ip_restriction_headers = {
    x_forwarded_host = ["myhost1.fr", "myhost2.fr"]
  }

  staging_slot_custom_app_settings = {
    John = "Doe"
  }

  extra_tags = {
    foo = "bar"
  }

  mount_points = [
    {
      account_name = azurerm_storage_account.assets_storage.name
      share_name   = azurerm_storage_share.assets_share.name
      access_key   = azurerm_storage_account.assets_storage.primary_access_key
      mount_path   = "/var/www/html/assets"
    }
  ]

  application_insights_log_analytics_workspace_id = module.logs.log_analytics_workspace_id

  logs_destinations_ids = [
    module.logs.logs_storage_account_id,
    module.logs.log_analytics_workspace_id,
  ]
}

Providers

Name Version
null ~> 3.0

Modules

Name Source Version
container_web_app ./modules/container-web-app n/a
linux_web_app ./modules/linux-web-app n/a
service_plan claranet/app-service-plan/azurerm ~> 6.5.0
windows_web_app ./modules/windows-web-app n/a

Resources

Name Type
null_resource.fake_webapp_container_condition resource

Inputs

Name Description Type Default Required
app_service_custom_name Name of the App Service, generated if not set. string "" no
app_service_environment_id The ID of the App Service Environment to create this Service Plan in. Requires an Isolated SKU. Use one of I1, I2, I3 for azurerm_app_service_environment, or I1v2, I2v2, I3v2 for azurerm_app_service_environment_v3 string null no
app_service_logs Configuration of the App Service and App Service Slot logs. Linux and Windows documentation.
object({
detailed_error_messages = optional(bool)
failed_request_tracing = optional(bool)
application_logs = optional(object({
file_system_level = string
azure_blob_storage = optional(object({
level = string
retention_in_days = number
sas_url = string
}))
}))
http_logs = optional(object({
azure_blob_storage = optional(object({
retention_in_days = number
sas_url = string
}))
file_system = optional(object({
retention_in_days = number
retention_in_mb = number
}))
}))
})
null no
app_service_vnet_integration_subnet_id Id of the subnet to associate with the app service string null no
app_settings Application settings for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#app_settings map(string) {} no
application_insights_custom_name Name of the Application Insights, generated if not set. string "" no
application_insights_daily_data_cap Daily data volume cap (in GB) for Application Insights. number null no
application_insights_daily_data_cap_notifications_disabled Whether disable email notifications when data volume cap is met. bool null no
application_insights_enabled Whether Application Insights should be deployed. bool true no
application_insights_force_customer_storage_for_profiler Whether to enforce users to create their own Storage Account for profiling in Application Insights. bool false no
application_insights_id ID of the existing Application Insights to use instead of deploying a new one. string null no
application_insights_internet_ingestion_enabled Whether ingestion support from Application Insights component over the Public Internet is enabled. bool true no
application_insights_internet_query_enabled Whether querying support from Application Insights component over the Public Internet is enabled. bool true no
application_insights_ip_masking_disabled Whether IP masking in logs is disabled. bool false no
application_insights_local_authentication_disabled Whether Non-Azure AD based authentication is disabled. bool false no
application_insights_log_analytics_workspace_id ID of the Log Analytics Workspace to be used with Application Insights. string null no
application_insights_retention Retention period (in days) for logs. number 90 no
application_insights_sampling_percentage Percentage of data produced by the monitored application sampled for Application Insights telemetry. number null no
application_insights_type Application Insights type if need to be generated. See documentation https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/application_insights#application_type string "web" no
auth_settings Authentication settings. Issuer URL is generated thanks to the tenant ID. For active_directory block, the allowed_audiences list is filled with a value generated with the name of the App Service. See https://www.terraform.io/docs/providers/azurerm/r/app_service.html#auth_settings any {} no
auth_settings_v2 Authentication settings V2. See https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_web_app#auth_settings_v2 any {} no
authorized_ips IPs restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#ip_restriction list(string) [] no
authorized_service_tags Service Tags restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#ip_restriction list(string) [] no
authorized_subnet_ids Subnets restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#ip_restriction list(string) [] no
backup_custom_name Custom name for backup string null no
backup_enabled true to enable App Service backup bool false no
backup_frequency_interval Frequency interval for the App Service backup. number 1 no
backup_frequency_unit Frequency unit for the App Service backup. Possible values are Day or Hour. string "Day" no
backup_keep_at_least_one_backup Should the service keep at least one backup, regardless of age of backup. bool true no
backup_retention_period_in_days Retention in days for the App Service backup. number 30 no
backup_storage_account_connection_string Storage account connection string to use if App Service backup is enabled. string null no
backup_storage_account_container Name of the container in the Storage Account if App Service backup is enabled string "webapps" no
certificates Certificates for custom domains map(map(string)) {} no
client_affinity_enabled Client affinity activation for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#client_affinity_enabled bool false no
client_certificate_enabled Client certificate activation for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#client_certificate_enabled bool false no
client_name Client name/account used in naming string n/a yes
connection_strings Connection strings for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#connection_string list(map(string)) [] no
custom_diagnostic_settings_name Custom name of the diagnostics settings, name will be 'default' if not set. string "default" no
custom_domains Custom domains and SSL certificates of the App Service. Could declare a custom domain with SSL binding. SSL certificate could be provided from an Azure Keyvault Certificate Secret or from a file with following attributes :
- certificate_name:                     Name of the stored certificate.
- certificate_keyvault_certificate_id: ID of the Azure Keyvault Certificate Secret.
map(object({
certificate_name = optional(string)
certificate_keyvault_certificate_id = optional(string)
certificate_thumbprint = optional(string)
}))
null no
default_tags_enabled Option to enable or disable default tags. bool true no
docker_image Docker image to use for this App Service
object({
registry = string
name = string
tag = string
registry_username = optional(string)
registry_password = optional(string)
slot_tag = optional(string)
})
null no
environment Project environment string n/a yes
extra_tags Extra tags to add. map(string) {} no
https_only HTTPS restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#https_only bool false no
identity Map with identity block information.
object({
type = string
identity_ids = list(string)
})
{
"identity_ids": [],
"type": "SystemAssigned"
}
no
ip_restriction_headers IPs restriction headers for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#headers map(list(string)) null no
location Azure location. string n/a yes
location_short Short string for Azure location. string n/a yes
logs_categories Log categories to send to destinations. list(string) null no
logs_destinations_ids List of destination resources IDs for logs diagnostic destination.
Can be Storage Account, Log Analytics Workspace and Event Hub. No more than one of each can be set.
If you want to specify an Azure EventHub to send logs and metrics to, you need to provide a formated string with both the EventHub Namespace authorization send ID and the EventHub name (name of the queue to use in the Namespace) separated by the `
` character. list(string) n/a
logs_metrics_categories Metrics categories to send to destinations. list(string) null no
maximum_elastic_worker_count The maximum number of workers to use in an Elastic SKU Plan. Cannot be set unless using an Elastic SKU. number null no
mount_points Storage Account mount points. Name is generated if not set and default type is AzureFiles. See https://www.terraform.io/docs/providers/azurerm/r/app_service.html#storage_account
list(object({
name = optional(string)
type = optional(string, "AzureFiles")
account_name = string
share_name = string
access_key = string
mount_path = optional(string)
}))
[] no
name_prefix Optional prefix for the generated name string "" no
name_suffix Optional suffix for the generated name string "" no
os_type The O/S type for the App Services to be hosted in this plan. Possible values include Windows, Linux, and Container. string n/a yes
per_site_scaling_enabled Should Per Site Scaling be enabled. bool false no
public_network_access_enabled Whether enable public access for the App Service. bool false no
resource_group_name Resource group name string n/a yes
scm_authorized_ips SCM IPs restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#scm_ip_restriction list(string) [] no
scm_authorized_service_tags SCM Service Tags restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#scm_ip_restriction list(string) [] no
scm_authorized_subnet_ids SCM subnets restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#scm_ip_restriction list(string) [] no
scm_ip_restriction_headers IPs restriction headers for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#headers map(list(string)) null no
service_plan_custom_name Name of the App Service Plan, generated if not set. string "" no
service_plan_extra_tags Extra tags to add. map(string) {} no
site_config Site config for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#site_config. IP restriction attribute is no more managed in this block. any {} no
sku_name The SKU for the plan. Possible values include B1, B2, B3, D1, F1, FREE, I1, I2, I3, I1v2, I2v2, I3v2, P1v2, P2v2, P3v2, P0v3, P1v3, P2v3, P3v3, S1, S2, S3, SHARED, Y1, EP1, EP2, EP3, WS1, WS2, and WS3. string n/a yes
stack Project stack name string n/a yes
staging_slot_custom_app_settings Override staging slot with custom app settings map(string) null no
staging_slot_custom_name Custom name of the app service slot string null no
staging_slot_enabled Create a staging slot alongside the app service for blue/green deployment purposes. See documentation https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service_slot bool true no
staging_slot_mount_points Storage Account mount points for Staging slot. Name is generated if not set and default type is AzureFiles. See https://www.terraform.io/docs/providers/azurerm/r/app_service.html#storage_account
list(object({
name = optional(string)
type = optional(string, "AzureFiles")
account_name = string
share_name = string
access_key = string
mount_path = optional(string)
}))
[] no
sticky_settings Lists of connection strings and app settings to prevent from swapping between slots.
object({
app_setting_names = optional(list(string))
connection_string_names = optional(list(string))
})
null no
use_caf_naming Use the Azure CAF naming provider to generate default resource name. custom_name override this if set. Legacy default name is used if this is set to false. bool true no
worker_count The number of Workers (instances) to be allocated. number null no
zone_balancing_enabled Should the Service Plan balance across Availability Zones in the region. bool true no

Outputs

Name Description
app_service_container App Service Container (Container WebApp) output object if Container is choosen. Please refer to ./modules/container-web-app/README.md
app_service_linux App Service Linux (Linux WebApp) output object if Linux is choosen. Please refer to ./modules/linux-web-app/README.md
app_service_windows App Service Windows (Windows WebApp) output object if Windows is choosen. Please refer to ./modules/windows-web-app/README.md
service_plan Service Plan output object. Please refer to https://github.com/claranet/terraform-azurerm-app-service-plan/blob/master/README.md#outputs

Related documentation

Microsoft Azure documentation: docs.microsoft.com/en-us/azure/app-service/overview