Skip to content

Commit 8a53d89

Browse files
committed
chore(mbe, awm): remove fallback client mtls config
Ticket: WP-5523
1 parent 7763041 commit 8a53d89

File tree

6 files changed

+105
-31
lines changed

6 files changed

+105
-31
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Both modes use the same TLS configuration variables:
7676
- `AWM_SERVER_CA_CERT_PATH` - Path to the CA certificate to verify the AWM server (required when TLS_MODE=mtls)
7777
- `AWM_SERVER_CA_CERT` - The CA certificate as a string (alternative to `_PATH`)
7878
- `AWM_SERVER_CERT_ALLOW_SELF_SIGNED` - Allow self-signed certificates from the AWM (default: false)
79-
- **Fallback:** If client certs are not provided, `SERVER_TLS_KEY_PATH` and `SERVER_TLS_CERT_PATH` are used
79+
- **Required:** Client certificates must be explicitly provided for outbound mTLS connections
8080

8181
#### Outbound mTLS to KMS (AWM Mode only)
8282

@@ -87,7 +87,7 @@ Both modes use the same TLS configuration variables:
8787
- `KMS_SERVER_CA_CERT_PATH` - Path to the CA certificate to verify the KMS server (required when TLS_MODE=mtls)
8888
- `KMS_SERVER_CA_CERT` - The CA certificate as a string (alternative to `_PATH`)
8989
- `KMS_SERVER_CERT_ALLOW_SELF_SIGNED` - Allow self-signed certificates from the KMS (default: false)
90-
- **Fallback:** If client certs are not provided, `SERVER_TLS_KEY_PATH` and `SERVER_TLS_CERT_PATH` are used
90+
- **Required:** Client certificates must be explicitly provided for outbound mTLS connections
9191

9292
### Logging and Debug
9393

@@ -175,6 +175,8 @@ export MTLS_ALLOWED_CLIENT_FINGERPRINTS=ABC123...,DEF456...
175175
npm start
176176
```
177177

178+
**Note:** Client certificates for outbound connections must be separate from server certificates for security reasons.
179+
178180
#### Master Express (Production)
179181

180182
```bash
@@ -190,6 +192,8 @@ export CLIENT_CERT_ALLOW_SELF_SIGNED=false
190192
npm start
191193
```
192194

195+
**Note:** Client certificates for outbound connections must be separate from server certificates for security reasons.
196+
193197
## Container Deployment with Podman
194198

195199
First, build the container image:

src/__tests__/config.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ describe('Configuration', () => {
1111
const originalEnv = process.env;
1212
const mockTlsKey = '-----BEGIN PRIVATE KEY-----\nMOCK_KEY\n-----END PRIVATE KEY-----';
1313
const mockTlsCert = '-----BEGIN CERTIFICATE-----\nMOCK_CERT\n-----END CERTIFICATE-----';
14+
const mockClientTlsKey =
15+
'-----BEGIN PRIVATE KEY-----\nMOCK_CLIENT_KEY\n-----END PRIVATE KEY-----';
16+
const mockClientTlsCert =
17+
'-----BEGIN CERTIFICATE-----\nMOCK_CLIENT_CERT\n-----END CERTIFICATE-----';
1418

1519
beforeEach(() => {
1620
// Reset to original environment and clear all relevant variables
@@ -39,6 +43,16 @@ describe('Configuration', () => {
3943
delete process.env.BITGO_CUSTOM_BITCOIN_NETWORK;
4044
delete process.env.SERVER_TLS_KEY_PATH;
4145
delete process.env.SERVER_TLS_CERT_PATH;
46+
delete process.env.KMS_CLIENT_TLS_KEY;
47+
delete process.env.KMS_CLIENT_TLS_CERT;
48+
delete process.env.KMS_CLIENT_TLS_KEY_PATH;
49+
delete process.env.KMS_CLIENT_TLS_CERT_PATH;
50+
delete process.env.AWM_CLIENT_TLS_KEY;
51+
delete process.env.AWM_CLIENT_TLS_CERT;
52+
delete process.env.AWM_CLIENT_TLS_KEY_PATH;
53+
delete process.env.AWM_CLIENT_TLS_CERT_PATH;
54+
delete process.env.KMS_SERVER_CA_CERT_PATH;
55+
delete process.env.RECOVERY_MODE;
4256
});
4357

4458
after(() => {
@@ -67,6 +81,8 @@ describe('Configuration', () => {
6781
process.env.KMS_URL = 'http://localhost:3000';
6882
process.env.SERVER_TLS_KEY = mockTlsKey;
6983
process.env.SERVER_TLS_CERT = mockTlsCert;
84+
process.env.KMS_CLIENT_TLS_KEY = mockClientTlsKey;
85+
process.env.KMS_CLIENT_TLS_CERT = mockClientTlsCert;
7086
process.env.KMS_SERVER_CA_CERT_PATH = path.resolve(
7187
__dirname,
7288
'mocks/certs/test-ssl-cert.pem',
@@ -89,6 +105,8 @@ describe('Configuration', () => {
89105
process.env.KMS_URL = 'http://localhost:3000';
90106
process.env.SERVER_TLS_KEY = mockTlsKey;
91107
process.env.SERVER_TLS_CERT = mockTlsCert;
108+
process.env.KMS_CLIENT_TLS_KEY = mockClientTlsKey;
109+
process.env.KMS_CLIENT_TLS_CERT = mockClientTlsCert;
92110
process.env.KMS_SERVER_CA_CERT_PATH = path.resolve(
93111
__dirname,
94112
'mocks/certs/test-ssl-cert.pem',
@@ -107,6 +125,8 @@ describe('Configuration', () => {
107125
process.env.KMS_URL = 'http://localhost:3000';
108126
process.env.SERVER_TLS_KEY = mockTlsKey;
109127
process.env.SERVER_TLS_CERT = mockTlsCert;
128+
process.env.KMS_CLIENT_TLS_KEY = mockClientTlsKey;
129+
process.env.KMS_CLIENT_TLS_CERT = mockClientTlsCert;
110130
process.env.RECOVERY_MODE = 'true';
111131
process.env.KMS_SERVER_CA_CERT_PATH = path.resolve(
112132
__dirname,
@@ -120,6 +140,8 @@ describe('Configuration', () => {
120140
process.env.KMS_URL = 'http://localhost:3000';
121141
process.env.SERVER_TLS_KEY = mockTlsKey;
122142
process.env.SERVER_TLS_CERT = mockTlsCert;
143+
process.env.KMS_CLIENT_TLS_KEY = mockClientTlsKey;
144+
process.env.KMS_CLIENT_TLS_CERT = mockClientTlsCert;
123145
process.env.KMS_SERVER_CA_CERT_PATH = path.resolve(
124146
__dirname,
125147
'mocks/certs/test-ssl-cert.pem',
@@ -167,6 +189,8 @@ describe('Configuration', () => {
167189
process.env.KMS_URL = 'http://localhost:3000';
168190
process.env.SERVER_TLS_KEY = mockTlsKey;
169191
process.env.SERVER_TLS_CERT = mockTlsCert;
192+
process.env.KMS_CLIENT_TLS_KEY = mockClientTlsKey;
193+
process.env.KMS_CLIENT_TLS_CERT = mockClientTlsCert;
170194
process.env.MTLS_ALLOWED_CLIENT_FINGERPRINTS = 'ABC123,DEF456';
171195
process.env.KMS_SERVER_CA_CERT_PATH = path.resolve(
172196
__dirname,
@@ -226,6 +250,8 @@ describe('Configuration', () => {
226250
process.env.KMS_URL = 'http://localhost:3000';
227251
process.env.SERVER_TLS_KEY = mockTlsKey;
228252
process.env.SERVER_TLS_CERT = mockTlsCert;
253+
process.env.KMS_CLIENT_TLS_KEY = mockClientTlsKey;
254+
process.env.KMS_CLIENT_TLS_CERT = mockClientTlsCert;
229255
process.env.HTTP_LOGFILE = '/tmp/test-http-access.log';
230256
process.env.KMS_SERVER_CA_CERT_PATH = path.resolve(
231257
__dirname,
@@ -258,6 +284,8 @@ describe('Configuration', () => {
258284
);
259285
process.env.SERVER_TLS_CERT_PATH = path.resolve(__dirname, 'mocks/certs/test-ssl-cert.pem');
260286
process.env.SERVER_TLS_KEY_PATH = path.resolve(__dirname, 'mocks/certs/test-ssl-key.pem');
287+
process.env.AWM_CLIENT_TLS_KEY = mockClientTlsKey;
288+
process.env.AWM_CLIENT_TLS_CERT = mockClientTlsCert;
261289
});
262290

263291
it('should use default configuration when minimal environment variables are set', () => {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIID9TCCAt2gAwIBAgIUKCkJ6fcl2+2EsK0n9v7iqGu1qgIwDQYJKoZIhvcNAQEL
3+
BQAwgYkxCzAJBgNVBAYTAkNBMQswCQYDVQQIDAJPTjEQMA4GA1UEBwwHVG9yb250
4+
bzEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ8wDQYDVQQDDAZQ
5+
cmFuYXYxJzAlBgkqhkiG9w0BCQEWGHByYW5hdmphaW4xMTk3QGdtYWlsLmNvbTAe
6+
Fw0yNTA4MDEyMjE4MTVaFw0yNjA4MDEyMjE4MTVaMIGJMQswCQYDVQQGEwJDQTEL
7+
MAkGA1UECAwCT04xEDAOBgNVBAcMB1Rvcm9udG8xITAfBgNVBAoMGEludGVybmV0
8+
IFdpZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAwwGUHJhbmF2MScwJQYJKoZIhvcNAQkB
9+
FhhwcmFuYXZqYWluMTE5N0BnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
10+
DwAwggEKAoIBAQC+QfWH5GbQidrIawVbjZ7RL/uZtF7wbmacER2wYlOO7Ib+Je1h
11+
03P3BQlI5bTBE3KkxrwDqycxWk/MA9hj2VT1tL3+bE/yuYVaOgGN4fiibG9Cc8MG
12+
MrWsZKRvP5Hy/ZUobVfLAPXvpUKM+nf//MaO6x9F/9TEwIb9rqfoD+bynL1s2LhR
13+
wr2ppYZXoOmdS/yhEiXloX4fO//5ivC/1zpt6bYaqdA2WAkBHyM24LOm02lJvRV+
14+
oq5dFxH0c0YCAEe05QfVLXgb/S/JTpxfOlabAVomb9+9ESOpEWqCyOo3U3QaSh49
15+
FdCUGFnaZHXc4324E/La955dSdeziLlDKXrdAgMBAAGjUzBRMB0GA1UdDgQWBBSe
16+
jCcPNqJHmbsXhsdKaJj9BUIhfTAfBgNVHSMEGDAWgBSejCcPNqJHmbsXhsdKaJj9
17+
BUIhfTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQARJW7QnfwS
18+
afy2M9ShDC7mqVa54LOaT6Ics+QYRPvJIRazlkODGm/n49rYZatgUNN1ouK6m7xk
19+
HuycnsWFZKly+w0/ugoe9fK59KUJCFNtPlTrAmJM4/x2yzSky/XlqEt0n8L8U8N1
20+
dbWcIC8EWNcUVKCKiS8ecoOm4G34I7YFOc5JwqEPJwfaQ76EHTKwEQe3MtM+wZaQ
21+
TrSm8WuYwlio53nyoyHHNGnJLKuN9DjOp9VdAtJcgCU8TutlKxAn1aDixrjcuzrk
22+
cqxn97OnE6eXsHurFY193lFs0HWpIAztXhjdtLjFJy68nVVmPcWAAWbcu4JhbBUX
23+
jZJ7DNuCDOoV
24+
-----END CERTIFICATE-----
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+QfWH5GbQidrI
3+
awVbjZ7RL/uZtF7wbmacER2wYlOO7Ib+Je1h03P3BQlI5bTBE3KkxrwDqycxWk/M
4+
A9hj2VT1tL3+bE/yuYVaOgGN4fiibG9Cc8MGMrWsZKRvP5Hy/ZUobVfLAPXvpUKM
5+
+nf//MaO6x9F/9TEwIb9rqfoD+bynL1s2LhRwr2ppYZXoOmdS/yhEiXloX4fO//5
6+
ivC/1zpt6bYaqdA2WAkBHyM24LOm02lJvRV+oq5dFxH0c0YCAEe05QfVLXgb/S/J
7+
TpxfOlabAVomb9+9ESOpEWqCyOo3U3QaSh49FdCUGFnaZHXc4324E/La955dSdez
8+
iLlDKXrdAgMBAAECggEASWNI8eekzxj1xuwdL3EDy14OV34vRt/W/alOgeyTnaRX
9+
9+2qUNtPNn//Ulqkq/sz9CJigKnC3vMep6vuCqnY70QOK3cdKZvtN937Hn8FOKXK
10+
DuB3YEssL7jMgssLIac2I1d2D2yp8QwWjSnKIvieoJ9KO2aQ7Gn1SCJYSxfjNj6b
11+
Z4BBnLgfOZebf2zDnXOnfee35v00zLw6EFyMhdwPNEwy505M32EQLu6qyPllSG4a
12+
srlqRsOMyo5iWEV7P8EBzquaWDB/B9PZWkG9JTokaXPFQJnX6Kn5ha5wcuoKBdVy
13+
R0mgPgtfhpvN2Ott4YQdIuo2PTfpc/Y1cTqRTuKWowKBgQDz9F8CmauFHmzrCp6n
14+
cZcW+Z2kUbjI25qat53G4QHAVIcWhMyQaAi+9dbVAuH9r3f1BWb8TcCJ+ut5fONL
15+
WR4oJpgeG6UVMaF15HqSj2FDic1JzY2jWtbKKiytRXlPCNGeCftQalZzsJtTI0Bl
16+
TqFj32flI+ZsfJR3v+9a6Nr14wKBgQDHptlyggV9TCXtSCfLAbaUJeqOVymTymrr
17+
qMcnYp99jHy7tmZIdmULxkeyF54uAX1/xc+nvSGFIO09rH3nEnZovDnvbFPpiFZb
18+
bNMxmGahW4//boTFSFRxxecknDBcUin0b8YjQER6i4tHtj3qUUjvW/J1XlWzZo1z
19+
cPF4oI6oPwKBgQDw9jaGXf0iHrxcqP+uyq7/XY1NSf8oPmmGWsl4MLXHIHbSUlew
20+
Z2IEJNWPTyqjphbpqO1hVvdQEs1WEXp86Ui1RfHJA2ta9MvTo9tCOmdLC6j/Ng6q
21+
BMbVpzS77Tx2SXKrFJbshixgV1gElXQ83J7jBD8eAQjPrXoEkku80vW8GwKBgGmC
22+
SWP0RoZi2aA+A5mK/DvqlbxHX9eUn1COz0CHJBYrSjfBOuiMePXyAS2iwZs6emIt
23+
3YGdt7stHXL8V0ToQt8yqcNXkjjWLhz+s9V/3qzjQIQSmePQR6Agn/h++iev3DAr
24+
aaBzdDz2xdJOAwZzkoG8K7PO+KdoSNR7GYFQCFPtAoGAFlvGvoX6WvQ47AwmVLgk
25+
gBfe1nruqVyz7kubWsy/V2iAkzMcWUUrcvpZgqAy9pRJlWs1wM91SjtFbZ+/UPwQ
26+
HGCGuclXo89b5uCTYVA0B2PxivY9F+RcQtTJZvTGBGIAC5m1+EqR9pVWY9527WD6
27+
7/MjOwPWTPT7j0jwBkXTo1w=
28+
-----END PRIVATE KEY-----
Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
11
-----BEGIN CERTIFICATE-----
2-
MIIDCTCCAfGgAwIBAgIUYN0EUBLwq7uoLwDuTx7gDW0HS2UwDQYJKoZIhvcNAQEL
3-
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDUxNDIxMTUzMVoXDTI2MDUx
4-
NDIxMTUzMVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
5-
AAOCAQ8AMIIBCgKCAQEAmxdCF7xCJcE6yyG+wrdhHMwRiQxbhDLW/hiKQcO/nn7z
6-
QMM9LAV04+WG5LCmm0ygocbfXXhfWn5D6SSSESKTb8dbSj6AJbLSmYjA5vDSzh9R
7-
rO9GzNTDCDne+epo+rN4BOjGh7K83naLei/bEfmklMp7x+TyoBC8Ps/3Eq4HOJfd
8-
UzgV2L3oC/4dCbAnkgK2zanL8KEaH6aM0HytIaqMFYLBs2t8s7HHHcSEadHfjlJu
9-
GwTmTS0nVhJBWYJvF6Pv/SwLFuSo93TJybaMMUSF3oJK35NEYXg6EtibJLUC9RvX
10-
FVLytRA5z+x7FBnGBdi4ctMseecokV4u15ePCB3MXwIDAQABo1MwUTAdBgNVHQ4E
11-
FgQUxHrQZFFBfTfuXeOOoXmHZQ8E6rswHwYDVR0jBBgwFoAUxHrQZFFBfTfuXeOO
12-
oXmHZQ8E6rswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAj0hy
13-
bwWh2B26cR0ADhuDC0MtGPBH0BrHypJEZ96nUPTY4oxRrjZusgdq60ooqsNyIW6k
14-
cZHkajC/O0V6hnV4yMhLE8ZwA+31iyQakonpT5N1OON4Ddv9Bfvx8xOn75x/+RP+
15-
GlAa31XxivryIi/5y7MEI0PwU34T/6bbMWdBaFRQtbuIXJ/90AZ0fBwIV0vJWjaO
16-
1DriZAJe7hl63ZUw6CsfutpoyKkanF5GQB2CpolR3t1oeHwuDbZ550p1g2XFB6UI
17-
9W+zlggQFeAnthzMoi3erO4sQ3j2b15QLZbk1HXHZcn3+89QcvdUcpG0u51bZdFW
18-
SJ+bnT3TZ9H+szoa1w==
2+
MOCK_CERT_CONTENT
193
-----END CERTIFICATE-----

src/initConfig.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ function advancedWalletManagerEnvConfig(): Partial<AdvancedWalletManagerConfig>
105105
kmsServerCaCertPath: readEnvVar('KMS_SERVER_CA_CERT_PATH'),
106106
kmsClientTlsKeyPath: readEnvVar('KMS_CLIENT_TLS_KEY_PATH'),
107107
kmsClientTlsCertPath: readEnvVar('KMS_CLIENT_TLS_CERT_PATH'),
108+
kmsClientTlsKey: readEnvVar('KMS_CLIENT_TLS_KEY'),
109+
kmsClientTlsCert: readEnvVar('KMS_CLIENT_TLS_CERT'),
108110
kmsServerCertAllowSelfSigned: readEnvVar('KMS_SERVER_CERT_ALLOW_SELF_SIGNED') === 'true',
109111
// mTLS server settings
110112
serverTlsKeyPath: readEnvVar('SERVER_TLS_KEY_PATH'),
@@ -227,12 +229,13 @@ function configureAdvancedWalletManagaerMode(): AdvancedWalletManagerConfig {
227229
}
228230
}
229231

230-
// Fallback to server certs if client certs are not provided
231-
if (!config.kmsClientTlsKey) {
232-
config.kmsClientTlsKey = config.serverTlsKey;
233-
}
234-
if (!config.kmsClientTlsCert) {
235-
config.kmsClientTlsCert = config.serverTlsCert;
232+
// Validate that client certificates are provided for outbound mTLS connections
233+
if (config.tlsMode === TlsMode.MTLS) {
234+
if (!config.kmsClientTlsKey || !config.kmsClientTlsCert) {
235+
throw new Error(
236+
'KMS_CLIENT_TLS_KEY_PATH and KMS_CLIENT_TLS_CERT_PATH (or KMS_CLIENT_TLS_KEY and KMS_CLIENT_TLS_CERT) are required for outbound mTLS connections to KMS. Client certificates cannot reuse server certificates for security reasons.',
237+
);
238+
}
236239
}
237240

238241
// Validate that certificates are properly loaded when TLS is enabled
@@ -310,6 +313,8 @@ function masterExpressEnvConfig(): Partial<MasterExpressConfig> {
310313
awmServerCaCertPath: awmServerCaCertPath,
311314
awmClientTlsKeyPath: readEnvVar('AWM_CLIENT_TLS_KEY_PATH'),
312315
awmClientTlsCertPath: readEnvVar('AWM_CLIENT_TLS_CERT_PATH'),
316+
awmClientTlsKey: readEnvVar('AWM_CLIENT_TLS_KEY'),
317+
awmClientTlsCert: readEnvVar('AWM_CLIENT_TLS_CERT'),
313318
awmServerCertAllowSelfSigned,
314319
customBitcoinNetwork: readEnvVar('BITGO_CUSTOM_BITCOIN_NETWORK'),
315320
// mTLS server settings
@@ -468,12 +473,13 @@ export function configureMasterExpressMode(): MasterExpressConfig {
468473

469474
logger.info('==========================');
470475

471-
// Fallback to server certs if client certs are not provided
472-
if (!config.awmClientTlsKey) {
473-
config.awmClientTlsKey = config.serverTlsKey;
474-
}
475-
if (!config.awmClientTlsCert) {
476-
config.awmClientTlsCert = config.serverTlsCert;
476+
// Validate that client certificates are provided for outbound mTLS connections
477+
if (config.tlsMode === TlsMode.MTLS) {
478+
if (!config.awmClientTlsKey || !config.awmClientTlsCert) {
479+
throw new Error(
480+
'AWM_CLIENT_TLS_KEY_PATH and AWM_CLIENT_TLS_CERT_PATH (or AWM_CLIENT_TLS_KEY and AWM_CLIENT_TLS_CERT) are required for outbound mTLS connections to Advanced Wallet Manager. Client certificates cannot reuse server certificates for security reasons.',
481+
);
482+
}
477483
}
478484

479485
// Validate Master Express configuration

0 commit comments

Comments
 (0)