@namzu/sandbox 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +474 -0
- package/LICENSE.md +110 -0
- package/README.md +148 -0
- package/dist/backends/aci-standby-pool/index.d.ts +104 -0
- package/dist/backends/aci-standby-pool/index.d.ts.map +1 -0
- package/dist/backends/aci-standby-pool/index.js +425 -0
- package/dist/backends/aci-standby-pool/index.js.map +1 -0
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts +40 -0
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts.map +1 -0
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js +157 -0
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js.map +1 -0
- package/dist/backends/docker/index.d.ts +118 -0
- package/dist/backends/docker/index.d.ts.map +1 -0
- package/dist/backends/docker/index.js +645 -0
- package/dist/backends/docker/index.js.map +1 -0
- package/dist/backends/firecracker/__tests__/backend.test.d.ts +13 -0
- package/dist/backends/firecracker/__tests__/backend.test.d.ts.map +1 -0
- package/dist/backends/firecracker/__tests__/backend.test.js +353 -0
- package/dist/backends/firecracker/__tests__/backend.test.js.map +1 -0
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts +19 -0
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts.map +1 -0
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js +201 -0
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js.map +1 -0
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts +39 -0
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts.map +1 -0
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js +149 -0
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js.map +1 -0
- package/dist/backends/firecracker/__tests__/protocol.test.d.ts +6 -0
- package/dist/backends/firecracker/__tests__/protocol.test.d.ts.map +1 -0
- package/dist/backends/firecracker/__tests__/protocol.test.js +77 -0
- package/dist/backends/firecracker/__tests__/protocol.test.js.map +1 -0
- package/dist/backends/firecracker/__tests__/transport.test.d.ts +20 -0
- package/dist/backends/firecracker/__tests__/transport.test.d.ts.map +1 -0
- package/dist/backends/firecracker/__tests__/transport.test.js +449 -0
- package/dist/backends/firecracker/__tests__/transport.test.js.map +1 -0
- package/dist/backends/firecracker/index.d.ts +124 -0
- package/dist/backends/firecracker/index.d.ts.map +1 -0
- package/dist/backends/firecracker/index.js +334 -0
- package/dist/backends/firecracker/index.js.map +1 -0
- package/dist/backends/firecracker/protocol.d.ts +132 -0
- package/dist/backends/firecracker/protocol.d.ts.map +1 -0
- package/dist/backends/firecracker/protocol.js +112 -0
- package/dist/backends/firecracker/protocol.js.map +1 -0
- package/dist/backends/firecracker/transport.d.ts +251 -0
- package/dist/backends/firecracker/transport.d.ts.map +1 -0
- package/dist/backends/firecracker/transport.js +524 -0
- package/dist/backends/firecracker/transport.js.map +1 -0
- package/dist/index.d.ts +611 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +376 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +28 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +670 -0
- package/dist/index.test.js.map +1 -0
- package/package.json +54 -0
- package/src/backends/aci-standby-pool/index.ts +602 -0
- package/src/backends/docker/__tests__/leaf-permissions.smoke.test.ts +169 -0
- package/src/backends/docker/index.ts +826 -0
- package/src/backends/firecracker/__tests__/backend.test.ts +418 -0
- package/src/backends/firecracker/__tests__/control-plane-mtls.test.ts +253 -0
- package/src/backends/firecracker/__tests__/fixtures/mtls-pki.ts +166 -0
- package/src/backends/firecracker/__tests__/protocol.test.ts +90 -0
- package/src/backends/firecracker/__tests__/transport.test.ts +526 -0
- package/src/backends/firecracker/index.ts +528 -0
- package/src/backends/firecracker/protocol.ts +191 -0
- package/src/backends/firecracker/transport.ts +667 -0
- package/src/index.test.ts +731 -0
- package/src/index.ts +930 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control-plane mTLS dial for the Firecracker backend (additive
|
|
3
|
+
* `config.controlPlaneMtls`).
|
|
4
|
+
*
|
|
5
|
+
* A loopback `https.createServer` with `requestCert + rejectUnauthorized`
|
|
6
|
+
* (pinned to the test CA) stands in for the orchestrator over the public hop.
|
|
7
|
+
* It serves the real `POST /sandboxes` + `:delete` routes; the create response
|
|
8
|
+
* points the agent handle at a unix-socket loopback running the REAL
|
|
9
|
+
* `agent/agent.cjs`, so the FULL create flow (control-plane POST over mTLS →
|
|
10
|
+
* vsock readiness fence → exec) runs end to end.
|
|
11
|
+
*
|
|
12
|
+
* Proves:
|
|
13
|
+
* - with `controlPlaneMtls` injected, the create POST succeeds over mTLS and
|
|
14
|
+
* the sandbox round-trips an exec.
|
|
15
|
+
* - WITHOUT the client cert (no `controlPlaneMtls`, so the backend uses plain
|
|
16
|
+
* `fetch` against the https listener), create is rejected at the TLS layer.
|
|
17
|
+
*/
|
|
18
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
19
|
+
import { createServer as createHttpsServer, request as httpsRequest, } from 'node:https';
|
|
20
|
+
import { createRequire } from 'node:module';
|
|
21
|
+
import { createServer } from 'node:net';
|
|
22
|
+
import { tmpdir } from 'node:os';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
25
|
+
import { buildFirecrackerBackend } from '../index.js';
|
|
26
|
+
import { CA_CRT, CLIENT_CRT, CLIENT_KEY, ROGUE_CLIENT_CRT, ROGUE_CLIENT_KEY, SERVER_CRT, SERVER_KEY, } from './fixtures/mtls-pki.js';
|
|
27
|
+
const require_ = createRequire(import.meta.url);
|
|
28
|
+
let workDir;
|
|
29
|
+
let sockPath;
|
|
30
|
+
let agentServer;
|
|
31
|
+
let orchestrator;
|
|
32
|
+
let agent;
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
workDir = mkdtempSync(join(tmpdir(), 'fc-cp-mtls-'));
|
|
35
|
+
sockPath = join(workDir, 'agent.sock');
|
|
36
|
+
process.env.NAMZU_SANDBOX_WORKSPACE = workDir;
|
|
37
|
+
delete require_.cache[require_.resolve('../../../../agent/agent.cjs')];
|
|
38
|
+
agent = require_('../../../../agent/agent.cjs');
|
|
39
|
+
});
|
|
40
|
+
afterEach(async () => {
|
|
41
|
+
if (orchestrator) {
|
|
42
|
+
await new Promise((r) => orchestrator?.close(() => r()));
|
|
43
|
+
orchestrator = undefined;
|
|
44
|
+
}
|
|
45
|
+
if (agentServer) {
|
|
46
|
+
await new Promise((r) => agentServer?.close(() => r()));
|
|
47
|
+
agentServer = undefined;
|
|
48
|
+
}
|
|
49
|
+
rmSync(workDir, { recursive: true, force: true });
|
|
50
|
+
});
|
|
51
|
+
function startAgent() {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const s = createServer(agent.handleConnection);
|
|
54
|
+
s.on('error', reject);
|
|
55
|
+
s.listen(sockPath, () => resolve(s));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A loopback mTLS orchestrator. Requires + verifies a client cert chaining to
|
|
60
|
+
* the test CA, then serves the control-plane routes: `POST /sandboxes` returns
|
|
61
|
+
* a unix agent handle, `:delete` returns 204. Records calls so the test can
|
|
62
|
+
* assert the create round-trip.
|
|
63
|
+
*/
|
|
64
|
+
function startMtlsOrchestrator(handlePath) {
|
|
65
|
+
const calls = [];
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const server = createHttpsServer({
|
|
68
|
+
cert: SERVER_CRT,
|
|
69
|
+
key: SERVER_KEY,
|
|
70
|
+
ca: CA_CRT,
|
|
71
|
+
requestCert: true,
|
|
72
|
+
rejectUnauthorized: true,
|
|
73
|
+
minVersion: 'TLSv1.3',
|
|
74
|
+
}, (req, res) => {
|
|
75
|
+
const method = req.method ?? 'GET';
|
|
76
|
+
const url = req.url ?? '/';
|
|
77
|
+
calls.push({ method, url });
|
|
78
|
+
// Drain the body, then respond per route.
|
|
79
|
+
req.on('data', () => { });
|
|
80
|
+
req.on('end', () => {
|
|
81
|
+
if (method === 'POST' && url.endsWith('/sandboxes')) {
|
|
82
|
+
res.statusCode = 200;
|
|
83
|
+
res.setHeader('content-type', 'application/json');
|
|
84
|
+
res.end(JSON.stringify({
|
|
85
|
+
sandboxId: 'sbx_cp_mtls',
|
|
86
|
+
agent: { kind: 'unix', path: handlePath },
|
|
87
|
+
rootDir: workDir,
|
|
88
|
+
}));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (method === 'DELETE' && url.includes(':delete')) {
|
|
92
|
+
res.statusCode = 204;
|
|
93
|
+
res.end();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
res.statusCode = 500;
|
|
97
|
+
res.end('unexpected');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
server.on('error', reject);
|
|
101
|
+
server.listen(0, '127.0.0.1', () => {
|
|
102
|
+
const addr = server.address();
|
|
103
|
+
if (addr === null || typeof addr === 'string') {
|
|
104
|
+
reject(new Error('orchestrator: no TCP port'));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
resolve({ server, port: addr.port, calls });
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
describe('buildFirecrackerBackend (control-plane mTLS dial)', () => {
|
|
112
|
+
it('create POST succeeds over mTLS and round-trips an exec', async () => {
|
|
113
|
+
agentServer = await startAgent();
|
|
114
|
+
const orch = await startMtlsOrchestrator(sockPath);
|
|
115
|
+
orchestrator = orch.server;
|
|
116
|
+
const backend = buildFirecrackerBackend({
|
|
117
|
+
// An https:// endpoint over the (loopback stand-in for the) public hop.
|
|
118
|
+
orchestratorEndpoint: `https://127.0.0.1:${orch.port}/`,
|
|
119
|
+
getToken: async () => 'tok',
|
|
120
|
+
readyTimeoutMs: 5_000,
|
|
121
|
+
readyPollIntervalMs: 50,
|
|
122
|
+
// CONTROL-plane client material — injected by the consumer, never
|
|
123
|
+
// shipped by the orchestrator. Drives the node:https mTLS dial.
|
|
124
|
+
controlPlaneMtls: {
|
|
125
|
+
ca: CA_CRT,
|
|
126
|
+
cert: CLIENT_CRT,
|
|
127
|
+
key: CLIENT_KEY,
|
|
128
|
+
servername: 'sandbox.fc.internal',
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
const sandbox = await backend.create({ workingDirectory: workDir });
|
|
132
|
+
expect(sandbox.id).toBe('sbx_cp_mtls');
|
|
133
|
+
expect(sandbox.status).toBe('ready');
|
|
134
|
+
// The control-plane POST reached the mTLS orchestrator.
|
|
135
|
+
expect(orch.calls.some((c) => c.method === 'POST' && c.url.endsWith('/sandboxes'))).toBe(true);
|
|
136
|
+
// Exec over the vsock tunnel (the data plane), proving the whole flow.
|
|
137
|
+
const r = await sandbox.exec('/bin/sh', ['-c', 'echo hello-cp-mtls']);
|
|
138
|
+
expect(r.stdout).toContain('hello-cp-mtls');
|
|
139
|
+
// destroy DELETE also rides the mTLS control plane.
|
|
140
|
+
await sandbox.destroy();
|
|
141
|
+
expect(orch.calls.some((c) => c.method === 'DELETE' && c.url.includes(':delete'))).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
it('the backend without controlPlaneMtls cannot reach the mTLS orchestrator (plain fetch fails the handshake)', async () => {
|
|
144
|
+
agentServer = await startAgent();
|
|
145
|
+
const orch = await startMtlsOrchestrator(sockPath);
|
|
146
|
+
orchestrator = orch.server;
|
|
147
|
+
// No `controlPlaneMtls` → the backend uses plain `fetch`, which neither
|
|
148
|
+
// presents a client cert nor trusts the test CA, so the TLS handshake
|
|
149
|
+
// fails and create rejects BEFORE any route runs.
|
|
150
|
+
const backend = buildFirecrackerBackend({
|
|
151
|
+
orchestratorEndpoint: `https://127.0.0.1:${orch.port}/`,
|
|
152
|
+
getToken: async () => 'tok',
|
|
153
|
+
readyTimeoutMs: 2_000,
|
|
154
|
+
readyPollIntervalMs: 50,
|
|
155
|
+
});
|
|
156
|
+
await expect(backend.create({ workingDirectory: workDir })).rejects.toThrow(/failed to create microVM sandbox/);
|
|
157
|
+
expect(orch.calls.some((c) => c.method === 'POST' && c.url.endsWith('/sandboxes'))).toBe(false);
|
|
158
|
+
});
|
|
159
|
+
it("the orchestrator's requestCert rejects a client presenting NO cert (server-side proof)", async () => {
|
|
160
|
+
// Isolate the SERVER's requestCert+rejectUnauthorized from any client-side
|
|
161
|
+
// CA distrust: dial directly with node:https TRUSTING the server CA but
|
|
162
|
+
// presenting NO client cert. The handshake must be rejected by the server.
|
|
163
|
+
const orch = await startMtlsOrchestrator(sockPath);
|
|
164
|
+
orchestrator = orch.server;
|
|
165
|
+
const err = await new Promise((resolve) => {
|
|
166
|
+
const req = httpsRequest({
|
|
167
|
+
host: '127.0.0.1',
|
|
168
|
+
port: orch.port,
|
|
169
|
+
method: 'POST',
|
|
170
|
+
path: '/sandboxes',
|
|
171
|
+
ca: CA_CRT,
|
|
172
|
+
servername: 'sandbox.fc.internal',
|
|
173
|
+
}, () => resolve(undefined));
|
|
174
|
+
req.on('error', (e) => resolve(e));
|
|
175
|
+
req.end();
|
|
176
|
+
});
|
|
177
|
+
expect(err).toBeInstanceOf(Error);
|
|
178
|
+
expect(orch.calls.some((c) => c.method === 'POST')).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
it("the orchestrator's requestCert rejects a client cert from a DIFFERENT CA", async () => {
|
|
181
|
+
const orch = await startMtlsOrchestrator(sockPath);
|
|
182
|
+
orchestrator = orch.server;
|
|
183
|
+
const err = await new Promise((resolve) => {
|
|
184
|
+
const req = httpsRequest({
|
|
185
|
+
host: '127.0.0.1',
|
|
186
|
+
port: orch.port,
|
|
187
|
+
method: 'POST',
|
|
188
|
+
path: '/sandboxes',
|
|
189
|
+
ca: CA_CRT,
|
|
190
|
+
cert: ROGUE_CLIENT_CRT,
|
|
191
|
+
key: ROGUE_CLIENT_KEY,
|
|
192
|
+
servername: 'sandbox.fc.internal',
|
|
193
|
+
}, () => resolve(undefined));
|
|
194
|
+
req.on('error', (e) => resolve(e));
|
|
195
|
+
req.end();
|
|
196
|
+
});
|
|
197
|
+
expect(err).toBeInstanceOf(Error);
|
|
198
|
+
expect(orch.calls.some((c) => c.method === 'POST')).toBe(false);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
//# sourceMappingURL=control-plane-mtls.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-plane-mtls.test.js","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/control-plane-mtls.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Ring-0 mTLS test PKI + a loopback relay stand-in.
|
|
3
|
+
*
|
|
4
|
+
* A throwaway P-256 test PKI (CA + server leaf + client leaf + an unrelated
|
|
5
|
+
* rogue client) baked in as PEM constants — no openssl/forge at test time, so
|
|
6
|
+
* the package stays dependency-light. Minted offline:
|
|
7
|
+
* openssl ec/x509 self-signed CA + leaves
|
|
8
|
+
* (server SAN = DNS:sandbox.fc.internal, IP:127.0.0.1), far-future expiry.
|
|
9
|
+
* `ROGUE_*` chains to a DIFFERENT CA to prove `rejectUnauthorized` blocks it.
|
|
10
|
+
*
|
|
11
|
+
* Used by both transport.test.ts (the raw `kind:'mtls'` dialer arm) and
|
|
12
|
+
* backend.test.ts (the cert-INJECTION seam through `buildFirecrackerBackend`),
|
|
13
|
+
* so the PKI + relay harness lives in one place instead of per-test copies.
|
|
14
|
+
*/
|
|
15
|
+
import { type Server as TlsServer } from 'node:tls';
|
|
16
|
+
export declare const CA_CRT = "-----BEGIN CERTIFICATE-----\nMIIBjjCCATWgAwIBAgIUGXUtG14KQr4spNGW7rpfjZGoBIIwCgYIKoZIzj0EAwIw\nHDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP\nMjEyNjA1MjMwODMyNTJaMBwxGjAYBgNVBAMMEXZhbmRhbC1mYy10ZXN0LWNhMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5l+vjhjm/PX02D55n56EwelgvM1jrqQM\nZ+ezzvMmrZEBGWInvBND3z3kc6nv7snu6fHT2HHOyhwUNoLqmrIg/qNTMFEwHQYD\nVR0OBBYEFP0M8/KZY1ovxyGDci5iuoYXcmZgMB8GA1UdIwQYMBaAFP0M8/KZY1ov\nxyGDci5iuoYXcmZgMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIg\nC0xtFDASnwsOYT0GiZwzYWTOBfgmjDWK7ANXQQFNTh4CICVLQwq5eLy3424drEHk\n5Ol/FNKVZcGRjE96rB0mRUOp\n-----END CERTIFICATE-----\n";
|
|
17
|
+
export declare const SERVER_CRT = "-----BEGIN CERTIFICATE-----\nMIIBsDCCAVWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1MwCgYIKoZIzj0EAwIw\nHDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP\nMjEyNjA1MjMwODMyNTJaMBIxEDAOBgNVBAMMB2ZjLWhvc3QwWTATBgcqhkjOPQIB\nBggqhkjOPQMBBwNCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMBfmonVb7dUhM0ZWpo\nePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6o30wezAkBgNVHREEHTAbghNz\nYW5kYm94LmZjLmludGVybmFshwR/AAABMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0G\nA1UdDgQWBBRXHU1vlX7WvqzcbaNxRxV4f3gfDDAfBgNVHSMEGDAWgBT9DPPymWNa\nL8chg3IuYrqGF3JmYDAKBggqhkjOPQQDAgNJADBGAiEAlqzKqgBf5hxJqd26QwcY\nn3cvEKi4f2BSLe1Rfzr5oSoCIQD0izUOJXLNvmac9cMgV0HvkftBerDKFOcGeGTN\ng3Eunw==\n-----END CERTIFICATE-----\n";
|
|
18
|
+
export declare const SERVER_KEY = "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/ROnYXIkMKnipbLt\nJnFEwXAifgeOv9TGLcK2RojE7jmhRANCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMB\nfmonVb7dUhM0ZWpoePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6\n-----END PRIVATE KEY-----\n";
|
|
19
|
+
export declare const CLIENT_CRT = "-----BEGIN CERTIFICATE-----\nMIIBjjCCATWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1QwCgYIKoZIzj0EAwIw\nHDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP\nMjEyNjA1MjMwODMyNTJaMBgxFjAUBgNVBAMMDWNhLXZhbmRhbC1hcHAwWTATBgcq\nhkjOPQIBBggqhkjOPQMBBwNCAASlCMCwjtrQUicWcWsO29R5S7fzjMbbxXvDh8/K\nw57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXko1cwVTATBgNVHSUE\nDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQU2cxDCNrlVkk4ODs6ZPrkC6GzHjkwHwYD\nVR0jBBgwFoAU/Qzz8pljWi/HIYNyLmK6hhdyZmAwCgYIKoZIzj0EAwIDRwAwRAIg\nRghqArNm3bXnWnRi+jkEEJa8mRb2z0Wj4G7SIhtMurUCIBQSllVtICgZB9hvcM0D\nd24fcW4nlfvaZJMJ6dRC1Wle\n-----END CERTIFICATE-----\n";
|
|
20
|
+
export declare const CLIENT_KEY = "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaamj/ycrEuPqpiC2\nIhAYx/M5iN4t4P+B17V4GO54Nb2hRANCAASlCMCwjtrQUicWcWsO29R5S7fzjMbb\nxXvDh8/Kw57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXk\n-----END PRIVATE KEY-----\n";
|
|
21
|
+
export declare const ROGUE_CLIENT_CRT = "-----BEGIN CERTIFICATE-----\nMIIBhjCCASugAwIBAgIUbAYOlW4PQGyXjjRsjCPy62EHUmIwCgYIKoZIzj0EAwIw\nEzERMA8GA1UEAwwIcm9ndWUtY2EwIBcNMjYwNjE2MDgzMjUyWhgPMjEyNjA1MjMw\nODMyNTJaMBcxFTATBgNVBAMMDHJvZ3VlLWNsaWVudDBZMBMGByqGSM49AgEGCCqG\nSM49AwEHA0IABOPSzdzQTQz3M5CDHLVPguvHd10ncaDV9t4zKUy/PCE+U7GTJwN2\nTtypGnmYEahbcl45j94hwu495P5VbR5ohb6jVzBVMBMGA1UdJQQMMAoGCCsGAQUF\nBwMCMB0GA1UdDgQWBBTf0woauniche3/ps77+Kd0dsbbSDAfBgNVHSMEGDAWgBSX\nYu0IJlPxi79Gyi5hR1IfS/sqyzAKBggqhkjOPQQDAgNJADBGAiEAxD4N4XWtaHPJ\nyaCOzQP0e5RRyNst3QrhH0NSMyPw89wCIQC+bezLX97TuV1sId53Bo1l9j1TSOMa\nEZotN/Wsq6L+qw==\n-----END CERTIFICATE-----\n";
|
|
22
|
+
export declare const ROGUE_CLIENT_KEY = "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR6fGq27O9eT/hi0Q\nc+L5+lSm5fbDEghVJCo6k7HrG62hRANCAATj0s3c0E0M9zOQgxy1T4Lrx3ddJ3Gg\n1fbeMylMvzwhPlOxkycDdk7cqRp5mBGoW3JeOY/eIcLuPeT+VW0eaIW+\n-----END PRIVATE KEY-----\n";
|
|
23
|
+
export interface RelayHandle {
|
|
24
|
+
readonly server: TlsServer;
|
|
25
|
+
readonly port: number;
|
|
26
|
+
/** sandboxId from the first connection's `SANDBOX <id>` preamble. */
|
|
27
|
+
preamble(): Promise<string>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A loopback stand-in for the per-FC-host mTLS relay.
|
|
31
|
+
*
|
|
32
|
+
* Terminates mTLS (requestCert + rejectUnauthorized + CA pin), reads the
|
|
33
|
+
* `SANDBOX <id>\n` routing preamble line, then bridges the rest of the TLS
|
|
34
|
+
* stream verbatim to a FRESH `net.connect` to `agentSockPath` (the
|
|
35
|
+
* unix-socket-backed real agent) — exactly the dumb byte-pump the production
|
|
36
|
+
* relay is. It does NOT speak framing itself and does NOT send an ack line.
|
|
37
|
+
*/
|
|
38
|
+
export declare function startMtlsRelay(agentSockPath: string, listenPort?: number): Promise<RelayHandle>;
|
|
39
|
+
//# sourceMappingURL=mtls-pki.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mtls-pki.d.ts","sourceRoot":"","sources":["../../../../../src/backends/firecracker/__tests__/fixtures/mtls-pki.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAkB,KAAK,MAAM,IAAI,SAAS,EAAmC,MAAM,UAAU,CAAA;AAEpG,eAAO,MAAM,MAAM,umBAWlB,CAAA;AAED,eAAO,MAAM,UAAU,ypBAYtB,CAAA;AAED,eAAO,MAAM,UAAU,2PAKtB,CAAA;AAED,eAAO,MAAM,UAAU,umBAWtB,CAAA;AAED,eAAO,MAAM,UAAU,2PAKtB,CAAA;AAED,eAAO,MAAM,gBAAgB,+lBAW5B,CAAA;AAED,eAAO,MAAM,gBAAgB,2PAK5B,CAAA;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAC3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,SAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAyD1F"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Ring-0 mTLS test PKI + a loopback relay stand-in.
|
|
3
|
+
*
|
|
4
|
+
* A throwaway P-256 test PKI (CA + server leaf + client leaf + an unrelated
|
|
5
|
+
* rogue client) baked in as PEM constants — no openssl/forge at test time, so
|
|
6
|
+
* the package stays dependency-light. Minted offline:
|
|
7
|
+
* openssl ec/x509 self-signed CA + leaves
|
|
8
|
+
* (server SAN = DNS:sandbox.fc.internal, IP:127.0.0.1), far-future expiry.
|
|
9
|
+
* `ROGUE_*` chains to a DIFFERENT CA to prove `rejectUnauthorized` blocks it.
|
|
10
|
+
*
|
|
11
|
+
* Used by both transport.test.ts (the raw `kind:'mtls'` dialer arm) and
|
|
12
|
+
* backend.test.ts (the cert-INJECTION seam through `buildFirecrackerBackend`),
|
|
13
|
+
* so the PKI + relay harness lives in one place instead of per-test copies.
|
|
14
|
+
*/
|
|
15
|
+
import { connect as netConnect } from 'node:net';
|
|
16
|
+
import { createServer as createTlsServer } from 'node:tls';
|
|
17
|
+
export const CA_CRT = `-----BEGIN CERTIFICATE-----
|
|
18
|
+
MIIBjjCCATWgAwIBAgIUGXUtG14KQr4spNGW7rpfjZGoBIIwCgYIKoZIzj0EAwIw
|
|
19
|
+
HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
|
|
20
|
+
MjEyNjA1MjMwODMyNTJaMBwxGjAYBgNVBAMMEXZhbmRhbC1mYy10ZXN0LWNhMFkw
|
|
21
|
+
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5l+vjhjm/PX02D55n56EwelgvM1jrqQM
|
|
22
|
+
Z+ezzvMmrZEBGWInvBND3z3kc6nv7snu6fHT2HHOyhwUNoLqmrIg/qNTMFEwHQYD
|
|
23
|
+
VR0OBBYEFP0M8/KZY1ovxyGDci5iuoYXcmZgMB8GA1UdIwQYMBaAFP0M8/KZY1ov
|
|
24
|
+
xyGDci5iuoYXcmZgMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIg
|
|
25
|
+
C0xtFDASnwsOYT0GiZwzYWTOBfgmjDWK7ANXQQFNTh4CICVLQwq5eLy3424drEHk
|
|
26
|
+
5Ol/FNKVZcGRjE96rB0mRUOp
|
|
27
|
+
-----END CERTIFICATE-----
|
|
28
|
+
`;
|
|
29
|
+
export const SERVER_CRT = `-----BEGIN CERTIFICATE-----
|
|
30
|
+
MIIBsDCCAVWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1MwCgYIKoZIzj0EAwIw
|
|
31
|
+
HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
|
|
32
|
+
MjEyNjA1MjMwODMyNTJaMBIxEDAOBgNVBAMMB2ZjLWhvc3QwWTATBgcqhkjOPQIB
|
|
33
|
+
BggqhkjOPQMBBwNCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMBfmonVb7dUhM0ZWpo
|
|
34
|
+
ePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6o30wezAkBgNVHREEHTAbghNz
|
|
35
|
+
YW5kYm94LmZjLmludGVybmFshwR/AAABMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0G
|
|
36
|
+
A1UdDgQWBBRXHU1vlX7WvqzcbaNxRxV4f3gfDDAfBgNVHSMEGDAWgBT9DPPymWNa
|
|
37
|
+
L8chg3IuYrqGF3JmYDAKBggqhkjOPQQDAgNJADBGAiEAlqzKqgBf5hxJqd26QwcY
|
|
38
|
+
n3cvEKi4f2BSLe1Rfzr5oSoCIQD0izUOJXLNvmac9cMgV0HvkftBerDKFOcGeGTN
|
|
39
|
+
g3Eunw==
|
|
40
|
+
-----END CERTIFICATE-----
|
|
41
|
+
`;
|
|
42
|
+
export const SERVER_KEY = `-----BEGIN PRIVATE KEY-----
|
|
43
|
+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/ROnYXIkMKnipbLt
|
|
44
|
+
JnFEwXAifgeOv9TGLcK2RojE7jmhRANCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMB
|
|
45
|
+
fmonVb7dUhM0ZWpoePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6
|
|
46
|
+
-----END PRIVATE KEY-----
|
|
47
|
+
`;
|
|
48
|
+
export const CLIENT_CRT = `-----BEGIN CERTIFICATE-----
|
|
49
|
+
MIIBjjCCATWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1QwCgYIKoZIzj0EAwIw
|
|
50
|
+
HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
|
|
51
|
+
MjEyNjA1MjMwODMyNTJaMBgxFjAUBgNVBAMMDWNhLXZhbmRhbC1hcHAwWTATBgcq
|
|
52
|
+
hkjOPQIBBggqhkjOPQMBBwNCAASlCMCwjtrQUicWcWsO29R5S7fzjMbbxXvDh8/K
|
|
53
|
+
w57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXko1cwVTATBgNVHSUE
|
|
54
|
+
DDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQU2cxDCNrlVkk4ODs6ZPrkC6GzHjkwHwYD
|
|
55
|
+
VR0jBBgwFoAU/Qzz8pljWi/HIYNyLmK6hhdyZmAwCgYIKoZIzj0EAwIDRwAwRAIg
|
|
56
|
+
RghqArNm3bXnWnRi+jkEEJa8mRb2z0Wj4G7SIhtMurUCIBQSllVtICgZB9hvcM0D
|
|
57
|
+
d24fcW4nlfvaZJMJ6dRC1Wle
|
|
58
|
+
-----END CERTIFICATE-----
|
|
59
|
+
`;
|
|
60
|
+
export const CLIENT_KEY = `-----BEGIN PRIVATE KEY-----
|
|
61
|
+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaamj/ycrEuPqpiC2
|
|
62
|
+
IhAYx/M5iN4t4P+B17V4GO54Nb2hRANCAASlCMCwjtrQUicWcWsO29R5S7fzjMbb
|
|
63
|
+
xXvDh8/Kw57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXk
|
|
64
|
+
-----END PRIVATE KEY-----
|
|
65
|
+
`;
|
|
66
|
+
export const ROGUE_CLIENT_CRT = `-----BEGIN CERTIFICATE-----
|
|
67
|
+
MIIBhjCCASugAwIBAgIUbAYOlW4PQGyXjjRsjCPy62EHUmIwCgYIKoZIzj0EAwIw
|
|
68
|
+
EzERMA8GA1UEAwwIcm9ndWUtY2EwIBcNMjYwNjE2MDgzMjUyWhgPMjEyNjA1MjMw
|
|
69
|
+
ODMyNTJaMBcxFTATBgNVBAMMDHJvZ3VlLWNsaWVudDBZMBMGByqGSM49AgEGCCqG
|
|
70
|
+
SM49AwEHA0IABOPSzdzQTQz3M5CDHLVPguvHd10ncaDV9t4zKUy/PCE+U7GTJwN2
|
|
71
|
+
TtypGnmYEahbcl45j94hwu495P5VbR5ohb6jVzBVMBMGA1UdJQQMMAoGCCsGAQUF
|
|
72
|
+
BwMCMB0GA1UdDgQWBBTf0woauniche3/ps77+Kd0dsbbSDAfBgNVHSMEGDAWgBSX
|
|
73
|
+
Yu0IJlPxi79Gyi5hR1IfS/sqyzAKBggqhkjOPQQDAgNJADBGAiEAxD4N4XWtaHPJ
|
|
74
|
+
yaCOzQP0e5RRyNst3QrhH0NSMyPw89wCIQC+bezLX97TuV1sId53Bo1l9j1TSOMa
|
|
75
|
+
EZotN/Wsq6L+qw==
|
|
76
|
+
-----END CERTIFICATE-----
|
|
77
|
+
`;
|
|
78
|
+
export const ROGUE_CLIENT_KEY = `-----BEGIN PRIVATE KEY-----
|
|
79
|
+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR6fGq27O9eT/hi0Q
|
|
80
|
+
c+L5+lSm5fbDEghVJCo6k7HrG62hRANCAATj0s3c0E0M9zOQgxy1T4Lrx3ddJ3Gg
|
|
81
|
+
1fbeMylMvzwhPlOxkycDdk7cqRp5mBGoW3JeOY/eIcLuPeT+VW0eaIW+
|
|
82
|
+
-----END PRIVATE KEY-----
|
|
83
|
+
`;
|
|
84
|
+
/**
|
|
85
|
+
* A loopback stand-in for the per-FC-host mTLS relay.
|
|
86
|
+
*
|
|
87
|
+
* Terminates mTLS (requestCert + rejectUnauthorized + CA pin), reads the
|
|
88
|
+
* `SANDBOX <id>\n` routing preamble line, then bridges the rest of the TLS
|
|
89
|
+
* stream verbatim to a FRESH `net.connect` to `agentSockPath` (the
|
|
90
|
+
* unix-socket-backed real agent) — exactly the dumb byte-pump the production
|
|
91
|
+
* relay is. It does NOT speak framing itself and does NOT send an ack line.
|
|
92
|
+
*/
|
|
93
|
+
export function startMtlsRelay(agentSockPath, listenPort = 0) {
|
|
94
|
+
let resolvePreamble;
|
|
95
|
+
const preamble = new Promise((r) => {
|
|
96
|
+
resolvePreamble = r;
|
|
97
|
+
});
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
const server = createTlsServer({
|
|
100
|
+
requestCert: true,
|
|
101
|
+
rejectUnauthorized: true,
|
|
102
|
+
ca: CA_CRT,
|
|
103
|
+
cert: SERVER_CRT,
|
|
104
|
+
key: SERVER_KEY,
|
|
105
|
+
minVersion: 'TLSv1.3',
|
|
106
|
+
}, (tlsSock) => {
|
|
107
|
+
let pre = Buffer.alloc(0);
|
|
108
|
+
const onPreambleData = (chunk) => {
|
|
109
|
+
pre = Buffer.concat([pre, chunk]);
|
|
110
|
+
const nl = pre.indexOf(0x0a);
|
|
111
|
+
if (nl < 0)
|
|
112
|
+
return;
|
|
113
|
+
tlsSock.removeListener('data', onPreambleData);
|
|
114
|
+
tlsSock.pause();
|
|
115
|
+
const line = pre.subarray(0, nl).toString('utf8');
|
|
116
|
+
const rest = pre.subarray(nl + 1);
|
|
117
|
+
if (rest.length > 0)
|
|
118
|
+
tlsSock.unshift(rest);
|
|
119
|
+
const m = /^SANDBOX (.+)$/.exec(line);
|
|
120
|
+
const id = m?.[1];
|
|
121
|
+
if (id === undefined) {
|
|
122
|
+
tlsSock.destroy();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
resolvePreamble(id);
|
|
126
|
+
// 1 inbound mTLS conn -> 1 FRESH local agent connect (the
|
|
127
|
+
// resume-survival invariant the relay must preserve).
|
|
128
|
+
const upstream = netConnect({ path: agentSockPath });
|
|
129
|
+
upstream.on('error', () => tlsSock.destroy());
|
|
130
|
+
tlsSock.on('error', () => upstream.destroy());
|
|
131
|
+
upstream.once('connect', () => {
|
|
132
|
+
tlsSock.pipe(upstream);
|
|
133
|
+
upstream.pipe(tlsSock);
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
tlsSock.on('data', onPreambleData);
|
|
137
|
+
});
|
|
138
|
+
server.on('error', reject);
|
|
139
|
+
server.listen(listenPort, '127.0.0.1', () => {
|
|
140
|
+
const addr = server.address();
|
|
141
|
+
if (addr === null || typeof addr === 'string') {
|
|
142
|
+
reject(new Error('relay: no TCP port'));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
resolve({ server, port: addr.port, preamble: () => preamble });
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=mtls-pki.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mtls-pki.js","sourceRoot":"","sources":["../../../../../src/backends/firecracker/__tests__/fixtures/mtls-pki.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.test.d.ts","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/protocol.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit-pins the shared NDJSON codec the vsock + HTTP transports both
|
|
3
|
+
* speak, and the `pickBackend` routing for `microvm:self-hosted`.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import { SandboxBackendNotImplementedError, createSandboxProvider } from '../../../index.js';
|
|
7
|
+
import { ExecResultAccumulator, parseExecLine } from '../protocol.js';
|
|
8
|
+
describe('ExecResultAccumulator', () => {
|
|
9
|
+
it('accumulates stdout/stderr deltas and captures the terminal result', () => {
|
|
10
|
+
const acc = new ExecResultAccumulator(0);
|
|
11
|
+
expect(acc.push({ type: 'stdout_delta', data: 'a' })).toBe(false);
|
|
12
|
+
expect(acc.push({ type: 'stdout_delta', data: 'b' })).toBe(false);
|
|
13
|
+
expect(acc.push({ type: 'stderr_delta', data: 'E' })).toBe(false);
|
|
14
|
+
expect(acc.done).toBe(false);
|
|
15
|
+
expect(acc.push({ type: 'result', exitCode: 0, timedOut: false })).toBe(true);
|
|
16
|
+
expect(acc.done).toBe(true);
|
|
17
|
+
const r = acc.finish();
|
|
18
|
+
expect(r.stdout).toBe('ab');
|
|
19
|
+
expect(r.stderr).toBe('E');
|
|
20
|
+
expect(r.exitCode).toBe(0);
|
|
21
|
+
expect(r.timedOut).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
it('throws on an error event (docker loop parity)', () => {
|
|
24
|
+
const acc = new ExecResultAccumulator(0);
|
|
25
|
+
expect(() => acc.push({ type: 'error', error: 'boom' })).toThrow('boom');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('parseExecLine', () => {
|
|
29
|
+
it('parses a valid NDJSON line', () => {
|
|
30
|
+
expect(parseExecLine('{"type":"stdout_delta","data":"x"}')).toEqual({
|
|
31
|
+
type: 'stdout_delta',
|
|
32
|
+
data: 'x',
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it('returns undefined for blank or malformed lines (SyntaxError swallow)', () => {
|
|
36
|
+
expect(parseExecLine('')).toBeUndefined();
|
|
37
|
+
expect(parseExecLine(' ')).toBeUndefined();
|
|
38
|
+
expect(parseExecLine('{not json')).toBeUndefined();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('pickBackend — microvm:self-hosted', () => {
|
|
42
|
+
it('builds the firecracker backend when orchestratorEndpoint + getToken are present', () => {
|
|
43
|
+
const provider = createSandboxProvider({
|
|
44
|
+
backend: {
|
|
45
|
+
tier: 'microvm',
|
|
46
|
+
service: 'self-hosted',
|
|
47
|
+
firecrackerBinary: '/usr/bin/firecracker',
|
|
48
|
+
kernelImage: '/golden/vmlinux',
|
|
49
|
+
rootfsImage: '/golden/rootfs.ext4',
|
|
50
|
+
orchestratorEndpoint: 'https://orchestrator.test',
|
|
51
|
+
getToken: async () => 'tok',
|
|
52
|
+
template: 'golden-rev-1',
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
expect(provider.id).toContain('microvm');
|
|
56
|
+
expect(provider.id).toContain('firecracker');
|
|
57
|
+
expect(provider.name).toContain('microvm:self-hosted');
|
|
58
|
+
});
|
|
59
|
+
it('still throws for the legacy local-containerd self-hosted shape (no orchestrator)', () => {
|
|
60
|
+
expect(() => createSandboxProvider({
|
|
61
|
+
backend: {
|
|
62
|
+
tier: 'microvm',
|
|
63
|
+
service: 'self-hosted',
|
|
64
|
+
firecrackerBinary: '/usr/bin/firecracker',
|
|
65
|
+
kernelImage: '/k',
|
|
66
|
+
rootfsImage: '/r',
|
|
67
|
+
},
|
|
68
|
+
})).toThrow(SandboxBackendNotImplementedError);
|
|
69
|
+
});
|
|
70
|
+
it('still throws for microvm:e2b and microvm:fly-machines', () => {
|
|
71
|
+
expect(() => createSandboxProvider({ backend: { tier: 'microvm', service: 'e2b', apiKey: 'k' } })).toThrow(SandboxBackendNotImplementedError);
|
|
72
|
+
expect(() => createSandboxProvider({
|
|
73
|
+
backend: { tier: 'microvm', service: 'fly-machines', apiToken: 't', app: 'a', image: 'i' },
|
|
74
|
+
})).toThrow(SandboxBackendNotImplementedError);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=protocol.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/protocol.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loopback transport round-trip tests for the Firecracker vsock path.
|
|
3
|
+
*
|
|
4
|
+
* These prove the NEW transport (host dialer ↔ in-VM agent) over a
|
|
5
|
+
* **unix-socket stand-in** — the faithful local peer for AF_VSOCK,
|
|
6
|
+
* because the production vsock path also terminates on a host
|
|
7
|
+
* unix socket (see `transport.ts` docblock). The peer is the REAL
|
|
8
|
+
* `agent/agent.cjs` connection handler (its spawn/jail + NDJSON shapes
|
|
9
|
+
* verbatim), driven in-process over a temp unix socket; the client is
|
|
10
|
+
* the REAL {@link VsockAgentTransport}. So one test exercises:
|
|
11
|
+
* - exec → streamed stdout/stderr/result NDJSON, accumulated;
|
|
12
|
+
* - writeFile / readFile → base64 round-trip through the jail;
|
|
13
|
+
* - a simulated resume (server torn down + re-listened) survived by
|
|
14
|
+
* the dialer's connect-retry budget — the FC #4713 invariant.
|
|
15
|
+
*
|
|
16
|
+
* No docker, no Azure, no AF_VSOCK kernel support required: pure
|
|
17
|
+
* loopback, safe in CI.
|
|
18
|
+
*/
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=transport.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.test.d.ts","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/transport.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
|