From a1def1542abb65db3fe253bd19b77a31b2dfe4af Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 19 Apr 2024 10:55:20 -0500 Subject: [PATCH 1/3] PYTHON-4376 Document recommended dnspython version (#1610) --- doc/changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/changelog.rst b/doc/changelog.rst index 9a840e6e2..4f84e38a3 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -46,6 +46,10 @@ PyMongo 4.7 brings a number of improvements including: - Deprecated :attr:`pymongo.write_concern.WriteConcern.wtimeout` and :attr:`pymongo.mongo_client.MongoClient.wTimeoutMS`. Use :meth:`~pymongo.timeout` instead. +.. warning:: PyMongo depends on ``dnspython``, which released version 2.6.1 with a fix for + `CVE-2023-29483 `_. We do not explicitly require + that version, but we strongly recommend that you install at last that version in your environment. + Unavoidable breaking changes ............................ From 90906c3f9dfa44e02ef9da29f46771de8173a470 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 19 Apr 2024 13:06:39 -0500 Subject: [PATCH 2/3] PYTHON-4346 Remove CODEOWNERS file (#1609) --- .github/CODEOWNERS | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index a9d726b96..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -# Global owner for repo -* @mongodb/dbx-python From 2588ca3782c874fa5b6b80d886f4f5fb6607bdb3 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 19 Apr 2024 13:29:50 -0500 Subject: [PATCH 3/3] PYTHON-3601 OIDC: Add Documentation Examples (#1601) Co-authored-by: Noah Stapp --- .pre-commit-config.yaml | 2 +- doc/api/pymongo/auth_oidc.rst | 5 + doc/api/pymongo/index.rst | 1 + doc/examples/authentication.rst | 162 ++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 doc/api/pymongo/auth_oidc.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c605981a1..1a567b73f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -93,4 +93,4 @@ repos: # - test/test_bson.py:267: isnt ==> isn't # - test/versioned-api/crud-api-version-1-strict.json:514: nin ==> inn, min, bin, nine # - test/test_client.py:188: te ==> the, be, we, to - args: ["-L", "fle,fo,infinit,isnt,nin,te"] + args: ["-L", "fle,fo,infinit,isnt,nin,te,aks"] diff --git a/doc/api/pymongo/auth_oidc.rst b/doc/api/pymongo/auth_oidc.rst new file mode 100644 index 000000000..1466b21e9 --- /dev/null +++ b/doc/api/pymongo/auth_oidc.rst @@ -0,0 +1,5 @@ +:mod:`auth_oidc` -- MONGODB-OIDC Authentication +=========================================================================== + +.. automodule:: pymongo.auth_oidc + :members: diff --git a/doc/api/pymongo/index.rst b/doc/api/pymongo/index.rst index 625c13817..2beb8f574 100644 --- a/doc/api/pymongo/index.rst +++ b/doc/api/pymongo/index.rst @@ -29,6 +29,7 @@ Sub-modules: .. toctree:: :maxdepth: 2 + auth_oidc change_stream client_options client_session diff --git a/doc/examples/authentication.rst b/doc/examples/authentication.rst index b3ba89026..e038b47b8 100644 --- a/doc/examples/authentication.rst +++ b/doc/examples/authentication.rst @@ -384,3 +384,165 @@ would be:: .. _Assume Role: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html .. _EC2 instance: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html .. _environment variables: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + +MONGODB-OIDC +------------ +.. versionadded:: 4.7 + +The `MONGODB-OIDC authentication mechanism`_ is available in MongoDB 7.0+ on Linux platforms. + +The MONGODB-OIDC mechanism authenticates using an OpenID Connect (OIDC) access token. +The driver supports OIDC for workload identity, defined as an identity you assign to a software workload +(such as an application, service, script, or container) to authenticate and access other services and resources. + +Credentials can be configured through the MongoDB URI or as arguments to +:class:`~pymongo.mongo_client.MongoClient`. + +Built-in Support +~~~~~~~~~~~~~~~~ + +The driver has built-in support for Azure IMDS and GCP IMDS environments. Other environments +are supported with `Custom Callbacks`_. + +Azure IMDS +^^^^^^^^^^ + +For an application running on an Azure VM or otherwise using the `Azure Internal Metadata Service`_, +you can use the built-in support for Azure, where "" below is the client id of the Azure +managed identity, and ```` is the url-encoded ``audience`` `configured on your MongoDB deployment`_. + +.. code-block:: python + + import os + + uri = os.environ["MONGODB_URI"] + + props = {"ENVIRONMENT": "azure", "TOKEN_RESOURCE": ""} + c = MongoClient( + uri, + username="", + authMechanism="MONGODB-OIDC", + authMechanismProperties=props, + ) + c.test.test.insert_one({}) + c.close() + +If the application is running on an Azure VM and only one managed identity is associated with the +VM, ``username`` can be omitted. + +GCP IMDS +^^^^^^^^ + +For an application running on an GCP VM or otherwise using the `GCP Internal Metadata Service`_, +you can use the built-in support for GCP, where ```` below is the url-encoded ``audience`` +`configured on your MongoDB deployment`_. + +.. code-block:: python + + import os + + uri = os.environ["MONGODB_URI"] + + props = {"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} + c = MongoClient(uri, authMechanism="MONGODB-OIDC", authMechanismProperties=props) + c.test.test.insert_one({}) + c.close() + + +Custom Callbacks +~~~~~~~~~~~~~~~~ + +For environments that are not directly supported by the driver, you can use :class:`~pymongo.auth_oidc.OIDCCallback`. +Some examples are given below. + +AWS EKS +^^^^^^^ + +For an EKS Cluster with a configured `IAM OIDC provider`_, the token can be read from a path given by +the ``AWS_WEB_IDENTITY_TOKEN_FILE`` environment variable. + +.. code-block:: python + + import os + from pymongo.auth_oidc import OIDCCallback, OIDCCallbackContext, OIDCCallbackResult + + + class MyCallback(OIDCCallback): + def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: + with open(os.environ["AWS_WEB_IDENTITY_TOKEN_FILE"]) as fid: + token = fid.read() + return OIDCCallbackResult(access_token=token) + + + uri = os.environ["MONGODB_URI"] + props = {"OIDC_CALLBACK": MyCallback()} + c = MongoClient(uri, authMechanism="MONGODB-OIDC", authMechanismProperties=props) + c.test.test.insert_one({}) + c.close() + + +Other Azure Environments +^^^^^^^^^^^^^^^^^^^^^^^^ + +For applications running on Azure Functions, App Service Environment (ASE), or +Azure Kubernetes Service (AKS), you can use the `azure-identity package`_ +to fetch the credentials. This example assumes you have set environment variables for +the ``audience`` `configured on your MongoDB deployment`_, and for the client id of the Azure +managed identity. + +.. code-block:: python + + import os + from azure.identity import DefaultAzureCredential + from pymongo import MongoClient + from pymongo.auth_oidc import OIDCCallback, OIDCCallbackContext, OIDCCallbackResult + + audience = os.environ["AZURE_AUDIENCE"] + client_id = os.environ["AZURE_IDENTITY_CLIENT_ID"] + uri = os.environ["MONGODB_URI"] + + + class MyCallback(OIDCCallback): + def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: + credential = DefaultAzureCredential(managed_identity_client_id=client_id) + token = credential.get_token(f"{audience}/.default").token + return OIDCCallbackResult(access_token=token) + + + props = {"OIDC_CALLBACK": MyCallback()} + c = MongoClient(uri, authMechanismProperties=props) + c.test.test.insert_one({}) + c.close() + +GCP GKE +^^^^^^^ + +For a Google Kubernetes Engine cluster with a `configured service account`_, the token can be read from the standard +service account token file location. + +.. code-block:: python + + import os + from pymongo.auth_oidc import OIDCCallback, OIDCCallbackContext, OIDCCallbackResult + + + class MyCallback(OIDCCallback): + def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: + with open("/var/run/secrets/kubernetes.io/serviceaccount/token") as fid: + token = fid.read() + return OIDCCallbackResult(access_token=token) + + + uri = os.environ["MONGODB_URI"] + props = {"OIDC_CALLBACK": MyCallback()} + c = MongoClient(uri, authMechanism="MONGODB-OIDC", authMechanismProperties=props) + c.test.test.insert_one({}) + c.close() + +.. _MONGODB-OIDC authentication mechanism: https://www.mongodb.com/docs/manual/core/security-oidc/ +.. _Azure Internal Metadata Service: https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service +.. _configured on your MongoDB deployment: https://www.mongodb.com/docs/manual/reference/parameters/#mongodb-parameter-param.oidcIdentityProviders +.. _GCP Internal Metadata Service: https://cloud.google.com/compute/docs/metadata/querying-metadata +.. _IAM OIDC provider: https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html +.. _azure-identity package: https://pypi.org/project/azure-identity/ +.. _configured service account: https://cloud.google.com/kubernetes-engine/docs/how-to/service-accounts