Run the custom policy in a worker for security
This commit is contained in:
parent
6a1b8b0943
commit
9e9ab40886
|
@ -1,7 +1,7 @@
|
||||||
FROM denoland/deno:1.43.3
|
FROM denoland/deno:1.43.3
|
||||||
EXPOSE 4036
|
EXPOSE 4036
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN mkdir -p data && chown -R deno data
|
RUN mkdir -p data/policy && chown -R deno data
|
||||||
USER deno
|
USER deno
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN deno cache src/server.ts
|
RUN deno cache src/server.ts
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
*
|
*
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
!/policy
|
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
|
@ -13,7 +13,7 @@
|
||||||
"admin:role": "deno run -A scripts/admin-role.ts",
|
"admin:role": "deno run -A scripts/admin-role.ts",
|
||||||
"stats:recompute": "deno run -A scripts/stats-recompute.ts"
|
"stats:recompute": "deno run -A scripts/stats-recompute.ts"
|
||||||
},
|
},
|
||||||
"unstable": ["ffi", "kv"],
|
"unstable": ["ffi", "kv", "worker-options"],
|
||||||
"exclude": ["./public"],
|
"exclude": ["./public"],
|
||||||
"imports": {
|
"imports": {
|
||||||
"@/": "./src/",
|
"@/": "./src/",
|
||||||
|
|
|
@ -221,7 +221,7 @@ class Conf {
|
||||||
}
|
}
|
||||||
/** Path to the custom policy module. Must be an absolute path, https:, npm:, or jsr: URI. */
|
/** Path to the custom policy module. Must be an absolute path, https:, npm:, or jsr: URI. */
|
||||||
static get policy(): string {
|
static get policy(): string {
|
||||||
return Deno.env.get('DITTO_POLICY') || new URL('../data/policy.ts', import.meta.url).toString();
|
return Deno.env.get('DITTO_POLICY') || new URL('../data/policy.ts', import.meta.url).pathname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { Storages } from '@/storages.ts';
|
||||||
import { getTagSet } from '@/tags.ts';
|
import { getTagSet } from '@/tags.ts';
|
||||||
import { eventAge, nostrDate, nostrNow, parseNip05, Time } from '@/utils.ts';
|
import { eventAge, nostrDate, nostrNow, parseNip05, Time } from '@/utils.ts';
|
||||||
import { fetchWorker } from '@/workers/fetch.ts';
|
import { fetchWorker } from '@/workers/fetch.ts';
|
||||||
|
import { policyWorker } from '@/workers/policy.ts';
|
||||||
import { TrendsWorker } from '@/workers/trends.ts';
|
import { TrendsWorker } from '@/workers/trends.ts';
|
||||||
import { verifyEventWorker } from '@/workers/verify.ts';
|
import { verifyEventWorker } from '@/workers/verify.ts';
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
|
@ -62,11 +63,11 @@ async function policyFilter(event: NostrEvent): Promise<void> {
|
||||||
];
|
];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const CustomPolicy = (await import(Conf.policy)).default;
|
await policyWorker.import(Conf.policy);
|
||||||
policies.push(new CustomPolicy());
|
policies.push(policyWorker);
|
||||||
debug(`Using custom policy: ${Conf.policy}`);
|
debug(`Using custom policy: ${Conf.policy}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === 'ERR_MODULE_NOT_FOUND') {
|
if (e.message.includes('Module not found')) {
|
||||||
debug('Custom policy not found <https://docs.soapbox.pub/ditto/policies/>');
|
debug('Custom policy not found <https://docs.soapbox.pub/ditto/policies/>');
|
||||||
} else {
|
} else {
|
||||||
console.error(`DITTO_POLICY (error importing policy): ${Conf.policy}`, e);
|
console.error(`DITTO_POLICY (error importing policy): ${Conf.policy}`, e);
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import * as Comlink from 'comlink';
|
||||||
|
|
||||||
|
import { Conf } from '@/config.ts';
|
||||||
|
import type { CustomPolicy } from '@/workers/policy.worker.ts';
|
||||||
|
|
||||||
|
const policyDir = new URL('../../data/policy', import.meta.url).pathname;
|
||||||
|
|
||||||
|
export const policyWorker = Comlink.wrap<CustomPolicy>(
|
||||||
|
new Worker(
|
||||||
|
new URL('./policy.worker.ts', import.meta.url),
|
||||||
|
{
|
||||||
|
type: 'module',
|
||||||
|
deno: {
|
||||||
|
permissions: {
|
||||||
|
read: [Conf.policy, policyDir],
|
||||||
|
write: [policyDir],
|
||||||
|
net: 'inherit',
|
||||||
|
env: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/nostrify';
|
||||||
|
import { ReadOnlyPolicy } from '@nostrify/nostrify/policies';
|
||||||
|
import * as Comlink from 'comlink';
|
||||||
|
|
||||||
|
export class CustomPolicy implements NPolicy {
|
||||||
|
private policy: NPolicy = new ReadOnlyPolicy();
|
||||||
|
|
||||||
|
// deno-lint-ignore require-await
|
||||||
|
async call(event: NostrEvent): Promise<NostrRelayOK> {
|
||||||
|
return this.policy.call(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
async import(path: string): Promise<void> {
|
||||||
|
const Policy = (await import(path)).default;
|
||||||
|
this.policy = new Policy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Comlink.expose(new CustomPolicy());
|
Loading…
Reference in New Issue