无法使用应用服务上的 Azure MSI 访问 Key Vault
Posted
技术标签:
【中文标题】无法使用应用服务上的 Azure MSI 访问 Key Vault【英文标题】:Unable to get access to Key Vault using Azure MSI on App Service 【发布时间】:2018-02-28 15:32:49 【问题描述】:我已在应用服务上启用托管服务标识。但是,我的 WebJobs 似乎无法访问密钥。
他们报告:
Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connectionstring: [No connection string specified], Resource: https://vault.azure.net, Authority: . 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: Connectionstring: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.microsoftonline.com/common. Exception Message: Tried to get token using Active Directory Integrated Authentication. Access token could not be acquired. password_required_for_managed_user: Password is required for managed user
Parameters: Connectionstring: [No connection string specified], Resource: https://vault.azure.net, Authority: . Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 'az' is not recognized as an internal or external command,
Kudo 不显示任何 MSI_ 环境变量。
这应该如何工作?这是现有的应用服务计划。
【问题讨论】:
我想补充一点,我今天遇到了这个问题,在检查一切正常后,我尝试重新启动应用服务。它解决了问题。 【参考方案1】:AppAuthentication 库利用应用服务中代表您的站点接收令牌的内部端点。此端点是非静态的,因此设置为环境变量。通过 ARM 为您的站点激活 MSI 后,您的站点需要重新启动才能在其中设置两个新的环境变量:
MSI_ENDPOINT 和 MSI_SECRET
这些变量的存在对于 MSI 功能在运行时正常工作至关重要,因为 AppAuthentication 库使用它们来获取授权令牌。错误消息反映了这一点:
异常消息:尝试使用托管服务标识获取令牌。无法连接到托管服务身份 (MSI) 端点。请检查您是否在已设置 MSI 的 Azure 资源上运行。
如果这些变量不存在,您可能需要重新启动站点。
https://docs.microsoft.com/en-us/azure/app-service/app-service-managed-service-identity
如果设置了环境变量,但您仍然看到相同的错误,上面的文章有一个代码示例,展示了如何手动向该端点发送请求。
public static async Task<HttpResponseMessage> GetToken(string resource, string apiversion)
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Secret", Environment.GetEnvironmentVariable("MSI_SECRET"));
return await client.GetAsync(String.Format("0/?resource=1&api-version=2", Environment.GetEnvironmentVariable("MSI_ENDPOINT"), resource, apiversion));
我会尝试一下,看看我会得到什么样的回应。
【讨论】:
所以,我尝试重新启动服务。无数次。似乎没有什么可以使它起作用。下一步是手工完成。但是,我觉得问题可能只是 env 变量不存在。 我应该补充一点,每次我再次部署站点(使用 Arm 模板)时,启用 MSI 都会被禁用。我将手臂模板设置为 SystemAssigned。 在您的 ARM 模板中,确保“身份”块不在“属性”块中。您可以转到resources.azure.com 并查找您的站点以查看它的 ARM 属性。如果启用了 MSI,您应该能够在“身份”对象中找到 TenantId 和 PrincipalId。在门户中,确保应用程序设置 WEBSITE_DISABLE_MSI 设置为“false”。如果所有这些都失败了,您应该按照这篇文章让应用服务团队调查您的案例:github.com/projectkudu/kudu/wiki/… 所以,看起来它无法在插槽交换中幸存下来。我的部署过程是创建一个新插槽,部署到它,然后与 prod 交换。 啊,我明白了。我们知道应用服务的部署槽中的 MSI 存在问题,这可能解释了您在此处遇到的问题,我们正在研究解决此问题。【参考方案2】:我刚刚在尝试将 MSI 与 Function 应用程序一起使用时解决了这个问题,尽管我已经设置了环境变量。我尝试多次重启都没有成功。我最终做的是手动关闭该功能的 MSI,然后重新启用它。这并不理想,但它奏效了。
希望对你有帮助!
【讨论】:
【参考方案3】:我发现,如果您启用 MSI,然后换出插槽,则功能会随着插槽的变化而消失。您可以通过将其关闭再打开来重新启用它,但这会在 AD 中创建一个新身份,并且需要您重置密钥保管库的权限才能使其正常工作。
【讨论】:
【参考方案4】:在我的情况下,我忘记在 Key Vault 中添加应用程序的访问策略
【讨论】:
【参考方案5】:对于像我这样想知道如何启用MSI
的人。
我的场景:
我有一个App Service
已经部署并运行了很长时间。
此外,在 Azure DevOps
上,我将管道配置为 Auto-Swap 我的 Deployment Slots(暂存/生产)。突然,在正常推送之后,由于所描述的问题,生产开始失败。
所以,为了再次启用 MSI(我不知道为什么必须重新启用它,但我相信这只是一种解决方法,而不是解决方案,因为它应该仍然是首先启用)
转到您的应用服务。然后在 设置 --> 身份下。 检查状态:就我而言,它是关闭
我在下面附上了一张图片,以便于理解。
【讨论】:
【参考方案6】:通过访问策略启用身份并授予对 keyvault 中 azure 函数应用的访问权限。 您可以在平台功能选项卡中找到身份 这两个步骤对我有用
【讨论】:
【参考方案7】:刚刚打开ON 状态 就像@Sebastian Inones 显示的那样。 比为 KeyVault 添加访问策略,例如
问题解决了!!
【讨论】:
如果您能给我的答案投票,我将不胜感激。【参考方案8】:对于会遇到这些答案的人,我想分享我的经验。
我在运行 Azure Synapse 管道时遇到了这个问题。本质上,我将访问策略正确地添加到 KeyVault,并且我将 LinkedService 添加到指向我的 KeyVault 的 Azure Synapse。
如果我手动触发笔记本,它可以工作,但在管道中,它会失败。
最初,我使用了以下语句:
url = TokenLibrary.getSecret("mykeyvault", "ConnectionString")
然后我添加了链接服务的名称作为第三个参数,管道能够利用该链接服务来获取 Vault 的 MSI 令牌。
url = TokenLibrary.getSecret("mykeyvault", "ConnectionString", "AzureKeyVaultLinkedServiceName")
【讨论】:
以上是关于无法使用应用服务上的 Azure MSI 访问 Key Vault的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 MSI 而不是 Service Principal 来调用部署在 Azure 上的 Authenticate web api
带有 AdlsClient 的 Azure MSI:访问令牌已过期
使用 MSI 从 Azure 函数将文件写入 Azure Data Lake 时出错
“用户''登录失败。”使用 EF 代码优先实现通过 MSI 访问 Azure SQL DB 时出现 SqlException