我正在尝试使用ASPNet 4.6.2 Web应用程序中的服务身份从Azure Key Vault检索机密。我正在使用此article中概述的代码。在本地,一切正常,尽管这是因为它使用了我的身份。将应用程序部署到Azure时,调用keyVaultClient.GetSecretAsync(keyUrl)
时会出现异常。
据我所知,一切均已正确配置。我创建了一个用户分配的身份,以便可以重复使用该身份,并确保该身份具有对KeyVault策略中的机密和密钥的访问权限。
例外是AzureServiceTokenProviderException
。它很冗长,概述了它如何尝试四种方法进行身份验证。我关心的信息是它尝试使用托管服务标识的时间:
试图使用托管服务身份获取令牌。访问令牌可以 不被收购。 MSI ResponseCode:BadRequest,响应:
我检查了应用程序的见解,发现它试图建立以下连接,并显示400结果错误:
http://127.0.0.1:41340/MSI/token/?resource=https://vault.azure.net&api-version=2017-09-01
对此有两件事很有趣:
目前我不知道该怎么办。在线示例都使它看起来像魔术,但是如果我对问题的根源是正确的,那么有些模糊的自动设置需要修复。
为完整起见,这是我所有相关的代码:
public class ServiceIdentityKeyVaultUtil : IDisposable
{
private readonly AzureServiceTokenProvider azureServiceTokenProvider;
private readonly Uri baseSecretsUri;
private readonly KeyVaultClient keyVaultClient;
public ServiceIdentityKeyVaultUtil(string baseKeyVaultUrl)
{
baseSecretsUri = new Uri(new Uri(baseKeyVaultUrl, UriKind.Absolute), "secrets/");
azureServiceTokenProvider = new AzureServiceTokenProvider();
keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
}
public async Task<string> GetSecretAsync(string key, CancellationToken cancellationToken = new CancellationToken())
{
var keyUrl = new Uri(baseSecretsUri, key).ToString();
try
{
var secret = await keyVaultClient.GetSecretAsync(keyUrl, cancellationToken);
return secret.Value;
}
catch (Exception ex)
{
/** rethrows error with extra details */
}
}
/** IDisposable support */
}
更新#2 (我删除了更新#1)
我创建了一个全新的应用程序或新的服务实例,并能够重新创建该错误。 但是,在所有情况下,我都使用了用户分配的身份。如果我删除它并使用系统分配的身份,那么它将正常工作。
我不知道为什么这些会有所不同。任何人都有见识,我希望用户分配一个见识。
答案 0 :(得分:1)
用户分配的身份的主要区别之一是可以将其分配给多个服务。它作为蔚蓝中的单独资产存在,而系统标识绑定到与其配对的服务的生命周期。
直接在Azure服务实例上启用系统分配的托管身份。启用身份后,Azure会在Azure AD租户中为实例创建一个实例的身份,该实例受实例的预订信任。创建身份后,将凭据提供给实例。系统分配的身份的生命周期直接与启用该身份的Azure服务实例相关。如果实例被删除,Azure会自动清除Azure AD中的凭据和身份。
用户分配的托管身份被创建为独立的Azure资源。通过创建过程,Azure在Azure AD租户中创建一个使用中的订阅信任的身份。创建身份后,可以将身份分配给一个或多个Azure服务实例。用户分配的身份的生命周期与为其分配到的Azure服务实例的生命周期是分开管理的。
用户分配的身份仍在App Services的预览中。请参阅文档here。它可能仍处于私人预览中(即Microsoft必须在您的订阅中显式启用它),它可能在您选择的区域中不可用,或者可能是缺陷。
答案 1 :(得分:1)
要使用用户分配的身份,获取令牌的HTTP调用必须包含身份的ID。 否则,它将尝试使用系统分配的身份。
为什么要尝试连接到本地主机地址?这似乎是错误的。
因为MSI终结点在App Service本地,所以只能从实例内部访问。
这是不是因为没有对resource参数进行转义而取回400?
是的,但是我不认为这是原因。
在MsiAccessTokenProvider源中,仅当设置了环境变量MSI_ENDPOINT和MSI_SECRET时,才使用该地址形式。它们没有在应用程序设置中设置,但是当我输出环境变量时,我可以在调试控制台中看到它们。
这些是由App Service隐形添加的,未添加到应用设置中。
关于如何使用用户分配的身份, 我看不到使用AppAuthentication库执行此操作的方法。 您可以在Azure:https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http中手动进行HTTP调用。 然后,您就可以自己缓存了! 托管身份端点不能一次处理很多查询:)