9.11 Ensure Azure Keyvaults are used to store secrets

Warning! Audit Deprecated

This audit has been deprecated and will be removed in a future update.

View Next Audit Version

Information

Encryption keys ,Certificate thumbprints and Managed Identity Credentials can be coded into the APP service, this renders them visible as part of the configuration, to maintain security of these keys it is better to store in an Azure Keyvault and reference them from the Keyvault.

Rationale:

App secrets control access to the application and thus need to be secured externally to the app configuration, storing the secrets externally and referencing them in the configuration also enables key rotation without having to redeploy the app service.

Impact:

Impact is primarily during the initial setup of the application or redeploying an old app to include this functionality. This will require configuration effort to setup the keyvault and then to configure the app service to use the keyvault.

Solution

Remediation has 2 steps

Setup the keyvault

setup the app service to use the keyvault

Set up the keyvault
Using Azure CLI
'az keyvault create --name 'myKV' --resource-group 'myResourceGroup' --location myLocation
Using Azure Powershell
'New-AzKeyvault -name MyKV -ResourceGroupName myResourceGroup -Location myLocation
Set up the App Service to use the keyvault
Sample JSON Template for App Service Configuration

{
//...
'resources': [
{
'type': 'Microsoft.Storage/storageAccounts',
'name': '[variables('storageAccountName')]',
//...
},
{
'type': 'Microsoft.Insights/components',
'name': '[variables('appInsightsName')]',
//...
},
{
'type': 'Microsoft.Web/sites',
'name': '[variables('functionAppName')]',
'identity': {
'type': 'SystemAssigned'
},
//...
'resources': [
{
'type': 'config',
'name': 'appsettings',
//...
'dependsOn': [
'[resourceId('Microsoft.Web/sites', variables('functionAppName'))]',
'[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]',
'[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('storageConnectionStringName'))]',
'[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('appInsightsKeyName'))]'
],
'properties': {
'AzureWebJobsStorage': '[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringResourceId')).secretUriWithVersion, ')')]',
'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING': '[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringResourceId')).secretUriWithVersion, ')')]',
'APPINSIGHTS_INSTRUMENTATIONKEY': '[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyResourceId')).secretUriWithVersion, ')')]',
'WEBSITE_ENABLE_SYNC_UPDATE_SITE': 'true'
//...
}
},
{
'type': 'sourcecontrols',
'name': 'web',
//...
'dependsOn': [
'[resourceId('Microsoft.Web/sites', variables('functionAppName'))]',
'[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]'
],
}
]
},
{
'type': 'Microsoft.KeyVault/vaults',
'name': '[variables('keyVaultName')]',
//...
'dependsOn': [
'[resourceId('Microsoft.Web/sites', variables('functionAppName'))]'
],
'properties': {
//...
'accessPolicies': [
{
'tenantId': '[reference(concat('Microsoft.Web/sites/', variables('functionAppName'), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').tenantId]',
'objectId': '[reference(concat('Microsoft.Web/sites/', variables('functionAppName'), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]',
'permissions': {
'secrets': [ 'get' ]
}
}
]
},
'resources': [
{
'type': 'secrets',
'name': '[variables('storageConnectionStringName')]',
//...
'dependsOn': [
'[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]',
'[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]'
],
'properties': {
'value': '[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),'2015-05-01-preview').key1)]'
}
},
{
'type': 'secrets',
'name': '[variables('appInsightsKeyName')]',
//...
'dependsOn': [
'[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]',
'[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]'
],
'properties': {
'value': '[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2015-05-01').InstrumentationKey]'
}
}
]
}
]
}

See Also

https://workbench.cisecurity.org/files/3459