There is a good chance you've never heard of Azure Key Vault Managed HSM. It's essentially a Key Vault with less features and higher price.

So why would anyone use it then? Simple: regulatory requirements and a higher security level (critically, key sovereignty).

In this article, let's take a quick look at Managed HSM and my experiences with using it.

Features

A normal Key Vault supports:

  • Keys
  • Secrets
  • Certificates

A Managed HSM supports:

  • Keys

Yes, really. This is why I said it's basically a Key Vault with less features.

But there is an important distinction. Keys stores on Key Vault are only software-protected (on Standard tier). On Managed HSM, they are stored on dedicated HSM (Hardware Security Module) partitions. This means they are now hardware-protected and isolated from other users of Azure.

If you only need HSMs, you can use Key Vault Premium. There you still have support for secrets and certificates. The only downside is that the physical HSM is shared with other Azure users.

Thanks to Managed HSM using dedicated hardware, it does cost >$2000/month.

Getting started

We can create a Managed HSM using Bicep:

resource webAppDataProtectionManagedHsm 'Microsoft.KeyVault/managedHSMs@2023-07-01' = {
  location: 'westeurope'
  name: 'our-test-hsm'
  properties: {
    tenantId: tenant().tenantId
    publicNetworkAccess: 'Disabled'
    networkAcls: {
      defaultAction: 'Deny'
      ipRules: []
      bypass: 'None'
      virtualNetworkRules: []
    }
    initialAdminObjectIds: [
      'initial-admin-id-here'
    ]
    enableSoftDelete: true
    enablePurgeProtection: true
  }
  sku: {
    family: 'B'
    name: 'Standard_B1'
  }
}

In my sample app, we also define a private endpoint for the Managed HSM. By default, no public access is allowed; though you could modify the network ACLs above to allow it.

If this was a Key Vault, we could define the Key resource in Bicep as well and be done. Not with Managed HSM. Two reasons:

  1. Managed HSM does not trust Azure Resource Management API by default
  2. We need to activate the HSM first

If you look carefully at the Bicep above, we specified an initialAdminObjectIds array. These are the users who can activate the HSM and allow usage of ARM API if we want.

Activating the HSM is a bit of a ritual. Firstly we need network visibility to the HSM. Then we will sign in to AZ CLI as the admin user. Now we can run this script to activate the HSM:

#!/bin/bash

HSM_NAME=your-hsm-name
TENANT_ID=your-entra-id-tenant-id

# Login to Azure
az login -t "$TENANT_ID"

echo "Logged in to Azure"

# Create certificates for HSM activation (min 3 RSA keys are needed)
# NOTE: Normally you would need to store these extremely securely, you need them for DR purposes
openssl req -newkey rsa:2048 -nodes -keyout cert_0.key -x509 -days 365 -out cert_0.cer -subj "/C=FI/ST=Uusimaa/L=Helsinki/O=SSAP/OU=TodoAppDev/CN=cert0"
openssl req -newkey rsa:2048 -nodes -keyout cert_1.key -x509 -days 365 -out cert_1.cer -subj "/C=FI/ST=Uusimaa/L=Helsinki/O=SSAP/OU=TodoAppDev/CN=cert1"
openssl req -newkey rsa:2048 -nodes -keyout cert_2.key -x509 -days 365 -out cert_2.cer -subj "/C=FI/ST=Uusimaa/L=Helsinki/O=SSAP/OU=TodoAppDev/CN=cert2"

echo "Certificates created for HSM activation"

# Activate HSM
echo "Activating HSM, this will take a moment..."
az keyvault security-domain download --hsm-name "$HSM_NAME" --sd-wrapping-keys ./cert_0.cer ./cert_1.cer ./cert_2.cer --sd-quorum 2 --security-domain-file SSAPHSM-SD.json

echo "HSM activated"

Ok, so what the heck happens here?

  1. Login to AZ CLI
  2. Generate 3 certificates with RSA keys (minimum is 3)
  3. Download the security domain of the Managed HSM, use the keys, set quorum to 2

The idea is that the 3 certificates are then stored extremely securely. These can be used to restore a backup of the Managed HSM. But you don't necessarily need all of them. We set the quorum to 2 here, which means only 2 of the keys are needed to restore a backup. You can of course have more certificates and set the quorum to another value.

Note the script above is not storing the certificates securely. This is something that you would need to handle. A disaster recovery plan is also critical, as if you lose these certificates (below the quorum), you cannot recover a backup anymore.

Now that this is done, we can create a key:

az keyvault key create --hsm-name "$HSM_NAME" -n "$DATA_PROTECTION_KEY_NAME" --kty RSA-HSM -p hsm --size 4096 --subscription "$SUBSCRIPTION_ID" --ops wrapKey unwrapKey

echo "Data protection key created"

Alternatively, at this point we could use a different command to allow ARM API operations and create the key through Bicep.

We can also assign RBAC roles to users/applications. Managed HSM does not use Azure RBAC, it has its own internal thing (of course).

az keyvault role assignment create --hsm-name "$HSM_NAME" --role 'Managed HSM Crypto Service Encryption User' --scope "/keys/$DATA_PROTECTION_KEY_NAME" --assignee-object-id "$WEB_APP_OBJECT_ID" --assignee-principal-type ServicePrincipal -n "$WEB_APP_ROLE_ASSIGNMENT_ID"

echo "Role assigned to web app"

You can see the whole script in my sample app.

All in all, this would have been a lot easier with Standard/Premium Key Vault.

Using Managed HSM in your app

One neat thing about Managed HSM is that its API for keys is compatible with Key Vault. So you can just specify the Key Vault URI as https://our-test-hsm.managedhsm.azure.net, and the standard Key Vault SDK will work.

We can for example use the approach from ASP.NET Core Data Protection with Azure Key Vault and Azure Storage to store Data Protection keys encrypted with Managed HSM. In fact, this is what we do in my sample app.

Other services

In Azure there are also Dedicated HSM and Payment HSM. We will not go into those in this article, but you can check out the decision tree for when to use those as well as the ones mentioned here: https://learn.microsoft.com/en-us/azure/security/fundamentals/key-management-choose#choose-an-azure-key-management-solution-by-scenario.

Summary

Azure Key Vault Managed HSM is a pain to setup and expensive. It also introduces additional requirements for disaster recovery. But, once you have it setup, it's quite easy to use.

I would never recommend it for customer architectures unless requirements mandate it though. Key Vault Premium offers FIPS 140-3 level 3 compliance already. If key sovereignty is also needed, then Managed HSM is the way to go.