Vårt delingshjørne

Using Managed Identity with Azure Functions

Using Managed Identity with Azure Functions

Using Managed Identity with Azure Functions

Adrian

Brenne

Utvikler

Utvikler

4. august 2025

Utvikling

Every developer grapples with managing credentials. Azure’s elegant solution for this is Managed Identity. While powerful, its underlying “magic” can sometimes make implementation seem complex. This article will attempt to demystify the process, guiding you through using both System and User-assigned Managed Identities with Azure Functions, and demonstrating how to leverage them to securely access other Azure resources like Storage Accounts and Key Vaults.

What is Managed Identity?

Managed Identity in Azure provides an automatically managed identity for Azure resources (like VMs, App Services, or Functions) in Microsoft Entra ID (formerly Azure Active Directory). This eliminates the need for developers to manage credentials, secrets, or certificates in their code, as the Azure platform handles the lifecycle and rotation of these credentials for secure authentication to other Azure services that support Microsoft Entra authentication.

What is Azure Functions?

Azure Functions are a serverless compute service that allows you to run small, event-driven pieces of code (functions) without having to explicitly provision or manage infrastructure. You write your code, and Azure handles the underlying servers, scaling, and maintenance. This is ideal for scenarios like processing data, responding to API calls, or running scheduled tasks, where you only pay for the compute resources consumed when your function is actively running.

Azure Functions with System-Managed Identity

For reference, the Azure Functions i used for this setup runs on Linux on the Y1 Consumption plan. I am using Python as my programming language and using External Package URL deployment method for deploying the app.

First, you need to assign your Azure Function a System-managed Identity. Do this by navigating to your function in Azure, then go Settings -> Identity and switch the System-Assigned identity to ON.

Connect to your Storage Account using System-Managed IdentityAs we now know, a Storage Account is required for an Azure Function to work properly. We can use the Managed Identity of the Azure Function to gain access to the Storage Account. To do this, the following configurations are required:The Azure Functions System-Managed Identity needs the following role on the Storage Account: Storage Blob Data Owner.

The Azure Function needs the following environment-variable:

  • AzureWebJobsStorage__accountName = “the name of your storage account”

Its important that you dont have an environment-variable with the name AzureWebJobsStorage, as this usually contains the value of the connection-string to the Storage Account, which is what we are trying to avoid.

Connect to your Key Vault using System-Managed Identity

Azure Key Vault also supports identity-based access. You can turn this on by navigating to your Key Vault in the Azure Portal -> Settings -> Access Configuration -> Choose RBAC under Permission Model.

Then your Azure Function needs to be assigned a role based on the actions its going to perform. For example, for reading secrets, the Key Vault Secrets User needs to be assigned.

Azure Functions with User-Managed Identity

This time you need to assign your Azure Function a User-managed Identity (UMI). To do this you first need to create a UMI. Do this by navigating to the Managed Identities plane, then hit Create. Assign it to your Azure function by going to Settings -> Identity -> User-Assigned and select your newly-created User-Managed identity.

Connect to your Storage Account using User-Managed Identity

The Azure Functions User-Managed Identity needs the following role on the Storage Account: Storage Blob Data Owner.

The Azure Function needs the following environment-variables:

  • AzureWebJobsStorage__accountName = “the name of your storage account”

  • AzureWebJobsStorage__clientId = “the client id of your UMI*”

  • AzureWebJobsStorage__credential = managedIdentity

  • AZURE_CLIENT_ID= “the client id of your UMI”

  • WEBSITE_RUN_FROM_PACKAGE_BLOB_MI_RESOURCE_ID = “the resource id of your UMI**”

*You can find the client id of your UMI by navigating to the resource in the portal:

User-managed identity overview

**The resource id of your UMI is the following: /subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name of your umi>.

You can also see this in the URL when you are viewing your UMI resource in the Azure Portal.

Example function with these variables set:

Azure Function with UMI-specific environment variables set

Connect to your Key Vault using User-Managed Identity

For connecting to other resources using your UMI such as an Azure Key Vault, the procedure is the same as with a System-managed Identity.

Bonus: Use your Managed Identity on Blob-triggers

The blob storage trigger starts a function when a new or updated blob is detected. For this to work, the function needs a connection to the designated Storage Account.

Since we already have established a connection to the Storage Account, we can use that. But since we are using Managed Identity for that access, some extra configuration is required for it to properly work.

Lets say you have the following blob trigger header on your function:

@app.blob_trigger(
    arg_name="trigger", path="bronze/manual/{name}", connection="AzureWebJobsStorage"

You need to define a few more environment variables for the connection to pick up the correct URLs:

  • AzureWebJobsStorage__blobServiceUri = “https://<storage account name>.blob.core.windows.net”

  • AzureWebJobsStorage__queueServiceUri = “https://<storage account name>.queue.core.windows.net”

  • AzureWebJobsStorage__tableServiceUri = “https://<storage account name>.table.core.windows.net”

Then your identity needs the following roles:

  • Storage Blob Data Owner

  • Storage Account Contributor

  • Storage Queue Data Contributor

Example function with these variables set:

Azure Function with blob trigger-specific environment variables

If your more interested, you can read more about this connection in their official docs.

Wrapping up

Thats it! You have successfully removed the need for storing sensitive connection-strings in your Azure Function setup. You are now one step closer to a credential-free code!

This solution was found by scavenging the internet, and a lot of trying and failing. I decided to publish my findings as i only found bits and pieces here and there myself.

If anything is unclear, or if anyone knows any alternative or better methods of solving this, let me know!

Every developer grapples with managing credentials. Azure’s elegant solution for this is Managed Identity. While powerful, its underlying “magic” can sometimes make implementation seem complex. This article will attempt to demystify the process, guiding you through using both System and User-assigned Managed Identities with Azure Functions, and demonstrating how to leverage them to securely access other Azure resources like Storage Accounts and Key Vaults.

What is Managed Identity?

Managed Identity in Azure provides an automatically managed identity for Azure resources (like VMs, App Services, or Functions) in Microsoft Entra ID (formerly Azure Active Directory). This eliminates the need for developers to manage credentials, secrets, or certificates in their code, as the Azure platform handles the lifecycle and rotation of these credentials for secure authentication to other Azure services that support Microsoft Entra authentication.

What is Azure Functions?

Azure Functions are a serverless compute service that allows you to run small, event-driven pieces of code (functions) without having to explicitly provision or manage infrastructure. You write your code, and Azure handles the underlying servers, scaling, and maintenance. This is ideal for scenarios like processing data, responding to API calls, or running scheduled tasks, where you only pay for the compute resources consumed when your function is actively running.

Azure Functions with System-Managed Identity

For reference, the Azure Functions i used for this setup runs on Linux on the Y1 Consumption plan. I am using Python as my programming language and using External Package URL deployment method for deploying the app.

First, you need to assign your Azure Function a System-managed Identity. Do this by navigating to your function in Azure, then go Settings -> Identity and switch the System-Assigned identity to ON.

Connect to your Storage Account using System-Managed IdentityAs we now know, a Storage Account is required for an Azure Function to work properly. We can use the Managed Identity of the Azure Function to gain access to the Storage Account. To do this, the following configurations are required:The Azure Functions System-Managed Identity needs the following role on the Storage Account: Storage Blob Data Owner.

The Azure Function needs the following environment-variable:

  • AzureWebJobsStorage__accountName = “the name of your storage account”

Its important that you dont have an environment-variable with the name AzureWebJobsStorage, as this usually contains the value of the connection-string to the Storage Account, which is what we are trying to avoid.

Connect to your Key Vault using System-Managed Identity

Azure Key Vault also supports identity-based access. You can turn this on by navigating to your Key Vault in the Azure Portal -> Settings -> Access Configuration -> Choose RBAC under Permission Model.

Then your Azure Function needs to be assigned a role based on the actions its going to perform. For example, for reading secrets, the Key Vault Secrets User needs to be assigned.

Azure Functions with User-Managed Identity

This time you need to assign your Azure Function a User-managed Identity (UMI). To do this you first need to create a UMI. Do this by navigating to the Managed Identities plane, then hit Create. Assign it to your Azure function by going to Settings -> Identity -> User-Assigned and select your newly-created User-Managed identity.

Connect to your Storage Account using User-Managed Identity

The Azure Functions User-Managed Identity needs the following role on the Storage Account: Storage Blob Data Owner.

The Azure Function needs the following environment-variables:

  • AzureWebJobsStorage__accountName = “the name of your storage account”

  • AzureWebJobsStorage__clientId = “the client id of your UMI*”

  • AzureWebJobsStorage__credential = managedIdentity

  • AZURE_CLIENT_ID= “the client id of your UMI”

  • WEBSITE_RUN_FROM_PACKAGE_BLOB_MI_RESOURCE_ID = “the resource id of your UMI**”

*You can find the client id of your UMI by navigating to the resource in the portal:

User-managed identity overview

**The resource id of your UMI is the following: /subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name of your umi>.

You can also see this in the URL when you are viewing your UMI resource in the Azure Portal.

Example function with these variables set:

Azure Function with UMI-specific environment variables set

Connect to your Key Vault using User-Managed Identity

For connecting to other resources using your UMI such as an Azure Key Vault, the procedure is the same as with a System-managed Identity.

Bonus: Use your Managed Identity on Blob-triggers

The blob storage trigger starts a function when a new or updated blob is detected. For this to work, the function needs a connection to the designated Storage Account.

Since we already have established a connection to the Storage Account, we can use that. But since we are using Managed Identity for that access, some extra configuration is required for it to properly work.

Lets say you have the following blob trigger header on your function:

@app.blob_trigger(
    arg_name="trigger", path="bronze/manual/{name}", connection="AzureWebJobsStorage"

You need to define a few more environment variables for the connection to pick up the correct URLs:

  • AzureWebJobsStorage__blobServiceUri = “https://<storage account name>.blob.core.windows.net”

  • AzureWebJobsStorage__queueServiceUri = “https://<storage account name>.queue.core.windows.net”

  • AzureWebJobsStorage__tableServiceUri = “https://<storage account name>.table.core.windows.net”

Then your identity needs the following roles:

  • Storage Blob Data Owner

  • Storage Account Contributor

  • Storage Queue Data Contributor

Example function with these variables set:

Azure Function with blob trigger-specific environment variables

If your more interested, you can read more about this connection in their official docs.

Wrapping up

Thats it! You have successfully removed the need for storing sensitive connection-strings in your Azure Function setup. You are now one step closer to a credential-free code!

This solution was found by scavenging the internet, and a lot of trying and failing. I decided to publish my findings as i only found bits and pieces here and there myself.

If anything is unclear, or if anyone knows any alternative or better methods of solving this, let me know!

Kanskje du liker:

Kanskje du liker:

Kanskje du liker:

Utvikling

4. august 2025

Denne artikkelen av Adrian Brenne viser steg-for-steg hvordan du bruker både system- og bruker-tilordnet Managed Identity for å sikre tilgang til tjenester som Azure Storage og Key Vault med minimal risiko og maksimal effektivitet.

Utvikling

4. august 2025

Denne artikkelen av Adrian Brenne viser steg-for-steg hvordan du bruker både system- og bruker-tilordnet Managed Identity for å sikre tilgang til tjenester som Azure Storage og Key Vault med minimal risiko og maksimal effektivitet.

kotlinconf2025

Utvikling

5. juni 2025

Dette var personlig min aller første konferanse. For å være helt ærlig visste jeg ikke helt hva jeg kunne forvente. Er det som en bedriftspresentasjon der JetBrains er bedriften? Hvorfor drar man egentlig på konferanse?

kotlinconf2025

Utvikling

5. juni 2025

Dette var personlig min aller første konferanse. For å være helt ærlig visste jeg ikke helt hva jeg kunne forvente. Er det som en bedriftspresentasjon der JetBrains er bedriften? Hvorfor drar man egentlig på konferanse?

Utvikling

4. juni 2025

Vi var en god gjeng Alver som tok turen til årets NDC-konferanse, og som vanlig leverte arrangementet både på faglig innhold og inspirasjon.

Utvikling

4. juni 2025

Vi var en god gjeng Alver som tok turen til årets NDC-konferanse, og som vanlig leverte arrangementet både på faglig innhold og inspirasjon.

Utvikling

4. august 2025

Denne artikkelen av Adrian Brenne viser steg-for-steg hvordan du bruker både system- og bruker-tilordnet Managed Identity for å sikre tilgang til tjenester som Azure Storage og Key Vault med minimal risiko og maksimal effektivitet.

kotlinconf2025

Utvikling

5. juni 2025

Dette var personlig min aller første konferanse. For å være helt ærlig visste jeg ikke helt hva jeg kunne forvente. Er det som en bedriftspresentasjon der JetBrains er bedriften? Hvorfor drar man egentlig på konferanse?

Utvikling

4. august 2025

Denne artikkelen av Adrian Brenne viser steg-for-steg hvordan du bruker både system- og bruker-tilordnet Managed Identity for å sikre tilgang til tjenester som Azure Storage og Key Vault med minimal risiko og maksimal effektivitet.

kotlinconf2025

Utvikling

5. juni 2025

Dette var personlig min aller første konferanse. For å være helt ærlig visste jeg ikke helt hva jeg kunne forvente. Er det som en bedriftspresentasjon der JetBrains er bedriften? Hvorfor drar man egentlig på konferanse?

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2025. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2025. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2025. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2025. All rights reserved.