jeroen / mongolite

Fast and Simple MongoDB Client for R
https://jeroen.github.io/mongolite/
284 stars 64 forks source link

Connecting using SSL Server and client validation #209

Closed harshalna1du closed 3 years ago

harshalna1du commented 4 years ago

I'm trying to connect to mongo referring to https://jeroen.github.io/mongolite/connecting-to-mongodb.html

In the mongo compass utility(that comes with mongodb), I have the following SSL settings

SSL Dropdown : Server and Client Validation Certificate Authority : C:/certs/ca-sec.pem Client Certificate: C:/certs/mongo-sec.pem Client Private Key: C:/certs/mongo-sec.pem

This works fine.

In R, I tried this but got the error - unused argument ca_file = read_cert("C:/certs/ca-sec.pem)

con <- mongo(
  url = "mongodb://<my username>:<my password><mydomain><:port>/<mongo auth db>?ssl=true",
  options = ssl_options(
    ca_file = read_cert("C:/certs/ca-sec.pem"),
    crl_file = read_cert("C:/certs/mongo-sec.pem"),
    key = read_key("C:/certs/mongo-sec.pem")
  )
)

I tried various other combinations of options given on the page but to no avail.

I'd appreciate if someone could please point me to the right options.

0xthierry commented 3 years ago

Hello @harshalna1du,

I reproduced the same error here and I see we are using just "ca" and not "ca_file".

I paste bellow the comment in the code showing the parameters name for this function.

https://github.com/jeroen/mongolite/blob/master/R/ssl.R

harshalna1du commented 3 years ago

Thank you. I change the parameter to ca and I got the error

Error in path.expand(path) : invalid 'path' argument

Then I used the parameter cert instead of crl_file and I got this error

Error: OpenSSL error in asn1_check_tlen: wrong tag

I also tried using read_pem instead of read_cert and I got the error

Error in read_input(file) : 
  file must be connection, raw vector or file path

The mongo-sec.pem file has both the cert and an rsa key.

I'm not sure what is happening. I'd appreciate any guidance to make it work.

JerchPaul commented 3 years ago

Hi @harshalna1du I was experiencing a similar issue, specifically: Error: OpenSSL error in asn1_check_tlen: wrong tag

Calling openssl::read_key() on my cert/rsa key file - mongo-sec.pem in your case - resulted in Input is a certificate. Use read_cert() to read.

To fix that, I copied the private key from my cert/rsa key file into a separate file I named key.pem. Consider doing the same and try the following parameters below:

ssl_options parameters:

ca =  "C:/certs/ca-sec.pem",  
cert = read_cert("C:/certs/mongo-sec.pem"),  
key = read_key(“C:/certs/key.pem”)  #This is the newly created key file
harshalna1du commented 3 years ago

Thank you @JerchafliePaul.

I tried again after separating the key in a different file but I still get the error Error in path.expand(path) : invalid 'path' argument

Here's the output of traceback()

8: path.expand(path)
7: normalizePath(ca, mustWork = TRUE)
6: ssl_options(
                ca = read_cert("C:/certs/ca-sec.pem"),
                cert = read_cert("C:/certs/mongo-sec.pem"), 
                key = read_key("C:/certs/key.pem")
               )
5: serialize(params, NULL)
4: rawstringhash(x, "md5", key)
3: openssl::md5(serialize(params, NULL))
2: new_client(c(list(uri = url), options))
1: mongo(url = "mongodb://<my username>:<my password><mydomain><:port>/<mongo auth db>?ssl=true", 
         options = ssl_options(
                                ca = read_cert("C:/certs/ca-sec.pem"), 
                                cert = read_cert("C:/certs/mongo-sec.pem"),
                                key = read_key("C:/certs/key.pem")
                               )
        )

In this case the mongo-sec.pem file had both the cert and the rsa key. And the key.pem file had only the key. I also tried with mongo-sec.pem containing only the cert and not the rsa key. The result was the same.

JerchPaul commented 3 years ago

@harshalna1du My mistake, just pass the path for the ca parameter. I edited my previous comment to reflect this change.

harshalna1du commented 3 years ago

@GiraffeFile Thanks so much. I'm making progress but getting a new error now.

Error: No suitable servers found (serverSelectionTryOnceset): [connection closed calling ismaster on '<ip>:<port>']

I tried setting the ssl option allow_invalid_hostname to TRUE. I also tried connecting using the the host name after updating the windows hosts file.

I can connect to mongodb using a GUI client called nosqlbooster.

Appreciate the help.

harshalna1du commented 3 years ago

My issue is resolved and I can now connect to mongodb . The error in my last comment was because I missed the port name in copy pasting.

When I included the port name I got the following error

Error: No suitable servers found (serverSelectionTryOnceset): [TLS handshake failed: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed calling ismaster on '<ip>:<port>']

This issue was resolved by adding the ssl option allow_invalid_hostname =TRUE. Alternatively adding the ip host name mapping to the hosts file also resolved the issue without having to use the said ssl option.

Here's the approach I finally used to connect to mongo. Hope it helps someone

library(mongolite)

con <- mongo(
  url = "mongodb://<username>:<password>@<ip>:<port>/<dbname>?ssl=true",
  options = ssl_options
  (
    ca = "<path/cert filename>",
    cert = read_cert("path/ssl cert.pem"),  
    key = read_key("path/rsa key.pem"),
    allow_invalid_hostname =TRUE
  )
)

Example

library(mongolite)

con <- mongo(
  url = "mongodb://misterMister:mypassword@172.x.x.0:30719/mydb?ssl=true",
  options = ssl_options
  (
    ca = "C:/certs/ca-sec.pem",
    cert = read_cert("C:/certs/mongo-sec.pem"),  
    key = read_key("C:/certs/key.pem"),
    allow_invalid_hostname =TRUE
  )
)

Appreciate the support for this super useful library.