Azure Key Vault支持“复合身份”来控制访问(https://docs.microsoft.com/en-us/azure/key-vault/general/secure-your-key-vault),但是有没有人有使用复合身份在.NET中执行身份验证的经验?
使用本地应用程序从桌面运行时,我认为身份验证将涉及到这两个方面:
身份验证工作流将是什么样?有可用的例子吗?我们可以通过使用MSAL来实现吗?
假设我们已经创建了一个Azure密钥保管库,并且在该保管库中保存了一些机密。如何在Windows 10下运行的桌面应用程序中实现以下功能:
换句话说,我希望可以通过两种身份验证的组合来访问密钥库资源
答案 0 :(得分:1)
我要回答我的问题。简短的答案是使用
IConfidentialClientApplication.AcquireTokenOnBehalfOf(
IEnumerable<string> scopes,
UserAssertion userAssertion);
以交互方式获取的用户令牌可以用作UserAssertion。
长版,因为我是新手,所以我将详细介绍我发现的所有细节。事实证明,这里到处都是创建一个完整的可运行.net应用程序的地方,所以并不是所有事情都与我的问题直接相关。
平台:移动和桌面应用程序
安装证书或其他内容:我们将在此演示中使用秘密。
重定向URI:在Mobile and desktop application
部分下添加一个新的URI,并将其设置为http://127.0.0.1
如果作为控制台应用程序运行,则没有与运行的应用程序直接关联的窗口,因此执行用户登录的最简单方法是使用系统默认的Web浏览器应用程序。因此,消耗返回的代码的唯一方法是使用Redir URL,即“ http:// localhost”或“ http://127.0.0.1”,也称为回送URL。在运行时,MSAL将使用动态端口作为本地Web服务器,以捕获来自Web浏览器的redir URL调用。由于它在本地运行,因此,除非有一个通过使用DNS或主机文件劫持了“本地主机”的主机,否则都允许使用http://或https://。
在“公开API”部分中设置API,并添加范围。
在“代表代理”工作流程中,用户使用应用程序提供的范围登录,而不是直接访问密钥库资源。我们需要“设置”应用程序ID URI,并至少创建一个范围以供交互式登录使用。
创建密钥库。
在“访问策略”中,添加新的访问策略。
要创建复合身份,请为Seelct principal
选择一个有效的用户或组帐户,然后选择我们在上一步中为Authorized application
创建的同一应用。
创建一个.NET Core控制台应用程序。添加以下nuget程序包
<PackageReference Include="Microsoft.Identity.Client" Version="4.18.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.8" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.5" />
这是使用复合身份访问密钥库的代码
const string AppClientId = "[Enter_your_Application_(client)_ID";
const string AppClientSecret = "[Enter_your_Application_(secret)";
const string TenantId = "[Enter_your_tenantId]";
const string KeyVaultBaseUri = "https://[your_keyvault_name].vault.azure.net/";
// In on-behalf-of flow, the following scope needs to be consented when acquiring the user token. Otherwise, the app cannot access the key vault on-behalf-of user.
const string KeyVaultUserImScope = "https://vault.azure.net/user_impersonation";
// In on-behalf-of flow, the following scope is used to access key vault data when acquiring client token
const string KeyVaultScope = "https://vault.azure.net/.default";
// An "Exposed API" in app registration is required when using on-behalf-of flow.
const string AppClientScope = "[Enter_your_Application_ID_URI]/[Enter_Your_Scope_Name]";
const string Instance = "https://login.microsoftonline.com/";
Console.WriteLine("Acquire User token");
var pubClient = PublicClientApplicationBuilder.Create(AppClientId)
.WithAuthority($"{Instance}{TenantId}")
.WithRedirectUri("http://localhost") // Make sure the "http://localhost" is added and selected as the app Redirect URI
.Build();
var userResult= pubClient
.AcquireTokenInteractive(new[] {AppClientScope })
.WithExtraScopesToConsent(new [] {KeyVaultUserImScope})
.WithPrompt(Prompt.Consent)
.ExecuteAsync().Result;
// In normal case, when user token is directly given from outside, we should validate if the user Result has consented to the required customized scope AppClientScope before proceeded with next steps. Here we will ignore this step.
Console.WriteLine("Acquire Client token");
// The following two steps are equivalent to https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#middle-tier-access-token-request
var conClient = ConfidentialClientApplicationBuilder.Create(AppClientId)
.WithAuthority($"{Instance}{TenantId}")
.WithClientSecret(AppClientSecret)
.Build();
var OboResult= conClient.AcquireTokenOnBehalfOf(
new[] {KeyVaultScope},
new UserAssertion(userReult.AccessToken))
.ExecuteAsync().Result;
Console.WriteLine("Access Key Vault");
var kc = new KeyVaultCredential((authority, resource, scope) =>
{
Console.WriteLine($"Authority: {authority}, Resource: {resource}, Scope: {scope}");
return Task.FromResult(OboResult.AccessToken);
});
var kvClient = new KeyVaultClient(kc);
var secretBundle = await kvClient.GetSecretAsync(KeyVaultBaseUri, SecretName);
Console.WriteLine("Secret:" + secretBundle.Value);
如果我们不使用复合身份,则可以使用Azure.Security.KeyVault.Secrets.SecretClient
通过以下方法之一访问密钥库数据
// For access policy assigned to confidential application
var client = new SecretClient(new Uri(KeyVaultBaseUri),
new ClientSecretCredential(TenantId, AppClientId, AppClientSecret));
var secretBundle = await client.GetSecretAsync(SecretName);
Console.WriteLine("Secret:" + secretBundle.Value.Value);
和
// For access policy assigned to User or Group account
var client = new SecretClient(new Uri(KeyVaultBaseUri), new InteractiveBrowserCredential());
var secretBundle = await client.GetSecretAsync(SecretName);
Console.WriteLine("Secret:" + secretBundle.Value.Value);
答案 1 :(得分:0)
实际上,如果您授予访问权限,例如秘密,它不允许用户查看Azure Portal中的密钥保管库。 如果他们没有对Azure RBAC中的资源的读取权限,则无法查看。 因此,您应该能够为用户添加访问权限,并代表用户直接从应用程序中调用它。
另一种方法是使用后端来检查用户ID并访问Key Vault(而不是用户)。
这里,您只需要允许后端应用访问Key Vault本身即可。