Skip to content

Commit 184e3f1

Browse files
committed
feat(NODE-6069): OIDC k8s machine workflow
1 parent 5c4355a commit 184e3f1

File tree

12 files changed

+249
-5
lines changed

12 files changed

+249
-5
lines changed

.evergreen/config.in.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,36 @@ tasks:
12651265
args:
12661266
- src/.evergreen/run-azure-kms-tests.sh
12671267

1268+
- name: "oidc-auth-test-k8s-latest"
1269+
commands:
1270+
- func: "install dependencies"
1271+
- command: subprocess.exec
1272+
type: test
1273+
params:
1274+
working_dir: src
1275+
binary: bash
1276+
env:
1277+
PROJECT_DIRECTORY: ${PROJECT_DIRECTORY}
1278+
ENVIRONMENT: k8s
1279+
K8S_VARIANT: eks
1280+
SCRIPT: run-oidc-prose-tests.sh
1281+
include_expansions_in_env: ["DRIVERS_TOOLS", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"]
1282+
args:
1283+
- .evergreen/run-oidc-tests-k8s.sh
1284+
- command: subprocess.exec
1285+
type: test
1286+
params:
1287+
working_dir: src
1288+
binary: bash
1289+
env:
1290+
PROJECT_DIRECTORY: ${PROJECT_DIRECTORY}
1291+
ENVIRONMENT: k8s
1292+
K8S_VARIANT: gke
1293+
SCRIPT: run-oidc-prose-tests.sh
1294+
include_expansions_in_env: ["DRIVERS_TOOLS", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"]
1295+
args:
1296+
- .evergreen/run-oidc-tests-k8s.sh
1297+
12681298
- name: "oidc-auth-test-azure-latest"
12691299
commands:
12701300
- func: "install dependencies"
@@ -1487,6 +1517,28 @@ task_groups:
14871517
tasks:
14881518
- test-azurekms-task
14891519

1520+
- name: testk8soidc_task_group
1521+
setup_group:
1522+
- func: fetch source
1523+
- command: ec2.assume_role
1524+
params:
1525+
role_arn: ${OIDC_AWS_ROLE_ARN}
1526+
- command: subprocess.exec
1527+
params:
1528+
binary: bash
1529+
args:
1530+
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/setup.sh
1531+
teardown_task:
1532+
- command: subprocess.exec
1533+
params:
1534+
binary: bash
1535+
args:
1536+
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/teardown.sh
1537+
setup_group_can_fail_task: true
1538+
setup_group_timeout_secs: 1800
1539+
tasks:
1540+
- oidc-auth-test-k8s-latest
1541+
14901542
- name: testtestoidc_task_group
14911543
setup_group:
14921544
- func: fetch source

.evergreen/config.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,43 @@ tasks:
12171217
EXPECTED_AZUREKMS_OUTCOME: failure
12181218
args:
12191219
- src/.evergreen/run-azure-kms-tests.sh
1220+
- name: oidc-auth-test-k8s-latest
1221+
commands:
1222+
- func: install dependencies
1223+
- command: subprocess.exec
1224+
type: test
1225+
params:
1226+
working_dir: src
1227+
binary: bash
1228+
env:
1229+
PROJECT_DIRECTORY: ${PROJECT_DIRECTORY}
1230+
ENVIRONMENT: k8s
1231+
K8S_VARIANT: eks
1232+
SCRIPT: run-oidc-prose-tests.sh
1233+
include_expansions_in_env:
1234+
- DRIVERS_TOOLS
1235+
- AWS_ACCESS_KEY_ID
1236+
- AWS_SECRET_ACCESS_KEY
1237+
- AWS_SESSION_TOKEN
1238+
args:
1239+
- .evergreen/run-oidc-tests-k8s.sh
1240+
- command: subprocess.exec
1241+
type: test
1242+
params:
1243+
working_dir: src
1244+
binary: bash
1245+
env:
1246+
PROJECT_DIRECTORY: ${PROJECT_DIRECTORY}
1247+
ENVIRONMENT: k8s
1248+
K8S_VARIANT: gke
1249+
SCRIPT: run-oidc-prose-tests.sh
1250+
include_expansions_in_env:
1251+
- DRIVERS_TOOLS
1252+
- AWS_ACCESS_KEY_ID
1253+
- AWS_SECRET_ACCESS_KEY
1254+
- AWS_SESSION_TOKEN
1255+
args:
1256+
- .evergreen/run-oidc-tests-k8s.sh
12201257
- name: oidc-auth-test-azure-latest
12211258
commands:
12221259
- func: install dependencies
@@ -4422,6 +4459,27 @@ task_groups:
44224459
- ${DRIVERS_TOOLS}/.evergreen/csfle/azurekms/teardown.sh
44234460
tasks:
44244461
- test-azurekms-task
4462+
- name: testk8soidc_task_group
4463+
setup_group:
4464+
- func: fetch source
4465+
- command: ec2.assume_role
4466+
params:
4467+
role_arn: ${OIDC_AWS_ROLE_ARN}
4468+
- command: subprocess.exec
4469+
params:
4470+
binary: bash
4471+
args:
4472+
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/setup.sh
4473+
teardown_task:
4474+
- command: subprocess.exec
4475+
params:
4476+
binary: bash
4477+
args:
4478+
- ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/teardown.sh
4479+
setup_group_can_fail_task: true
4480+
setup_group_timeout_secs: 1800
4481+
tasks:
4482+
- oidc-auth-test-k8s-latest
44254483
- name: testtestoidc_task_group
44264484
setup_group:
44274485
- func: fetch source
@@ -5114,6 +5172,7 @@ buildvariants:
51145172
- testtestoidc_task_group
51155173
- testazureoidc_task_group
51165174
- testgcpoidc_task_group
5175+
- testk8soidc_task_group
51175176
- name: rhel8-test-atlas
51185177
display_name: Atlas Cluster Tests
51195178
run_on: rhel80-large

.evergreen/generate_evergreen_tasks.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,8 @@ BUILD_VARIANTS.push({
733733
tasks: [
734734
'testtestoidc_task_group',
735735
'testazureoidc_task_group',
736-
'testgcpoidc_task_group'
736+
'testgcpoidc_task_group',
737+
'testk8soidc_task_group'
737738
]
738739
});
739740

.evergreen/run-oidc-prose-tests.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ if [ "$ENVIRONMENT" = "azure" ]; then
1919
npm run check:oidc-azure
2020
elif [ "$ENVIRONMENT" = "gcp" ]; then
2121
npm run check:oidc-gcp
22-
else
22+
elif [ "$ENVIRONMENT" = "test" ]; then
2323
if [ -z "${OIDC_TOKEN_FILE}" ]; then
2424
echo "Must specify OIDC_TOKEN_FILE"
2525
exit 1
2626
fi
2727
npm run check:oidc-test
28+
else
29+
if [ -z "${K8S_VARIANT}" ]; then
30+
echo "Must specify K8S_VARIANT"
31+
exit 1
32+
fi
33+
npm run check:oidc-k8s
2834
fi

.evergreen/run-oidc-tests-k8s.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
set -o xtrace # Write all commands first to stderr
3+
set -o errexit # Exit the script with error if any of the commands fail
4+
5+
export K8S_DRIVERS_TAR_FILE=/tmp/node-mongodb-native.tgz
6+
tar czf $K8S_DRIVERS_TAR_FILE .
7+
bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/setup-pod.sh
8+
bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/run-self-test.sh
9+
export K8S_TEST_CMD="ENVIRONMENT=k8s ./.evergreen/${SCRIPT}"
10+
source $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/secrets-export.sh
11+
bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/run-driver-test.sh
12+
bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/teardown-pod.sh

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151
"check:oidc-test": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc.prose.test.ts",
152152
"check:oidc-azure": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_azure.prose.05.test.ts",
153153
"check:oidc-gcp": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_gcp.prose.06.test.ts",
154+
"check:oidc-k8s": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_oidc_k8s.prose.07.test.ts",
154155
"check:ocsp": "mocha --config test/manual/mocharc.json test/manual/ocsp_support.test.js",
155156
"check:kerberos": "nyc mocha --config test/manual/mocharc.json test/manual/kerberos.test.ts",
156157
"check:tls": "mocha --config test/manual/mocharc.json test/manual/tls_support.test.ts",

src/cmap/auth/mongo_credentials.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ function getDefaultAuthMechanism(hello: Document | null): AuthMechanism {
3131
const ALLOWED_ENVIRONMENT_NAMES: AuthMechanismProperties['ENVIRONMENT'][] = [
3232
'test',
3333
'azure',
34-
'gcp'
34+
'gcp',
35+
'k8s'
3536
];
3637
const ALLOWED_HOSTS_ERROR = 'Auth mechanism property ALLOWED_HOSTS must be an array of strings.';
3738

@@ -62,7 +63,7 @@ export interface AuthMechanismProperties extends Document {
6263
/** A user provided OIDC human interacted callback function. */
6364
OIDC_HUMAN_CALLBACK?: OIDCCallbackFunction;
6465
/** The OIDC environment. Note that 'test' is for internal use only. */
65-
ENVIRONMENT?: 'test' | 'azure' | 'gcp';
66+
ENVIRONMENT?: 'test' | 'azure' | 'gcp' | 'k8s';
6667
/** Allowed hosts that OIDC auth can connect to. */
6768
ALLOWED_HOSTS?: string[];
6869
/** The resource token for OIDC auth in Azure and GCP. */

src/cmap/auth/mongodb_oidc.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { type AuthContext, AuthProvider } from './auth_provider';
66
import type { MongoCredentials } from './mongo_credentials';
77
import { AzureMachineWorkflow } from './mongodb_oidc/azure_machine_workflow';
88
import { GCPMachineWorkflow } from './mongodb_oidc/gcp_machine_workflow';
9+
import { K8SMachineWorkflow } from './mongodb_oidc/k8s_machine_workflow';
910
import { TokenCache } from './mongodb_oidc/token_cache';
1011
import { TokenMachineWorkflow } from './mongodb_oidc/token_machine_workflow';
1112

@@ -88,7 +89,7 @@ export type OIDCCallbackFunction = (params: OIDCCallbackParams) => Promise<OIDCR
8889
/** The current version of OIDC implementation. */
8990
export const OIDC_VERSION = 1;
9091

91-
type EnvironmentName = 'test' | 'azure' | 'gcp' | undefined;
92+
type EnvironmentName = 'test' | 'azure' | 'gcp' | 'k8s' | undefined;
9293

9394
/** @internal */
9495
export interface Workflow {
@@ -118,6 +119,7 @@ export const OIDC_WORKFLOWS: Map<EnvironmentName, () => Workflow> = new Map();
118119
OIDC_WORKFLOWS.set('test', () => new TokenMachineWorkflow(new TokenCache()));
119120
OIDC_WORKFLOWS.set('azure', () => new AzureMachineWorkflow(new TokenCache()));
120121
OIDC_WORKFLOWS.set('gcp', () => new GCPMachineWorkflow(new TokenCache()));
122+
OIDC_WORKFLOWS.set('k8s', () => new K8SMachineWorkflow(new TokenCache()));
121123

122124
/**
123125
* OIDC auth provider.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { readFile } from 'fs/promises';
2+
3+
import { type AccessToken, MachineWorkflow } from './machine_workflow';
4+
import { type TokenCache } from './token_cache';
5+
6+
/** The fallback file name */
7+
const FALLBACK_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/token';
8+
9+
/** The azure environment variable for the file name. */
10+
const AZURE_FILENAME = 'AZURE_FEDERATED_TOKEN_FILE';
11+
12+
/** The AWS environment variable for the file name. */
13+
const AWS_FILENAME = 'AWS_WEB_IDENTITY_TOKEN_FILE';
14+
15+
export class K8SMachineWorkflow extends MachineWorkflow {
16+
/**
17+
* Instantiate the machine workflow.
18+
*/
19+
constructor(cache: TokenCache) {
20+
super(cache);
21+
}
22+
23+
/**
24+
* Get the token from the environment.
25+
*/
26+
async getToken(): Promise<AccessToken> {
27+
let filename: string;
28+
if (process.env[AZURE_FILENAME]) {
29+
filename = process.env[AZURE_FILENAME];
30+
} else if (process.env[AWS_FILENAME]) {
31+
filename = process.env[AWS_FILENAME];
32+
} else {
33+
filename = FALLBACK_FILENAME;
34+
}
35+
const token = await readFile(filename, 'utf8');
36+
return { access_token: token };
37+
}
38+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { expect } from 'chai';
2+
3+
import { type Collection, MongoClient } from '../../mongodb';
4+
5+
const DEFAULT_URI = 'mongodb://127.0.0.1:27017';
6+
7+
describe('OIDC Auth Spec K8s Tests', function () {
8+
// Note there is no spec or tests for GCP yet, these are 2 scenarios based on the
9+
// drivers tools scripts available.
10+
describe('6. GCP Tests', function () {
11+
let client: MongoClient;
12+
let collection: Collection;
13+
14+
beforeEach(function () {
15+
if (!this.configuration.isOIDC(process.env.MONGODB_URI_SINGLE, 'k8s')) {
16+
this.skipReason = 'K8s OIDC prose tests require a K8s OIDC environment.';
17+
this.skip();
18+
}
19+
});
20+
21+
afterEach(async function () {
22+
await client?.close();
23+
});
24+
25+
describe('7.1 K8s With Environment Set', function () {
26+
beforeEach(function () {
27+
client = new MongoClient(process.env.MONGODB_URI_SINGLE ?? DEFAULT_URI);
28+
collection = client.db('test').collection('test');
29+
});
30+
31+
it('successfully authenticates', async function () {
32+
const result = await collection.findOne();
33+
expect(result).to.not.be.null;
34+
});
35+
});
36+
});
37+
});

0 commit comments

Comments
 (0)