是否可以在 .NET Core 应用程序中从 AWS Certificate Manager 检索证书并在 HttpClient post 中使用它?

Is it possible in a .NET Core application to retrieve a certificate from AWS Certificate Manager and use it in a HttpClient post?

我的 .Net 核心应用程序使用 HttpClient 向外部 Web 服务发出 post 请求。外部 Web 服务需要证书进行验证。

证书安装在 AWS 中,我有一个指向证书的 ARN。

是否可以通过编程方式从 AWS Certificate Manager 获取证书并在我的 HtppClient 中使用它,例如,这是我通常用来添加证书但我需要从 AWS 获取的代码。

   private HttpClientHandler HttpClientHandler()
   {
        var handler = new HttpClientHandler
        {
            ClientCertificateOptions = ClientCertificateOption.Manual,
            SslProtocols = SslProtocols.Tls12
        };
        handler.ClientCertificates.Add(new X509Certificate2("cert.crt")); //TODO: fetch from AWS.
        return handler;
    }

如果您使用 AWS SDK,您可以使用 AmazonCertificateManagerClient 获取证书。有关详细信息,请参阅 the AWS SDK documentation。 (select Amazon.CertificateManager > AmazonCertificateManagerClient)

所以,这是可能的。

我从 NuGet 安装了 AWSSDK.Core 和 AWSSDK.CertificateManager。

然后,我为 AWS 创建了一个凭证文件,请参阅 Amazon 的说明 https://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html

接下来,我使用 AmazonCertificateManagerClient 获取证书。

AmazonCertificateManagerClient client = new AmazonCertificateManagerClient();
var certificates = client.GetCertificateAsync(arn).Result;

然后我将证书从字符串转换为字节,然后添加到处理程序中。

var handler = new HttpClientHandler{
  ClientCertificateOptions = ClientCertificateOption.Manual,
  SslProtocols = SslProtocols.Tls12
};

byte[] toBytes = Encoding.ASCII.GetBytes(certificates.Certificate);
var cert = new X509Certificate2(toBytes);

handler.ClientCertificates.Add(cert); 
var httpClient = new HttpClient(handler);

显然,不是生产价值代码,希望对您有所帮助。

如 Zack 所述,已接受的答案无效。它确实从 ACM 中检索了一个证书,但它不能用作 HttpClient 的客户端证书,因为它没有私钥。

据我所知,无法从 ACM 中获取私钥,因此我最终将其放入 SecretsManager 中并执行如下操作:

var certManagerClient = new AmazonCertificateManagerClient();
var awsCert = certManagerClient.GetCertificateAsync(arn).Result;
byte[] awsBytes = Encoding.ASCII.GetBytes(awsCert.Certificate);
var cert = new X509Certificate2(awsBytes);

var secretsManagerClient = new AmazonSecretsManagerClient();
var privateKey = secretsManagerClient.GetSecretValueAsync(new GetSecretValueRequest { SecretId = secretId }).Result.SecretString;
byte[] privateKeyBytes = Convert.FromBase64String(privateKey);
var privateKey = RSA.Create();
privateKey.ImportRSAPrivateKey(new ReadOnlySpan<byte>(privateKeyBytes), out _);
var certWithPrivateKey = cert.CopyWithPrivateKey(privateKey);

然后在我的 HttpClientHandler 中使用 certWithPrivateKey:

var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Manual };
handler.ClientCertificates.Add(certWithPrivateKey);