Skip to content

Commit cbed540

Browse files
authored
Refactor OIDC provider tests to share base mock server helper (#3138)
* Initial plan * refactor: share OIDC mock server helper across provider tests * test: tidy shared OIDC mock helper naming and comments * test: align shared OIDC mock helper callback naming --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 5089336 commit cbed540

4 files changed

Lines changed: 113 additions & 138 deletions

File tree

containers/api-proxy/aws-oidc-token-provider.test.js

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,38 @@
22

33
const http = require('http');
44
const { AwsOidcTokenProvider } = require('./aws-oidc-token-provider');
5+
const { createBaseMockServer } = require('./test-helpers/mock-oidc-server');
56

67
function createMockServer(handlers = {}) {
7-
const server = http.createServer((req, res) => {
8-
let body = '';
9-
req.on('data', chunk => { body += chunk; });
10-
req.on('end', () => {
11-
const url = new URL(req.url, `http://localhost`);
12-
13-
// GitHub OIDC token endpoint
14-
if (url.pathname === '/token' && req.method === 'GET') {
15-
const handler = handlers.oidcToken || (() => ({
16-
statusCode: 200,
17-
body: JSON.stringify({ value: 'mock-github-oidc-jwt', count: 1 }),
18-
}));
19-
const result = handler(url, req);
20-
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
21-
res.end(result.body);
22-
return;
23-
}
24-
25-
// AWS STS AssumeRoleWithWebIdentity
26-
if (url.pathname === '/' && url.searchParams.get('Action') === 'AssumeRoleWithWebIdentity') {
27-
const handler = handlers.stsAssume || (() => ({
28-
statusCode: 200,
29-
body: JSON.stringify({
30-
AssumeRoleWithWebIdentityResponse: {
31-
AssumeRoleWithWebIdentityResult: {
32-
Credentials: {
33-
AccessKeyId: 'AKIAIOSFODNN7EXAMPLE',
34-
SecretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
35-
SessionToken: 'FwoGZXIvYXdzEBYaDN...',
36-
Expiration: new Date(Date.now() + 3600000).toISOString(),
37-
},
38-
AssumedRoleUser: {
39-
AssumedRoleId: 'AROA3XFRBF23:awf-oidc-session',
40-
Arn: 'arn:aws:sts::123456789012:assumed-role/role/awf-oidc-session',
41-
},
8+
return createBaseMockServer((url, req, res, routeHandlers) => {
9+
if (url.pathname === '/' && url.searchParams.get('Action') === 'AssumeRoleWithWebIdentity') {
10+
const handler = routeHandlers.stsAssume || (() => ({
11+
statusCode: 200,
12+
body: JSON.stringify({
13+
AssumeRoleWithWebIdentityResponse: {
14+
AssumeRoleWithWebIdentityResult: {
15+
Credentials: {
16+
AccessKeyId: 'AKIAIOSFODNN7EXAMPLE',
17+
SecretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
18+
SessionToken: 'FwoGZXIvYXdzEBYaDN...',
19+
Expiration: new Date(Date.now() + 3600000).toISOString(),
20+
},
21+
AssumedRoleUser: {
22+
AssumedRoleId: 'AROA3XFRBF23:awf-oidc-session',
23+
Arn: 'arn:aws:sts::123456789012:assumed-role/role/awf-oidc-session',
4224
},
4325
},
44-
}),
45-
}));
46-
const result = handler(url, req);
47-
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
48-
res.end(result.body);
49-
return;
50-
}
51-
52-
res.writeHead(404);
53-
res.end('Not found');
54-
});
55-
});
56-
return server;
26+
},
27+
}),
28+
}));
29+
const result = handler(url, req);
30+
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
31+
res.end(result.body);
32+
return true;
33+
}
34+
35+
return false;
36+
}, handlers);
5737
}
5838

5939
describe('AwsOidcTokenProvider', () => {

containers/api-proxy/gcp-oidc-token-provider.test.js

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,41 @@
22

33
const http = require('http');
44
const { GcpOidcTokenProvider } = require('./gcp-oidc-token-provider');
5+
const { createBaseMockServer } = require('./test-helpers/mock-oidc-server');
56

67
function createMockServer(handlers = {}) {
7-
const server = http.createServer((req, res) => {
8-
let body = '';
9-
req.on('data', chunk => { body += chunk; });
10-
req.on('end', () => {
11-
const url = new URL(req.url, `http://localhost`);
12-
13-
// GitHub OIDC token endpoint
14-
if (url.pathname === '/token' && req.method === 'GET') {
15-
const handler = handlers.oidcToken || (() => ({
16-
statusCode: 200,
17-
body: JSON.stringify({ value: 'mock-github-oidc-jwt', count: 1 }),
18-
}));
19-
const result = handler(url, req);
20-
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
21-
res.end(result.body);
22-
return;
23-
}
24-
25-
// GCP STS token exchange
26-
if (url.pathname === '/v1/token' && req.method === 'POST') {
27-
const handler = handlers.stsToken || (() => ({
28-
statusCode: 200,
29-
body: JSON.stringify({
30-
access_token: 'mock-federated-token',
31-
expires_in: 3600,
32-
token_type: 'Bearer',
33-
}),
34-
}));
35-
const result = handler(body, req);
36-
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
37-
res.end(result.body);
38-
return;
39-
}
40-
41-
// GCP service account impersonation
42-
if (url.pathname.includes(':generateAccessToken') && req.method === 'POST') {
43-
const handler = handlers.impersonate || (() => ({
44-
statusCode: 200,
45-
body: JSON.stringify({
46-
accessToken: 'mock-sa-token',
47-
expireTime: new Date(Date.now() + 3600000).toISOString(),
48-
}),
49-
}));
50-
const result = handler(body, req);
51-
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
52-
res.end(result.body);
53-
return;
54-
}
55-
56-
res.writeHead(404);
57-
res.end('Not found');
58-
});
59-
});
60-
return server;
8+
return createBaseMockServer((url, req, res, routeHandlers, body) => {
9+
if (url.pathname === '/v1/token' && req.method === 'POST') {
10+
const handler = routeHandlers.stsToken || (() => ({
11+
statusCode: 200,
12+
body: JSON.stringify({
13+
access_token: 'mock-federated-token',
14+
expires_in: 3600,
15+
token_type: 'Bearer',
16+
}),
17+
}));
18+
const result = handler(body, req);
19+
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
20+
res.end(result.body);
21+
return true;
22+
}
23+
24+
if (url.pathname.includes(':generateAccessToken') && req.method === 'POST') {
25+
const handler = routeHandlers.impersonate || (() => ({
26+
statusCode: 200,
27+
body: JSON.stringify({
28+
accessToken: 'mock-sa-token',
29+
expireTime: new Date(Date.now() + 3600000).toISOString(),
30+
}),
31+
}));
32+
const result = handler(body, req);
33+
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
34+
res.end(result.body);
35+
return true;
36+
}
37+
38+
return false;
39+
}, handlers);
6140
}
6241

6342
describe('GcpOidcTokenProvider', () => {

containers/api-proxy/oidc-token-provider.test.js

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,24 @@
33
const http = require('http');
44
const { httpPost } = require('./github-oidc');
55
const { OidcTokenProvider } = require('./oidc-token-provider');
6+
const { createBaseMockServer } = require('./test-helpers/mock-oidc-server');
67

7-
// Helper to create a mock HTTP server that responds to token requests
8+
// Helper to create a mock OIDC server with Azure token exchange support
89
function createMockOidcServer(handlers = {}) {
9-
const server = http.createServer((req, res) => {
10-
let body = '';
11-
req.on('data', chunk => { body += chunk; });
12-
req.on('end', () => {
13-
const url = new URL(req.url, `http://localhost`);
14-
15-
// GitHub OIDC token endpoint
16-
if (url.pathname === '/token' && req.method === 'GET') {
17-
const handler = handlers.oidcToken || (() => ({
18-
statusCode: 200,
19-
body: JSON.stringify({ value: 'mock-github-oidc-jwt', count: 1 }),
20-
}));
21-
const result = handler(url, req);
22-
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
23-
res.end(result.body);
24-
return;
25-
}
26-
27-
// Azure token exchange endpoint
28-
if (url.pathname.includes('/oauth2/v2.0/token') && req.method === 'POST') {
29-
const handler = handlers.azureToken || (() => ({
30-
statusCode: 200,
31-
body: JSON.stringify({ access_token: 'mock-azure-ad-token', expires_in: 3600 }),
32-
}));
33-
const result = handler(body, req);
34-
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
35-
res.end(result.body);
36-
return;
37-
}
38-
39-
res.writeHead(404);
40-
res.end('Not found');
41-
});
42-
});
43-
return server;
10+
return createBaseMockServer((url, req, res, routeHandlers, body) => {
11+
if (url.pathname.includes('/oauth2/v2.0/token') && req.method === 'POST') {
12+
const handler = routeHandlers.azureToken || (() => ({
13+
statusCode: 200,
14+
body: JSON.stringify({ access_token: 'mock-azure-ad-token', expires_in: 3600 }),
15+
}));
16+
const result = handler(body, req);
17+
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
18+
res.end(result.body);
19+
return true;
20+
}
21+
22+
return false;
23+
}, handlers);
4424
}
4525

4626
describe('OidcTokenProvider', () => {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
const http = require('http');
4+
5+
function createBaseMockServer(handleProviderRoute, handlers = {}) {
6+
const routeHandler = handleProviderRoute || (() => false);
7+
8+
return http.createServer((req, res) => {
9+
let body = '';
10+
req.on('data', chunk => { body += chunk; });
11+
req.on('end', () => {
12+
const url = new URL(req.url, 'http://localhost');
13+
14+
if (url.pathname === '/token' && req.method === 'GET') {
15+
const handler = handlers.oidcToken || (() => ({
16+
statusCode: 200,
17+
body: JSON.stringify({ value: 'mock-github-oidc-jwt', count: 1 }),
18+
}));
19+
const result = handler(url, req);
20+
res.writeHead(result.statusCode, { 'Content-Type': 'application/json' });
21+
res.end(result.body);
22+
return;
23+
}
24+
25+
const handled = routeHandler(url, req, res, handlers, body);
26+
if (handled) {
27+
return;
28+
}
29+
30+
res.writeHead(404);
31+
res.end('Not found');
32+
});
33+
});
34+
}
35+
36+
module.exports = { createBaseMockServer };

0 commit comments

Comments
 (0)