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-39405: kotlin v5.1 content #161

Merged
merged 3 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion examples/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
kotlin.code.style=official
kotlin_mongodb_version=4.11.0
kotlin_mongodb_version=5.1.0
86 changes: 86 additions & 0 deletions examples/src/test/kotlin/EnterpriseAuthTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import com.mongodb.ConnectionString
import com.mongodb.KerberosSubjectProvider
import com.mongodb.MongoClientSettings
import com.mongodb.MongoCredential
import com.mongodb.MongoCredential.OidcCallbackResult
import com.mongodb.ServerAddress
import com.mongodb.kotlin.client.coroutine.MongoClient
import kotlinx.coroutines.runBlocking
import java.nio.file.Files
import java.nio.file.Paths
import javax.naming.Context
import javax.security.auth.Subject
import javax.security.auth.login.LoginContext
import kotlin.test.Ignore
Expand Down Expand Up @@ -113,6 +117,88 @@ internal class EnterpriseAuthTest {
val mongoClient = MongoClient.create(connectionString)
// :snippet-end:
}

fun oidcAzureConnectionString() = runBlocking {
// :snippet-start: oidc-azure-connection-string
val connectionString = ConnectionString(
"mongodb://<username>@<hostname>:<port>/?" +
"?authMechanism=MONGODB-OIDC" +
"&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:<percent-encoded audience>")
val mongoClient = MongoClient.create(connectionString)
// :snippet-end:
}

fun oidcAzureCredential() = runBlocking {
// :snippet-start: oidc-azure-credential
val credential = MongoCredential.createOidcCredential("<username>")
.withMechanismProperty("ENVIRONMENT", "azure")
.withMechanismProperty("TOKEN_RESOURCE", "<audience>")

val mongoClient = MongoClient.create(
MongoClientSettings.builder()
.applyToClusterSettings { builder ->
builder.hosts(listOf(ServerAddress("<hostname>", PORT)))
}
.credential(credential)
.build())
// :snippet-end:
}

fun oidcGCPConnectionString() = runBlocking {
// :snippet-start: oidc-gcp-connection-string
val connectionString = ConnectionString(
"mongodb://<hostname>:<port>/?" +
"authMechanism=MONGODB-OIDC" +
"&authMechanismProperties=ENVIRONMENT:gcp,TOKEN_RESOURCE:<percent-encoded audience>")
val mongoClient = MongoClient.create(connectionString)
// :snippet-end:
}

fun oidcGCPCredential() = runBlocking {
// :snippet-start: oidc-gcp-credential
val credential = MongoCredential.createOidcCredential("<username>")
.withMechanismProperty("ENVIRONMENT", "gcp")
.withMechanismProperty("TOKEN_RESOURCE", "<audience>")

val mongoClient = MongoClient.create(
MongoClientSettings.builder()
.applyToClusterSettings { builder ->
builder.hosts(listOf(ServerAddress("<hostname>", PORT)))
}
.credential(credential)
.build())
// :snippet-end:
}

fun oidcCallback() = runBlocking {
// :snippet-start: oidc-callback
val credential = MongoCredential.createOidcCredential(null)
.withMechanismProperty("OIDC_CALLBACK") { Context context ->
val accessToken = "..."
OidcCallbackResult(accessToken)
}
// :snippet-end:
}


fun oidcCallbackFile() = runBlocking {
// :snippet-start: oidc-callback-file
val credential = MongoCredential.createOidcCredential(null)
.withMechanismProperty("OIDC_CALLBACK") { Context context ->
val accessToken = String(Files.readAllBytes(Paths.get("access-token.dat")))
OidcCallbackResult(accessToken)
}

val mongoClient = MongoClient.create(
MongoClientSettings.builder()
.applyToClusterSettings { builder ->
builder.hosts(listOf(ServerAddress("<hostname>", PORT)))
}
.credential(credential)
.build()
)
// :snippet-end:
}
}
// :replace-end:

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
val connectionString = ConnectionString(
"mongodb://<username>@<hostname>:<port>/?" +
"?authMechanism=MONGODB-OIDC" +
"&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:<percent-encoded audience>")
val mongoClient = MongoClient.create(connectionString)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
val credential = MongoCredential.createOidcCredential("<username>")
.withMechanismProperty("ENVIRONMENT", "azure")
.withMechanismProperty("TOKEN_RESOURCE", "<audience>")

val mongoClient = MongoClient.create(
MongoClientSettings.builder()
.applyToClusterSettings { builder ->
builder.hosts(listOf(ServerAddress("<hostname>", <port>)))
}
.credential(credential)
.build())
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
val credential = MongoCredential.createOidcCredential(null)
.withMechanismProperty("OIDC_CALLBACK") { Context context ->
val accessToken = String(Files.readAllBytes(Paths.get("access-token.dat")))
OidcCallbackResult(accessToken)
}

val mongoClient = MongoClient.create(
MongoClientSettings.builder()
.applyToClusterSettings { builder ->
builder.hosts(listOf(ServerAddress("<hostname>", <port>)))
}
.credential(credential)
.build()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
val credential = MongoCredential.createOidcCredential(null)
.withMechanismProperty("OIDC_CALLBACK") { Context context ->
val accessToken = "..."
OidcCallbackResult(accessToken)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
val connectionString = ConnectionString(
"mongodb://<hostname>:<port>/?" +
"authMechanism=MONGODB-OIDC" +
"&authMechanismProperties=ENVIRONMENT:gcp,TOKEN_RESOURCE:<percent-encoded audience>")
val mongoClient = MongoClient.create(connectionString)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
val credential = MongoCredential.createOidcCredential("<username>")
.withMechanismProperty("ENVIRONMENT", "gcp")
.withMechanismProperty("TOKEN_RESOURCE", "<audience>")

val mongoClient = MongoClient.create(
MongoClientSettings.builder()
.applyToClusterSettings { builder ->
builder.hosts(listOf(ServerAddress("<hostname>", <port>)))
}
.credential(credential)
.build())
9 changes: 9 additions & 0 deletions source/fundamentals/connection/connection-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,15 @@ parameters of the connection URI to specify the behavior of the client.

| **Default**: ``true``

* - **serverMonitoringMode**
- string
- Specifies which server monitoring protocol the driver uses. When set to
``auto``, the monitoring mode is determined by the environment in which
the driver is running. The driver uses ``poll`` mode in function-as-a-service
(FaaS) environments and ``stream`` mode in other environments.

| **Default**: ``auto``

* - **uuidRepresentation**
- string
- Specifies the UUID representation to use for read and write
Expand Down
3 changes: 3 additions & 0 deletions source/fundamentals/connection/mongoclientsettings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ settings to modify the driver's behavior:
* - ``minHeartbeatFrequency()``
- Sets the minimum interval for server monitoring checks.

* - ``serverMonitoringMode()``
- Specifies which server monitoring protocol the driver uses.

Example
~~~~~~~

Expand Down
138 changes: 137 additions & 1 deletion source/fundamentals/enterprise-auth.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
Enterprise Authentication Mechanisms
====================================

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: ldap, encryption, principal, tls


.. contents:: On this page
:local:
:backlinks: none
Expand All @@ -22,6 +30,7 @@ Enterprise Edition:

- :ref:`Kerberos (GSSAPI) <gssapi-auth-mechanism>`
- :ref:`LDAP (PLAIN) <plain-auth-mechanism>`
- :ref:`MONGODB-OIDC <kotlin-oidc>`

:doc:`Authentication Mechanisms guide </fundamentals/auth>`.

Expand Down Expand Up @@ -278,4 +287,131 @@ mechanism:

.. literalinclude:: /examples/generated/EnterpriseAuthTest.snippet.ldap-mongo-credential.kt
:language: kotlin


.. _kotlin-oidc:

MONGODB-OIDC
~~~~~~~~~~~~

.. important::

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

S: I don't think this needs to be monospaced, based on the other mentions of MONGODB-OIDC, Kerberos, LDAP

Suggested change
The following sections describe how to use the ``MONGODB-OIDC``
The following sections describe how to use the MONGODB-OIDC

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

For more information 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 MongoDB Server manual.

.. _kotlin-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.

You can specify Azure IMDS OIDC authentication either by
Copy link
Collaborator

Choose a reason for hiding this comment

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

S: clarify what this is

Suggested change
using a ``MongoCredential`` or specifying your credentials in the connection string.
using a ``MongoCredential`` instance or specifying your credentials in the connection string.

using a ``MongoCredential`` or specifying your credentials in the connection string.

Select from the :guilabel:`Connection String` or :guilabel:`MongoCredential` tabs to
see the corresponding syntax.

.. tabs::

.. tab:: Connection String
:tabid: mongodb-azure-imds-connection-string

Replace the ``<percent-encoded audience>`` placeholder in the
following code with the percent-encoded value of the audience server
parameter configured on your MongoDB deployment.

The comma (``,``) character and its encoding (``%2C``) are
reserved, and using these characters in a value causes the
driver to interpret commas as delimiters of key-value pairs.
You must specify values that contain commas in a ``MongoCredential`` instance, as
demonstrated in the :guilabel:`MongoCredential` tab.

.. literalinclude:: /examples/generated/EnterpriseAuthTest.snippet.oidc-azure-connection-string.kt
:language: kotlin

.. tab:: MongoCredential
:tabid: mongodb-azure-mongo-credential

Replace the ``<username>`` placeholder with the client ID or application ID of the
Azure managed identity or enterprise application. Replace the ``<audience>``
placeholder with the value of the
``audience`` server parameter configured on your MongoDB deployment.

.. literalinclude:: /examples/generated/EnterpriseAuthTest.snippet.oidc-azure-credential.kt
:language: kotlin

.. _kotlin-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>`__,
Copy link
Collaborator

Choose a reason for hiding this comment

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

S:

Suggested change
you can authenticate to MongoDB by using {+driver-short+}'s built-in GCP
you can authenticate to MongoDB by using the {+driver-short+}'s built-in GCP

you can authenticate to MongoDB by using {+driver-short+}'s built-in GCP
support.

You can specify GCP IMDS OIDC authentication either by
Copy link
Collaborator

Choose a reason for hiding this comment

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

S:

Suggested change
using a ``MongoCredential`` or as part of the connection string.
using a ``MongoCredential`` instance or as part of the connection string.

using a ``MongoCredential`` or as part of the connection string.

Select from the :guilabel:`Connection String` or :guilabel:`MongoCredential` tabs to
see the corresponding syntax.

.. tabs::

.. tab:: Connection String
:tabid: mongodb-gcp-imds-connection-string

Replace the ``<percent-encoded audience>`` placeholder in the
following code with the percent-encoded value of the audience server
parameter configured on your MongoDB deployment.

The comma (``,``) character and its encoding (``%2C``) are
reserved, and using these characters in a value causes the
driver to interpret commas as delimiters of key-value pairs.
You must specify values that contain commas in a ``MongoCredential`` instance, as
demonstrated in the :guilabel:`MongoCredential` tab.

.. literalinclude:: /examples/generated/EnterpriseAuthTest.snippet.oidc-gcp-connection-string.kt
:language: kotlin

.. tab:: MongoCredential
:tabid: mongodb-gcp-mongo-credential

Replace the ``<audience>`` placeholder with the value of the
``audience`` server parameter configured on your MongoDB deployment.

.. literalinclude:: /examples/generated/EnterpriseAuthTest.snippet.oidc-gcp-credential.kt
:language: kotlin

Custom Callback
+++++++++++++++

The {+driver-short+} doesn't offer built-in support for all platforms, including
Azure Functions and Azure Kubernetes Service (AKS). Instead, you
must define a custom callback to use OIDC to authenticate from these platforms.
To do so, use the ``"OIDC_CALLBACK"`` authentication property, as shown in the following
code example:

.. literalinclude:: /examples/generated/EnterpriseAuthTest.snippet.oidc-callback.kt
:language: kotlin

The value of the ``"OIDC_CALLBACK"`` property must be a lambda or other implementation
of the ``OidcCallback`` functional interface that accepts an ``OidcCallbackContext``
as a parameter and returns an ``OidcCallbackResult``.

The following example uses an example callback to retrieve an OIDC token from a file
named ``"access-token.dat"`` in the local file system:

.. literalinclude:: /examples/generated/EnterpriseAuthTest.snippet.oidc-callback-file.kt
:language: kotlin
9 changes: 4 additions & 5 deletions source/whats-new.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ Improvements in 5.1
native applications by using the GraalVM native-image tool.

- Enhanced support for the ``MONGODB-OIDC`` authentication mechanism.

.. TODO add OIDC content and link
To learn more about OIDC, see the :ref:`kotlin-oidc` section of the
Enterprise Authentication Mechanisms guide.

- Fixes an issue in which operations used the incorrect codec when using
a polymorphic ``MongoCollection`` instance. This ensures that
Expand All @@ -72,9 +72,8 @@ New Features in 5.1

.. TODO add polymorphic serialization content

- Introduces the ``serverMonitoringMode`` connection URI option.

.. TODO add serverMonitoringMode content and link
- Introduces the ``serverMonitoringMode`` connection URI option. To
learn more, see the :ref:`connection-options` guide.

.. _version-5.0:

Expand Down
Loading