@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.
Files changed (98) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +62 -1
  3. package/dist/backends/docker/index.d.ts +26 -1
  4. package/dist/backends/docker/index.d.ts.map +1 -1
  5. package/dist/backends/docker/index.js +20 -7
  6. package/dist/backends/docker/index.js.map +1 -1
  7. package/dist/egress/address.d.ts +75 -0
  8. package/dist/egress/address.d.ts.map +1 -0
  9. package/dist/egress/address.js +289 -0
  10. package/dist/egress/address.js.map +1 -0
  11. package/dist/egress/index.d.ts +2 -0
  12. package/dist/egress/index.d.ts.map +1 -1
  13. package/dist/egress/index.js +1 -0
  14. package/dist/egress/index.js.map +1 -1
  15. package/dist/egress/proxy.d.ts +41 -0
  16. package/dist/egress/proxy.d.ts.map +1 -1
  17. package/dist/egress/proxy.js +83 -2
  18. package/dist/egress/proxy.js.map +1 -1
  19. package/dist/index.d.ts +16 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +2 -0
  22. package/dist/index.js.map +1 -1
  23. package/package.json +12 -2
  24. package/src/backends/docker/index.ts +45 -8
  25. package/src/egress/address.ts +366 -0
  26. package/src/egress/index.ts +7 -0
  27. package/src/egress/proxy.ts +106 -2
  28. package/src/index.ts +18 -0
  29. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.d.ts +0 -2
  30. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.d.ts.map +0 -1
  31. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.js +0 -61
  32. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.js.map +0 -1
  33. package/dist/backends/docker/__tests__/hardening.test.d.ts +0 -2
  34. package/dist/backends/docker/__tests__/hardening.test.d.ts.map +0 -1
  35. package/dist/backends/docker/__tests__/hardening.test.js +0 -32
  36. package/dist/backends/docker/__tests__/hardening.test.js.map +0 -1
  37. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts +0 -40
  38. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts.map +0 -1
  39. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js +0 -157
  40. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js.map +0 -1
  41. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.d.ts +0 -16
  42. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.d.ts.map +0 -1
  43. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.js +0 -37
  44. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.js.map +0 -1
  45. package/dist/backends/firecracker/__tests__/backend.test.d.ts +0 -13
  46. package/dist/backends/firecracker/__tests__/backend.test.d.ts.map +0 -1
  47. package/dist/backends/firecracker/__tests__/backend.test.js +0 -361
  48. package/dist/backends/firecracker/__tests__/backend.test.js.map +0 -1
  49. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts +0 -19
  50. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts.map +0 -1
  51. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js +0 -209
  52. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js.map +0 -1
  53. package/dist/backends/firecracker/__tests__/egress-policy.test.d.ts +0 -2
  54. package/dist/backends/firecracker/__tests__/egress-policy.test.d.ts.map +0 -1
  55. package/dist/backends/firecracker/__tests__/egress-policy.test.js +0 -67
  56. package/dist/backends/firecracker/__tests__/egress-policy.test.js.map +0 -1
  57. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.d.ts +0 -21
  58. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.d.ts.map +0 -1
  59. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.js +0 -30
  60. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.js.map +0 -1
  61. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts +0 -39
  62. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts.map +0 -1
  63. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js +0 -149
  64. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js.map +0 -1
  65. package/dist/backends/firecracker/__tests__/protocol.test.d.ts +0 -6
  66. package/dist/backends/firecracker/__tests__/protocol.test.d.ts.map +0 -1
  67. package/dist/backends/firecracker/__tests__/protocol.test.js +0 -67
  68. package/dist/backends/firecracker/__tests__/protocol.test.js.map +0 -1
  69. package/dist/backends/firecracker/__tests__/transport.test.d.ts +0 -20
  70. package/dist/backends/firecracker/__tests__/transport.test.d.ts.map +0 -1
  71. package/dist/backends/firecracker/__tests__/transport.test.js +0 -457
  72. package/dist/backends/firecracker/__tests__/transport.test.js.map +0 -1
  73. package/dist/egress/__tests__/allowlist.test.d.ts +0 -2
  74. package/dist/egress/__tests__/allowlist.test.d.ts.map +0 -1
  75. package/dist/egress/__tests__/allowlist.test.js +0 -85
  76. package/dist/egress/__tests__/allowlist.test.js.map +0 -1
  77. package/dist/egress/__tests__/proxy.test.d.ts +0 -2
  78. package/dist/egress/__tests__/proxy.test.d.ts.map +0 -1
  79. package/dist/egress/__tests__/proxy.test.js +0 -177
  80. package/dist/egress/__tests__/proxy.test.js.map +0 -1
  81. package/dist/index.test.d.ts +0 -28
  82. package/dist/index.test.d.ts.map +0 -1
  83. package/dist/index.test.js +0 -649
  84. package/dist/index.test.js.map +0 -1
  85. package/src/backends/aci-standby-pool/__tests__/unenforceable-controls.test.ts +0 -69
  86. package/src/backends/docker/__tests__/hardening.test.ts +0 -43
  87. package/src/backends/docker/__tests__/leaf-permissions.smoke.test.ts +0 -169
  88. package/src/backends/firecracker/__tests__/agent-timeout-clamp.test.ts +0 -48
  89. package/src/backends/firecracker/__tests__/backend.test.ts +0 -429
  90. package/src/backends/firecracker/__tests__/control-plane-mtls.test.ts +0 -261
  91. package/src/backends/firecracker/__tests__/egress-policy.test.ts +0 -91
  92. package/src/backends/firecracker/__tests__/fixtures/ipc-path.ts +0 -31
  93. package/src/backends/firecracker/__tests__/fixtures/mtls-pki.ts +0 -166
  94. package/src/backends/firecracker/__tests__/protocol.test.ts +0 -75
  95. package/src/backends/firecracker/__tests__/transport.test.ts +0 -534
  96. package/src/egress/__tests__/allowlist.test.ts +0 -103
  97. package/src/egress/__tests__/proxy.test.ts +0 -212
  98. 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,6 +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
- export {};
6
- //# sourceMappingURL=protocol.test.d.ts.map
@@ -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"}