Skip to content

Commit 2cfbf74

Browse files
committed
chore(mbe): move ebe config checks to middleware
Ticket: WP-4724
1 parent 8488e2d commit 2cfbf74

7 files changed

Lines changed: 109 additions & 19 deletions

File tree

src/__tests__/masterBitgoExpress/generateWallet.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,35 @@ describe('POST /api/:coin/wallet/generate', () => {
142142
bitgoAddBitGoKeyNock.done();
143143
bitgoAddWalletNock.done();
144144
});
145+
146+
it('should fail when enclaved express client is not configured', async () => {
147+
// Create a config without enclaved express settings
148+
const invalidConfig: Partial<MasterExpressConfig> = {
149+
appMode: AppMode.MASTER_EXPRESS,
150+
port: 0,
151+
bind: 'localhost',
152+
timeout: 60000,
153+
logFile: '',
154+
env: 'test',
155+
disableEnvCheck: true,
156+
authVersion: 2,
157+
tlsMode: TlsMode.DISABLED,
158+
mtlsRequestCert: false,
159+
allowSelfSigned: true,
160+
};
161+
162+
const app = expressApp(invalidConfig as MasterExpressConfig);
163+
const testAgent = request.agent(app);
164+
165+
const response = await testAgent
166+
.post(`/api/${coin}/wallet/generate`)
167+
.set('Authorization', `Bearer ${accessToken}`)
168+
.send({
169+
label: 'test-wallet',
170+
});
171+
172+
response.status.should.equal(500);
173+
response.body.should.have.property('error');
174+
response.body.error.should.equal('Please configure enclaved express configs.');
175+
});
145176
});

src/__tests__/masterBitgoExpress/sendMany.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,42 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => {
260260
walletGetNock.done();
261261
keychainGetNock.done();
262262
});
263+
264+
it('should fail when enclaved express client is not configured', async () => {
265+
// Create a config without enclaved express settings
266+
const invalidConfig: Partial<MasterExpressConfig> = {
267+
appMode: AppMode.MASTER_EXPRESS,
268+
port: 0,
269+
bind: 'localhost',
270+
timeout: 60000,
271+
logFile: '',
272+
env: 'test',
273+
disableEnvCheck: true,
274+
authVersion: 2,
275+
tlsMode: TlsMode.DISABLED,
276+
mtlsRequestCert: false,
277+
allowSelfSigned: true,
278+
};
279+
280+
const app = expressApp(invalidConfig as MasterExpressConfig);
281+
const testAgent = request.agent(app);
282+
283+
const response = await testAgent
284+
.post(`/api/${coin}/wallet/${walletId}/sendMany`)
285+
.set('Authorization', `Bearer ${accessToken}`)
286+
.send({
287+
recipients: [
288+
{
289+
address: 'tb1qtest1',
290+
amount: '100000',
291+
},
292+
],
293+
source: 'user',
294+
pubkey: 'xpub_user',
295+
});
296+
297+
response.status.should.equal(500);
298+
response.body.should.have.property('error');
299+
response.body.error.should.equal('Please configure enclaved express configs.');
300+
});
263301
});

src/masterBitgoExpress/generateWallet.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ import {
88
WalletWithKeychains,
99
AddKeychainOptions,
1010
} from '@bitgo/sdk-core';
11-
import { createEnclavedExpressClient } from './enclavedExpressClient';
1211
import _ from 'lodash';
1312
import { MasterApiSpecRouteRequest } from './routers/masterApiSpec';
14-
import { isMasterExpressConfig } from '../types';
15-
import assert from 'assert';
1613

1714
/**
1815
* This route is used to generate a multisig wallet when enclaved express is enabled
@@ -23,17 +20,8 @@ export async function handleGenerateWalletOnPrem(
2320
const bitgo = req.bitgo;
2421
const baseCoin = bitgo.coin(req.params.coin);
2522

26-
assert(
27-
isMasterExpressConfig(req.config),
28-
'Expected req.config to be of type MasterExpressConfig',
29-
);
30-
31-
const enclavedExpressClient = createEnclavedExpressClient(req.config, req.params.coin);
32-
if (!enclavedExpressClient) {
33-
throw new Error(
34-
'Enclaved express client not configured - enclaved express features will be disabled',
35-
);
36-
}
23+
// The enclavedExpressClient is now available from the request
24+
const enclavedExpressClient = req.enclavedExpressClient;
3725

3826
const reqId = new RequestTracer();
3927

src/masterBitgoExpress/handleSendMany.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ export async function handleSendMany(req: MasterApiSpecRouteRequest<'v1.wallet.s
2121
if (!isMasterExpressConfig(req.config)) {
2222
throw new Error('Configuration must be in master express mode');
2323
}
24-
const enclavedExpressClient = createEnclavedExpressClient(req.config, req.params.coin);
25-
if (!enclavedExpressClient) {
26-
throw new Error('Please configure enclaved express configs to sign the transactions.');
27-
}
24+
const enclavedExpressClient = req.enclavedExpressClient;
2825
const reqId = new RequestTracer();
2926
const bitgo = req.bitgo;
3027
const baseCoin = bitgo.coin(req.params.coin);
@@ -96,7 +93,7 @@ export async function handleSendMany(req: MasterApiSpecRouteRequest<'v1.wallet.s
9693
const err = e as Error;
9794
logger.error('transaction prebuild failed local validation:', err.message);
9895
logger.error('transaction prebuild:', JSON.stringify(txPrebuilt, null, 2));
99-
throw new Error(`Transaction prebuild failed local validation: ${err.message}`);
96+
throw new Error(`Transaction prebuild failed local validation: ${err.message}`);
10097
}
10198

10299
logger.debug('Tx prebuild: %s', JSON.stringify(txPrebuilt, null, 2));
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Request, Response, NextFunction } from 'express';
2+
import { isMasterExpressConfig } from '../types';
3+
import { createEnclavedExpressClient } from './enclavedExpressClient';
4+
import { BitGoRequest } from '../types/request';
5+
6+
/**
7+
* Middleware to validate master express configuration and enclaved express client
8+
*/
9+
export function validateMasterExpressConfig(req: Request, res: Response, next: NextFunction) {
10+
const bitgoReq = req as BitGoRequest;
11+
12+
// Validate master express config
13+
if (!isMasterExpressConfig(bitgoReq.config)) {
14+
return res.status(500).json({
15+
error: 'Invalid configuration',
16+
details: 'Expected req.config to be of type MasterExpressConfig',
17+
});
18+
}
19+
20+
// Validate enclaved express client
21+
const enclavedExpressClient = createEnclavedExpressClient(bitgoReq.config, bitgoReq.params?.coin);
22+
if (!enclavedExpressClient) {
23+
return res.status(500).json({
24+
error: 'Please configure enclaved express configs.',
25+
details: 'Enclaved express features will be disabled',
26+
});
27+
}
28+
29+
// Attach the client to the request for use in route handlers
30+
bitgoReq.enclavedExpressClient = enclavedExpressClient;
31+
next();
32+
}

src/masterBitgoExpress/routers/masterApiSpec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { MasterExpressConfig } from '../../initConfig';
1818
import { handleGenerateWalletOnPrem } from '../generateWallet';
1919
import { prepareBitGo, responseHandler } from '../../shared/middleware';
2020
import { handleSendMany } from '../handleSendMany';
21+
import { validateMasterExpressConfig } from '../middleware';
2122

2223
// Middleware functions
2324
export function parseBody(req: express.Request, res: express.Response, next: express.NextFunction) {
@@ -141,6 +142,7 @@ export function createMasterApiRouter(
141142
// Add middleware to all routes
142143
router.use(parseBody);
143144
router.use(prepareBitGo(cfg));
145+
router.use(validateMasterExpressConfig);
144146

145147
// Generate wallet endpoint handler
146148
router.post('v1.wallet.generate', [

src/types/request.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import express from 'express';
22
import { type BitGo } from 'bitgo';
33
import { Config } from '../types';
4+
import { EnclavedExpressClient } from '../masterBitgoExpress/enclavedExpressClient';
45

56
// Extended request type for BitGo Express
67
export interface BitGoRequest<T extends Config = Config> extends express.Request {
78
bitgo: BitGo;
89
config: T;
10+
enclavedExpressClient: EnclavedExpressClient;
911
}
1012

1113
export function isBitGoRequest<T extends Config>(req: express.Request): req is BitGoRequest<T> {

0 commit comments

Comments
 (0)