Azure Function with identity-based connections

Azure Function with identity-based connections

Table of Contents

1 Objective
2 Managed identity
3 Azure Table binding

Configure an identity-based connection

Some connections in Azure Functions can be configured to use an identity instead of a secret. Support depends on the extension using the connection. In some cases, a connection string may still be required in Functions even though the service to which you are connecting supports identity-based connections. For a tutorial on configuring your function apps with managed identities, see the creating a function app with identity-based connections tutorial.

Tutorial: Create a function app that connects to Azure services using identities instead of secrets

This tutorial shows you how to configure a function app using Azure Active Directory identities instead of secrets or connection strings, where possible. Using identities helps you avoid accidentally leaking sensitive secrets and can provide better visibility into how data is accessed.

Well, this is really awesome :-)

Please find the my complete code for an identity-based connection at
https://github.com/MarkusMeyer13/azure.functions.tables

1 Objective

Create an Azure Function with identity-based connections to AzureWebJobsStorage and a Table Storage.

image.png

2 Managed identity

Create an Azure Function with a managed identity:

The following script assigns the system-assigned managed identity to the new Azure Function app.

storageAccountFunction='strfunctionmm01'
resourceGroup='eval.table'
functionName='SampleFunctionMM01'

az appservice plan create --resource-group $resourceGroup --name 'samplePlan' 
az functionapp create --name $functionName --resource-group $resourceGroup --storage-account $storageAccountFunction --os-type Linux --functions-version 4 --plan 'samplePlan'

az functionapp identity assign --name $functionName --resource-group $resourceGroup

Created managed identity in Azure Function:

image.png

Retrieve the Ids for managed identity and storage account and assign the Storage Blob Data Contributor role.

functionManagedId=$(az functionapp identity show --name $functionName --resource-group $resourceGroup --query principalId -o tsv)

storageAccountFunctionId=$(az storage account list --resource-group $resourceGroup --query "[?name=='$storageAccountFunction'].id" -o tsv)
az role assignment create --role "Storage Blob Data Contributor" --scope $storageAccountFunctionId --assignee-principal-type ServicePrincipal --assignee-object-id $functionManagedId

The Storage Account with the assigned role:

image.png

The last step is to remove the default AzureWebJobsStorage configuration and set only the storage account name AzureWebJobsStorage__accountName:

az functionapp config appsettings delete --name $functionName --resource-group $resourceGroup --setting-names "AzureWebJobsStorage"
az functionapp config appsettings set --name $functionName --resource-group $resourceGroup --settings AzureWebJobsStorage__accountName=${storageAccountFunction}

No connection strings in the Azure Function configuration:

image.png

Edit the AzureWebJobsStorage configuration

Update the name from AzureWebJobsStorage to the exact name AzureWebJobsStorage__accountName. This setting tells the host to use the identity instead of looking for a stored secret. The new setting uses a double underscore (__), which is a special character in application settings.

3 Azure Table binding

The new Azure WebJobs Tables extension is used for the Azure Function binding:

The Azure Function shall add and delete entities in Table Storage. The Table Storage is part of a different Storage Account than AzureWebJobsStorage. So the Connection has to be specified in the binding:

public static async Task<IActionResult> AddAsync(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = "sample")] HttpRequest req,
    [Table("Sample", Connection = "SampleTableConnection")] TableClient client,
    ILogger log)
{
// ...
}

Grant permission to the identity - Azure Table API extension

Binding typeExample built-in roles (Azure Storage1)
Input bindingStorage Table Data Reader
Output bindingStorage Table Data Contributor

Therefore the managed identity has to be assigned with the Storage Table Data Contributor role for Azure Table Storage.

storageAccount='strsample'
resourceGroup='eval.table'
functionName='SampleFunctionMM01'

functionManagedId=$(az functionapp identity show --name $functionName --resource-group $resourceGroup --query principalId -o tsv)

storageAccountId=$(az storage account list --resource-group $resourceGroup --query "[?name=='$storageAccount'].id" -o tsv)
az role assignment create --role "Storage Table Data Contributor" --scope $storageAccountId --assignee-principal-type ServicePrincipal --assignee-object-id $functionManagedId

The assigned role Storage Table Data Contributor:

image.png

The naming convention for connection:

Using endpoint and token credential

<ConnectionName>__endpoint = https://...table.core.windows.net

tableEndpoint="https://$storageAccount.table.core.windows.net"
az functionapp config appsettings set --name $functionName --resource-group $resourceGroup --settings SampleTableConnection__endpoint=$tableEndpoint

Finally, all Azure Function settings do no longer contain connection strings:

image.png

Please get the complete code here:

git clone https://github.com/MarkusMeyer13/azure.functions.tables.git

Azure services that can use managed identities to access other services

What’s new in the Azure Functions Tables extension for