I'm currently writing a .NET 7 isolated Azure Function. I want to configure the function and its callers to use Azure Key Vault.
I've got the key vault working, everything is connected and the keys are accessible from the application.
What I don't understand is how to secure the endpoint. I've set AuthorizationLevel.Function
as per the docs:
public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
Console.WriteLine(Environment.GetEnvironmentVariable("FunctionApiKey"));
Console.WriteLine((getSecretAsync().GetAwaiter().GetResult()).Value);
_logger.LogInformation("C# HTTP trigger function processed a request.");
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
response.WriteString("Welcome to Azure Functions!");
return response;
}
Now, when I call my app on my dev environment, I can just trigger it with a simple URL in postman, without even providing a key. So I don't know that the authorization is working as intended, or if the Azure Function framework provides some mechanism to not require it in the dev environment.
Further, I don't understand how to point the authorization API key at the keyvault secret. I've set the following in appsettings.local
:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsSecretStorageType": "keyvault",
"AzureWebJobsSecretStorageKeyVaultUri": "https://<vaultURI>.vault.azure.net/",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
That was set as per the documentation here. But they don't describe how to point the app at a specific secret for authorization.
EDIT:
Looks like the answer to this was partially right in front of me: AzureWebJobsSecretStorageKeyVaultClientSecret <CLIENT_SECRET>
However I still don't understand why the endpoint is running without authorization in my dev environment.
You've got two separate things here.
The AuthorizationLevel
is for consumers to use the endpoint. When you deploy the functions app to Azure, it creates a few initial function API keys at different scopes and through the Azure portal or Azure CLI is where you can manage these keys on the functions app instance.
When you run this locally, I don't believe the functions host emulator enforces the AuthorizationLevel or possibly uses a well-known developer API key, much like the UseDeveloperStorage=true
setting to access the storage account emulator. I don't believe this is configurable, I haven't needed to try.
Consumers do not interact directly with the storage account the functions host runs on, nor should the consumers use the key vault that the functions app gets its secrets from, like database connection strings.
Your deployed functions app can use Key Vault References.
In your locally emulated host, the key vault references above is exposed as the two AzureWebJobsSecretStorageKeyVaultClient*
settings provided in the local appsettings file (still do not check it into source control!).
Aaaand just in case you run into authentication issues..
The way this authenticates to the key vault and retrieves the secret is the DefaultAzureCredential()
mechanism. So if you're running this from Visual Studio, it will likely fall to your VisualStudioCredential
. If you run it from the command prompt with dotnet
you may get an interactive sign-in through the browser.
By default, the function app keys like '_master' and 'default' are stored in a blob container. You can change this by taking the steps you mentioned where the function app now stores those keys in the key vault.
Once wired up correctly, and the function app is given access to the KV either by System Assigned Managed Identity (recommended), User assigned managed identity, or access policy you should see the function app keys populate into the KV.
_master
and default
app keys still show in the app keys blade of the functions app, but if you look at the KV secrets you will see respective secrets host--masterKey--master
and host--functionKey--default
You will still manage and create new function app keys through the app keys blade of the functions app.
The app key values are what is provided to the consumer to be authorized to call a function, or a specific function. This mechanism does not change.
For example, you have your HTTP trigger with AuthorizationLevel.Function, that means the caller will have to pass the function app key for the specific function they are calling.
Now that the key is IN the key vault, the consumer may authenticate to the key vault, retrieve the secret value from /secrets/myhttptrigger--functionKey--default
, then pass that value to the function app endpoint to authorize.