Azure Function App - Configuration Notes

A Reference for Azure Function Apps, For when I forget πŸ‘΄

Blogging often serves a dual purpose: not only does it help others who may be facing similar challenges, but it also acts as a personal reference for when we inevitably forget the finer details of our own work. This post is a perfect example of that. While it’s written to assist anyone who might find themselves in need of the same information, it also serves as a handy reminder for me when I look back on it in the future. Hopefully, this can help others in the same way it helps me!

Community Note:

I’m hoping this will be a β€˜living’ post that I can update over time whenever I come across things I need to remember, and later forget πŸ˜…

What is an Azure Function App

An Azure Function App is a serverless compute service in Microsoft Azure that allows you to run event-driven, lightweight code without having to manage the underlying infrastructure. It is designed to execute small pieces of code, called functions, in response to events such as HTTP requests, timer triggers, message queues, or changes in Azure resources.

Key Features

  1. Event-Driven & Serverless – Code runs only when triggered, and Azure automatically scales resources as needed.
  2. Multiple Triggers – Supports HTTP, Timer, Queue, Blob, Event Grid, Event Hub, Service Bus, and more.
  3. Multiple Programming Languages – Supports C#, JavaScript (Node.js), Python, PowerShell, Java, and TypeScript.
  4. Automatic Scaling – Scales up/down dynamically based on demand.
  5. Flexible Hosting Options:
    • Consumption Plan (pay-per-execution, fully serverless)
    • Premium Plan (scales automatically but provides always-on instances)
    • Dedicated (App Service) Plan (fixed infrastructure, good for long-running functions)
  6. Integration with Azure Services – Works with Storage, SQL, Cosmos DB, Azure Monitor, and more.
  7. Durable Functions – Enables stateful, long-running workflows.

Use Cases

  • Automation & Scheduling (e.g., clean-up tasks, report generation)
  • Event Processing (e.g., handling messages from an Azure Queue)
  • Webhooks & API Endpoints (e.g., processing HTTP requests)
  • Data Transformation & Processing (e.g., transforming data before storing it)
  • Security & Monitoring (e.g., responding to security alerts)

For more information, you can check out the MIcrosoft Learn Docs: Azure Function App
For Infrastructure As Code things, You can check out the Azure Verified Modules Web/Function Apps

Configuration Notes and Tips

Requirements.psd1

When wanting to connect to Azure, The base module you need is Az.Accounts
If you’re wanting to interact with Microsoft Graph, you need Microsoft.Graph.Authentication

Key Considerations

Selective vs. Wildcard (‘Az.’ & ‘Microsoft.Graph.’) Loading
  • Using Az.* and Microsoft.Graph.* loads all submodules under the respective parent modules.
  • This provides maximum functionality but significantly increases the cold start time for an Azure Function because all modules are installed and loaded, even if not used.
Cold Start Performance Impact
  • Loading only necessary modules (Az.Accounts, Microsoft.Graph.Authentication) improves start time.
  • Loading all modules (Az.*, Microsoft.Graph.*) increases size and loading time, potentially leading to performance issues.
  • If you only need authentication, load Az.Accounts and Microsoft.Graph.Authentication.
  • If you need full functionality, you may use wildcards but should be aware of the impact on load times.

Basic Authentication Modules

1
2
3
4
5
6
7
8
9
# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
@{
    # For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'.
    # To use the Az module in your function app, please uncomment the line below.
    'Az.Accounts'                                  = '4.*'
    'Microsoft.Graph.Authentication'               = '2.*'
}

All Modules

1
2
3
4
5
6
7
8
9
# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
@{
    # For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'.
    # To use the Az module in your function app, please uncomment the line below.
    'Az.*'                                  = '13.*'
    'Microsoft.Graph.*'                     = '2.*'
}

Azure Authentication

To Configure Azure Authentication, First you need to create an environment variable for managedIdentityId, This needs to be the Client Id

IMPORTANT

Don’t forget to assign the User Managed Identity RBAC Permissions to the Subscription

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Azure Functions profile.ps1
#
# This script runs during a "cold start" of your Function App.
# A "cold start" happens when:
#
# * The Function App starts for the first time.
# * The Function App starts after being de-allocated due to inactivity.
#
# You can use this file to define helper functions, run commands, or set environment variables.
# NOTE: Any non-environment variables will be reset after the first execution.

# Authenticate with Azure PowerShell using Managed Identity (MSI) if Managed Identity ID is available.
if ($env:managedIdentityId) {

    # Disable automatic Az context saving for the current process to avoid conflicts.
    Disable-AzContextAutosave -Scope Process | Out-Null

    # Authenticate to Azure using Managed Identity.
    Write-Host "Authenticating with Azure using Managed Identity..."
    Connect-AzAccount -Identity -AccountId $env:managedIdentityId | Out-Null

    # Retrieve the Azure access token for Microsoft Graph API.
    $azAccessToken = (Get-AzAccessToken -AsSecureString -ResourceUrl "https://graph.microsoft.com").Token

    # Connect to Microsoft Graph using the access token.
    Write-Host "Authenticating with Microsoft Graph..."
    Connect-MgGraph -AccessToken $azAccessToken | Out-Null

    Write-Host "Authentication successful."
}
else {
    Write-Warning "Managed Identity ID is not found. Azure authentication will be skipped."
}

Configuring CORS Access

Cross-Origin Resource Sharing (CORS) is a security feature implemented by web browsers to control how resources on a web server can be accessed from different origins (i.e., domain, protocol, or port). It ensures that resources on a web server are only accessible by web pages from allowed origins, which helps prevent malicious websites from accessing sensitive data.

In a typical scenario, a browser-based JavaScript application might want to make an API call to a backend service (like an Azure Function). If the frontend and backend are hosted on different domains (cross-origin), the browser by default blocks the request for security reasons, unless the backend explicitly allows it.

Azure Portal Configuration

When you create an Azure Function, CORS is not configured out of the box, (When using click ops), If you try and run a function you’ll get this message:

To resolve this, Head to API > CORS and add the url: https://portal.azure.com

Once saved, head back to the function and try execute Try/Run, this time it will pass and give you the results you hoped for πŸŽ‰

Below is a snippet for the Bicep configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
    siteConfig: {
      alwaysOn: false
      linuxFxVersion: 'POWERSHELL|7.4'
      ftpsState: 'Disabled'
      http20Enabled: true
      minTlsVersion: '1.3'
      use32BitWorkerProcess: false
      cors: {
        allowedOrigins: [
          'https://portal.azure.com'
        ]
      }
    }

Key Vault Values

Azure Key Vault is a centralized, secure service to manage secrets, keys, and certificates. When developing a Function App, securely storing sensitive data such as connection strings, API keys, and passwords is crucial. By using Azure Key Vault, you can ensure that secrets are stored in a secure and compliant manner, eliminating the need to store them in code or configuration files, which could lead to accidental exposure.

Key benefits of using Azure Key Vault include:

  • Centralized Management: Manage secrets, keys, and certificates in one place.
  • Access Control: Fine-grained access policies to restrict who can access which secrets.
  • Auditability: Built-in logging and monitoring for security purposes.
  • Security Best Practices: Azure Key Vault integrates with managed identities, providing seamless and secure access to secrets without needing to handle credentials in code.

Storage Account Setup

Using the Azure Verified Modules, We can use export the Access Keys and Connection Strings direct into an Azure Key Vault, Below is an example module which passed these values into the keyvault

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
module createStorageAccount 'br/public:avm/res/storage/storage-account:0.17.3' = {
  name: 'create-storage-account'
  scope: resourceGroup(resourceGroupName)
  params: {
    name: storageAccountName
    location: location
    skuName: stSkuName
    minimumTlsVersion: stTlsVersion
    publicNetworkAccess: stPublicNetworkAccess
    allowSharedKeyAccess: stAllowedSharedKeyAccess
    secretsExportConfiguration: {
      accessKey1Name: 'accessKey1'
      accessKey2Name: 'accessKey2'
      connectionString1Name: 'connectionString1'
      connectionString2Name: 'connectionString2'
      keyVaultResourceId: createKeyVault.outputs.resourceId
    }
    networkAcls: stNetworkAcls
    tags: tags
  }
  dependsOn: [
    createKeyVault
  ]
}

Using Azure Key Vault References in Application Settings

You can configure your Function App’s settings to pull secrets directly from Azure Key Vault. By using a Key Vault reference, you can inject secrets into your function’s environment without storing them explicitly in the configuration.

1
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING: '@Microsoft.KeyVault(VaultName=${keyvaultName};SecretName=connectionString1)'

In this case, ${keyvaultName} is replaced by the name of your Key Vault, and connectionString1 is the name of the secret. When the Function App starts, Azure automatically resolves the secret and makes it available as an environment variable.

ZIP Deployments

Why Use WEBSITE_RUN_FROM_PACKAGE?

WEBSITE_RUN_FROM_PACKAGE is an Azure App Service setting that allows you to deploy your application as a ZIP package rather than individual files. This method offers several benefits:

Faster and More Reliable Deployments

By deploying a single package, you minimize file transfers, reducing deployment time and the risk of incomplete deployments.

Read-Only File System for Consistency

Setting WEBSITE_RUN_FROM_PACKAGE=1 mounts the package as a read-only file system, preventing unintended modifications and ensuring consistency across deployments.

Seamless CI/CD Integration

It works well with CI/CD pipelines like Azure DevOps and GitHub Actions, enabling streamlined, automated deployments.

Reduced Cold Start Time

Preloading the package as a read-only mount can improve startup performance, especially for larger applications.

Easy Rollbacks

Since deployments are immutable, rolling back is as simple as redeploying a previous ZIP package.

Ideal for Azure Functions and App Services

For Azure Functions, this method enhances performance, reduces deployment time, and ensures a stable execution environment.

Building Function Zip

Prepare Your ZIP Package

Ensure your application files are structured correctly. For an Azure Function App, the expected format is:

1
2
3
4
5
6
7
8
/
│── hosts.json
│── requirements.psd1
│── profile.ps1
β”‚
└── functionName/
    │── run.ps1
    │── function.json

Upload the Zip File to a Storage Account, Or Repository

Configure with Bicep

If using Infrastructure as Code, add this setting under appSettingsKeyValuePairs:

1
2
3
appSettingsKeyValuePairs: {
    WEBSITE_RUN_FROM_PACKAGE: 'public-url-to-zip-folder-here' // https://stfuncprodbuild.blob.core.windows.net/functionapp/v1/latest.zip
}

Auto Update

Auto-Update Scenarios

Auto-updating behavior depends on where the package is stored:

  • If WEBSITE_RUN_FROM_PACKAGE points to an Azure Blob Storage URL (e.g., https://storageaccount.blob.core.windows.net/...), the app will always run from the latest version of that blob.
  • When you replace the zip package in storage, the next restart (manual or automatic) picks up the new package.
  • This allows for automatic updates without redeploying the app.

Deployment via Zip Push to Kudu (Azure App Service Zip Deploy)

  • If you deploy a zip package using az webapp deployment source config-zip, it is copied to D:\home\data\SitePackages.
  • The app does not auto-update unless a new zip package is deployed.
  • Restarting the app does not fetch a new version unless a fresh deployment occurs.

Deployment via CI/CD (Azure DevOps, GitHub Actions, etc.)

  • CI/CD pipelines can push a new zip package automatically when changes are made.
  • The app updates whenever a new package is deployed via the pipeline.

How to Ensure Auto-Updates

Use Azure Storage URL (WEBSITE_RUN_FROM_PACKAGE=<Blob URL>)

  • Upload a new zip file to the storage account.
  • Restart the app (az webapp restart or via the portal) to apply the update.

Enable Continuous Deployment (CI/CD)

  • Automate package deployment using Azure DevOps, GitHub Actions, or similar tools.

Set Up App Restart Mechanisms

  • Use deployment slots to swap updated versions seamlessly.
  • Schedule periodic restarts via Azure Functions Timer Trigger or Logic Apps.

Share with your network!

Built with Hugo - Theme Stack designed by Jimmy