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

时间:2019-02-22 23:46:48

标签: mongodb amazon-web-services ssl asp.net-core aws-documentdb-mongoapi

AWS文档指出,要连接到我的DocumentDB集群,我需要使用一个像?ssl_ca_certs=rds-combined-ca-bundle.pem&replicaSet=rs0这样结束的查询字符串。 It is a root certificate chain我的客户应进行验证。我不需要Client Certificate

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

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

我以为可以使用.pem.pfx文件转换为openssl,但是我必须给.pfx设置密码和MongoDB documentation states that

  

当使用密码加载证书时,必须   PrivateKey属性不能为null。如果该属性为null,则表示   您的证书不包含私钥,并且不会   传递给服务器。

如何使用the .pem file provided by Amazon AWS通过C#MongoDB驱动程序连接到数据库?

6 个答案:

答案 0 :(得分:1)

尝试将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();
            }

答案 1 :(得分:1)

###使用具有SSL的简单.Net控制台应用程序连接到文档数据库。

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

->在您的环境中设置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”:“世界”}

因此,在执行了上述步骤之后,我能够使用.Net的Mongo驱动程序成功连接到Document DB。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

这是另一种方式。但是我发现通过将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());

答案 4 :(得分:0)

这里是有关如何使用启用和禁用TLS的C#(和其他驱动程序)以编程方式连接到Amazon DocumentDB的示例。

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

答案 5 :(得分:0)

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

AWS Developer Guide建议使用P7B证书代替,可以从此处下载:https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.p7b

这对我们有用。

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

在Mac上,由于存在P7B问题,我难以通过编程方式将access denied证书添加到Keystore中。如果我设法解决问题,将会更新答案。


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