@bedrock/kms-http 23.1.0 → 23.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config.js +30 -1
- package/lib/http.js +48 -1
- package/package.json +2 -1
package/lib/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Copyright (c) 2019-
|
|
2
|
+
* Copyright (c) 2019-2026 Digital Bazaar, Inc.
|
|
3
3
|
*/
|
|
4
4
|
import {config} from '@bedrock/core';
|
|
5
5
|
import '@bedrock/app-identity';
|
|
@@ -35,3 +35,32 @@ cfg.kmsOperationOptions = {
|
|
|
35
35
|
// 1000 year max TTL by default
|
|
36
36
|
maxDelegationTtl: 1000 * 60 * 60 * 24 * 365 * 1000
|
|
37
37
|
};
|
|
38
|
+
|
|
39
|
+
/* Optional proxy feature: An application running bedrock-kms-http can use
|
|
40
|
+
these configuration options to redirect KMS operations to another
|
|
41
|
+
bedrock-kms-http application, called a "proxy target". The proxy target must
|
|
42
|
+
shares the same database and be configured with the same public address
|
|
43
|
+
(domain / origin) but it is expected to be run behind a firewall (with
|
|
44
|
+
restricted access) and inside of an isolated environment, such as a secure
|
|
45
|
+
enclave, to add an additional layer of security during the processing of
|
|
46
|
+
KMS operations.
|
|
47
|
+
|
|
48
|
+
The proxying application will not have access to secret key material or to
|
|
49
|
+
secrets that can decrypt/unseal/unwrap other secrets, only the proxy target
|
|
50
|
+
will have access to some or all of these (or be capable of using some or all
|
|
51
|
+
of these via authz credentials only it can access). Both applications will
|
|
52
|
+
have access to the same database and will be expected to run compatible
|
|
53
|
+
versions of software to ensure database record compatibility. The proxy
|
|
54
|
+
target MUST properly check authz on all incoming requests; authz is is NOT
|
|
55
|
+
checked by the proxy.
|
|
56
|
+
|
|
57
|
+
Proxy entries are defined by KMS module, i.e., at most one proxy target can
|
|
58
|
+
be configured per KMS module. When requests for a particular KMS module arrive,
|
|
59
|
+
they are forwarded in their entirety to the related proxy target. */
|
|
60
|
+
cfg.kmsModuleProxy = {
|
|
61
|
+
/*
|
|
62
|
+
<kms-module-name>: {
|
|
63
|
+
proxyTarget: <address (base URL) for kms proxy target>
|
|
64
|
+
}
|
|
65
|
+
*/
|
|
66
|
+
};
|
package/lib/http.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Copyright (c) 2019-
|
|
2
|
+
* Copyright (c) 2019-2026 Digital Bazaar, Inc.
|
|
3
3
|
*/
|
|
4
4
|
import * as bedrock from '@bedrock/core';
|
|
5
5
|
import * as brZCapStorage from '@bedrock/zcap-storage';
|
|
6
6
|
import * as helpers from './helpers.js';
|
|
7
7
|
import * as middleware from './middleware.js';
|
|
8
|
+
import {createProxyMiddleware, fixRequestBody} from 'http-proxy-middleware';
|
|
8
9
|
import {
|
|
9
10
|
getConfigsQuery,
|
|
10
11
|
postKeystoreBody,
|
|
@@ -49,6 +50,9 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
|
|
|
49
50
|
// associated with a request
|
|
50
51
|
const getKeystoreConfig = middleware.createGetKeystoreConfig({routes});
|
|
51
52
|
|
|
53
|
+
// create KMS module proxy middleware for use with KMS operations
|
|
54
|
+
const kmsModuleProxyMiddleware = _createKmsModuleProxyMiddleware();
|
|
55
|
+
|
|
52
56
|
/* Note: CORS is used on all endpoints. This is safe because authorization
|
|
53
57
|
uses HTTP signatures + capabilities, not cookies; CSRF is not possible. */
|
|
54
58
|
|
|
@@ -215,6 +219,7 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
|
|
|
215
219
|
routes.keys,
|
|
216
220
|
cors(),
|
|
217
221
|
getKeystoreConfig,
|
|
222
|
+
kmsModuleProxyMiddleware,
|
|
218
223
|
handleOperation);
|
|
219
224
|
|
|
220
225
|
// invoke KMS operation on an existing key
|
|
@@ -223,6 +228,7 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
|
|
|
223
228
|
routes.key,
|
|
224
229
|
cors(),
|
|
225
230
|
getKeystoreConfig,
|
|
231
|
+
kmsModuleProxyMiddleware,
|
|
226
232
|
handleOperation);
|
|
227
233
|
|
|
228
234
|
// TODO: consider whether this should be exposed w/o authorization
|
|
@@ -233,6 +239,7 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
|
|
|
233
239
|
routes.key,
|
|
234
240
|
cors(),
|
|
235
241
|
getKeystoreConfig,
|
|
242
|
+
kmsModuleProxyMiddleware,
|
|
236
243
|
asyncHandler(async (req, res) => {
|
|
237
244
|
const {webkms: {keystore}} = req;
|
|
238
245
|
const keyId = `${keystore.id}/keys/${req.params.keyId}`;
|
|
@@ -286,3 +293,43 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
|
|
|
286
293
|
reportOperationUsage({req});
|
|
287
294
|
}));
|
|
288
295
|
});
|
|
296
|
+
|
|
297
|
+
function _createKmsModuleProxyMiddleware() {
|
|
298
|
+
const cfg = config['kms-http'];
|
|
299
|
+
|
|
300
|
+
const kmsModuleProxyEntries = Object.entries(cfg.kmsModuleProxy ?? {});
|
|
301
|
+
if(kmsModuleProxyEntries.length === 0) {
|
|
302
|
+
// nothing to proxy; no-op
|
|
303
|
+
return function kmsModuleProxyMiddleware(req, res, next) {
|
|
304
|
+
next();
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const map = new Map();
|
|
309
|
+
for(const [kmsModule, {proxyTarget}] of kmsModuleProxyEntries) {
|
|
310
|
+
map.set(kmsModule, createProxyMiddleware({
|
|
311
|
+
target: proxyTarget,
|
|
312
|
+
// do not rewrite host header
|
|
313
|
+
changeOrigin: false,
|
|
314
|
+
// match TLS certificate checking expectations w/bedrock config
|
|
315
|
+
secure: config['https-agent'].rejectUnauthorized,
|
|
316
|
+
// include x-forward* headers
|
|
317
|
+
xfwd: true,
|
|
318
|
+
// do not forward websockets
|
|
319
|
+
ws: false,
|
|
320
|
+
on: {
|
|
321
|
+
// required to rewrite body since it has been parsed
|
|
322
|
+
proxyReq: fixRequestBody
|
|
323
|
+
}
|
|
324
|
+
}));
|
|
325
|
+
}
|
|
326
|
+
return function kmsModuleProxyMiddleware(req, res, next) {
|
|
327
|
+
const {webkms: {keystore}} = req;
|
|
328
|
+
const {kmsModule} = keystore;
|
|
329
|
+
const mw = map.get(kmsModule);
|
|
330
|
+
if(!mw) {
|
|
331
|
+
return next();
|
|
332
|
+
}
|
|
333
|
+
mw(req, res, next);
|
|
334
|
+
};
|
|
335
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bedrock/kms-http",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Bedrock KMS HTTP API",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"cidr-regex": "^4.1.3",
|
|
36
36
|
"cors": "^2.8.5",
|
|
37
37
|
"forwarded": "^0.2.0",
|
|
38
|
+
"http-proxy-middleware": "^3.0.5",
|
|
38
39
|
"ipaddr.js": "^2.2.0"
|
|
39
40
|
},
|
|
40
41
|
"peerDependencies": {
|