Skip to content

Commit 99ebebd

Browse files
feat(mbe): move ebe ping handler to typed route
Ticket: WP-46222
1 parent 030547e commit 99ebebd

File tree

2 files changed

+100
-41
lines changed

2 files changed

+100
-41
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import * as t from 'io-ts';
2+
import { apiSpec, httpRoute, httpRequest, HttpResponse } from '@api-ts/io-ts-http';
3+
import { createRouter, type WrappedRouter } from '@api-ts/typed-express-router';
4+
import { Response } from '@api-ts/response';
5+
import https from 'https';
6+
import superagent from 'superagent';
7+
import { MasterExpressConfig, TlsMode } from '../../config';
8+
import logger from '../../logger';
9+
import { withResponseHandler } from '../../shared/responseHandler';
10+
11+
// Response type for /ping/enclavedExpress endpoint
12+
const PingEnclavedResponse: HttpResponse = {
13+
200: t.type({
14+
status: t.string,
15+
// TODO: Move to common definition between enclavedExpress and masterExpress
16+
enclavedResponse: t.type({
17+
message: t.string,
18+
timestamp: t.string,
19+
}),
20+
}),
21+
500: t.type({
22+
error: t.string,
23+
details: t.string,
24+
}),
25+
};
26+
27+
// API Specification
28+
export const EnclavedExpressApiSpec = apiSpec({
29+
'v1.enclaved.ping': {
30+
post: httpRoute({
31+
method: 'POST',
32+
path: '/ping/enclavedExpress',
33+
request: httpRequest({}),
34+
response: PingEnclavedResponse,
35+
description: 'Ping the enclaved express server',
36+
}),
37+
},
38+
});
39+
40+
// Create router with handlers
41+
export function createEnclavedExpressRouter(
42+
cfg: MasterExpressConfig,
43+
): WrappedRouter<typeof EnclavedExpressApiSpec> {
44+
const router = createRouter(EnclavedExpressApiSpec, {
45+
onDecodeError: (err, _req, _res) => {
46+
logger.error('Decode error:', { error: err });
47+
},
48+
onEncodeError: (err, _req, _res) => {
49+
logger.error('Encode error:', { error: err });
50+
},
51+
});
52+
53+
// Ping endpoint handler
54+
router.post('v1.enclaved.ping', [
55+
withResponseHandler(async () => {
56+
logger.debug('Pinging enclaved express');
57+
58+
try {
59+
let response;
60+
if (cfg.tlsMode === TlsMode.MTLS) {
61+
// Use Master Express's own certificate as client cert when connecting to Enclaved Express
62+
const httpsAgent = new https.Agent({
63+
rejectUnauthorized: !cfg.allowSelfSigned,
64+
ca: cfg.enclavedExpressCert,
65+
// Provide client certificate for mTLS
66+
key: cfg.tlsKey,
67+
cert: cfg.tlsCert,
68+
});
69+
70+
response = await superagent
71+
.post(`${cfg.enclavedExpressUrl}/ping`)
72+
.ca(cfg.enclavedExpressCert)
73+
.agent(httpsAgent)
74+
.send();
75+
} else {
76+
// When TLS is disabled, use plain HTTP without any TLS configuration
77+
response = await superagent.post(`${cfg.enclavedExpressUrl}/ping`).send();
78+
}
79+
80+
return Response.ok({
81+
status: 'Successfully pinged enclaved express',
82+
enclavedResponse: response.body,
83+
});
84+
} catch (error) {
85+
logger.error('Failed to ping enclaved express:', { error });
86+
return Response.internalError({
87+
error: 'Failed to ping enclaved express',
88+
details: error instanceof Error ? error.message : String(error),
89+
});
90+
}
91+
}),
92+
]);
93+
94+
return router;
95+
}

src/routes/master.ts

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import express from 'express';
2-
import superagent from 'superagent';
3-
import https from 'https';
42
import { BitGo, BitGoOptions } from 'bitgo';
53
import { BitGoBase } from '@bitgo/sdk-core';
64
import { version } from 'bitgo/package.json';
75
import pjson from '../../package.json';
8-
import { MasterExpressConfig, TlsMode } from '../config';
6+
import { MasterExpressConfig } from '../config';
97
import { BitGoRequest } from '../types/request';
108
import { handleGenerateWalletOnPrem } from '../masterBitgoExpress/generateWallet';
119
import { createHealthCheckRouter } from '../masterBitgoExpress/routers/healthCheck';
10+
import { createEnclavedExpressRouter } from '../masterBitgoExpress/routers/enclavedExpressHealth';
1211
import { promiseWrapper } from './utils';
1312
import logger from '../logger';
1413

@@ -70,44 +69,9 @@ export function setupRoutes(app: express.Application, cfg: MasterExpressConfig):
7069
// Setup health check routes using the new router
7170
app.use(createHealthCheckRouter('master express'));
7271

73-
// Add enclaved express ping route
74-
app.post('/ping/enclavedExpress', async (req, res) => {
75-
try {
76-
logger.debug('Pinging enclaved express');
77-
78-
let response;
79-
if (cfg.tlsMode === TlsMode.MTLS) {
80-
// Use Master Express's own certificate as client cert when connecting to Enclaved Express
81-
const httpsAgent = new https.Agent({
82-
rejectUnauthorized: !cfg.allowSelfSigned,
83-
ca: cfg.enclavedExpressCert,
84-
// Provide client certificate for mTLS
85-
key: cfg.tlsKey,
86-
cert: cfg.tlsCert,
87-
});
88-
89-
response = await superagent
90-
.post(`${cfg.enclavedExpressUrl}/ping`)
91-
.ca(cfg.enclavedExpressCert)
92-
.agent(httpsAgent)
93-
.send();
94-
} else {
95-
// When TLS is disabled, use plain HTTP without any TLS configuration
96-
response = await superagent.post(`${cfg.enclavedExpressUrl}/ping`).send();
97-
}
98-
99-
res.json({
100-
status: 'Successfully pinged enclaved express',
101-
enclavedResponse: response.body,
102-
});
103-
} catch (error) {
104-
logger.error('Failed to ping enclaved express:', { error });
105-
res.status(500).json({
106-
error: 'Failed to ping enclaved express',
107-
details: error instanceof Error ? error.message : String(error),
108-
});
109-
}
110-
});
72+
// Add enclaved express routes for pinging the enclaved express server
73+
// TODO: Add version endpoint to enclaved express
74+
app.use(createEnclavedExpressRouter(cfg));
11175

11276
// TODO: Add api-ts to these new API routes
11377
app.post(

0 commit comments

Comments
 (0)