@namzu/sandbox 2.0.2 → 3.0.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 +84 -0
- package/README.md +62 -1
- package/dist/backends/docker/index.d.ts +26 -1
- package/dist/backends/docker/index.d.ts.map +1 -1
- package/dist/backends/docker/index.js +20 -7
- package/dist/backends/docker/index.js.map +1 -1
- package/dist/egress/address.d.ts +75 -0
- package/dist/egress/address.d.ts.map +1 -0
- package/dist/egress/address.js +289 -0
- package/dist/egress/address.js.map +1 -0
- package/dist/egress/index.d.ts +2 -0
- package/dist/egress/index.d.ts.map +1 -1
- package/dist/egress/index.js +1 -0
- package/dist/egress/index.js.map +1 -1
- package/dist/egress/proxy.d.ts +41 -0
- package/dist/egress/proxy.d.ts.map +1 -1
- package/dist/egress/proxy.js +83 -2
- package/dist/egress/proxy.js.map +1 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +12 -2
- package/src/backends/docker/index.ts +45 -8
- package/src/egress/address.ts +366 -0
- package/src/egress/index.ts +7 -0
- package/src/egress/proxy.ts +106 -2
- package/src/index.ts +18 -0
- package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.d.ts +0 -2
- package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.d.ts.map +0 -1
- package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.js +0 -61
- package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.js.map +0 -1
- package/dist/backends/docker/__tests__/hardening.test.d.ts +0 -2
- package/dist/backends/docker/__tests__/hardening.test.d.ts.map +0 -1
- package/dist/backends/docker/__tests__/hardening.test.js +0 -32
- package/dist/backends/docker/__tests__/hardening.test.js.map +0 -1
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts +0 -40
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts.map +0 -1
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js +0 -157
- package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js.map +0 -1
- package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.d.ts +0 -16
- package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.js +0 -37
- package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.js.map +0 -1
- package/dist/backends/firecracker/__tests__/backend.test.d.ts +0 -13
- package/dist/backends/firecracker/__tests__/backend.test.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/backend.test.js +0 -361
- package/dist/backends/firecracker/__tests__/backend.test.js.map +0 -1
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts +0 -19
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js +0 -209
- package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js.map +0 -1
- package/dist/backends/firecracker/__tests__/egress-policy.test.d.ts +0 -2
- package/dist/backends/firecracker/__tests__/egress-policy.test.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/egress-policy.test.js +0 -67
- package/dist/backends/firecracker/__tests__/egress-policy.test.js.map +0 -1
- package/dist/backends/firecracker/__tests__/fixtures/ipc-path.d.ts +0 -21
- package/dist/backends/firecracker/__tests__/fixtures/ipc-path.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/fixtures/ipc-path.js +0 -30
- package/dist/backends/firecracker/__tests__/fixtures/ipc-path.js.map +0 -1
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts +0 -39
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js +0 -149
- package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js.map +0 -1
- package/dist/backends/firecracker/__tests__/protocol.test.d.ts +0 -6
- package/dist/backends/firecracker/__tests__/protocol.test.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/protocol.test.js +0 -67
- package/dist/backends/firecracker/__tests__/protocol.test.js.map +0 -1
- package/dist/backends/firecracker/__tests__/transport.test.d.ts +0 -20
- package/dist/backends/firecracker/__tests__/transport.test.d.ts.map +0 -1
- package/dist/backends/firecracker/__tests__/transport.test.js +0 -457
- package/dist/backends/firecracker/__tests__/transport.test.js.map +0 -1
- package/dist/egress/__tests__/allowlist.test.d.ts +0 -2
- package/dist/egress/__tests__/allowlist.test.d.ts.map +0 -1
- package/dist/egress/__tests__/allowlist.test.js +0 -85
- package/dist/egress/__tests__/allowlist.test.js.map +0 -1
- package/dist/egress/__tests__/proxy.test.d.ts +0 -2
- package/dist/egress/__tests__/proxy.test.d.ts.map +0 -1
- package/dist/egress/__tests__/proxy.test.js +0 -177
- package/dist/egress/__tests__/proxy.test.js.map +0 -1
- package/dist/index.test.d.ts +0 -28
- package/dist/index.test.d.ts.map +0 -1
- package/dist/index.test.js +0 -649
- package/dist/index.test.js.map +0 -1
- package/src/backends/aci-standby-pool/__tests__/unenforceable-controls.test.ts +0 -69
- package/src/backends/docker/__tests__/hardening.test.ts +0 -43
- package/src/backends/docker/__tests__/leaf-permissions.smoke.test.ts +0 -169
- package/src/backends/firecracker/__tests__/agent-timeout-clamp.test.ts +0 -48
- package/src/backends/firecracker/__tests__/backend.test.ts +0 -429
- package/src/backends/firecracker/__tests__/control-plane-mtls.test.ts +0 -261
- package/src/backends/firecracker/__tests__/egress-policy.test.ts +0 -91
- package/src/backends/firecracker/__tests__/fixtures/ipc-path.ts +0 -31
- package/src/backends/firecracker/__tests__/fixtures/mtls-pki.ts +0 -166
- package/src/backends/firecracker/__tests__/protocol.test.ts +0 -75
- package/src/backends/firecracker/__tests__/transport.test.ts +0 -534
- package/src/egress/__tests__/allowlist.test.ts +0 -103
- package/src/egress/__tests__/proxy.test.ts +0 -212
- package/src/index.test.ts +0 -709
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { resolveEgressAllowlist } from '../index.js';
|
|
3
|
-
/**
|
|
4
|
-
* Omitting the allowlist means "no allowlist to apply", which the
|
|
5
|
-
* orchestrator reads as unrestricted. That makes omission the encoding for
|
|
6
|
-
* `allow-all` and only for `allow-all`.
|
|
7
|
-
*
|
|
8
|
-
* `resolver` used to be omitted too — so two opposite intentions shared one
|
|
9
|
-
* encoding, the tenant-scoped allowlist the variant exists for was silently
|
|
10
|
-
* absent, and the callback that would have produced it was never called
|
|
11
|
-
* anywhere in the repo. Whichever way the orchestrator reads an omitted
|
|
12
|
-
* field, one of the two variants was always mis-enforced, and the one that
|
|
13
|
-
* failed OPEN was the one whose entire purpose is restriction.
|
|
14
|
-
*/
|
|
15
|
-
const opts = (egress) => ({
|
|
16
|
-
workingDirectory: '/w',
|
|
17
|
-
...(egress ? { egress } : {}),
|
|
18
|
-
});
|
|
19
|
-
describe('each policy gets its own encoding', () => {
|
|
20
|
-
it('allow-all omits the field', async () => {
|
|
21
|
-
expect(await resolveEgressAllowlist(opts({ kind: 'allow-all' }))).toBeUndefined();
|
|
22
|
-
});
|
|
23
|
-
it('deny-all sends an explicitly empty list, not an absent one', async () => {
|
|
24
|
-
expect(await resolveEgressAllowlist(opts({ kind: 'deny-all' }))).toEqual([]);
|
|
25
|
-
});
|
|
26
|
-
it('static forwards the hosts as given', async () => {
|
|
27
|
-
expect(await resolveEgressAllowlist(opts({ kind: 'static', allowedHosts: ['a.example'] }))).toEqual(['a.example']);
|
|
28
|
-
});
|
|
29
|
-
it('resolver calls the callback and forwards what it returned', async () => {
|
|
30
|
-
const resolve = vi.fn(async () => ['tenant-a.example', 'tenant-b.example']);
|
|
31
|
-
expect(await resolveEgressAllowlist(opts({ kind: 'resolver', resolve }))).toEqual([
|
|
32
|
-
'tenant-a.example',
|
|
33
|
-
'tenant-b.example',
|
|
34
|
-
]);
|
|
35
|
-
// The callback IS the feature. It was declared and never invoked.
|
|
36
|
-
expect(resolve).toHaveBeenCalledOnce();
|
|
37
|
-
});
|
|
38
|
-
it('never encodes resolver the same way as allow-all', async () => {
|
|
39
|
-
const restrictive = await resolveEgressAllowlist(opts({ kind: 'resolver', resolve: async () => ['only-this.example'] }));
|
|
40
|
-
const unrestricted = await resolveEgressAllowlist(opts({ kind: 'allow-all' }));
|
|
41
|
-
expect(restrictive).not.toEqual(unrestricted);
|
|
42
|
-
});
|
|
43
|
-
it('sends an empty resolver result as a real deny-all', async () => {
|
|
44
|
-
// An empty allowlist is a decision, not an absence. Collapsing it
|
|
45
|
-
// back to omission would turn "this tenant may reach nothing" into
|
|
46
|
-
// "this tenant may reach everything".
|
|
47
|
-
expect(await resolveEgressAllowlist(opts({ kind: 'resolver', resolve: async () => [] }))).toEqual([]);
|
|
48
|
-
});
|
|
49
|
-
it('omits the field when the host set no policy at all', async () => {
|
|
50
|
-
expect(await resolveEgressAllowlist(opts())).toBeUndefined();
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
describe('an unknown policy', () => {
|
|
54
|
-
it('refuses rather than defaulting to unrestricted', async () => {
|
|
55
|
-
await expect(resolveEgressAllowlist(opts({ kind: 'something-new' }))).rejects.toThrow(/Refusing rather than defaulting to unrestricted/);
|
|
56
|
-
});
|
|
57
|
-
it('propagates a failing resolver instead of falling back to open', async () => {
|
|
58
|
-
// A resolver that cannot answer must not become "allow everything".
|
|
59
|
-
await expect(resolveEgressAllowlist(opts({
|
|
60
|
-
kind: 'resolver',
|
|
61
|
-
resolve: async () => {
|
|
62
|
-
throw new Error('directory unreachable');
|
|
63
|
-
},
|
|
64
|
-
}))).rejects.toThrow('directory unreachable');
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
//# sourceMappingURL=egress-policy.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"egress-policy.test.js","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/egress-policy.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A local IPC address Node can actually `listen()` on, for the current OS.
|
|
3
|
-
*
|
|
4
|
-
* These suites bind a loopback agent over a Unix domain socket in a temp
|
|
5
|
-
* directory. Windows supports `AF_UNIX` at the OS level, but Node's `net`
|
|
6
|
-
* server does not bind filesystem sockets there — it wants a **named
|
|
7
|
-
* pipe**, so every one of these tests failed with
|
|
8
|
-
* `listen EACCES: permission denied …\agent.sock` and the whole
|
|
9
|
-
* `@namzu/sandbox` suite has been red for Windows contributors.
|
|
10
|
-
*
|
|
11
|
-
* The transport under test is address-agnostic: it is handed a path and
|
|
12
|
-
* connects to it. So the fix belongs in the fixture, not the driver.
|
|
13
|
-
*/
|
|
14
|
-
export declare function localIpcPath(workDir: string, name?: string): string;
|
|
15
|
-
/**
|
|
16
|
-
* True when the socket address lives on disk and can be cleaned up with
|
|
17
|
-
* the temp directory. Named pipes disappear with the process that owns
|
|
18
|
-
* them, so there is nothing to unlink.
|
|
19
|
-
*/
|
|
20
|
-
export declare const IPC_IS_FILESYSTEM_PATH: boolean;
|
|
21
|
-
//# sourceMappingURL=ipc-path.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ipc-path.d.ts","sourceRoot":"","sources":["../../../../../src/backends/firecracker/__tests__/fixtures/ipc-path.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAU,GAAG,MAAM,CAOpE;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,SAA+B,CAAA"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
/**
|
|
4
|
-
* A local IPC address Node can actually `listen()` on, for the current OS.
|
|
5
|
-
*
|
|
6
|
-
* These suites bind a loopback agent over a Unix domain socket in a temp
|
|
7
|
-
* directory. Windows supports `AF_UNIX` at the OS level, but Node's `net`
|
|
8
|
-
* server does not bind filesystem sockets there — it wants a **named
|
|
9
|
-
* pipe**, so every one of these tests failed with
|
|
10
|
-
* `listen EACCES: permission denied …\agent.sock` and the whole
|
|
11
|
-
* `@namzu/sandbox` suite has been red for Windows contributors.
|
|
12
|
-
*
|
|
13
|
-
* The transport under test is address-agnostic: it is handed a path and
|
|
14
|
-
* connects to it. So the fix belongs in the fixture, not the driver.
|
|
15
|
-
*/
|
|
16
|
-
export function localIpcPath(workDir, name = 'agent') {
|
|
17
|
-
if (process.platform === 'win32') {
|
|
18
|
-
// Named pipes are not filesystem entries, so the temp dir cannot
|
|
19
|
-
// namespace them — a uuid keeps concurrent test files apart.
|
|
20
|
-
return `\\\\.\\pipe\\namzu-${name}-${randomUUID()}`;
|
|
21
|
-
}
|
|
22
|
-
return join(workDir, `${name}.sock`);
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* True when the socket address lives on disk and can be cleaned up with
|
|
26
|
-
* the temp directory. Named pipes disappear with the process that owns
|
|
27
|
-
* them, so there is nothing to unlink.
|
|
28
|
-
*/
|
|
29
|
-
export const IPC_IS_FILESYSTEM_PATH = process.platform !== 'win32';
|
|
30
|
-
//# sourceMappingURL=ipc-path.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ipc-path.js","sourceRoot":"","sources":["../../../../../src/backends/firecracker/__tests__/fixtures/ipc-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,IAAI,GAAG,OAAO;IAC3D,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,iEAAiE;QACjE,6DAA6D;QAC7D,OAAO,sBAAsB,IAAI,IAAI,UAAU,EAAE,EAAE,CAAA;IACpD,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,CAAA;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAA"}
|
|
@@ -1,39 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,149 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mtls-pki.js","sourceRoot":"","sources":["../../../../../src/backends/firecracker/__tests__/fixtures/mtls-pki.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.test.d.ts","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/protocol.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -1,67 +0,0 @@
|
|
|
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
|
-
orchestratorEndpoint: 'https://orchestrator.test',
|
|
48
|
-
getToken: async () => 'tok',
|
|
49
|
-
template: 'golden-rev-1',
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
expect(provider.id).toContain('microvm');
|
|
53
|
-
expect(provider.id).toContain('firecracker');
|
|
54
|
-
expect(provider.name).toContain('microvm:self-hosted');
|
|
55
|
-
});
|
|
56
|
-
it('refuses the shape that reaches no orchestrator', () => {
|
|
57
|
-
// The control-plane endpoint and its bearer are required now. They
|
|
58
|
-
// used to be optional beside three REQUIRED fields belonging to a
|
|
59
|
-
// local-daemon path that was never written, so the only working
|
|
60
|
-
// configuration had to supply three values nothing reads — and
|
|
61
|
-
// omitting these two type-checked its way to a runtime throw.
|
|
62
|
-
expect(() => createSandboxProvider({
|
|
63
|
-
backend: { tier: 'microvm', service: 'self-hosted' },
|
|
64
|
-
})).toThrow(SandboxBackendNotImplementedError);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
//# sourceMappingURL=protocol.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/protocol.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transport.test.d.ts","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/transport.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
|