SuttyHoo
SuttyHoo

Reputation: 101

MongoDb c# driver - UseSsl = true. Attempted to read past the end of the stream

I have installed MongoDb mongodb-win32-x86_64-2008plus-ssl-3.0.0-signed on an Azure 2012 R2 Windows server VM.

I want to configure MongoDb to use SSL. I generated a certificate (.crt, pem, pfx files) using open SSL. The same files (generated on the server), have been copied to the remote PC to be used in the client-server connections,

I can successfully connect to the mongod instance and query the database running on the server from a remote pc through the mongo shell. The client has the same version of MongoDb installed.

However, I am not able to connect via c# code on the same remote PC. The code use the Official MongoDb c# driver pulled into project via NuGet [v1.10.0 = latest version].

Error message. Unable to connect to ':27017. Attempted to read past the end of the stream'.

I can successfully connect using the C# driver if the mongod instance on the VM is started with --sslMode preferSSL option rather than requireSSL (having set the c# driver's 'UseSsl' property to false). I have tried setting up the MongoClient SslSettings using X509Certificate with each of the files I generated using OpenSSL (pfx; crt) and receive the already mentioned error. If I try to use the generated .pem file, the error is "Cannot find the requested object". The file is definitely in the location the code will be looking for it. I believe that it is the .pfx file that I should be using.

These files, when opened in notepad look correct (in terms of their 'begin' and 'end' statements).

The command to start Mongod on the VM:

mongod --sslMode requireSSL --sslPEMKeyFile mongodb.pem --sslCAFile mongodb-cert.crt --dbpath "C:\Dump\MongoDb_Db" --logpath "C:\Dump\MongoDb_Logs\logs.txt" --directoryperdb --journal --port 27017 --noscripting

The command that successfully connects from remote PC using mongo shell:

mongo --host my.cloudapp.net --port 27017 --ssl --sslCAFile c:\Dump\OpenSSL\mongodb-cert.crt --sslPEMKeyFile c:\Dump\OpenSSL\mongodb.pem --sslPEMKeyPassword MYPASSPHRASE --verbose

C# client code:

 var mongoClientSettings = new MongoClientSettings();

 var cert = new X509Certificate(fileName: @"c:\dump\OpenSSL\mongoDb.pfx", password:"*MYPASSPHRASE*");

 var certs = new List<X509Certificate> { cert };
 mongoClientSettings.UseSsl = true;
 mongoClientSettings.VerifySslCertificate = false; // tried setting to true

 mongoClientSettings.Server = new MongoServerAddress("my.cloudapp.net", 27017);
 mongoClientSettings.SslSettings = new SslSettings
    {
       CheckCertificateRevocation = true,   //tried setting to true             
       ClientCertificates = certs,
       EnabledSslProtocols = SslProtocols.Default,
       ServerCertificateValidationCallback = 
                (sender, certificate, chain, errors) =>
                 {
                     return true;
                 }, 
      ClientCertificateSelectionCallback = 
                 (sender, host, certificates, certificate, issuers) =>
                 {
                  return certs.ToList()[0];  // certificate as expected seen here
                 }    
             };

             try
             {
                 var client = new MongoClient(mongoClientSettings);
                 var server = client.GetServer();

                 var database = server.GetDatabase("test");
                 database.CreateCollection("NewCollection"); //fails here
                 //var names = database.GetCollectionNames();  //fails here
             }
             catch (Exception exception)
             {
             }

Hopefully someone can give me a pointer on how to get the connection using the C' driver to work.

Thanks.

Upvotes: 6

Views: 4085

Answers (2)

Peter Horsley
Peter Horsley

Reputation: 1756

Craig's blog post was extremely helpful, although it wasn't the usage of X509Certificate2 that fixed it for me - I had to follow his advice and construct it from a PFX file, generated from the public certificate (.crt) and private key (.key) files using openssl:

openssl pkcs12 -export -out client.pfx -inkey client.key -in client.crt

Upvotes: 0

SuttyHoo
SuttyHoo

Reputation: 101

Craig,

Magic. Thanks for your help.

Your blog post you indicated about this had the answer. The only thing that needed to be changed was to use the 509Certificate2 class (as you had done)not 509Certificate class. The pfx file was not an issue, as I had already generated the pfx file using openSSL as you had done.

I successfully run the code with everything else the same as detailed in my question.

I did not need to use the MongoCredentials. The 'CN' etc seemed to just get picked up correctly from the pfx file. For some reason you needed to include that in your code.

Thanks again.

Upvotes: 4

Related Questions