id | title |
---|---|
azure_kms |
AzureKMS |
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.
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.
az login
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"
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.
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.
openssl req -newkey rsa:4096 -nodes -keyout "service-principal.key" -out "service-principal.csr"
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.
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.
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
).
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.
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
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
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": "[email protected]",
"type": "user"
}
}
]
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 | OPTIONAL | Used for secret based authentication. Not covered here. Not recommended. |
client_pkcs12_certificate | string | OPTIONAL | Path to PKCS #12 file |
client_certificate_thumbprint | string | OPTIONAL | Hex or Base64 encoded client certificate hash. Use along with client_private_key as an alternative to PKCS #12 flow |
client_private_key | string | OPTIONAL | Path to the client private key. Use along with client_certificate_thumbprint as an alternative to PKCS #12 flow |
subscription_id | UUID | OPTIONAL | Subscription ID. Optional. Only if Microsoft.ResourceHealth is enabled (see above) |
resource_group | string | OPTIONAL | 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
AZURE_CLIENT_TENANT
AZURE_CLIENT_ID
AZURE_CLIENT_SECRET
AZURE_CLIENT_PKCS12_CERTIFICATE
AZURE_CLIENT_CERTIFICATE
AZURE_CLIENT_CERTIFICATE_THUMBPRINT
AZURE_CLIENT_PRIVATE_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