@bedrock/kms-http 14.3.0 → 14.3.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # bedrock-kms-http ChangeLog
2
2
 
3
+ ## 14.3.1 - 2022-05-16
4
+
5
+ ### Fixed
6
+ - Use `@digitalbazaar/webkms-switch@10.2` to ensure that pre-cached `webkms`
7
+ request meta data is not overwritten and that a custom `getRootController`
8
+ function is used (to enable cache busting on KMS operations).
9
+
3
10
  ## 14.3.0 - 2022-05-16
4
11
 
5
12
  ### Added
package/lib/http.js CHANGED
@@ -191,6 +191,7 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
191
191
  app.post(
192
192
  routes.keys,
193
193
  cors(),
194
+ getKeystoreConfig,
194
195
  handleOperation);
195
196
 
196
197
  // invoke KMS operation on an existing key
@@ -198,6 +199,7 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
198
199
  app.post(
199
200
  routes.key,
200
201
  cors(),
202
+ getKeystoreConfig,
201
203
  handleOperation);
202
204
 
203
205
  // TODO: consider whether this should be exposed w/o authorization
package/lib/middleware.js CHANGED
@@ -46,7 +46,7 @@ export function createGetKeystoreConfig({routes}) {
46
46
  id: keystoreId, req, returnRecord: true
47
47
  });
48
48
  const {config: keystore} = configRecord;
49
- req.webkms = {keystore, configRecord};
49
+ req.webkms = {...req.webkms, keystore, configRecord};
50
50
  }
51
51
  next();
52
52
  });
@@ -58,7 +58,10 @@ export function createKmsOperationMiddleware() {
58
58
  return createOperationMiddleware({
59
59
  ...kmsOperationOptions,
60
60
  storage, moduleManager, documentLoader,
61
- expectedHost: config.server.host, getVerifier,
61
+ expectedHost: config.server.host,
62
+ // override `getRootController` to provide cache busting capability
63
+ getRootController: getKeystoreController,
64
+ getVerifier,
62
65
  inspectCapabilityChain,
63
66
  onError, onSuccess: reportOperationUsage, suiteFactory
64
67
  });
@@ -185,7 +188,7 @@ async function getKeystoreController({req}) {
185
188
  id: req.webkms.keystore.id, req, returnRecord: true, fresh: true
186
189
  });
187
190
  const {config: keystore} = configRecord;
188
- req.webkms = {keystore, configRecord};
191
+ req.webkms = {...req.webkms, keystore, configRecord};
189
192
  logger.debug('Forced fresh keystore config retrieval during zcap check.');
190
193
  }
191
194
 
@@ -243,10 +246,7 @@ function onError({error}) {
243
246
  if(!(error instanceof BedrockError)) {
244
247
  // always expose cause message and name; expose cause details as
245
248
  // BedrockError if error is marked public
246
- let details = {};
247
- if(error.details && error.details.public) {
248
- details = error.details;
249
- }
249
+ const details = error.details?.public ? error.details : {};
250
250
  error = new BedrockError(
251
251
  error.message,
252
252
  error.name || 'NotAllowedError', {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrock/kms-http",
3
- "version": "14.3.0",
3
+ "version": "14.3.1",
4
4
  "type": "module",
5
5
  "description": "Bedrock KMS HTTP API",
6
6
  "main": "./lib/index.js",
@@ -27,7 +27,7 @@
27
27
  "@digitalbazaar/ed25519-signature-2020": "^3.0.0",
28
28
  "@digitalbazaar/ed25519-verification-key-2020": "^3.2.0",
29
29
  "@digitalbazaar/ezcap-express": "^6.2.0",
30
- "@digitalbazaar/webkms-switch": "^10.0.0",
30
+ "@digitalbazaar/webkms-switch": "^10.2.0",
31
31
  "cidr-regex": "^3.1.1",
32
32
  "cors": "^2.8.5",
33
33
  "crypto-ld": "^6.0.0",
@@ -67,7 +67,7 @@ describe('keystore API interactions using webkms-client', () => {
67
67
  bobKeystoreAgent.keystoreId);
68
68
  });
69
69
 
70
- it('updates config controller twice proving cache busting', async () => {
70
+ it('updates config and uses key proving cache busting', async () => {
71
71
  const keystoreId = aliceKeystoreConfig.id;
72
72
  const kmsClient = new KmsClient({httpsAgent});
73
73
 
@@ -88,6 +88,9 @@ describe('keystore API interactions using webkms-client', () => {
88
88
  const agent3KeystoreAgent = new KeystoreAgent(
89
89
  {capabilityAgent: agent3, keystoreId, kmsClient});
90
90
 
91
+ // generate a key for use
92
+ const hmacKey = await aliceKeystoreAgent.generateKey({type: 'hmac'});
93
+
91
94
  // delegate zcap for updating config from agent2 to agent3 to test
92
95
  // cache busting with delegated zcap
93
96
  const rootCapability = ZCAP_ROOT_PREFIX + encodeURIComponent(keystoreId);
@@ -120,7 +123,7 @@ describe('keystore API interactions using webkms-client', () => {
120
123
  // disable cache delete functionality on update
121
124
  keystores._disableClearCacheOnUpdate(true);
122
125
 
123
- // update controller alice => agent1 (no cache busting required
126
+ // update controller alice => agent1 (no cache busting required)
124
127
  {
125
128
  config.sequence++;
126
129
  config.controller = agent1.id;
@@ -164,6 +167,72 @@ describe('keystore API interactions using webkms-client', () => {
164
167
  result.config.controller.should.eql(agent1.id);
165
168
  ({config} = result);
166
169
  }
170
+
171
+ // update controller back to alice to test key op cache busting
172
+ {
173
+ config.sequence++;
174
+ config.controller = aliceCapabilityAgent.id;
175
+ const result = await agent1KeystoreAgent.updateConfig({config});
176
+ result.config.id.should.eql(config.id);
177
+ result.config.controller.should.eql(aliceCapabilityAgent.id);
178
+ ({config} = result);
179
+ }
180
+
181
+ // use hmac key as alice (requires cache busting by inspecting root
182
+ // zcap)
183
+ await hmacKey.sign({data: new Uint8Array([0])});
184
+
185
+ // update controller alice => agent1 (no cache busting required)
186
+ {
187
+ config.sequence++;
188
+ config.controller = agent1.id;
189
+ const result = await aliceKeystoreAgent.updateConfig({config});
190
+ result.config.id.should.eql(config.id);
191
+ result.config.controller.should.eql(agent1.id);
192
+ ({config} = result);
193
+ }
194
+
195
+ // use hmac key as agent1 (requires cache busting by
196
+ // inspecting the root zcap)
197
+ hmacKey.invocationSigner = agent1.getSigner();
198
+ // use different data each time to avoid hmac caching
199
+ await hmacKey.sign({data: new Uint8Array([1])});
200
+
201
+ // update controller agent1 => agent2 (requires cache busting by
202
+ // inspecting the root zcap)
203
+ {
204
+ config.sequence++;
205
+ config.controller = agent2.id;
206
+ const result = await agent1KeystoreAgent.updateConfig({config});
207
+ result.config.id.should.eql(config.id);
208
+ result.config.controller.should.eql(agent2.id);
209
+ ({config} = result);
210
+ }
211
+
212
+ // use hmac key as agent3 (requires cache busting by
213
+ // inspecting a delegated zcap)
214
+ hmacKey.capability = agent3Zcap;
215
+ hmacKey.invocationSigner = agent3.getSigner();
216
+ // use different data each time to avoid hmac caching
217
+ await hmacKey.sign({data: new Uint8Array([1])});
218
+
219
+ // update controller agent2 => agent3 (cache should already be fresh)
220
+ {
221
+ config.sequence++;
222
+ config.controller = agent3.id;
223
+ const result = await agent3KeystoreAgent.updateConfig(
224
+ {capability: agent3Zcap, config});
225
+ result.config.id.should.eql(config.id);
226
+ result.config.controller.should.eql(agent3.id);
227
+ ({config} = result);
228
+ }
229
+
230
+ // use hmac key as agent1 (requires cache busting by
231
+ // inspecting a deep delegated zcap)
232
+ hmacKey.capability = agent1Zcap;
233
+ hmacKey.invocationSigner = agent1.getSigner();
234
+ // use different data each time to avoid hmac caching
235
+ await hmacKey.sign({data: new Uint8Array([1])});
167
236
  } catch(e) {
168
237
  assertNoError(e);
169
238
  } finally {