Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

DOCSP-43473: oidc #382

Merged
merged 10 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions snooty.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ cmk-long = "Customer Master Key"
dek-long = "Data Encryption Key"
csfle-short = "CSFLE"
csfle-long = "Client-side Field Level Encryption"
mdb-server = "MongoDB Server"
2 changes: 1 addition & 1 deletion source/connection-troubleshooting.txt
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ instance. For more information about configuring the firewall, see
Check the Number of Connections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Each ``MongoClient`` instance supports a maximum number of concurrent open
Each ``Client`` instance supports a maximum number of concurrent open
connections in its connection pool. The configuration parameter ``maxPoolSize``
defines this value and is set to ``100`` by default. If there are already a
number of open connections equal to ``maxPoolSize``, the server waits until
Expand Down
310 changes: 309 additions & 1 deletion source/fundamentals/enterprise-auth.txt
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,324 @@ address of your MongoDB server:
authenticates using the PLAIN Simple Authentication and Security Layer
(SASL) defined in `RFC-4616 <https://tools.ietf.org/html/rfc4616>`__.

.. _golang-mongodb-oidc:

MONGODB-OIDC
------------

.. important::

The MONGODB-OIDC authentication mechanism requires {+mdb-server+}
v7.0 or later running on a Linux platform.

The {+driver-short+} supports OpenID Connect (**OIDC**) authentication for **workload
identities**. A workload identity is an identity you assign to a
software workload, such as an application, service, script, or
container, to authenticate and access other services and resources.

The following sections describe how to use the MONGODB-OIDC
authentication mechanism to authenticate to various platforms.

To learn more about the MONGODB-OIDC authentication mechanism, see
:manual:`OpenID Connect Authentication </core/security-oidc/>` and
:manual:`MongoDB Server Parameters </reference/parameters/#mongodb-parameter-param.oidcIdentityProviders>`
in the {+mdb-server+} manual.

.. _golang-mongodb-oidc-azure-imds:

Azure IMDS
~~~~~~~~~~

If your application runs on an Azure VM, or otherwise uses the
`Azure Instance Metadata Service <https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service>`__
(IMDS), you can authenticate to MongoDB by using the {+driver-short+}'s
built-in Azure support.
Comment on lines +230 to +231
Copy link
Collaborator

Choose a reason for hiding this comment

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

fyi: the info on azure imds and other platforms should be correct across all drivers, but the level of integration might not. for example, not every driver might have built-in support for azure, gcp, etc. The DBX team will know for sure.

Copy link
Collaborator

Choose a reason for hiding this comment

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

edit: based on the rest of the PR, looks like you've accounted for that!


You can configure OIDC for Azure IMDS in the following ways:

- By creating a ``Credential`` struct and passing it to the
``SetAuth()`` method when creating a client
- By setting parameters in your connection string

.. include:: /includes/authentication/auth-properties-commas.rst

.. tabs::

.. tab:: Credential
:tabid: credential struct

First, create a map to store your authentication
mechanism properties, as shown in the following example. Replace
the ``<audience>`` placeholder with the value of the ``audience``
parameter configured on your MongoDB deployment.

.. code-block:: go

props := map[string]string{
"ENVIRONMENT": "azure",
"TOKEN_RESOURCE": "<audience>",
}

Then, set the following ``Credential`` struct fields:

- ``Username``: If you're using an Azure managed identity, set this to the client ID
of the managed identity. If you're using a service principal to represent an
enterprise application, set this to the application ID of the service principal.
- ``AuthMechanism``: Set to ``"MONGODB-OIDC"``.
- ``AuthMechanismProperties``: Set to the ``props`` map that you
previously created.

The following code example shows how to set these options when creating a
``Client``:

.. literalinclude:: /includes/authentication/azure-imds-client.go
:dedent:
:language: go
:copyable: true
:start-after: start-azure-imds-client
:end-before: end-azure-imds-client
:emphasize-lines: 9-11

.. tab:: Connection String
:tabid: connectionstring

Include the following connection options in your connection string:

- ``username``: If you're using an Azure managed identity, set this to the client ID
of the managed identity. If you're using a service principal to represent an
enterprise application, set this to the application ID of the service principal.
- ``authMechanism``: Set to ``MONGODB-OIDC``.
- ``authMechanismProperties``: Set to
``ENVIRONMENT:azure,TOKEN_RESOURCE:<audience>``.
Replace the ``<audience>`` placeholder with the
value of the ``audience`` parameter configured on your MongoDB deployment.

The following code example shows how to set these options in
your connection string:

.. code-block:: go

uri := "mongodb://<hostname>:<port>/?" +
"username=<Azure client ID or application ID>" +
"&authMechanism=MONGODB-OIDC" +
"&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:<percent-encoded audience>"

client, err := mongo.Connect(options.Client().ApplyURI(uri))
Copy link
Collaborator

@matthewdale matthewdale Sep 13, 2024

Choose a reason for hiding this comment

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

This is valid for the Go Driver v2.0 API, but not for v1.17. If this is intended to document v1.17, the first argument to Connect must be a Context value.

This comment applies to all mongo.Connect calls in this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This Pr is against the master branch of the docs, which is tracking for the v2 release. When I backport this ticket to the v1.17 branch, I'll make sure to correct that!

if err != nil {
panic(err)
}

.. tip::

If your application is running on an Azure VM, and only one managed identity is
associated with the VM, you can omit the ``username`` connection option.

.. _golang-mongodb-oidc-gcp-imds:

GCP IMDS
~~~~~~~~

If your application runs on a Google Compute Engine VM, or otherwise uses the
`GCP Instance Metadata Service <https://cloud.google.com/compute/docs/metadata/querying-metadata>`__,
you can authenticate to MongoDB by using the {+driver-short+}'s built-in GCP
support.

You can configure OIDC for GCP IMDS in the following ways:

- By creating a ``Credential`` struct and passing it to the
``SetAuth()`` method when creating a client
- By setting parameters in your connection string

.. include:: /includes/authentication/auth-properties-commas.rst

.. tabs::

.. tab:: Credential
:tabid: credential struct

First, create a map to store your authentication
mechanism properties, as shown in the following example. Replace
the ``<audience>`` placeholder with the value of the ``audience``
parameter configured on your MongoDB deployment.

.. code-block:: go

props := map[string]string{
"ENVIRONMENT": "gcp",
"TOKEN_RESOURCE": "<audience>",
}

Then, set the following ``Credential`` struct fields:

- ``AuthMechanism``: Set to ``"MONGODB-OIDC"``.
- ``AuthMechanismProperties``: Set to the ``props`` map that you
previously created.

The following code example shows how to set these options when creating a
``Client``:

.. literalinclude:: /includes/authentication/gcp-imds-client.go
:language: go
:dedent:
:copyable: true
:start-after: start-gcp-imds-client
:end-before: end-gcp-imds-client
:emphasize-lines: 9-10

.. tab:: Connection String
:tabid: connectionstring

Include the following connection options in your connection string:

- ``authMechanism``: Set to ``MONGODB-OIDC``.
- ``authMechanismProperties``: Set to
``ENVIRONMENT:gcp,TOKEN_RESOURCE:<audience>``.
Replace the ``<audience>`` placeholder with the
value of the ``audience`` parameter configured on your MongoDB deployment.

The following code example shows how to set these options in your connection string:

.. code-block:: go

uri := "mongodb://<hostname>:<port>/?" +
"&authMechanism=MONGODB-OIDC" +
"&authMechanismProperties=ENVIRONMENT:gcp,TOKEN_RESOURCE:<percent-encoded audience>"

client, err := mongo.Connect(options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}

.. _golang-mongodb-oidc-custom-callback:

Custom Callback
~~~~~~~~~~~~~~~

The {+driver-short+} doesn't offer built-in support for all platforms,
including the AWS Elastic Kubernetes Service (EKS). To authenticate
against unsupported platforms, you must define a custom callback
function to use OIDC to authenticate. In the driver, you can define an
``options.OIDCCallback`` function and set it as the value of the
``OIDCMachineCallback`` struct field in your ``Credential`` struct.

The following example defines a custom callback for an EKS
cluster with a configured IAM OIDC provider. The access token is
read from a path set in the ``AWS_WEB_IDENTITY_TOKEN_FILE``
environment variable:

.. literalinclude:: /includes/authentication/eks-custom-callback.go
:language: go
:dedent:
:copyable: true
:start-after: start-custom-callback
:end-before: end-custom-callback

Next, create a map to store your authentication
mechanism properties, as shown in the following example. Replace
the ``<audience>`` placeholder with the value of the ``audience``
parameter configured on your MongoDB deployment.

.. code-block:: go

props := map[string]string{
"TOKEN_RESOURCE": "<audience>",
}

Then, you can create a ``Credential`` struct that uses the properties
map and the EKS callback function:

.. literalinclude:: /includes/authentication/eks-custom-callback.go
:language: go
:dedent:
:copyable: true
:start-after: start-credential-callback
:end-before: end-credential-callback
:emphasize-lines: 10

.. _golang-mongodb-oidc-azure-envs:

Other Azure Environments
~~~~~~~~~~~~~~~~~~~~~~~~

If your application runs on Azure Functions, App Service Environment (ASE), or Azure
Kubernetes Service (AKS), you can use the `azidentity
<https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity>`__
module to fetch authentication credentials.

First, install the ``azidentity`` module by running the
following command:

.. code-block:: sh

go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity

Your ``OIDCCallback`` function must return an ``OIDCCredential``
instance that uses the ``AccessToken`` generated from the ``azidentity``
package. See the preceding :ref:`golang-mongodb-oidc-custom-callback`
section for an example that implements a custom callback to retrieve an
access token and then creates a ``Credential``.

.. _golang-mongodb-oidc-gcp-gke:

GCP GKE
~~~~~~~

If your application runs on a GCP Google Kubernetes Engine (GKE) cluster with a
`configured service account
<https://cloud.google.com/kubernetes-engine/docs/how-to/service-accounts>`__,
you can read the OIDC token from the standard service-account token-file location.

First, define the ``OIDCCallback`` function. This function reads the
OIDC token and returns an ``OIDCCredential`` instance.

The following example defines a callback function named ``gkeCallback``.
The function retrieves an OIDC token from a file in the standard
service-account token-file location:

.. literalinclude:: /includes/authentication/gke-callback.go
:language: go
:copyable: true
:dedent:
:start-after: start-callback
:end-before: end-callback

Next, create a map to store your authentication
mechanism properties, as shown in the following example. Replace
the ``<audience>`` placeholder with the value of the ``audience``
parameter configured on your MongoDB deployment.

.. code-block:: go

props := map[string]string{
"ENVIRONMENT": "gcp",
"TOKEN_RESOURCE": "<audience>",
}

Then, you can create a ``Credential`` struct that uses the properties
map and the GKE callback function:

.. literalinclude:: /includes/authentication/gke-callback.go
:language: go
:copyable: true
:dedent:
:start-after: start-credential-callback
:end-before: end-credential-callback
:emphasize-lines: 11

Additional Information
----------------------

To learn more about the concepts in this guide, see the following documentation:

- :manual:`MongoDB Server Support for Kerberos Authentication </core/kerberos/>`
- :manual:`MongoDB Server Support for LDAP Proxy Authentication </core/security-ldap/>`
- :atlas:`Authentication and Authorization with OIDC/OAuth 2.0 </security-oidc/>`

API Documentation
~~~~~~~~~~~~~~~~~

- `Credential <{+api+}/mongo/options#Credential>`__ type
- `SetAuth() <{+api+}/mongo/options#ClientOptions.SetAuth>`__ method
- `SetAuth() <{+api+}/mongo/options#ClientOptions.SetAuth>`__ method

.. TODO - `OIDCCredential <{+api+}/...>`__ type
.. TODO - `OIDCCallback <{+api+}/...>`__ function
5 changes: 5 additions & 0 deletions source/includes/authentication/auth-properties-commas.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.. note::

If your ``AuthMechanismProperties`` struct field values
include a comma, you must create a ``Credential`` instance
to set your authentication options.
28 changes: 28 additions & 0 deletions source/includes/authentication/azure-imds-client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
// start-azure-imds-client
uri := "mongodb://<hostname>:<port>"
props := map[string]string{
"ENVIRONMENT": "azure",
"TOKEN_RESOURCE": "<audience>",
}
opts := options.Client().ApplyURI(uri)
opts.SetAuth(
options.Credential{
Username: "<Azure client ID or application ID>",
AuthMechanism: "MONGODB-OIDC",
AuthMechanismProperties: props,
},
)
client, err := mongo.Connect(opts)
if err != nil {
panic(err)
}
// end-azure-imds-client
}
Loading
Loading