Skip to content

Commit 0a0dd30

Browse files
committed
fix: migrate machine workflows to callbacks
1 parent e386c87 commit 0a0dd30

12 files changed

+90
-303
lines changed

src/cmap/auth/mongodb_oidc.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import type { HandshakeDocument } from '../connect';
44
import type { Connection } from '../connection';
55
import { type AuthContext, AuthProvider } from './auth_provider';
66
import type { MongoCredentials } from './mongo_credentials';
7-
import { AzureMachineWorkflow } from './mongodb_oidc/azure_machine_workflow';
8-
import { GCPMachineWorkflow } from './mongodb_oidc/gcp_machine_workflow';
9-
import { K8SMachineWorkflow } from './mongodb_oidc/k8s_machine_workflow';
7+
import { AutomatedCallbackWorkflow } from './mongodb_oidc/automated_callback_workflow';
8+
import { callback as azureCallback } from './mongodb_oidc/azure_machine_workflow';
9+
import { callback as gcpCallback } from './mongodb_oidc/gcp_machine_workflow';
10+
import { callback as k8sCallback } from './mongodb_oidc/k8s_machine_workflow';
1011
import { TokenCache } from './mongodb_oidc/token_cache';
11-
import { TokenMachineWorkflow } from './mongodb_oidc/token_machine_workflow';
12+
import { callback as testCallback } from './mongodb_oidc/token_machine_workflow';
1213

1314
/** Error when credentials are missing. */
1415
const MISSING_CREDENTIALS_ERROR = 'AuthContext must provide credentials.';
@@ -78,6 +79,8 @@ export interface OIDCCallbackParams {
7879
idpInfo?: IdPInfo;
7980
/** The refresh token, if applicable, to be used by the callback to request a new token from the issuer. */
8081
refreshToken?: string;
82+
/** The token audience for GCP and Azure. */
83+
tokenAudience?: string;
8184
}
8285

8386
/**
@@ -118,10 +121,10 @@ export interface Workflow {
118121

119122
/** @internal */
120123
export const OIDC_WORKFLOWS: Map<EnvironmentName, () => Workflow> = new Map();
121-
OIDC_WORKFLOWS.set('test', () => new TokenMachineWorkflow(new TokenCache()));
122-
OIDC_WORKFLOWS.set('azure', () => new AzureMachineWorkflow(new TokenCache()));
123-
OIDC_WORKFLOWS.set('gcp', () => new GCPMachineWorkflow(new TokenCache()));
124-
OIDC_WORKFLOWS.set('k8s', () => new K8SMachineWorkflow(new TokenCache()));
124+
OIDC_WORKFLOWS.set('test', () => new AutomatedCallbackWorkflow(new TokenCache(), testCallback));
125+
OIDC_WORKFLOWS.set('azure', () => new AutomatedCallbackWorkflow(new TokenCache(), azureCallback));
126+
OIDC_WORKFLOWS.set('gcp', () => new AutomatedCallbackWorkflow(new TokenCache(), gcpCallback));
127+
OIDC_WORKFLOWS.set('k8s', () => new AutomatedCallbackWorkflow(new TokenCache(), k8sCallback));
125128

126129
/**
127130
* OIDC auth provider.

src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export class AutomatedCallbackWorkflow extends CallbackWorkflow {
6666
if (credentials.username) {
6767
params.username = credentials.username;
6868
}
69+
if (credentials.mechanismProperties.TOKEN_RESOURCE) {
70+
params.tokenAudience = credentials.mechanismProperties.TOKEN_RESOURCE;
71+
}
6972
const timeout = Timeout.expires(AUTOMATED_TIMEOUT_MS);
7073
try {
7174
return await Promise.race([this.executeAndValidateCallback(params), timeout]);

src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { addAzureParams, AZURE_BASE_URL } from '../../../client-side-encryption/providers/azure';
22
import { MongoAzureError } from '../../../error';
33
import { get } from '../../../utils';
4-
import type { MongoCredentials } from '../mongo_credentials';
5-
import { type AccessToken, MachineWorkflow } from './machine_workflow';
6-
import { type TokenCache } from './token_cache';
4+
import type { OIDCCallbackParams, OIDCResponse } from '../mongodb_oidc';
75

86
/** Azure request headers. */
97
const AZURE_HEADERS = Object.freeze({ Metadata: 'true', Accept: 'application/json' });
@@ -17,39 +15,27 @@ const TOKEN_RESOURCE_MISSING_ERROR =
1715
'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is azure.';
1816

1917
/**
20-
* Device workflow implementation for Azure.
21-
*
22-
* @internal
18+
* The callback function to be used in the automated callback workflow.
19+
* @param params - The OIDC callback parameters.
20+
* @returns The OIDC response.
2321
*/
24-
export class AzureMachineWorkflow extends MachineWorkflow {
25-
/**
26-
* Instantiate the machine workflow.
27-
*/
28-
constructor(cache: TokenCache) {
29-
super(cache);
22+
export async function callback(params: OIDCCallbackParams): Promise<OIDCResponse> {
23+
const tokenAudience = params.tokenAudience;
24+
const username = params.username;
25+
if (!tokenAudience) {
26+
throw new MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
3027
}
31-
32-
/**
33-
* Get the token from the environment.
34-
*/
35-
async getToken(credentials?: MongoCredentials): Promise<AccessToken> {
36-
const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
37-
const username = credentials?.username;
38-
if (!tokenAudience) {
39-
throw new MongoAzureError(TOKEN_RESOURCE_MISSING_ERROR);
40-
}
41-
const response = await getAzureTokenData(tokenAudience, username);
42-
if (!isEndpointResultValid(response)) {
43-
throw new MongoAzureError(ENDPOINT_RESULT_ERROR);
44-
}
45-
return response;
28+
const response = await getAzureTokenData(tokenAudience, username);
29+
if (!isEndpointResultValid(response)) {
30+
throw new MongoAzureError(ENDPOINT_RESULT_ERROR);
4631
}
32+
return response;
4733
}
4834

4935
/**
5036
* Hit the Azure endpoint to get the token data.
5137
*/
52-
async function getAzureTokenData(tokenAudience: string, username?: string): Promise<AccessToken> {
38+
async function getAzureTokenData(tokenAudience: string, username?: string): Promise<OIDCResponse> {
5339
const url = new URL(AZURE_BASE_URL);
5440
addAzureParams(url, tokenAudience, username);
5541
const response = await get(url, {
@@ -62,8 +48,8 @@ async function getAzureTokenData(tokenAudience: string, username?: string): Prom
6248
}
6349
const result = JSON.parse(response.body);
6450
return {
65-
access_token: result.access_token,
66-
expires_in: Number(result.expires_in)
51+
accessToken: result.access_token,
52+
expiresInSeconds: Number(result.expires_in)
6753
};
6854
}
6955

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { MongoGCPError } from '../../../error';
22
import { get } from '../../../utils';
3-
import { type MongoCredentials } from '../mongo_credentials';
4-
import { type AccessToken, MachineWorkflow } from './machine_workflow';
5-
import { type TokenCache } from './token_cache';
3+
import type { OIDCCallbackParams, OIDCResponse } from '../mongodb_oidc';
64

75
/** GCP base URL. */
86
const GCP_BASE_URL =
@@ -15,30 +13,23 @@ const GCP_HEADERS = Object.freeze({ 'Metadata-Flavor': 'Google' });
1513
const TOKEN_RESOURCE_MISSING_ERROR =
1614
'TOKEN_RESOURCE must be set in the auth mechanism properties when ENVIRONMENT is gcp.';
1715

18-
export class GCPMachineWorkflow extends MachineWorkflow {
19-
/**
20-
* Instantiate the machine workflow.
21-
*/
22-
constructor(cache: TokenCache) {
23-
super(cache);
24-
}
25-
26-
/**
27-
* Get the token from the environment.
28-
*/
29-
async getToken(credentials?: MongoCredentials): Promise<AccessToken> {
30-
const tokenAudience = credentials?.mechanismProperties.TOKEN_RESOURCE;
31-
if (!tokenAudience) {
32-
throw new MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
33-
}
34-
return await getGcpTokenData(tokenAudience);
16+
/**
17+
* The callback function to be used in the automated callback workflow.
18+
* @param params - The OIDC callback parameters.
19+
* @returns The OIDC response.
20+
*/
21+
export async function callback(params: OIDCCallbackParams): Promise<OIDCResponse> {
22+
const tokenAudience = params.tokenAudience;
23+
if (!tokenAudience) {
24+
throw new MongoGCPError(TOKEN_RESOURCE_MISSING_ERROR);
3525
}
26+
return await getGcpTokenData(tokenAudience);
3627
}
3728

3829
/**
3930
* Hit the GCP endpoint to get the token data.
4031
*/
41-
async function getGcpTokenData(tokenAudience: string): Promise<AccessToken> {
32+
async function getGcpTokenData(tokenAudience: string): Promise<OIDCResponse> {
4233
const url = new URL(GCP_BASE_URL);
4334
url.searchParams.append('audience', tokenAudience);
4435
const response = await get(url, {
@@ -49,5 +40,5 @@ async function getGcpTokenData(tokenAudience: string): Promise<AccessToken> {
4940
`Status code ${response.status} returned from the GCP endpoint. Response body: ${response.body}`
5041
);
5142
}
52-
return { access_token: response.body };
43+
return { accessToken: response.body };
5344
}
Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { readFile } from 'fs/promises';
22

3-
import { type AccessToken, MachineWorkflow } from './machine_workflow';
4-
import { type TokenCache } from './token_cache';
3+
import type { OIDCResponse } from '../mongodb_oidc';
54

65
/** The fallback file name */
76
const FALLBACK_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/token';
@@ -12,27 +11,20 @@ const AZURE_FILENAME = 'AZURE_FEDERATED_TOKEN_FILE';
1211
/** The AWS environment variable for the file name. */
1312
const AWS_FILENAME = 'AWS_WEB_IDENTITY_TOKEN_FILE';
1413

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 };
14+
/**
15+
* The callback function to be used in the automated callback workflow.
16+
* @param params - The OIDC callback parameters.
17+
* @returns The OIDC response.
18+
*/
19+
export async function callback(): Promise<OIDCResponse> {
20+
let filename: string;
21+
if (process.env[AZURE_FILENAME]) {
22+
filename = process.env[AZURE_FILENAME];
23+
} else if (process.env[AWS_FILENAME]) {
24+
filename = process.env[AWS_FILENAME];
25+
} else {
26+
filename = FALLBACK_FILENAME;
3727
}
28+
const token = await readFile(filename, 'utf8');
29+
return { accessToken: token };
3830
}

src/cmap/auth/mongodb_oidc/machine_workflow.ts

Lines changed: 0 additions & 142 deletions
This file was deleted.

0 commit comments

Comments
 (0)