繁体   English   中英

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

[英]How to access Azure Keyvault from docker container running locally?

我有一个 docker 映像,其中包含一个 ASP.NET Core 应用程序,该应用程序使用 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 的基本映像是FROM microsoft/dotnet:2.1-aspnetcore-runtime ,这是如何完成的?

此基本映像是 Alpine OS 映像,所以我是否需要考虑使用 Alpine 安装 Azure CLI?

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

更一般地说,这里最好的方法是什么。

我当前的解决方案是将环境变量与访问令牌一起使用。

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

$Env:ACCESS_TOKEN=(az account get-access-token  --resource=https://vault.azure.net | ConvertFrom-Json).accessToken

我们在 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());

解决方案(不适用于生产用途)

您的问题的一个可能解决方案是生成服务主体 ( SP ) 并授予此服务主体访问密钥保管库的权限(通过 RBAC 或 IAM)。 有关创建SP 的Microsoft 文档

使用SP的凭据作为client-idclient-secret随机示例),然后您可以登录保管库并检索机密。

顾虑

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

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

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

为了简化和自动化E. Staal 的回答,我想出了这个:

  1. 更新您的.gitignore文件,在其底部添加以下行:

     appsettings.local.json
  2. 在解决方案资源管理器中右键单击该项目,然后单击Properties Build Events选项卡中,找到Pre-build event command line文本框并添加以下代码:

     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 )
  3. 在您的launchSettings.json (或使用项目设置下的可视化编辑器)中配置以下值:

     { "profiles": { // ... "Docker": { "commandName": "Docker", "environmentVariables": { "DOTNET_ENVIRONMENT": "Development", "AZURE_TENANT_ID": "<YOUR-AZURE-TENANT-ID-HERE>" } } } }
  4. 在您的Program.cs文件中找到 CreateHostBuilder 方法并相应地更新ConfigureAppConfiguration块——这里以我的为例:

     Host.CreateDefaultBuilder(args).ConfigureAppConfiguration ( (ctx, cfg) => { if (ctx.HostingEnvironment.IsDevelopment()) { cfg.AddJsonFile("appsettings.local.json", true); } var builtConfig = cfg.Build(); var keyVault = builtConfig["KeyVault"]; if (!string.IsNullOrWhiteSpace(keyVault)) { var accessToken = builtConfig["accessToken"]; cfg.AddAzureKeyVault ( $"https://{keyVault}.vault.azure.net/", new KeyVaultClient ( string.IsNullOrWhiteSpace(accessToken) ? new KeyVaultClient.AuthenticationCallback ( new AzureServiceTokenProvider().KeyVaultTokenCallback ) : (x, y, z) => Task.FromResult(accessToken) ), new DefaultKeyVaultSecretManager() ); } } )

如果这仍然不起作用,请验证是否已执行az login并且az account get-access-token --resource=https://vault.azure.net是否适合您。

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

尝试使用此链接中的方法进行安装: https : //github.com/Azure/azure-cli/issues/8863

安装后:

  1. 登录/身份验证: az login --service-principal --username "ServicePrincipalName-or-ID" --password "ServicePrincipalPassword" --tenant "Azure_Tenant"
  2. 然后获取az keyvault secret show --name "SecretName" --vault-name "KeyVaultName" --query value

这里的快速启动, 在这里为更好的流动性,并在这里,一旦你熟悉了更先进的使用过程

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM