Skip to main content

Azure Key Vault

The goal of this guide is to configure Signatory to use an Azure Key Vault as a signing backend.

To setup Azure Key Vault as a signing backend for Signatory, you will need:

  • An active Azure subscription
  • The Azure CLI installed and configured on your computer.

Azure setup

You will need to create several Azure resources, and copy configuration into the signatory config file. Let's begin.

This guide uses the az cli command to create all required resources. For each command, you will get a json formatted result, or an error.

Log in

az login

Create an Azure resource group.

You need to specify the location you want your Signatory to be located. This is up to you. The closer to your baker the better, but other criteria may be important to you.

az group create \
--name RESOURCE_GROUP \
--location LOCATION

Example:

az group create --name "signatory" --location "canadaeast"

Create a new Key Vault, with HSM enabled

Next we will create a new Key Vault within our newly created resource group.

az keyvault create \
--name KEYVAULT_NAME \
--resource-group RESOURCE_GROUP \
--sku "premium"

Example:

az keyvault create --name "sigy" --resource-group "sigy" --sku "premium"

The --sku argument must be set to premium if you want to have your keys stored in a HSM.

Take note of the returned values of properties.vaultUri and properties.tenantId, these will be used later in the Signatory configuration.

Create a Service Principal for authentication

This document describes a service principal creation flow and a backend configuration for a key-based authentication. Alternatively, you can use client secret-based authentication but it's not recommended.

You will need openssl to manipulate keys and certificates.

Generate a client certificate

openssl req -newkey rsa:4096 -nodes -keyout "service-principal.key" -out "service-principal.csr"

Sign a certificate

openssl x509 -signkey "service-principal.key" -in "service-principal.csr" -req -days 365 -out "service-principal.crt"

Now you can safely delete the request file (.csr).

Note: If running signatory in docker then the service-principal.crt should be within the docker. The full path of service-principal.crt within the container is a Signatory configuration file value.

Create a Service Principal for authentication

Next we need to create a "service principal" resource (also known as a "service account" or a "App Registration").

This is the credential that allows Signatory to authenticate and work with the Azure Key Vault service.

az ad sp create-for-rbac \
-n APP_NAME
--cert "@CERT_FILE"

Example:

az ad sp create-for-rbac -n "signatory" --cert "@service-principal.crt"

Example output:

Changing "sigy" to a valid URI of "http://sigy", which is the required format used for service principal names
Certificate expires 2020-10-24 16:00:14+00:00. Adjusting SP end date to match.
Creating a role assignment under the scope of "/subscriptions/be273d20-6dc1-4bbc-ab26-15d082cca908"
Retrying role assignment creation: 1/36
Retrying role assignment creation: 2/36
Retrying role assignment creation: 3/36
Retrying role assignment creation: 4/36
{
"appId": "d5ccc5ea-8a1f-4dc1-9673-183a4c85e280",
"displayName": "sigy",
"name": "http://sigy",
"password": null,
"tenant": "50c46f11-1d0a-4c56-b468-1bcb03a8f69e"
}

Take note of the returned value of appId, it is used in subsequent steps, and later in the Signatory configuration.

Create a PKCS #12 file (the Microsoft way)

This method uses PKCS #12 container file for keeping a self-signed certificate along with the corresponding private key in one bundle. The certificate's hash is needed for the authentication.

openssl pkcs12 -export -out "service-principal.pfx" -inkey "service-principal.key" -in "service-principal.crt"

Now you can safely delete the certificate file (.csr).

Get certificate hash from AD

Alternatively, you can get back a certificate hash

az ad sp credential list --id APPID --cert

Example:

az ad sp credential list --id "d5ccc5ea-8a1f-4dc1-9673-183a4c85e280" --cert

Example output:

[
{
"additionalProperties": null,
"customKeyIdentifier": "6B7HDJ60582104C37600CC237555E7517F5B394C",
"endDate": "2020-10-24T16:00:13+00:00",
"keyId": "172bb0bf-77d3-49ud-9725-a642d768tm47",
"startDate": "2019-11-06T17:06:56.249417+00:00",
"type": "AsymmetricX509Cert",
"usage": "Verify",
"value": null
}
]

The customKeyIdentifier contains the certificate's SHA-1 hash (called a thumbprint in Azure documentation). The thumbprint of the certificate can also be found in Azure portal, through Active Directory -> App Registrations -> Client Credentials.

You don't need the certificate anymore.

Permissions granting

Next, we need to grant the new service principal access to our Key Vault. You need to use the appId value from the registration stage to do this.

az keyvault set-policy \
--name signatory-keyvault \
--spn APPID \
--key-permissions sign list get import

Example:

az keyvault set-policy --name signatory --spn "d5ccc5ea-8a1f-4dc1-9673-183a4c85e280" --key-permissions sign list get import

Enable Microsoft.ResourceHealth service (optional)

Microsoft.ResourceHealth service is used to check the Key Vault availability status

az provider register --namespace "Microsoft.ResourceHealth"

ATTENTION: The registration process can take up to an hour. To check the registration status run the command:

az provider show -n "Microsoft.ResourceHealth"
registrationState property should say Registered

Get the subscription and tenant id for your account

To find your subscription id, run the command:

az account list

Example output:

[
{
"cloudName": "AzureCloud",
"id": "172bb0bf-77d3-49ud-9725-a642d768tm47",
"isDefault": true,
"name": "My Subscription",
"state": "Enabled",
"tenantId": "52c46f11-1j3a-4c56-b728-1bcb03fhf48e",
"user": {
"name": "user@domain.com",
"type": "user"
}
}
]

Backend configuration

Configuration parameters

NameTypeRequiredDescription
vaultURLVault URL
tenant_idUUIDTenant ID
client_idUUIDService Principal (application) ID from the registration stage
client_secretstringOPTIONALUsed for secret based authentication. Not covered here. Not recommended.
client_pkcs12_certificatestringOPTIONALPath to PKCS #12 file
client_certificate_thumbprintstringOPTIONALHex or Base64 encoded client certificate hash. Use along with client_private_key as an alternative to PKCS #12 flow
client_private_keystringOPTIONALPath to the client private key. Use along with client_certificate_thumbprint as an alternative to PKCS #12 flow
subscription_idUUIDOPTIONALSubscription ID. Optional. Only if Microsoft.ResourceHealth is enabled (see above)
resource_groupstringOPTIONALResource group name. Optional. Only if Microsoft.ResourceHealth is enabled (see above)

Example:

vault: https://signatory.vault.azure.net/
tenant_id: 50c46f11-1d0a-4c56-b468-1bcb03a8f69e
client_id: d5ccc5ea-8a1f-4dc1-9673-183a4c85e280
client_private_key: service-principal.key
client_certificate_thumbprint: 6B7DDE60582104C37600BB337555E7517F5B834C

Environment variables

  • AZURE_CLIENT_TENANT
  • AZURE_CLIENT_ID
  • AZURE_CLIENT_SECRET
  • AZURE_CLIENT_PKCS12_CERTIFICATE
  • AZURE_CLIENT_CERTIFICATE
  • AZURE_CLIENT_CERTIFICATE_THUMBPRINT
  • AZURE_CLIENT_PRIVATE_KEY

Create EC-HSM key

az keyvault key create --curve {P-256, P-256K, P-384, P-521}                                     
--kty {EC, EC-HSM, RSA, RSA-HSM, oct, oct-HSM}]
--name
--vault-name

Example:

az keyvault key create --curve P-256 --kty EC-HSM --name "sigy-key" --vault-name "sigy"

Obtain public key hash (PKH) of above key:

% ./signatory-cli list -c /etc/s.yaml
Public Key Hash: tz3d6nYmR1LmSDsgJ463Kgd8EbH53pYnuv8S
Vault: Azure
ID: https://sigy.vault.azure.net/keys/sigy-EC-HSM/77154e5846b4sdajbf78fs876dfse963b0b4bec
Status: ACTIVE
Allowed Operations: [block endorsement generic]
Allowed Kinds: [endorsement transaction]

Update signatory.yaml config with PKH:

server:
address: :6732
utility_address: :9583

vaults:
azure:
driver: azure
config:
vault: https://sigy.vault.azure.net/
tenant_id: 50a7adf11-1a9a-4b76-b468-1acdb03a8f69e
client_id: b673iu8cc5-98c9-44ac-a688-7cafcdb9b9bcb4
client_private_key: service-principal.key
client_certificate_thumbprint: 643F14403B695090D8ABDC34ABBE7EF2423497352
subscription_id: be223726da0-6dc1-4cdc-ab26-15a082bdaaa908
resource_group: sigy

tezos:
tz3d6nYmR1LmSDsgJ463Kgd8EbH53pYnuv8S:
log_payloads: true
allow:
block:
endorsement:
preendorsement:
generic:
- transaction
- reveal
- delegation