I am trying to access secrets in my Azure Key Vault from VMs running in my Azure Batch node pool.
However, I keep running into the exception:
Exception Message: Tried 1 certificate(s). Access token could not be acquired.
Exception for cert #1 with thumbprint MY-THUMBPRINT: Keyset does not exist
So far I have been following the instructions outlined here: https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication
The article outlines the scenario of Azure Batch, and indicates I should use a Service Principal. I would like to ensure no secrets or keys are in version control, so I am using the first method of a certificate in a local keystore to sign into Azure AD.
Running all of the below locally as an executable works fine, but fails when run on an Azure Batch pool node.
My steps so far to do the above are:
Create a service principal and associated certificate in keyvault:
az ad sp create-for-rbac --name myserviceprincipal --create-cert --cert mycertname --keyvault mykeyvaultname
. Keep the service principal app id and tenant id for use in the AzureServicesAuthConnectionString.Create key vault access policy for the created service principal (done in the azure portal UI).
Download the created certificate in PFX/PEM format (done in the Azure Portal UI).
Ensuring a PFX password on the certificate (I am doing this as uploading the cert to azure batch in step 6 requires an associated password): https://coombes.nz/blog/azure-keyvault-export-certificate/
# Replace these variables with your own values
$vaultName = "YOUR-KEYVAULT-NAME"
$certificateName = "YOUR-CERTIFICATE-NAME"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "\$certificateName.pfx"
$password = "YOUR-CERTIFICATE-PASSWORD"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfxProtectedBytes = $pfx.Export([Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $password)
[IO.File]::WriteAllBytes($pfxPath, $pfxProtectedBytes)
Installing the certificate locally into my computer's LocalMachine store (for local testing).
Uploading the certificate into Azure Batch (using the Azure Portal UI upload).
Associating the certificate with the appropriate Node Pool and rebooting the nodes (using the Azure Portal UI for now).
My application package running on Azure Batch is a simple console executable. The AzureServicesAuthConnectionString
is set to RunAs=App;AppId={AppId};TenantId={TenantId};CertificateThumbprint={Thumbprint};CertificateStoreLocation={LocalMachine}
and the remaining key vault code to retreive the secret looks like:
Environment.SetEnvironmentVariable("AzureServicesAuthConnectionString", "RunAs=App;AppId=<MY-APP-ID>;TenantId=<MY-TENANT>;CertificateThumbprint=<MY-THUMBPRINT>;CertificateStoreLocation=LocalMachine");
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(Environment.GetEnvironmentVariable("AzureServicesAuthConnectionString"));
KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var secret = await keyVaultClient.GetSecretAsync("<MY-SECRET>").ConfigureAwait(false);
var message = secret.Value;
Console.WriteLine(message);
Things work fine locally, but fail on the remote node. I am able to RDP into the Azure Batch node and see that the certificate has been installed for the local machine.
I am wondering how to resolve my error or if my above steps are wrong in some way?