Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# bedrock-kms-http ChangeLog

## 23.2.0 - 2025-11-dd

### Changed
- Include route for fetching all keystore configs for a given root controller.

## 23.0.0 - 2025-10-14

### Changed
Expand Down
24 changes: 24 additions & 0 deletions lib/BedrockKeystoreConfigStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,28 @@ export class BedrockKeystoreConfigStorage extends KeystoreConfigStorage {

return returnRecord ? record : keystoreConfig;
}

async getAll({
controller, req, query = {}, options = {}, returnRecord = false
} = {}) {
const records = await keystores.find({controller, query, options});
const keystoreConfigs = records.map(r => r.config);
// skip request checks if specifically requested
if(req === false) {
return returnRecord ? records : keystoreConfigs;
}
// verify that request is from an IP that is allowed to access the config
for(let i = 0; i < keystoreConfigs.length; ++i) {
const keystoreConfig = keystoreConfigs[i];
const {verified} = helpers.verifyRequestIp({keystoreConfig, req});
if(!verified) {
throw new BedrockError(
'Permission denied. Source IP is not allowed.', 'NotAllowedError', {
httpStatusCode: 403,
public: true,
});
}
}
return returnRecord ? records : keystoreConfigs;
}
}
38 changes: 34 additions & 4 deletions lib/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ import * as brZCapStorage from '@bedrock/zcap-storage';
import * as helpers from './helpers.js';
import * as middleware from './middleware.js';
import {
keystores,
defaultModuleManager as moduleManager
} from '@bedrock/kms';
import {
getConfigsQuery,
postKeystoreBody,
postRevocationBody,
updateKeystoreConfigBody
} from '../schemas/bedrock-kms-http.js';
import {
keystores,
defaultModuleManager as moduleManager
} from '@bedrock/kms';
import {reportOperationUsage, SERVICE_TYPE} from './metering.js';
import {asyncHandler} from '@bedrock/express';
import {BedrockKeystoreConfigStorage} from './BedrockKeystoreConfigStorage.js';
import {generateRandom} from '@digitalbazaar/webkms-switch';
import {meters} from '@bedrock/meter-usage-reporter';
import {createValidateMiddleware as validate} from '@bedrock/validation';
Expand All @@ -41,6 +43,10 @@ bedrock.events.on('bedrock-express.configure.routes', app => {
routes.key = `${routes.keys}/:keyId`;
routes.revocations = `${routes.keystore}/zcaps/revocations/:revocationId`;

const {baseUri} = bedrock.config.server;

const storage = new BedrockKeystoreConfigStorage();

// create middleware for handling KMS operations
const handleOperation = middleware.createKmsOperationMiddleware();

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

// get all keystores with root controller
app.options(routes.keystores, cors());
app.get(
routes.keystores,
cors(),
validate({querySchema: getConfigsQuery}),
middleware.authorizeZcapInvocation({
async getExpectedValues() {
return {
host: bedrock.config.server.host,
rootInvocationTarget: baseUri + routes.keystores
};
},
async getRootController({req}) {
return req.query.controller;
}
}),
asyncHandler(async (req, res) => {
const controller = req.query.controller;
const options = {projection: {_id: 0, config: 1}, limit: 100};
const results = await storage.getAll({controller, req, options});
res.json({results});
}));

// create a new keystore
app.options(routes.keystores, cors());
app.post(
Expand Down
11 changes: 11 additions & 0 deletions schemas/bedrock-kms-http.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,18 @@ const postRevocationBody = {
...delegatedZcap
};

const getConfigsQuery = {
title: 'Service Object Configuration Query',
type: 'object',
required: ['controller'],
additionalProperties: false,
properties: {
controller
}
};

export {
getConfigsQuery,
postKeystoreBody,
postRevocationBody,
updateKeystoreConfigBody
Expand Down