From 9742332cf767d7c587465e2e21853d2740e7b82a Mon Sep 17 00:00:00 2001 From: Pranav Jain Date: Tue, 22 Jul 2025 15:15:01 -0400 Subject: [PATCH 1/5] test(mbe): add more config tests for master express Ticket: WP-5339 --- src/__tests__/config.test.ts | 235 +++++++++++++++++- .../mocks/certs/enclaved-express-cert.pem | 19 ++ src/__tests__/mocks/certs/test-ssl-cert.pem | 19 ++ src/__tests__/mocks/certs/test-ssl-key.pem | 28 +++ src/enclavedApp.ts | 25 +- src/initConfig.ts | 10 +- src/masterExpressApp.ts | 24 +- src/shared/appUtils.ts | 63 +++-- src/shared/types/index.ts | 39 ++- ...s-ba298b51-18b9-4753-83c1-4c9b746bf912.xml | 2 + 10 files changed, 377 insertions(+), 87 deletions(-) create mode 100644 src/__tests__/mocks/certs/enclaved-express-cert.pem create mode 100644 src/__tests__/mocks/certs/test-ssl-cert.pem create mode 100644 src/__tests__/mocks/certs/test-ssl-key.pem create mode 100644 test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index a090fdf..2f4a82c 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -1,15 +1,43 @@ import 'should'; -import { initConfig, isEnclavedConfig, TlsMode } from '../initConfig'; +import { initConfig, isEnclavedConfig, isMasterExpressConfig, TlsMode } from '../initConfig'; +import path from 'path'; describe('Configuration', () => { const originalEnv = process.env; const mockTlsKey = '-----BEGIN PRIVATE KEY-----\nMOCK_KEY\n-----END PRIVATE KEY-----'; const mockTlsCert = '-----BEGIN CERTIFICATE-----\nMOCK_CERT\n-----END CERTIFICATE-----'; + const mockSecuredExpressCert = + '-----BEGIN CERTIFICATE-----\nENCLAVED_EXPRESS_CERT\n-----END CERTIFICATE-----'; beforeEach(() => { + // Reset to original environment and clear all relevant variables process.env = { ...originalEnv }; - // Clear TLS-related environment variables + delete process.env.APP_MODE; + delete process.env.BITGO_APP_MODE; + delete process.env.KMS_URL; + delete process.env.ENCLAVED_EXPRESS_URL; + delete process.env.ENCLAVED_EXPRESS_CERT; delete process.env.TLS_MODE; + delete process.env.TLS_KEY; + delete process.env.TLS_CERT; + delete process.env.MTLS_REJECT_UNAUTHORIZED; + delete process.env.MTLS_ALLOWED_CLIENT_FINGERPRINTS; + delete process.env.ALLOW_SELF_SIGNED; + delete process.env.ENCLAVED_EXPRESS_PORT; + delete process.env.MASTER_EXPRESS_PORT; + delete process.env.BIND; + delete process.env.IPC; + delete process.env.DEBUG_NAMESPACE; + delete process.env.LOGFILE; + delete process.env.KEEP_ALIVE_TIMEOUT; + delete process.env.HEADERS_TIMEOUT; + delete process.env.BITGO_ENV; + delete process.env.BITGO_CUSTOM_ROOT_URI; + delete process.env.BITGO_DISABLE_ENV_CHECK; + delete process.env.BITGO_AUTH_VERSION; + delete process.env.BITGO_CUSTOM_BITCOIN_NETWORK; + delete process.env.TLS_KEY_PATH; + delete process.env.TLS_CERT_PATH; }); after(() => { @@ -32,13 +60,12 @@ describe('Configuration', () => { describe('Enclaved Mode', () => { beforeEach(() => { process.env.APP_MODE = 'enclaved'; + }); + + it('should use default configuration when minimal environment variables are set', () => { process.env.KMS_URL = 'http://localhost:3000'; - // Set default TLS certificates process.env.TLS_KEY = mockTlsKey; process.env.TLS_CERT = mockTlsCert; - }); - - it('should use default configuration when no environment variables are set', () => { const cfg = initConfig(); isEnclavedConfig(cfg).should.be.true(); if (isEnclavedConfig(cfg)) { @@ -54,6 +81,9 @@ describe('Configuration', () => { it('should read port from environment variable', () => { process.env.ENCLAVED_EXPRESS_PORT = '4000'; + process.env.KMS_URL = 'http://localhost:3000'; + process.env.TLS_KEY = mockTlsKey; + process.env.TLS_CERT = mockTlsCert; const cfg = initConfig(); isEnclavedConfig(cfg).should.be.true(); if (isEnclavedConfig(cfg)) { @@ -65,6 +95,10 @@ describe('Configuration', () => { }); it('should read TLS mode from environment variables', () => { + process.env.KMS_URL = 'http://localhost:3000'; + process.env.TLS_KEY = mockTlsKey; + process.env.TLS_CERT = mockTlsCert; + // Test with TLS disabled process.env.TLS_MODE = 'disabled'; let cfg = initConfig(); @@ -104,19 +138,204 @@ describe('Configuration', () => { }); it('should read mTLS settings from environment variables', () => { - process.env.MTLS_REQUEST_CERT = 'true'; + process.env.KMS_URL = 'http://localhost:3000'; + process.env.TLS_KEY = mockTlsKey; + process.env.TLS_CERT = mockTlsCert; process.env.MTLS_REJECT_UNAUTHORIZED = 'true'; process.env.MTLS_ALLOWED_CLIENT_FINGERPRINTS = 'ABC123,DEF456'; const cfg = initConfig(); isEnclavedConfig(cfg).should.be.true(); if (isEnclavedConfig(cfg)) { - cfg.mtlsRequestCert!.should.be.true(); cfg.mtlsAllowedClientFingerprints!.should.deepEqual(['ABC123', 'DEF456']); cfg.kmsUrl.should.equal('http://localhost:3000'); cfg.tlsKey!.should.equal(mockTlsKey); cfg.tlsCert!.should.equal(mockTlsCert); } }); + + it('should throw error when KMS_URL is not set', () => { + delete process.env.KMS_URL; + (() => initConfig()).should.throw( + 'KMS_URL environment variable is required and cannot be empty', + ); + }); + + it('should throw error when KMS_URL is empty', () => { + process.env.KMS_URL = ''; + (() => initConfig()).should.throw( + 'KMS_URL environment variable is required and cannot be empty', + ); + }); + + it('should succeed when TLS certificates are not set for disabled TLS mode', () => { + process.env.KMS_URL = 'http://localhost:3000'; + process.env.TLS_MODE = 'disabled'; + delete process.env.TLS_KEY; + delete process.env.TLS_CERT; + const cfg = initConfig(); + isEnclavedConfig(cfg).should.be.true(); + if (isEnclavedConfig(cfg)) { + cfg.tlsMode.should.equal(TlsMode.DISABLED); + cfg.kmsUrl.should.equal('http://localhost:3000'); + } + }); + + it('should throw error when TLS certificates are not set for MTLS mode', () => { + process.env.KMS_URL = 'http://localhost:3000'; + process.env.TLS_MODE = 'mtls'; + delete process.env.TLS_KEY; + delete process.env.TLS_CERT; + (() => initConfig()).should.throw(); + }); + }); + + describe('Master Express Mode', () => { + beforeEach(() => { + process.env.APP_MODE = 'master-express'; + process.env.ENCLAVED_EXPRESS_URL = 'http://localhost:3080'; + process.env.ENCLAVED_EXPRESS_CERT = path.resolve( + __dirname, + 'mocks/certs/enclaved-express-cert.pem', + ); + process.env.TLS_CERT_PATH = path.resolve(__dirname, 'mocks/certs/test-ssl-cert.pem'); + process.env.TLS_KEY_PATH = path.resolve(__dirname, 'mocks/certs/test-ssl-key.pem'); + }); + + it('should use default configuration when minimal environment variables are set', () => { + const cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.port.should.equal(3081); + cfg.bind.should.equal('localhost'); + cfg.tlsMode.should.equal(TlsMode.MTLS); + cfg.timeout.should.equal(305 * 1000); + cfg.enclavedExpressUrl.should.equal('https://localhost:3080'); + cfg.env.should.equal('test'); + } + }); + + it('should read port from environment variable', () => { + process.env.MASTER_EXPRESS_PORT = '4001'; + const cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.port.should.equal(4001); + cfg.enclavedExpressUrl.should.equal('https://localhost:3080'); + } + }); + + it('should read BitGo environment settings', () => { + process.env.BITGO_ENV = 'prod'; + process.env.BITGO_CUSTOM_ROOT_URI = 'https://custom.bitgo.com'; + process.env.BITGO_DISABLE_ENV_CHECK = 'false'; + process.env.BITGO_AUTH_VERSION = '3'; + process.env.BITGO_CUSTOM_BITCOIN_NETWORK = 'testnet'; + + const cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.env.should.equal('prod'); + cfg.customRootUri!.should.equal('https://custom.bitgo.com'); + cfg.disableEnvCheck!.should.be.false(); + cfg.authVersion!.should.equal(3); + cfg.customBitcoinNetwork!.should.equal('testnet'); + } + }); + + it('should handle TLS mode disabled configuration', () => { + // Test with TLS disabled + process.env.TLS_MODE = 'disabled'; + delete process.env.ENCLAVED_EXPRESS_CERT; + delete process.env.TLS_KEY_PATH; + delete process.env.TLS_CERT_PATH; + delete process.env.TLS_KEY; + delete process.env.TLS_CERT; + + const cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.tlsMode.should.equal(TlsMode.DISABLED); + cfg.enclavedExpressUrl.should.equal('http://localhost:3080'); + } + }); + + it('should throw error when ENCLAVED_EXPRESS_URL is not set', () => { + delete process.env.ENCLAVED_EXPRESS_URL; + (() => initConfig()).should.throw( + 'ENCLAVED_EXPRESS_URL environment variable is required and cannot be empty', + ); + }); + + it('should throw error when ENCLAVED_EXPRESS_URL is empty', () => { + process.env.ENCLAVED_EXPRESS_URL = ''; + (() => initConfig()).should.throw( + 'ENCLAVED_EXPRESS_URL environment variable is required and cannot be empty', + ); + }); + + it('should throw error when ENCLAVED_EXPRESS_CERT is not set for MTLS mode', () => { + process.env.TLS_MODE = 'mtls'; + delete process.env.ENCLAVED_EXPRESS_CERT; + (() => initConfig()).should.throw( + 'ENCLAVED_EXPRESS_CERT environment variable is required for MTLS mode.', + ); + }); + + it('should succeed when ENCLAVED_EXPRESS_CERT is not set for disabled TLS mode', () => { + process.env.ENCLAVED_EXPRESS_URL = 'http://localhost:3080'; + process.env.TLS_MODE = 'disabled'; + delete process.env.ENCLAVED_EXPRESS_CERT; + const cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.tlsMode.should.equal(TlsMode.DISABLED); + cfg.enclavedExpressUrl.should.equal('http://localhost:3080'); + cfg.enclavedExpressCert!.should.equal(''); + } + }); + + it('should throw error when ENCLAVED_EXPRESS_CERT is not set for default MTLS mode', () => { + delete process.env.ENCLAVED_EXPRESS_CERT; + (() => initConfig()).should.throw( + 'ENCLAVED_EXPRESS_CERT environment variable is required for MTLS mode.', + ); + }); + + it('should handle URL protocol conversion correctly', () => { + // Test with URL that already has protocol + process.env.ENCLAVED_EXPRESS_URL = 'https://enclaved.example.com:3080'; + let cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.enclavedExpressUrl.should.equal('https://enclaved.example.com:3080'); + } + + // Test with URL without protocol (should add https for MTLS) + process.env.ENCLAVED_EXPRESS_URL = 'enclaved.example.com:3080'; + cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.enclavedExpressUrl.should.equal('https://enclaved.example.com:3080'); + } + + // Test with URL without protocol and disabled TLS (should add http) + process.env.ENCLAVED_EXPRESS_URL = 'enclaved.example.com:3080'; + process.env.TLS_MODE = 'disabled'; + cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.enclavedExpressUrl.should.equal('http://enclaved.example.com:3080'); + } + }); + + it('should handle custom BitGo root URI protocol conversion', () => { + process.env.BITGO_CUSTOM_ROOT_URI = 'bitgo.example.com'; + const cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.customRootUri!.should.equal('https://bitgo.example.com'); + } + }); }); }); diff --git a/src/__tests__/mocks/certs/enclaved-express-cert.pem b/src/__tests__/mocks/certs/enclaved-express-cert.pem new file mode 100644 index 0000000..6076da4 --- /dev/null +++ b/src/__tests__/mocks/certs/enclaved-express-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUbE+vqSu9IgPoLJncJqX5aiXh2GkwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDUzMDIwMDgxNVoXDTI2MDUz +MDIwMDgxNVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAsK1g8ts/QRdEHVnmiZSijvtKl08yf13JWY0yksJW0O6x +mrt2uotvONxMNKhGtS+hPjcJ2OC7fCyift8oaCDs7PfIXjVNcN2zRKPci8ihNWvQ +XrYGLTvL9EVHpH7CdlJU43BTaeFusH+k/qv2pW5WQnz13ULdq7yvnDFvJAeahm9X +ptvr9RX9f8Aki0Y82Zi04PCiaHdqBPPl1OfHi+brf4xl7pQUq7Pub94/IDywe+QK +lGFPQ0exSVm5X/7hWv/AxqEFa/Bqb6Uw0qatVqhrgLEHlLUYVXs9NDNXm+865+aT +kvW2dnBpTVRZjnXO+N+BwSj+PfI28RqMXsmIhraN4QIDAQABo1MwUTAdBgNVHQ4E +FgQUnsZxpWiuxqDq/1kV12rMos4NN/cwHwYDVR0jBBgwFoAUnsZxpWiuxqDq/1kV +12rMos4NN/cwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAsAX4 +CCEsIVrKQKJKluEDqOFiuKg0SSe4xVqlSW9vy9z3UYLfOpw14EtB6Lzbtgw7z47w +AnZZS99Zzn3tbYd06/X+b3jThF5TU1gqBcYDCC9HCd9xpmQEC7Ss1Xa88ubjuh+U +E/7xN5xRt85S07VihJWscfY7JCUAELBo3gDCZLfgHjw8xMfPRceE36rkc5B2p60b +WEmmOBWjrSboMOfocasBTUVUMDvGgmxEGEmKgTYshr5lWKcIteisbZi7+OZlkflp +PUZNu5DUyQyjftr2EShndaceZrjgXt6ezoyQBVgPRA+N+NAJn+uBr3B3nZZb/mft +n3XsbtsAAoU49kEVOg== +-----END CERTIFICATE----- diff --git a/src/__tests__/mocks/certs/test-ssl-cert.pem b/src/__tests__/mocks/certs/test-ssl-cert.pem new file mode 100644 index 0000000..773b5a0 --- /dev/null +++ b/src/__tests__/mocks/certs/test-ssl-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUYN0EUBLwq7uoLwDuTx7gDW0HS2UwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDUxNDIxMTUzMVoXDTI2MDUx +NDIxMTUzMVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAmxdCF7xCJcE6yyG+wrdhHMwRiQxbhDLW/hiKQcO/nn7z +QMM9LAV04+WG5LCmm0ygocbfXXhfWn5D6SSSESKTb8dbSj6AJbLSmYjA5vDSzh9R +rO9GzNTDCDne+epo+rN4BOjGh7K83naLei/bEfmklMp7x+TyoBC8Ps/3Eq4HOJfd +UzgV2L3oC/4dCbAnkgK2zanL8KEaH6aM0HytIaqMFYLBs2t8s7HHHcSEadHfjlJu +GwTmTS0nVhJBWYJvF6Pv/SwLFuSo93TJybaMMUSF3oJK35NEYXg6EtibJLUC9RvX +FVLytRA5z+x7FBnGBdi4ctMseecokV4u15ePCB3MXwIDAQABo1MwUTAdBgNVHQ4E +FgQUxHrQZFFBfTfuXeOOoXmHZQ8E6rswHwYDVR0jBBgwFoAUxHrQZFFBfTfuXeOO +oXmHZQ8E6rswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAj0hy +bwWh2B26cR0ADhuDC0MtGPBH0BrHypJEZ96nUPTY4oxRrjZusgdq60ooqsNyIW6k +cZHkajC/O0V6hnV4yMhLE8ZwA+31iyQakonpT5N1OON4Ddv9Bfvx8xOn75x/+RP+ +GlAa31XxivryIi/5y7MEI0PwU34T/6bbMWdBaFRQtbuIXJ/90AZ0fBwIV0vJWjaO +1DriZAJe7hl63ZUw6CsfutpoyKkanF5GQB2CpolR3t1oeHwuDbZ550p1g2XFB6UI +9W+zlggQFeAnthzMoi3erO4sQ3j2b15QLZbk1HXHZcn3+89QcvdUcpG0u51bZdFW +SJ+bnT3TZ9H+szoa1w== +-----END CERTIFICATE----- diff --git a/src/__tests__/mocks/certs/test-ssl-key.pem b/src/__tests__/mocks/certs/test-ssl-key.pem new file mode 100644 index 0000000..cf4f9ef --- /dev/null +++ b/src/__tests__/mocks/certs/test-ssl-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCbF0IXvEIlwTrL +Ib7Ct2EczBGJDFuEMtb+GIpBw7+efvNAwz0sBXTj5YbksKabTKChxt9deF9afkPp +JJIRIpNvx1tKPoAlstKZiMDm8NLOH1Gs70bM1MMIOd756mj6s3gE6MaHsrzedot6 +L9sR+aSUynvH5PKgELw+z/cSrgc4l91TOBXYvegL/h0JsCeSArbNqcvwoRofpozQ +fK0hqowVgsGza3yzsccdxIRp0d+OUm4bBOZNLSdWEkFZgm8Xo+/9LAsW5Kj3dMnJ +towxRIXegkrfk0RheDoS2JsktQL1G9cVUvK1EDnP7HsUGcYF2Lhy0yx55yiRXi7X +l48IHcxfAgMBAAECggEAAft4dHXgi+ZTX7iiXTobe1MUakxbzcMZ7QzX6jfxTA+o +APeTNuvURFFxDvKUaT8VJ9wzNgOi3F+UHffCB4a0nGTPmDxXm6O/KLKPHKSOso8Y +ln2cdGPHy7l0TdIe3g113EI0FL9GcLrSf5D7Bi4gWhKDJdlETKLKH9dn+2IkD3zE +VM+7pwqYV6XZu2GuZ1om1JE+Hx2D5YLIuRCON0RKpzCLikmM7VErA7sjy7LsCSh9 +ty5n1s9GoNtF+YuOD9WeMWGDonMyJdYWTsmFYoT+LF7W+GHoEwvYm9595QuNnxVx +KQ4P5oKm/EfcSiBhCC8BdCIGch9tQPT7c/syVhHG4QKBgQDTdUVW7rJNnLtHgWF2 +ubjh9b3ZfxPuTEu6ueKON5XXvSgfsMBNgCxwkemefGJ6xIjDu+swud+2H33Tqj23 +GMMTZ1JEzNYINO1m/laSAK+DcL81q4sLLlJTbBhYeE6FBeEO1hAmU2IiYrgU6zbO +eyo4ysXtFJdnHSR9PHjZpt/cMQKBgQC7wmxw2UNPlmwTzl6l7z5DqYxizIfezb9l +pIYrmcD92asxZKPi1soz8PcOn30gGmjtZn/7FkXFHSRsNknUmqJOEbZrvNCcKndz +O+RbKGs8FAKlyog8k3CTToAng4PutsYrAuK/kx84P9FPCgTxdhejRMkfkSebCJQH +fmXRnlRdjwKBgQCm2Drz0rcBIg9q5hz+zp+gOoOnnusc9TozhQPLbvReGzQTfSTe +gamO0LJiiIYzk+rNdfKmqaJoUwS3A/ZaB8G0B6wT+QNPymMfBsNLxBq4PTfBoy68 +jboLdJjpBVP/BZqEWEa51sTxmK7iYo0F8oxn7yaoX7zucUIfRp2cLl0noQKBgB+K +RG8cgAshiJw3IX0cWEhDdfquwvAxfcJURdmTJXE/HFvavREA5cyd4NKLBhjbdt7S +RhNmpWe8Qn8PC430P+l/XjZw7FYfaBtqZyzM+F6KOfuhrwsF9XY5TJvWotX5zAYz +oOVvkGIBjmaJl1T8cnIRvvtXheCsKzmrCO2SfDePAoGAM1ToKwXSeZEm2Kyf/PV9 +74lvBKYP5LP+pSmrcTq9jUbPQy3KmlhBi+kyhVK+2Awmh0J9tzu83C8lWR25L4mc +/Uwjhv2KwmvJKyZ4/5t/oMZ+BsZERSHj39juLNW+UL82M2heM5tv5/MI779SAmzl +VJMN4N1x+L7408dEGu0j2ds= +-----END PRIVATE KEY----- diff --git a/src/enclavedApp.ts b/src/enclavedApp.ts index 17e8306..840cedf 100644 --- a/src/enclavedApp.ts +++ b/src/enclavedApp.ts @@ -22,19 +22,15 @@ import logger from './logger'; * Create a startup function which will be run upon server initialization */ export function startup(config: EnclavedConfig, baseUri: string): () => void { - return function () { - logger.info('BitGo Enclaved Express running'); + return () => { + logger.info('Enclaved Express server starting...'); logger.info(`Base URI: ${baseUri}`); - logger.info(`TLS Mode: ${config.tlsMode}`); - logger.info(`mTLS Enabled: ${config.tlsMode === TlsMode.MTLS}`); - logger.info(`Request Client Cert: ${config.mtlsRequestCert}`); - logger.info(`Allow Self-Signed: ${config.allowSelfSigned}`); + logger.info(`mTLS Mode: ${config.tlsMode}`); + logger.info(`Allow Self-Signed Certificates: ${config.allowSelfSigned}`); + logger.info(`Port: ${config.port}`); + logger.info(`Bind: ${config.bind}`); logger.info(`KMS URL: ${config.kmsUrl}`); - if (config.mtlsAllowedClientFingerprints?.length) { - logger.info( - `Allowed Client Fingerprints: ${config.mtlsAllowedClientFingerprints.length} configured`, - ); - } + logger.info('Enclaved Express server started successfully'); }; } @@ -48,7 +44,7 @@ async function createHttpsServer( app: express.Application, config: EnclavedConfig, ): Promise { - const { tlsKey, tlsCert, tlsMode, mtlsRequestCert } = config; + const { tlsKey, tlsCert, tlsMode } = config; if (!tlsKey || !tlsCert) { throw new Error('TLS key and certificate must be provided for HTTPS server'); @@ -58,9 +54,8 @@ async function createHttpsServer( secureOptions: SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, key: tlsKey, cert: tlsCert, - // Only request cert if mTLS is enabled AND we want to request certs - // This prevents TLS handshake failures when no cert is provided - requestCert: tlsMode === TlsMode.MTLS && mtlsRequestCert, + // Always request cert if mTLS is enabled + requestCert: tlsMode === TlsMode.MTLS, rejectUnauthorized: false, // Handle authorization in middleware }; diff --git a/src/initConfig.ts b/src/initConfig.ts index cc4f5c3..73395cb 100644 --- a/src/initConfig.ts +++ b/src/initConfig.ts @@ -50,9 +50,9 @@ const defaultEnclavedConfig: EnclavedConfig = { bind: 'localhost', timeout: 305 * 1000, logFile: '', + debugNamespace: [], kmsUrl: '', // Will be overridden by environment variable tlsMode: TlsMode.MTLS, - mtlsRequestCert: true, allowSelfSigned: false, }; @@ -101,7 +101,6 @@ function enclavedEnvConfig(): Partial { tlsKey: readEnvVar('TLS_KEY'), tlsCert: readEnvVar('TLS_CERT'), tlsMode: determineTlsMode(), - mtlsRequestCert: readEnvVar('MTLS_REQUEST_CERT')?.toLowerCase() !== 'false', mtlsAllowedClientFingerprints: readEnvVar('MTLS_ALLOWED_CLIENT_FINGERPRINTS')?.split(','), allowSelfSigned: readEnvVar('ALLOW_SELF_SIGNED') === 'true', }; @@ -132,7 +131,6 @@ function mergeEnclavedConfigs(...configs: Partial[]): EnclavedCo tlsKey: get('tlsKey'), tlsCert: get('tlsCert'), tlsMode: get('tlsMode'), - mtlsRequestCert: get('mtlsRequestCert'), mtlsAllowedClientFingerprints: get('mtlsAllowedClientFingerprints'), allowSelfSigned: get('allowSelfSigned'), }; @@ -186,13 +184,13 @@ const defaultMasterExpressConfig: MasterExpressConfig = { bind: 'localhost', timeout: 305 * 1000, logFile: '', + debugNamespace: [], env: 'test', disableEnvCheck: true, authVersion: 2, enclavedExpressUrl: '', // Will be overridden by environment variable enclavedExpressCert: '', // Will be overridden by environment variable tlsMode: TlsMode.MTLS, - mtlsRequestCert: true, allowSelfSigned: false, }; @@ -219,9 +217,7 @@ function masterExpressEnvConfig(): Partial { } // Debug mTLS environment variables - const mtlsRequestCertRaw = readEnvVar('MTLS_REQUEST_CERT'); const allowSelfSignedRaw = readEnvVar('ALLOW_SELF_SIGNED'); - const mtlsRequestCert = mtlsRequestCertRaw?.toLowerCase() !== 'false'; const allowSelfSigned = allowSelfSignedRaw === 'true'; return { @@ -248,7 +244,6 @@ function masterExpressEnvConfig(): Partial { tlsKey: readEnvVar('TLS_KEY'), tlsCert: readEnvVar('TLS_CERT'), tlsMode, - mtlsRequestCert, mtlsAllowedClientFingerprints: readEnvVar('MTLS_ALLOWED_CLIENT_FINGERPRINTS')?.split(','), allowSelfSigned, }; @@ -287,7 +282,6 @@ function mergeMasterExpressConfigs( tlsKey: get('tlsKey'), tlsCert: get('tlsCert'), tlsMode: get('tlsMode'), - mtlsRequestCert: get('mtlsRequestCert'), mtlsAllowedClientFingerprints: get('mtlsAllowedClientFingerprints'), allowSelfSigned: get('allowSelfSigned'), }; diff --git a/src/masterExpressApp.ts b/src/masterExpressApp.ts index 25fd9f0..12b6eae 100644 --- a/src/masterExpressApp.ts +++ b/src/masterExpressApp.ts @@ -21,19 +21,14 @@ import { setupRoutes } from './routes/master'; * Create a startup function which will be run upon server initialization */ export function startup(config: MasterExpressConfig, baseUri: string): () => void { - return function () { - logger.info('BitGo Master Express running'); + return () => { + logger.info('Master Express server starting...'); logger.info(`Base URI: ${baseUri}`); - logger.info(`Environment: ${config.env}`); logger.info(`TLS Mode: ${config.tlsMode}`); - logger.info(`mTLS Enabled: ${config.tlsMode === TlsMode.MTLS}`); - logger.info(`Request Client Cert: ${config.mtlsRequestCert}`); - logger.info(`Allow Self-Signed: ${config.allowSelfSigned}`); - if (config.mtlsAllowedClientFingerprints?.length) { - logger.info( - `Allowed Client Fingerprints: ${config.mtlsAllowedClientFingerprints.length} configured`, - ); - } + logger.info(`Port: ${config.port}`); + logger.info(`Bind: ${config.bind}`); + logger.info(`Enclaved Express URL: ${config.enclavedExpressUrl}`); + logger.info('Master Express server started successfully'); }; } @@ -47,7 +42,7 @@ async function createHttpsServer( app: express.Application, config: MasterExpressConfig, ): Promise { - const { tlsKey, tlsCert, tlsMode, mtlsRequestCert } = config; + const { tlsKey, tlsCert, tlsMode } = config; if (!tlsKey || !tlsCert) { throw new Error('TLS key and certificate must be provided for HTTPS server'); @@ -57,9 +52,8 @@ async function createHttpsServer( secureOptions: SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, key: tlsKey, cert: tlsCert, - // Only request cert if mTLS is enabled AND we want to request certs - // This prevents TLS handshake failures when no cert is provided - requestCert: tlsMode === TlsMode.MTLS && mtlsRequestCert, + // Always request cert if mTLS is enabled + requestCert: tlsMode === TlsMode.MTLS, rejectUnauthorized: false, // Handle authorization in middleware }; diff --git a/src/shared/appUtils.ts b/src/shared/appUtils.ts index 1af51e6..000569d 100644 --- a/src/shared/appUtils.ts +++ b/src/shared/appUtils.ts @@ -9,7 +9,7 @@ import bodyParser from 'body-parser'; import pjson from '../../package.json'; import logger from '../logger'; -import { Config, TlsMode } from '../shared/types'; +import { Config, TlsMode, MasterExpressConfig } from '../shared/types'; /** * Set up the logging middleware provided by morgan @@ -121,7 +121,6 @@ export async function prepareIpc(ipcSocketFilePath: string): Promise { */ export function createMtlsMiddleware(config: { tlsMode: TlsMode; - mtlsRequestCert: boolean; allowSelfSigned?: boolean; mtlsAllowedClientFingerprints?: string[]; }): express.RequestHandler { @@ -132,8 +131,8 @@ export function createMtlsMiddleware(config: { const hasValidClientCert = clientCert && Object.keys(clientCert).length > 0 && clientCert.subject; - // If client cert is required but not provided - if (config.mtlsRequestCert && !hasValidClientCert) { + // If mTLS is enabled, client certificate is always required + if (config.tlsMode === TlsMode.MTLS && !hasValidClientCert) { return res.status(403).json({ error: 'mTLS Authentication Failed', message: 'Client certificate is required for this endpoint', @@ -176,29 +175,53 @@ export function createMtlsMiddleware(config: { /** * Validate that TLS certificates are properly loaded when TLS is enabled */ -export function validateTlsCertificates(config: { - tlsMode: TlsMode; - tlsKey?: string; - tlsCert?: string; -}): void { - if (config.tlsMode !== TlsMode.DISABLED) { - if (!config.tlsKey || !config.tlsCert) { - throw new Error('TLS is enabled but certificates are not properly loaded'); +export function validateTlsCertificates(config: Config): void { + if (config.tlsMode === TlsMode.DISABLED) { + return; + } + + if (!config.tlsKey || !config.tlsCert) { + throw new Error('TLS key and certificate must be provided when TLS is enabled'); + } + + // Validate certificate format + try { + // Basic PEM format validation + if ( + !config.tlsKey.includes('-----BEGIN PRIVATE KEY-----') && + !config.tlsKey.includes('-----BEGIN RSA PRIVATE KEY-----') + ) { + throw new Error('Invalid TLS private key format'); } + if (!config.tlsCert.includes('-----BEGIN CERTIFICATE-----')) { + throw new Error('Invalid TLS certificate format'); + } + } catch (error) { + throw new Error( + `TLS certificate validation failed: ${ + error instanceof Error ? error.message : String(error) + }`, + ); } } /** * Validate Master Express configuration */ -export function validateMasterExpressConfig(config: { - enclavedExpressUrl: string; - enclavedExpressCert: string; -}): void { - if (!config.enclavedExpressUrl) { - throw new Error('ENCLAVED_EXPRESS_URL is required for Master Express mode'); +export function validateMasterExpressConfig(config: MasterExpressConfig): void { + // Validate that we have the required enclaved express certificate for mTLS + if (config.tlsMode === TlsMode.MTLS && !config.enclavedExpressCert) { + throw new Error('Enclaved Express certificate is required for mTLS mode'); } - if (!config.enclavedExpressCert) { - throw new Error('ENCLAVED_EXPRESS_CERT is required for Master Express mode'); + + // Validate client certificate if mTLS is enabled + if (config.tlsMode === TlsMode.MTLS) { + const hasValidClientCert = + config.enclavedExpressCert && + config.enclavedExpressCert.includes('-----BEGIN CERTIFICATE-----'); + + if (!hasValidClientCert) { + throw new Error('Valid client certificate is required for mTLS mode'); + } } } diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts index 57164c8..2a88d02 100644 --- a/src/shared/types/index.ts +++ b/src/shared/types/index.ts @@ -10,55 +10,52 @@ export enum AppMode { export type EnvironmentName = 'prod' | 'test' | 'staging' | 'dev' | 'local'; -// Common base configuration shared by both modes -interface BaseConfig { - appMode: AppMode; +// Enclaved mode specific configuration +export interface EnclavedConfig { + appMode: AppMode.ENCLAVED; port: number; bind: string; ipc?: string; - debugNamespace?: string[]; - logFile?: string; + debugNamespace: string[]; + logFile: string; timeout: number; keepAliveTimeout?: number; headersTimeout?: number; -} - -// Enclaved mode specific configuration -export interface EnclavedConfig extends BaseConfig { - appMode: AppMode.ENCLAVED; - // KMS settings kmsUrl: string; - // mTLS settings keyPath?: string; crtPath?: string; tlsKey?: string; tlsCert?: string; tlsMode: TlsMode; - mtlsRequestCert: boolean; mtlsAllowedClientFingerprints?: string[]; - allowSelfSigned?: boolean; + allowSelfSigned: boolean; } // Master Express mode specific configuration -export interface MasterExpressConfig extends BaseConfig { +export interface MasterExpressConfig { appMode: AppMode.MASTER_EXPRESS; - // BitGo API settings + port: number; + bind: string; + ipc?: string; + debugNamespace: string[]; + logFile: string; + timeout: number; + keepAliveTimeout?: number; + headersTimeout?: number; env: EnvironmentName; customRootUri?: string; - disableEnvCheck?: boolean; - authVersion?: number; + disableEnvCheck: boolean; + authVersion: number; enclavedExpressUrl: string; enclavedExpressCert: string; customBitcoinNetwork?: string; - // mTLS settings keyPath?: string; crtPath?: string; tlsKey?: string; tlsCert?: string; tlsMode: TlsMode; - mtlsRequestCert: boolean; mtlsAllowedClientFingerprints?: string[]; - allowSelfSigned?: boolean; + allowSelfSigned: boolean; } // Union type for the configuration diff --git a/test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml b/test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml new file mode 100644 index 0000000..ed93b95 --- /dev/null +++ b/test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml @@ -0,0 +1,2 @@ + + From 18848f85af4fab8675023e65c1194d5c6506a0a7 Mon Sep 17 00:00:00 2001 From: Pranav Jain Date: Thu, 24 Jul 2025 12:40:10 -0400 Subject: [PATCH 2/5] chore(mbe): remove mtlsRequestCert from config Ticket: WP-5364 --- src/__tests__/api/enclaved/postIndependentKey.test.ts | 2 +- src/__tests__/api/enclaved/postMpcV2Key.test.ts | 2 +- .../api/enclaved/recoveryMultisigTransaction.test.ts | 2 +- src/__tests__/api/enclaved/recoveryMusigEth.test.ts | 2 +- .../api/enclaved/signMpcRecoveryTransaction.test.ts | 2 +- src/__tests__/api/enclaved/signMpcTransaction.test.ts | 2 +- src/__tests__/api/enclaved/signMultisigTransaction.test.ts | 2 +- src/__tests__/api/master/accelerate.test.ts | 2 +- src/__tests__/api/master/consolidate.test.ts | 2 +- src/__tests__/api/master/consolidateUnspents.test.ts | 2 +- src/__tests__/api/master/generateWallet.test.ts | 7 +++---- src/__tests__/api/master/musigRecovery.test.ts | 2 +- .../api/master/recoveryConsolidationsWallet.test.ts | 2 +- src/__tests__/api/master/recoveryWallet.test.ts | 2 +- src/__tests__/api/master/sendMany.test.ts | 3 +-- src/__tests__/api/master/signAndSendTxRequest.test.ts | 2 +- src/__tests__/config.test.ts | 4 ---- src/__tests__/routes.test.ts | 4 +++- 18 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/__tests__/api/enclaved/postIndependentKey.test.ts b/src/__tests__/api/enclaved/postIndependentKey.test.ts index 3b94087..f54ff54 100644 --- a/src/__tests__/api/enclaved/postIndependentKey.test.ts +++ b/src/__tests__/api/enclaved/postIndependentKey.test.ts @@ -36,8 +36,8 @@ describe('postIndependentKey', () => { logFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/postMpcV2Key.test.ts b/src/__tests__/api/enclaved/postMpcV2Key.test.ts index 8a8af68..c027c05 100644 --- a/src/__tests__/api/enclaved/postMpcV2Key.test.ts +++ b/src/__tests__/api/enclaved/postMpcV2Key.test.ts @@ -38,8 +38,8 @@ describe('postMpcV2Key', () => { logFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts b/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts index 5c63b1e..fe1b583 100644 --- a/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts +++ b/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts @@ -21,8 +21,8 @@ describe('UTXO recovery', () => { timeout: 60000, logFile: '', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], kmsUrl: 'kms.example.com', }; diff --git a/src/__tests__/api/enclaved/recoveryMusigEth.test.ts b/src/__tests__/api/enclaved/recoveryMusigEth.test.ts index d21bea3..07b477b 100644 --- a/src/__tests__/api/enclaved/recoveryMusigEth.test.ts +++ b/src/__tests__/api/enclaved/recoveryMusigEth.test.ts @@ -39,8 +39,8 @@ describe('recoveryMultisigTransaction', () => { logFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts b/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts index e7a79ae..a8d7978 100644 --- a/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts @@ -16,8 +16,8 @@ describe('EdDSA Recovery Signing', () => { timeout: 60000, logFile: '', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], kmsUrl: 'kms.example.com', }; diff --git a/src/__tests__/api/enclaved/signMpcTransaction.test.ts b/src/__tests__/api/enclaved/signMpcTransaction.test.ts index 1d57b2d..9e7f6a8 100644 --- a/src/__tests__/api/enclaved/signMpcTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMpcTransaction.test.ts @@ -43,8 +43,8 @@ describe('signMpcTransaction', () => { logFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/signMultisigTransaction.test.ts b/src/__tests__/api/enclaved/signMultisigTransaction.test.ts index 241775c..45ef4d1 100644 --- a/src/__tests__/api/enclaved/signMultisigTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMultisigTransaction.test.ts @@ -36,8 +36,8 @@ describe('signMultisigTransaction', () => { logFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/master/accelerate.test.ts b/src/__tests__/api/master/accelerate.test.ts index a2ddebc..67eca69 100644 --- a/src/__tests__/api/master/accelerate.test.ts +++ b/src/__tests__/api/master/accelerate.test.ts @@ -30,8 +30,8 @@ describe('POST /api/:coin/wallet/:walletId/accelerate', () => { enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'test-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/consolidate.test.ts b/src/__tests__/api/master/consolidate.test.ts index 2e983b7..d8c15dd 100644 --- a/src/__tests__/api/master/consolidate.test.ts +++ b/src/__tests__/api/master/consolidate.test.ts @@ -33,8 +33,8 @@ describe('POST /api/:coin/wallet/:walletId/consolidateunspents', () => { enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'test-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/consolidateUnspents.test.ts b/src/__tests__/api/master/consolidateUnspents.test.ts index 310437a..aa92eb8 100644 --- a/src/__tests__/api/master/consolidateUnspents.test.ts +++ b/src/__tests__/api/master/consolidateUnspents.test.ts @@ -30,8 +30,8 @@ describe('POST /api/:coin/wallet/:walletId/consolidateunspents', () => { enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'test-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/generateWallet.test.ts b/src/__tests__/api/master/generateWallet.test.ts index 5137627..2dab6af 100644 --- a/src/__tests__/api/master/generateWallet.test.ts +++ b/src/__tests__/api/master/generateWallet.test.ts @@ -32,8 +32,8 @@ describe('POST /api/:coin/wallet/generate', () => { enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); @@ -728,7 +728,7 @@ describe('POST /api/:coin/wallet/generate', () => { to: 0, payload: { encryptedMessage: 'test-p2p-message-backup-to-user-2', - signature: 'test-signature-backup-to-user-2', + signature: 'test-signature-user-to-backup-2', }, commitment: 'test-commitment-backup-2', }, @@ -874,7 +874,7 @@ describe('POST /api/:coin/wallet/generate', () => { to: 0, payload: { encryptedMessage: 'test-p2p-message-backup-to-user-3', - signature: 'test-signature-backup-to-user-3', + signature: 'test-signature-user-to-backup-3', }, commitment: 'test-commitment-backup-3', }, @@ -1127,7 +1127,6 @@ describe('POST /api/:coin/wallet/generate', () => { disableEnvCheck: true, authVersion: 2, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, }; diff --git a/src/__tests__/api/master/musigRecovery.test.ts b/src/__tests__/api/master/musigRecovery.test.ts index 86123ee..d8db680 100644 --- a/src/__tests__/api/master/musigRecovery.test.ts +++ b/src/__tests__/api/master/musigRecovery.test.ts @@ -30,8 +30,8 @@ describe('POST /api/:coin/wallet/recovery', () => { enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts b/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts index 0d37a71..d716d79 100644 --- a/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts +++ b/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts @@ -29,8 +29,8 @@ describe('POST /api/:coin/wallet/recoveryconsolidations', () => { enclavedExpressUrl, enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); agent = request.agent(app); diff --git a/src/__tests__/api/master/recoveryWallet.test.ts b/src/__tests__/api/master/recoveryWallet.test.ts index 6d60416..0d027ef 100644 --- a/src/__tests__/api/master/recoveryWallet.test.ts +++ b/src/__tests__/api/master/recoveryWallet.test.ts @@ -29,8 +29,8 @@ describe('Recovery Tests', () => { enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; beforeEach(() => { diff --git a/src/__tests__/api/master/sendMany.test.ts b/src/__tests__/api/master/sendMany.test.ts index d66a559..7a384ce 100644 --- a/src/__tests__/api/master/sendMany.test.ts +++ b/src/__tests__/api/master/sendMany.test.ts @@ -33,8 +33,8 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => { enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); @@ -585,7 +585,6 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => { disableEnvCheck: true, authVersion: 2, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, }; diff --git a/src/__tests__/api/master/signAndSendTxRequest.test.ts b/src/__tests__/api/master/signAndSendTxRequest.test.ts index 0351850..834714b 100644 --- a/src/__tests__/api/master/signAndSendTxRequest.test.ts +++ b/src/__tests__/api/master/signAndSendTxRequest.test.ts @@ -51,8 +51,8 @@ describe('POST /api/:coin/wallet/:walletId/txrequest/:txRequestId/signAndSend', enclavedExpressUrl: enclavedExpressUrl, enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, allowSelfSigned: true, + debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index 2f4a82c..4d1cbdb 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -6,8 +6,6 @@ describe('Configuration', () => { const originalEnv = process.env; const mockTlsKey = '-----BEGIN PRIVATE KEY-----\nMOCK_KEY\n-----END PRIVATE KEY-----'; const mockTlsCert = '-----BEGIN CERTIFICATE-----\nMOCK_CERT\n-----END CERTIFICATE-----'; - const mockSecuredExpressCert = - '-----BEGIN CERTIFICATE-----\nENCLAVED_EXPRESS_CERT\n-----END CERTIFICATE-----'; beforeEach(() => { // Reset to original environment and clear all relevant variables @@ -20,7 +18,6 @@ describe('Configuration', () => { delete process.env.TLS_MODE; delete process.env.TLS_KEY; delete process.env.TLS_CERT; - delete process.env.MTLS_REJECT_UNAUTHORIZED; delete process.env.MTLS_ALLOWED_CLIENT_FINGERPRINTS; delete process.env.ALLOW_SELF_SIGNED; delete process.env.ENCLAVED_EXPRESS_PORT; @@ -141,7 +138,6 @@ describe('Configuration', () => { process.env.KMS_URL = 'http://localhost:3000'; process.env.TLS_KEY = mockTlsKey; process.env.TLS_CERT = mockTlsCert; - process.env.MTLS_REJECT_UNAUTHORIZED = 'true'; process.env.MTLS_ALLOWED_CLIENT_FINGERPRINTS = 'ABC123,DEF456'; const cfg = initConfig(); diff --git a/src/__tests__/routes.test.ts b/src/__tests__/routes.test.ts index 2df84f4..b652a63 100644 --- a/src/__tests__/routes.test.ts +++ b/src/__tests__/routes.test.ts @@ -12,8 +12,10 @@ describe('Routes', () => { app = express(); setupRoutes(app, { appMode: AppMode.ENCLAVED, + debugNamespace: [], + logFile: '', + allowSelfSigned: true, tlsMode: TlsMode.DISABLED, - mtlsRequestCert: false, kmsUrl: 'http://localhost:3000/kms', timeout: 5000, port: 3000, From 1567585d2b69ab7014a8ac6b3967711bde23df2a Mon Sep 17 00:00:00 2001 From: Pranav Jain Date: Thu, 24 Jul 2025 12:43:56 -0400 Subject: [PATCH 3/5] chore(mbe): remove DEBUG_NAMESPACE config Ticket: WP-5364 --- README.md | 2 +- src/__tests__/api/enclaved/postIndependentKey.test.ts | 1 - src/__tests__/api/enclaved/postMpcV2Key.test.ts | 1 - .../api/enclaved/recoveryMultisigTransaction.test.ts | 1 - src/__tests__/api/enclaved/recoveryMusigEth.test.ts | 1 - .../api/enclaved/signMpcRecoveryTransaction.test.ts | 2 -- src/__tests__/api/enclaved/signMpcTransaction.test.ts | 1 - src/__tests__/api/enclaved/signMultisigTransaction.test.ts | 1 - src/__tests__/api/master/accelerate.test.ts | 1 - src/__tests__/api/master/consolidate.test.ts | 1 - src/__tests__/api/master/consolidateUnspents.test.ts | 1 - src/__tests__/api/master/generateWallet.test.ts | 1 - src/__tests__/api/master/musigRecovery.test.ts | 1 - .../api/master/recoveryConsolidationsWallet.test.ts | 1 - src/__tests__/api/master/recoveryWallet.test.ts | 1 - src/__tests__/api/master/sendMany.test.ts | 1 - src/__tests__/api/master/signAndSendTxRequest.test.ts | 1 - src/__tests__/config.test.ts | 1 - src/__tests__/routes.test.ts | 1 - src/initConfig.ts | 6 ------ src/shared/types/index.ts | 2 -- 21 files changed, 1 insertion(+), 28 deletions(-) diff --git a/README.md b/README.md index dca8a9c..2845b71 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,6 @@ Both modes use the same TLS configuration variables: ### Logging and Debug - `LOGFILE` - Path to log file (optional) -- `DEBUG_NAMESPACE` - Debug namespaces to enable (e.g., 'enclaved:\*') ## Quick Start @@ -232,6 +231,7 @@ curl -k -X POST https://localhost:3081/ping/enclavedExpress ``` Notes: + - `host.containers.internal` is a special DNS name that resolves to the host machine from inside containers - The `:Z` option in volume mounts is specific to SELinux-enabled systems and ensures proper volume labeling - The logs directory will be created with appropriate permissions if it doesn't exist diff --git a/src/__tests__/api/enclaved/postIndependentKey.test.ts b/src/__tests__/api/enclaved/postIndependentKey.test.ts index f54ff54..a8bdb1d 100644 --- a/src/__tests__/api/enclaved/postIndependentKey.test.ts +++ b/src/__tests__/api/enclaved/postIndependentKey.test.ts @@ -37,7 +37,6 @@ describe('postIndependentKey', () => { kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/postMpcV2Key.test.ts b/src/__tests__/api/enclaved/postMpcV2Key.test.ts index c027c05..2910e9c 100644 --- a/src/__tests__/api/enclaved/postMpcV2Key.test.ts +++ b/src/__tests__/api/enclaved/postMpcV2Key.test.ts @@ -39,7 +39,6 @@ describe('postMpcV2Key', () => { kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts b/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts index fe1b583..44b191a 100644 --- a/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts +++ b/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts @@ -22,7 +22,6 @@ describe('UTXO recovery', () => { logFile: '', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], kmsUrl: 'kms.example.com', }; diff --git a/src/__tests__/api/enclaved/recoveryMusigEth.test.ts b/src/__tests__/api/enclaved/recoveryMusigEth.test.ts index 07b477b..33aa259 100644 --- a/src/__tests__/api/enclaved/recoveryMusigEth.test.ts +++ b/src/__tests__/api/enclaved/recoveryMusigEth.test.ts @@ -40,7 +40,6 @@ describe('recoveryMultisigTransaction', () => { kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts b/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts index a8d7978..b9ff8fb 100644 --- a/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts @@ -17,8 +17,6 @@ describe('EdDSA Recovery Signing', () => { logFile: '', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], - kmsUrl: 'kms.example.com', }; const commonKeychain = diff --git a/src/__tests__/api/enclaved/signMpcTransaction.test.ts b/src/__tests__/api/enclaved/signMpcTransaction.test.ts index 9e7f6a8..5acf4bc 100644 --- a/src/__tests__/api/enclaved/signMpcTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMpcTransaction.test.ts @@ -44,7 +44,6 @@ describe('signMpcTransaction', () => { kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/enclaved/signMultisigTransaction.test.ts b/src/__tests__/api/enclaved/signMultisigTransaction.test.ts index 45ef4d1..8e18ab4 100644 --- a/src/__tests__/api/enclaved/signMultisigTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMultisigTransaction.test.ts @@ -37,7 +37,6 @@ describe('signMultisigTransaction', () => { kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; configStub = sinon.stub(configModule, 'initConfig').returns(cfg); diff --git a/src/__tests__/api/master/accelerate.test.ts b/src/__tests__/api/master/accelerate.test.ts index 67eca69..02c114b 100644 --- a/src/__tests__/api/master/accelerate.test.ts +++ b/src/__tests__/api/master/accelerate.test.ts @@ -31,7 +31,6 @@ describe('POST /api/:coin/wallet/:walletId/accelerate', () => { enclavedExpressCert: 'test-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/consolidate.test.ts b/src/__tests__/api/master/consolidate.test.ts index d8c15dd..429bb36 100644 --- a/src/__tests__/api/master/consolidate.test.ts +++ b/src/__tests__/api/master/consolidate.test.ts @@ -34,7 +34,6 @@ describe('POST /api/:coin/wallet/:walletId/consolidateunspents', () => { enclavedExpressCert: 'test-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/consolidateUnspents.test.ts b/src/__tests__/api/master/consolidateUnspents.test.ts index aa92eb8..6e66f37 100644 --- a/src/__tests__/api/master/consolidateUnspents.test.ts +++ b/src/__tests__/api/master/consolidateUnspents.test.ts @@ -31,7 +31,6 @@ describe('POST /api/:coin/wallet/:walletId/consolidateunspents', () => { enclavedExpressCert: 'test-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/generateWallet.test.ts b/src/__tests__/api/master/generateWallet.test.ts index 2dab6af..f9f1055 100644 --- a/src/__tests__/api/master/generateWallet.test.ts +++ b/src/__tests__/api/master/generateWallet.test.ts @@ -33,7 +33,6 @@ describe('POST /api/:coin/wallet/generate', () => { enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/musigRecovery.test.ts b/src/__tests__/api/master/musigRecovery.test.ts index d8db680..827aea8 100644 --- a/src/__tests__/api/master/musigRecovery.test.ts +++ b/src/__tests__/api/master/musigRecovery.test.ts @@ -31,7 +31,6 @@ describe('POST /api/:coin/wallet/recovery', () => { enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts b/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts index d716d79..6c15217 100644 --- a/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts +++ b/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts @@ -30,7 +30,6 @@ describe('POST /api/:coin/wallet/recoveryconsolidations', () => { enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); agent = request.agent(app); diff --git a/src/__tests__/api/master/recoveryWallet.test.ts b/src/__tests__/api/master/recoveryWallet.test.ts index 0d027ef..0586dfb 100644 --- a/src/__tests__/api/master/recoveryWallet.test.ts +++ b/src/__tests__/api/master/recoveryWallet.test.ts @@ -30,7 +30,6 @@ describe('Recovery Tests', () => { enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; beforeEach(() => { diff --git a/src/__tests__/api/master/sendMany.test.ts b/src/__tests__/api/master/sendMany.test.ts index 7a384ce..6f731da 100644 --- a/src/__tests__/api/master/sendMany.test.ts +++ b/src/__tests__/api/master/sendMany.test.ts @@ -34,7 +34,6 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => { enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/api/master/signAndSendTxRequest.test.ts b/src/__tests__/api/master/signAndSendTxRequest.test.ts index 834714b..599b15e 100644 --- a/src/__tests__/api/master/signAndSendTxRequest.test.ts +++ b/src/__tests__/api/master/signAndSendTxRequest.test.ts @@ -52,7 +52,6 @@ describe('POST /api/:coin/wallet/:walletId/txrequest/:txRequestId/signAndSend', enclavedExpressCert: 'dummy-cert', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, - debugNamespace: [], }; const app = expressApp(config); diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index 4d1cbdb..fe2b2d0 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -24,7 +24,6 @@ describe('Configuration', () => { delete process.env.MASTER_EXPRESS_PORT; delete process.env.BIND; delete process.env.IPC; - delete process.env.DEBUG_NAMESPACE; delete process.env.LOGFILE; delete process.env.KEEP_ALIVE_TIMEOUT; delete process.env.HEADERS_TIMEOUT; diff --git a/src/__tests__/routes.test.ts b/src/__tests__/routes.test.ts index b652a63..47bd219 100644 --- a/src/__tests__/routes.test.ts +++ b/src/__tests__/routes.test.ts @@ -12,7 +12,6 @@ describe('Routes', () => { app = express(); setupRoutes(app, { appMode: AppMode.ENCLAVED, - debugNamespace: [], logFile: '', allowSelfSigned: true, tlsMode: TlsMode.DISABLED, diff --git a/src/initConfig.ts b/src/initConfig.ts index 73395cb..fe78665 100644 --- a/src/initConfig.ts +++ b/src/initConfig.ts @@ -50,7 +50,6 @@ const defaultEnclavedConfig: EnclavedConfig = { bind: 'localhost', timeout: 305 * 1000, logFile: '', - debugNamespace: [], kmsUrl: '', // Will be overridden by environment variable tlsMode: TlsMode.MTLS, allowSelfSigned: false, @@ -88,7 +87,6 @@ function enclavedEnvConfig(): Partial { port: Number(readEnvVar('ENCLAVED_EXPRESS_PORT')), bind: readEnvVar('BIND'), ipc: readEnvVar('IPC'), - debugNamespace: (readEnvVar('DEBUG_NAMESPACE') || '').split(',').filter(Boolean), logFile: readEnvVar('LOGFILE'), timeout: Number(readEnvVar('TIMEOUT')), keepAliveTimeout: Number(readEnvVar('KEEP_ALIVE_TIMEOUT')), @@ -120,7 +118,6 @@ function mergeEnclavedConfigs(...configs: Partial[]): EnclavedCo port: get('port'), bind: get('bind'), ipc: get('ipc'), - debugNamespace: get('debugNamespace'), logFile: get('logFile'), timeout: get('timeout'), keepAliveTimeout: get('keepAliveTimeout'), @@ -184,7 +181,6 @@ const defaultMasterExpressConfig: MasterExpressConfig = { bind: 'localhost', timeout: 305 * 1000, logFile: '', - debugNamespace: [], env: 'test', disableEnvCheck: true, authVersion: 2, @@ -225,7 +221,6 @@ function masterExpressEnvConfig(): Partial { port: Number(readEnvVar('MASTER_EXPRESS_PORT')), bind: readEnvVar('BIND'), ipc: readEnvVar('IPC'), - debugNamespace: (readEnvVar('DEBUG_NAMESPACE') || '').split(',').filter(Boolean), logFile: readEnvVar('LOGFILE'), timeout: Number(readEnvVar('TIMEOUT')), keepAliveTimeout: Number(readEnvVar('KEEP_ALIVE_TIMEOUT')), @@ -265,7 +260,6 @@ function mergeMasterExpressConfigs( port: get('port'), bind: get('bind'), ipc: get('ipc'), - debugNamespace: get('debugNamespace'), logFile: get('logFile'), timeout: get('timeout'), keepAliveTimeout: get('keepAliveTimeout'), diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts index 2a88d02..9ef0c79 100644 --- a/src/shared/types/index.ts +++ b/src/shared/types/index.ts @@ -16,7 +16,6 @@ export interface EnclavedConfig { port: number; bind: string; ipc?: string; - debugNamespace: string[]; logFile: string; timeout: number; keepAliveTimeout?: number; @@ -37,7 +36,6 @@ export interface MasterExpressConfig { port: number; bind: string; ipc?: string; - debugNamespace: string[]; logFile: string; timeout: number; keepAliveTimeout?: number; From 29dfdbba64f8648a5a2e2817d3d814da4dd59682 Mon Sep 17 00:00:00 2001 From: Pranav Jain Date: Thu, 24 Jul 2025 12:59:10 -0400 Subject: [PATCH 4/5] chore(mbe): rename logFile to httpLogger The logFile env var is only being used for HTTP logs. Update the name to reflect that. Ticket: WP-5364 --- README.md | 2 +- .../api/enclaved/postIndependentKey.test.ts | 2 +- .../api/enclaved/postMpcV2Key.test.ts | 2 +- .../recoveryMultisigTransaction.test.ts | 2 +- .../api/enclaved/recoveryMusigEth.test.ts | 2 +- .../signMpcRecoveryTransaction.test.ts | 3 +- .../api/enclaved/signMpcTransaction.test.ts | 2 +- .../enclaved/signMultisigTransaction.test.ts | 2 +- src/__tests__/api/master/accelerate.test.ts | 2 +- src/__tests__/api/master/consolidate.test.ts | 2 +- .../api/master/consolidateUnspents.test.ts | 2 +- .../api/master/generateWallet.test.ts | 8 ++--- .../api/master/musigRecovery.test.ts | 2 +- .../recoveryConsolidationsWallet.test.ts | 2 +- .../api/master/recoveryWallet.test.ts | 2 +- src/__tests__/api/master/sendMany.test.ts | 4 +-- .../api/master/signAndSendTxRequest.test.ts | 2 +- .../api/secured/postIndependentKey.test.ts | 0 src/__tests__/config.test.ts | 23 ++++++++++++- src/__tests__/routes.test.ts | 2 +- src/initConfig.ts | 12 +++---- src/shared/appUtils.ts | 4 +-- src/shared/types/index.ts | 34 ++++++++++--------- ...s-ba298b51-18b9-4753-83c1-4c9b746bf912.xml | 2 -- 24 files changed, 71 insertions(+), 49 deletions(-) create mode 100644 src/__tests__/api/secured/postIndependentKey.test.ts delete mode 100644 test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml diff --git a/README.md b/README.md index 2845b71..af941ef 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Both modes use the same TLS configuration variables: ### Logging and Debug -- `LOGFILE` - Path to log file (optional) +- `HTTP_LOGFILE` - Path to HTTP request log file (optional, used by Morgan for HTTP access logs) ## Quick Start diff --git a/src/__tests__/api/enclaved/postIndependentKey.test.ts b/src/__tests__/api/enclaved/postIndependentKey.test.ts index a8bdb1d..cb2a75d 100644 --- a/src/__tests__/api/enclaved/postIndependentKey.test.ts +++ b/src/__tests__/api/enclaved/postIndependentKey.test.ts @@ -33,7 +33,7 @@ describe('postIndependentKey', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, diff --git a/src/__tests__/api/enclaved/postMpcV2Key.test.ts b/src/__tests__/api/enclaved/postMpcV2Key.test.ts index 2910e9c..e8edb69 100644 --- a/src/__tests__/api/enclaved/postMpcV2Key.test.ts +++ b/src/__tests__/api/enclaved/postMpcV2Key.test.ts @@ -35,7 +35,7 @@ describe('postMpcV2Key', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, diff --git a/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts b/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts index 44b191a..601d0a0 100644 --- a/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts +++ b/src/__tests__/api/enclaved/recoveryMultisigTransaction.test.ts @@ -19,7 +19,7 @@ describe('UTXO recovery', () => { port: 0, bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, kmsUrl: 'kms.example.com', diff --git a/src/__tests__/api/enclaved/recoveryMusigEth.test.ts b/src/__tests__/api/enclaved/recoveryMusigEth.test.ts index 33aa259..b06e4a6 100644 --- a/src/__tests__/api/enclaved/recoveryMusigEth.test.ts +++ b/src/__tests__/api/enclaved/recoveryMusigEth.test.ts @@ -36,7 +36,7 @@ describe('recoveryMultisigTransaction', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, diff --git a/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts b/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts index b9ff8fb..41413a9 100644 --- a/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMpcRecoveryTransaction.test.ts @@ -10,11 +10,12 @@ import { AppMode, EnclavedConfig, TlsMode } from '../../../shared/types'; describe('EdDSA Recovery Signing', () => { let agent: supertest.SuperTest; const config: EnclavedConfig = { + kmsUrl: 'http://localhost:3000', appMode: AppMode.ENCLAVED, port: 0, bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', tlsMode: TlsMode.DISABLED, allowSelfSigned: true, }; diff --git a/src/__tests__/api/enclaved/signMpcTransaction.test.ts b/src/__tests__/api/enclaved/signMpcTransaction.test.ts index 5acf4bc..8327b29 100644 --- a/src/__tests__/api/enclaved/signMpcTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMpcTransaction.test.ts @@ -40,7 +40,7 @@ describe('signMpcTransaction', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, diff --git a/src/__tests__/api/enclaved/signMultisigTransaction.test.ts b/src/__tests__/api/enclaved/signMultisigTransaction.test.ts index 8e18ab4..df97430 100644 --- a/src/__tests__/api/enclaved/signMultisigTransaction.test.ts +++ b/src/__tests__/api/enclaved/signMultisigTransaction.test.ts @@ -33,7 +33,7 @@ describe('signMultisigTransaction', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', kmsUrl: kmsUrl, tlsMode: TlsMode.DISABLED, allowSelfSigned: true, diff --git a/src/__tests__/api/master/accelerate.test.ts b/src/__tests__/api/master/accelerate.test.ts index 02c114b..11c5fb2 100644 --- a/src/__tests__/api/master/accelerate.test.ts +++ b/src/__tests__/api/master/accelerate.test.ts @@ -23,7 +23,7 @@ describe('POST /api/:coin/wallet/:walletId/accelerate', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 30000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/consolidate.test.ts b/src/__tests__/api/master/consolidate.test.ts index 429bb36..6dea2b1 100644 --- a/src/__tests__/api/master/consolidate.test.ts +++ b/src/__tests__/api/master/consolidate.test.ts @@ -26,7 +26,7 @@ describe('POST /api/:coin/wallet/:walletId/consolidateunspents', () => { port: 0, bind: 'localhost', timeout: 30000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/consolidateUnspents.test.ts b/src/__tests__/api/master/consolidateUnspents.test.ts index 6e66f37..3facc47 100644 --- a/src/__tests__/api/master/consolidateUnspents.test.ts +++ b/src/__tests__/api/master/consolidateUnspents.test.ts @@ -23,7 +23,7 @@ describe('POST /api/:coin/wallet/:walletId/consolidateunspents', () => { port: 0, bind: 'localhost', timeout: 30000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/generateWallet.test.ts b/src/__tests__/api/master/generateWallet.test.ts index f9f1055..3b1efc1 100644 --- a/src/__tests__/api/master/generateWallet.test.ts +++ b/src/__tests__/api/master/generateWallet.test.ts @@ -25,7 +25,7 @@ describe('POST /api/:coin/wallet/generate', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, @@ -727,7 +727,7 @@ describe('POST /api/:coin/wallet/generate', () => { to: 0, payload: { encryptedMessage: 'test-p2p-message-backup-to-user-2', - signature: 'test-signature-user-to-backup-2', + signature: 'test-signature-backup-to-user-2', }, commitment: 'test-commitment-backup-2', }, @@ -873,7 +873,7 @@ describe('POST /api/:coin/wallet/generate', () => { to: 0, payload: { encryptedMessage: 'test-p2p-message-backup-to-user-3', - signature: 'test-signature-user-to-backup-3', + signature: 'test-signature-backup-to-user-3', }, commitment: 'test-commitment-backup-3', }, @@ -1121,7 +1121,7 @@ describe('POST /api/:coin/wallet/generate', () => { port: 0, bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/musigRecovery.test.ts b/src/__tests__/api/master/musigRecovery.test.ts index 827aea8..1b09c9f 100644 --- a/src/__tests__/api/master/musigRecovery.test.ts +++ b/src/__tests__/api/master/musigRecovery.test.ts @@ -23,7 +23,7 @@ describe('POST /api/:coin/wallet/recovery', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts b/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts index 6c15217..9ca4bff 100644 --- a/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts +++ b/src/__tests__/api/master/recoveryConsolidationsWallet.test.ts @@ -22,7 +22,7 @@ describe('POST /api/:coin/wallet/recoveryconsolidations', () => { port: 0, bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/recoveryWallet.test.ts b/src/__tests__/api/master/recoveryWallet.test.ts index 0586dfb..60c1477 100644 --- a/src/__tests__/api/master/recoveryWallet.test.ts +++ b/src/__tests__/api/master/recoveryWallet.test.ts @@ -22,7 +22,7 @@ describe('Recovery Tests', () => { port: 0, bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/sendMany.test.ts b/src/__tests__/api/master/sendMany.test.ts index 6f731da..d5a583a 100644 --- a/src/__tests__/api/master/sendMany.test.ts +++ b/src/__tests__/api/master/sendMany.test.ts @@ -26,7 +26,7 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => { port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, @@ -579,7 +579,7 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => { port: 0, bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/master/signAndSendTxRequest.test.ts b/src/__tests__/api/master/signAndSendTxRequest.test.ts index 599b15e..b635427 100644 --- a/src/__tests__/api/master/signAndSendTxRequest.test.ts +++ b/src/__tests__/api/master/signAndSendTxRequest.test.ts @@ -44,7 +44,7 @@ describe('POST /api/:coin/wallet/:walletId/txrequest/:txRequestId/signAndSend', port: 0, // Let OS assign a free port bind: 'localhost', timeout: 60000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, diff --git a/src/__tests__/api/secured/postIndependentKey.test.ts b/src/__tests__/api/secured/postIndependentKey.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index fe2b2d0..63ee0fb 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -24,7 +24,7 @@ describe('Configuration', () => { delete process.env.MASTER_EXPRESS_PORT; delete process.env.BIND; delete process.env.IPC; - delete process.env.LOGFILE; + delete process.env.HTTP_LOGFILE; delete process.env.KEEP_ALIVE_TIMEOUT; delete process.env.HEADERS_TIMEOUT; delete process.env.BITGO_ENV; @@ -183,6 +183,18 @@ describe('Configuration', () => { delete process.env.TLS_CERT; (() => initConfig()).should.throw(); }); + + it('should read HTTP_LOGFILE into httpLoggerFile in Enclaved mode', () => { + process.env.KMS_URL = 'http://localhost:3000'; + process.env.TLS_KEY = mockTlsKey; + process.env.TLS_CERT = mockTlsCert; + process.env.HTTP_LOGFILE = '/tmp/test-http-access.log'; + const cfg = initConfig(); + isEnclavedConfig(cfg).should.be.true(); + if (isEnclavedConfig(cfg)) { + cfg.httpLoggerFile?.should.equal('/tmp/test-http-access.log'); + } + }); }); describe('Master Express Mode', () => { @@ -332,5 +344,14 @@ describe('Configuration', () => { cfg.customRootUri!.should.equal('https://bitgo.example.com'); } }); + + it('should read HTTP_LOGFILE into httpLoggerFile in Master Express mode', () => { + process.env.HTTP_LOGFILE = '/tmp/test-http-access.log'; + const cfg = initConfig(); + isMasterExpressConfig(cfg).should.be.true(); + if (isMasterExpressConfig(cfg)) { + cfg.httpLoggerFile?.should.equal('/tmp/test-http-access.log'); + } + }); }); }); diff --git a/src/__tests__/routes.test.ts b/src/__tests__/routes.test.ts index 47bd219..41dd6e1 100644 --- a/src/__tests__/routes.test.ts +++ b/src/__tests__/routes.test.ts @@ -12,7 +12,7 @@ describe('Routes', () => { app = express(); setupRoutes(app, { appMode: AppMode.ENCLAVED, - logFile: '', + httpLoggerFile: '', allowSelfSigned: true, tlsMode: TlsMode.DISABLED, kmsUrl: 'http://localhost:3000/kms', diff --git a/src/initConfig.ts b/src/initConfig.ts index fe78665..1298766 100644 --- a/src/initConfig.ts +++ b/src/initConfig.ts @@ -49,7 +49,7 @@ const defaultEnclavedConfig: EnclavedConfig = { port: 3080, bind: 'localhost', timeout: 305 * 1000, - logFile: '', + httpLoggerFile: '', kmsUrl: '', // Will be overridden by environment variable tlsMode: TlsMode.MTLS, allowSelfSigned: false, @@ -87,7 +87,7 @@ function enclavedEnvConfig(): Partial { port: Number(readEnvVar('ENCLAVED_EXPRESS_PORT')), bind: readEnvVar('BIND'), ipc: readEnvVar('IPC'), - logFile: readEnvVar('LOGFILE'), + httpLoggerFile: readEnvVar('HTTP_LOGFILE'), timeout: Number(readEnvVar('TIMEOUT')), keepAliveTimeout: Number(readEnvVar('KEEP_ALIVE_TIMEOUT')), headersTimeout: Number(readEnvVar('HEADERS_TIMEOUT')), @@ -118,7 +118,7 @@ function mergeEnclavedConfigs(...configs: Partial[]): EnclavedCo port: get('port'), bind: get('bind'), ipc: get('ipc'), - logFile: get('logFile'), + httpLoggerFile: get('httpLoggerFile'), timeout: get('timeout'), keepAliveTimeout: get('keepAliveTimeout'), headersTimeout: get('headersTimeout'), @@ -180,7 +180,7 @@ const defaultMasterExpressConfig: MasterExpressConfig = { port: 3081, bind: 'localhost', timeout: 305 * 1000, - logFile: '', + httpLoggerFile: '', env: 'test', disableEnvCheck: true, authVersion: 2, @@ -221,7 +221,7 @@ function masterExpressEnvConfig(): Partial { port: Number(readEnvVar('MASTER_EXPRESS_PORT')), bind: readEnvVar('BIND'), ipc: readEnvVar('IPC'), - logFile: readEnvVar('LOGFILE'), + httpLoggerFile: readEnvVar('HTTP_LOGFILE'), timeout: Number(readEnvVar('TIMEOUT')), keepAliveTimeout: Number(readEnvVar('KEEP_ALIVE_TIMEOUT')), headersTimeout: Number(readEnvVar('HEADERS_TIMEOUT')), @@ -260,7 +260,7 @@ function mergeMasterExpressConfigs( port: get('port'), bind: get('bind'), ipc: get('ipc'), - logFile: get('logFile'), + httpLoggerFile: get('httpLoggerFile'), timeout: get('timeout'), keepAliveTimeout: get('keepAliveTimeout'), headersTimeout: get('headersTimeout'), diff --git a/src/shared/appUtils.ts b/src/shared/appUtils.ts index 000569d..a1e13db 100644 --- a/src/shared/appUtils.ts +++ b/src/shared/appUtils.ts @@ -17,9 +17,9 @@ import { Config, TlsMode, MasterExpressConfig } from '../shared/types'; export function setupLogging(app: express.Application, config: Config): void { // Set up morgan for logging, with optional logging into a file let middleware; - if (config.logFile) { + if (config.httpLoggerFile) { // create a write stream (in append mode) - const accessLogPath = path.resolve(config.logFile); + const accessLogPath = path.resolve(config.httpLoggerFile); const accessLogStream = fs.createWriteStream(accessLogPath, { flags: 'a' }); logger.info(`Log location: ${accessLogPath}`); // setup the logger diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts index 9ef0c79..a982a47 100644 --- a/src/shared/types/index.ts +++ b/src/shared/types/index.ts @@ -10,50 +10,52 @@ export enum AppMode { export type EnvironmentName = 'prod' | 'test' | 'staging' | 'dev' | 'local'; -// Enclaved mode specific configuration -export interface EnclavedConfig { - appMode: AppMode.ENCLAVED; +// Common base configuration shared by both modes +export interface BaseConfig { + appMode: AppMode; port: number; bind: string; ipc?: string; - logFile: string; timeout: number; keepAliveTimeout?: number; headersTimeout?: number; + httpLoggerFile?: string; +} + +// Enclaved mode specific configuration +export interface EnclavedConfig extends BaseConfig { + appMode: AppMode.ENCLAVED; + // KMS settings kmsUrl: string; + // mTLS settings keyPath?: string; crtPath?: string; tlsKey?: string; tlsCert?: string; tlsMode: TlsMode; mtlsAllowedClientFingerprints?: string[]; - allowSelfSigned: boolean; + allowSelfSigned?: boolean; } // Master Express mode specific configuration -export interface MasterExpressConfig { +export interface MasterExpressConfig extends BaseConfig { appMode: AppMode.MASTER_EXPRESS; - port: number; - bind: string; - ipc?: string; - logFile: string; - timeout: number; - keepAliveTimeout?: number; - headersTimeout?: number; + // BitGo API settings env: EnvironmentName; customRootUri?: string; - disableEnvCheck: boolean; - authVersion: number; + disableEnvCheck?: boolean; + authVersion?: number; enclavedExpressUrl: string; enclavedExpressCert: string; customBitcoinNetwork?: string; + // mTLS settings keyPath?: string; crtPath?: string; tlsKey?: string; tlsCert?: string; tlsMode: TlsMode; mtlsAllowedClientFingerprints?: string[]; - allowSelfSigned: boolean; + allowSelfSigned?: boolean; } // Union type for the configuration diff --git a/test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml b/test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml deleted file mode 100644 index ed93b95..0000000 --- a/test-results-ba298b51-18b9-4753-83c1-4c9b746bf912.xml +++ /dev/null @@ -1,2 +0,0 @@ - - From 54e5298216294aba9a274bd9a4746190a2090c93 Mon Sep 17 00:00:00 2001 From: Pranav Jain Date: Thu, 24 Jul 2025 14:08:29 -0400 Subject: [PATCH 5/5] chore(mbe): add default file for http access logs Ticket: WP-5339 --- src/__tests__/config.test.ts | 4 ++-- src/initConfig.ts | 6 +++--- src/shared/types/index.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index 63ee0fb..d058791 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -192,7 +192,7 @@ describe('Configuration', () => { const cfg = initConfig(); isEnclavedConfig(cfg).should.be.true(); if (isEnclavedConfig(cfg)) { - cfg.httpLoggerFile?.should.equal('/tmp/test-http-access.log'); + cfg.httpLoggerFile.should.equal('/tmp/test-http-access.log'); } }); }); @@ -350,7 +350,7 @@ describe('Configuration', () => { const cfg = initConfig(); isMasterExpressConfig(cfg).should.be.true(); if (isMasterExpressConfig(cfg)) { - cfg.httpLoggerFile?.should.equal('/tmp/test-http-access.log'); + cfg.httpLoggerFile.should.equal('/tmp/test-http-access.log'); } }); }); diff --git a/src/initConfig.ts b/src/initConfig.ts index 1298766..e042697 100644 --- a/src/initConfig.ts +++ b/src/initConfig.ts @@ -49,7 +49,7 @@ const defaultEnclavedConfig: EnclavedConfig = { port: 3080, bind: 'localhost', timeout: 305 * 1000, - httpLoggerFile: '', + httpLoggerFile: 'logs/http-access.log', kmsUrl: '', // Will be overridden by environment variable tlsMode: TlsMode.MTLS, allowSelfSigned: false, @@ -180,7 +180,7 @@ const defaultMasterExpressConfig: MasterExpressConfig = { port: 3081, bind: 'localhost', timeout: 305 * 1000, - httpLoggerFile: '', + httpLoggerFile: 'logs/http-access.log', env: 'test', disableEnvCheck: true, authVersion: 2, @@ -221,7 +221,7 @@ function masterExpressEnvConfig(): Partial { port: Number(readEnvVar('MASTER_EXPRESS_PORT')), bind: readEnvVar('BIND'), ipc: readEnvVar('IPC'), - httpLoggerFile: readEnvVar('HTTP_LOGFILE'), + httpLoggerFile: readEnvVar('HTTP_LOGFILE') || 'logs/http-access.log', timeout: Number(readEnvVar('TIMEOUT')), keepAliveTimeout: Number(readEnvVar('KEEP_ALIVE_TIMEOUT')), headersTimeout: Number(readEnvVar('HEADERS_TIMEOUT')), diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts index a982a47..05f7c65 100644 --- a/src/shared/types/index.ts +++ b/src/shared/types/index.ts @@ -19,7 +19,7 @@ export interface BaseConfig { timeout: number; keepAliveTimeout?: number; headersTimeout?: number; - httpLoggerFile?: string; + httpLoggerFile: string; } // Enclaved mode specific configuration