Microsoft Azure Key Vault
The goal of this guide is to configure Signatory to use a 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 a 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 "signatory" --resource-group "signatory" --sku "premium"
The --sku
argument must be set to premium if you want to have your keys
stored in a HSM.
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
).
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 "signatory" to a valid URI of "http://signatory", 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": "signatory",
"name": "http://signatory",
"password": null,
"tenant": "50c46f11-1d0a-4c56-b468-1bcb03a8f69e"
}
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 (the rational way).
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": "6B7DDE60582104C37600BB337555E7517F5B834C",
"endDate": "2020-10-24T16:00:13+00:00",
"keyId": "172aa0bf-77d3-49ec-9978-a642d768ae47",
"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).
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": "be273d20-6dc1-4bbc-ab26-15d082cca908",
"isDefault": true,
"name": "My Subscription",
"state": "Enabled",
"tenantId": "50c46f11-1d0a-4c56-b468-1bcb03a8f69e",
"user": {
"name": "user@domain.com",
"type": "user"
}
}
]
Backend configuration
Configuration parameters
Name |
Type |
Required |
Description |
vault |
URL |
✅ |
Vault URL |
tenant_id |
UUID |
✅ |
Tenant ID |
client_id |
UUID |
✅ |
Service Principal (application) ID from the registration stage |
client_secret |
string |
|
Used for secret based authentication. Not covered here. Not recommended. |
client_pkcs12_certificate |
string |
|
Path to PKCS #12 file |
client_certificate_thumbprint |
string |
|
Hex or Base64 encoded client certificate hash. Use along with client_private_key as an alternative to PKCS #12 flow |
client_private_key |
string |
|
Path to the client private key. Use along with client_certificate_thumbprint as an alternative to PKCS #12 flow |
subscription_id |
UUID |
|
Subscription ID. Optional. Only if Microsoft.ResourceHealth is enabled (see above) |
resource_group |
string |
|
Resource 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
Import options
Name |
Type |
Description |
name |
string |
New key name. Otherwise will be auto generated. |