INTEGRITY Dokumentace

Řízení odchozího provozu

Když v dynamickém Workeru spouštíte nedůvěryhodný nebo AI generovaný kód, musíte mít kontrolu nad tím, k čemu má v síti přístup. Můžete například chtít:

globalOutbound možnost v WorkerCode objekt vrácený get() nebo předán do load() to vše řídí. Zachytává každé fetch() a connect() volání, které dynamic Worker provede.

Blokování veškerého odchozího přístupu

Nastavte globalOutbound na null k úplné izolaci dynamic Workeru od sítě:

return {
	mainModule: "index.js",
	modules: { "index.js": code },
	globalOutbound: null,
};

Tím se způsobí, že jakýkoli fetch() nebo connect() požadavku z dynamic Workeru vyvolat výjimku.

I v tomto režimu můžete Dynamic Workeru dát přímý přístup ke konkrétním prostředkům a službám pomocí vazby. Toto je nejčistší a nejbezpečnější způsob návrhu sandboxu: nejprve zablokujte přístup k internetu a poté cíleně povolte konkrétní schopnosti prostřednictvím bindingů.

Pokud však potřebujete zajistit kompatibilitu se stávajícími HTTP klientskými knihovnami běžícími přímo ve vašem sandboxu Dynamic Workeru, pak blokující fetch() nemusí být proveditelné a je možné, že budete raději zachytávat požadavky.

Zachytávání odchozích požadavků

Chcete-li zachytávat odchozí požadavky, definujte WorkerEntrypoint třídu v loader Workeru, která funguje jako brána. Každé fetch() a connect() volání, které dynamic Worker provede, prochází touto bránou místo přímého přístupu k síti. Bránu dynamic Workeru předáte pomocí globalOutbound a ctx.exports:

import { WorkerEntrypoint } from "cloudflare:workers";

export class HttpGateway extends WorkerEntrypoint {
	async fetch(request) {
		// Every outbound fetch() from the dynamic Worker arrives here.
		// Inspect, modify, block, or forward the request.
		return fetch(request);
	}
}

export default {
	async fetch(request, env, ctx) {
		const worker = env.LOADER.get("my-worker", async () => {
			return {
				compatibilityDate: "$today",
				mainModule: "index.js",
				modules: { "index.js": code },

				// Pass the gateway as a service binding.
				// The dynamic Worker's fetch() and connect() calls
				// are routed through HttpGateway instead of going
				// to the network directly.
				globalOutbound: ctx.exports.HttpGateway(),
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};

Odtud můžete do brány přidat libovolnou logiku, například omezení cílů, vkládání přihlašovacích údajů nebo logování požadavků.

Vložení přihlašovacích údajů

Běžným postupem je připojit přihlašovací údaje k odchozím požadavkům tak, aby dynamický Worker nikdy neviděl tajný údaj. Podobně jako u vlastní bindingy, můžete použít ctx.props k předání kontextu pro jednotlivé tenanty nebo požadavky do gateway.

Dynamický Worker zavolá fetch() běžným způsobem. HttpGateway zachytí požadavek, připojí token z prostředí loader Workeru a přepošle ho dál. Dynamic Worker nikdy nemá přístup k API_TOKEN.

import { WorkerEntrypoint } from "cloudflare:workers";

export class HttpGateway extends WorkerEntrypoint {
	async fetch(request) {
		let url = new URL(request.url);
		const headers = new Headers(request.headers);

		// For requests to api.example.com, inject credentials.
		if (url.hostname === "api.example.com") {
			headers.set("Authorization", `Bearer ${this.env.API_TOKEN}`);
			headers.set("X-Tenant-Id", this.ctx.props.tenantId);
		}

		return fetch(request, { headers });
	}
}

export default {
	async fetch(request, env, ctx) {
		const tenantId = getTenantFromRequest(request);

		const worker = env.LOADER.get(`tenant:${tenantId}`, async () => {
			return {
				mainModule: "index.js",
				modules: {
					"index.js": `
						export default {
							async fetch() {
								const resp = await fetch("https://api.example.com/data");
								return new Response(await resp.text());
							},
						};
					`,
				},
				globalOutbound: ctx.exports.HttpGateway({
					props: { tenantId },
				}),
			};
		});

		return worker.getEntrypoint().fetch(request);
	},
};