UNPKG

@m-ld/gateway

Version:

m-ld gateway for services

86 lines 7.62 kB
import { ClassicLevel } from 'classic-level'; import { clone as meldClone, propertyValue } from '@m-ld/m-ld'; import { AuthKey } from './AuthKey.js'; import { gatewayVocab } from '../data/index.js'; import { UserKey } from '../data/UserKey.js'; export class CloneFactory { async clone(config, dataDir, principal) { // noinspection JSCheckFunctionSignatures const backend = new ClassicLevel(dataDir, { valueEncoding: 'buffer' }); const clone = await meldClone(backend, await this.remotes(config), config, new GatewayApp(config['@domain'], principal)); return [clone, backend]; } /** * @returns the subset of configuration that can be re-used by other engines * cloning the same domains */ async reusableConfig(config, remotesAuth, who) { const { networkTimeout, maxOperationSize, logLevel } = config; return { networkTimeout, maxOperationSize, logLevel }; } } export class GatewayPrincipal { /** * @param id absolute principal IRI * @param config */ constructor(id, config) { /** We do not implement sign, it's delegated to the userKey */ this.sign = undefined; this['@id'] = id; this.authKey = AuthKey.fromString(config.auth.key); this.userKey = UserKey.fromConfig(config); this.signer = { signData: data => this.userKey.sign(data, this.authKey), signJwt: (payload, options) => this.userKey.signJwt(payload, this.authKey, options), /** @returns Arguments for HTTP signing */ getSignHttpArgs: () => this.userKey.getSignHttpArgs(this.authKey) }; } } export class GatewayApp { constructor(domain, principal) { this.principal = principal; this.sign = (data) => ({ sig: this.principal.signer.signData(data), pid: this.principal['@id'] }); if (principal?.signer != null) { this.transportSecurity = { wire: data => data, sign: this.sign, verify: GatewayApp.verify(domain) }; } // TODO: Security constraint: only gateway can add/remove users } /** * @param {string} domain name * @returns import('@m-ld/m-ld').MeldTransportSecurity['verify'] */ static verify(domain) { return async (data, attr, state) => { // Load the declared user info from the data const [keyid] = UserKey.splitSignature(attr.sig); if (keyid == null) throw new Error('Signature has no keyid'); // Gotcha: verify is called without a context; all IRIs must be absolute const keyRef = UserKey.refFromKeyid(keyid, domain); const exists = await state.ask({ '@where': { '@id': attr.pid, [gatewayVocab('key')]: keyRef } }); if (!exists) throw new Error(`Principal ${attr.pid} not found`); const keySrc = await state.get(keyRef['@id']); if (keySrc == null) throw new Error('Signature key not found'); const userKey = new UserKey({ keyid: UserKey.keyidFromRef(keySrc), publicKey: propertyValue(keySrc, gatewayVocab('public'), Uint8Array) }); if (!userKey.verify(attr.sig, data)) throw new Error('Signature not valid'); }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2xvbmVGYWN0b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9DbG9uZUZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQ3NCLEtBQUssSUFBSSxTQUFTLEVBQ0ssYUFBYSxFQUNoRSxNQUFNLFlBQVksQ0FBQztBQUNwQixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsT0FBTyxFQUFpQixNQUFNLG9CQUFvQixDQUFDO0FBVTVELE1BQU0sT0FBZ0IsWUFBWTtJQUNoQyxLQUFLLENBQUMsS0FBSyxDQUNULE1BQXlCLEVBQ3pCLE9BQWUsRUFDZixTQUE0QjtRQUU1Qix5Q0FBeUM7UUFDekMsTUFBTSxPQUFPLEdBQUcsSUFBSSxZQUFZLENBQzlCLE9BQU8sRUFBRSxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sS0FBSyxHQUFHLE1BQU0sU0FBUyxDQUMzQixPQUFPLEVBQ1AsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUMxQixNQUFNLEVBQ04sSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDaEQsT0FBTyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBY0Q7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGNBQWMsQ0FDbEIsTUFBeUIsRUFDekIsV0FBOEIsRUFDOUIsR0FBUztRQUVULE1BQU0sRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxDQUFDO1FBQzlELE9BQU8sRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxFQUFFLENBQUM7SUFDeEQsQ0FBQztDQUNGO0FBRUQsTUFBTSxPQUFPLGdCQUFnQjtJQVUzQjs7O09BR0c7SUFDSCxZQUFZLEVBQVUsRUFBRSxNQUFxQjtRQWE3Qyw4REFBOEQ7UUFDOUQsU0FBSSxHQUFHLFNBQVMsQ0FBQztRQWJmLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDWixRQUFRLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQztZQUN2RCxPQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FDNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDO1lBQ3RELDBDQUEwQztZQUMxQyxlQUFlLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztTQUNsRSxDQUFDO0lBQ0osQ0FBQztDQUlGO0FBRUQsTUFBTSxPQUFPLFVBQVU7SUFHckIsWUFDRSxNQUFjLEVBQ0wsU0FBNEI7UUFBNUIsY0FBUyxHQUFULFNBQVMsQ0FBbUI7UUFZdkMsU0FBSSxHQUFHLENBQUMsSUFBWSxFQUFlLEVBQUUsQ0FBQyxDQUFDO1lBQ3JDLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBVSxDQUFDLE1BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO1lBQzNDLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBVSxDQUFDLEtBQUssQ0FBQztTQUM1QixDQUFDLENBQUM7UUFiRCxJQUFJLFNBQVMsRUFBRSxNQUFNLElBQUksSUFBSSxFQUFFO1lBQzdCLElBQUksQ0FBQyxpQkFBaUIsR0FBRztnQkFDdkIsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSTtnQkFDbEIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNmLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQzthQUNsQyxDQUFDO1NBQ0g7UUFDRCwrREFBK0Q7SUFDakUsQ0FBQztJQU9EOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBYztRQUMxQixPQUFPLEtBQUssRUFBRSxJQUFnQixFQUFFLElBQWlCLEVBQUUsS0FBb0IsRUFBRSxFQUFFO1lBQ3pFLDRDQUE0QztZQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakQsSUFBSSxLQUFLLElBQUksSUFBSTtnQkFDZixNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7WUFDNUMsd0VBQXdFO1lBQ3hFLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ25ELE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQztnQkFDN0IsUUFBUSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7YUFDN0QsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLE1BQU07Z0JBQ1QsTUFBTSxJQUFJLEtBQUssQ0FBQyxhQUFhLElBQUksQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDO1lBQ3JELE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUM5QyxJQUFJLE1BQU0sSUFBSSxJQUFJO2dCQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7WUFDN0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUM7Z0JBQzFCLEtBQUssRUFBRSxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQztnQkFDbkMsU0FBUyxFQUFFLGFBQWEsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLFFBQVEsQ0FBQyxFQUFFLFVBQVUsQ0FBQzthQUNyRSxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFDakMsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQzNDLENBQUMsQ0FBQztJQUNKLENBQUM7Q0FDRiJ9