termify-agent 1.0.51 → 1.0.54

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.
@@ -0,0 +1,24 @@
1
+ import assert from 'node:assert/strict';
2
+ import { existsSync, mkdtempSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import test from 'node:test';
6
+ import { WireGuardManager } from './wireguard-manager.js';
7
+ test('preloads a local WireGuard identity before the interface is created', async (t) => {
8
+ const tempDir = mkdtempSync(join(tmpdir(), 'termify-agent-wg-'));
9
+ t.after(() => {
10
+ rmSync(tempDir, { recursive: true, force: true });
11
+ });
12
+ const manager = new WireGuardManager(tempDir);
13
+ assert.equal(manager.getStatus().publicKey, undefined);
14
+ assert.equal(manager.getStatus().listenPort, undefined);
15
+ const identity = await manager.ensureIdentityLoaded();
16
+ const status = manager.getStatus();
17
+ assert.equal(status.interfaceName, identity.interfaceName);
18
+ assert.equal(status.listenPort, identity.listenPort);
19
+ assert.equal(status.publicKey, identity.publicKey);
20
+ assert.ok(status.publicKey);
21
+ assert.equal(existsSync(join(tempDir, 'wireguard.key')), true);
22
+ assert.equal(existsSync(join(tempDir, 'wireguard.json')), true);
23
+ });
24
+ //# sourceMappingURL=wireguard-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wireguard-manager.test.js","sourceRoot":"","sources":["../../src/network/wireguard-manager.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,IAAI,CAAC,qEAAqE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACtF,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAEjE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QACX,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAE9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACvD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,oBAAoB,EAAE,CAAC;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAEnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5B,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface OpenSSHRenderPaths {
2
+ userPrivateKeyPath: string;
3
+ userCertificatePath: string;
4
+ knownHostsPath: string;
5
+ hostPrivateKeyPath: string;
6
+ hostCertificatePath: string;
7
+ userCaPublicKeyPath: string;
8
+ principalsCommand?: string;
9
+ principalsCommandUser?: string;
10
+ authorizedPrincipalsFilePath?: string;
11
+ }
12
+ export declare function renderClientConfig(paths: OpenSSHRenderPaths): string;
13
+ export declare function renderKnownHostsCertAuthority(pattern: string, hostCaPublicKey: string): string;
14
+ export declare function renderSshdConfigFragment(paths: OpenSSHRenderPaths): string;
15
+ export declare function upsertManagedBlock(existing: string, name: string, block: string): string;
16
+ //# sourceMappingURL=platform-openssh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-openssh.d.ts","sourceRoot":"","sources":["../../src/ssh/platform-openssh.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAUpE;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAE9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAmB1E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBxF"}
@@ -0,0 +1,51 @@
1
+ export function renderClientConfig(paths) {
2
+ return [
3
+ 'Host 10.100.*',
4
+ ` IdentityFile ${paths.userPrivateKeyPath}`,
5
+ ` CertificateFile ${paths.userCertificatePath}`,
6
+ ` UserKnownHostsFile ${paths.knownHostsPath}`,
7
+ ' StrictHostKeyChecking yes',
8
+ ' IdentitiesOnly yes',
9
+ '',
10
+ ].join('\n');
11
+ }
12
+ export function renderKnownHostsCertAuthority(pattern, hostCaPublicKey) {
13
+ return `@cert-authority ${pattern} ${hostCaPublicKey.trimEnd()}\n`;
14
+ }
15
+ export function renderSshdConfigFragment(paths) {
16
+ const principalLines = paths.authorizedPrincipalsFilePath
17
+ ? [
18
+ `AuthorizedPrincipalsFile ${paths.authorizedPrincipalsFilePath}`,
19
+ ]
20
+ : [
21
+ `AuthorizedPrincipalsCommand ${paths.principalsCommand}`,
22
+ `AuthorizedPrincipalsCommandUser ${paths.principalsCommandUser ?? 'root'}`,
23
+ ];
24
+ return [
25
+ '# Managed by Termify',
26
+ `HostKey ${paths.hostPrivateKeyPath}`,
27
+ `HostCertificate ${paths.hostCertificatePath}`,
28
+ `TrustedUserCAKeys ${paths.userCaPublicKeyPath}`,
29
+ ...principalLines,
30
+ 'PubkeyAuthentication yes',
31
+ '',
32
+ ].join('\n');
33
+ }
34
+ export function upsertManagedBlock(existing, name, block) {
35
+ const start = `# >>> termify:${name} >>>`;
36
+ const end = `# <<< termify:${name} <<<`;
37
+ const managed = `${start}\n${block.trimEnd()}\n${end}\n`;
38
+ const pattern = new RegExp(`${escapeRegExp(start)}[\\s\\S]*?${escapeRegExp(end)}\\n?`, 'g');
39
+ if (pattern.test(existing)) {
40
+ return existing.replace(pattern, managed);
41
+ }
42
+ const trimmed = existing.trimEnd();
43
+ if (trimmed.length === 0) {
44
+ return managed;
45
+ }
46
+ return `${trimmed}\n\n${managed}`;
47
+ }
48
+ function escapeRegExp(value) {
49
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
50
+ }
51
+ //# sourceMappingURL=platform-openssh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-openssh.js","sourceRoot":"","sources":["../../src/ssh/platform-openssh.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,OAAO;QACL,eAAe;QACf,kBAAkB,KAAK,CAAC,kBAAkB,EAAE;QAC5C,qBAAqB,KAAK,CAAC,mBAAmB,EAAE;QAChD,wBAAwB,KAAK,CAAC,cAAc,EAAE;QAC9C,6BAA6B;QAC7B,sBAAsB;QACtB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,OAAe,EAAE,eAAuB;IACpF,OAAO,mBAAmB,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAyB;IAChE,MAAM,cAAc,GAAG,KAAK,CAAC,4BAA4B;QACvD,CAAC,CAAC;YACE,4BAA4B,KAAK,CAAC,4BAA4B,EAAE;SACjE;QACH,CAAC,CAAC;YACE,+BAA+B,KAAK,CAAC,iBAAiB,EAAE;YACxD,mCAAmC,KAAK,CAAC,qBAAqB,IAAI,MAAM,EAAE;SAC3E,CAAC;IAEN,OAAO;QACL,sBAAsB;QACtB,WAAW,KAAK,CAAC,kBAAkB,EAAE;QACrC,mBAAmB,KAAK,CAAC,mBAAmB,EAAE;QAC9C,qBAAqB,KAAK,CAAC,mBAAmB,EAAE;QAChD,GAAG,cAAc;QACjB,0BAA0B;QAC1B,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,IAAY,EAAE,KAAa;IAC9E,MAAM,KAAK,GAAG,iBAAiB,IAAI,MAAM,CAAC;IAC1C,MAAM,GAAG,GAAG,iBAAiB,IAAI,MAAM,CAAC;IACxC,MAAM,OAAO,GAAG,GAAG,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC;IACzD,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE5F,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;IACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,GAAG,OAAO,OAAO,OAAO,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=platform-openssh.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-openssh.test.d.ts","sourceRoot":"","sources":["../../src/ssh/platform-openssh.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
1
+ import assert from 'node:assert/strict';
2
+ import test from 'node:test';
3
+ import { renderClientConfig, renderKnownHostsCertAuthority, renderSshdConfigFragment, } from './platform-openssh.js';
4
+ const paths = {
5
+ userPrivateKeyPath: '/Users/diego/.termify/ssh/user_ed25519',
6
+ userCertificatePath: '/Users/diego/.termify/ssh/user_ed25519-cert.pub',
7
+ knownHostsPath: '/Users/diego/.termify/ssh/known_hosts',
8
+ hostPrivateKeyPath: '/Users/diego/.termify/ssh/host_ed25519',
9
+ hostCertificatePath: '/etc/termify/ssh/host_ed25519-cert.pub',
10
+ userCaPublicKeyPath: '/etc/termify/ssh/user_ca.pub',
11
+ authorizedPrincipalsFilePath: '/etc/termify/ssh/authorized_principals',
12
+ };
13
+ test('renders client config for the Termify virtual network', () => {
14
+ const config = renderClientConfig(paths);
15
+ assert.match(config, /Host 10\.100\.\*/);
16
+ assert.match(config, /IdentityFile \/Users\/diego\/\.termify\/ssh\/user_ed25519/);
17
+ assert.match(config, /CertificateFile \/Users\/diego\/\.termify\/ssh\/user_ed25519-cert\.pub/);
18
+ assert.match(config, /UserKnownHostsFile \/Users\/diego\/\.termify\/ssh\/known_hosts/);
19
+ assert.match(config, /StrictHostKeyChecking yes/);
20
+ assert.match(config, /IdentitiesOnly yes/);
21
+ });
22
+ test('renders known_hosts trust for the Termify host CA', () => {
23
+ const entry = renderKnownHostsCertAuthority('10.100.*', 'ssh-ed25519 AAAATESTCA termify-host-ca');
24
+ assert.equal(entry, '@cert-authority 10.100.* ssh-ed25519 AAAATESTCA termify-host-ca\n');
25
+ });
26
+ test('renders sshd fragment that trusts the Termify account CA', () => {
27
+ const fragment = renderSshdConfigFragment(paths);
28
+ assert.match(fragment, /HostKey \/Users\/diego\/\.termify\/ssh\/host_ed25519/);
29
+ assert.match(fragment, /TrustedUserCAKeys \/etc\/termify\/ssh\/user_ca\.pub/);
30
+ assert.match(fragment, /HostCertificate \/etc\/termify\/ssh\/host_ed25519-cert\.pub/);
31
+ assert.match(fragment, /AuthorizedPrincipalsFile \/etc\/termify\/ssh\/authorized_principals/);
32
+ assert.doesNotMatch(fragment, /AuthorizedPrincipalsCommand/);
33
+ });
34
+ test('renders a static authorized principals file for Windows OpenSSH', () => {
35
+ const fragment = renderSshdConfigFragment({
36
+ ...paths,
37
+ authorizedPrincipalsFilePath: 'C:\\ProgramData\\Termify\\ssh\\authorized_principals',
38
+ });
39
+ assert.match(fragment, /AuthorizedPrincipalsFile C:\\ProgramData\\Termify\\ssh\\authorized_principals/);
40
+ assert.doesNotMatch(fragment, /AuthorizedPrincipalsCommand/);
41
+ });
42
+ //# sourceMappingURL=platform-openssh.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-openssh.test.js","sourceRoot":"","sources":["../../src/ssh/platform-openssh.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,KAAK,GAAG;IACZ,kBAAkB,EAAE,wCAAwC;IAC5D,mBAAmB,EAAE,iDAAiD;IACtE,cAAc,EAAE,uCAAuC;IACvD,kBAAkB,EAAE,wCAAwC;IAC5D,mBAAmB,EAAE,wCAAwC;IAC7D,mBAAmB,EAAE,8BAA8B;IACnD,4BAA4B,EAAE,wCAAwC;CACvE,CAAC;AAEF,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACjE,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAEzC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,2DAA2D,CAAC,CAAC;IAClF,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,wEAAwE,CAAC,CAAC;IAC/F,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,gEAAgE,CAAC,CAAC;IACvF,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mDAAmD,EAAE,GAAG,EAAE;IAC7D,MAAM,KAAK,GAAG,6BAA6B,CAAC,UAAU,EAAE,wCAAwC,CAAC,CAAC;IAClG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,mEAAmE,CAAC,CAAC;AAC3F,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;IACpE,MAAM,QAAQ,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAEjD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,sDAAsD,CAAC,CAAC;IAC/E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,qDAAqD,CAAC,CAAC;IAC9E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,6DAA6D,CAAC,CAAC;IACtF,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,qEAAqE,CAAC,CAAC;IAC9F,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC;AAC/D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;IAC3E,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QACxC,GAAG,KAAK;QACR,4BAA4B,EAAE,sDAAsD;KAC9E,CAAC,CAAC;IAEV,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,+EAA+E,CAAC,CAAC;IACxG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC;AAC/D,CAAC,CAAC,CAAC"}
@@ -0,0 +1,58 @@
1
+ import type { AgentSshBootstrapResponse } from '@termify/shared';
2
+ export interface SystemSSHPaths {
3
+ userRootDir: string;
4
+ systemRootDir: string;
5
+ userPrivateKeyPath: string;
6
+ userPublicKeyPath: string;
7
+ userCertificatePath: string;
8
+ hostPrivateKeyPath: string;
9
+ hostPublicKeyPath: string;
10
+ hostCertificatePath: string;
11
+ userCaPublicKeyPath: string;
12
+ hostCaPublicKeyPath: string;
13
+ metadataPath: string;
14
+ authorizedPrincipalsPath: string;
15
+ knownHostsPath: string;
16
+ clientConfigPath: string;
17
+ principalsCommandPath: string;
18
+ }
19
+ export interface SystemSSHOptions {
20
+ userRootDir?: string;
21
+ systemRootDir?: string;
22
+ homeDir?: string;
23
+ sshdConfigPath?: string;
24
+ helperNodePath?: string;
25
+ helperCliPath?: string;
26
+ applyUserOwnership?: (filePath: string) => Promise<void>;
27
+ platformOverride?: NodeJS.Platform;
28
+ reloadSshd?: boolean;
29
+ }
30
+ export declare class SystemSSHManager {
31
+ private userRootDir;
32
+ private systemRootDir;
33
+ private homeDir;
34
+ private options;
35
+ constructor(userRootDirOrOptions?: string | SystemSSHOptions, homeDirArg?: string, legacyOptions?: SystemSSHOptions);
36
+ getPaths(): SystemSSHPaths;
37
+ ensureLocalKeyPairs(): Promise<{
38
+ userPublicKey: string;
39
+ hostPublicKey: string;
40
+ }>;
41
+ applyBootstrap(material: AgentSshBootstrapResponse): Promise<void>;
42
+ installOpenSshIntegration(): Promise<void>;
43
+ fetchBootstrap(params: {
44
+ serverUrl: string;
45
+ accessToken: string;
46
+ virtualIp: string;
47
+ hostname: string;
48
+ }): Promise<AgentSshBootstrapResponse>;
49
+ readAccountPrincipal(): string | null;
50
+ private getSshdConfigPath;
51
+ private readMetadata;
52
+ private ensureEd25519KeyPair;
53
+ private installPrincipalsCommandHelper;
54
+ private applyUserOwnership;
55
+ private getPlatform;
56
+ private reloadSshd;
57
+ }
58
+ //# sourceMappingURL=system-ssh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-ssh.d.ts","sourceRoot":"","sources":["../../src/ssh/system-ssh.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,yBAAyB,EAC1B,MAAM,iBAAiB,CAAC;AAiBzB,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,EAAE,MAAM,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA2ID,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAA6B;gBAEhC,oBAAoB,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,aAAa,GAAE,gBAAqB;IAOvH,QAAQ,IAAI,cAAc;IAuBpB,mBAAmB,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IAqBhF,cAAc,CAAC,QAAQ,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBlE,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiE1C,cAAc,CAAC,MAAM,EAAE;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA+BtC,oBAAoB,IAAI,MAAM,GAAG,IAAI;IAKrC,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,YAAY;YASN,oBAAoB;YAepB,8BAA8B;YAe9B,kBAAkB;IAIhC,OAAO,CAAC,WAAW;YAIL,UAAU;CAiBzB"}
@@ -0,0 +1,328 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { chmod, chown, mkdir, readFile, writeFile } from 'node:fs/promises';
4
+ import { homedir } from 'node:os';
5
+ import { dirname, join } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { promisify } from 'node:util';
8
+ import { renderClientConfig, renderKnownHostsCertAuthority, renderSshdConfigFragment, upsertManagedBlock, } from './platform-openssh.js';
9
+ const execFileAsync = promisify(execFile);
10
+ const DEFAULT_HELPER_CLI_PATH = fileURLToPath(new URL('../index.js', import.meta.url));
11
+ async function writeFileWithNewline(filePath, contents) {
12
+ await writeFile(filePath, contents.trimEnd() + '\n', 'utf8');
13
+ }
14
+ function resolveDefaultUserRootDir(homeDir) {
15
+ return join(homeDir, '.termify', 'ssh');
16
+ }
17
+ function getPlatform(platformOverride) {
18
+ return platformOverride ?? process.platform;
19
+ }
20
+ function isRunningAsRoot() {
21
+ return typeof process.getuid === 'function' && process.getuid() === 0;
22
+ }
23
+ function resolveEffectiveHomeDir(platformOverride) {
24
+ if (process.env.TERMIFY_SSH_HOME_DIR) {
25
+ return process.env.TERMIFY_SSH_HOME_DIR;
26
+ }
27
+ if (isRunningAsRoot() && process.env.SUDO_USER) {
28
+ if (getPlatform(platformOverride) === 'win32') {
29
+ return join('C:\\Users', process.env.SUDO_USER);
30
+ }
31
+ if (getPlatform(platformOverride) === 'darwin') {
32
+ return join('/Users', process.env.SUDO_USER);
33
+ }
34
+ return join('/home', process.env.SUDO_USER);
35
+ }
36
+ return homedir();
37
+ }
38
+ function resolveDefaultSystemRootDir(platformOverride) {
39
+ if (process.env.TERMIFY_SSH_SYSTEM_DIR) {
40
+ return process.env.TERMIFY_SSH_SYSTEM_DIR;
41
+ }
42
+ if (getPlatform(platformOverride) === 'win32') {
43
+ return 'C:\\ProgramData\\Termify\\ssh';
44
+ }
45
+ if (getPlatform(platformOverride) === 'darwin') {
46
+ return '/Library/Termify/ssh';
47
+ }
48
+ return '/var/lib/termify-agent/ssh';
49
+ }
50
+ function resolveDefaultPrincipalsCommandPath(systemRootDir, platformOverride) {
51
+ return join(systemRootDir, getPlatform(platformOverride) === 'win32' ? 'termify-ssh-principals.cmd' : 'termify-ssh-principals');
52
+ }
53
+ function quoteForShell(value) {
54
+ return `'${value.replace(/'/g, `'\\''`)}'`;
55
+ }
56
+ function renderPrincipalsCommandScript(params) {
57
+ if (getPlatform(params.platformOverride) === 'win32') {
58
+ return [
59
+ '@echo off',
60
+ `set "TERMIFY_SSH_SYSTEM_DIR=${params.systemRootDir}"`,
61
+ `"${params.nodePath}" "${params.cliPath}" ssh principals %*`,
62
+ '',
63
+ ].join('\r\n');
64
+ }
65
+ return [
66
+ '#!/bin/sh',
67
+ `export TERMIFY_SSH_SYSTEM_DIR=${quoteForShell(params.systemRootDir)}`,
68
+ `exec ${quoteForShell(params.nodePath)} ${quoteForShell(params.cliPath)} ssh principals "$@"`,
69
+ '',
70
+ ].join('\n');
71
+ }
72
+ function normalizeConstructorArgs(userRootDirOrOptions, homeDirArg, legacyOptions = {}) {
73
+ if (typeof userRootDirOrOptions === 'string') {
74
+ const homeDir = homeDirArg ?? resolveEffectiveHomeDir(legacyOptions.platformOverride);
75
+ return {
76
+ userRootDir: userRootDirOrOptions,
77
+ systemRootDir: legacyOptions.systemRootDir ?? userRootDirOrOptions,
78
+ homeDir,
79
+ sshdConfigPath: legacyOptions.sshdConfigPath ?? '',
80
+ helperNodePath: legacyOptions.helperNodePath ?? process.execPath,
81
+ helperCliPath: legacyOptions.helperCliPath ?? DEFAULT_HELPER_CLI_PATH,
82
+ applyUserOwnership: legacyOptions.applyUserOwnership ?? resolveUserOwnershipApplier(),
83
+ platformOverride: legacyOptions.platformOverride ?? process.platform,
84
+ reloadSshd: legacyOptions.reloadSshd ?? true,
85
+ };
86
+ }
87
+ const options = userRootDirOrOptions ?? {};
88
+ const homeDir = options.homeDir ?? resolveEffectiveHomeDir(options.platformOverride);
89
+ return {
90
+ userRootDir: options.userRootDir ?? resolveDefaultUserRootDir(homeDir),
91
+ systemRootDir: options.systemRootDir ?? resolveDefaultSystemRootDir(options.platformOverride),
92
+ homeDir,
93
+ sshdConfigPath: options.sshdConfigPath ?? '',
94
+ helperNodePath: options.helperNodePath ?? process.execPath,
95
+ helperCliPath: options.helperCliPath ?? DEFAULT_HELPER_CLI_PATH,
96
+ applyUserOwnership: options.applyUserOwnership ?? resolveUserOwnershipApplier(),
97
+ platformOverride: options.platformOverride ?? process.platform,
98
+ reloadSshd: options.reloadSshd ?? true,
99
+ };
100
+ }
101
+ function resolveUserOwnershipApplier() {
102
+ if (!isRunningAsRoot()) {
103
+ return async () => { };
104
+ }
105
+ const uid = process.env.SUDO_UID ? Number(process.env.SUDO_UID) : Number.NaN;
106
+ const gid = process.env.SUDO_GID ? Number(process.env.SUDO_GID) : Number.NaN;
107
+ if (!Number.isInteger(uid) || !Number.isInteger(gid)) {
108
+ return async () => { };
109
+ }
110
+ return async (filePath) => {
111
+ try {
112
+ await chown(filePath, uid, gid);
113
+ }
114
+ catch { }
115
+ };
116
+ }
117
+ export class SystemSSHManager {
118
+ userRootDir;
119
+ systemRootDir;
120
+ homeDir;
121
+ options;
122
+ constructor(userRootDirOrOptions, homeDirArg, legacyOptions = {}) {
123
+ this.options = normalizeConstructorArgs(userRootDirOrOptions, homeDirArg, legacyOptions);
124
+ this.userRootDir = this.options.userRootDir;
125
+ this.systemRootDir = this.options.systemRootDir;
126
+ this.homeDir = this.options.homeDir;
127
+ }
128
+ getPaths() {
129
+ const userPrivateKeyPath = join(this.userRootDir, 'user_ed25519');
130
+ const hostPrivateKeyPath = join(this.systemRootDir, 'host_ed25519');
131
+ return {
132
+ userRootDir: this.userRootDir,
133
+ systemRootDir: this.systemRootDir,
134
+ userPrivateKeyPath,
135
+ userPublicKeyPath: `${userPrivateKeyPath}.pub`,
136
+ userCertificatePath: join(this.userRootDir, 'user_ed25519-cert.pub'),
137
+ hostPrivateKeyPath,
138
+ hostPublicKeyPath: `${hostPrivateKeyPath}.pub`,
139
+ hostCertificatePath: join(this.systemRootDir, 'host_ed25519-cert.pub'),
140
+ userCaPublicKeyPath: join(this.systemRootDir, 'user_ca.pub'),
141
+ hostCaPublicKeyPath: join(this.systemRootDir, 'host_ca.pub'),
142
+ metadataPath: join(this.systemRootDir, 'bootstrap.json'),
143
+ authorizedPrincipalsPath: join(this.systemRootDir, 'authorized_principals'),
144
+ knownHostsPath: join(this.userRootDir, 'known_hosts'),
145
+ clientConfigPath: join(this.homeDir, '.ssh', 'config'),
146
+ principalsCommandPath: resolveDefaultPrincipalsCommandPath(this.systemRootDir, this.getPlatform()),
147
+ };
148
+ }
149
+ async ensureLocalKeyPairs() {
150
+ const paths = this.getPaths();
151
+ await Promise.all([
152
+ mkdir(paths.userRootDir, { recursive: true }),
153
+ mkdir(paths.systemRootDir, { recursive: true }),
154
+ ]);
155
+ await this.applyUserOwnership(paths.userRootDir);
156
+ const userPublicKey = await this.ensureEd25519KeyPair(paths.userPrivateKeyPath, 'termify-user');
157
+ const hostPublicKey = await this.ensureEd25519KeyPair(paths.hostPrivateKeyPath, 'termify-host');
158
+ await Promise.all([
159
+ this.applyUserOwnership(paths.userPrivateKeyPath),
160
+ this.applyUserOwnership(paths.userPublicKeyPath),
161
+ ]);
162
+ return {
163
+ userPublicKey,
164
+ hostPublicKey,
165
+ };
166
+ }
167
+ async applyBootstrap(material) {
168
+ const paths = this.getPaths();
169
+ await Promise.all([
170
+ mkdir(paths.userRootDir, { recursive: true }),
171
+ mkdir(paths.systemRootDir, { recursive: true }),
172
+ ]);
173
+ await Promise.all([
174
+ writeFile(paths.userCertificatePath, material.userCertificate, 'utf8'),
175
+ writeFile(paths.hostCertificatePath, material.hostCertificate, 'utf8'),
176
+ writeFileWithNewline(paths.userCaPublicKeyPath, material.userCaPublicKey),
177
+ writeFileWithNewline(paths.hostCaPublicKeyPath, material.hostCaPublicKey),
178
+ writeFileWithNewline(paths.authorizedPrincipalsPath, material.accountPrincipal),
179
+ writeFile(paths.metadataPath, JSON.stringify({
180
+ accountPrincipal: material.accountPrincipal,
181
+ userValidForSeconds: material.userValidForSeconds,
182
+ hostValidForSeconds: material.hostValidForSeconds,
183
+ }, null, 2), 'utf8'),
184
+ ]);
185
+ await this.applyUserOwnership(paths.userCertificatePath);
186
+ }
187
+ async installOpenSshIntegration() {
188
+ const paths = this.getPaths();
189
+ const principal = this.readAccountPrincipal();
190
+ if (!principal) {
191
+ throw new Error('Cannot install OpenSSH integration without bootstrap metadata');
192
+ }
193
+ await Promise.all([
194
+ mkdir(paths.userRootDir, { recursive: true }),
195
+ mkdir(paths.systemRootDir, { recursive: true }),
196
+ mkdir(join(this.homeDir, '.ssh'), { recursive: true }),
197
+ ]);
198
+ await Promise.all([
199
+ this.applyUserOwnership(paths.userRootDir),
200
+ this.applyUserOwnership(join(this.homeDir, '.ssh')),
201
+ ]);
202
+ await writeFile(paths.knownHostsPath, renderKnownHostsCertAuthority('10.100.*', readFileSync(paths.hostCaPublicKeyPath, 'utf8')), 'utf8');
203
+ await this.applyUserOwnership(paths.knownHostsPath);
204
+ const existingClientConfig = existsSync(paths.clientConfigPath)
205
+ ? readFileSync(paths.clientConfigPath, 'utf8')
206
+ : '';
207
+ const mergedClientConfig = upsertManagedBlock(existingClientConfig, 'ssh-client', renderClientConfig({
208
+ userPrivateKeyPath: paths.userPrivateKeyPath,
209
+ userCertificatePath: paths.userCertificatePath,
210
+ knownHostsPath: paths.knownHostsPath,
211
+ hostPrivateKeyPath: paths.hostPrivateKeyPath,
212
+ hostCertificatePath: paths.hostCertificatePath,
213
+ userCaPublicKeyPath: paths.userCaPublicKeyPath,
214
+ principalsCommand: `${paths.principalsCommandPath} %u`,
215
+ }));
216
+ await writeFile(paths.clientConfigPath, mergedClientConfig, 'utf8');
217
+ await this.applyUserOwnership(paths.clientConfigPath);
218
+ const sshdConfigPath = this.getSshdConfigPath();
219
+ const existingSshdConfig = existsSync(sshdConfigPath)
220
+ ? readFileSync(sshdConfigPath, 'utf8')
221
+ : '';
222
+ const mergedSshdConfig = upsertManagedBlock(existingSshdConfig, 'sshd', renderSshdConfigFragment({
223
+ userPrivateKeyPath: paths.userPrivateKeyPath,
224
+ userCertificatePath: paths.userCertificatePath,
225
+ knownHostsPath: paths.knownHostsPath,
226
+ hostPrivateKeyPath: paths.hostPrivateKeyPath,
227
+ hostCertificatePath: paths.hostCertificatePath,
228
+ userCaPublicKeyPath: paths.userCaPublicKeyPath,
229
+ authorizedPrincipalsFilePath: paths.authorizedPrincipalsPath,
230
+ }));
231
+ await mkdir(dirname(sshdConfigPath), { recursive: true }).catch(() => { });
232
+ await writeFile(sshdConfigPath, mergedSshdConfig, 'utf8');
233
+ await this.reloadSshd();
234
+ }
235
+ async fetchBootstrap(params) {
236
+ const keyPairs = await this.ensureLocalKeyPairs();
237
+ const payload = {
238
+ virtualIp: params.virtualIp,
239
+ hostname: params.hostname,
240
+ hostPublicKey: keyPairs.hostPublicKey,
241
+ userPublicKey: keyPairs.userPublicKey,
242
+ };
243
+ const response = await fetch(`${params.serverUrl}/api/agent/ssh/bootstrap`, {
244
+ method: 'POST',
245
+ headers: {
246
+ Authorization: `Bearer ${params.accessToken}`,
247
+ 'Content-Type': 'application/json',
248
+ },
249
+ body: JSON.stringify(payload),
250
+ });
251
+ if (!response.ok) {
252
+ throw new Error(`SSH bootstrap failed with status ${response.status}`);
253
+ }
254
+ const json = await response.json();
255
+ if (!json.success || !json.data) {
256
+ throw new Error(json.error || 'SSH bootstrap returned no data');
257
+ }
258
+ await this.applyBootstrap(json.data);
259
+ return json.data;
260
+ }
261
+ readAccountPrincipal() {
262
+ const metadata = this.readMetadata();
263
+ return metadata?.accountPrincipal ?? null;
264
+ }
265
+ getSshdConfigPath() {
266
+ if (this.options.sshdConfigPath) {
267
+ return this.options.sshdConfigPath;
268
+ }
269
+ if (this.getPlatform() === 'win32') {
270
+ return 'C:\\ProgramData\\ssh\\sshd_config';
271
+ }
272
+ return '/etc/ssh/sshd_config';
273
+ }
274
+ readMetadata() {
275
+ const { metadataPath } = this.getPaths();
276
+ if (!existsSync(metadataPath)) {
277
+ return null;
278
+ }
279
+ return JSON.parse(readFileSync(metadataPath, 'utf8'));
280
+ }
281
+ async ensureEd25519KeyPair(privateKeyPath, comment) {
282
+ const publicKeyPath = `${privateKeyPath}.pub`;
283
+ if (!existsSync(privateKeyPath) || !existsSync(publicKeyPath)) {
284
+ await execFileAsync('ssh-keygen', [
285
+ '-q',
286
+ '-t', 'ed25519',
287
+ '-N', '',
288
+ '-C', comment,
289
+ '-f', privateKeyPath,
290
+ ]);
291
+ }
292
+ return readFile(publicKeyPath, 'utf8');
293
+ }
294
+ async installPrincipalsCommandHelper() {
295
+ const paths = this.getPaths();
296
+ const contents = renderPrincipalsCommandScript({
297
+ systemRootDir: this.systemRootDir,
298
+ nodePath: this.options.helperNodePath,
299
+ cliPath: this.options.helperCliPath,
300
+ platformOverride: this.getPlatform(),
301
+ });
302
+ await writeFile(paths.principalsCommandPath, contents, 'utf8');
303
+ if (this.getPlatform() !== 'win32') {
304
+ await chmod(paths.principalsCommandPath, 0o755);
305
+ }
306
+ }
307
+ async applyUserOwnership(filePath) {
308
+ await this.options.applyUserOwnership(filePath);
309
+ }
310
+ getPlatform() {
311
+ return getPlatform(this.options.platformOverride);
312
+ }
313
+ async reloadSshd() {
314
+ if (!this.options.reloadSshd) {
315
+ return;
316
+ }
317
+ if (this.getPlatform() === 'win32') {
318
+ await execFileAsync('powershell.exe', ['-Command', 'Restart-Service sshd']);
319
+ return;
320
+ }
321
+ if (this.getPlatform() === 'darwin') {
322
+ await execFileAsync('launchctl', ['kickstart', '-k', 'system/com.openssh.sshd']);
323
+ return;
324
+ }
325
+ await execFileAsync('sh', ['-lc', 'systemctl reload sshd || systemctl reload ssh']);
326
+ }
327
+ }
328
+ //# sourceMappingURL=system-ssh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-ssh.js","sourceRoot":"","sources":["../../src/ssh/system-ssh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=system-ssh.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-ssh.test.d.ts","sourceRoot":"","sources":["../../src/ssh/system-ssh.test.ts"],"names":[],"mappings":""}