Encrypt registry using a customer-managed key

When you store images and other artifacts in an Azure container registry, Azure automatically encrypts the registry content at rest with service-managed keys. You can supplement default encryption with an additional encryption layer using a key that you create and manage in Azure Key Vault. This article walks you through the steps using the Azure CLI and the Azure portal.

Server-side encryption with customer-managed keys is supported through integration with Azure Key Vault. You can create your own encryption keys and store them in a key vault, or use Azure Key Vault's APIs to generate keys. With Azure Key Vault, you can also audit key usage.

This feature is available in the Premium container registry service tier. For information about registry service tiers and limits, see Azure Container Registry service tiers.

Things to know

  • You can currently enable a customer-managed key only when you create a registry.
  • After enabling a customer-managed key on a registry, you can't disable it.
  • Content trust is currently not supported in a registry encrypted with a customer-managed key.
  • In a registry encrypted with a customer-managed key, run logs for ACR Tasks are currently retained for only 24 hours. If you need to retain logs for a longer period, see guidance to export and store task run logs.

Prerequisites

To use the Azure CLI steps in this article, you need Azure CLI version 2.2.0 or later. If you need to install or upgrade, see Install Azure CLI.

Enable customer-managed key - CLI

Create a resource group

If needed, run the az group create command to create a resource group for creating the key vault, container registry, and other required resources.

az group create --name <resource-group-name> --location <location>

Create a user-assigned managed identity

Create a user-assigned managed identity for Azure resources with the az identity create command. This identity will be used by your registry to access the Key Vault service.

az identity create \
  --resource-group <resource-group-name> \
  --name <managed-identity-name> 

In the command output, take note of the following values: id and principalId. You need these values in later steps to configure registry access to the key vault.

{
  "clientId": "xxxx2bac-xxxx-xxxx-xxxx-192cxxxx6273",
  "clientSecretUrl": "https://control-eastus.identity.azure.net/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myresourcegroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myidentityname/credentials?tid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&oid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&aid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myresourcegroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myresourcegroup",
  "location": "eastus",
  "name": "myidentityname",
  "principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "resourceGroup": "myresourcegroup",
  "tags": {},
  "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}

For convenience, store these values in environment variables:

identityID=$(az identity show --resource-group <resource-group-name> --name <managed-identity-name> --query 'id' --output tsv)

identityPrincipalID=$(az identity show --resource-group <resource-group-name> --name <managed-identity-name> --query 'principalId' --output tsv)

Create a key vault

Create a key vault with az keyvault create to store a customer-managed key for registry encryption.

To prevent data loss caused by accidental key or key vault deletions, you must enable the following settings: Soft delete and Purge protection. The following example includes parameters for these settings:

az keyvault create --name <key-vault-name> \
  --resource-group <resource-group-name> \
  --enable-soft-delete \
  --enable-purge-protection

Add key vault access policy

Configure a policy for the key vault so that the identity can access it. In the following az keyvault set-policy command, you pass the principal ID of the managed identity that you created, stored previously in an environment variable. Set key permissions to get, unwrapKey, and wrapKey.

az keyvault set-policy \
  --resource-group <resource-group-name> \
  --name <key-vault-name> \
  --object-id $identityPrincipalID \
  --key-permissions get unwrapKey wrapKey 

Create key and get key ID

Run the az keyvault key create command to create a key in the key vault.

az keyvault key create \
  --name <key-name> \
  --vault-name <key-vault-name>

In the command output, take note of the key's ID, kid. You use this ID in the next step:

[...]
  "key": {
    "crv": null,
    "d": null,
    "dp": null,
    "dq": null,
    "e": "AQAB",
    "k": null,
    "keyOps": [
      "encrypt",
      "decrypt",
      "sign",
      "verify",
      "wrapKey",
      "unwrapKey"
    ],
    "kid": "https://mykeyvault.vault.azure.net/keys/mykey/xxxxxxxxxxxxxxxxxxxxxxxx",
    "kty": "RSA",
[...]

For convenience, store this value in an environment variable:

keyID=$(az keyvault key show \
  --name <keyname> \
  --vault-name <key-vault-name> \
  --query 'key.kid' --output tsv)

Create a registry with customer-managed key

Run the az acr create command to create a registry in the Premium service tier and enable the customer-managed key. Pass the managed identity principal ID and the key ID, stored previously in environment variables:

az acr create \
  --resource-group <resource-group-name> \
  --name <container-registry-name> \
  --identity $identityID \
  --key-encryption-key $keyID \
  --sku Premium

Show encryption status

To show whether registry encryption with a customer-managed key is enabled, run the az acr encryption show command:

az acr encryption show --name <registry-name> 

Output is similar to:

{
  "keyVaultProperties": {
    "identity": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "keyIdentifier": "https://myvault.vault.azure.net/keys/myresourcegroup/abcdefg123456789...",
    "versionedKeyIdentifier": "https://myvault.vault.azure.net/keys/myresourcegroup/abcdefg123456789..."
  },
  "status": "enabled"
}

Enable customer-managed key - portal

Create a managed identity

Create a user-assigned managed identity for Azure resources in the Azure portal. For steps, see Create a user-assigned identity.

You use the identity's name in later steps.

Create user-assigned managed identity in the Azure portal

Create a key vault

For steps to create a key vault, see Quickstart: Set and retrieve a secret from Azure Key Vault using the Azure portal.

When creating a key vault for a customer-managed key, in the Basics tab, enable the following protection settings: Soft delete and Purge protection. These settings help prevent data loss caused by accidental key or key vault deletions.

Create key vault in the Azure portal

Add key vault access policy

Configure a policy for the key vault so that the identity can access it.

  1. Navigate to your key vault.
  2. Select Settings > Access policies > +Add Access Policy.
  3. Select Key permissions, and select Get, Unwrap Key, and Wrap Key.
  4. Select Select principal and select the resource name of your user-assigned managed identity.
  5. Select Add, then select Save.

Create key vault access policy

Create key

  1. Navigate to your key vault.
  2. Select Settings > Keys.
  3. Select +Generate/Import and enter a unique name for the key.
  4. Accept the remaining default values and select Create.
  5. After creation, select the key and take note of the current key version.

Create Azure container registry

  1. Select Create a resource > Containers > Container Registry.
  2. In the Basics tab, select or create a resource group, and enter a registry name. In SKU, select Premium.
  3. In the Encryption tab, in Customer-managed key, select Enabled.
  4. In Identity, select the managed identity you created.
  5. In Encryption, select Select from Key Vault.
  6. In the Select key from Azure Key Vault window, select the key vault, key, and version you created in the preceding section.
  7. In the Encryption tab, select Review + create.
  8. Select Create to deploy the registry instance.

Create container registry in the Azure portal

To see the encryption status of your registry in the portal, navigate to your registry. Under Settings, select Encryption.

Enable customer-managed key - template

You can also use a Resource Manager template to create a registry and enable encryption with a customer-managed key.

The following template creates a new container registry and a user-assigned managed identity. Copy the following contents to a new file and save it using a filename such as CMKtemplate.json.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "vault_name": {
      "defaultValue": "",
      "type": "String"
    },
    "registry_name": {
      "defaultValue": "",
      "type": "String"
    },
    "identity_name": {
      "defaultValue": "",
      "type": "String"
    },
    "kek_id": {
      "type": "String"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.ContainerRegistry/registries",
      "apiVersion": "2019-12-01-preview",
      "name": "[parameters('registry_name')]",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Premium",
        "tier": "Premium"
      },
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "[resourceID('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name'))]": {}
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name'))]"
      ],
      "properties": {
        "adminUserEnabled": false,
        "encryption": {
          "status": "enabled",
          "keyVaultProperties": {
            "identity": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name')), '2018-11-30').clientId]",
            "KeyIdentifier": "[parameters('kek_id')]"
          }
        },
        "networkRuleSet": {
          "defaultAction": "Allow",
          "virtualNetworkRules": [],
          "ipRules": []
        },
        "policies": {
          "quarantinePolicy": {
            "status": "disabled"
          },
          "trustPolicy": {
            "type": "Notary",
            "status": "disabled"
          },
          "retentionPolicy": {
            "days": 7,
            "status": "disabled"
          }
        }
      }
    },
    {
      "type": "Microsoft.KeyVault/vaults/accessPolicies",
      "apiVersion": "2018-02-14",
      "name": "[concat(parameters('vault_name'), '/add')]",
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name'))]"
      ],
      "properties": {
        "accessPolicies": [
          {
            "tenantId": "[subscription().tenantId]",
            "objectId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identity_name')), '2018-11-30').principalId]",
            "permissions": {
              "keys": [
                "get",
                "unwrapKey",
                "wrapKey"
              ]
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
      "apiVersion": "2018-11-30",
      "name": "[parameters('identity_name')]",
      "location": "[resourceGroup().location]"
    }
  ]
}

Follow the steps in the previous sections to create the following resources:

  • Key vault, identified by name
  • Key vault key, identified by key ID

Run the following az group deployment create command to create the registry using the preceding template file. Where indicated, provide a new registry name and managed identity name, as well as the key vault name and key ID you created.

az group deployment create \
  --resource-group <resource-group-name> \
  --template-file CMKtemplate.json \
  --parameters \
    registry_name=<registry-name> \
    identity_name=<managed-identity> \
    vault_name=<key-vault-name> \
    kek_id=<key-vault-key-id>

Show encryption status

To show the status of registry encryption, run the az acr encryption show command:

az acr encryption show --name <registry-name> 

Use the registry

After enabling a customer-managed key in a registry, you can perform the same registry operations that you perform in a registry that's not encrypted with a customer-managed key. For example, you can authenticate with the registry and push Docker images. See example commands in Push and pull an image.

Rotate key

Rotate a customer-managed key used for registry encryption to your compliance policies. Create a new key, or update a key version, and then update the registry to encrypt data using the key. You can perform these steps using the Azure CLI or in the portal.

When rotating a key, typically you specify the same identity used when creating the registry. Optionally, configure a new user-assigned identity for key access, or enable and specify the registry's system-assigned identity.

Note

Ensure that the required key vault access policy is set for the identity you configure for key access.

Azure CLI

Use az keyvault key commands to create or manage your key vault keys. For example, to create a new key version or key, run the az keyvault key create command:

# Create new version of existing key
az keyvault key create \
  –-name <key-name> \
  --vault-name <key-vault-name> 

# Create new key
az keyvault key create \
  –-name <new-key-name> \
  --vault-name <key-vault-name> 

Then run the az acr encryption rotate-key command, passing the new key ID and the identity you want to configure:

# Rotate key and use user-assigned identity
az acr encryption rotate-key \
  --name <registry-name> \
  --key-encryption-key <new-key-id> \
  --identity <principal-id-user-assigned-identity>

# Rotate key and use system-assigned identity
az acr encryption rotate-key \
  --name <registry-name> \
  --key-encryption-key <new-key-id> \
  --identity [system]

Portal

Use the registry's Encryption settings to update the key version, key, key vault, or identity settings used for the customer-managed key.

For example, to generate and configure a new key version:

  1. In the portal, navigate to your registry.

  2. Under Settings, select Encryption > Change key.

  3. Select Select key

    Rotate key in the Azure portal

  4. In the Select key from Azure Key Vault window, select the key vault and key you configured previously, and in Version, select Create new.

  5. In the Create a key window, select Generate, and then Create.

  6. Complete the key selection and select Save.

Revoke key

Revoke the customer-managed encryption key by changing the access policy on the key vault or by deleting the key. For example, use the az keyvault delete-policy command to change the access policy of the managed identity used by your registry:

az keyvault delete-policy \
  --resource-group <resource-group-name> \
  --name <key-vault-name> \
  --object-id $identityPrincipalID

Revoking the key effectively blocks access to all registry data, since the registry can't access the encryption key. If access to the key is enabled or the deleted key is restored, your registry will pick the key so you can again access the encrypted registry data.

Advanced scenarios

System-assigned identity

You can configure a registry's system-assigned managed identity to access the key vault for encryption keys. If you're unfamiliar with the different managed identities for Azure resources, see the overview.

To enable the registry's system-assigned identity in the portal:

  1. In the portal, navigate to your registry.
  2. Select Settings > Identity.
  3. Under System assigned, set Status to On. Select Save.
  4. Copy the Object ID of the identity.

To grant the identity access to your key vault:

  1. Navigate to your key vault.
  2. Select Settings > Access policies > +Add Access Policy.
  3. Select Key permissions, and select Get, Unwrap Key, and Wrap Key.
  4. Select Select principal and search for the object ID of your system-assigned managed identity, or the name of your registry.
  5. Select Add, then select Save.

To update the registry's encryption settings to use the identity:

  1. In the portal, navigate to your registry.
  2. Under Settings, select Encryption > Change key.
  3. In Identity, select System assigned, and select Save.

Key Vault firewall

If your Azure key vault is deployed in a virtual network with a Key Vault firewall, perform the following steps:

  1. Configure registry encryption to use the registry's system-assigned identity. See the preceding section.
  2. Configure the key vault to allow access by any trusted service.

For detailed steps, see Configure Azure Key Vault firewalls and virtual networks.

Next steps