• Skip to main content
  • Skip to secondary menu
  • Skip to primary sidebar
  • Skip to footer
  • Articles
  • News
  • Events
  • Advertize
  • Jobs
  • Courses
  • Contact
  • (0)
  • LoginRegister
    • Facebook
    • LinkedIn
    • RSS
      Articles
      News
      Events
      Job Posts
    • Twitter
Datafloq

Datafloq

Data and Technology Insights

  • Categories
    • Big Data
    • Blockchain
    • Cloud
    • Internet Of Things
    • Metaverse
    • Robotics
    • Cybersecurity
    • Startups
    • Strategy
    • Technical
  • Big Data
  • Blockchain
  • Cloud
  • Metaverse
  • Internet Of Things
  • Robotics
  • Cybersecurity
  • Startups
  • Strategy
  • Technical

Connecting MongoDB to Ruby with Self-Signed Certificates for SSL

Dharshan Rangegowda / 11 min read.
June 21, 2019
Datafloq AI Score
×

Datafloq AI Score: 89.67

Datafloq enables anyone to contribute articles, but we value high-quality content. This means that we do not accept SEO link building content, spammy articles, clickbait, articles written by bots and especially not misinformation. Therefore, we have developed an AI, built using multiple built open-source and proprietary tools to instantly define whether an article is written by a human or a bot and determine the level of bias, objectivity, whether it is fact-based or not, sentiment and overall quality.

Articles published on Datafloq need to have a minimum AI score of 60% and we provide this graph to give more detailed information on how we rate this article. Please note that this is a work in progress and if you have any suggestions, feel free to contact us.

floq.to/H6KXi

Given the popularity of our post on connecting MongoDB SSL with Self-Signed Certificates in Node.js, we decided to write a tutorial on connecting MongoDB with Ruby. In this blog, we’ll show you how to connect to a MongoDB server configured with self-signed certificates for SSL using both the Ruby MongoDB driver and the popular Object-Document-Mapper (ODM) mongoid.

ScaleGrid currently uses self-signed certificates for SSL when creating nodes for a new cluster. Additionally, we also provide you with the option of purchasing your own SSL certificates and configuring them on the MongoDB server, and you can email support@scalegrid.io to learn more about this offer.

Connecting to a Replica Set Using Ruby MongoDB Driver

We will use the latest stable Ruby MongoDB driver version 2.8 for this example. The 2.5.x versions of the driver have a known bug that inhibit them from working with ScaleGrid deployments. The Ruby version used in both the examples below is 2.6.3.

The connection options available for the driver are documented here, and the options we will need are:

  • :ssl
  • :ssl_verify
  • :ssl_ca_cert.

First, find and copy your MongoDB connection string from the cluster details page on the ScaleGrid console:

MongoDB Connection String for Ruby Applications

The CA certificate file is also available for download from the cluster details page. Download and store the cert file at a location that is available to the application:
MongoDB SSL Certificate and Command Line Syntax for Ruby ApplicationsHere’s a snippet showing how to connect to a MongoDB replica set from Ruby:

require 'mongo'

Mongo::Logger.logger.level = ::Logger::DEBUG

MONGODB_CA_CERT = "/path/to/ca_cert.pem"
MONGODB_CONN_URL = "mongodb://testuser:<pwd>@SG-example-17026.servers.mongodirector.com:27017,SG-example-17027.servers.mongodirector.com:27017,SG-example-17028.servers.mongodirector.com:27017/test?replicaSet=RS-example-0&ssl=true"

options = { ssl:true, ssl_verify: true, :ssl_ca_cert => MONGODB_CA_CERT }

client = Mongo::Client.new(MONGODB_CONN_URL, options)

db = client.database
collections = db.collection_names
puts "db #{db.name} has collections #{collections}"
client.close

To keep the example simple, we have specified the connection string and the cert file path directly in the code snippet you would generally either put them in a yaml file or specify them as environment variables. Also, the example sets the log level to DEBUG so that any connectivity issues can be debugged. It should be changed to a less verbose level once connectivity issues have been sorted out.

Connecting Using Mongoid

The mongoid version we will use in our example is the latest stable version 7.0.2. We will use a yaml file to provide configuration to mongoid, and the details of such a config file are documented here. The SSL-specific configuration options we will need to connect to our replica set are:

  • ssl
  • ssl_verify
  • ssl_ca_cert

Our yml file:

development:
  # Configure available database clients. (required)
  clients:
    # Define the default client. (required)
    default:
      # A uri may be defined for a client:
      # uri: 'mongodb://user:password@myhost1.mydomain.com:27017/my_db'
      # Please see driver documentation for details. Alternatively, you can define the following:
      #
      # Define the name of the default database that Mongoid can connect to.
      # (required).
      database: test
      # Provide the hosts the default client can connect to. Must be an array
      # of host:port pairs. (required)
      hosts:
        - SG-example-17026.servers.mongodirector.com:27017
        - SG-example-17027.servers.mongodirector.com:27017
        - SG-example-17028.servers.mongodirector.com:47100
      options:
        # The name of the user for authentication.
        user: 'testuser'

        # The password of the user for authentication.
        password: 'pwd'

        # The user's database roles.
        roles:
          - 'readWrite'

        # Change the default authentication mechanism. Valid options are: :scram,
        # :mongodb_cr, :mongodb_x509, and :plain. (default on 3.0 is :scram, default
        # on 2.4 and 2.6 is :plain)
        auth_mech: :scram

        # The database or source to authenticate the user against. (default: admin)
        auth_source: test

        # Force the driver to connect in a specific way instead of auto-
        # discovering. Can be one of: :direct, :replica_set, :sharded. Set to :direct
        # when connecting to hidden members of a replica set.
        connect: :replica_set
        ...
        ...
        # The name of the replica set to connect to. Servers provided as seeds that do
        # not belong to this replica set will be ignored.
        replica_set: RS-example-0

        # Whether to connect to the servers via ssl. (default: false)
        ssl: true

        # Whether or not to do peer certification validation. (default: true)
        ssl_verify: true

        # The file containing a set of concatenated certification authority certifications
        # used to validate certs passed from the other end of the connection.
        ssl_ca_cert: /path/to/ca_cert.pem

  # Configure Mongoid specific options. (optional)
  options:
    # Set the Mongoid and Ruby driver log levels. (default: :info)
    log_level: :debug

Connection example:


Interested in what the future will bring? Download our 2023 Technology Trends eBook for free.

Consent

gem 'mongoid', '7.0.2'
require 'mongoid'

Mongoid.load!("/path/to/mongoid.yml", :development)

# Not using any of the ODM features - just fetch the underlying mongo client and attempt to connect

client = Mongoid::Clients.default
db = client.database
collections = db.collection_names
puts "db #{db.name} has collections #{collections}"
Mongoid::Clients.disconnect

Again, in production Ruby on Rails applications, the yaml file path would be picked up from the environment variables.

Testing Failover Behavior

Like other MongoDB drivers, the Ruby MongoDB driver is also designed to internally recognize changes in topology due to events like failover. However, it is good to test and validate the behavior of the driver during failovers to avoid surprises in production.

Like my previous post on MongoDB PyMongo, we can write a perpetual writer test program to observe the failover behavior of the driver.

The easiest way to induce failover is to run the rs.stepDown() command:

RS-example-0:PRIMARY> rs.stepDown()
2019-04-18T19:44:42.257+0530 E QUERY [thread1] Error: error doing query: failed: network error while attempting to run command 'replSetStepDown' on host 'SG-example-1.servers.mongodirector.com:27017' :
DB.prototype.runCommand@src/mongo/shell/db.js:168:1
DB.prototype.adminCommand@src/mongo/shell/db.js:185:1
rs.stepDown@src/mongo/shell/utils.js:1305:12
@(shell):1:1
2019-04-18T19:44:42.261+0530 I NETWORK [thread1] trying reconnect to SG-example-1.servers.mongodirector.com:27017 (X.X.X.X) failed
2019-04-18T19:44:43.267+0530 I NETWORK [thread1] reconnect SG-example-1.servers.mongodirector.com:27017 (X.X.X.X) ok
RS-example-0:SECONDARY>

Here are the relevant parts of our test code:

require 'mongo'
...

logger = Logger.new(STDOUT)
logger.level = Logger::INFO

MONGODB_CA_CERT = "/path/to/ca_cert.pem"
MONGODB_CONN_URL = "mongodb://testuser:<pwd>@SG-example-17026.servers.mongodirector.com:27017,SG-example-17027.servers.mongodirector.com:27017,SG-example-17028.servers.mongodirector.com:27017/test?replicaSet=RS-example-0&ssl=true"
options = { ssl:true, ssl_verify: true, :ssl_ca_cert => MONGODB_CA_CERT }

begin
    logger.info("Attempting to connect...")
    client = Mongo::Client.new(MONGODB_CONN_URL, options)
    i = 0
    loop do
        db = client.database
        collection = db[:test]
        begin
            doc = {"idx": i, "date": DateTime.now, "text": SecureRandom.base64(3) }
            result = collection.insert_one(doc)
            logger.info("Record inserted - id: #{result.inserted_id}")
            i += 1
            sleep(3)
        rescue Mongo::Error => e
            logger.error("Mong Error seen: #{e.message}")
            logger.error(e.backtrace)
            logger.info("Retrying...")
        end
    end
    logger.info("Done")
rescue => e
rr    logger.error("Exception seen: #{err.message}")
    logger.error(err.backtrace)
ensure
    client.close unless client.nil?
end

This continuously writes entries like these to the test collection on the test database:

RS-test-0:PRIMARY> db.test.find()
{ "_id" : ObjectId("5cf50ff1896cd172a4f7c6ee"), "idx" : 0, "date" : ISODate("2019-06-03T12:17:53.008Z"), "text" : "HTvd" }
{ "_id" : ObjectId("5cf50ff6896cd172a4f7c6ef"), "idx" : 1, "date" : ISODate("2019-06-03T12:17:58.697Z"), "text" : "/e5Z" }
{ "_id" : ObjectId("5cf50ff9896cd172a4f7c6f0"), "idx" : 2, "date" : ISODate("2019-06-03T12:18:01.940Z"), "text" : "quuw" }
{ "_id" : ObjectId("5cf50ffd896cd172a4f7c6f1"), "idx" : 3, "date" : ISODate("2019-06-03T12:18:05.194Z"), "text" : "gTyY" }
{ "_id" : ObjectId("5cf51000896cd172a4f7c6f2"), "idx" : 4, "date" : ISODate("2019-06-03T12:18:08.442Z"), "text" : "VDXX" }
{ "_id" : ObjectId("5cf51003896cd172a4f7c6f3"), "idx" : 5, "date" : ISODate("2019-06-03T12:18:11.691Z"), "text" : "UY87" }
...

Let’s see the behavior during a failover:

I, [2019-06-03T17:53:25.079829 #9464]  INFO -- : Attempting to connect...
I, [2019-06-03T17:53:30.577099 #9464]  INFO -- : Record inserted - id: 5cf5113f896cd124f8f31062
I, [2019-06-03T17:53:33.816528 #9464]  INFO -- : Record inserted - id: 5cf51145896cd124f8f31063
I, [2019-06-03T17:53:37.047043 #9464]  INFO -- : Record inserted - id: 5cf51148896cd124f8f31064
I, [2019-06-03T17:53:40.281537 #9464]  INFO -- : Record inserted - id: 5cf5114c896cd124f8f31065
I, [2019-06-03T17:53:43.520010 #9464]  INFO -- : Record inserted - id: 5cf5114f896cd124f8f31066
I, [2019-06-03T17:53:46.747080 #9464]  INFO -- : Record inserted - id: 5cf51152896cd124f8f31067
I, [2019-06-03T17:53:49.978077 #9464]  INFO -- : Record inserted - id: 5cf51155896cd124f8f31068 <<< Failover initiated here
E, [2019-06-03T17:53:52.980434 #9464] ERROR -- : Mong Error seen: EOFError: end of file reached (for x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017, TLS))
E, [2019-06-03T17:53:52.980533 #9464] ERROR -- : ["C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/socket.rb:300:in `rescue in handle_errors'", "C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/socket.rb:294:in `handle_errors'", "C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/socket.rb:126:in `read'", "C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/protocol/message.rb:139:in `deserialize'",...
...
I, [2019-06-03T17:53:52.980688 #9464]  INFO -- : Retrying...
W, [2019-06-03T17:53:52.981575 #9464]  WARN -- : Retrying ismaster on sg-example-17026.servers.mongodirector.com:27017 due to: Mongo::Error::SocketError EOFError: end of file reached (for x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017, TLS))
I, [2019-06-03T17:54:06.293100 #9464]  INFO -- : Record inserted - id: 5cf51163896cd124f8f3106a
I, [2019-06-03T17:54:09.547716 #9464]  INFO -- : Record inserted - id: 5cf51169896cd124f8f3106b
I, [2019-06-03T17:54:12.806636 #9464]  INFO -- : Record inserted - id: 5cf5116c896cd124f8f3106c

It is evident that if correct errors are caught and read/writes retried, the driver will automatically detect the topology change and reconnect to the new master. For writes, the option :retry_writes ensure that the driver will retry once on its own before notifying the application of an error.

There are also multiple driver timeouts that can be tweaked based on the exact behavior and latency you see on your setup. These are documented here.

Troubleshooting

If you’re having trouble connecting to your SSL-enabled MongoDB deployment, here are a few tips for debugging:

  • First, verify that you can actually connect to the MongoDB server from the server where your application is running. The simplest way to do this is to install mongo shell on the client machine. On Linux, you wouldn’t need to install the entire MongoDB server you can choose to just install the shell separately. Once the shell is available, try to use the Command Line Syntax’ we provide to attempt to connect to the server.
  • If you are unable to connect via the mongo shell, it means that the client machine is unable to reach the port 27017 of the MongoDB servers. Look at your Security Group, VPC, and ScaleGrid firewall settings to ensure that there is connectivity between the client and server machines.
  • If network connectivity is correct, the next thing to check is that you are using versions of Ruby, mongoid, and mongo gem that are compatible with the version of your MongoDB server.
  • If you have confirmed that the driver versions are correct, try running a sample Ruby script, similar to the example we provided above, on the IRB. A step-by-step execution might point out where the issue is.
  • If the test script runs fine, but you are still unable to connect with mongoid, attempt to run a simple test script, like the example we provided above.
  • If you are still having trouble connecting to your instance, please write to us at support@scalegrid.io with detailed results of the above troubleshooting steps and with the exact versions of Ruby, mongoid and mongo driver you are using. The Gemfile.lock will provide you with the exact versions.

If you are new to ScaleGrid and want to give this tutorial a try, sign up for a free 30-day trialto explore the platform and test out connecting MongoDB to your Ruby application.

Categories: Cloud, Technical
Tags: database, databases, developers, MongoDB, security

About Dharshan Rangegowda

ScaleGrid offers a fully managed MongoDB, MySQL, PostgreSQL and Redis on AWS, Azure, and DigitalOcean. Bring your own cloud account or host with us. Deploy standalone, replica sets or shards.

Primary Sidebar

E-mail Newsletter

Sign up to receive email updates daily and to hear what's going on with us!

Publish
AN Article
Submit
a press release
List
AN Event
Create
A Job Post

Related Articles

The Advantages of IT Staff Augmentation Over Traditional Hiring

May 4, 2023 By Mukesh Ram

The State of Digital Asset Management in 2023

May 3, 2023 By pimcoremkt

Test Data Management – Implementation Challenges and Tools Available

May 1, 2023 By yash.mehta262

Related Jobs

  • Software Engineer | South Yorkshire, GB - February 07, 2023
  • Software Engineer with C# .net Investment House | London, GB - February 07, 2023
  • Senior Java Developer | London, GB - February 07, 2023
  • Software Engineer – Growing Digital Media Company | London, GB - February 07, 2023
  • LBG Returners – Senior Data Analyst | Chester Moor, GB - February 07, 2023
More Jobs

Tags

AI Amazon analysis analytics app application Artificial Intelligence BI Big Data business China Cloud Companies company costs crypto customers Data design development digital engineer engineering environment experience future Google+ government health information machine learning market mobile news public research security services share skills social social media software strategy technology

Related Events

  • 6th Middle East Banking AI & Analytics Summit 2023 | Riyadh, Saudi Arabia - May 10, 2023
  • Data Science Salon NYC: AI & Machine Learning in Finance & Technology | The Theater Center - December 7, 2022
  • Big Data LDN 2023 | Olympia London - September 20, 2023
More events

Related Online Courses

  • Oracle Cloud Data Management Foundations Workshop
  • Data Science at Scale
  • Statistics with Python
More courses

Footer


Datafloq is the one-stop source for big data, blockchain and artificial intelligence. We offer information, insights and opportunities to drive innovation with emerging technologies.

  • Facebook
  • LinkedIn
  • RSS
  • Twitter

Recent

  • 5 Reasons Why Modern Data Integration Gives You a Competitive Advantage
  • 5 Most Common Database Structures for Small Businesses
  • 6 Ways to Reduce IT Costs Through Observability
  • How is Big Data Analytics Used in Business? These 5 Use Cases Share Valuable Insights
  • How Realistic Are Self-Driving Cars?

Search

Tags

AI Amazon analysis analytics app application Artificial Intelligence BI Big Data business China Cloud Companies company costs crypto customers Data design development digital engineer engineering environment experience future Google+ government health information machine learning market mobile news public research security services share skills social social media software strategy technology

Copyright © 2023 Datafloq
HTML Sitemap| Privacy| Terms| Cookies

  • Facebook
  • Twitter
  • LinkedIn
  • WhatsApp

In order to optimize the website and to continuously improve Datafloq, we use cookies. For more information click here.

settings

Dear visitor,
Thank you for visiting Datafloq. If you find our content interesting, please subscribe to our weekly newsletter:

Did you know that you can publish job posts for free on Datafloq? You can start immediately and find the best candidates for free! Click here to get started.

Not Now Subscribe

Thanks for visiting Datafloq
If you enjoyed our content on emerging technologies, why not subscribe to our weekly newsletter to receive the latest news straight into your mailbox?

Subscribe

No thanks

Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.

Necessary Cookies

Strictly Necessary Cookie should be enabled at all times so that we can save your preferences for cookie settings.

If you disable this cookie, we will not be able to save your preferences. This means that every time you visit this website you will need to enable or disable cookies again.

Marketing cookies

This website uses Google Analytics to collect anonymous information such as the number of visitors to the site, and the most popular pages.

Keeping this cookie enabled helps us to improve our website.

Please enable Strictly Necessary Cookies first so that we can save your preferences!