Skip to content

Commit

Permalink
Merge branch 'master' of github.com:mongodb/specifications into DRIVE…
Browse files Browse the repository at this point in the history
  • Loading branch information
blink1073 committed Mar 21, 2024
2 parents 06e0110 + 2c3be08 commit fd9481a
Show file tree
Hide file tree
Showing 17 changed files with 612 additions and 81 deletions.
106 changes: 91 additions & 15 deletions source/auth/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -1212,12 +1212,17 @@ in the MONGODB-OIDC specification, including sections or blocks that specificall

- mechanism_properties

- PROVIDER_NAME\
Drivers MUST allow the user to specify the name of a built-in OIDC provider integration to use to
obtain credentials. If provided, the value MUST be one of `["aws"]`. If both `PROVIDER_NAME` and an
[OIDC Callback](#oidc-callback) or [OIDC Human Callback](#oidc-human-callback) are provided for the same
- ENVIRONMENT\
Drivers MUST allow the user to specify the name of a built-in OIDC application environment integration
to use to obtain credentials. If provided, the value MUST be one of `["test", "azure"]`. If both `ENVIRONMENT` and
an [OIDC Callback](#oidc-callback) or [OIDC Human Callback](#oidc-human-callback) are provided for the same
`MongoClient`, the driver MUST raise an error.

- TOKEN_RESOURCE\
The URI of the target resource. This property is currently only used and required by the Azure
built-in OIDC provider integration. If `TOKEN_RESOURCE` is provided and `PROVIDER_NAME` is not `azure` or
`TOKEN_RESOURCE` is not provided and `PROVIDER_NAME` is `azure`, the driver MUST raise an error.

- OIDC_CALLBACK\
An [OIDC Callback](#oidc-callback) that returns OIDC credentials. Drivers MAY allow the user to
specify an [OIDC Callback](#oidc-callback) using a `MongoClient` configuration instead of a mechanism property,
Expand All @@ -1243,20 +1248,83 @@ in the MONGODB-OIDC specification, including sections or blocks that specificall
performed after SRV record resolution, if applicable. This property is only required for drivers that support the
[Human Authentication Flow](#human-authentication-flow).

#### Built-in Provider Integrations
<div id="built-in-provider-integrations">

#### Built-in OIDC Environment Integrations

Drivers MUST support all of the following built-in OIDC application environment integrations.

**Test**

The test integration is enabled by setting auth mechanism property `ENVIRONMENT:test`. It is meant for driver testing
purposes, and is not meant to be documented as a user-facing feature.

If enabled, drivers MUST generate a token using a script in the `auth_oidc`
[folder](https://github.com/mongodb-labs/drivers-evergreen-tools/tree/master/.evergreen/auth_oidc#readme) in Drivers
Evergreen Tools. The must then set the `OIDC_TOKEN_FILE` environment variable to the path to that file. At runtime, the
driver MUST use the `OIDC_TOKEN_FILE` environment variable and read the OIDC access token from that path. The driver
MUST use the contents of that file as value in the `jwt` field of the `saslStart` payload.

Drivers MAY implement the "test" integration so that it conforms to the function signature of the
[OIDC Callback](#oidc-callback) to prevent having to re-implement the "test" integration logic in the OIDC prose tests.

**Azure**

The Azure provider integration is enabled by setting auth mechanism property `ENVIRONMENT:azure`.

If enabled, drivers MUST use an internal machine callback that calls the
[Azure Instance Metadata Service](https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service)
and parse the JSON response body, as follows:

Make an HTTP GET request to

```
http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=<resource>&client_id=<client_id>
```

with headers

Drivers MUST support all of the following built-in OIDC providers.
```
Accept: application/json
Metadata: true
```

####### AWS
where `<resource>` is the value of the `TOKEN_RESOURCE` mechanism property and `<client_id>` is the `username` from the
connection string. If a `username` is not provided, the `client_id` query parameter should be omitted. The timeout
should equal the `callbackTimeoutMS` parameter given to the callback.

The AWS provider is enabled by setting auth mechanism property `PROVIDER_NAME:aws`.
Example code for the above using curl, where `$TOKEN_RESOURCE` is the value of the `TOKEN_RESOURCE` mechanism property.

If enabled, drivers MUST read the file path from environment variable `AWS_WEB_IDENTITY_TOKEN_FILE` and then read the
OIDC access token from that file. The driver MUST use the contents of that file as value in the `jwt` field of the
`saslStart` payload.
```bash
curl -X GET \
-H "Accept: application/json" \
-H "Metadata: true" \
--max-time $CALLBACK_TIMEOUT_MS \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$TOKEN_RESOURCE"
```

Drivers MAY implement the AWS provider so that it conforms to the function signature of the
[OIDC Callback](#oidc-callback) to prevent having to re-implement the AWS provider logic in the OIDC prose tests.
The JSON response will be in this format:

```json
{
"access_token": "eyJ0eXAi...",
"refresh_token": "",
"expires_in": "3599",
"expires_on": "1506484173",
"not_before": "1506480273",
"resource": "https://management.azure.com/",
"token_type": "Bearer"
}
```

The driver MUST use the returned `"access_token"` value as the access token in a `JwtStepRequest`. If the response does
not return a status code of 200, the driver MUST raise an error including the HTTP response body.

For more details, see
[How to use managed identities for Azure resources on an Azure VM to acquire an access token](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token).

The callback itself MUST not perform any caching, and the driver MUST cache its tokens in the same way as if a custom
callback had been provided by the user.

#### OIDC Callback

Expand All @@ -1275,6 +1343,8 @@ The driver MUST pass the following information to the callback:

- `timeout`: A timeout, in milliseconds, a deadline, or a `timeoutContext`.

- `username`: The username given as part of the connection string or `MongoClient` parameter.

- `version`: The callback API version number. The version number is used to communicate callback API changes that are
not breaking but that users may want to know about and review their implementation. Drivers MUST pass `1` for the
initial callback API version number and increment the version number anytime the API changes. Note that this may
Expand Down Expand Up @@ -1305,6 +1375,7 @@ An example callback API might look like:
```typescript
interface OIDCCallbackParams {
callbackTimeoutMS: int;
username: str;
version: int;
}

Expand Down Expand Up @@ -1352,6 +1423,7 @@ interface IdpInfo {
}

interface OIDCCallbackParams {
username: str;
callbackTimeoutMS: int;
version: int;
idpInfo: Optional<IdpInfo>;
Expand Down Expand Up @@ -1569,7 +1641,7 @@ def invalidate(access_token):
Drivers that support the [Human Authentication Flow](#human-authentication-flow) MUST also cache the `IdPInfo` and
refresh token in the *Client Cache* when a [OIDC Human Callback](#oidc-human-callback) is configured.

####### Authentication
**Authentication**

Use the following algorithm to authenticate a new connection:

Expand Down Expand Up @@ -1920,7 +1992,11 @@ to EC2 instance metadata in ECS, for security reasons, Amazon states it's best p

## Changelog

- 2024-03-19: Specify to only invalidate cached OIDC access tokens if the server returns error 18.
- 2024-03-21: Specify to only invalidate cached OIDC access tokens if the server returns error 18.

- 2024-03-21: Added Azure built-in OIDC provider integration.

- 2024-03-09: Rename OIDC integration name and values.

- 2024-01-31: Migrated from reStructuredText to Markdown.

Expand Down
24 changes: 12 additions & 12 deletions source/auth/tests/legacy/connection-string.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions source/auth/tests/legacy/connection-string.yml
Original file line number Diff line number Diff line change
Expand Up @@ -350,39 +350,39 @@ tests:
mechanism: MONGODB-AWS
mechanism_properties:
AWS_SESSION_TOKEN: token!@#$%^&*()_+
- description: should recognise the mechanism with aws provider (MONGODB-OIDC)
uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:aws
- description: should recognise the mechanism with test environment (MONGODB-OIDC)
uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test
valid: true
credential:
username:
password:
source: "$external"
mechanism: MONGODB-OIDC
mechanism_properties:
PROVIDER_NAME: aws
- description: should recognise the mechanism when auth source is explicitly specified and with provider (MONGODB-OIDC)
uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authSource=$external&authMechanismProperties=PROVIDER_NAME:aws
ENVIRONMENT: test
- description: should recognise the mechanism when auth source is explicitly specified and with environment (MONGODB-OIDC)
uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authSource=$external&authMechanismProperties=ENVIRONMENT:test
valid: true
credential:
username:
password:
source: "$external"
mechanism: MONGODB-OIDC
mechanism_properties:
PROVIDER_NAME: aws
ENVIRONMENT: test
- description: should throw an exception if supplied a password (MONGODB-OIDC)
uri: mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:aws
uri: mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test
valid: false
credential:
- description: should throw an exception if username is specified for aws (MONGODB-OIDC)
uri: mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&PROVIDER_NAME:aws
uri: mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&ENVIRONMENT:test
valid: false
credential:
- description: should throw an exception if specified provider is not supported (MONGODB-OIDC)
uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=PROVIDER_NAME:invalid
- description: should throw an exception if specified environment is not supported (MONGODB-OIDC)
uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:invalid
valid: false
credential:
- description: should throw an exception if neither provider nor callbacks specified (MONGODB-OIDC)
- description: should throw an exception if neither environment nor callbacks specified (MONGODB-OIDC)
uri: mongodb://localhost/?authMechanism=MONGODB-OIDC
valid: false
credential:
Expand Down
44 changes: 36 additions & 8 deletions source/auth/tests/mongodb-oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,27 @@ For example, if the selected AWS profile ID is "drivers-test", run:
aws configure sso
export OIDC_TOKEN_DIR=/tmp/tokens
AWS_PROFILE="drivers-test" oidc_get_tokens.sh
AWS_WEB_IDENTITY_TOKEN_FILE="$OIDC_TOKEN_DIR/test_user1" /my/test/command
OIDC_TOKEN_FILE="$OIDC_TOKEN_DIR/test_user1" /my/test/command
```

______________________________________________________________________

## Unified Spec Tests

Drivers MUST run the unified spec tests in all supported OIDC environments.

______________________________________________________________________

## Prose Tests

Drivers MUST implement all prose tests in this section. Unless otherwise noted, all `MongoClient` instances MUST be
configured with `retryReads=false`.

Drivers MUST run the prose tests in all supported OIDC environments.

> [!NOTE]
> For test cases that create fail points, drivers MUST either use a unique `appName` or explicitly remove the fail point
> after the test to prevent interaction between test cases.
> callback to prevent interaction between test cases.
Note that typically the preconfigured Atlas Dev clusters are used for testing, in Evergreen and locally. The URIs can be
fetched from the `drivers/oidc` Secrets vault, see
Expand All @@ -35,18 +43,18 @@ Use `OIDC_ATLAS_URI_SINGLE` for the `MONGODB_URI`. If using local servers is pre
[Local Testing](https://github.com/mongodb-labs/drivers-evergreen-tools/blob/master/.evergreen/auth_oidc/README.md#local-testing)
method, use `mongodb://localhost/?authMechanism=MONGODB-OIDC` for `MONGODB_URI`.

### (1) OIDC Callback Authentication
### Callback Authentication

**1.1 Callback is called during authentication**

- Create a `MongoClient` configured with an OIDC callback that implements the AWS provider logic.
- Create a `MongoClient` configured with an OIDC callback that implements the `ENVIRONMENT:test` logic.
- Perform a `find` operation that succeeds.
- Assert that the callback was called 1 time.
- Close the client.

**1.2 Callback is called once for multiple connections**

- Create a `MongoClient` configured with an OIDC callback that implements the AWS provider logic.
- Create a `MongoClient` configured with an OIDC callback that implements the `ENVIRONMENT:test` logic.
- Start 10 threads and run 100 `find` operations in each thread that all succeed.
- Assert that the callback was called 1 time.
- Close the client.
Expand Down Expand Up @@ -75,14 +83,14 @@ method, use `mongodb://localhost/?authMechanism=MONGODB-OIDC` for `MONGODB_URI`.

**2.4 Invalid Client Configuration with Callback**

- Create a `MongoClient` configured with an OIDC callback and auth mechanism property `PROVIDER_NAME:aws`.
- Create a `MongoClient` configured with an OIDC callback and auth mechanism property `ENVIRONMENT:test`.
- Assert it returns a client configuration error.

### (3) Authentication Failure

**3.1 Authentication failure with cached tokens fetch a new token and retry auth**

- Create a `MongoClient` configured with an OIDC callback that implements the AWS provider logic.
- Create a `MongoClient` configured with an OIDC callback that implements the `ENVIRONMENT:test` logic.
- Poison the *Client Cache* with an invalid access token.
- Perform a `find` operation that succeeds.
- Assert that the callback was called 1 time.
Expand Down Expand Up @@ -123,7 +131,7 @@ method, use `mongodb://localhost/?authMechanism=MONGODB-OIDC` for `MONGODB_URI`.

### (4) Reauthentication

- Create a `MongoClient` configured with an OIDC callback that implements the AWS provider logic.
- Create a `MongoClient` configured with an OIDC callback that implements the `ENVIRONMENT:test` logic.
- Set a fail point for `find` commands of the form:

```javascript
Expand All @@ -145,13 +153,33 @@ method, use `mongodb://localhost/?authMechanism=MONGODB-OIDC` for `MONGODB_URI`.
- Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication).
- Close the client.

## (5) Azure Tests

Drivers MUST only run the Azure tests when testing on an Azure VM. See instructions in
[Drivers Evergreen Tools](https://github.com/mongodb-labs/drivers-evergreen-tools/tree/master/.evergreen/auth_oidc/azure#azure-oidc-testing)
for test setup.

# 5.1 Azure With No Username

- Create a `MongoClient` configured with `ENVIRONMENT:Azure` and a valid `TOKEN_RESOURCE` and no username.
- Perform a `find` operation that succeeds.
- Close the client.

# 5.2 Azure with Bad Usernam

- Create a `MongoClient` configured with `ENVIRONMENT:Azure` and a valid `TOKEN_RESOURCE` and a username of `"bad"`.
- Perform a `find` operation that fails.
- Close the client.

______________________________________________________________________

## Human Authentication Flow Prose Tests

Drivers that support the [Human Authentication Flow](../auth.md#human-authentication-flow) MUST implement all prose
tests in this section. Unless otherwise noted, all `MongoClient` instances MUST be configured with `retryReads=false`.

The human workflow tests MUST only be run when testing in the default environment described beflow.

> [!NOTE]
> For test cases that create fail points, drivers MUST either use a unique `appName` or explicitly remove the fail point
> after the test to prevent interaction between test cases.
Expand Down
Loading

0 comments on commit fd9481a

Please sign in to comment.