nterminal 1.3.13 → 1.3.14
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/README.md +1 -1
- package/dist/client/assets/MarkdownPreview-Bqq8nsbg.js +1 -0
- package/dist/client/assets/{TranscriptMarkdownBody-BAkL6ovK.js → TranscriptMarkdownBody-DkUMrYOc.js} +1 -1
- package/dist/client/assets/{index-WSS03d_S.js → index-DW6pRsCC.js} +29 -29
- package/dist/client/assets/{index-DLFQwECZ.js → index-iZGXrm6V.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/scripts/onboarding.js +320 -134
- package/dist/scripts/onboarding.js.map +1 -1
- package/dist/server/accounts/accountService.d.ts +4 -0
- package/dist/server/accounts/accountService.js +102 -9
- package/dist/server/accounts/accountService.js.map +1 -1
- package/dist/server/agent/agentProxy.js +4 -1
- package/dist/server/agent/agentProxy.js.map +1 -1
- package/dist/server/agent/agentTransport.d.ts +11 -0
- package/dist/server/agent/agentTransport.js +117 -0
- package/dist/server/agent/agentTransport.js.map +1 -0
- package/dist/server/agent/agentWebSocketProxy.js +3 -0
- package/dist/server/agent/agentWebSocketProxy.js.map +1 -1
- package/dist/server/agent/directTlsIdentity.d.ts +39 -0
- package/dist/server/agent/directTlsIdentity.js +493 -0
- package/dist/server/agent/directTlsIdentity.js.map +1 -0
- package/dist/server/agent/directTlsMigration.d.ts +25 -0
- package/dist/server/agent/directTlsMigration.js +322 -0
- package/dist/server/agent/directTlsMigration.js.map +1 -0
- package/dist/server/agent/directTlsProtocol.d.ts +10 -0
- package/dist/server/agent/directTlsProtocol.js +32 -0
- package/dist/server/agent/directTlsProtocol.js.map +1 -0
- package/dist/server/agent/directTlsServer.d.ts +7 -0
- package/dist/server/agent/directTlsServer.js +72 -0
- package/dist/server/agent/directTlsServer.js.map +1 -0
- package/dist/server/agent/outboundAgentRegistry.js +2 -1
- package/dist/server/agent/outboundAgentRegistry.js.map +1 -1
- package/dist/server/agent/secondaryDirectTls.d.ts +20 -0
- package/dist/server/agent/secondaryDirectTls.js +143 -0
- package/dist/server/agent/secondaryDirectTls.js.map +1 -0
- package/dist/server/config.d.ts +1 -0
- package/dist/server/config.js +1 -0
- package/dist/server/config.js.map +1 -1
- package/dist/server/hooks/hookInstallation.d.ts +2 -0
- package/dist/server/hooks/hookInstallation.js +42 -17
- package/dist/server/hooks/hookInstallation.js.map +1 -1
- package/dist/server/hooks/verifiedLock.js +96 -2
- package/dist/server/hooks/verifiedLock.js.map +1 -1
- package/dist/server/http.d.ts +2 -0
- package/dist/server/http.js +9 -1
- package/dist/server/http.js.map +1 -1
- package/dist/server/index.js +26 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/notifications/agentCompletionMonitor.js +4 -2
- package/dist/server/notifications/agentCompletionMonitor.js.map +1 -1
- package/dist/server/routes/agentManagementRoutes.js +73 -7
- package/dist/server/routes/agentManagementRoutes.js.map +1 -1
- package/dist/server/storage/fileStore.d.ts +12 -1
- package/dist/server/storage/fileStore.js +30 -6
- package/dist/server/storage/fileStore.js.map +1 -1
- package/docs/onboarding.md +58 -5
- package/docs/provider-hooks.md +24 -3
- package/package.json +5 -4
- package/scripts/nterminalctl +25 -2
- package/dist/client/assets/MarkdownPreview-8vEkrQtk.js +0 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface DirectTlsIdentity {
|
|
2
|
+
certificate: string;
|
|
3
|
+
privateKey: string;
|
|
4
|
+
}
|
|
5
|
+
export interface DirectTlsLink {
|
|
6
|
+
agentId: string;
|
|
7
|
+
mainUrl: string;
|
|
8
|
+
required: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface DirectTlsIdentityOptions {
|
|
11
|
+
requireExisting?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const DIRECT_TLS_CERTIFICATE_DAYS = 365;
|
|
14
|
+
export declare const DIRECT_TLS_RENEW_BEFORE_MS: number;
|
|
15
|
+
/**
|
|
16
|
+
* One self-signed agent certificate; never a chain or a CN fallback. Expired
|
|
17
|
+
* pins may be retained during an explicit transition, but not future-dated pins.
|
|
18
|
+
* Local loading, renewal, and activation deliberately use the strict default.
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateAgentCertificate(pem: unknown, options?: {
|
|
21
|
+
allowExpired?: boolean;
|
|
22
|
+
}): string;
|
|
23
|
+
export declare function readDirectTlsLink(stateDir: string): Promise<DirectTlsLink | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Explicit state only, outside the installed package. Never silently renews.
|
|
26
|
+
* Expired committed certificates fail closed with direct_tls_certificate_expired
|
|
27
|
+
* and remain untouched: missed renewal requires explicit operator repair.
|
|
28
|
+
*/
|
|
29
|
+
export declare function ensureDirectTlsIdentity(stateDir: string, options?: DirectTlsIdentityOptions): Promise<DirectTlsIdentity>;
|
|
30
|
+
/**
|
|
31
|
+
* Durable activation CAS. The parent must roll out overlapping CA pins first,
|
|
32
|
+
* then hot-reload only after success. A stale expected identity is a conflict;
|
|
33
|
+
* missing, invalid, or expired committed state is never repaired by this API.
|
|
34
|
+
* An I/O error after rename can leave next committed: reload to reconcile before
|
|
35
|
+
* retrying activation. This function does not manage the parent's staged file.
|
|
36
|
+
*/
|
|
37
|
+
export declare function saveDirectTlsIdentity(stateDir: string, expected: DirectTlsIdentity, next: DirectTlsIdentity): Promise<void>;
|
|
38
|
+
/** Staging only: preserve the private key; the parent owns pin rollout and activation. */
|
|
39
|
+
export declare function createRenewedDirectTlsIdentity(identity: DirectTlsIdentity): Promise<DirectTlsIdentity>;
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { createPrivateKey, randomBytes, sign, verify, X509Certificate } from 'node:crypto';
|
|
3
|
+
import { constants } from 'node:fs';
|
|
4
|
+
import { lstat, mkdir, mkdtemp, open, readdir, realpath, rename, rmdir, unlink } from 'node:fs/promises';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { promisify } from 'node:util';
|
|
10
|
+
import { acquireVerifiedLock, VerifiedLockError } from '../hooks/verifiedLock.js';
|
|
11
|
+
import { httpsOrigin } from './directTlsProtocol.js';
|
|
12
|
+
export const DIRECT_TLS_CERTIFICATE_DAYS = 365;
|
|
13
|
+
export const DIRECT_TLS_RENEW_BEFORE_MS = 30 * 24 * 60 * 60 * 1000;
|
|
14
|
+
const AGENT_NAME = 'nterminal-agent.invalid';
|
|
15
|
+
const MAX_PEM_BYTES = 16 * 1024;
|
|
16
|
+
const MAX_IDENTITY_BYTES = 48 * 1024;
|
|
17
|
+
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
18
|
+
const runFile = promisify(execFile);
|
|
19
|
+
const pendingEnsures = new Map();
|
|
20
|
+
const WORK_FILES = new Set(['openssl.cnf', 'private-key.pem', 'certificate.pem', 'identity.json']);
|
|
21
|
+
const OPENSSL_CONFIG = `[req]
|
|
22
|
+
prompt = no
|
|
23
|
+
distinguished_name = subject
|
|
24
|
+
[subject]
|
|
25
|
+
CN = ${AGENT_NAME}
|
|
26
|
+
[agent]
|
|
27
|
+
subjectAltName = DNS:${AGENT_NAME}
|
|
28
|
+
subjectKeyIdentifier = hash
|
|
29
|
+
# Bind the issuer serial so same-key renewal pins cannot shadow one another.
|
|
30
|
+
authorityKeyIdentifier = keyid,issuer:always
|
|
31
|
+
basicConstraints = critical,CA:FALSE
|
|
32
|
+
keyUsage = critical,digitalSignature
|
|
33
|
+
extendedKeyUsage = serverAuth
|
|
34
|
+
`;
|
|
35
|
+
function failure(reason) { return new Error(`direct_tls_${reason}`); }
|
|
36
|
+
class CertificateExpiredError extends Error {
|
|
37
|
+
constructor() { super('direct_tls_certificate_expired'); }
|
|
38
|
+
}
|
|
39
|
+
function missing(error) { return error?.code === 'ENOENT'; }
|
|
40
|
+
function exists(error) { return error?.code === 'EEXIST'; }
|
|
41
|
+
function uid() {
|
|
42
|
+
if (!process.getuid)
|
|
43
|
+
throw failure('unsupported_platform');
|
|
44
|
+
return process.getuid();
|
|
45
|
+
}
|
|
46
|
+
function singlePem(pem, labels) {
|
|
47
|
+
if (typeof pem !== 'string' || Buffer.byteLength(pem, 'utf8') > MAX_PEM_BYTES)
|
|
48
|
+
throw failure('invalid_pem');
|
|
49
|
+
const match = new RegExp(`^[ \\t\\r\\n]*-----BEGIN (${labels})-----\\r?\\n([A-Za-z0-9+/=\\r\\n]+)\\r?\\n-----END \\1-----[ \\t\\r\\n]*$`).exec(pem);
|
|
50
|
+
if (!match)
|
|
51
|
+
throw failure('invalid_pem');
|
|
52
|
+
const base64 = match[2].replace(/[\r\n]/g, '');
|
|
53
|
+
const der = Buffer.from(base64, 'base64');
|
|
54
|
+
if (!base64 || der.toString('base64') !== base64 || der[0] !== 0x30)
|
|
55
|
+
throw failure('invalid_pem');
|
|
56
|
+
// OpenSSL accepts trailing DER bytes. Require precisely one definite-length
|
|
57
|
+
// DER sequence, including minimal length encoding, before asking it to parse.
|
|
58
|
+
const first = der[1];
|
|
59
|
+
if (first === undefined)
|
|
60
|
+
throw failure('invalid_pem');
|
|
61
|
+
let header = 2;
|
|
62
|
+
let length = first;
|
|
63
|
+
if (first & 0x80) {
|
|
64
|
+
const count = first & 0x7f;
|
|
65
|
+
if (count < 1 || count > 3 || der.length < 2 + count || der[2] === 0)
|
|
66
|
+
throw failure('invalid_pem');
|
|
67
|
+
header += count;
|
|
68
|
+
length = der.readUIntBE(2, count);
|
|
69
|
+
if (length < 128)
|
|
70
|
+
throw failure('invalid_pem');
|
|
71
|
+
}
|
|
72
|
+
if (header + length !== der.length)
|
|
73
|
+
throw failure('invalid_pem');
|
|
74
|
+
return { label: match[1], der };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* One self-signed agent certificate; never a chain or a CN fallback. Expired
|
|
78
|
+
* pins may be retained during an explicit transition, but not future-dated pins.
|
|
79
|
+
* Local loading, renewal, and activation deliberately use the strict default.
|
|
80
|
+
*/
|
|
81
|
+
export function validateAgentCertificate(pem, options = {}) {
|
|
82
|
+
try {
|
|
83
|
+
const { der } = singlePem(pem, 'CERTIFICATE');
|
|
84
|
+
const cert = new X509Certificate(der);
|
|
85
|
+
const now = Date.now();
|
|
86
|
+
const from = Date.parse(cert.validFrom);
|
|
87
|
+
const to = Date.parse(cert.validTo);
|
|
88
|
+
if (!cert.raw.equals(der) || !Number.isFinite(from) || !Number.isFinite(to)
|
|
89
|
+
|| from > now || to <= from || cert.subject !== cert.issuer || !cert.verify(cert.publicKey)) {
|
|
90
|
+
throw failure('invalid_certificate');
|
|
91
|
+
}
|
|
92
|
+
if (cert.checkHost(AGENT_NAME, { subject: 'never', wildcards: false, partialWildcards: false,
|
|
93
|
+
multiLabelWildcards: false, singleLabelSubdomains: false })?.toLowerCase() !== AGENT_NAME) {
|
|
94
|
+
throw failure('invalid_certificate');
|
|
95
|
+
}
|
|
96
|
+
const key = cert.publicKey;
|
|
97
|
+
const details = key.asymmetricKeyDetails;
|
|
98
|
+
const rsa = (key.asymmetricKeyType === 'rsa' || key.asymmetricKeyType === 'rsa-pss')
|
|
99
|
+
&& (details?.modulusLength ?? 0) >= 2048;
|
|
100
|
+
const ec = key.asymmetricKeyType === 'ec'
|
|
101
|
+
&& ['prime256v1', 'secp256k1', 'secp384r1', 'secp521r1'].includes(details?.namedCurve ?? '');
|
|
102
|
+
if (!rsa && !ec)
|
|
103
|
+
throw failure('invalid_certificate');
|
|
104
|
+
if (to <= now && options.allowExpired !== true)
|
|
105
|
+
throw new CertificateExpiredError();
|
|
106
|
+
const canonical = cert.toString();
|
|
107
|
+
if (Buffer.byteLength(canonical) > MAX_PEM_BYTES)
|
|
108
|
+
throw failure('invalid_certificate');
|
|
109
|
+
return canonical;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (error instanceof CertificateExpiredError)
|
|
113
|
+
throw error;
|
|
114
|
+
throw failure('invalid_certificate');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function validateIdentity(value) {
|
|
118
|
+
try {
|
|
119
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
120
|
+
throw failure('invalid_identity');
|
|
121
|
+
const record = value;
|
|
122
|
+
if (Object.keys(record).length !== 2 || typeof record.privateKey !== 'string')
|
|
123
|
+
throw failure('invalid_identity');
|
|
124
|
+
const certificate = validateAgentCertificate(record.certificate);
|
|
125
|
+
const { label, der } = singlePem(record.privateKey, 'PRIVATE KEY|RSA PRIVATE KEY|EC PRIVATE KEY');
|
|
126
|
+
const key = createPrivateKey({ key: der, format: 'der',
|
|
127
|
+
type: label === 'PRIVATE KEY' ? 'pkcs8' : label === 'RSA PRIVATE KEY' ? 'pkcs1' : 'sec1' });
|
|
128
|
+
const cert = new X509Certificate(certificate);
|
|
129
|
+
if (!cert.checkPrivateKey(key))
|
|
130
|
+
throw failure('invalid_identity');
|
|
131
|
+
// Matching public fields alone does not detect a damaged private scalar or
|
|
132
|
+
// RSA private components in an otherwise parseable key container.
|
|
133
|
+
const challenge = Buffer.from('nterminal-direct-tls-key-consistency', 'ascii');
|
|
134
|
+
const digest = key.asymmetricKeyDetails?.hashAlgorithm ?? 'sha256';
|
|
135
|
+
if (!verify(digest, challenge, cert.publicKey, sign(digest, challenge, key)))
|
|
136
|
+
throw failure('invalid_identity');
|
|
137
|
+
return { certificate, privateKey: record.privateKey };
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
if (error instanceof CertificateExpiredError)
|
|
141
|
+
throw error;
|
|
142
|
+
throw failure('invalid_identity');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function safeDirectory(info, owned, privateMode = false) {
|
|
146
|
+
const owner = uid();
|
|
147
|
+
// Root-owned, sticky system temp directories are trusted ancestors, not state
|
|
148
|
+
// directories. All other writable-by-others or foreign-owned paths fail shut.
|
|
149
|
+
const systemTemp = !owned && info.uid === 0 && (info.mode & 0o1000) !== 0;
|
|
150
|
+
if (!info.isDirectory() || (info.uid !== owner && (owned || info.uid !== 0))
|
|
151
|
+
|| (!systemTemp && (info.mode & 0o022) !== 0)
|
|
152
|
+
|| (privateMode && (info.mode & 0o7777) !== 0o700))
|
|
153
|
+
throw failure('unsafe_path');
|
|
154
|
+
}
|
|
155
|
+
async function directoryChain(directory, create = false, ownedLeaf = true) {
|
|
156
|
+
const root = path.parse(directory).root;
|
|
157
|
+
let current = root;
|
|
158
|
+
safeDirectory(await lstat(root), false);
|
|
159
|
+
for (const component of directory.slice(root.length).split(path.sep).filter(Boolean)) {
|
|
160
|
+
const parent = current;
|
|
161
|
+
current = path.join(current, component);
|
|
162
|
+
if (create) {
|
|
163
|
+
try {
|
|
164
|
+
await mkdir(current, { mode: 0o700 });
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if (!exists(error))
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
safeDirectory(await lstat(current), ownedLeaf && current === directory);
|
|
172
|
+
// Sync even existing entries: the previous owner may have exited between
|
|
173
|
+
// mkdir and its directory fsync. No successfully returned path is volatile.
|
|
174
|
+
if (create)
|
|
175
|
+
await syncDirectory(parent);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async function syncDirectory(directory) {
|
|
179
|
+
const handle = await open(directory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
180
|
+
try {
|
|
181
|
+
safeDirectory(await handle.stat(), false);
|
|
182
|
+
await handle.sync();
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
await handle.close();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function privateDirectory(directory) {
|
|
189
|
+
try {
|
|
190
|
+
await mkdir(directory, { mode: 0o700 });
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
if (!exists(error))
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
safeDirectory(await lstat(directory), true, true);
|
|
197
|
+
await syncDirectory(path.dirname(directory));
|
|
198
|
+
}
|
|
199
|
+
function safeFile(info) {
|
|
200
|
+
if (!info.isFile() || info.uid !== uid() || info.nlink !== 1 || (info.mode & 0o7777) !== 0o600) {
|
|
201
|
+
throw failure('unsafe_path');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async function readPrivateFile(file, durable = false) {
|
|
205
|
+
let handle;
|
|
206
|
+
try {
|
|
207
|
+
handle = await open(file, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
if (missing(error))
|
|
211
|
+
return null;
|
|
212
|
+
throw failure('unsafe_path');
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const before = await handle.stat();
|
|
216
|
+
safeFile(before);
|
|
217
|
+
if (before.size > MAX_IDENTITY_BYTES)
|
|
218
|
+
throw failure('file_too_large');
|
|
219
|
+
const buffer = Buffer.alloc(MAX_IDENTITY_BYTES + 1);
|
|
220
|
+
let size = 0;
|
|
221
|
+
while (size < buffer.length) {
|
|
222
|
+
const { bytesRead } = await handle.read(buffer, size, buffer.length - size, null);
|
|
223
|
+
if (bytesRead === 0)
|
|
224
|
+
break;
|
|
225
|
+
size += bytesRead;
|
|
226
|
+
}
|
|
227
|
+
if (size > MAX_IDENTITY_BYTES)
|
|
228
|
+
throw failure('file_too_large');
|
|
229
|
+
const after = await handle.stat();
|
|
230
|
+
safeFile(after);
|
|
231
|
+
const entry = await lstat(file);
|
|
232
|
+
if (entry.ino !== after.ino || entry.dev !== after.dev || before.size !== after.size
|
|
233
|
+
|| before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs)
|
|
234
|
+
throw failure('file_changed');
|
|
235
|
+
if (durable)
|
|
236
|
+
await handle.sync();
|
|
237
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(buffer.subarray(0, size));
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
await handle.close();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async function writePrivateFile(file, text) {
|
|
244
|
+
const handle = await open(file, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
245
|
+
try {
|
|
246
|
+
await handle.chmod(0o600);
|
|
247
|
+
safeFile(await handle.stat());
|
|
248
|
+
await handle.writeFile(text, 'utf8');
|
|
249
|
+
await handle.sync();
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
await handle.close();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async function readIdentity(file) {
|
|
256
|
+
const text = await readPrivateFile(file, true);
|
|
257
|
+
if (text === null)
|
|
258
|
+
return null;
|
|
259
|
+
try {
|
|
260
|
+
return validateIdentity(JSON.parse(text));
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
if (error instanceof CertificateExpiredError)
|
|
264
|
+
throw error;
|
|
265
|
+
throw failure('invalid_identity');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
export async function readDirectTlsLink(stateDir) {
|
|
269
|
+
const directory = path.join(resolveStateDirectory(stateDir), 'direct-tls');
|
|
270
|
+
await directoryChain(directory);
|
|
271
|
+
const text = await readPrivateFile(path.join(directory, 'link.json'), true);
|
|
272
|
+
if (text === null)
|
|
273
|
+
return null;
|
|
274
|
+
try {
|
|
275
|
+
const link = JSON.parse(text);
|
|
276
|
+
if (!link || typeof link.agentId !== 'string' || !link.agentId || typeof link.required !== 'boolean') {
|
|
277
|
+
throw failure('invalid_state');
|
|
278
|
+
}
|
|
279
|
+
return { agentId: link.agentId, mainUrl: httpsOrigin(link.mainUrl), required: link.required };
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
throw new Error('invalid_direct_tls_state');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function sameIdentity(actual, expected) {
|
|
286
|
+
return actual === null || expected === null ? actual === expected
|
|
287
|
+
: actual.certificate === expected.certificate && actual.privateKey === expected.privateKey;
|
|
288
|
+
}
|
|
289
|
+
async function commitIdentity(directory, work, expected, next) {
|
|
290
|
+
const staged = path.join(work, 'identity.json');
|
|
291
|
+
const file = path.join(directory, 'identity.json');
|
|
292
|
+
await writePrivateFile(staged, `${JSON.stringify(next)}\n`);
|
|
293
|
+
await syncDirectory(work);
|
|
294
|
+
if (!sameIdentity(await readIdentity(file), expected))
|
|
295
|
+
throw failure('identity_conflict');
|
|
296
|
+
await rename(staged, file);
|
|
297
|
+
await syncDirectory(directory);
|
|
298
|
+
await syncDirectory(work);
|
|
299
|
+
}
|
|
300
|
+
async function clearWork(directory) {
|
|
301
|
+
let info;
|
|
302
|
+
try {
|
|
303
|
+
info = await lstat(directory);
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
if (missing(error))
|
|
307
|
+
return;
|
|
308
|
+
throw error;
|
|
309
|
+
}
|
|
310
|
+
safeDirectory(info, true, true);
|
|
311
|
+
const names = await readdir(directory);
|
|
312
|
+
// Never recursively remove unknown or linked entries, even during recovery.
|
|
313
|
+
for (const name of names) {
|
|
314
|
+
if (!WORK_FILES.has(name))
|
|
315
|
+
throw failure('unsafe_staging');
|
|
316
|
+
safeFile(await lstat(path.join(directory, name)));
|
|
317
|
+
}
|
|
318
|
+
for (const name of names)
|
|
319
|
+
await unlink(path.join(directory, name));
|
|
320
|
+
await rmdir(directory);
|
|
321
|
+
await syncDirectory(path.dirname(directory));
|
|
322
|
+
}
|
|
323
|
+
async function generateIdentity(work, privateKey) {
|
|
324
|
+
await writePrivateFile(path.join(work, 'openssl.cnf'), OPENSSL_CONFIG);
|
|
325
|
+
await writePrivateFile(path.join(work, 'private-key.pem'), privateKey ?? '');
|
|
326
|
+
await writePrivateFile(path.join(work, 'certificate.pem'), '');
|
|
327
|
+
const options = { cwd: work, encoding: 'utf8', maxBuffer: 64 * 1024, timeout: 5000, killSignal: 'SIGKILL',
|
|
328
|
+
env: { PATH: process.env.PATH ?? '/usr/bin:/bin', OPENSSL_CONF: path.join(work, 'openssl.cnf') } };
|
|
329
|
+
try {
|
|
330
|
+
if (privateKey === undefined) {
|
|
331
|
+
await runFile('openssl', ['genpkey', '-algorithm', 'EC', '-pkeyopt', 'ec_paramgen_curve:P-256', '-out', 'private-key.pem'], options);
|
|
332
|
+
}
|
|
333
|
+
await runFile('openssl', ['req', '-new', '-x509', '-batch', '-sha256', '-days', String(DIRECT_TLS_CERTIFICATE_DAYS),
|
|
334
|
+
'-key', 'private-key.pem', '-out', 'certificate.pem', '-config', 'openssl.cnf', '-extensions', 'agent',
|
|
335
|
+
'-set_serial', `0x${randomBytes(16).toString('hex')}`], options);
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
throw failure('openssl_failed');
|
|
339
|
+
}
|
|
340
|
+
return validateIdentity({ certificate: await readPrivateFile(path.join(work, 'certificate.pem')),
|
|
341
|
+
privateKey: privateKey ?? await readPrivateFile(path.join(work, 'private-key.pem')) });
|
|
342
|
+
}
|
|
343
|
+
async function lockIdentity(directory) {
|
|
344
|
+
const lock = path.join(directory, '.identity.lock');
|
|
345
|
+
const owners = `${lock}.owners`;
|
|
346
|
+
await privateDirectory(owners);
|
|
347
|
+
const deadline = performance.now() + 30_000;
|
|
348
|
+
for (;;) {
|
|
349
|
+
// The shared lock checks identity and hard links; enforce this store's more
|
|
350
|
+
// restrictive directory modes before it reads or reclaims owner records.
|
|
351
|
+
for (const name of await readdir(owners)) {
|
|
352
|
+
try {
|
|
353
|
+
safeDirectory(await lstat(path.join(owners, name)), true, true);
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
if (!missing(error))
|
|
357
|
+
throw error;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
return (await acquireVerifiedLock(lock)).release;
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
if (!(error instanceof VerifiedLockError) || !error.retryable)
|
|
365
|
+
throw error;
|
|
366
|
+
if (performance.now() >= deadline)
|
|
367
|
+
throw failure('busy');
|
|
368
|
+
await delay(20 + Math.floor(Math.random() * 30));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async function ensureIdentity(stateDir, requireExisting) {
|
|
373
|
+
await directoryChain(stateDir, true);
|
|
374
|
+
const directory = path.join(stateDir, 'direct-tls');
|
|
375
|
+
await privateDirectory(directory);
|
|
376
|
+
const release = await lockIdentity(directory);
|
|
377
|
+
const file = path.join(directory, 'identity.json');
|
|
378
|
+
const work = path.join(directory, '.identity-work');
|
|
379
|
+
try {
|
|
380
|
+
await directoryChain(directory);
|
|
381
|
+
const link = await readDirectTlsLink(stateDir);
|
|
382
|
+
const existing = await readIdentity(file);
|
|
383
|
+
if (!existing && (requireExisting || link?.required))
|
|
384
|
+
throw failure('identity_missing');
|
|
385
|
+
// A verified lock proves any previous writer is gone before discarding its
|
|
386
|
+
// incomplete staging. A committed but invalid identity is never replaced.
|
|
387
|
+
await clearWork(work);
|
|
388
|
+
if (existing) {
|
|
389
|
+
await syncDirectory(directory);
|
|
390
|
+
return existing;
|
|
391
|
+
}
|
|
392
|
+
await privateDirectory(work);
|
|
393
|
+
try {
|
|
394
|
+
const identity = await generateIdentity(work);
|
|
395
|
+
await commitIdentity(directory, work, null, identity);
|
|
396
|
+
return identity;
|
|
397
|
+
}
|
|
398
|
+
finally {
|
|
399
|
+
await clearWork(work);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
finally {
|
|
403
|
+
await release();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function resolveStateDirectory(stateDir) {
|
|
407
|
+
if (typeof stateDir !== 'string' || !stateDir.trim() || stateDir.includes('\0'))
|
|
408
|
+
throw failure('invalid_state_directory');
|
|
409
|
+
const directory = path.resolve(stateDir);
|
|
410
|
+
const relative = path.relative(PACKAGE_ROOT, directory);
|
|
411
|
+
if (relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative))
|
|
412
|
+
|| directory.split(path.sep).includes('node_modules'))
|
|
413
|
+
throw failure('state_in_package');
|
|
414
|
+
return directory;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Explicit state only, outside the installed package. Never silently renews.
|
|
418
|
+
* Expired committed certificates fail closed with direct_tls_certificate_expired
|
|
419
|
+
* and remain untouched: missed renewal requires explicit operator repair.
|
|
420
|
+
*/
|
|
421
|
+
export async function ensureDirectTlsIdentity(stateDir, options = {}) {
|
|
422
|
+
const directory = resolveStateDirectory(stateDir);
|
|
423
|
+
// A load-only request must never join a request allowed to generate a key.
|
|
424
|
+
const key = `${directory}\0${options.requireExisting === true ? 'existing' : 'create'}`;
|
|
425
|
+
let pending = pendingEnsures.get(key);
|
|
426
|
+
if (!pending) {
|
|
427
|
+
pending = ensureIdentity(directory, options.requireExisting === true);
|
|
428
|
+
pendingEnsures.set(key, pending);
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
return { ...await pending };
|
|
432
|
+
}
|
|
433
|
+
finally {
|
|
434
|
+
if (pendingEnsures.get(key) === pending)
|
|
435
|
+
pendingEnsures.delete(key);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Durable activation CAS. The parent must roll out overlapping CA pins first,
|
|
440
|
+
* then hot-reload only after success. A stale expected identity is a conflict;
|
|
441
|
+
* missing, invalid, or expired committed state is never repaired by this API.
|
|
442
|
+
* An I/O error after rename can leave next committed: reload to reconcile before
|
|
443
|
+
* retrying activation. This function does not manage the parent's staged file.
|
|
444
|
+
*/
|
|
445
|
+
export async function saveDirectTlsIdentity(stateDir, expected, next) {
|
|
446
|
+
const state = resolveStateDirectory(stateDir);
|
|
447
|
+
const previous = validateIdentity(expected);
|
|
448
|
+
const replacement = validateIdentity(next);
|
|
449
|
+
await directoryChain(state);
|
|
450
|
+
const directory = path.join(state, 'direct-tls');
|
|
451
|
+
safeDirectory(await lstat(directory), true, true);
|
|
452
|
+
const release = await lockIdentity(directory);
|
|
453
|
+
const work = path.join(directory, '.identity-work');
|
|
454
|
+
try {
|
|
455
|
+
await directoryChain(directory);
|
|
456
|
+
const current = await readIdentity(path.join(directory, 'identity.json'));
|
|
457
|
+
if (!sameIdentity(current, previous))
|
|
458
|
+
throw failure('identity_conflict');
|
|
459
|
+
await clearWork(work);
|
|
460
|
+
if (sameIdentity(current, replacement)) {
|
|
461
|
+
await syncDirectory(directory);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
await privateDirectory(work);
|
|
465
|
+
try {
|
|
466
|
+
await commitIdentity(directory, work, previous, replacement);
|
|
467
|
+
}
|
|
468
|
+
finally {
|
|
469
|
+
await clearWork(work);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
finally {
|
|
473
|
+
await release();
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
/** Staging only: preserve the private key; the parent owns pin rollout and activation. */
|
|
477
|
+
export async function createRenewedDirectTlsIdentity(identity) {
|
|
478
|
+
const validated = validateIdentity(identity);
|
|
479
|
+
// Only the OS temp root may be an alias. Check the canonical path as strictly
|
|
480
|
+
// as before; state and identity paths must still never traverse symlinks.
|
|
481
|
+
const parent = await realpath(path.resolve(tmpdir()));
|
|
482
|
+
await directoryChain(path.dirname(parent), false, false);
|
|
483
|
+
safeDirectory(await lstat(parent), false);
|
|
484
|
+
const work = await mkdtemp(path.join(parent, 'nterminal-direct-tls-'));
|
|
485
|
+
try {
|
|
486
|
+
safeDirectory(await lstat(work), true, true);
|
|
487
|
+
return await generateIdentity(work, validated.privateKey);
|
|
488
|
+
}
|
|
489
|
+
finally {
|
|
490
|
+
await clearWork(work);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
//# sourceMappingURL=directTlsIdentity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directTlsIdentity.js","sourceRoot":"","sources":["../../../src/server/agent/directTlsIdentity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
|
+
import type { AppConfig } from '../config.js';
|
|
3
|
+
import type { FileStore, StoredAgent } from '../storage/fileStore.js';
|
|
4
|
+
import { type SecondaryDirectTls } from './secondaryDirectTls.js';
|
|
5
|
+
import type { AuthService } from '../auth/authService.js';
|
|
6
|
+
export declare function probeDirectTls(agent: StoredAgent): Promise<boolean>;
|
|
7
|
+
export declare function registerDirectTlsRoutes(app: FastifyInstance, config: AppConfig, store: FileStore, auth: AuthService, secondary?: SecondaryDirectTls): void;
|
|
8
|
+
/** Runs on main, independent of Update all/browser lifetime. At most two peers at a time. */
|
|
9
|
+
export declare class DirectTlsMigration {
|
|
10
|
+
private readonly config;
|
|
11
|
+
private readonly store;
|
|
12
|
+
private readonly warn;
|
|
13
|
+
private stopped;
|
|
14
|
+
private timer;
|
|
15
|
+
private readonly controller;
|
|
16
|
+
private readonly retryAfter;
|
|
17
|
+
constructor(config: AppConfig, store: FileStore, warn: (agentId: string, code: string) => void);
|
|
18
|
+
start(): void;
|
|
19
|
+
dispose(): void;
|
|
20
|
+
private schedule;
|
|
21
|
+
private run;
|
|
22
|
+
private needsRenewal;
|
|
23
|
+
renew(agent: StoredAgent): Promise<void>;
|
|
24
|
+
migrate(agent: StoredAgent, mainUrl: string): Promise<void>;
|
|
25
|
+
}
|