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

DRIVERS-2416 OIDC: Automatic token acquisition for Azure Identity Provider #1421

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 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
24 changes: 21 additions & 3 deletions source/auth/auth.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,10 @@ mechanism
mechanism_properties
PROVIDER_NAME
Drivers MUST allow the user to specify a name for using a service
to obtain credentials that is one of ["aws"].
to obtain credentials that is one of ["aws", "azure"].
TOKEN_AUDIENCE
durran marked this conversation as resolved.
Show resolved Hide resolved
The authorization token audience claim, needed for the "azure"
provider.
REQUEST_TOKEN_CALLBACK
Drivers MUST allow the user to specify a callback of the form
"onRequest" (defined below), if the driver supports
Expand Down Expand Up @@ -1349,8 +1352,8 @@ the driver MUST raise an error.
Supported Service Providers
```````````````````````````

Drivers MUST support obtaining credentials for a service for "aws", given
by the PROVIDER_NAME mechanism property. In all cases the acquired token
Drivers MUST support obtaining credentials for a service for "aws" and "azure",
given by the PROVIDER_NAME mechanism property. In all cases the acquired token
will be given as the ``jwt`` argument and the JwtStepRequest MUST be made immediately, as part of speculative authentication if appropriate, skipping the PrincipalStepRequest.
Drivers MUST raise an error if both a PROVIDER_NAME and username are
given, since using a service will not use the username.
Expand All @@ -1364,6 +1367,21 @@ interpret it as a file path. The contents of the file are read as the
access token. If the path does not exist or cannot be read, or the environment variable does not exist, the driver MUST raise an error.


AZURE
_____
When the PROVIDER_NAME mechanism property is set to "azure", the driver MUST
attempt to retrieve a credential from the Azure Instance Metadata Service (IMDS).
The driver MUST ensure that the TOKEN_AUDIENCE mechanism property is set when
the PROVIDER_NAME is "azure".

The driver MUST use the same procedure given in `Obtaining an Access Token for Azure Key Vault`_ to
obtain an access token, with the one exception of using the TOKEN_AUDIENCE as
the ``resource`` parameter. The azure credentials MUST be cached by
TOKEN_AUDIENCE, and expire within 5 minutes of the time given by the
``expires_in`` parameter of the IMDS response.
Copy link
Member

@durran durran May 25, 2023

Choose a reason for hiding this comment

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

I think we should call out that the token audience is in the format api://${TOKEN_AUDIENCE}

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it would be more accurate to say that the audience itself is an encoded URI, most likely an Application ID URI of the form app://<app id>.


.. _Obtaining an Access Token for Azure Key Vault: https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst#obtaining-an-access-token-for-azure-key-vault

Caching Credentials
```````````````````

Expand Down
78 changes: 78 additions & 0 deletions source/auth/tests/mongodb-oidc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Drivers MUST test the following scenarios:

- ``Callback-Driven Auth``
- ``AWS Automatic Auth``
- ``Azure Automatic Auth``
- ``Callback Validation``
- ``Cached Credentials``
- ``Speculative Authentication``
Expand Down Expand Up @@ -141,6 +142,83 @@ Allowed Hosts Ignored
- Assert that a ``find`` operation succeeds.
- Close the client.

Azure Automatic Auth
==================

Drivers MUST be able to authenticate using the "azure" provider workflow, using
an Azure VM provisioned using the helper scripts in Drivers Evergreen Tools.
These tests will most likely need to be run in a separate test file from the
rest of the tests, to avoid needing to skip multiple tests.
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it's worth noting here that the URI for all tests is the same, and must be equal to:

mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:azure,TOKEN_AUDIENCE:api://${AZUREOIDC_CLIENTID}

Then each individual test can reuse the same URI. Thoughts? I did the same as Python and just set it as the MONGODB_URI and had all the clients use that.


Connect
~~~~~~~
- Create a client with a url of the form ``mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:azure,TOKEN_AUDIENCE:<foo>``.
- Assert that a ``find`` operation succeeds.
- Close the client.

Allowed Hosts Ignored
~~~~~~~~~~~~~~~~~~~~~
- Create a client with a url of the form ``mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:azure,TOKEN_AUDIENCE:<foo>``, and an
``ALLOWED_HOSTS`` that is an empty list.
- Assert that a ``find`` operation succeeds.
- Close the client.

Main Cache Not Used
~~~~~~~~~~~~~~~~~~~
- Clear the main OIDC cache.
- Create a client with a url of the form ``mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:azure,TOKEN_AUDIENCE:<foo>``.
- Assert that a ``find`` operation succeeds.
- Close the client.
- Assert that the main OIDC cache is empty.

Azure Cache is Used
~~~~~~~~~~~~~~~~~~~
- Clear the Azure OIDC cache.
- Create a client with a url of the form ``mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:azure,TOKEN_AUDIENCE:<foo>``.
- Assert that a ``find`` operation succeeds.
- Close the client.
- Assert that the Azure OIDC cache has one entry.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not combine the Main Cache Not Used and Azure Cache is Used tests? Clear both caches, perform the operation, and check that the main cache remains empty and the Azure one has a single entry.


Reauthentication Succeeds
~~~~~~~~~~~~~~~~~~~~~~~~~
- Clear the Azure OIDC cache.
- Create a client with an event listener. The following
assumes that the driver does not emit ``saslStart`` or ``saslContinue``
events. If the driver does emit those events, ignore/filter them for the
purposes of this test.
- Perform a ``find`` operation that succeeds.
- Clear the listener state if possible.
- Force a reauthenication using a ``failCommand`` of the form:

.. code:: javascript

{
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"find"
],
"errorCode": 391
}
}

.. note::

the driver MUST either use a unique ``appName`` or explicitly
remove the ``failCommand`` after the test to prevent leakage.

- Perform another find operation that succeeds.
- Assert that the ordering of list started events is [``find``],
, ``find``. Note that if the listener stat could not be cleared then there
will and be extra ``find`` command.
- Assert that the list of command succeeded events is [``find``].
- Assert that a ``find`` operation failed once during the command execution.
- Close the client.


Callback Validation
===================

Expand Down