mongodb/mongo-ruby-driver

View on GitHub
docs/reference/authentication.txt

Summary

Maintainability
Test Coverage
**************
Authentication
**************

.. default-domain:: mongodb

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

MongoDB supports a variety of
:manual:`authentication mechanisms </core/authentication/>`.

For more information about configuring your MongoDB server for each of
these authentication mechanisms see MongoDB's
:manual:`online documentation </tutorial/enable-authentication>`.

For more information about users and the Ruby driver's helpers for
user management, see the :ref:`User Management tutorial<user-management>`.


Providing credentials
=====================

If authentication is enabled, provide credentials when creating a new
client:

.. code-block:: ruby

  client = Mongo::Client.new([ '127.0.0.1:27017' ],
                             user: 'test',
                             password: '123',
                             database: 'mydb' )

  # If using a URI:
  client = Mongo::Client.new("mongodb://test:123@127.0.0.1:27017/mydb")

Authentication credentials can be changed on a client instance to obtain
a new client using the ``Client#with`` method:

.. code-block:: ruby

  authenticated_client = client.with( user: 'another-user',
                                      password: '123' )

It is also possible to change the client's database and credentials in
one step:

.. code-block:: ruby

  authenticated_music_client = client.with( database: 'music',
                                            user:'test',
                                            password:'123' )


.. _auth-source:

Auth Source
===========

A user's auth source is the database where that user's authentication
credentials are stored.

The user's auth source may be specified whenever the credentials are specified:

.. code-block:: ruby

  client = Mongo::Client.new([ '127.0.0.1:27017' ],
                             database: 'mydb',
                             user: 'test',
                             password: '123',
                             auth_source: 'admin' )

  # If using a URI:
  client = Mongo::Client.new("mongodb://test:123@127.0.0.1:27017/mydb?authSource=admin")

If no auth source is specified, then a default will be assumed by the client.
The default auth source depends on the authentication mechanism that is being
used to connect.

For the ``MONGODB-CR``, ``SCRAM-SHA-1``, and ``SCRAM-SHA-256`` authentication
mechanisms, the default auth source is the database to which the client is
connecting; if no database is specified, ``admin`` database is the default
database and hence the default auth source. For the ``PLAIN`` mechanism (LDAP),
the default auth source is the database to which the client is connecting;
if no database is specified, the ``$external`` database is used as the
auth source. For the ``AWS``, ``GSSAPI`` and ``MONGODB_X509`` mechanisms, the
auth source is always ``$external``.

When a client is constructed using an SRV URI, the driver will look for URI
options in a TXT DNS record that corresponds to the SRV record. Thus, for
example, MongoDB Atlas generally uses the ``admin`` database as its auth
source, but this is not specified in SRV URIs because the database is given
as a URI option on the TXT records.

Note that when using SRV URIs, the SRV query and the TXT query are performed
separately. On systems where DNS resolution is not 100% reliable, the
failure to look up TXT records can cause authentication errors, as the driver
may end up using an incorrect auth source. If reliable DNS resolution cannot
be guaranteed, the auth source can be specified explicitly in SRV URIs as
a URI option:

.. code-block:: ruby

  Mongo::Client.new("mongodb+srv://username:myRealPassword@cluster0.mongodb.net/test?w=majority&authSource=admin")

.. note::

  When changing the database using the ``with`` method, the auth source is
  determined in the new ``Client`` instance using the full set of options
  that applies to it. For example, if the original client had an auth source
  specified, this auth source would take precedence over the database
  given in the ``with`` call. If the original client did not have an auth
  source specified, the new database would be the new auth source, subject
  to the rules of the authentication mechanism used.


Authentication Mechanisms
=========================

MongoDB supports several authentication mechanisms, as detailed in this section.
Authentication mechanism to use can be explicitly specified when a Client is
created; if authentication mechanism is not provided by the application, it is
selected as follows:

- For MongoDB 4.0 and higher, the client performs SCRAM mechanism negotiation
  with the server. If the user specified in client configuration permits
  authentication with SCRAM-SHA-256, then SCRAM-SHA-256 is used for
  authentication. Otherwise SCRAM-SHA-1 is used.
- For MongoDB 3.0 through 3.6, SCRAM-SHA-1 is used.
- For MongoDB 2.6, MONGODB-CR is used.

Note that:

- X.509, AWS, LDAP and Kerberos authentication mechanisms must always be
  explicitly requested.
- If the MongoDB server that the client is connecting to supports SCRAM,
  the client will attempt to authenticate using SCRAM if no authentication
  mechanism is explicitly specified. To authenticate to MongoDB 3.0 and
  higher servers using MONGODB-CR, the MONGODB-CR mechanism must be
  explicitly requested.

.. _scram:

SCRAM
`````

:manual:`SCRAM authentication </core/security-scram/>` is the default
authentication mechanism for MongoDB. There are two SCRAM mechanisms in
MongoDB: SCRAM-SHA-1 (available as of MongoDB 3.0) and SCRAM-SHA-256
(available as of MongoDB 4.0). If an authentication mechanism is not
specified but user credentials are, the driver will attempt to use SCRAM
authentication on server 3.0 or newer and will negotiate the mechanism
to use based on the server version and the mechanisms defined for a
particular user (it is possible to configure a user in the server to only
allow SCRAM-SHA-1 mechanism, only SCRAM-SHA-256 mechanism or both).

To explicitly specify SCRAM-SHA-1 as the authentication mechanism, use the
``auth_mech: :scram`` Ruby client option or the ``SCRAM-SHA-1`` as the value
for the ``authMechanism`` URI option, as follows:

.. code-block:: ruby

  client = Mongo::Client.new([ '127.0.0.1:27017' ],
                             database: 'mydb',
                             user: 'test',
                             password: '123',
                             auth_mech: :scram )

  client = Mongo::Client.new("mongodb://test:123@127.0.0.1:27017/mydb?authMechanism=SCRAM-SHA-1")

To explicitly specify SCRAM-SHA-256 as the authentication mechanism, use the
``auth_mech: :scram256`` Ruby client option or the ``SCRAM-SHA-256`` as the
value for the ``authMechanism`` URI option, as follows:

.. code-block:: ruby

  client = Mongo::Client.new([ '127.0.0.1:27017' ],
                             database: 'mydb',
                             user: 'test',
                             password: '123',
                             auth_mech: :scram256 )

  client = Mongo::Client.new("mongodb://test:123@127.0.0.1:27017/mydb?authMechanism=SCRAM-SHA-256")


.. _x.509:

Client Certificate (X.509)
``````````````````````````

The driver presents an X.509 certificate during TLS negotiation.
The MONGODB-X509 authentication mechanism authenticates a username
retrieved from the distinguished subject name of this certificate.

.. note::

  Since the username is retrieved from the certificate, a username does not
  need to be specified. If a username is specified, it will be sent to the
  server verbatim. If a password is provided, an error will be raised.

This authentication method requires the use of TLS connections with
certificate validation.

To authenticate the client, you will need a valid TLS certificate
and private encryption key. These can be stored in separate files,
or together in one file (in the PEM format). Even if the certificate
and private key are stored in the same file, you must specify the path to
that file by passing both the ``ssl_cert`` and ``ssl_key`` options
to the client.

For more information about configuring X.509 authentication in MongoDB,
see the :manual:`X.509 tutorial in the MongoDB Manual
</tutorial/configure-x509/>`.

.. code-block:: ruby

  client = Mongo::Client.new([ '127.0.0.1:27017' ],
                             auth_mech: :mongodb_x509,
                             ssl: true,
                             ssl_cert: '/path/to/client.pem',
                             ssl_key: '/path/to/client.pem',
                             ssl_ca_cert: '/path/to/ca.pem' )


.. _aws-auth:

AWS
```

*Requires MongoDB Enterprise Edition and server version 4.4 or later.*

The AWS authentication mechanism uses AWS `Identity and Access Management (IAM)
<https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html>`_
and AWS `Security Token Service (STS)
<https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html>`_
to prove the client's identity to a MongoDB server. Briefly, AWS authentication
works as follows:

1. The client uses AWS IAM credentials to create a signature that is sent to
   the MongoDB server.
2. The server sends a request to AWS STS using the client's signature.
3. A successful STS request returns the username (technically, the ARN of
   the IAM user or role) corresponding to the credentials that the client used.
   The IAM user ARN is used by the server to look up a defined user, and the
   client is considered to have authenticated as this user.

.. note::

  Unlike other authentication mechanisms, the username that the application
  provides when creating a client and the username of the server user are
  different: the username on the client is the AWS access key ID, but the
  username on the server is the ARN of the IAM user or role corresponding
  to the access key ID.

AWS credentials are comprised of:

- The access key ID.
- The secret access key.
- The optional session token.

Authentication with `AWS IAM credentials
<https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html>`_,
uses the access key ID and the secret access key. Authentication with
`temporary AWS IAM credentials
<https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html>`_
uses all three components.

.. note::

  The driver never sends the secret access key or the session token over
  the network.

Temporary credentials are used with:

- STS `Assume Role <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-api.html>`_
  requests.
- `EC2 instance roles <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html>`_.
- `ECS task roles <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html>`_.
- `AWS Lambda environment <https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html>`_.
- `IAM roles for service accounts <https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html>`_.

The Ruby driver allows providing both regular and temporary credentials
explicitly as Ruby options or URI options. If credentials are not explicitly
provided, the driver will attempt to retrieve them from environment variables
described below and from EC2 instance and ECS task metadata endpoints.

Providing Credentials Explicitly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Regular (non-temporary) IAM credentials can be provided as Ruby options,
as follows:

.. code-block:: ruby

  client = Mongo::Client.new(['mongodb.example.com'],
    auth_mech: :aws,
    user: '<AWS-ACCESS-KEY-ID>',
    password: '<AWS-SECRET-ACCESS-KEY>',
    database: 'mydb',
  )

They can also be provided via a URI:

.. code-block:: ruby

  client = Mongo::Client.new(
    'mongodb://<AWS-ACCESS-KEY-ID>:<AWS-SECRET-ACCESS-KEY>@mongodb.example.com/mydb?authMechanism=MONGODB-AWS')

.. note::

  When credentials are provided via a URI, they must be percent-escaped.

To provide temporary credentials, specify the session token in the
authentication mechanism properties as follows:

.. code-block:: ruby

  client = Mongo::Client.new(['mongodb.example.com'],
    auth_mech: :aws,
    user: '<AWS-ACCESS-KEY-ID>',
    password: '<AWS-SECRET-ACCESS-KEY>',
    auth_mech_properties: {
      aws_session_token: '<AWS-SESSION-TOKEN>',
    },
    database: 'mydb',
  )

The temporary credentials can also be provided via a URI:

.. code-block:: ruby

  client = Mongo::Client.new(
    'mongodb://<AWS-ACCESS-KEY-ID>:<AWS-SECRET-ACCESS-KEY>@mongodb.example.com/mydb?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:<AWS-SESSION-TOKEN>')

.. _auto-retrieve-aws-credentials:

Automatically Retrieving Credentials
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The client can retrieve credentials from the environment or from EC2 or ECS
metadata endpoints. To retrieve credentials automatically, specify the
AWS authentication mechanism but do not specify a username nor a password:

.. code-block:: ruby

  client = Mongo::Client.new(['mongodb.example.com'],
    auth_mech: :aws,
    database: 'mydb',
  )

  # Using a URI:
  client = Mongo::Client.new(
    'mongodb://mongodb.example.com/mydb?authMechanism=MONGODB-AWS')

The driver will try to obtain credentials from the following sources, in
the specified order:

- ``AWS_ACCESS_KEY_ID``, ``AWS_SECRET_ACCESS_KEY`` and ``AWS_SESSION_TOKEN``
  environment variables. These environment variables are recognized by
  a variety of AWS-related libraries and tools such as the official
  AWS Ruby SDK and the AWS CLI. They are also defined when running in an
  AWS Lambda environment.
- The AWS STS `AssumeRoleWithWebIdentity action
  <https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html>`_.
  This returns credentials associated with the service account token. This mechanism
  requires the following environment variables to be set:

  - ``AWS_WEB_IDENTITY_TOKEN_FILE`` - path to a file containing the service
    account token.
  - ``AWS_ROLE_ARN`` - the Amazon Resource Name (ARN) of the role that the
    caller is assuming.
  - ``AWS_ROLE_SESSION_NAME`` (optional) - An identifier for the assumed role
    session. If omitted, a random name will be generated by the driver.

- The AWS `ECS task metadata endpoint
  <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html>`_.
  This returns credentials associated with the ECS task role assigned to
  the container.
- The AWS `EC2 instance metadata endpoint
  <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html>`_.
  This returns credentials associated with the EC2 instance role assigned to
  the instance.

.. note::

  A credentials source that provides any credentials must provide a complete
  set of credentials. For example, the driver will raise an error if only
  one of ``AWS_ACCESS_KEY_ID`` or ``AWS_SECRET_ACCESS_KEY`` environment
  variables is populated but not the other.

.. note::

  If an application is running in an ECS container on an EC2 instance and
  `the container is allowed access to the instance metadata
  <https://aws.amazon.com/premiumsupport/knowledge-center/ecs-container-ec2-metadata/>`_,
  the driver will attempt to retrieve credentials for the AWS authentication
  mechanism from the EC2 instance metadata endpoint, thus potentially
  authenticating as the IAM role assigned to the EC2 instance, if it was not
  able to retrieve ECS task role credentials from the ECS task endpoint.


.. _plain:

LDAP (SASL PLAIN)
`````````````````

*Requires MongoDB Enterprise Edition.*

MongoDB Enterprise Edition supports the LDAP authentication mechanism
which allows you to delegate authentication using a Lightweight Directory
Access Protocol `LDAP <http://en.wikipedia.org/wiki/LDAP>`_ server.

.. warning::

  When using LDAP, passwords are sent to the server in plain text. For this
  reason, we strongly recommend enabling TLS when using LDAP as your
  authentication mechanism.

For more information about configuring LDAP authentication in
MongoDB, see the :manual:`SASL/LDAP tutorial in the MongoDB Manual
</tutorial/configure-ldap-sasl-authentication/>`.

.. code-block:: ruby

  client = Mongo::Client.new([ '127.0.0.1:27017' ],
                             auth_mech: :plain,
                             ssl: true,
                             ssl_verify: true,
                             ssl_cert: '/path/to/client.pem',
                             ssl_ca_cert: '/path/to/ca.pem' )


.. _kerberos:

Kerberos (GSSAPI)
`````````````````

*Requires MongoDB Enterprise Edition.*

To configure the MongoDB server to use Kerberos, please refer to the
:manual:`server Kerberos documentation
</tutorial/control-access-to-mongodb-with-kerberos-authentication/>`.

To use the Kerberos authentication mechanism with the Ruby MongoDB driver,
an additional library implementing the Kerberos authenticator -
`mongo_kerberos <https://rubygems.org/gems/mongo_kerberos>`_ - must be
installed and loaded. To do so, add to your ``Gemfile``:

.. code-block:: ruby

  gem 'mongo', '~> 2'
  gem 'mongo_kerberos', '~> 2'

... and add to your application code:

.. code-block:: ruby

  require 'mongo'
  require 'mongo_kerberos'

If using Kerberos authentication with **MRI**, the password is not specified
in driver configuration and it is not sent to the MongoDB server by the driver.
Instead a Kerberos session must be established externally to the driver
and this session is used by the driver to prove the user's identity to
the server. Establishing this session requires that the host system is
configured for Kerberos authentication; refer to the `Kerberos documentation
<https://web.mit.edu/kerberos/krb5-latest/doc/admin/install_clients.html>`_
or your operating system documentation for details. Use the `kinit utility
<https://web.mit.edu/kerberos/krb5-latest/doc/user/user_commands/kinit.html>`_
to establish a Kerberos session.

If using Kerberos authentication with **JRuby**, the Kerberos session may
be estabished externally to the driver using the process described above
for MRI; alternatively, the password may be provided directly to the driver
via client configuration, or the path to a keytab file may be provided via
configuration stored in the ``java.security.auth.login.config`` system property.
Additionally, the Java runtime environment must be configured for Kerberos;
please refer to the  `MongoDB Java Driver Kerberos documentation
<https://mongodb.github.io/mongo-java-driver/4.0/driver/tutorials/authentication/#gssapi>`_
for more information.

.. note::

  As per the server Kerberos documentation, the FQDN of the host
  running MongoDB must be specified when using Kerberos authentication.

.. note::

  If using MongoDB URIs, be sure to percent-escape special characters like
  ``/`` and ``@`` when they appear in the username.

.. code-block:: ruby

  # Authenticate as appuser@MYREALM:
  client = Mongo::Client.new("mongodb://appuser%40MYREALM@myserver.mycompany.com:27017/mydb?authMechanism=GSSAPI")

  # Authenticate as myapp/appuser@MYREALM:
  client = Mongo::Client.new("mongodb://myapp%2Fappuser%40MYREALM@myserver.mycompany.com:27017/mydb?authMechanism=GSSAPI")

  # Authenticate using Ruby options:
  client = Mongo::Client.new(['myserver.mycompany.com:27017'],
                             auth_mech: :gssapi,
                             user: 'myapp/appuser@MYREALM')


MONGODB-CR
``````````

*Deprecated:* MONGODB-CR mechanism is deprecated as of MongoDB 3.6 and
removed as of MongoDB 4.0. Please use `SCRAM authentication <#scram>`_ instead.

MONGODB-CR was the default authentication mechanism for MongoDB through
version 2.6.

The mechanism can be explicitly set with the credentials:

.. code-block:: ruby

  client = Mongo::Client.new([ '127.0.0.1:27017' ],
                             database: 'mydb',
                             user: 'test',
                             password: '123',
                             auth_mech: :mongodb_cr )

.. note::

  If the MongoDB server that the client is connecting to supports SCRAM,
  the client will attempt to authenticate using SCRAM if no authentication
  mechanism is explicitly specified. To authenticate to MongoDB 3.0 and
  higher servers using MONGODB-CR, the MONGODB-CR mechanism must be
  explicitly requested.