Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Use Key Vaults to Store Azure Function App Secrets

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: Medium (should be achieved)

Enable working with secrets from the Azure Key Vaults within your Microsoft Azure Function Apps without requiring any code changes. Azure Key Vault is a cloud service that provides centralized secrets management with full control over access policies and audit history.

Security

To maintain the security of the secrets used by your Microsoft Azure Function Apps, it is strongly recommended to store them in an Azure Key Vault and reference them from that key vault. Storing these secrets externally and referencing them in the Function App configuration also enables key rotation without redeployment.


Audit

To determine if the Azure Key Vaults are used to store Azure Function Apps secrets, perform the following operations:

Using Azure Console

01 Sign in to the Microsoft Azure Portal.

02 Navigate to All resources blade available at https://portal.azure.com/#browse/all to access your Azure cloud resources.

03 Choose the Azure subscription that you want to access from the Subscription equalls all filter box and choose Apply.

04 From the Type equalls all filter box, choose Equals, select Function App, and choose Apply to list only the Microsoft Azure Function Apps available in the selected subscription.

05 Click on the name (link) of the Azure Function App that you want to examine.

06 In the resource navigation panel, under Settings, choose Environment variables and select the App settings tab to access the application settings available for the selected Function App.

07 On the App settings panel, perform the following checks:

  1. Check the name of each listed setting to determine if any of the defined settings should be stored as secrets.
  2. Check the Source column for each application setting. If there are no application settings with the Source set to Key vault and displaying a green checkmark icon, the Azure Key Vault service is not used to store secrets for the selected Microsoft Azure Function App. If your Function App has a secret partially configured, where the Key vault is displayed with an x (red x mark icon), the application setting indicates that there is a misconfiguration with the access, therefore, is not compliant.
  3. Choose Show values to display the settings values. Check the Value column for each application setting defined. If there are no settings with the Value set to @Microsoft.KeyVault(SecretUri=https://<key-vault-name>.vault.azure.net/secrets/<secret-name>/) or @Microsoft.KeyVault(VaultName=<key-vault-name>;SecretName=<secret-name>), where <key-vault-name> is the name of your key vault and <secret-name> is the name of the secret used, the Azure Key Vault service is not used to store secrets for the selected Microsoft Azure Function App.

08 To check the Key Vault configuration for compliance, perform the following actions:

  1. On your Function App blade, in the resource navigation panel, under Settings, choose Identity, and select the System assigned tab. If the Status is set to Off, there is no system-assigned managed identity set for your Function App. Because Azure Key Vault access policies rely on assigning a principal to grant access, if there is no system-assigned managed identity set for your Function App, the relevant Key Vault access policy can't have the principal correctly defined.
  2. Navigate to the Key Vaults blade at https://portal.azure.com/#browse/Microsoft.KeyVault%2Fvaults and click on the name of the Azure Key Vault that should host the intended secret. If there are no Key Vault available in your Azure subscription, the Audit process ends here. Otherwise, you can continue the Audit process with the next step.
  3. On your Key Vault blade, under Objects, choose Secrets and click on the name of the secret that should be configured for your Function App. If there is no relevant secret defined, the Audit process ends here. Otherwise, continue the Audit process with the next step.
  4. Back to the Key Vault navigation panel, choose Access policies, and check the Secret Permissions column for each access policy defined. If there are no policies with Secret Permissions set to Get, List and Set, the selected Key Vault is not properly configured to allow your Function App to access the secrets.

09 Repeat steps no. 5 - 8 for each Azure Function App deployed in the selected Azure subscription.

10 Repeat steps no. 3 – 9 for each subscription created in your Microsoft Azure cloud account.

Using Azure CLI

01 Run account list command (Windows/macOS/Linux) with custom output filters to list the IDs of the cloud subscriptions available in your Azure cloud account:

az account list
  --query '[*].id'

02 The command output should return the requested subscription identifiers (IDs):

[
	"abcdabcd-1234-abcd-1234-abcdabcdabcd",
	"abcd1234-abcd-1234-abcd-abcd1234abcd"
]

03 Run account set command (Windows/macOS/Linux) with the ID of the Azure cloud subscription that you want to examine as the identifier parameter to set the selected subscription to be the current active subscription (the command does not produce an output):

az account set
  --subscription abcdabcd-1234-abcd-1234-abcdabcdabcd

04 Run functionapp list command (Windows/macOS/Linux) with custom query filters to list the name and the associated resource group for each Azure Function App available in the selected subscription:

az functionapp list
  --output table
  --query '[*].{name:name, resourceGroup:resourceGroup}'

05 The command output should return the requested Function App names:

Name                      ResourceGroup
----------------------    ------------------------------
cc-main-function-app      cloud-shell-storage-westeurope
cc-project5-function-app  cloud-shell-storage-westeurope

06 Run functionapp config appsettings list command (Windows/macOS/Linux) with the name of the Azure Function App that you want to examine and its associated resource group as the identifier parameters to list the application settings configured for the selected Function App:

az functionapp config appsettings list
  --name cc-main-function-app
  --resource-group cloud-shell-storage-westeurope

07 The command output should return the requested configuration information:

[
	{
		"name": "FUNCTIONS_EXTENSION_VERSION",
		"slotSetting": false,
		"value": "~4"
	},
	{
		"name": "FUNCTIONS_WORKER_RUNTIME",
		"slotSetting": false,
		"value": "dotnet-isolated"
	},
	{
		"name": "WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED",
		"slotSetting": false,
		"value": "1"
	},
	{
		"name": "WEBSITE_CONTENTSHARE",
		"slotSetting": false,
		"value": "cc-main-function-appadba"
	}
]

To identify any application settings that should be stored as secrets, check the "name" attribute value for each application setting. Then, check the "value" attribute to identify the settings values. If there are no application settings with the "value" set to @Microsoft.KeyVault(SecretUri=https://<key-vault-name>.vault.azure.net/secrets/<secret-name>/) or @Microsoft.KeyVault(VaultName=<key-vault-name>;SecretName=<secret-name>), where <key-vault-name> is the name of your key vault and <secret-name> is the name of the secret used, the Azure Key Vault service is not used to store secrets for the selected Microsoft Azure Function App.

08 To check the Key Vault configuration for compliance, perform the following actions:

  1. Run functionapp show command (Windows/macOS/Linux) with the name of the Azure Function App that you want to examine and its associated resource group as the identifier parameters to determine the type of the managed identity (i.e. system-assigned and/or user-assigned) configured for the selected Function App:
    az functionapp show
      --name cc-main-function-app
      --resource-group cloud-shell-storage-westeurope
      --query '{"IdentityType":identity.type}'
    
  2. The functionapp show command should return one of the following outputs:
    1. If the command does not return "SystemAssigned" for the "IdentityType" attribute, there is no system-assigned managed identity set for your Function App. Because Azure Key Vault access policies rely on assigning a principal to grant access, if there is no system-assigned managed identity set for your Function App, the relevant Key Vault access policy can't have the principal correctly defined.
    2. If the command returns "SystemAssigned" for the "IdentityType" attribute, as shown in the example below, you can continue the Audit process with the next step:
      {
      	"IdentityType": "SystemAssigned"
      }
      
  3. Run keyvault list command (Windows/macOS/Linux) with custom query filters to list the name of each Azure Key Vault (and the name of the associated resource group) deployed in the selected Azure subscription:
    az keyvault list
      --output table
      --query '[*].{name:name, resourceGroup:resourceGroup}'
    
  4. The command should return a table with requested information, as shown in the output example below. Otherwise, if the keyvault list command does not produce an output, there are no Azure Key Vaults available in the selected subscription:
    Name                   ResourceGroup
    -------------------    ------------------------------
    cc-project5-key-vault  cloud-shell-storage-westeurope
    cc-main-app-key-vault  cloud-shell-storage-westeurope
    
  5. Run keyvault secret list command (Windows/macOS/Linux) with the name of the Key Vault that you want to examine as the identifier parameter, to list the secrets stored within the selected vault. The command output should return the list of secrets managed by the selected Key Vault. If the command does not produce an output, there are no secrets available within the selected Key Vault, therefore, the Audit process ends here. Otherwise, you can continue the Audit process with the next step:
    az keyvault secret list
      --vault-name cc-main-key-vault
      --query '[*].name'
    
  6. The command should return an array with the requested information:
    [
    	"tm-api-access-key",
    	"tm-app-db-password"
    ]
    
  7. Run keyvault show command (Windows/macOS/Linux) to describe the access policy settings available for the selected Key Vault:
    az keyvault show
      --name cc-main-key-vault
      --query 'properties.accessPolicies'
    
  8. Check the "secrets" attribute value to determine the secret permissions defined for each Key Vault policy. If there are no policies with "secrets" set to "Get", "List" and "Set", the selected Key Vault is not properly configured to allow your Function App to access the secrets:
    [
    	{
    		"applicationId": null,
    		"objectId": "abcd1234-1234-1234-1234-abcd1234abcd",
    		"permissions": {
    			"certificates": [
    				"Get",
    				"List",
    				"Update",
    				"Create",
    				"Import",
    				"Delete",
    				"Recover",
    				"Backup",
    				"Restore",
    				"ManageContacts",
    				"ManageIssuers",
    				"GetIssuers",
    				"ListIssuers",
    				"SetIssuers",
    				"DeleteIssuers"
    			],
    			"keys": [
    				"Get",
    				"List",
    				"Update",
    				"Create",
    				"Import",
    				"Delete",
    				"Recover",
    				"Backup",
    				"Restore"
    			],
    			"secrets": [
    				"Get",
    				"List",
    				"Set",
    				"Delete",
    				"Recover",
    				"Backup",
    				"Restore"
    			],
    			"storage": null
    		},
    		"tenantId": "1234abcd-1234-1234-1234-1234abcd1234"
    	}
    ]
    

09 Repeat steps no. 6 - 8 for each Azure Function App available within the current Azure subscription.

10 Repeat steps no. 3 – 10 for each subscription created within your Microsoft Azure cloud account.

Remediation / Resolution

To use the Azure Key Vault service to store and manage secrets for your Microsoft Azure Function Apps, perform the following operations:

Using Azure Console

01 Sign in to the Microsoft Azure Portal.

02 Navigate to All resources blade available at https://portal.azure.com/#browse/all to access your Azure cloud resources.

03 Choose the Azure subscription that you want to access from the Subscription equalls all filter box and choose Apply.

04 From the Type equalls all filter box, choose Equals, select Function App, and choose Apply to list only the Microsoft Azure Function Apps available in the selected subscription.

05 Click on the name (link) of the Azure Function App that you want to configure.

06 In the resource navigation panel, under Settings, select Identity, choose the System assigned tab and select On under Status to enable the system-assigned managed identity for the selected Function App. Choose Save and select Yes to confirm the changes. Once the feature is enabled, note the Object (principal) ID value.

07 Navigate to the Key Vaults blade available at https://portal.azure.com/#browse/Microsoft.KeyVault%2Fvaults, choose Create, and perform the following actions to create the Key Vault that will store your Azure Function App secret:

  1. For Basics, choose the appropriate subscription and resource group, provide a unique name for the new Key Vault, select the Azure cloud region where the vault will be deployed, and choose the appropriate pricing tier. You can also configure the Purge Protection feature at this step. Choose Next to continue the setup process.
  2. For Access configuration, select Vault access policy for Permission model, and choose Create under Access policies to create the required access policy. For Permissions, select Get, List, and Set for Secret permissions. For Principal, choose the name of your Function App (confirming that the object ID matches the one identified at step no. 6). Once the access policy is configured, choose Create to attach it to your Key Vault. Choose Next to continue the setup.
  3. For Networking, configure the network access control for your Key Vault. Choose the connectivity method that you want to use and ensure that only trusted Azure services and/or networks can access your vault. Choose Next to continue.
  4. For Tags, use the Name and Value fields to create tags that will help organize the identity of the Key Vault. Choose Next : Review + create > to validate the setup.
  5. For Review + create, review the configuration details, then choose Create to create your new Azure Key Vault.

08 To create a new secret for your Microsoft Azure Function App, click on the name (link) of the newly created Key Vault, select Secrets under Objects, choose Generate/Import, and perform the following operations:

  1. For Name, enter a valid secret name.
  2. For Secret value, provide a single-line secret value.
  3. (Optional) For Set activation date and Set expiration date, configure an activation and an expiration date.
  4. Set the Enabled flag to Yes.
  5. Choose Create to generate your new Key Vault secret.

09 Navigate back to the Function App blade and click on the name (link) of the Azure Function App that you want to configure.

10 In the resource navigation panel, under Settings, choose Environment variables, select the App settings tab, and choose Add to add a new application setting to your Function App.

11 Provide a unique name for the setting in the Name box and paste the following Key Vault reference in the Value box: @Microsoft.KeyVault(SecretUri=https://<key-vault-name>.vault.azure.net/secrets/<secret-name>/) or @Microsoft.KeyVault(VaultName=<key-vault-name>;SecretName=<secret-name>), where <key-vault-name> and <secret-name> are the names of the Key Vault resources created earlier in the Remediation section. Choose Apply to save the application setting. Choose Apply and Confirm to apply the changes. The new application setting should display a green checkmark icon in the Source column. Your Function App can now reference the secret through its key. No code changes are required.

12 Repeat steps no. 5 – 11 for each Azure Function App that you want to configure, deployed in the selected Azure subscription.

13 Repeat steps no. 3 – 12 for other subscriptions created in your Microsoft Azure cloud account.

Using Azure CLI

01 Run account list command (Windows/macOS/Linux) with custom output filters to list the IDs of the cloud subscriptions available in your Azure cloud account:

az account list
  --query '[*].id'

02 The command output should return the requested subscription identifiers (IDs):

[
	"abcdabcd-1234-abcd-1234-abcdabcdabcd",
	"abcd1234-abcd-1234-abcd-abcd1234abcd"
]

03 Run account set command (Windows/macOS/Linux) with the ID of the Azure cloud subscription that you want to examine as the identifier parameter to set the selected subscription to be the current active subscription (the command does not produce an output):

az account set
  --subscription abcdabcd-1234-abcd-1234-abcdabcdabcd

04 Run functionapp identity assign command (OSX/Linux/UNIX) with the name of the Azure Function App that you want to configure as the identifier parameter to enable the system-assigned managed identity for the function managed with the specified Function App:

az functionapp identity assign
  --name cc-main-function-app
  --resource-group cloud-shell-storage-westeurope
  --identities [system]

05 Once the assignment process is completed, the command output should return the information available for the managed identity (including the principal ID, i.e. "principalId"):

{
	"principalId": "abcd1234-abcd-1234-abcd-1234abcd1234",
	"tenantId": "1234abcd-abcd-1234-abcd-abcd1234abcd",
	"type": "SystemAssigned",
	"userAssignedIdentities": null
}

06 Run keyvault create command (Windows/macOS/Linux) to create the Azure Key Vault where the Function App secret will be placed:

az keyvault create
  --name cc-main-key-vault
  --resource-group cloud-shell-storage-westeurope
  --location westeurope
  --enabled-for-deployment true
  --enabled-for-template-deployment true
  --query 'id'

07 The command output should return the ID of the new Microsoft Azure Key Vault:

"/subscriptions/abcd1234-abcd-1234-abcd-abcd1234abcd/resourceGroups/cloud-shell-storage-westeurope/providers/Microsoft.KeyVault/vaults/cc-main-key-vault"

08 Run keyvault set-policy command (Windows/macOS/Linux) with the principal ID returned at step no. 5 and the name of the newly created Key Vault as the identifier parameters, to assign the right permissions for the selected Key Vault:

az keyvault set-policy
  --name cc-main-key-vault
  --object-id abcd1234-abcd-1234-abcd-1234abcd1234
  --secret-permissions get list set
  --query 'properties.accessPolicies'

09 The command output should return the new Key Vault access policy:

[
	{
		"applicationId": null,
		"objectId": "2a64e9d1-1234-1234-1234-12349dcf079d",
		"permissions": {
			"certificates": [
				"Get",
				"List",
				"Update",
				"Create",
				"Import",
				"Delete",
				"Recover",
				"Backup",
				"Restore",
				"ManageContacts",
				"ManageIssuers",
				"GetIssuers",
				"ListIssuers",
				"SetIssuers",
				"DeleteIssuers"
			],
			"keys": [
				"Get",
				"List",
				"Update",
				"Create",
				"Import",
				"Delete",
				"Recover",
				"Backup",
				"Restore"
			],
			"secrets": [
				"Get",
				"List",
				"Set",
				"Delete",
				"Recover",
				"Backup",
				"Restore"
			],
			"storage": null
		},
		"tenantId": "6b5a32ca-1234-1234-1234-12341aa347d2"
	},
	{
		"applicationId": null,
		"objectId": "thisismy-new1-web2-app3-4identifier5",
		"permissions": {
			"certificates": null,
			"keys": null,
			"secrets": [
				"set",
				"list",
				"get"
			],
			"storage": null
		},
		"tenantId": "6b5a32ca-1234-1234-1234-12341aa347d2"
	}
]

10 Run keyvault secret set command (Windows/macOS/Linux) to create the Key Vault secret for your Microsoft Azure Function App:

az keyvault secret set
  --name "web-api-key"
  --value "<enter-the-secret-value-here>"
  --vault-name "cc-main-key-vault"
  --disabled false
  --query 'name'

11 The command output should return the name of the new Key Vault secret:

"web-api-key"

12 Run functionapp config appsettings set command (Windows/macOS/Linux) to create a new application setting for your Microsoft Azure Function App. Use the following format when you define the Key Vault reference for the application setting: @Microsoft.KeyVault(SecretUri=https://<key-vault-name>.vault.azure.net/secrets/<secret-name>/) or @Microsoft.KeyVault(VaultName=<key-vault-name>;SecretName=<secret-name>), where <key-vault-name> and <secret-name> are the names of the Key Vault resources created earlier in the Remediation section:

az functionapp config appsettings set
  --name cc-main-function-app
  --resource-group cloud-shell-storage-westeurope
  --settings API_KEY="@Microsoft.KeyVault(SecretUri=https://<key-vault-name>.vault.azure.net/secrets/<secret-name>/)"

13 The command output should return the application settings configured for the selected Function App:

[
	{
		"name": "API_KEY",
		"slotSetting": false,
		"value": "@Microsoft.KeyVault(SecretUri=https://<key-vault-name>.vault.azure.net/secrets/<secret-name>/)"
	},
	{
		"name": "FUNCTIONS_EXTENSION_VERSION",
		"slotSetting": false,
		"value": "~4"
	},
	{
		"name": "FUNCTIONS_WORKER_RUNTIME",
		"slotSetting": false,
		"value": "dotnet-isolated"
	},
	{
		"name": "WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED",
		"slotSetting": false,
		"value": "1"
	},
	{
		"name": "WEBSITE_CONTENTSHARE",
		"slotSetting": false,
		"value": "cc-main-function-appadba"
	}
]

14 Repeat steps no. 10 – 14 for each Azure Function App that you want to configure, deployed in the selected Azure subscription.

15 Repeat steps no. 3 – 13 for other subscriptions created in your Microsoft Azure cloud account.

References

Publication date Oct 23, 2023