从Azure批处理访问Azure密钥库

从Azure批处理访问Azure密钥库,azure,certificate,azure-virtual-machine,azure-keyvault,azure-batch,Azure,Certificate,Azure Virtual Machine,Azure Keyvault,Azure Batch,我正在尝试从Azure批处理节点池中运行的VM访问Azure密钥库中的机密 但是,我不断遇到异常: 异常消息:已尝试1个证书。无法获取访问令牌。 带有指纹MY-thumbprint的cert#1例外:密钥集不存在 到目前为止,我一直遵循此处概述的说明: 本文概述了Azure批处理的场景,并指出我应该使用服务主体。我想确保版本控制中没有机密或密钥,因此我使用本地密钥库中证书的第一种方法登录Azure AD 以可执行文件的形式在本地运行以下所有内容可以正常工作,但在Azure批处理池节点上运行时失

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

但是,我不断遇到异常:

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

带有指纹MY-thumbprint的cert#1例外:密钥集不存在

到目前为止,我一直遵循此处概述的说明:

本文概述了Azure批处理的场景,并指出我应该使用服务主体。我想确保版本控制中没有机密或密钥,因此我使用本地密钥库中证书的第一种方法登录Azure AD

以可执行文件的形式在本地运行以下所有内容可以正常工作,但在Azure批处理池节点上运行时失败

到目前为止,我执行上述操作的步骤是:

  • 在keyvault中创建服务主体和关联证书:
    az ad sp create for rbac--name myserviceprincipal--create cert--cert mycertname--keyvault mykeyvaultname
    。保留服务主体应用程序id和租户id,以便在AzureServicesAuthConnectionString中使用

  • 为创建的服务主体创建密钥vault访问策略(在azure portal UI中完成)

  • 下载以PFX/PEM格式创建的证书(在Azure门户UI中完成)

  • 确保证书上有PFX密码(我这样做是因为在步骤6中将证书上载到azure批处理需要相关密码):

  • 将证书本地安装到我的计算机的LocalMachine存储中(用于本地测试)

  • 将证书上载到Azure批处理(使用Azure门户UI上载)

  • 将证书与适当的节点池关联并重新启动节点(目前使用Azure Portal UI)

  • 我在Azure批处理上运行的应用程序包是一个简单的控制台可执行文件。
    AzureServicesAuthConnectionString
    设置为
    RunAs=App;AppId={AppId};TenantId={TenantId};CertificateThumbprint={指纹};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);
    
    
    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);
    
    Environment.SetEnvironmentVariable(“AzureServicesAuthConnectionString”,“RunAs=App;AppId=;TenantId=;CertificateThumbprint=;CertificateStoreLocation=LocalMachine”);
    AzureServiceTokenProvider AzureServiceTokenProvider=新的AzureServiceTokenProvider(Environment.GetEnvironmentVariable(“AzureServicesAuthConnectionString”);
    KeyVaultClient KeyVaultClient=new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
    var secret=await keyVaultClient.GetSecretAsync(“”).ConfigureAwait(false);
    var message=secret.Value;
    控制台写入线(消息);
    
    本地工作正常,但在远程节点上失败。我能够将RDP导入Azure批处理节点,并看到已为本地计算机安装了证书


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

    除上述内容外,我还遵循了Sam Cogan文章中的说明:

    然而,我收到了与原始问题相同的问题。我的错误和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中的证书转换为PFX格式:
  • C:\ProgramFiles(x86)\Windows Kits\10\bin\x64>\pvk2pfx.exe-pvk batchcertificate6.pvk-spc batchcertificate6.cer-pfx batchcertificate7.pfx-po-pi
    
  • 创建ActiveDirectory应用程序和服务主体,并关联和上载创建的证书:
  • #将脚本指向您创建的cer文件
    $cerCertificateFilePath='C:\ProgramFiles(x86)\Windows Kits\10\bin\x64\batchcertificate6.cer'
    $cer=新对象System.Security.Cryptography.X509Certificates.X509Certificate2
    $cer.Import($cerCertificateFilePath)
    #将证书加载到内存中
    $credValue=[System.Convert]::ToBase64String($cer.GetRawCertData())
    #创建使用此证书的新AAD应用程序
    $newADApplication=New AzureRmADApplication-DisplayName”“-HomePage”“-IdentifierUris”“-certValue$credValue
    #创建使用此应用程序的新AAD服务原则
    $newAzureAdPrincipal=新AzureRmADServicePrincipal-ApplicationId$newADApplication.ApplicationId
    
  • 为服务主体授予密钥Vault访问权限(我在UI中添加了额外的权限,但也通过命令行运行):
  • Set-AzureRmKeyVaultAccessPolicy-VaultName'myvaultname'-ServicePrincipalName'-PermissionsToSecrets'Get'
    
  • 通过门户将证书(pfx)上载到Azure批处理。将其与我的节点池关联为LocalMachine并重新启动节点。使用连接字符串运行应用程序,如:
  • Environment.SetEnvironmentVariable(“AzureServicesAuthConnectionString”,
    “RunAs=App;”+
    “AppId=;”+
    “租户=;”+
    “CertificateThumbprint=;”+
    “CertificateStoreLocation=LocalMachine”);
    AzureServiceTokenProvider AzureServiceTokenProvider=新的AzureServiceTokenProvider(Environment.GetEnvironmentVariable(“AzureServicesAuthConnectionString”);
    KeyVaultClient KeyVaultClient=new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
    var secret=wait keyVaultClient.GetSecretAsync(“https://.vault.azure.net/secrets//")
    .配置等待(错误);
    message=secret.Value;
    控制台写入线(消息);
    

    我的代码使用上述连接字符串在本地与已安装的证书一起工作,但在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
    
    C:\Program Files (x86)\Windows Kits\10\bin\x64> .\pvk2pfx.exe -pvk batchcertificate6.pvk -spc batchcertificate6.cer -pfx batchcertificate7.pfx -po <MyPassword>  -pi <MyPassword>  
    
    #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
    
    Set-AzureRmKeyVaultAccessPolicy -VaultName 'myvaultname' -ServicePrincipalName '<my url>' -PermissionsToSecrets 'Get'
    
    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);
    
    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);