Skip to content

Commit 8ca192c

Browse files
mohammadalfaiyazbitgopranavjain97
authored andcommitted
feat(express): add enclaved express configurations
TICKET: WP-4376
1 parent 9bf6627 commit 8ca192c

File tree

7 files changed

+105
-30
lines changed

7 files changed

+105
-30
lines changed

modules/express/README.md

Lines changed: 28 additions & 27 deletions
Large diffs are not rendered by default.

modules/express/src/args.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ parser.addArgument(['--externalSignerUrl'], {
9696
help: 'URL which specifies the external signing API.',
9797
});
9898

99+
parser.addArgument(['--enclavedExpressUrl'], {
100+
help: 'URL to an Express instance in a secure environment.',
101+
});
102+
103+
parser.addArgument(['--enclavedExpressSSLCert'], {
104+
help: 'Path to the SSL certificate file for communicating with enclavedExpressUrl.',
105+
});
106+
99107
parser.addArgument(['--signerMode'], {
100108
action: 'storeConst',
101109
constant: true,

modules/express/src/clientRoutes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import type { ParamsDictionary } from 'express-serve-static-core';
3838
import * as _ from 'lodash';
3939
import * as url from 'url';
4040
import * as superagent from 'superagent';
41+
import { handlePingEnclavedExpress } from './enclavedExpressRoutes';
4142

4243
// RequestTracer should be extracted into a separate npm package (along with
4344
// the rest of the BitGoJS HTTP request machinery)
@@ -1770,6 +1771,10 @@ export function setupSigningRoutes(app: express.Application, config: Config): vo
17701771
);
17711772
}
17721773

1774+
export function setupEnclavedSigningRoutes(app: express.Application, config: Config): void {
1775+
app.post('/ping/enclavedExpress', parseBody, prepareBitGo(config), promiseWrapper(handlePingEnclavedExpress));
1776+
}
1777+
17731778
export function setupLightningSignerNodeRoutes(app: express.Application, config: Config): void {
17741779
app.post(
17751780
'/api/v2/:coin/wallet/:id/initwallet',

modules/express/src/config.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { EnvironmentName, V1Network } from 'bitgo';
22
import { isNil, isNumber } from 'lodash';
3+
import { readFileSync } from 'fs';
34
import 'dotenv/config';
45

56
import { args } from './args';
@@ -38,6 +39,8 @@ export interface Config {
3839
customBitcoinNetwork?: V1Network;
3940
authVersion: number;
4041
externalSignerUrl?: string;
42+
enclavedExpressUrl?: string;
43+
enclavedExpressSSLCert?: string;
4144
signerMode?: boolean;
4245
signerFileSystemPath?: string;
4346
lightningSignerFileSystemPath?: string;
@@ -64,6 +67,8 @@ export const ArgConfig = (args): Partial<Config> => ({
6467
customBitcoinNetwork: args.custombitcoinnetwork,
6568
authVersion: args.authVersion,
6669
externalSignerUrl: args.externalSignerUrl,
70+
enclavedExpressUrl: args.enclavedExpressUrl,
71+
enclavedExpressSSLCert: args.enclavedExpressSSLCert,
6772
signerMode: args.signerMode,
6873
signerFileSystemPath: args.signerFileSystemPath,
6974
lightningSignerFileSystemPath: args.lightningSignerFileSystemPath,
@@ -90,6 +95,8 @@ export const EnvConfig = (): Partial<Config> => ({
9095
customBitcoinNetwork: readEnvVar('BITGO_CUSTOM_BITCOIN_NETWORK') as V1Network,
9196
authVersion: Number(readEnvVar('BITGO_AUTH_VERSION')),
9297
externalSignerUrl: readEnvVar('BITGO_EXTERNAL_SIGNER_URL'),
98+
enclavedExpressUrl: readEnvVar('BITGO_ENCLAVED_EXPRESS_URL'),
99+
enclavedExpressSSLCert: readEnvVar('BITGO_ENCLAVED_EXPRESS_SSL_CERT'),
93100
signerMode: readEnvVar('BITGO_SIGNER_MODE') ? true : undefined,
94101
signerFileSystemPath: readEnvVar('BITGO_SIGNER_FILE_SYSTEM_PATH'),
95102
lightningSignerFileSystemPath: readEnvVar('BITGO_LIGHTNING_SIGNER_FILE_SYSTEM_PATH'),
@@ -110,6 +117,8 @@ export const DefaultConfig: Config = {
110117
disableEnvCheck: true,
111118
timeout: 305 * 1000,
112119
authVersion: 2,
120+
enclavedExpressUrl: undefined,
121+
enclavedExpressSSLCert: undefined,
113122
};
114123

115124
/**
@@ -147,6 +156,8 @@ function mergeConfigs(...configs: Partial<Config>[]): Config {
147156
const disableSSL = get('disableSSL') || false;
148157
let customRootUri = get('customRootUri');
149158
let externalSignerUrl = get('externalSignerUrl');
159+
let enclavedExpressUrl = get('enclavedExpressUrl');
160+
let enclavedExpressSSLCert: string | undefined;
150161

151162
if (disableSSL !== true) {
152163
if (customRootUri) {
@@ -155,6 +166,19 @@ function mergeConfigs(...configs: Partial<Config>[]): Config {
155166
if (externalSignerUrl) {
156167
externalSignerUrl = forceSecureUrl(externalSignerUrl);
157168
}
169+
if (enclavedExpressUrl) {
170+
enclavedExpressUrl = forceSecureUrl(enclavedExpressUrl);
171+
console.log('Using secure enclaved express URL:', enclavedExpressUrl);
172+
}
173+
const enclavedExpressSSLCertPath = get('enclavedExpressSSLCert');
174+
if (enclavedExpressSSLCertPath) {
175+
try {
176+
enclavedExpressSSLCert = readFileSync(enclavedExpressSSLCertPath, { encoding: 'utf8' });
177+
console.log('Successfully loaded SSL cert from:', enclavedExpressSSLCertPath);
178+
} catch (e) {
179+
console.error(`Failed to load enclaved express SSL cert from path: ${enclavedExpressSSLCertPath}`, e);
180+
}
181+
}
158182
}
159183

160184
return {
@@ -176,6 +200,8 @@ function mergeConfigs(...configs: Partial<Config>[]): Config {
176200
customBitcoinNetwork: get('customBitcoinNetwork'),
177201
authVersion: get('authVersion'),
178202
externalSignerUrl,
203+
enclavedExpressUrl,
204+
enclavedExpressSSLCert,
179205
signerMode: get('signerMode'),
180206
signerFileSystemPath: get('signerFileSystemPath'),
181207
lightningSignerFileSystemPath: get('lightningSignerFileSystemPath'),
@@ -184,8 +210,8 @@ function mergeConfigs(...configs: Partial<Config>[]): Config {
184210
};
185211
}
186212

187-
export const config = () => {
213+
export function config(): Config {
188214
const arg = ArgConfig(args());
189215
const env = EnvConfig();
190216
return mergeConfigs(env, arg);
191-
};
217+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import * as superagent from 'superagent';
2+
import * as debug from 'debug';
3+
import * as express from 'express';
4+
import { retryPromise } from '../retryPromise';
5+
6+
export async function handlePingEnclavedExpress(req: express.Request) {
7+
return await retryPromise(
8+
() =>
9+
superagent
10+
.post(`${req.config?.enclavedExpressUrl}/ping`)
11+
.ca(req.config?.enclavedExpressSSLCert as string)
12+
.send({}),
13+
(err, tryCount) => {
14+
debug(`Failed to ping enclavedExpress: ${err.message}`);
15+
}
16+
);
17+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './enclavedExpressRoutes';

modules/express/src/expressApp.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,16 @@ function createHttpServer(app: express.Application): http.Server {
116116
*/
117117
export function startup(config: Config, baseUri: string): () => void {
118118
return function () {
119-
const { env, ipc, customRootUri, customBitcoinNetwork, signerMode, lightningSignerFileSystemPath } = config;
119+
const {
120+
env,
121+
ipc,
122+
customRootUri,
123+
customBitcoinNetwork,
124+
signerMode,
125+
lightningSignerFileSystemPath,
126+
enclavedExpressUrl,
127+
enclavedExpressSSLCert,
128+
} = config;
120129
/* eslint-disable no-console */
121130
console.log('BitGo-Express running');
122131
console.log(`Environment: ${env}`);
@@ -137,6 +146,12 @@ export function startup(config: Config, baseUri: string): () => void {
137146
if (lightningSignerFileSystemPath) {
138147
console.log(`Lightning signer file system path: ${lightningSignerFileSystemPath}`);
139148
}
149+
if (enclavedExpressUrl) {
150+
console.log(`Enclaved Express URL: ${enclavedExpressUrl}`);
151+
if (enclavedExpressSSLCert) {
152+
console.log('Enclaved Express SSL certificate configured');
153+
}
154+
}
140155
/* eslint-enable no-console */
141156
};
142157
}
@@ -271,6 +286,8 @@ function checkPreconditions(config: Config) {
271286
export function setupRoutes(app: express.Application, config: Config): void {
272287
if (config.signerMode) {
273288
clientRoutes.setupSigningRoutes(app, config);
289+
} else if (config.enclavedExpressUrl && config.enclavedExpressSSLCert) {
290+
clientRoutes.setupEnclavedSigningRoutes(app, config);
274291
} else {
275292
if (config.lightningSignerFileSystemPath) {
276293
clientRoutes.setupLightningSignerNodeRoutes(app, config);

0 commit comments

Comments
 (0)