Function Apps can bring a lot of functionality into your architecture yet most of the times Function Apps don’t work alone. They access other resources in Azure to read or write data, or push the workload to other compute solutions. But to do so – function apps would need some kind of credentials – for example to a SQL server. And where should those credentials be stored? And after you decide what resource to use to store those credentials – what credentials are used to access the resource where those credentials are stored? Its a vicious circle. You need credentials to access credentials.For this situation Azure has Managed Identities. This is a special kind of service principal assigned to an Azure compute resource for which you do not need any additional authentication information. If you use Azure AD authentication in a request originating from a resource with managed identity – Azure recognizes the managed identity almost seamlessly, without you possessing any passwords, secrets or certificates. You can assign permissions to the managed identity via RBAC. It allows you to add a fully-fledged identity layer without saving credentials. This is why Defender for cloud provides a recommendation “Managed Identity should be used in Function Apps”. In this article you will learn how to remediate it in example where a Function App retrieves data from a keyvault.
Enabling Managed Identity to be used in Function Apps
To enable managed identity in your Function app find your app in the Azure portal and proceed to “Identity”.
Set the status of Managed Identity to “On”.
Confirm your choice. You will be acknowledged that from now on you can use RBAC for role assignments to the managed identity.
Using managed identity to access a key vault
The recommendation is there for a reason. If you set it up, you should use it. Managed Identity should be used in function apps to access various kinds of resources like SQL servers, Key vaults, storage accounts etc.
As much as Managed Identity is perfect for accessing a long list of resources, a best example is accessing a key vault. As having credentials allow you to access all kinds of resources – inside or outside Azure ecosystem. But you need to store those credentials somewhere. Using managed identity+keyvault actually solves the problem of where the initial credentials originate.
Let’s create a secret in a keyvault and see that with Managed Identity your code does not require any kind of connection string or password to retrieve it.
Find your keyvault in the Azure Portal and generate secret.
Create a secret. Set a name and a value. Click “Create”
Go to Access Policies and click “Add Access Policy”
In “Select Principal” click “None Selected” to open a window with available principals.
Start typing the name of your managed identity and pick it up from the list.
Select “Get” for “secret permissions” and click “Add”.
Now Managed Identity for your Function App is set up, a secret in a Key Vault is created, and access policies allowing the Managed Identity to access that secret are in place. The last thing is to actually reach the keyvault from the code of your function app.
Accessing Keyvault from Function Apps in Python with Managed Identity
Below is a very simplified example of accessing the keyvault secret from a Python Function App. Your application might be developed in a different language but the core concepts should stay the same. A credential object required for accessing a given endpoint is retrieved by “DefaultAzureCredential” function. With no additional credentials – the authentication of Managed Identity is abstracted to you.
from azure.keyvault.secrets import SecretClient from azure.identity import DefaultAzureCredential import requests, random, string, os import azure.functions as func def main(req: func.HttpRequest) -> func.HttpResponse: # Azure Authentication. With Managed Identity you do not need to provide anything more to get the credential object. credential = DefaultAzureCredential() # Setting up the client for requests to the key vault. Replace the key vault URL with the URL of your key vault key_vault_url = "https://samkeyvault1234.vault.azure.net" keyvault_client = SecretClient(vault_url=key_vault_url, credential=credential) # Provide the secret name secret_name = "sampleSecretName" #retrieve secret retrieved_secret = keyvault_client.get_secret(secret_name) retrieved_secret_value = retrieved_secret.value if retrieved_secret_value: return func.HttpResponse(f"Retrieved secret: {retrieved_secret_value}.") else: return func.HttpResponse( "Not retrieved.", status_code=200 )
This article is part of the series detailing resolution of security recommendations. Check fixes to other recommendations of Microsoft Defender for cloud.