Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Prepare Azure environments for new workloads—subscriptions, networking, identity, and landing zones
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/services/functions/terraform.md
1# Functions Terraform Patterns — REFERENCE ONLY23> ⛔ **DO NOT COPY THIS CODE DIRECTLY**4>5> This file contains **reference patterns** for understanding Azure Functions Terraform structure.6> **You MUST use the composition algorithm** to generate infrastructure:7>8> 1. Load `templates/selection.md` to choose the correct base template9> 2. Follow `templates/recipes/composition.md` for the exact algorithm10> 3. Use `functions_template_get` MCP tool (with `infrastructure: "terraform"`) to list and fetch templates and write `functionFiles[]` + `projectFiles[]` directly — NEVER hand-write Bicep/Terraform and use `azd init -t <template>`/`func init`/`func new` as fallback when composing multiple recipes and required templates are not found11>12> Hand-writing Terraform from these patterns will result in missing RBAC, incorrect managed identity configuration, and security vulnerabilities.1314## Flex Consumption (Recommended)1516**Use Flex Consumption for new deployments with managed identity (no connection strings).**1718> **⚠️ IMPORTANT**: Flex Consumption requires **azurerm provider v4.2 or later**.1920```hcl21terraform {22required_providers {23azurerm = {24source = "hashicorp/azurerm"25version = "~> 4.2"26}27}28}2930provider "azurerm" {31features {}32}3334resource "azurerm_storage_account" "function_storage" {35name = "${var.resource_prefix}func${var.unique_hash}"36location = var.location37resource_group_name = azurerm_resource_group.main.name38account_tier = "Standard"39account_replication_type = "LRS"4041min_tls_version = "TLS1_2"42allow_nested_items_to_be_public = false43shared_access_key_enabled = false # Enforce managed identity44}4546resource "azurerm_storage_container" "deployment_package" {47name = "deploymentpackage"48storage_account_id = azurerm_storage_account.function_storage.id49container_access_type = "private"50}5152resource "azurerm_application_insights" "function_insights" {53name = "appi-${var.unique_hash}"54location = var.location55resource_group_name = azurerm_resource_group.main.name56application_type = "web"57}5859resource "azurerm_service_plan" "function_plan" {60name = "plan-${var.unique_hash}"61location = var.location62resource_group_name = azurerm_resource_group.main.name63os_type = "Linux"64sku_name = "FC1"65}6667resource "azurerm_linux_function_app" "function_app" {68name = "${var.resource_prefix}-${var.service_name}-${var.unique_hash}"69location = var.location70resource_group_name = azurerm_resource_group.main.name71service_plan_id = azurerm_service_plan.function_plan.id72storage_account_name = azurerm_storage_account.function_storage.name73storage_uses_managed_identity = true74https_only = true7576identity {77type = "SystemAssigned"78}7980function_app_config {81deployment {82storage {83type = "blob_container"84value = "${azurerm_storage_account.function_storage.primary_blob_endpoint}${azurerm_storage_container.deployment_package.name}"85authentication {86type = "SystemAssignedIdentity"87}88}89}9091scale_and_concurrency {92maximum_instance_count = 10093instance_memory_mb = 204894}9596runtime {97name = "python" # or "node", "dotnet-isolated"98version = "3.11"99}100}101102site_config {103application_insights_connection_string = azurerm_application_insights.function_insights.connection_string104105application_stack {106python_version = "3.11" # Adjust based on runtime107}108}109110app_settings = {111"AzureWebJobsStorage__blobServiceUri" = azurerm_storage_account.function_storage.primary_blob_endpoint112"FUNCTIONS_EXTENSION_VERSION" = "~4"113"FUNCTIONS_WORKER_RUNTIME" = "python"114}115}116117# Grant Function App access to Storage for runtime118resource "azurerm_role_assignment" "function_storage_access" {119scope = azurerm_storage_account.function_storage.id120role_definition_name = "Storage Blob Data Owner"121principal_id = azurerm_linux_function_app.function_app.identity[0].principal_id122}123```124125> 💡 **Key Points:**126> - Use `AzureWebJobsStorage__blobServiceUri` instead of connection string127> - Set `shared_access_key_enabled = false` for enhanced security128> - Use `storage_uses_managed_identity = true` for deployment authentication129> - Grant `Storage Blob Data Owner` role for full access to blobs, queues, and tables130> - Requires azurerm provider **v4.2 or later**131132### Using Azure Verified Module133134For production deployments, use the official Azure Verified Module:135136```hcl137module "function_app" {138source = "Azure/avm-res-web-site/azurerm"139version = "~> 0.0"140141name = "${var.resource_prefix}-${var.service_name}-${var.unique_hash}"142location = var.location143resource_group_name = azurerm_resource_group.main.name144145kind = "functionapp"146os_type = "Linux"147148sku_name = "FC1"149150function_app_storage_account_name = azurerm_storage_account.function_storage.name151function_app_storage_uses_managed_identity = true152153site_config = {154application_insights_connection_string = azurerm_application_insights.function_insights.connection_string155156application_stack = {157python_version = "3.11"158}159}160161app_settings = {162"AzureWebJobsStorage__blobServiceUri" = azurerm_storage_account.function_storage.primary_blob_endpoint163"FUNCTIONS_EXTENSION_VERSION" = "~4"164"FUNCTIONS_WORKER_RUNTIME" = "python"165}166167identity = {168type = "SystemAssigned"169}170}171```172173> 💡 **Example Reference:** [HashiCorp Flex Consumption Example](https://registry.terraform.io/modules/Azure/avm-res-web-site/azurerm/latest/examples/flex_consumption)174175## Consumption Plan (Legacy)176177> ⛔ **DO NOT USE** — Y1/Dynamic SKU is deprecated for new deployments.178> **ALWAYS use Flex Consumption (FC1)** for all new Azure Functions.179> The Y1 example below is only for reference when migrating legacy apps.180181**⚠️ Not recommended for new deployments. Use Flex Consumption instead.**182183> 💡 **OS and Slots Matter for Consumption:**184> - **Linux Consumption** (`os_type = "Linux"`): Does **not** support deployment slots.185> - **Windows Consumption** (`os_type = "Windows"`): Supports **1 staging slot** (2 total including production).186> If a user specifically needs Windows Consumption with a slot, that is supported — use the Windows pattern below.187> For new apps needing slots, prefer **Elastic Premium (EP1)** for better performance and no cold-start issues.188189### Linux Consumption (no slot support)190191```hcl192resource "azurerm_storage_account" "function_storage" {193name = "${var.resource_prefix}func${var.unique_hash}"194location = var.location195resource_group_name = azurerm_resource_group.main.name196account_tier = "Standard"197account_replication_type = "LRS"198}199200resource "azurerm_service_plan" "function_plan" {201name = "${var.resource_prefix}-funcplan-${var.unique_hash}"202location = var.location203resource_group_name = azurerm_resource_group.main.name204os_type = "Linux"205sku_name = "Y1"206}207208resource "azurerm_linux_function_app" "function_app" {209name = "${var.resource_prefix}-${var.service_name}-${var.unique_hash}"210location = var.location211resource_group_name = azurerm_resource_group.main.name212service_plan_id = azurerm_service_plan.function_plan.id213https_only = true214215storage_account_name = azurerm_storage_account.function_storage.name216storage_account_access_key = azurerm_storage_account.function_storage.primary_access_key217218site_config {219application_insights_connection_string = azurerm_application_insights.function_insights.connection_string220221application_stack {222python_version = "3.11"223}224}225226app_settings = {227"FUNCTIONS_EXTENSION_VERSION" = "~4"228"FUNCTIONS_WORKER_RUNTIME" = "python"229}230231identity {232type = "SystemAssigned"233}234}235```236237### Windows Consumption (supports 1 staging slot)238239> ⚠️ **Windows Consumption is not recommended for new projects** — consider Flex Consumption or Elastic Premium.240> Use this pattern only for existing Windows apps or when Windows-specific features are required.241242```hcl243resource "azurerm_service_plan" "function_plan" {244name = "${var.resource_prefix}-funcplan-${var.unique_hash}"245location = var.location246resource_group_name = azurerm_resource_group.main.name247os_type = "Windows"248sku_name = "Y1"249}250251resource "azurerm_windows_function_app" "function_app" {252name = "${var.resource_prefix}-${var.service_name}-${var.unique_hash}"253location = var.location254resource_group_name = azurerm_resource_group.main.name255service_plan_id = azurerm_service_plan.function_plan.id256https_only = true257258storage_account_name = azurerm_storage_account.function_storage.name259storage_account_access_key = azurerm_storage_account.function_storage.primary_access_key260261site_config {262application_insights_connection_string = azurerm_application_insights.function_insights.connection_string263application_stack {264node_version = "~20"265}266}267268app_settings = {269"FUNCTIONS_EXTENSION_VERSION" = "~4"270"FUNCTIONS_WORKER_RUNTIME" = "node"271"WEBSITE_CONTENTSHARE" = "${lower(var.service_name)}-prod" # must differ per slot; Azure Files share names are lowercase272"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" = azurerm_storage_account.function_storage.primary_connection_string273}274275sticky_settings {276app_setting_names = ["WEBSITE_CONTENTSHARE", "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING"]277}278279identity {280type = "SystemAssigned"281}282}283284# 1 staging slot is supported on Windows Consumption285resource "azurerm_windows_function_app_slot" "staging" {286name = "staging"287function_app_id = azurerm_windows_function_app.function_app.id288289storage_account_name = azurerm_storage_account.function_storage.name290storage_account_access_key = azurerm_storage_account.function_storage.primary_access_key291292site_config {293application_insights_connection_string = azurerm_application_insights.function_insights.connection_string294application_stack {295node_version = "~20"296}297}298299app_settings = {300"FUNCTIONS_EXTENSION_VERSION" = "~4"301"FUNCTIONS_WORKER_RUNTIME" = "node"302"WEBSITE_CONTENTSHARE" = "${var.service_name}-staging" # MUST differ from production303"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" = azurerm_storage_account.function_storage.primary_connection_string304}305}306```307308## Service Bus Integration (Managed Identity)309310```hcl311data "azurerm_servicebus_namespace" "example" {312name = var.servicebus_namespace_name313resource_group_name = var.servicebus_resource_group314}315316resource "azurerm_linux_function_app" "function_app" {317# ... (Function App definition from above)318319app_settings = {320# Storage with managed identity321"AzureWebJobsStorage__blobServiceUri" = azurerm_storage_account.function_storage.primary_blob_endpoint322323# Service Bus with managed identity324"SERVICEBUS__fullyQualifiedNamespace" = "${data.azurerm_servicebus_namespace.example.name}.servicebus.windows.net"325"SERVICEBUS_QUEUE_NAME" = var.servicebus_queue_name326327# Other settings...328"FUNCTIONS_EXTENSION_VERSION" = "~4"329"FUNCTIONS_WORKER_RUNTIME" = "python"330"APPLICATIONINSIGHTS_CONNECTION_STRING" = azurerm_application_insights.function_insights.connection_string331}332}333334# Grant Service Bus Data Receiver role for triggers335resource "azurerm_role_assignment" "servicebus_receiver" {336scope = data.azurerm_servicebus_namespace.example.id337role_definition_name = "Azure Service Bus Data Receiver"338principal_id = azurerm_linux_function_app.function_app.identity[0].principal_id339}340341# Grant Service Bus Data Sender role (if function sends messages)342resource "azurerm_role_assignment" "servicebus_sender" {343scope = data.azurerm_servicebus_namespace.example.id344role_definition_name = "Azure Service Bus Data Sender"345principal_id = azurerm_linux_function_app.function_app.identity[0].principal_id346}347```348349> 💡 **Key Points:**350> - Use `SERVICEBUS__fullyQualifiedNamespace` (double underscore) for managed identity351> - Grant `Service Bus Data Receiver` role for reading messages352> - Grant `Service Bus Data Sender` role for sending messages (if needed)353> - Role assignments automatically enable connection via managed identity354355## Premium Plan (No Cold Starts)356357```hcl358resource "azurerm_service_plan" "function_plan" {359name = "${var.resource_prefix}-funcplan-${var.unique_hash}"360location = var.location361resource_group_name = azurerm_resource_group.main.name362os_type = "Linux"363sku_name = "EP1" # EP1, EP2, or EP3364}365366resource "azurerm_linux_function_app" "function_app" {367# ... (rest of configuration similar to Flex Consumption)368369site_config {370# Premium-specific settings371always_on = true372pre_warmed_instance_count = 1373elastic_instance_minimum = 1374375application_stack {376python_version = "3.11"377}378}379}380```381