Basic Function Security
Introduction
The aim of this chapter is to give you an understanding of the most fundamental security mechanisms of Azure Functions, or more specific, on how to use Function Access Keys.
Azure Function security in general is a much broader topic, which we can't possibly explain in its entirety in this training. That said, I strongly encourage you to read the whole documentation of Azure Functions security concepts after completing this chapter.
Commands in this chapter are to be executed in the Function App root directory unless stated otherwise.
Function Access Keys
As the name implies, Function Access Keys can be used to secure your functions in a manner where your requests must include an API access key in the request. Unless the HTTP access level on an HTTP triggered function is set to anonymous, that is.
They're good enough for trainings, demos, or development purposes but shouldn't be used in production.
Nevertheless they are the default security mechanisms Azure Functions provide and that's why we're learning about them.
In fact, we already used Function Access keys back in Chapter 2.5, were we created a function with authorization level function
, and they're also the reason why we created most of our functions with authorization level anonymous
.
So, as you might have already guessed, authorization levels are coupled to access keys.
Possible authorization levels are:
anonymous
: functions can be called without providing an API access key.function
: functions can be called providing an API access key of scope Function or Host.admin
: functions can be called providing an API access key of scope Admin.
Possible key scopes are:
- Function: These keys apply only to the specific functions under which they're defined.
- Host: These keys apply to all functions within the Function App (host-level).
- Admin: Each Function App also has an admin-level host key. In addition to providing host-level access to all functions in the app, the master key also provides administrative access to the runtime REST APIs.
- System: These keys are required by certain function extensions and the scope of system keys is determined by the extension, but it generally applies to the entire function app (host-level).
As a developer you'll most likely use authorization level function
with either key scope Function
or Host
.
List Function App keys
Let's take a look at the keys our Function App provides:
az functionapp keys list --resource-group rg-functions-demo --name <APP_NAME>
{
"functionKeys": {
"default": "<some-default-key>"
},
"masterKey": "<some-master-key>",
"systemKeys": {}
}
As you can see, there's only one function key and the master key so far.
Calling functions using keys
Let's call our settings
function with using anonymous and the different keys.
Anonymous:
curl 'https://<APP_NAME>.azurewebsites.net/api/settings' -v
Using a key:
curl 'https://<APP_NAME>.azurewebsites.net/api/settings?code=<KEY>'
Using a anonymous call, the function response is 401 Unauthorized
, whereas it works as expected if we provide the key.
🛠TASK (optional): Verify the admin key access
Update the function.json of your settings
function, and set the authorization level to admin
instead of function
.
Redeploy the Function App and try using the function
key and the admin
key for the call.
What're the results?
🎓 SOLUTION
Update the authLevel in the function.json (snippet):
{
"bindings": [
{
"authLevel": "Admin",
"type": "httpTrigger",
"direction": "in",
...
}
...
]
}
Redeploy with:
func azure functionapp publish <APP_NAME>
Summary: The function key, doesn't work anymore, whereas the admin key works as expected.
Function-specific keys
So far, we've used a host key or the admin key, where both can access all APIs of our Function App. But, as we've learned above, we can also create keys for specific functions.
Let's create one for our greetings
function:
az functionapp function keys set --resource-group rg-functions-demo --function-name greetings --key-name GreetingsKey --name <APP_NAME>
Sample output
Output (snippet):
{
...
"name": "GreetingsKey",
"resourceGroup": "rg-functions-demo",
"type": "Microsoft.Web/sites/functions/keys",
"value": "<your-new-key>"
}
If we list our keys again, we won't find the key we just created, because it's function-specific.
We need to use the function specific command to list the keys for a function.
az functionapp function keys list --resource-group rg-functions-demo --function-name greetings --name <APP_NAME>
Note: We use
az functionapp keys list ...
for the Function App, butaz functionapp function keys list ...
for a specific function. The keys using the first command have the Host scope, the keys using the second command have the Function scope.
🛠TASK (optional): Verify the function scope access
This task contains of three easy questions.
- Using the function key, we just created, can you access the
greetings
function with it? - Using the function key, we just created, can you access the
settings
function with it? - Can you still access the
greetings
function with the function key if you set its authorization level toadmin
?
🎓 SOLUTION
Question 1: Calling the greetings function with the key it works as expected and results in a 200 OK. The function should be anonymous right now, so it doesn't care about the key at all.
Question 2: As one would expect it results in 401 Unauthorized. Again nothing unexpected because the key is not valid for the settings function.
Question 3: This results in 401 Unauthorized because a function with authorization level admin can only be called using the master key.