繁体   English   中英

无法使用带有服务器 CA 验证的 TLS 连接到 AWS 数据库

[英]Cannot Connect to AWS Database using TLS with Server CA Validation

AWS 文档指出,要连接到我的 DocumentDB 集群,我需要使用以?ssl_ca_certs=rds-combined-ca-bundle.pem&replicaSet=rs0结尾的查询字符串。 这是我的客户应该验证的根证书链 我不应该需要客户证书

使用 MongoDB C# 驱动程序和此特定查询,并且.pem文件位于同一目录中,我无法建立连接。 如果我使用相同的.pem文件和来自 Mongo Shell 的查询字符串,我可以正确连接到我的数据库。 它仅不适用于我的 .net 核心应用程序,该应用程序也在 AWS 上运行。

通过从集群中删除 TLS 并从查询中删除ssl_ca_certs选项,我可以正确连接到我的集群。

我以为我可以使用openssl将我的.pem文件转换为.pfx ,但我必须给.pfx一个密码, MongoDB 文档指出

加载带有密码的证书时,PrivateKey 属性必须不为空。 如果该属性为空,则表示您的证书不包含私钥,不会传递给服务器。

如何使用Amazon AWS 提供的.pem文件通过C# MongoDB 驱动程序连接到我的数据库?

###Connection to Document DB with simple .Net console Application with SSL。

->首先,通过将参数 tls 设置为“已启用”,在文档数据库集群上启用 SSL。 确保重新启动集群的编写器节点以重新启动整个集群以应用参数组更改。 默认情况下 TLS 在您启动新的 Doc 数据库集群时启用。

-> 在您的环境中设置 SSL 证书:

1) 从以下链接下载源 Windows 计算机上的 PKCS#7 SSL 证书:

https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.p7b

2)点击开始菜单,点击运行,输入mmc

3) 在 MMC 中,文件->添加/删除管理单元。

4) 从管理单元列表中选择证书,然后单击添加。

5) 受信任的 CA 证书应该在本地计算机存储中,因此选择“计算机帐户”单选按钮,单击下一步,然后选择“本地计算机”。 单击下一步,然后单击完成。

6)现在从左侧窗格(在控制台根目录下,您将看到“证书”选项。单击它。

7)将出现一个列表,右键单击“受信任的根证书颁发机构”,然后选择“所有任务”->“导入”

8)在打开的窗口中,点击下一步,浏览步骤1中下载的证书(.p7b)文件(如果找不到,从文件类型下拉菜单中选择所有文件),然后继续单击“下一步”,最后单击“完成”。 然后保存配置。

->然后写了下面的代码:

---------------------------------------------------

using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace FirstDocDB
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var connectionString = "mongodb://pulkit:password@ClusterID:27017/?ssl=true&sslVerifyCertificate=true&replicaSet=rs0";
            var client = new MongoClient(connectionString);
            var database = client.GetDatabase("test");
            var collection = database.GetCollection("stuff");
            var document = collection.Find(new BsonDocument()).FirstOrDefault();
            Console.WriteLine(document.ToString());
        }
    }
}

---------------------------------------------------

->在构建和运行之后,我成功地获得了名为“stuff”的集合中的文档作为输出: { "_id" : ObjectId("5c5a63b10cf861158c1d241c"), "hello" : "world" }

因此,按照上述步骤操作后,我成功地使用 .Net 的 Mongo 驱动程序连接到文档数据库。

我遇到了类似的问题,在 AWS 上开了一张票,并通过与 Pulkit Agarwal 的回答类似的步骤解决了这个问题。

主要变化是连接字符串,即使在将证书添加到本地存储后,我仍然使用查询字符串作为“?ssl_ca_certs=rds-combined-ca-bundle.pem&replicaSet=rs0”,需要更改为“?ssl=true&sslVerifyCertificate=true&replicaSet =rs0"

以下示例介绍了如何在启用/禁用 TLS 的情况下使用 C#(和其他驱动程序)以编程方式连接到 Amazon DocumentDB。

https://docs.aws.amazon.com/documentdb/latest/developerguide/connect.html

这是另一种方式。 但是我发现通过将 SSL 与 C# Mongo 驱动程序一起使用不会进行连接池并为每个调用打开一个新连接。 您可以通过包括 MaxConnectionIdleTime 来减少活动连接,但如果您的应用程序创建了大量连接,它仍然不理想。

    var connectionString = "username:password@cluster_endpoint:27017/?replicaSet=rs0";
    var clientSettings = MongoClientSettings.FromUrl(new MongoUrl("mongodb://" + connectionString));
    var certificatePath = "ssl\rds-combined-ca-bundle.pem";

    var pem = System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + certificatePath);
    byte[] certBuffer = GetBytesFromPEM(pem, "CERTIFICATE");

    clientSettings.UseSsl = true;
    clientSettings.SslSettings = new SslSettings()
    {
        ClientCertificates = new List<X509Certificate2>()
        {
            new X509Certificate2(certBuffer)
        },
        EnabledSslProtocols = System.Security.Authentication.SslProtocols.Default,
        CheckCertificateRevocation = true
        };

    clientSettings.VerifySslCertificate = true;

    clientSettings.SslSettings.ClientCertificateSelectionCallback = (sender, host, certificates, certificate, issuers) => clientSettings.SslSettings.ClientCertificates.ToList()[0];
    clientSettings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

    clientSettings.MaxConnectionIdleTime = new TimeSpan(0, 0, 30);

    _client = new MongoClient(clientSettings);
    _database = _client.GetDatabase(db.ToString());

值得补充的是,目前 MongoDB C# 驱动程序不支持PEM证书。 因此,任何引用PEM证书的内容都将失败,并出现System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.

AWS 开发人员指南建议使用P7B证书,可以从这里下载: https : //s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.p7b

这对我们有用。

在 Kubernetes 和 Windows 上,我们需要将rds-combined-ca-bundlee.p7b到本地信任存储,如AWS C# 示例所示,并且不要在连接字符串中引用它。

在 Mac 上,由于access denied问题,我一直在努力以编程方式将P7B证书添加到密钥库。 如果我设法解决它,将更新答案。


最后值得一提的是,Kenny Dickie 提供的答案基本上关闭了证书验证并使设置不安全。 这行代码clientSettings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true; 将始终返回true

尝试将 RDS CA 文件添加到您的 C# 信任存储中。

            X509Store store = new X509Store(StoreName.Root);
            X509Certificate2 ca = new X509Certificate2(<path_to_rds-combined-ca-bundle.pem>);
            try {
                store.Open(OpenFlags.ReadWrite);
                store.Add(ca);
            } catch (Exception ex) {
                Console.WriteLine("Root certificate import failed: " + ex.Message);
                throw;
            } finally {
                store.Close();
            }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM