如何:在本地 Azure VM 上托管的 ASP.NET Core 站点中实现 Azure Key Vault
在本地 Azure VM 上托管的 ASP.NET Core 站点中的 Azure Key Vault 实现
引言
在 ASP.NET core 站点中实现 Azure Key Vault,该站点托管在本地 Azure VM 上。
本文涵盖了密钥库在应用程序设计、架构和开发中的实现方式。云配置以消耗密钥库不在本文的讨论范围内,但是为了在本地 Web 应用程序设置中消耗密钥库,提供了所需的基本信息作为预备条件。
背景
当需要密钥库来存储客户端密钥、云中主机 VM 的凭据,特别是 Azure 时。
预备条件
- 按照 https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal 创建 Azure Key Vault
- 确保密钥库创建在相同的 vnet 中,以便无需任何问题即可进行通信。对于位于任何其他 vnet 中的密钥库(出于安全考虑),请确保您添加/允许这些网络或任何防火墙设置以访问密钥库,如以下密钥库设置所示
- 如果您不确定所需的设置,请与您的内部云网络工程师沟通以使其正常运行。
- 将网站在 AAD 区域的应用程序注册中注册的服务主体添加到密钥库的访问策略。
- 同样,将托管网站的 VM 添加到密钥库的访问策略(VM 应该是系统标识,在 VM 的身份设置中启用它)。
- 所有 2.1 之后的最新 .NET Core 项目都内置了 Azure Key Vault 包。
Using the Code
在 ASP.NET Core Program.cs 文件中实现密钥库的代码
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var builder = config.Build();
var keyVaultEndpoint = builder["KeyVault:Vault"];
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback)
);
config.AddAzureKeyVault(keyVaultEndpoint,keyVaultClient,
new DefaultKeyVaultSecretManager());
})
.UseStartup<Startup>()
.Build();
基于示例环境的 appSettings 文件,其中包含对例如 CRM、社交登录、自定义密码等的引用。
"KeyVault": {
"Vault": "https://nameofkeyvault.vault.azure.net/",
//"ClientId": "myclientid",
//"ClientSecret": "myclientsecret",
"Authentication": {
"Microsoft": {
"ApplicationId": "appidkey",
"Password": "nameofpasswordkeyvault"
},
"Google": {
"ClientId": "appidkey",
"ClientSecret": "nameofpasswordkeyvault"
},
"Facebook": {
"AppId": "appidkey",
"AppSecret": "nameofpasswordkeyvault"
},
"LinkedIn": {
"AppId": "appidkey",
"AppSecret": "nameofpasswordkeyvault"
}
},
"Xrm": {
"Configuration": {
"SVCEndpoint": "https://client.myblog.com:443/OnlineService.svc",
"ServiceUrl": "http://client.myblog.com/api/data/v8.0/",
"ClientId": "",
"Domain": "myblog.com",
"UserName": "crm",
"Password": "crm",
"IsWebAPIEndpoint": true,
"IsSVCEndpoint": true
}
}
}
- 通过 Startup.cs 或任何其他类(如果引用任何外部登录或任何其他依赖项,例如 API 等)访问密钥库值。
Startup.cs 的示例
//AUTHENTICATION
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => { options.LoginPath = "/Account/Login/"; })
.AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId =
Configuration["KeyVault:Authentication:Microsoft:ApplicationId"];
var password= Configuration["KeyVault:Authentication:Microsoft:Password"];
microsoftOptions.ClientSecret = Configuration[password];
})
.AddGoogle(googleOptions =>
{
googleOptions.ClientId = Configuration["KeyVault:Authentication:Google:ClientId"];
var clientSecret= Configuration["KeyVault:Authentication:Google:ClientSecret"];
googleOptions.ClientSecret = Configuration[clientSecret];
})
.AddFacebook(facebookOptions =>
{
facebookOptions.AppId = Configuration["KeyVault:Authentication:Facebook:AppId"];
var appSecret= Configuration["KeyVault:Authentication:Facebook:AppSecret"];
facebookOptions.AppSecret = Configuration[appSecret];
});
在任何控制器或任何类文件中,可以通过 IOptions
配置接口访问配置值。
通过构造函数注入在控制器中,如下所示
public class SampleController : Controller
{
#region Variables
private readonly IConfiguration _configuration;
#endregion #region constructors
public SampleController(IConfiguration configuration)
{
_configuration = configuration;
}
#Methods
public async Task<ActionResult> SampleMethod(string fileUri, string fileName)
{
try
{
if (User.Identity.IsAuthenticated)
{
//Get the email and load the person Identity
//var loggedInEmail = "###@i.com";
var vault = _configuration.GetSection
("KeyVault:Xrm: COnfiguration:UserName"); // Get the value
// from key vault config key in appsettings which
// gets from key vault.
}
}
catch (Exception ex)
{
ViewData["message"] = ex.Message;
View("~/Views/Shared/Error.cshtml");
}
return null;
}
已知问题
- 由于以下软件包升级需要,2.1 之后的项目会出现已知问题。
需要Microsoft.Azure.Services.AppAuthentication v1.3.1
,添加 nuget 并发布。 - 请添加此软件包并构建,发布到 VM 上的网站进行测试,如果出现任何问题,请在 web.config 中启用日志记录(
stdout ~ true
)