在 .NET 应用中读取数据库密码、API 密钥等敏感信息时,AWS Secrets Manager 是常见的选择。AWS SDK for .NET(NuGet 包 AWSSDK.SecretsManager)提供了两个核心类:AmazonSecretsManagerConfig 负责描述"怎么连",AmazonSecretsManagerClient 负责"真正去连"。本文介绍这两个类的作用和常见用法。
一、AmazonSecretsManagerConfig:客户端的配置容器
AmazonSecretsManagerConfig 位于 Amazon.SecretsManager 命名空间,继承自通用基类 Amazon.Runtime.ClientConfig。它本身不发起任何网络请求,只是保存一组设置,供客户端在创建时使用。
csharp
var config = new AmazonSecretsManagerConfig();
无参构造后所有属性都是默认值。如果不做任何设置,客户端会从环境变量 AWS_REGION 或 ~/.aws/config 中自动推断区域。实际使用中,最值得关注的是以下三个参数。
RegionEndpoint:连接哪个区域
AWS 服务按区域独立部署,在某个区域创建的密钥只能通过该区域的端点访问。RegionEndpoint 用来指定目标区域:
csharp
config.RegionEndpoint = RegionEndpoint.APNortheast1;
config.RegionEndpoint = RegionEndpoint.GetBySystemName("us-west-2"); // 便于从配置文件读取
设置后,SDK 会自动拼出服务地址(如 secretsmanager.ap-northeast-1.amazonaws.com),并用该区域进行请求签名。中国区(CNNorth1、CNNorthWest1)会自动切换到 .amazonaws.com.cn 域名。绝大多数场景只需设置这一项。
ServiceURL:直接指定服务地址
ServiceURL 绕过 SDK 的自动拼接,让请求直接发往指定地址。典型用途包括本地测试(如 LocalStack)、VPC 接口终端节点(流量不经公网)以及 FIPS 合规端点:
csharp
config.ServiceURL = "https://vpce-0abc123.secretsmanager.us-east-1.vpce.amazonaws.com";
config.AuthenticationRegion = "us-east-1";
需要注意,ServiceURL 与 RegionEndpoint 互斥,设置一个会清空另一个。使用 ServiceURL 时建议同时设置 AuthenticationRegion,以免出现签名错误。
ProxyHost:经过代理访问
在企业内网等无法直连外网的环境中,可以通过 ProxyHost 和 ProxyPort 让请求经由代理服务器转发:
csharp
config.ProxyHost = "proxy.company.com"; // 只写主机名,不带协议前缀
config.ProxyPort = 8080;
config.ProxyCredentials = new NetworkCredential("username", "password"); // 代理需要认证时
代理只改变请求经过的路径,不改变最终目的地,因此可以与 RegionEndpoint 或 ServiceURL 叠加使用。
此外,Timeout(请求超时)和 MaxErrorRetry(重试次数)也是常用的调优参数。
二、AmazonSecretsManagerClient:与服务通信的客户端
AmazonSecretsManagerClient 实现了 IAmazonSecretsManager 接口,负责签名、发送 HTTP 请求、自动重试以及解析响应。创建它需要两样东西:凭证(你是谁)和配置(连哪里)。
csharp
var client = new AmazonSecretsManagerClient(); // 全部使用默认值
var client = new AmazonSecretsManagerClient(RegionEndpoint.USEast1); // 只指定区域
var client = new AmazonSecretsManagerClient(config); // 传入完整配置
var client = new AmazonSecretsManagerClient(credentials, config); // 显式凭证 + 配置
未显式提供凭证时,SDK 会沿默认凭证链依次查找:环境变量、~/.aws/credentials 中的 profile、ECS 任务角色、EC2 实例 IAM 角色等。生产环境推荐使用 IAM 角色,避免在代码中硬编码访问密钥。
常用操作
客户端的每个方法都对应一个 Secrets Manager API,并遵循 XxxRequest / XxxResponse 的命名规律。最常用的是读取密钥:
csharp
var response = await client.GetSecretValueAsync(new GetSecretValueRequest
{
SecretId = "prod/myapp/db"
});
string secret = response.SecretString;
其他常见操作还有 CreateSecretAsync(创建)、PutSecretValueAsync(更新值)、ListSecretsAsync(列出)和 DeleteSecretAsync(删除)。调用失败时会抛出具体的异常类型,例如 ResourceNotFoundException 表示密钥不存在,DecryptionFailureException 表示 KMS 解密失败,可按类型分别处理。
使用要点
第一,客户端是线程安全的,内部维护连接池,应在整个应用中复用同一个实例,而不是每次请求都重新创建。
第二,客户端实现了 IDisposable。短生命周期程序可以用 using 管理;作为单例长期使用时,随应用一起释放即可。
第三,在 ASP.NET Core 中推荐通过依赖注入使用。安装 AWSSDK.Extensions.NETCore.Setup 后:
csharp
builder.Services.AddDefaultAWSOptions(builder.Configuration.GetAWSOptions());
builder.Services.AddAWSService<IAmazonSecretsManager>();
业务代码依赖 IAmazonSecretsManager 接口而非具体类,单元测试时便于替换为 mock 实现。
第四,对于读取频繁的场景,可以引入官方的 AWSSDK.SecretsManager.Caching 包。其中的 SecretsManagerCache 会在内存中缓存密钥并定期刷新,既降低延迟,也减少按调用次数计费的开销。
三、总结
两个类的分工可以概括为一条流程:Config 描述连接方式 → Client 建立通信能力 → Request 获取具体密钥 。日常开发中通常只需设置 RegionEndpoint;本地调试或走 VPC 私有链路时改用 ServiceURL;在受限网络中再叠加 ProxyHost。客户端方面,要点是依赖默认凭证链、复用单一实例、借助依赖注入解耦,并在高频读取时加上缓存。掌握这几点,就能在 .NET 应用中安全、高效地管理敏感配置。