22 Mar 2020

Infrastructure Notes - Azure Key Vault

Using Gary Grudzinskas ‘Securing Virtual Machines with Azure Key Vault’ training course on Pluralsight

Azure Key Vault helps solve the following problems:

  • Secrets Management - Azure Key Vault can be used to Securely store and tightly control access to tokens, passwords, certificates, API keys, and other secrets
  • Key Management - Azure Key Vault can also be used as a Key Management solution.
  • Certificate Management - Azure Key Vault is also a service that lets you easily provision, manage, and deploy public and private Transport Layer Security/Secure Sockets Layer (TLS/SSL) certificates for use with Azure and your internal connected resources.
  • Store secrets backed by Hardware Security Modules - The secrets and keys can be protected either by software or FIPS 140-2 Level 2 validated HSMs

Key Vault PowerShell reference: https://docs.microsoft.com/en-us/powershell/module/azurerm.keyvault/?view=azurermps-6.13.0#key_vault

Requirements for Key Vault:

  • Azure AD
  • PowerShell for Azure
  • Connectivity from VM to Key Vault, VM to Azure AD, VM to Storage account.

Components:

  • Azure App
  • Key Vault
  • VM

You can have multiple key vaults in your account, fit for purpose. You can create them in the UI if needed. Even if you use encryption on your storage account, bitlocker with key vault gives you that assurance that the VM cannot leave Azure. The key is in vault.

In the context of secrets: Azure Key Vault is a secret store: a centralized cloud service for storing application secrets - configuration values like passwords and connection strings that must remain secure at all times. Key Vault helps you control your applications’ secrets by keeping them in a single central location and providing secure access, permissions control, and access logging.

IAM

There are a stack of built in roles, and the ability to customize them or create new ones - but there is also a wizard to show exactly what things a particular principal can do based on their role assignments.

Access to a key vault is controlled through two interfaces: the management plane and the data plane. The management plane is where you manage Key Vault itself. Operations in this plane include creating and deleting key vaults, retrieving Key Vault properties, and updating access policies. The data plane is where you work with the data stored in a key vault. You can add, delete, and modify keys, secrets, and certificates.

To access a key vault in either plane, all callers (users or applications) must have proper authentication and authorization. Authentication establishes the identity of the caller. Authorization determines which operations the caller can execute.

Both planes use Azure Active Directory (Azure AD) for authentication. For authorization, the management plane uses role-based access control (RBAC) and the data plane uses a Key Vault access policy.

IAM reference

Logging

Key vault builds activity logs. Very granular logging with search built in to the console. You can access your logging information 10 minutes (at most) after the key vault operation. In most cases, it will be quicker than this. You can access your logging information 10 minutes (at most) after the key vault operation. In most cases, it will be quicker than this.

Logging reference

Creating a Key Vault

The actual command (you need to do other things first):

PS C:\Users\ChadDuffey> New-AzureRmKeyVault -VaultName $kvName -ResourceGroupName $rgName -Location $location


Vault Name                       : duffKV
Resource Group Name              : duffRG
Location                         : West US
Resource ID                      : /subscriptions/a/resourceGroups/duffRG/providers/Microsoft.KeyVault/vaults/duffKV
Vault URI                        : https://duffkv.vault.azure.net/
Tenant ID                        : 
SKU                              : Standard
Enabled For Deployment?          : False
Enabled For Template Deployment? : False
Enabled For Disk Encryption?     : False
Soft Delete Enabled?             : 
Access Policies                  : 
                                   Tenant ID                                  : 
                                   Object ID                                  : 
                                   Application ID                             : 
                                   Display Name                               : Chad Duffey (chad@chadduffey.com)
                                   Permissions to Keys                        : get, create, delete, list, update, import, backup, restore, recover
                                   Permissions to Secrets                     : get, list, set, delete, backup, restore, recover
                                   Permissions to Certificates                : get, delete, list, create, import, update, deleteissuers, getissuers, listissuers, managecontacts, 
                                   manageissuers, setissuers, recover, backup, restore
                                   Permissions to (Key Vault Managed) Storage : delete, deletesas, get, getsas, list, listsas, regeneratekey, set, setsas, update, recover, backup, 
                                   restore
                                   
                                   
Network Rule Set                 : 
                                   Default Action                             : Allow
                                   Bypass                                     : AzureServices
                                   IP Rules                                   : 
                                   Virtual Network Rules                      : 
                                   
Tags                             : 




PS C:\Users\ChadDuffey> 

A better script to create a Key Vault and Azure App:

$kvName = 'duffKV'
$rgName = 'duffRG'
$location = 'West US'
$aadClientSecret = 'duffClientSecret123'
$appDisplayName = 'duffEncryptApp'

#Connect-AzureRmAccount -Subscription XXXXXXX

New-AzureRmResourceGroup -Name $rgName -Location $location
New-AzureRmKeyVault -VaultName $kvName -ResourceGroupName $rgName -Location $location

Set-AzureRmKeyVaultAccessPolicy -VaultName $kvName -ResourceGroupName $rgName -EnabledForDiskEncryption

$secureaadClientSecret = ConvertTo-SecureString $aadClientSecret -AsPlainText -Force

$aadApp = New-AzureRmADApplication -DisplayName $appDisplayName -HomePage 'http://homepageduffEncryptApp' -IdentifierUris 'http://uriduffEncryptApp' -Password $secureaadClientSecret

$appID = $aadApp.ApplicationId

$aadServicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $appID

Set-AzureRmKeyVaultAccessPolicy -VaultName $kvName -ServicePrincipalName $appID `
    -PermissionsToKeys decrypt,encrypt,unwrapKey,wrapKey,verify,sign,get,list,update,create,import,delete,backup,restore,recover,purge `
    -PermissionsToSecrets get, list, set, delete, backup, restore, recover, purge

Bitlocker integration

Generation 2 VMs do not yet support some Azure platform features, including Azure Disk Encryption.

When we first build a VM: unencrypted

unencrypted2

To encrypt, we add the following to our script:

$vmName = 'plazVM'

$kv = Get-AzureRmKeyVault -VaultName $kvName -ResourceGroupName $rgName
$kvUri = $kv.VaultUri
$kvRID = $kv.ResourceId

Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $rgName -VMName $vmName -AadClientID $appID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $kvUri -DiskEncryptionKeyVaultId $kvRID

PowerShell will let you know that you have a 10-15 minute wait coming up.

We could also do the data disks:

$kv = Get-AzureRmKeyVault -VaultName $kvName -ResourceGroupName $rgName
$kvUri = $kv.VaultUri
$kvRID = $kv.ResourceId

$aadApp = Get-AzureRmADApplication -DisplayName $appDisplayName
$appID = $aadApp.ApplicationId


Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $rgName -VMName $vmName -AadClientID $appID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $kvUri -DiskEncryptionKeyVaultId $kvRID -VolumeType Data

Get-AzureRmVMDiskEncryptionStatus -VMName $vmName -ResourceGroupName $rgName

Here’s a gotcha! Not all VM types support encryption:

Set-AzureRmVMDiskEncryptionExtension : VM size is Basic_A1. Disk encryption is not supported for Basic Family VM sizes currently.
ErrorCode: NotSupported
ErrorMessage: VM size is Basic_A1. Disk encryption is not supported for Basic Family VM sizes currently.
ErrorTarget: 
StatusCode: 409
ReasonPhrase: Conflict
OperationID : 75a81ea3-a426-4c16-981c-ded861fb876b

And a second one, VM and Key Vault need to be in the same region:

Set-AzureRmVMDiskEncryptionExtension : Long running operation failed with status 'Failed'. Additional Info:'The Key Vault 
https://duffkv.vault.azure.net/secrets/FCC65FF0-B580-42F5-828A-3B100D905FDE/40f226f47b2a40ff832cb7bc030ec653 is located in location West US, which is different from the location of the 
VM, westus2. The VM and Key Vault need to be located within the same region.'
ErrorCode: KeyVaultAndVMInDifferentRegions
ErrorMessage: The Key Vault https://duffkv.vault.azure.net/secrets/FCC65FF0-B580-42F5-828A-3B100D905FDE/40f226f47b2a40ff832cb7bc030ec653 is located in location West US, which is 
different from the location of the VM, westus2. The VM and Key Vault need to be located within the same region.

Here’s what it looks like when it goes well:

PS C:\Users\ChadDuffey> Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $rgName -VMName $vmName -AadClientID $appID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $kvUri -DiskEncryptionKeyVaultId $kvRID

RequestId IsSuccessStatusCode StatusCode ReasonPhrase
--------- ------------------- ---------- ------------
                         True         OK OK       

Quickstart Templates

Quickstart templates: https://github.com/Azure/azure-quickstart-templates Specifically: https://github.com/Azure/azure-quickstart-templates/tree/master/201-encrypt-create-new-vm-gallery-image Check out the “Deploy to Azure” button. Hot. deploytoazure

Deploying Certificates via Key Vault

(Gary Grudzinskas script for:) Deploying Certificates into Key Vault for distribution:

$secretName = "CertVM"
$certPassword = "CertPW"
$fileName = "CertVM.pfx"

$fileContentBytes = Get-Content $fileName -Encoding Byte
$fileContentEncoded = [System.Convert]::ToBase64String($fileContentBytes)

$jsonObject = @"
{
  "data": "$fileContentEncoded",
  "dataType" :"pfx",
  "password": "$certPassword"
}
"@

$jsonObjectBytes = [System.Text.Encoding]::UTF8.GetBytes($jsonObject)
$jsonEncoded = [System.Convert]::ToBase64String($jsonObjectBytes)

$secret = ConvertTo-SecureString -String $jsonEncoded -AsPlainText –Force
Set-AzureKeyVaultSecret -VaultName $kvName -Name $secretName -SecretValue $secret

Then: https://github.com/Azure/azure-quickstart-templates/tree/master/201-vm-push-certificate-windows. This will run you through the configuration that will allow a certificate to be pushed right into the personal store inside the image. That is, we can deploy certificates using Azure.

Custom Secrets with Key vault

Say i had to store the setup password for a machine:

az keyvault secret set --name WVD-Machine001 --value 5645342anbt12 --vault-name duffKV

or with PowerShell module:

$Secret = ConvertTo-SecureString -String 'Password123' -AsPlainText -Force
Set-AzureKeyVaultSecret -VaultName 'duffkv' -Name 'WVD-Machine123' -SecretValue $Secret

Output:

{
  "attributes": {
    "created": "2020-03-22T19:42:22+00:00",
    "enabled": true,
    "expires": null,
    "notBefore": null,
    "recoveryLevel": "Purgeable",
    "updated": "2020-03-22T19:42:22+00:00"
  },
  "contentType": null,
  "id": "https://duffkv.vault.azure.net/secrets/WVD-Machine001/df3e6bfcb4334d0ab74fa176c98d22ac",
  "kid": null,
  "managed": null,
  "tags": {
    "file-encoding": "utf-8"
  },
  "value": "5645342anbt12"
}

kvsecret

Notice how we can even set expiration on the secrets. Hot.

Thanks!
Chad Duffey

Security Engineer