This commit is contained in:
Ishaan Dey 2024-05-25 01:16:25 -07:00
parent a16b530b56
commit a90c09200d
3 changed files with 86 additions and 60 deletions

View File

@ -1,4 +1,4 @@
import type { DrizzleD1Database } from "drizzle-orm/d1"; // import type { DrizzleD1Database } from "drizzle-orm/d1";
import { drizzle } from "drizzle-orm/d1"; import { drizzle } from "drizzle-orm/d1";
import { json } from "itty-router-extras"; import { json } from "itty-router-extras";
import { ZodError, z } from "zod"; import { ZodError, z } from "zod";
@ -10,6 +10,7 @@ import { and, eq, sql } from "drizzle-orm";
export interface Env { export interface Env {
DB: D1Database; DB: D1Database;
STORAGE: any; STORAGE: any;
KV: KVNamespace;
} }
// https://github.com/drizzle-team/drizzle-orm/tree/main/examples/cloudflare-d1 // https://github.com/drizzle-team/drizzle-orm/tree/main/examples/cloudflare-d1
@ -30,7 +31,35 @@ export default {
const db = drizzle(env.DB, { schema }); const db = drizzle(env.DB, { schema });
if (path === "/api/sandbox") { if (path === "/api/session") {
if (method === "PUT") {
const body = await request.json();
const schema = z.object({
userId: z.string(),
sandboxId: z.string(),
});
const { userId, sandboxId } = schema.parse(body);
await env.KV.put(userId, sandboxId);
return success;
} else if (method === "GET") {
const params = url.searchParams;
if (params.has("id")) {
const id = params.get("id") as string;
const sandboxId = await env.KV.get(id);
return json({ sandboxId });
} else return invalidRequest;
} else if (method === "DELETE") {
const params = url.searchParams;
if (params.has("id")) {
const id = params.get("id") as string;
await env.KV.delete(id);
return success;
} else return invalidRequest;
} else return methodNotAllowed;
} else if (path === "/api/sandbox") {
if (method === "GET") { if (method === "GET") {
const params = url.searchParams; const params = url.searchParams;
if (params.has("id")) { if (params.has("id")) {
@ -65,14 +94,14 @@ export default {
return invalidRequest; return invalidRequest;
} }
} else if (method === "POST") { } else if (method === "POST") {
const initSchema = z.object({ const postSchema = z.object({
id: z.string(), id: z.string(),
name: z.string().optional(), name: z.string().optional(),
visibility: z.enum(["public", "private"]).optional(), visibility: z.enum(["public", "private"]).optional(),
}); });
const body = await request.json(); const body = await request.json();
const { id, name, visibility } = initSchema.parse(body); const { id, name, visibility } = postSchema.parse(body);
const sb = await db.update(sandbox).set({ name, visibility }).where(eq(sandbox.id, id)).returning().get(); const sb = await db.update(sandbox).set({ name, visibility }).where(eq(sandbox.id, id)).returning().get();
return success; return success;
@ -99,9 +128,8 @@ export default {
body: JSON.stringify({ sandboxId: sb.id, type }), body: JSON.stringify({ sandboxId: sb.id, type }),
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
}); });
const initStorageRes = await env.STORAGE.fetch(initStorageRequest);
// const initStorage = await initStorageRes.text(); await env.STORAGE.fetch(initStorageRequest);
return new Response(sb.id, { status: 200 }); return new Response(sb.id, { status: 200 });
} else { } else {

View File

@ -2,8 +2,8 @@ FROM node:20
# Security: Drop all capabilities # Security: Drop all capabilities
USER root USER root
RUN apt-get update && apt-get install -y libcap2-bin && \ RUN apt-get update && apt-get install -y libcap2-bin
setcap cap_net_bind_service=+ep /usr/local/bin/node RUN setcap cap_net_bind_service=+ep /usr/local/bin/node
WORKDIR /code WORKDIR /code
@ -15,21 +15,14 @@ COPY . .
RUN npm run build RUN npm run build
# Security: Create non-root user and assign ownership
RUN useradd -m sboxuser RUN useradd -m sboxuser
RUN mkdir projects && chown -R sboxuser:sboxuser projects RUN mkdir projects && chown -R sboxuser:sboxuser projects
# todo user namespace mapping
RUN apt-get install -y firejail
# RUN echo "noblacklist /code/projects\nprivate-bin node\nwhitelist /code/projects\n" > /etc/firejail/sboxuser.profile
# RUN echo '#!/bin/bash\nexec firejail --private=/projects --noprofile node dist/index.js' > /start.sh
RUN echo '#!/bin/bash\nexec firejail --private=/code/projects --noprofile --net=none --whitelist=/code/projects node dist/index.js' > /start.sh
RUN chmod +x /start.sh
USER sboxuser USER sboxuser
EXPOSE 8000 # user namespace mapping
EXPOSE 4000
CMD ["/start.sh"] EXPOSE 8000
EXPOSE 5173
CMD [ "node", "dist/index.js" ]

View File

@ -34,50 +34,55 @@ export default function Editor({
return; return;
} }
startServer(sandboxData.id).then((response) => { // startServer(sandboxData.id).then((response) => {
if (!response.success) { // if (!response.success) {
toast.error(response.message); // toast.error(response.message);
setDidFail(true); // setDidFail(true);
} else { // } else {
setIsServiceRunning(true); // setIsServiceRunning(true);
checkServiceStatus(sandboxData.id) // checkServiceStatus(sandboxData.id)
.then(() => { // .then(() => {
setIsDeploymentActive(true); // setIsDeploymentActive(true);
getTaskIp(sandboxData.id) // getTaskIp(sandboxData.id)
.then((ip) => { // .then((ip) => {
setTaskIp(ip); // setTaskIp(ip);
}) // })
.catch(() => { // .catch(() => {
setDidFail(true); // setDidFail(true);
toast.error("An error occurred while getting your server IP."); // toast.error("An error occurred while getting your server IP.");
}); // });
}) // })
.catch(() => { // .catch(() => {
toast.error("An error occurred while initializing your server."); // toast.error("An error occurred while initializing your server.");
setDidFail(true); // setDidFail(true);
}); // });
} // }
}); // });
}, []); }, []);
if (didFail) return <Loading didFail={didFail} />; // if (didFail) return <Loading didFail={didFail} />;
if (!isServiceRunning || !isDeploymentActive || !taskIp) // if (!isServiceRunning || !isDeploymentActive || !taskIp)
return ( // return (
<Loading // <Loading
text="Creating sandbox resources" // text="Creating sandbox resources"
description={ // description={
isDeploymentActive // isDeploymentActive
? "Preparing server networking..." // ? "Preparing server networking..."
: isServiceRunning // : isServiceRunning
? "Initializing server, this could take a minute..." // ? "Initializing server, this could take a minute..."
: "Requesting your server creation..." // : "Requesting your server creation..."
} // }
/> // />
); // );
return ( return (
<CodeEditor ip={taskIp} userData={userData} sandboxData={sandboxData} /> <CodeEditor
ip={"localhost"}
// ip={taskIp}
userData={userData}
sandboxData={sandboxData}
/>
); );
} }