Skip to content

Commit 4cb4e26

Browse files
committed
Add test to get all keystores for a controller.
1 parent b394f01 commit 4cb4e26

File tree

5 files changed

+76
-38
lines changed

5 files changed

+76
-38
lines changed

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# bedrock-kms-http ChangeLog
22

3-
## 23.2.0 - 2025-11-dd
3+
## 23.1.0 - 2025-11-dd
44

5-
### Changed
6-
- Include route for fetching all keystore configs for a given root controller.
5+
### Added
6+
- Add route for fetching all keystore configs for a given root controller.
77

88
## 23.0.0 - 2025-10-14
99

lib/http.js

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
2+
* Copyright (c) 2019-2025 Digital Bazaar, Inc. All rights reserved.
33
*/
44
import * as bedrock from '@bedrock/core';
55
import * as brZCapStorage from '@bedrock/zcap-storage';
@@ -17,13 +17,12 @@ import {
1717
} from '@bedrock/kms';
1818
import {reportOperationUsage, SERVICE_TYPE} from './metering.js';
1919
import {asyncHandler} from '@bedrock/express';
20-
import {BedrockKeystoreConfigStorage} from './BedrockKeystoreConfigStorage.js';
2120
import {generateRandom} from '@digitalbazaar/webkms-switch';
2221
import {meters} from '@bedrock/meter-usage-reporter';
2322
import {createValidateMiddleware as validate} from '@bedrock/validation';
2423

2524
const {config, util: {BedrockError}} = bedrock;
26-
const {cors} = middleware;
25+
const {cors, storage} = middleware;
2726

2827
bedrock.events.on('bedrock-express.configure.routes', app => {
2928
const cfg = config['kms-http'];
@@ -43,10 +42,6 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
4342
routes.key = `${routes.keys}/:keyId`;
4443
routes.revocations = `${routes.keystore}/zcaps/revocations/:revocationId`;
4544

46-
const {baseUri} = bedrock.config.server;
47-
48-
const storage = new BedrockKeystoreConfigStorage();
49-
5045
// create middleware for handling KMS operations
5146
const handleOperation = middleware.createKmsOperationMiddleware();
5247

@@ -57,30 +52,6 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
5752
/* Note: CORS is used on all endpoints. This is safe because authorization
5853
uses HTTP signatures + capabilities, not cookies; CSRF is not possible. */
5954

60-
// get all keystores with root controller
61-
app.options(routes.keystores, cors());
62-
app.get(
63-
routes.keystores,
64-
cors(),
65-
validate({querySchema: getConfigsQuery}),
66-
middleware.authorizeZcapInvocation({
67-
async getExpectedValues() {
68-
return {
69-
host: bedrock.config.server.host,
70-
rootInvocationTarget: baseUri + routes.keystores
71-
};
72-
},
73-
async getRootController({req}) {
74-
return req.query.controller;
75-
}
76-
}),
77-
asyncHandler(async (req, res) => {
78-
const controller = req.query.controller;
79-
const options = {projection: {_id: 0, config: 1}, limit: 100};
80-
const results = await storage.getAll({controller, req, options});
81-
res.json({results});
82-
}));
83-
8455
// create a new keystore
8556
app.options(routes.keystores, cors());
8657
app.post(
@@ -204,6 +175,30 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
204175
reportOperationUsage({req});
205176
}));
206177

178+
// get all keystores with root controller
179+
app.get(
180+
routes.keystores,
181+
cors(),
182+
validate({querySchema: getConfigsQuery}),
183+
middleware.authorizeZcapInvocation({
184+
async getExpectedValues() {
185+
const {baseUri, host} = bedrock.config.server;
186+
return {
187+
host,
188+
rootInvocationTarget: `${baseUri}${routes.keystores}`
189+
};
190+
},
191+
async getRootController({req}) {
192+
return req.query.controller;
193+
}
194+
}),
195+
asyncHandler(async (req, res) => {
196+
const controller = req.query.controller;
197+
const options = {projection: {_id: 0, config: 1}, limit: 100};
198+
const results = await storage.getAll({controller, req, options});
199+
res.json({results});
200+
}));
201+
207202
// get a keystore config
208203
app.get(
209204
routes.keystore,

lib/middleware.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const {helpers: {inspectCapabilityChain}} = brZCapStorage;
2424

2525
const FIVE_MINUTES = 1000 * 60 * 5;
2626

27-
const storage = new BedrockKeystoreConfigStorage();
27+
export const storage = new BedrockKeystoreConfigStorage();
2828

2929
// creates middleware to get the keystore config for the current request and
3030
// caches it in `req.webkms.keystore`

test/mocha/10-keystore.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
2+
* Copyright (c) 2019-2025 Digital Bazaar, Inc. All rights reserved.
33
*/
44
import * as bedrock from '@bedrock/core';
55
import * as helpers from './helpers.js';
@@ -138,7 +138,7 @@ describe('bedrock-kms-http API', () => {
138138
'the \'postKeystoreBody\' validator.');
139139
});
140140
it('throws error with no controller in zcap validation', async () => {
141-
const secret = ' b07e6b31-d910-438e-9a5f-08d945a5f676';
141+
const secret = 'b07e6b31-d910-438e-9a5f-08d945a5f676';
142142
const handle = 'testKey1';
143143
const capabilityAgent = await CapabilityAgent.fromSecret(
144144
{secret, handle});
@@ -165,6 +165,36 @@ describe('bedrock-kms-http API', () => {
165165
'A validation error occurred in the \'delegatedZcap\' validator.');
166166
});
167167

168+
describe(`get a controller's keystore configs`, () => {
169+
it('gets two keystores', async () => {
170+
const secret = 'e3ecebb0-d94f-47bf-b11b-5ac08ce37f5d';
171+
const handle = 'testKey1';
172+
const capabilityAgent = await CapabilityAgent.fromSecret(
173+
{secret, handle});
174+
175+
const keystore1 = await helpers.createKeystore({capabilityAgent});
176+
const keystore2 = await helpers.createKeystore({capabilityAgent});
177+
178+
let err;
179+
let result;
180+
try {
181+
const kmsBaseUrl = `${bedrock.config.server.baseUri}/kms`;
182+
const url = `${kmsBaseUrl}/keystores`;
183+
result = await helpers.getKeystores({url, capabilityAgent});
184+
} catch(e) {
185+
err = e;
186+
}
187+
assertNoError(err);
188+
should.exist(result);
189+
result.should.have.keys(['results']);
190+
result.results.length.should.equal(2);
191+
result.results[0].id.should.equal(keystore1.id);
192+
result.results[0].controller.should.equal(capabilityAgent.id);
193+
result.results[1].id.should.equal(keystore2.id);
194+
result.results[1].controller.should.equal(capabilityAgent.id);
195+
});
196+
}); // get keystore configs
197+
168198
describe('get keystore config', () => {
169199
it('gets a keystore', async () => {
170200
const secret = 'b07e6b31-d910-438e-9a5f-08d945a5f676';
@@ -216,7 +246,7 @@ describe('bedrock-kms-http API', () => {
216246
result.ipAllowList.should.eql(ipAllowList);
217247
});
218248
it('returns NotAllowedError for invalid source IP', async () => {
219-
const secret = ' b07e6b31-d910-438e-9a5f-08d945a5f676';
249+
const secret = 'b07e6b31-d910-438e-9a5f-08d945a5f676';
220250
const handle = 'testKey1';
221251
const capabilityAgent = await CapabilityAgent.fromSecret(
222252
{secret, handle});

test/mocha/helpers.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ export async function getKeystore({id, capabilityAgent}) {
107107
return kmsClient.getKeystore({invocationSigner});
108108
}
109109

110+
export async function getKeystores({url, capabilityAgent}) {
111+
const zcapClient = new ZcapClient({
112+
agent: httpsAgent,
113+
invocationSigner: capabilityAgent.getSigner(),
114+
SuiteClass: Ed25519Signature2020
115+
});
116+
const {data} = await zcapClient.read({
117+
url: `${url}?controller=${encodeURIComponent(capabilityAgent.id)}`,
118+
capability: `urn:zcap:root:${encodeURIComponent(url)}`
119+
});
120+
return data;
121+
}
122+
110123
export async function delegate({
111124
parentCapability, controller, invocationTarget, expires, allowedAction,
112125
delegator, purposeOptions = {}

0 commit comments

Comments
 (0)