Handle secrets in Azure functions configuration
T Here is the configuration in Azure app configuration: We’ll use RBAC and managed identity to set up authorization for our function to access the configuration and secret. This involves adding the role of App configuration data reader to Azure app configuration and Key vault secret user to Key vault. This setup works perfectly for a System Assigned Managed Identity. However, for a User Assigned Managed Identity, we need to specify which identity the application should use. This is done by adjusting the function’s And there we have it – our values are now successfully loaded in the application, and we’ve securely moved our secrets to the ideal spot: Azure Key Vault. You’ll notice the Source column pointing to the App configuration reference. A green tick icon is your sign of success, showing that we’ve successfully retrieved the value. Problem
ServiceBusTrigger
. While developing locally, local.settings.json
serves as a proper configuration solution. However, upon deployment to Azure, it becomes necessary to use Azure Functions configuration. This scenario presents a challenge due to configurations being stored in plain text, thereby posing a significant security risk. Anyone with access to the Azure portal can view these secret values. The Azure team acknowledges this issue and there are several open GitHub issues addressing it as of the writing of this article. This has always been a concern for me, and just last week, I discovered a solution I would like to share with you.Preferred architecture
Solution
IConfiguration
using ConfigurationBuilder
. You can do the same in Azure functions, but you are not able to use these values in several triggers. They need to be embedded right at the function level. Luckily there is new feature that will allow us to reference the secret value. It is still in preview at the time of writing this article.ConnectionStringFromAppConfig
first. To achieve it, we will use special syntax used for referencing value from App configuration. @Microsoft.AppConfiguration(Endpoint=https://app-config-functions-secret-demo.azconfig.io; Key=ConnectionStringFromAppConfig)
keyVaultReferenceIdentity
property to the resource ID of the user-assigned identity.userAssignedIdentityResourceId=$(az identity show -g functions-secret-config-demo -n function-identity --query id -o tsv)
az functionapp update --resource-group functions-secret-config-demo --name function-secrets-demo --set keyVaultReferenceIdentity=${userAssignedIdentityResourceId}
Conclusion
{
"deployment_branch": "master",
"SCM_TRACE_LEVEL": "Verbose",
"SCM_COMMAND_IDLE_TIMEOUT": "60",
"SCM_LOGSTREAM_TIMEOUT": "7200",
"SCM_BUILD_ARGS": "",
"FUNCTIONS_RUNTIME_SCALE_MONITORING_ENABLED": "0",
"ScmType": "None",
"AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=functionssecretconf881a;AccountKey=someky;EndpointSuffix=core.windows.net",
"CONNECTION_STRING__KEY_VAULT": "super secret connection string",
"SCM_USE_LIBGIT2SHARP_REPOSITORY": "0",
"CONNECTION_STRING__APP_CONFIG": "my connections string taken from app onfiguration",
"WEBSITE_SLOT_NAME": "Production",
"WEBSITE_AUTH_LOGOUT_PATH": "/.auth/logout",
"WEBSITE_AUTH_AUTO_AAD": "False",
"REMOTEDEBUGGINGVERSION": "16.0.33328.57",
"FUNCTIONS_EXTENSION_VERSION": "~4",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"WEBSITE_SITE_NAME": "function-secrets-demo",
"WEBSITE_AUTH_ENABLED": "False",
"WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED": "1",
"CONNECTION_STRING__PLAINTEXT": "my plaintext connection string"
}