如何从本地运行的docker容器访问Azure Keyvault?

如何从本地运行的docker容器访问Azure Keyvault?,azure,docker,asp.net-core,azure-keyvault,azure-cli,Azure,Docker,Asp.net Core,Azure Keyvault,Azure Cli,我有一个docker映像,其中包含一个ASP.NET核心应用程序,该应用程序使用Azure Key vault访问连接字符串等内容。在本地运行映像时,会出现以下错误: Unhandled Exception: Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], R

我有一个docker映像,其中包含一个ASP.NET核心应用程序,该应用程序使用Azure Key vault访问连接字符串等内容。在本地运行映像时,会出现以下错误:

Unhandled Exception: Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/[guid]. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/[guid]. Exception Message: Tried to get token using Managed Service Identity. Unable to connect to the Managed Service Identity (MSI) endpoint. Please check that you are running on an Azure resource that has MSI setup.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/[guid]. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Environment variable LOCALAPPDATA not set.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/[guid]. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. /bin/bash: az: No such file or directory
据我所知,它首先尝试获取访问令牌作为托管服务标识。由于它没有在Azure云中运行,因此无法执行此操作,并尝试通过visual studio连接服务获取它。由于这不会出现在docker映像上,它会尝试使用Azure CLI,但docker映像上没有安装

因此,我需要将Azure CLI安装到docker映像中。如果Dockerfile的基本映像是来自microsoft/dotnet:2.1-aspnetcore-runtime的
,那么这是如何实现的

这个基本映像是Alpine OS映像吗,那么我是否需要考虑使用Alpine安装Azure CLI

假设我安装了Azure CLI,有没有一种方法可以访问密钥库,而无需在Dockerfile源代码中存储任何凭据或通过纯文本将其传递给容器


一般来说,这里的最佳方法是什么。

这是因为docker容器以root用户身份运行,并且在密钥库中注册的用户是其他用户(yourusername@yourcmpany.com)

尝试此链接中的方法安装:

一旦安装:

  • 登录/验证:
    az登录--服务主体--用户名“ServicePrincipalName或ID”--密码“ServicePrincipalPassword”--租户“Azure\U租户”
  • 然后获取
    az keyvault secret show--name“SecretName”--vault name“KeyVaultName”--查询值
  • 请参阅Quickstart,以了解更好的流程,并在您熟悉该流程后获得更高级的使用

    解决方案(不用于生产) 您的问题的一个可能解决方案是生成服务主体(SP)并授予此服务主体对密钥库的访问权(通过RBAC或IAM)

    使用SP的凭据作为
    客户端id
    客户端机密
    (),然后您可以登录到vault并检索机密

    担心
    • 通过这种方法,您将在代码中引入秘密(很可能就是您使用密钥库的确切原因)。我想本地docker映像仅供开发使用。因此,我建议创建一个仅用于开发(并使用SP访问)的Keyvault,同时使用一个单独的Kevault进行生产,其中使用了一个已建立的、无秘密的身份验证方案
    • 您必须确保密钥保管库允许从azure云外部进行访问(请参阅portal.azure.com上的访问策略)

    我当前的解决方案是使用带有访问令牌的环境变量

    获取密钥并存储在环境变量中(完成az登录并设置正确的订阅后):

    我们在Visual Studio中添加该环境变量:

    将代码更改为:

                    config.AddEnvironmentVariables();
    
                    KeyVaultClient keyVaultClient;
                    var accessToken = Environment.GetEnvironmentVariable("ACCESS_TOKEN");
    
                    if (accessToken != null)
                    {
                        keyVaultClient = new KeyVaultClient(
                            async (string a, string r, string s) => accessToken);
                    }
                    else
                    {
                        var azureServiceTokenProvider = new AzureServiceTokenProvider();
                        keyVaultClient = new KeyVaultClient(
                           new KeyVaultClient.AuthenticationCallback(
                               azureServiceTokenProvider.KeyVaultTokenCallback));
                    }
    
                    config.AddAzureKeyVault(
                        $"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
                        keyVaultClient,
                        new DefaultKeyVaultSecretManager());
    

    尽管您提出这个问题已经有一段时间了,但另一个适合于生产环境的选项是使用x509证书


    微软已经解释了如何做到这一点。您可以使用自签名证书或任何其他有效的SSL证书。这取决于您的需要。

    为了简化和自动化,我提出了以下建议:

  • 通过在文件底部添加以下行来更新
    .gitignore
    文件:

    appsettings.local.json
    
  • 在解决方案资源管理器中右键单击该项目,然后单击
    Properties
    ;在
    生成事件
    选项卡中,找到
    预生成事件命令行
    文本框并添加以下代码:

    cd /d "$(ProjectDir)"
    if exist "appsettings.local.json" del "appsettings.local.json"
    if "$(ConfigurationName)" == "Debug" (
    az account get-access-token  --resource=https://vault.azure.net > appsettings.local.json
    )
    
  • 启动设置.json中(或使用项目设置下的可视化编辑器)配置以下值:

    {
    “概况”:{
    // ...
    “码头工人”:{
    “commandName”:“Docker”,
    “环境变量”:{
    “网络环境”:“发展”,
    “AZURE_租户_ID”:”
    }
    }
    }
    }
    
  • Program.cs
    文件中,找到CreateHostBuilder方法并相应地更新
    ConfigureAppConfiguration
    块——以下是我的示例:

    Host.CreateDefaultBuilder(args).ConfigureAppConfiguration
    (
    (ctx,cfg)=>
    {
    if(ctx.HostingEnvironment.IsDevelopment())
    {
    AddJsonFile(“appsettings.local.json”,true);
    }
    var builconfig=cfg.Build();
    var keyVault=builconfig[“keyVault”];
    如果(!string.IsNullOrWhiteSpace(keyVault))
    {
    var accessToken=builconfig[“accessToken”];
    cfg.AddAzureKeyVault
    (
    $“https://{keyVault}.vault.azure.net/”,
    新的KeyVaultClient
    (
    string.IsNullOrWhiteSpace(accessToken)
    ?新建KeyVaultClient.AuthenticationCallback
    (
    新建AzureServiceTokenProvider().KeyVault TokenCallback
    )
    :(x,y,z)=>Task.FromResult(accessToken)
    ),
    新的DefaultKeyVaultSecretManager()
    );
    }
    }
    )
    

  • 如果仍然不起作用,请验证是否已执行
    az登录
    ,以及
    az帐户获得访问令牌--resource=https://vault.azure.net
    适用于您。

    为什么不使用azure sdk?您能详细说明一下吗?嗯,就像您通常会做的那样,没有msi端点,您找到了解决方案吗?由于共享帐户和安全原因,我不希望创建像@fox918 suggest这样的SP。我当前要做的是从cli获取令牌,将其放入环境变量中,并在代码中使用该令牌。这样,每个开发人员仍然使用自己的身份,但这是一个有点手动工作如果你只是从谷歌来这里,这就是我最终要做的,以解决这个问题,这是一个自动化版本的@E.Staal的答案;它会的
    cd /d "$(ProjectDir)"
    if exist "appsettings.local.json" del "appsettings.local.json"
    if "$(ConfigurationName)" == "Debug" (
    az account get-access-token  --resource=https://vault.azure.net > appsettings.local.json
    )