Let PolicyWorker run in sandbox with store

This commit is contained in:
Alex Gleason 2024-09-11 14:04:11 -05:00
parent ebc0250d81
commit cae0f492f3
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
3 changed files with 34 additions and 4 deletions

View file

@ -1,3 +1,4 @@
import os from 'node:os';
import * as dotenv from '@std/dotenv'; import * as dotenv from '@std/dotenv';
import { getPublicKey, nip19 } from 'nostr-tools'; import { getPublicKey, nip19 } from 'nostr-tools';
import { z } from 'zod'; import { z } from 'zod';
@ -240,6 +241,14 @@ class Conf {
static get policy(): string { static get policy(): string {
return Deno.env.get('DITTO_POLICY') || new URL('../data/policy.ts', import.meta.url).pathname; return Deno.env.get('DITTO_POLICY') || new URL('../data/policy.ts', import.meta.url).pathname;
} }
/** Absolute path to the data directory used by Ditto. */
static get dataDir(): string {
return Deno.env.get('DITTO_DATA_DIR') || new URL('../data', import.meta.url).pathname;
}
/** Absolute path of the Deno directory. */
static get denoDir(): string {
return Deno.env.get('DENO_DIR') || `${os.userInfo().homedir}/.cache/deno`;
}
/** Whether zap splits should be enabled. */ /** Whether zap splits should be enabled. */
static get zapSplitsEnabled(): boolean { static get zapSplitsEnabled(): boolean {
return optionalBooleanSchema.parse(Deno.env.get('ZAP_SPLITS_ENABLED')) ?? false; return optionalBooleanSchema.parse(Deno.env.get('ZAP_SPLITS_ENABLED')) ?? false;

View file

@ -13,8 +13,8 @@ export const policyWorker = Comlink.wrap<CustomPolicy>(
type: 'module', type: 'module',
deno: { deno: {
permissions: { permissions: {
read: [Conf.policy], read: [Conf.denoDir, Conf.policy, Conf.dataDir],
write: false, write: [Conf.dataDir],
net: 'inherit', net: 'inherit',
env: false, env: false,
}, },
@ -24,7 +24,12 @@ export const policyWorker = Comlink.wrap<CustomPolicy>(
); );
try { try {
await policyWorker.init(Conf.policy, Conf.databaseUrl, Conf.pubkey); await policyWorker.init({
path: Conf.policy,
cwd: Deno.cwd(),
databaseUrl: Conf.databaseUrl,
adminPubkey: Conf.pubkey,
});
console.debug(`Using custom policy: ${Conf.policy}`); console.debug(`Using custom policy: ${Conf.policy}`);
} catch (e) { } catch (e) {
if (e.message.includes('Module not found')) { if (e.message.includes('Module not found')) {

View file

@ -6,6 +6,18 @@ import * as Comlink from 'comlink';
import { DittoDB } from '@/db/DittoDB.ts'; import { DittoDB } from '@/db/DittoDB.ts';
import { EventsDB } from '@/storages/EventsDB.ts'; import { EventsDB } from '@/storages/EventsDB.ts';
/** Serializable object the worker can use to set up the state. */
interface PolicyInit {
/** Path to the policy module (https, jsr, file, etc) */
path: string;
/** Current working directory. */
cwd: string;
/** Database URL to connect to. */
databaseUrl: string;
/** Admin pubkey to use for EventsDB checks. */
adminPubkey: string;
}
export class CustomPolicy implements NPolicy { export class CustomPolicy implements NPolicy {
private policy: NPolicy = new ReadOnlyPolicy(); private policy: NPolicy = new ReadOnlyPolicy();
@ -14,7 +26,11 @@ export class CustomPolicy implements NPolicy {
return this.policy.call(event); return this.policy.call(event);
} }
async init(path: string, databaseUrl: string, adminPubkey: string): Promise<void> { async init({ path, cwd, databaseUrl, adminPubkey }: PolicyInit): Promise<void> {
// HACK: PGlite uses `path.resolve`, which requires read permission on Deno (which we don't want to give).
// We can work around this getting the cwd from the caller and overwriting `Deno.cwd`.
Deno.cwd = () => cwd;
const { kysely } = DittoDB.create(databaseUrl, { poolSize: 1 }); const { kysely } = DittoDB.create(databaseUrl, { poolSize: 1 });
const store = new EventsDB({ const store = new EventsDB({