我有一个包含ASP.NET Core应用程序的docker映像,该应用程序使用Azure Key保管库访问诸如连接字符串之类的东西。在本地运行图像时,出现此错误:
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 Connected Service获取它。由于它不会出现在Docker映像上,因此它将尝试使用Azure CLI,但是未安装在Docker映像上。
因此,我需要将Azure CLI安装到docker映像中。假设Dockerfile的基本映像为FROM microsoft/dotnet:2.1-aspnetcore-runtime
,如何完成?
此基本映像是否是Alpine OS映像,所以我需要考虑使用Alpine安装Azure CLI吗?
假设我已经安装了Azure CLI,是否可以在不将任何凭据存储在Dockerfile源代码中或将它们通过纯文本传递到容器的情况下访问Key Vault?
一般来说,最好的方法是什么。
答案 0 :(得分:3)
我当前的解决方案是将环境变量与访问令牌一起使用。
获取密钥并将其存储在环境变量中(在进行az登录并设置正确的订阅之后):
$Env:ACCESS_TOKEN=(az account get-access-token --resource=https://vault.azure.net | ConvertFrom-Json).accessToken
将代码更改为:
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());
答案 1 :(得分:1)
可能的解决方案是生成服务主体( SP )并授予该服务主体访问密钥库的权限(通过RBAC或IAM)。 Microsoft Documentation on creating a SP
使用 SP 的凭据作为client-id
和client-secret
(Random example),您可以登录到保管库并检索机密。
答案 2 :(得分:0)
这是因为您的Docker容器以 root 用户身份运行,并且在密钥库中注册的用户是其他用户(yourusername@yourcmpany.com)
答案 3 :(得分:0)
尝试使用此链接中的方法进行安装:https://github.com/Azure/azure-cli/issues/8863
一旦安装:
az login --service-principal --username "ServicePrincipalName-or-ID" --password "ServicePrincipalPassword" --tenant "Azure_Tenant"
az keyvault secret show --name "SecretName" --vault-name "KeyVaultName" --query value
答案 4 :(得分:0)
尽管您提出这个问题已有一段时间,但另一个适合生产环境的选择是使用x509证书。
Microsoft有this article解释了如何执行此操作。您可以使用自签名证书或任何其他有效的SSL证书。这取决于您的需求。
答案 5 :(得分:0)
为了简化和自动化 E. Staal's answer,我想出了这个:
更新您的 .gitignore
文件,在其底部添加以下行:
appsettings.local.json
在解决方案资源管理器中右键单击项目,然后单击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
)
在您的 launchSettings.json
(或使用项目设置下的可视化编辑器)中配置以下值:
{
"profiles": {
// ...
"Docker": {
"commandName": "Docker",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development",
"AZURE_TENANT_ID": "<YOUR-AZURE-TENANT-ID-HERE>"
}
}
}
}
在您的 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
是否适合您。