从Azure Batch访问Azure Key Vault

时间:2019-09-25 16:32:25

标签: azure certificate azure-virtual-machine azure-keyvault azure-batch

我正在尝试从Azure批处理节点池中运行的VM访问Azure密钥保管库中的机密。

但是,我不断遇到异常:

异常消息:尝试过1个证书。无法获取访问令牌。

带有指纹MY-THUMBPRINT的证书#1的异常:密钥集不存在

到目前为止,我一直在遵循此处概述的说明: https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication

本文概述了Azure Batch的方案,并指示我应使用服务主体。我想确保版本控制中没有秘密或密钥,因此我正在使用本地密钥库中证书的第一种方法登录Azure AD。

以可执行文件本地方式运行以下所有程序,但在Azure批处理池节点上运行时失败。

到目前为止,我要做的步骤是:

  1. 在密钥库中创建服务主体和相关证书: az ad sp create-for-rbac --name myserviceprincipal --create-cert --cert mycertname --keyvault mykeyvaultname。保留要在AzureServicesAuthConnectionString中使用的服务主体应用ID和租户ID。

  2. 为创建的服务主体创建密钥库访问策略(在azure门户UI中完成)。

  3. 以PFX / PEM格式下载创建的证书(在Azure Portal UI中完成)。

  4. 确保证书上的PFX密码(我正在执行此操作,因为在步骤6中将证书上传到天蓝色的批次需要关联的密码):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)
  1. 将证书本地安装到计算机的LocalMachine存储中(用于本地测试)。

  2. 将证书上传到Azure Batch(使用Azure Portal UI上传)。

  3. 将证书与适当的节点池关联并重新启动节点(暂时使用Azure Portal UI)。

我在Azure Batch上运行的应用程序包是一个简单的控制台可执行文件。 AzureServicesAuthConnectionString设置为RunAs=App;AppId={AppId};TenantId={TenantId};CertificateThumbprint={Thumbprint};CertificateStoreLocation={LocalMachine},剩下的用于检索机密的密钥库代码如下:

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);

在本地一切正常,但在远程节点上失败。我能够将RDP导入Azure Batch节点,并看到已经为本地计算机安装了证书。

我想知道如何解决我的错误,或者上述步骤是否在某种程度上是错误的?

2 个答案:

答案 0 :(得分:0)

除上述内容外,我还按照此处的Sam Cogan文章中的说明进行操作: https://samcogan.com/secure-credential-access-with-azure-batch-and-keyvault/

但是,我收到与原始问题相同的问题。对于Sam Cogan文章,我的错误和相关的复制步骤如下:

Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: RunAs=App;AppId=<My Service Principal ID>;TenantId=<My Tenant ID>;CertificateThumbprint=<My cert thumbprint>;CertificateStoreLocation=LocalMachine, Resource: https://vault.azure.net, Authority: https://login.windows.net/<My Tenant ID>. Exception Message: Tried 1 certificate(s). Access token could not be acquired.
Exception for cert #1 with thumbprint <My cert thumbprint>: Keyset does not exist

我的复制步骤是:

  1. 创建证书(我添加了-a sha256 -len 2048部分,因为我在此处概述并解决了相同的错误:How to authenticate with Key Vault from Azure Batch
C:\Program Files (x86)\Windows Kits\10\bin\x64> .\makecert.exe -sv batchcertificate6.pvk -n "cn=andybatch6.cert.mydomain.org" batchcertificate6.cer -r -pe -a sha256 -len 2048
  1. 将步骤1中的证书转换为PFX格式:
C:\Program Files (x86)\Windows Kits\10\bin\x64> .\pvk2pfx.exe -pvk batchcertificate6.pvk -spc batchcertificate6.cer -pfx batchcertificate7.pfx -po <MyPassword>  -pi <MyPassword>  
  1. 创建ActiveDirectory应用程序和服务主体,并关联并上传创建的证书:
#Point the script at the cer file you created 

$cerCertificateFilePath = 'C:\Program Files (x86)\Windows Kits\10\bin\x64\batchcertificate6.cer' 
$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 
$cer.Import($cerCertificateFilePath)

#Load the certificate into memory 
$credValue = [System.Convert]::ToBase64String($cer.GetRawCertData()) 

#Create a new AAD application that uses this certifcate 
$newADApplication = New-AzureRmADApplication -DisplayName "<My display name>" -HomePage "<my url>" -IdentifierUris " <my url>" -certValue $credValue 

#Create new AAD service principle that uses this application 
$newAzureAdPrincipal = New-AzureRmADServicePrincipal -ApplicationId $newADApplication.ApplicationId
  1. 为服务主体授予密钥库访问权限(我在UI中添加了额外的权限,但也通过命令行运行了此权限):
Set-AzureRmKeyVaultAccessPolicy -VaultName 'myvaultname' -ServicePrincipalName '<my url>' -PermissionsToSecrets 'Get'
  1. 通过门户将证书(pfx)上载到Azure批处理。将其与我的节点池关联为LocalMachine并重新启动节点。使用以下连接字符串运行应用程序:
Environment.SetEnvironmentVariable("AzureServicesAuthConnectionString",
                    "RunAs=App;" +
                    "AppId=<the app id of my active directory app registration> ;" +
                    "TenantId=<my subscription tenant id>;" +
                    "CertificateThumbprint=<the thumbprint of my cert>;" +
                    "CertificateStoreLocation=LocalMachine");

                AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(Environment.GetEnvironmentVariable("AzureServicesAuthConnectionString"));
                KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
                var secret = await keyVaultClient.GetSecretAsync("https://<my vault name>.vault.azure.net/secrets/<secret name>/<secret id>")
                        .ConfigureAwait(false);
                message = secret.Value;
                Console.WriteLine(message);

我的代码使用上述连接字符串在本地与已安装的证书一起使用,但是在Azure Batch上运行时具有上述异常。

答案 1 :(得分:0)

为了访问证书,必须将其与“当前用户”关联并安装。可能是LocalMachine没有适当级别的权限?

在Azure Batch上,确保上载的证书与以下内容关联:

商店名称:“我的” 商店位置:“ CurrentUser”

此帖子很有帮助:https://github.com/nabhishek/customactivity_sample/tree/linkedservice

该帖子也是如此:X509Certificate - Keyset does not exist

C#exe中的连接字符串如下:

Environment.SetEnvironmentVariable("AzureServicesAuthConnectionString",
                    "RunAs=App;" +
                    "AppId=<the app id of my active directory app registration> ;" +
                    "TenantId=<my subscription tenant id>;" +
                    "CertificateThumbprint=<the thumbprint of my cert>;" +
                    "CertificateStoreLocation=CurrentUser");

                AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(Environment.GetEnvironmentVariable("AzureServicesAuthConnectionString"));
                KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
                var secret = await keyVaultClient.GetSecretAsync("https://<my vault name>.vault.azure.net/secrets/<secret name>/<secret id>")
                        .ConfigureAwait(false);
                message = secret.Value;
                Console.WriteLine(message);