MongoDB C# SSL Client Certificate

本文关键字:Certificate Client SSL MongoDB | 更新日期: 2023-09-27 18:32:43

我正在尝试使用证书验证使用 C# 驱动程序与 MongoDB 建立安全连接,但收到此错误:

无法

连接到服务器 localhost:27017:无法从传输连接读取数据:已建立的连接被主机中的软件中止。.

这是来自MongoDB的错误:

[initandlisten] connection accepted from 127.0.0.1:26163 #2 (1 connection now open)
[conn2] ERROR: no SSL certificate provided by peer; connection rejected
[conn2] SocketException handling request, closing client connection: 9001 socket exception [CONNECT_ERROR]

当我通过带有证书的 mongo shell 连接到 MongoDB 时,它可以工作。

var connectionString = "mongodb://localhost";
var clientSettings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
clientSettings.SslSettings = new SslSettings();
clientSettings.UseSsl = true;
clientSettings.SslSettings.ClientCertificates = new List<X509Certificate>()
    {
        new X509Certificate("cert.pem")
    };
clientSettings.SslSettings.EnabledSslProtocols = SslProtocols.Default;
clientSettings.SslSettings.ClientCertificateSelectionCallback =
    (sender, host, certificates, certificate, issuers) => clientSettings.SslSettings.ClientCertificates.ToList()[0];
clientSettings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
var client = new MongoClient(clientSettings);

有谁知道如何让它工作?

MongoDB C# SSL Client Certificate

意识到这已经过时了,但为了他人的利益......

如果不处理证书吊销列表,则需要关闭该设置,因为它默认处于启用状态。

clientSettings.SslSettings.CheckCertificateRevocation = false;

接下来,提供给驱动程序的 X509Certificate2 必须包含私钥。 .NET 似乎不会在 pem 文件中选取私钥,因此需要提供 .pfx 格式的证书并包含密码。

要在 openssl 中创建 pfx 文件,请执行以下操作:

openssl pkcs12 -export -in mycert.cer -inkey mycert.key -out mycert.pfx

OpenSSL 将提示您输入导出密码,请在创建 X509Certificate2 对象时使用该密码:

X509Certificate2 cert = new X509Certificate2("mycert.pfx","mypassphrase");

//struggled a lot to figure out this
using MongoDB.Bson;
using MongoDB.Driver;
namespace Mongo_AWS
{
    internal class Program
    {
        private static void Main(string[] args)
        {
//Mention cert file in connection string itself or put at your executable location
            string connectionString = @"mongodb://user:pwd@localhost:9999/?ssl=true&ssl_ca_certs=C:'Users'sivaram'Downloads'my.pem";
            MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
            
            //Disable certificate verification, if it is not issued for you
            settings.VerifySslCertificate = false;
            MongoClient client = new MongoClient(settings);
            IMongoDatabase database = client.GetDatabase("test");
            IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("numbers");
            System.Collections.Generic.List<BsonDocument> temp = collection.Find(new BsonDocument()).ToList();
            BsonDocument docToInsert = new BsonDocument { { "sivaram-Pi", 3.14159 } };
            collection.InsertOne(docToInsert);
        }
    }
}

,ssl_ca_certs = @"/path/my.pem",在连接字符串中添加了这个。

设置。验证SslCertificate = false;

如果您从本地测试它/您有根证书但未颁发给您的计算机,请使用上面的行,可能会颁发给您的生产主机。

将根证书放在绝对路径中,并在连接字符串中直接引用该路径。Mongo驱动程序将负责读取私钥和所有内容。无需将其放在证书存储区或某个地方。

从 tyjen 的答案反弹,它可以完全用 C# 完成。假设您有一个同时包含公钥和私钥的 PEM 格式文件,则可以使用以下内容创建有效的 X509 证书(假设在此用例中,您有一个包含公钥和私有 RSA 密钥的 PEM 文件):

using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using MongoDB.Driver;
function X509Certificate2 GetX509Pfx(String pem) {
    // Note that cert is `IDisposable`
    var cert = new X509Certificate2(Encoding.UTF8.GetBytes(pem)))
    if (cert.HasPrivateKey) {
        return cert;
    } else {
        // Note that rsa is `IDisposable`
        var rsa = RSA.Create();
        rsa.ImportFromPem(pem.AsSpan());
        return cert.CopyWithPrivateKey(rsa);
    }
}
function IMongoClient GetMongoClient(String connectionString, String pem) {
    var cert = GetX509Pfx(pem);
    var settings = MongoClientSettings.FromConnectionString(connectionString);
    settings.ServerApi = new ServerApi(ServerApiVersion.V1),
    settings.Credential = MongoCredential.CreateMongoX509Credential(cert.Subject),
    settings.SslSettings = new SslSettings {
        ClientCertificates = new List<X509Certificates> { cert }
    }
    return new MongoClient(settings);
}