This example demonstrates how to use an Azure Key Vault hosted secp256k1 key to securely sign EVM transactions in OpenZeppelin Relayer. The relayer supports three Azure authentication modes:
client_secretmanaged_identityworkload_identity
- An Azure subscription with access to Azure Key Vault
- One of the following Azure identity setups:
- A Microsoft Entra application (service principal) with a client secret
- A managed identity with access to the Key Vault
- A workload identity / federated credential with access to the Key Vault
- An EVM signing key stored in Azure Key Vault
- Rust and Cargo installed
- Git
- Docker
- Docker Compose
git clone https://github.com/OpenZeppelin/openzeppelin-relayer
cd openzeppelin-relayer- Open the Azure portal and create or select a Key Vault
- Create or import the EVM signing key you want the relayer to use
- Note the following values:
- Vault URL, for example
https://your-key-vault-name.vault.azure.net - Key name
- Optional key version
- Vault URL, for example
- Depending on the auth mode, also collect:
client_secret: tenant ID, client ID, client secretmanaged_identity: optional client ID for a user-assigned identityworkload_identity: tenant ID, client ID, and optionally a federated token file path if you don't rely onAZURE_FEDERATED_TOKEN_FILE
- Make sure the chosen identity has permission to read the key metadata and sign payloads with it
For client_secret, populate the environment variables used by the example:
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
API_KEY=generated_api_key
WEBHOOK_SIGNING_KEY=generated_webhook_keyIf you need values for API_KEY and WEBHOOK_SIGNING_KEY, you can generate them with:
cargo run --example generate_uuid
cargo run --example generate_uuidUpdate config/config.json with your Azure Key Vault details.
Client secret example:
{
"signers": [
{
"id": "azure-key-vault-signer-evm",
"type": "azure_key_vault",
"config": {
"auth_type": "client_secret",
"tenant_id": {
"type": "env",
"value": "AZURE_TENANT_ID"
},
"client_id": {
"type": "env",
"value": "AZURE_CLIENT_ID"
},
"client_secret": {
"type": "env",
"value": "AZURE_CLIENT_SECRET"
},
"vault_url": "https://your-key-vault-name.vault.azure.net",
"key_name": "your-secp256k1-key-name",
"key_version": null
}
}
]
}Managed identity example:
{
"id": "azure-key-vault-signer-evm",
"type": "azure_key_vault",
"config": {
"auth_type": "managed_identity",
"client_id": {
"type": "env",
"value": "AZURE_CLIENT_ID"
},
"vault_url": "https://your-key-vault-name.vault.azure.net",
"key_name": "your-secp256k1-key-name",
"key_version": null
}
}Workload identity example:
{
"id": "azure-key-vault-signer-evm",
"type": "azure_key_vault",
"config": {
"auth_type": "workload_identity",
"tenant_id": {
"type": "env",
"value": "AZURE_TENANT_ID"
},
"client_id": {
"type": "env",
"value": "AZURE_CLIENT_ID"
},
"vault_url": "https://your-key-vault-name.vault.azure.net",
"key_name": "your-secp256k1-key-name",
"key_version": null
}
}If you want to pin the signer to a specific key version, replace null with the Azure Key Vault key version string.
For workload identity, the relayer reads AZURE_FEDERATED_TOKEN_FILE automatically unless you set federated_token_file explicitly in the signer config.
Update the notification entry in config/config.json:
{
"notifications": [
{
"url": "your_webhook_url"
}
]
}For testing, you can use Webhook.site.
docker compose -f examples/evm-azure-key-vault-signer/docker-compose.yaml upVerify that the relayer is running:
curl -X GET http://localhost:8080/api/v1/relayers \
-H "Content-Type: application/json" \
-H "AUTHORIZATION: Bearer YOUR_API_KEY"- Verify the auth mode and identity values are correct for your deployment
- Verify the Key Vault URL, key name, and key version match your Azure resources
- Verify the chosen identity has access to the key for metadata lookup and signing
- Check relayer logs for Azure Key Vault API or authentication errors