65.9K
CodeProject 正在变化。 阅读更多。
Home

通过 .NET Core 访问 AWS Secrets Manager

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2019年3月11日

CPOL

3分钟阅读

viewsIcon

28136

downloadIcon

595

本文将帮助您实现将敏感数据存储在亚马逊 Secrets Manager 中并在启动应用程序时访问该功能。

引言

我正在我的项目中使用 application.json 存储密钥。但是,当我看到 AWS Secrets Manager 时,它看起来很安全,并且易于在我的系统中实现。

  • 这将有助于在安全位置存储密钥,如连接字符串路径。
  • 这些值总是被加密的,因此未经授权无法访问它们
  • 您无需在值被修改的情况下部署应用程序。
  • 非常容易更改值。
  • 实现简单且非常快速。

本文将帮助您实现一个基本原型,您可以在其中从 Secrets Manager 访问项目的密钥。代码将逐步向您解释我们能做什么以及如何做到这一点。

本文使用 .NET Core 2.2 来实现此功能。

安全密钥存储管理

  1. AWS Secrets Manager 使用您拥有并存储在 AWS Key Management Service (KMS) 中的加密密钥来静态加密密钥。
  2. 当您检索密钥时,Secrets Manager 会解密该密钥,并通过 TLS 将其安全地传输到您的本地环境。
  3. 默认情况下,Secrets Manager 不会将密钥写入或缓存到持久性存储中。您可以使用细粒度的 AWS Identity and Access Management (IAM) 策略来控制对密钥的访问。

审核和监控密钥使用情况

  1. 已更改或修改的密钥受版本控制。
  2. 您可以跟踪哪个密钥被更改以及何时被修改。
  3. 我们可以为密钥设置云观察日志记录,这将提供有关密钥版本控制的详细信息。

自动密钥轮换

  1. 使用 AWS Secrets Manager,您可以通过使用 Secrets Manager 控制台、AWS SDK 定期或按需轮换密钥
  2. 您还可以通过修改示例 Lambda 函数来扩展此功能以轮换其他密钥。例如,您可以轮换用于授权应用程序的 OAuth 刷新令牌或用于本地托管的 MySQL 数据库的密码。
  3. 所有这些都可以通过 AWS 提供的 Secrets Manager API 来完成。

Using the Code

我创建了一个微服务,它只做一件事,从 AWS 检索数据并将密钥以字符串格式提供。该服务包含从 Amazon Secrets manager 请求数据并以 json 格式返回的完整实现

项目先决条件

  1. Amazon Webservice 提供的 AWSSD.Core
  2. Amazon Seb Services 提供的 AWSSDK.SecretsManager
  3. Microsoft.AspNetCore.App
  4. Microsoft.NETCore.App
  5. Swashbuckle.AspNetCore (这是用于 swagger 的)

首先,对于我们的 Core API,我们需要通过 Rest 端点 API 输入。由于我们正在将其创建为 API,您可以发送详细信息和密钥。为了做到这一点,让我们创建一个模型,可以在其中使用它。

/// This is a class which will give us all the information for extracting the data 
  public class SecretsDetail
    {
        public string Region { get; set; }       // The region you deployed your secrets 
        public string SecretName { get; set; }   // The secret name to access the secret 
        public string AccessKeyID { get; set; }  // access id created for the secret authorization
        public string SecretKey { get; set; }    // key for authorization
        public string VersionStage { get; set; } // Which version you want to access 
        public string ServiceURL { get; set; }   // the path of the endpoint
    }

一旦我们的模型准备就绪,我们就可以在控制器中使用该模型,它将传递给 GetSecretManager 类。当我们拥有所有用于 AWS 通信的详细信息时,我们就可以构建对象了。在下面的代码块中,我们使用 AmazaonSecretsManagerConfig 构建 Secrets Manager 的端点信息。

AmazonSecretManagerClient 将接受参数,如 AccessID SecretKeyconfig。如果您在网络中或在 EC2 实例上工作,则无需提供配置。您只需传递 secretName 和访问 ID 以及 secretKey 即可。但在亚马逊网络之外,您需要下面使用的所有详细信息

// Get the Secret name 
string secretName = secretsDetail.SecretName;
//Assign the region. 
string region = secretsDetail.Region;
            string secret = "";

    MemoryStream memoryStream = new MemoryStream();
    AmazonSecretsManagerConfig amazonSecretsManagerConfig = new AmazonSecretsManagerConfig();
    amazonSecretsManagerConfig.ServiceURL = secretsDetail.ServiceURL;
            
   IAmazonSecretsManager client = new AmazonSecretsManagerClient
        (secretsDetail.AccessKeyID, secretsDetail.SecretKey, amazonSecretsManagerConfig);

   GetSecretValueRequest request = new GetSecretValueRequest();
   request.SecretId = secretName;
   request.VersionStage = secretsDetail.VersionStage == null ? 
     "AWSCURRENT" : secretsDetail.VersionStage; // VersionStage defaults to AWSCURRENT if unspecified.
   GetSecretValueResponse response = null;
   This code block will build the client get the response back. 

AmazonSecretsManagerConfig 将获取端点信息。这将有助于从 SecretManagerClient 获取值。 AccessKeyIDSecretKey 将为您提供 Response 的详细信息。

以下代码将从内存流中提取数据,并为我们提供纯 string,我们可以将其转换为 Json 格式。

         try
            {
                response = client.GetSecretValueAsync(request).Result;
            } catch (DecryptionFailureException)
            {
                // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
                // Deal with the exception here, and/or rethrow at your discretion
                throw;
            }
            
           if (response.SecretString != null)
            {
                return secret = response.SecretString;
            }
            else
            {
                memoryStream = response.SecretBinary;
                StreamReader reader = new StreamReader(memoryStream);
                string decodedBinarySecret = System.Text.Encoding.UTF8.GetString
                                             (Convert.FromBase64String(reader.ReadToEnd()));
                return decodedBinarySecret;
            }

Swagger 测试

结果

附带的源代码将提供有关其构建方式的所有详细信息。如果您需要更多说明,请随时写评论。

注释

  1. 代码已启动并运行。您只需要传递正确的值,它就会给出数据。
  2. 您可以使用配置好的 swagger 来测试代码。
  3. 如果您遇到任何挑战或任何错误,请在评论中提及。

历史

  • 2019年3月11日:初始版本
© . All rights reserved.