前言

以前就写过很多篇了

ASP.NET Core – Configuration & Options

Asp.net core 学习笔记 ( Azure key-vault )

Asp.net core 学习笔记 Secret 和 Data Protect Azure key-vault & Storage Account 第 2 篇

Azure 入门系列 (第四篇 Key Vault)

这篇作为最新最完整的版本呗.

参考

Docs – Safe storage of app secrets in development in ASP.NET Core

Docs –  Azure Key Vault configuration provider in ASP.NET Core

What & Why User Secrets?

一个项目里, 许多地方都会用到密码. 比如链接 SQL Server, SMTP, 还有各种 third party app client id & secret.

密码属于敏感信息, 只能个人或公司团队知道, 不可以外泄到其它地方.

早年, 大家都在本机上做开发, 公司团队则有自己的域网和服务器. 所以密码外泄是很难发生的.

可如今, 已经很少公司自己搞 version control 这些了. 大家都用 Github / Azure DevOps 等平台的 cloud service.

于是, 大家就开始关注如何确保密码不外泄了.

User Secrets 就是用来解决这些问题的. User Secrets 会确保密码只会保存在本机上, 不会被发布到 Github / Azure DevOps 上去.

只有每个开发人员的机子上才保存了密码. 这样就确保了密码不外泄.

而它在做到这些事情的同时并不会增加开发者的负担. 这点, ASP.NET Core 还是封装的很不错的.

User Secrets Get Started (WebApp)

创建项目

dotnet new webapp -o UserSecretsWebApp

添加账户密码到 appsettings.json

{
"Account": {
"Username": "Derrick",
"Password": "secret"
}
}

在 program.cs 读取  Account.Password

var builder = WebApplication.CreateBuilder(args);
var password = builder.Configuration.GetValue<string>("Account:Password");
Console.WriteLine(password); // secret

目前拿到的密码就是 appsettings.json 定义的 "secret", 现在我们加入 User Secrets

dotnet user-secrets init
dotnet user-secrets set "Account:Password" "my real password"

第一句是初始化, 第二句是添加 key value.

注意, key path 的分隔符是分号 : 而不是点 . 哦.

再次运行

dotnet run

password 从原本的 "secret" 换成了 "my real password"

几个重点

1.ASP.NET Core 的 User Secrets 通常是搭配 appsettings.json 和 Configuration 一起使用的.

2.常见的操作有: 初始化, 添加/更新, 列出, 删除

dotnet user-secrets init
dotnet user-secrets set "Account:Password" "my real password"
dotnet user-secrets list
dotnet user-secrets remove "Account:Password"

3. 所有 secret 会被保存到一个 json file, Windows 下的路径是

%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json

4. 通过 Visual Studio 可以直接打开 json file 修改

User Secrets Get Started (Console)

var builder = WebApplication.CreateBuilder(args);

CreateBuilder 封装了太多细节. 我们来一个比较底层的接口, 看看它是如果工作的.

创建 Console 和 add package

dotnet new console -o UserSecretsConsole
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.FileExtensions
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
dotnet add package Microsoft.Extensions.Configuration.Binder

program.cs

using System.Reflection;
using Microsoft.Extensions.Configuration; // 创建 config builder
// 链接 appsettings.json
var configurationBuilder = new ConfigurationManager()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.Development.json", optional: true, reloadOnChange: true); if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
{
// 链接 User Secrets
configurationBuilder = configurationBuilder.AddUserSecrets(Assembly.GetExecutingAssembly());
} // 这里相等于 WebApp 的 builder.Configuration 了
var configuration = configurationBuilder.Build();
var password = configuration.GetValue<string>("Account:Password"); // my real password
Console.WriteLine(password);

AddUserSecrets 就是它偷龙转风的地方了.

查看源码 dotnet/runtime 里的 UserSecretsConfigurationExtensions.cs

会发现它并没有什么神奇的地方, 它也是通过 .AddJsonFile 把 secrets.json 覆盖到 configuration 里而已.

User Secrets with Azure Key Vault (Azure-hosted)

What & Why?

上面讲的都是在开发阶段如何保护密码. 那到了 Production 阶段呢?密码和程序是否应该放在一块?

显然, 分开是比较好的, 至少不要让 hacker 一次过拿完所有东西嘛.

User Secrets 把密码存到了 json file, 那在 VM (Virtual Machine Web Server), 我们也可以把密码 (json file 概念) 放到另一台机子上 (不要和程序的 VM 同一台)

这就是 Azure Key Vault 的工作了. Azure Key Vault 是微软的 Cloud Service. 就是提供一个密码保险箱. 它可以管理 Secret, Key, Certificate 等等. 这里我们主要关注 Secret 就好.

Create Azure Key Vault

首先我们需要有 Microsoft Azure 账号, 然后安装 Azure CLI (MSI)

安装好后开启 Windows PowerShell, 输入

az login

它会开启游览器然后登入 Azure 账号。

有时候可能会需要指定 TENANT_ID,像这样

az login --tenant 12312312-1233-1233-1233-123123123123

TENANT_ID 可以去 Azure Portal search "Azure Active Directory" 就会看见了,或者问 ChatGPT。

接着创建 resource group

az group create --name "TestKeyVault-RG" --location "SoutheastAsia"

如果已经有其它 Resource Group 也可以用 existing 的.

接着创建 Key Vault

az keyvault create --name "First-KV" --resource-group "TestKeyVault-RG" --location "Southeast Asia"

然后给予 user 权限

先找出 user Object ID

az ad user list --output table

这句会 list out 全部的 users。UserPrincipalName 是 user 的 email address,抄下来。

然后

az ad user show --id "user email address"

这句会显示 user 的 information,其中的 id 就是我们需要的 Object ID,抄下来。

然后

az keyvault show --name "First-KV"

把 id 抄下来

接着添加权限

az role assignment create --assignee "Object ID" --role "Key Vault Administrator" --scope "key-vault-id"

这样就有添加 secret 的权限了。

然后添加 secret

az keyvault secret set --vault-name "First-KV" --name "Account-Password" --value "my read password"

注: name 是 Account-Password 分隔符是 hyphen -, 因为 Azure 不支持分号 : 所以...什么鬼嘛...超麻烦的...

另外,我们的项目要访问 secret 也需要权限,用回上面的方法。(注:如果你的程序不是 host 在 Azure VM 那要用另外一招, 下面会教)

获取 VM 的 Object ID

az vm show --ids /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName} --query 'identity.principalId'

里面 3 个 parameters 分别是 subscriptionId, resourceGroupName, vmName

获取 subscriptionId 的方式是

az account show --query 'id' -o tsv

如果拿不到就省略掉 --query,直接

az account show

里面的 id 就是 subscriptionId,然后

az role assignment create --assignee "Object ID" --role "Key Vault Administrator" --scope "key-vault-id"

好了,搞定!

想知道更多 Azure CLI command 可以参考 Docs – az keyvault 或者问 ChatGPT 会更快.

Connect with Azure Key Vault

add package

dotnet add package Azure.Identity
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets

program.cs

var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsProduction())
{
builder.Configuration.AddAzureKeyVault(
new Uri("https://first-kv.vault.azure.net/"),
new DefaultAzureCredential(),
new HyphenKeyVaultSecretManager()
);
var password = builder.Configuration.GetValue<string>("Account:Password"); // my read password
}

通过 AddAzureKeyVault 让 Azure Key Vault 关联进来.

获取 URI 的方式是 (其实也可以按照命名规范自己推断出来)

az keyvault show --name "First-KV" --query "properties.vaultUri"

class HyphenKeyVaultSecretManager 的作用是把 Azure Key Vault 的 hyphen - 换成分号 : (上面有提到...超麻烦的...)

public class HyphenKeyVaultSecretManager : KeyVaultSecretManager
{
public override string GetKey(KeyVaultSecret secret)
{
return secret.Name.Replace("-", ConfigurationPath.KeyDelimiter);
}
}

至此, 只要我们的程序是 host 在 Azure VM (和 Key Vault 相同 resource group) 那么它们就可以链接到了.

注: 或许你会发现本地测试也可以跑起来, 那是因为 Azure CLI login 了, 同时我们用相同 account create 了 Key Vault.

一旦 az logout 本地就无法访问了.

User Secrets with Azure Key Vault (non-Azure-hosted)

如果我们的程序不是运行在 Azure VM / App 的话, 过程会繁琐一些.

参考: Docs – Use Application ID and X.509 certificate for non-Azure-hosted apps

创建 Azure App Registration (AKA Client App)

首先我们需要搞一个 Client App, 它们的关系是 : 我们的程序 connect to Client App 然后由  Client App 去访问 Azure Key Vault.

az ad app create --display-name AzureKeyVault-AR

Add access policy for Client App

像上面我们授权给 VM 那样, Azure Key Vault 也需要授权给 Client App

az keyvault set-policy --name "First-KV" --secret-permissions get list --object-id "9e60491d-5161-43e2-b409-a580124944b8"

注意, 这里的 object-id 其实是放 application id 的值.

通过 az ad app 可以查看 Client App 的 application id 和 object id

az ad app list --display-name "AzureKeyVault-AR" --query "[].{id:id, appId:appId}" --output tsv

id 是 object id, appId 是 application id (AKA client id), 而 set-policy 的参数虽然叫 object-id 但正确的输入是放 application id 值哦, 它乱来, 我们可不要被误导哦.

Add certificate to Client App

早年 Azure 只是提供一个 Client Secret (AKA password), 但后来因为不够安全所以改成用 certificate 做非对称加密和签名.

具体怎样创建 certificate 可以看之前我写的 ASP.NET Core – Work with X509

创建 .pfx 和 .cer

using var algorithm = RSA.Create(keySizeInBits: 2048);
var subject = new X500DistinguishedName($"CN=AzureKeyVault"); // 名字顺便, 因为是 self-signed
var request = new CertificateRequest(subject, algorithm, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
var certificate = request.CreateSelfSigned(
notBefore: DateTimeOffset.UtcNow,
notAfter: DateTimeOffset.UtcNow.AddYears(2)
);
var pfxBytes = certificate.Export(X509ContentType.Pfx, "my password");
var certBytes = certificate.Export(X509ContentType.Cert);
File.WriteAllBytes(Directory.GetCurrentDirectory() + "\\AzureKeyVault.pfx", pfxBytes);
File.WriteAllBytes(Directory.GetCurrentDirectory() + "\\AzureKeyVault.cer", certBytes);

.pfx 是给程序用的 .cer 是给 Azure Client App 用的.

upload .cer to Client App

az ad app credential upload --id "9e60491d-5161-43e2-b409-a580124944b8" --cert "@C:\keatkeat\my-projects\asp.net core\7.0\Secret\UserSecretsWebApp\AzureKeyVault.cer"

参数 --id 同样是指 application id 而不是 object id 哦.

Connect to Client App and Key Vault

var builder = WebApplication.CreateBuilder(args);

// read certificate from file
var rowData = File.ReadAllBytes(Directory.GetCurrentDirectory() + "\\AzureKeyVault.pfx");
var certificate = new X509Certificate2(rowData, "my password"); // connect to Client App and Key Vault
builder.Configuration.AddAzureKeyVault(
new Uri("https://stgtestkeyvault-kv.vault.azure.net/"),
new ClientCertificateCredential(
tenantId: "30609328-e0b1-8cb0-974d-117ee17e02b5",
clientId: "9e60491d-5161-43e2-b409-a580124944b8",
certificate
),
new HyphenKeyVaultSecretManager()
);
var password = builder.Configuration.GetValue<string>("Account:Password"); // my read password
Console.WriteLine(password); // my read password

1. 其实 certificate 应该要放在 store 里面的, 但因为 IIS read store 经常有权限问题, 这里只是为了演示而已, 所以我直接 read from file 就好了.

2. 获取 tenantId

az account show --query tenantId -o tsv

ASP.NET Core – User Secrets & Azure Key Vault的更多相关文章

  1. 【Azure 环境】Azure Key Vault (密钥保管库)中所保管的Keys, Secrets,Certificates是否可以实现数据粒度的权限控制呢?

    问题描述 Key Vault (密钥保管库) 能不能针对用户授权实现指定用户只能访问某个或某些特定的key? 如当前有两个用户(User1, User2),在Key Vault中有10个Key,Use ...

  2. 如何在ASP.NET Core中使用Azure Service Bus Queue

    原文:USING AZURE SERVICE BUS QUEUES WITH ASP.NET CORE SERVICES 作者:damienbod 译文:如何在ASP.NET Core中使用Azure ...

  3. 【Azure Developer】Python代码通过AAD认证访问微软Azure密钥保管库(Azure Key Vault)中机密信息(Secret)

    关键字说明 什么是 Azure Active Directory?Azure Active Directory(Azure AD, AAD) 是 Microsoft 的基于云的标识和访问管理服务,可帮 ...

  4. Azure Key Vault(二)- 入门简介

    一,引言 在介绍 Azure Key Vault 之前,先简单介绍一下 HSM(硬件安全模块). -------------------- 我是分割线 -------------------- 1,什 ...

  5. Azure Key Vault (3) 在Azure Windows VM里使用Key Vaule

    <Windows Azure Platform 系列文章目录> 本章我们介绍如何在Azure Windows VM里面,使用.NET使用Azure Key Vault 我们需要对Key V ...

  6. Azure Key Vault (2) 使用Azure Portal创建和查看Azure Key Vault

    <Windows Azure Platform 系列文章目录> 请注意: 文本仅简单介绍如何在Azure Portal创建和创建Key Vault,如果需要结合Application做二次 ...

  7. 【Azure Developer】解决Azure Key Vault管理Storage的示例代码在中国区Azure遇见的各种认证/授权问题 - C# Example Code

    问题描述 使用Azure密钥保管库(Key Vault)来托管存储账号(Storage Account)密钥的示例中,从Github中下载的示例代码在中国区Azure运行时候会遇见各种认证和授权问题, ...

  8. 【Azure Developer - 密钥保管库 】使用 Python Azure SDK 实现从 Azure Key Vault Certificate 中下载证书(PEM文件)

    问题描述 在Azure Key Vault中,我们可以从Azure门户中下载证书PEM文件到本地. 可以通过OpenSSL把PFX文件转换到PEM文件.然后用TXT方式查看内容,操作步骤如下图: Op ...

  9. 【Azure Developer】记录一次使用Java Azure Key Vault Secret示例代码生成的Jar包,单独运行出现 no main manifest attribute, in target/demo-1.0-SNAPSHOT.jar 错误消息

    问题描述 创建一个Java Console程序,用于使用Azure Key Vault Secret.在VS Code中能正常Debug,但是通过mvn clean package打包为jar文件后, ...

  10. 如何在ASP.NET Core中自定义Azure Storage File Provider

    文章标题:如何在ASP.NET Core中自定义Azure Storage File Provider 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p ...

随机推荐

  1. 介绍几款强大实用的 IDEA 插件,助力大家开发【工欲善其事必先利其器】

    俗话说:"工欲善其事必先利其器",本问介绍几款强大实用的 IDEA 插件,助力大家开发. 希望大家做一个聪明又努力的人,而不只是一个努力的人. Alibaba Java Codin ...

  2. 使用GSAP制作动画视频

    GSAP 3Blue1Brown给我留下了深刻印象.利用动画制作视频,内容简洁,演示清晰.前两天刚好碰到一件事,我就顺便学习了一下怎么用代码做动画. 以javascrip为例,有两个动画引擎,GSAP ...

  3. <script> 和 <script setup> 的一些主要差别

    <script setup> 是 Vue 3 中的新特性,它是一种简化和更具声明性的语法,用于编写组件的逻辑部分.相比之下,<script> 是 Vue 2 中常用的编写组件逻 ...

  4. 技术文档必备工具:注释目录树神器 Annotree,我的第一个正式开源项目

    hi,大家好,我是爱听书的程序员阿超 非常开心能在这里介绍我的第一个正式开源项目 Annotree,项目具体情况如下,请继续阅读~ Annotree 注释树 一款生成带注释的目录树工具,大大方便技术文 ...

  5. typora下载安装以及notepad++下载安装

    notepad++下载安装 找到浏览器输入:notepad或者 https://notepad-plus-plus.org/downloads/ 官网下载即可使用 如果官网崩了,可以在微信公众号:A软 ...

  6. 云端IDE如何重定义开发体验

    豆包 MarsCode 是一个集成了AI功能的编程助手和云端IDE,旨在提高开发效率和质量.它支持多种编程语言和IDE,提供智能代码补全.代码解释.单元测试生成和问题修复等功能,同时具备AI对话视图和 ...

  7. [WPF] 脱机环境实现支持拼音模糊搜索的AutoCompleteBox

    AutoCompleteBox是一个常见的提高输入效率的组件,很多WPF的第三方控件库都提供了这个组件,但基本都是字符串的子串匹配,不支持拼音模糊匹配,例如无法通过输入ldh或liudehua匹配到刘 ...

  8. 文件系统(十一):Linux Squashfs只读文件系统介绍

    liwen01 2024.07.21 前言 嵌入式Linux系统中,squashfs文件系统使用非常广泛.它主要的特性是只读,文件压缩比例高.对于flash空间紧张的系统,可以将一些不需要修改的资源打 ...

  9. 虚拟硬盘系统 —— Windows系统 磁盘加速软件 —— 优缺点以及与真实物理磁盘访问文件的区别

    在家里的局域网搞了一个NAS,但是由于磁盘读存速率问题导致远程copy的速度只有15MB/s,而如果NAS中的文件已在内存中有缓存则远程copy的速度为50MB/s. 于是考虑利用内存建立虚拟硬盘: ...

  10. 暑假Java自学进度总结05

    一.今日所学: 1.if的第一个表达式: if(关系表达式){ 语句: } 执行流程: 1>首先执行关系表达式的值 2>如果关系表达式的值为true则执行语句,否则不执行 3>继续执 ...