CLI

Manage Azure Function Keys using PowerShell

The Azure Functions Runtime exposes a management API that enables users to programmatically add, delete, or update function keys. In this article, I will show you how to use this API to manage Azure Functions Keys using PowerShell.

Authorization keys

With Azure Functions, you can use keys to prevent anonymous users to access your HTTP endpoints. The Requests then must include an API key (either a function or host key) which can be included in two ways:

Providing the key

Using an URL query string named code

https://<FUNCTION_APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?code=<API_KEY>

Using an HTTP header named x-functions-key

Invoke-WebRequest ` 
	-Uri 'https://<FUNCTION_APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>' ` 
	-Headers @{'x-functions-key' = '<API_KEY>'}

Authorization scopes

Keys can be specified on three levels:

Function Keys

The keys defined on a function-level allow access only to a single function.

Host Keys

A Host Key allows access to all functions within a function app.

The Master key (named _master) not only allows host-level access to all functions within a function app but also provides access to the Azure Function Runtime REST APIs.
Note: This Key cannot be revoked thus you should avoid sharing this key.

You can find more information about Authorization Keys here.

Key management API

The Key management API allows us to programmatically add, delete, or update our Azure Functions keys. In order to use this API, we need to get an access token beforehand. We can obtain the token using the following PowerShell script.

Obtain an access token using PowerShell

param (
    [Parameter(Mandatory = $true)]
    [string]
    $ResourceGroupName,

    [Parameter(Mandatory = $true)]
    [string]
    $FunctionAppName
)

$publishingCredentials = Invoke-AzResourceAction  `
    -ResourceGroupName $ResourceGroupName `
    -ResourceType 'Microsoft.Web/sites/config' `
    -ResourceName ('{0}/publishingcredentials' -f $FunctionAppName) `
    -Action list `
    -ApiVersion 2019-08-01 `
    -Force

$base64Credentials = [Convert]::ToBase64String(
    [Text.Encoding]::ASCII.GetBytes(
        ('{0}:{1}' -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword)
    )
)

Invoke-RestMethod `
    -Uri ('https://{0}.scm.azurewebsites.net/api/functions/admin/token' -f $FunctionAppName) `
    -Headers @{ Authorization = ('Basic {0}' -f $base64Credentials) }

This script is also available on GitHub.

Before we can invoke this function, we have to log in to Azure using the Login-AzAccount cmdlet. Then all we have to do is to pass the name of the resource group and the name of the Azure Function App:

Login-AzAccount
$jwtToken = ./Get-AzureFunctionsAccessToken.ps1 `
    -ResourceGroupName '<RESOURCE_GROUP_NAME>' `
    -FunctionAppName '<FUNCTION_APP_NAME>'

Now we can use the return value (access token) to perform requests against the Key management API. Here a few examples:

Key Management API examples

Create a new host key with an auto-generated value (POST)

This is how the host key POST interface looks like:

POST https://<FUNCTION_APP_NAME>.azurewebsites.net/admin/functions/host/keys/<KEY_NAME>

Now let’s add a new host key named mynewkey to my Azure Function mbr-pwsh-test using PowerShell and the token ($jwtToken) that we retrieved previously:

Invoke-RestMethod `
    -Uri 'https://mbr-pwsh-test.azurewebsites.net/admin/host/keys/mynewkey' `
    -Headers @{Authorization = ("Bearer {0}" -f $jwtToken) } `
    -Method Post

This is how it looks like in the Portal:

new-host-key

Update a host key with a predefined value (PUT)

This is how the host key PUT interface looks like:

PUT https://<FUNCTION_APP_NAME>.azurewebsites.net/admin/functions/host/keys/<KEY_NAME>
{
    "name": "keyname",
    "value" : "keyvalue"
}

Now let’s update our previous created key with a new value. You can use the same endpoint to create a new key with a predefined value (instead of the auto-generated value that is used by the POST endpoint)

$keyName = 'mynewkey'
$keyValue = 'my-secret-value'

Invoke-RestMethod `
    -Uri "https://mbr-pwsh-test.azurewebsites.net/admin/host/keys/$keyName"`
    -Headers @{Authorization = ("Bearer {0}" -f $jwtToken) } `
    -Body ( @{ 'name' = $keyName; 'value' = $keyValue } | ConvertTo-Json) `
    -ContentType 'application/json' `
    -Method PUT

We can see the updated key inside the Azure Portal:

updated host key

Retrieve all host keys (GET)

The request to retrieve all host keys look like this:

GET https://<FUNCTION_APP_NAME>.azurewebsites.net/admin/functions/host/keys

Let’s retrieve them using PowerShell.
Note: I piped the result to the Select-Object cmdlet to get a cleaner output on the console.

Invoke-RestMethod `
    -Uri 'https://mbr-pwsh-test.azurewebsites.net/admin/host/keys/mynewkey' `
    -Headers @{Authorization = ("Bearer {0}" -f $jwtToken) } `
    -Method GET | Select-Object -ExpandProperty keys

And here is the output:

retrieve host keys example

Retrieve a specific host key (GET)

To retrieve a specific host key, we just have to add the name of the key to the URL:

GET https://<FUNCTION_APP_NAME>.azurewebsites.net/admin/functions/host/keys/<KEY_NAME>

Again, let’s do this using PowerShell:

Invoke-RestMethod `
    -Uri 'https://mbr-pwsh-test.azurewebsites.net/admin/host/keys/mynewkey' `
    -Headers @{Authorization = ("Bearer {0}" -f $jwtToken) } `
    -Method GET

Here is our key:

Remove a host key (DELETE)

The host key DELETE endpoint uses the same URL like the POST endpoint:

DELETE https://<FUNCTION_APP_NAME>.azurewebsites.net/admin/functions/host/keys/<KEY_NAME>

We can delete our mynewkey host key using the following PowerShell script:

Invoke-RestMethod `
    -Uri 'https://mbr-pwsh-test.azurewebsites.net/admin/host/keys/mynewkey' `
    -Headers @{Authorization = ("Bearer {0}" -f $jwtToken) } `
    -Method DELETE

Convenience script to set multiple host keys

In addition to the examples, I want to share a script with you where you can set multiple host keys with either a predefined or auto-generated value:

param (
    [Parameter(Mandatory = $true)]
    [string]
    $ResourceGroupName,

    [Parameter(Mandatory = $true)]
    [string]
    $FunctionAppName,

    [Parameter(Mandatory = $true)]
    [hashtable]
    $FunctionKeys
)

$functionBaseUrl = 'https://{0}.azurewebsites.net' -f $FunctionAppName

$publishingCredentials = Invoke-AzResourceAction  `
    -ResourceGroupName $ResourceGroupName `
    -ResourceType 'Microsoft.Web/sites/config' `
    -ResourceName ('{0}/publishingcredentials' -f $FunctionAppName) `
    -Action list `
    -ApiVersion 2019-08-01 `
    -Force

$base64Credentials = [Convert]::ToBase64String(
    [Text.Encoding]::ASCII.GetBytes(
        ('{0}:{1}' -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword)
    )
)

$jwtToken = Invoke-RestMethod `
    -Uri ('https://{0}.scm.azurewebsites.net/api/functions/admin/token' -f $FunctionAppName) `
    -Headers @{ Authorization = ('Basic {0}' -f $base64Credentials) }

$FunctionKeys.Keys | ForEach-Object {
    if ($FunctionKeys[$_]) {
        Invoke-RestMethod `
            -Uri ('{0}/admin/host/keys/{1}' -f $functionBaseUrl, $_) `
            -Headers @{Authorization = ("Bearer {0}" -f $jwtToken) } `
            -Method Put `
            -Body ( @{ 'name' = $_; 'value' = $FunctionKeys[$_] } | ConvertTo-Json) `
            -ContentType 'application/json'
    }
    else {
        Invoke-RestMethod `
            -Uri ('{0}/admin/host/keys/{1}' -f $functionBaseUrl, $_) `
            -Headers @{Authorization = ("Bearer {0}" -f $jwtToken) } `
            -Method Post
    }
}

In here the example of how to call the script to create two keys:

Login-AzAccount

./Add-AzureFunctionHostKey.ps1 `
    -ResourceGroupName "apim-rg" `
    -FunctionAppName "mbr-pwsh-test" `
    -FunctionKeys @{ 
        myKey1 = 'myValue1' # predefined key
        mykey2 = $null # key with auto-generated value
    }

The script is also available on GitHub.

Manage keys on function-level

Now we know how to manage (add, update, get, delete) an Azure Function Host Key using the Key management API. Of course, we can also manage a Function Key by changing the URL from admin/functions/host to admin/function/<FUNCTION_NAME>. You can find more information about the API here.