Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

DOCSP-45179 Configure TLS #129

Merged
merged 15 commits into from
Jan 17, 2025
5 changes: 3 additions & 2 deletions source/connect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ Connect to MongoDB
:titlesonly:
:maxdepth: 1

/connect/mongoclient
/connect/stable-api
Create a Client </connect/mongoclient>
Stable API </connect/stable-api>
Configure TLS </connect/tls>
247 changes: 247 additions & 0 deletions source/connect/tls.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
.. _ruby-tls:

========================================
Configure Transport Layer Security (TLS)
========================================

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: security, authentication, transport layer security, encrypt

Overview
--------

In this guide, you can learn how to use the Transport Layer Security (TLS)
protocol to secure your connection to a MongoDB deployment.

To connect to a MongoDB deployment using TLS, you must:

- Enable a TLS connection in ``Mongo::Client``.
- Specify the client TLS certificate.
- Specify the CA certificate to verify the server's TLS certificate.

To learn how to configure your MongoDB deployment for TLS, see the
:manual:`TLS configuration guide </tutorial/configure-ssl/>` in the
{+mdb-server+} manual.

.. note::

This page assumes prior knowledge of TLS/SSL and access to valid certificates.
A full description of TLS/SSL, PKI (Public Key Infrastructure) certificates, and
Certificate Authorities (CAs) is beyond the scope of this documentation. To
learn more about TLS, see the Wikipedia entry for :wikipedia:`Transport Layer Security <Transport_Layer_Security>`.

.. _ruby-enable-tls:

Enable TLS
----------

You can enable TLS for the connection to your MongoDB deployment in the following ways:

- Set the ``ssl`` option to ``true`` in a new ``Mongo:Client`` object
- Set the ``tls`` option to ``true`` in your connection string

.. note:: SSL Naming Convention

All {+mdb-server+} versions supported by the Ruby driver (2.6 and higher)
only implement TLS. 2.6 and do not use SSL.

For historical reasons, the Ruby option names pertaining to TLS configuration
use the ``ssl`` rather than the ``tls`` prefix. The next major version of the Ruby
driver (3.0) will use the ``tls`` prefix for Ruby option names.

.. tabs::

.. tab:: Mongo::Client
:tabid: mongoclient

To configure certificates, you must specify the following options:

- ``ssl_cert``: The certificate file used to identify the connection against MongoDB.
- ``ssl_key``: The private keyfile used to identify the connection against MongoDB.
- ``ssl_ca_cert``: The file containing the concatenated CA certificates
used to validate certs passed from the other end of the connection.
By default, the driver will use the default system root certificate
store as the trust anchor, if the option is not designated.

These certificate options can be specified as different types. For example, the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s: instead of spelling this out, you could put the options in a table that includes a column for 'data type'

``ssl_cert`` option has the alternative ``ssl_cert_object`` and ``ssl_cert_string``
options, to specify the certificate file as either a certificate object or a string.
For more information on certificate options, see the Options Hash section of
the API Documentation for `Mongo::Client <{+api-root+}/Mongo/Client.html>`__ .

In the following example, the TLS certificate and corresponding private key
are provided in separate files:

.. literalinclude:: /includes/connect/tls.rb
:language: ruby
:dedent:
:start-after: start-enable-tls-settings
:end-before: end-enable-tls-settings

The TLS certificate and private key can be contained in the same file, but
both the certificate and private key options must still be specified. In the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s: shortened

Suggested change
The TLS certificate and private key can be contained in the same file, but
both the certificate and private key options must still be specified. In the
You can specify both the TLS certificate and private key in a single file.
In the

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the edit! Will keep in the part about still needing to specify both options, as I think it's important to clarify.

following example, the TLS certificate and the private key are both defined
in the same ``client.pem`` file:

.. literalinclude:: /includes/connect/tls.rb
:language: ruby
:dedent:
:start-after: start-enable-tls-settings-same-file
:end-before: end-enable-tls-settings-same-file

.. tab:: Connection String
:tabid: uri

To configure certificates, you must specify the following URI options:

- ``tlsCertificateKeyFile``: The certificate and key file used to identify
identify the connection against MongoDB. Both the certificate and key
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: is 'identify the connection against mongodb' the right language? i would have gone for 'identify the client to MongoDB' or something similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'identify the connection against mongodb' is the language used in the API documentation, but it is a bit strange sounding. Changed to 'verify the connection to MongoDB' .

must be stored in the same file provided to this option.
- ``tlsCAFile``: The file containing the concatenated certificate authority (CA)
certificates used to validate certificates passed from the other end of the
connection. The driver will use the default system root certificate
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s: does this mean server to client, client to server, or both? i would be specific.

Copy link
Contributor Author

@lindseymoore lindseymoore Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to say 'from the Mongo deployment to the client', which I think is the correct flow. I can ask the technical reviewer to make sure.

store as the trust anchor, if the option is not designated.

.. literalinclude:: /includes/connect/tls.rb
:language: ruby
:dedent:
:start-after: start-enable-tls-uri
:end-before: end-enable-tls-uri

The file containing the certificate and key usually has a``.crt`` or ``.pem``
extension.

URI option values must be properly URI escaped. This applies, for example,
to slashes (/) in the paths, which are encoded as ``%2f``.

Modify the SSL Context
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: this section talks only about TLS options. is 'Modify the TLS Context' a more appropriate heading?

Copy link
Contributor Author

@lindseymoore lindseymoore Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the method has TLS in it, sounds good! I edited the following text, since Ruby calls it SSL Context.

----------------------

If your TLS configuration requires customization, you can set TLS context hooks
by adding a native Ruby class ``Proc`` object to the ``Mongo.tls_context_hooks``
array. The ``Proc`` should be added to the array before creating any ``Mongo::Client``
instances.

For example, the following code could be placed in an initializer to enable the
AES256-SHA cipher as the only cipher to be used for TLS:

.. literalinclude:: /includes/connect/tls.rb
:language: ruby
:dedent:
:start-after: start-modify-context
:end-before: end-modify-context

To learn more about the SSL context options available, see the Ruby
documentation for
`SSLContext <https://ruby-doc.org/stdlib-2.7.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html>`__.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For technical reviewer, is this an appropriate link to put for reference? I wasn't able to find much information on context options in our docs. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ruby 2.7 is EOL, so that link is probably not ideal. Linking out to the Ruby docs is otherwise probably fine, we just need to make sure the links remain relevant.

Here's the link to the same class, for Ruby 3.2.6: https://ruby-doc.org/3.2.6/exts/openssl/OpenSSL/SSL/SSLContext.html


OCSP Verification
-----------------

If the certificate provided by the server contains an OCSP endpoint URI,
the driver will issue an OCSP request to the specified endpoint to verify the
validity of the certificate by default.

The OCSP endpoint check may be disabled by setting the
``:ssl_verify_ocsp_endpoint`` Ruby option to ``false`` or by setting the
``tlsDisableOCSPEndpointCheck`` URI option to ``true`` when creating a client.

.. note::

OCSP endpoint checking is not currently performed when running on JRuby,
since JRuby does not correctly expose the OCSP endpoint URI.

Allow Insecure TLS
------------------

When TLS is enabled, the {+driver-short+} automatically verifies the certificate that
the server presents. When testing your code, you can disable this verification.
This is known as *insecure TLS*.

When insecure TLS is enabled, the driver requires only that the server present an
X.509 certificate. The driver accepts a certificate even if any of the following are
true:

- The hostname of the server and the subject name (or subject alternative name)
on the certificate don't match.
- The certificate is expired or not yet valid.
- The certificate doesn't have a trusted root certificate in the chain.
- The certificate purpose isn't valid for server identification.

.. note::

Even when insecure TLS is enabled, communication between the client and server
is encrypted with TLS.

To enable insecure TLS, set the ``sslVerify`` client option or the ``tlsInsecure``
URI option to ``true``:

.. tabs::

.. tab:: Mongo::Client
:tabid: mongoclient

.. literalinclude:: /includes/connect/tls.rb
:language: ruby
:dedent:
:start-after: start-ssl-verify
:end-before: end-ssl-verify

.. tab:: Connection String
:tabid: uri

.. literalinclude:: /includes/connect/tls.rb
:language: ruby
:dedent:
:start-after: start-tls-insecure
:end-before: end-tls-insecure

You can similarly set the following options to disable verification for the
certificate or hostname:

.. tabs::

.. tab:: Mongo::Client
:tabid: mongoclient

- ssl_verify_certificate: Disable certificate validation by setting the
option to ``false``.
- ssl_verify_hostname: Disable hostname verification by setting the option
to ``false``.

.. tab:: Connection String
:tabid: uri

- tlsAllowInvalidCertificates: Disable certificate validation by setting
the option to ``true``.
- tlsAllowInvalidHostnames: Disable hostname validation by setting
the option to ``true``.

.. warning:: Don't Use Insecure TLS in Production

Always disable insecure TLS in production.

Enabling insecure TLS in a production environment makes your application
insecure and potentially vulnerable to expired certificates and foreign
processes posing as valid client instances.

.. _ruby-tls-api:

API Documentation
-----------------

For more information about any of the types and methods discussed in this guide,
see the following API documentation:

- `Mongo::Client <{+api-root+}/Mongo/Client.html>`__
- `tls_context_hooks <{+api-root+/Mongo.html#tls_context_hooks-class_method}>`__
41 changes: 41 additions & 0 deletions source/includes/connect/tls.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# start-enable-tls-settings
client = Mongo::Client.new(["<hostname>:<port>"],
ssl: true,
ssl_cert: 'path/to/client.crt',
ssl_key: 'path/to/client.key',
ssl_ca_cert: 'path/to/ca.crt'
)
# end-enable-tls-settings

# start-enable-tls-settings-same-file
client = Mongo::Client.new(["<hostname>:<port>"],
ssl: true,
ssl_cert: 'path/to/client.pem',
ssl_key: 'path/to/client.pem',
ssl_ca_cert: 'path/to/ca.crt',
)
# end-enable-tls-settings-same-file

# start-enable-tls-uri
client = Mongo::Client.new(
"mongodb://<hostname>:<port>/?tls=true&tlsCertificateKeyFile=path%2fto%2fclient.pem&tlsCAFile=path%2fto%2fca.crt")
# end-enable-tls-uri

# start-modify-context
Mongo.tls_context_hooks.push(
Proc.new { |context|
context.ciphers = ["AES256-SHA"]
}
)
# end-modify-context

# start-ssl-verify
client = Mongo::Client.new(["<hostname>:<port>"],
ssl: true,
ssl_verify: false
)
# end-ssl-verify

# start-tls-insecure
client = Mongo::Client.new('mongodb://<hostname>:<port>/?tls=true&tlsInsecure=true');
# end-tls-insecure
Loading