Skip to content

Commit 32d1633

Browse files
committed
DOCSP-45153 Add MONGODB-OIDC (#152)
(cherry picked from commit 6700bfd)
1 parent cd396c0 commit 32d1633

File tree

2 files changed

+225
-1
lines changed

2 files changed

+225
-1
lines changed

Diff for: source/fundamentals/enterprise-auth.txt

+135
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,138 @@ a connection string URI by using the following placeholders:
108108

109109
let uri = "mongodb://<username>:<password>@<hostname>/?authSource=$external&authMechanism=PLAIN";
110110

111+
.. _rust-mongodb-oidc:
112+
113+
MONGODB-OIDC
114+
------------
115+
116+
.. important::
117+
118+
The MONGODB-OIDC authentication mechanism requires MongoDB Server
119+
v7.0 or later running on a Linux platform.
120+
121+
The {+driver-short+} supports OpenID Connect (**OIDC**) authentication for **workload
122+
identities**. A workload identity is an identity you assign to a
123+
software workload, such as an application, service, script, or
124+
container, to authenticate and access other services and resources.
125+
126+
The following sections describe how to use the MONGODB-OIDC
127+
authentication mechanism to authenticate to various platforms.
128+
129+
To learn more about the MONGODB-OIDC authentication mechanism, see
130+
:manual:`OpenID Connect Authentication </core/security-oidc/>` and
131+
:manual:`MongoDB Server Parameters </reference/parameters/#mongodb-parameter-param.oidcIdentityProviders>`
132+
in the Server manual.
133+
134+
.. _rust-mongodb-oidc-azure-imds:
135+
136+
Azure IMDS
137+
~~~~~~~~~~
138+
139+
If your application runs on an Azure VM, or otherwise uses the
140+
`Azure Instance Metadata Service <https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service>`__
141+
(IMDS), you can authenticate to MongoDB by using the {+driver-short+}'s
142+
built-in Azure support.
143+
144+
You can configure OIDC for Azure IMDS by setting the ``mechanism`` field of your
145+
``Credential`` struct to ``AuthMechanism::MongoDbOidc``. This example specifies
146+
the authentication mechanism by using the following placeholders:
147+
148+
- ``username``: If you're using an Azure managed identity, set this to the
149+
client ID of the managed identity. If you're using a service principal to
150+
represent an enterprise application, set this to the application ID of the
151+
service principal.
152+
- ``mechanism_properties``: Set the ``ENVIRONMENT`` property to ``azure`` and
153+
the ``TOKEN_RESOURCE`` to the value of the audience parameter configured
154+
on your MongoDB deployment.
155+
156+
The following code example shows how to set these options when creating a
157+
``Client``:
158+
159+
.. literalinclude:: /includes/fundamentals/code-snippets/enterprise-auth.rs
160+
:language: rust
161+
:dedent:
162+
:start-after: start-azure-imds
163+
:end-before: end-azure-imds
164+
:emphasize-lines: 2-5
165+
166+
.. _rust-mongodb-oidc-gcp-imds:
167+
168+
GCP IMDS
169+
~~~~~~~~
170+
171+
If your application runs on a Google Compute Engine VM, or otherwise uses the
172+
`GCP Instance Metadata Service <https://cloud.google.com/compute/docs/metadata/querying-metadata>`__,
173+
you can authenticate to MongoDB by using the {+driver-short+}'s built-in GCP
174+
support.
175+
176+
You can configure OIDC for GCP IMDS by setting the ``mechanism`` field of your
177+
``Credential`` struct to ``AuthMechanism::MongoDbOidc``. Then, specify the
178+
authentication mechanism by setting the following values in the
179+
``mechanism_properties`` field:
180+
181+
- ``ENVIRONMENT``: Set this property to ``gcp``.
182+
- ``TOKEN_RESOURCE``: Set this property to the value of the audience parameter configured
183+
on your MongoDB deployment.
184+
185+
The following code example shows how to set these options when creating a
186+
``Client``:
187+
188+
.. literalinclude:: /includes/fundamentals/code-snippets/enterprise-auth.rs
189+
:language: rust
190+
:dedent:
191+
:start-after: start-gcp-imds
192+
:end-before: end-gcp-imds
193+
:emphasize-lines: 2-4
194+
195+
.. _rust-mongodb-oidc-custom-callback:
196+
197+
Custom Callback
198+
~~~~~~~~~~~~~~~
199+
200+
The {+driver-short+} doesn't offer built-in support for all platforms, including
201+
the AWS Elastic Kubernetes Service (EKS). To use OIDC to authenticate against
202+
unsupported platforms, you must define a custom callback function.
203+
204+
The following code is an example implementation of a custom callback for an EKS
205+
cluster. First, set the ``oidc_callback`` field of your ``Credential`` struct to
206+
``oidc::Callback::machine``. Then, read the access token from a path set in the
207+
``AWS_WEB_IDENTITY_TOKEN_FILE`` environment variable. Finally, set the value of
208+
the ``access_token`` field of the ``IdpServerResponse`` struct. Optionally, set
209+
the values of the ``expires`` and ``refresh_token`` fields.
210+
211+
.. literalinclude:: /includes/fundamentals/code-snippets/enterprise-auth.rs
212+
:language: rust
213+
:dedent:
214+
:start-after: start-custom-callback-machine
215+
:end-before: end-custom-callback-machine
216+
:emphasize-lines: 3, 5-7
217+
218+
When the workforce identity authentication process involves human interaction,
219+
you must configure the client by setting the ``oidc_callback`` field of your
220+
``Credential`` struct to ``oidc::Callback::human`` instead of
221+
``oidc::Callback::machine``. The {+driver-short+} uses the callback in the
222+
following process:
223+
224+
1. The driver retrieves the Identity Provider Information (IDPInfo) for the
225+
provided username.
226+
#. The callback negotiates with the IDP to obtain an ``access_token``, and any
227+
potential ``refresh_token`` and timeout values, if configured. The callback
228+
returns a ``Result<IdpServerInfo>``.
229+
230+
The following example defines a custom callback to handle workforce identity. To
231+
customize this example for your use case, replace ``<human flow>`` with your own
232+
custom flow. Refer to `Authorization Code Flow with OIDC
233+
<https://auth0.com/docs/authenticate/login/oidc-conformant-authentication/oidc-adoption-auth-code-flow>`__
234+
for more details.
235+
236+
.. literalinclude:: /includes/fundamentals/code-snippets/enterprise-auth.rs
237+
:language: rust
238+
:dedent:
239+
:start-after: start-custom-callback-user
240+
:end-before: end-custom-callback-user
241+
:emphasize-lines: 3
242+
111243
Additional Information
112244
----------------------
113245

@@ -129,3 +261,6 @@ guide, see the following API documentation:
129261
- `ClientOptions <{+api+}/options/struct.ClientOptions.html>`__
130262
- `Client <{+api+}/struct.Client.html>`__
131263
- `with_options() <{+api+}/struct.Client.html#method.with_options>`__
264+
- `CallbackContext <{+api+}/options/oidc/struct.CallbackContext.html>`__
265+
- `IdpServerResponse <{+api+}/options/oidc/struct.IdpServerResponse.html>`__
266+
- `IdpServerInfo <{+api+}/options/oidc/struct.IdpServerInfo.html>`__

Diff for: source/includes/fundamentals/code-snippets/enterprise-auth.rs

+90-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
use mongodb::{ bson::doc, options::{ ClientOptions, Credential, AuthMechanism }, Client };
1+
use mongodb::options::oidc::{self, Callback, CallbackContext, IdpServerResponse};
2+
use mongodb::{
3+
bson::doc,
4+
bson::Document,
5+
options::{ClientOptions, Credential, AuthMechanism},
6+
Client,
7+
};
8+
use std::error::Error;
9+
use futures::FutureExt;
210

311
#[tokio::main]
412
async fn main() -> mongodb::error::Result<()> {
@@ -17,5 +25,86 @@ async fn main() -> mongodb::error::Result<()> {
1725
let client = Client::with_options(client_options)?;
1826
// end-ldap
1927

28+
// start-azure-imds
29+
let credential = Credential::builder()
30+
.username("<username>".to_owned())
31+
.mechanism(AuthMechanism::MongoDbOidc)
32+
.mechanism_properties(
33+
doc! { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": "<audience>" }
34+
)
35+
.build();
36+
37+
client_options.credential = Some(credential);
38+
let client = Client::with_options(client_options)?;
39+
let res = client
40+
.database("test")
41+
.collection::<Document>("test")
42+
.find_one(doc! {})
43+
.await?;
44+
// end-azure-imds
45+
46+
// start-gcp-imds
47+
let credential = Credential::builder()
48+
.mechanism(AuthMechanism::MongoDbOidc)
49+
.mechanism_properties(
50+
doc! { "ENVIRONMENT": "gcp", "TOKEN_RESOURCE": "<audience>" }
51+
)
52+
.build();
53+
54+
client_options.credential = Some(credential);
55+
let client = Client::with_options(client_options)?;
56+
let res = client
57+
.database("test")
58+
.collection::<Document>("test")
59+
.find_one(doc! {})
60+
.await?;
61+
// end-gcp-imds
62+
63+
// start-custom-callback-machine
64+
let credential = Credential::builder()
65+
.mechanism(AuthMechanism::MongoDbOidc)
66+
.oidc_callback(oidc::Callback::machine(move |_| {
67+
async move {
68+
let token_file_path = std::env::var("AWS_WEB_IDENTITY_TOKEN_FILE").map_err(mongodb::error::Error::custom)?;
69+
let access_token = tokio::fs::read_to_string(token_file_path).await?;
70+
Ok(IdpServerResponse::builder().access_token(access_token).build())
71+
}
72+
.boxed()
73+
}))
74+
.build()
75+
.into();
76+
77+
client_options.credential = Some(credential);
78+
let client = Client::with_options(client_options)?;
79+
80+
let res = client
81+
.database("test")
82+
.collection::<Document>("test")
83+
.find_one(doc! {})
84+
.await?;
85+
// end-custom-callback-machine
86+
87+
// start-custom-callback-user
88+
let callback = Callback::human(move |context| {
89+
async move {
90+
"<human flow>";
91+
todo!("human flow")
92+
}
93+
.boxed()
94+
});
95+
let credential = Credential::builder()
96+
.mechanism(AuthMechanism::MongoDbOidc)
97+
.oidc_callback(callback)
98+
.build();
99+
client_options.credential = Some(credential);
100+
let client = Client::with_options(client_options)?;
101+
102+
let res = client
103+
.database("test")
104+
.collection::<Document>("test")
105+
.find_one(doc! {})
106+
.await?;
107+
// end-custom-callback-user
108+
20109
Ok(())
21110
}

0 commit comments

Comments
 (0)