@lasso-ai/cli 1.4.1 → 1.4.3
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/dist/cli/host/certificates.js +187 -50
- package/package.json +1 -1
|
@@ -10,6 +10,8 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
10
10
|
const node_os_1 = __importDefault(require("node:os"));
|
|
11
11
|
const node_path_1 = __importDefault(require("node:path"));
|
|
12
12
|
const node_child_process_1 = require("node:child_process");
|
|
13
|
+
const node_https_1 = __importDefault(require("node:https"));
|
|
14
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
13
15
|
const paths_1 = require("./paths");
|
|
14
16
|
exports.TLS_KEY_FILE = node_path_1.default.join(paths_1.HOST_DIR, "host.key");
|
|
15
17
|
exports.TLS_CERT_FILE = node_path_1.default.join(paths_1.HOST_DIR, "host.crt");
|
|
@@ -17,79 +19,213 @@ function hasCertificate() {
|
|
|
17
19
|
return node_fs_1.default.existsSync(exports.TLS_KEY_FILE) && node_fs_1.default.existsSync(exports.TLS_CERT_FILE);
|
|
18
20
|
}
|
|
19
21
|
function isMkcertInstalled() {
|
|
22
|
+
// Check system PATH first
|
|
20
23
|
try {
|
|
21
24
|
(0, node_child_process_1.execFileSync)("mkcert", ["-version"], { stdio: "ignore" });
|
|
22
25
|
return true;
|
|
23
26
|
}
|
|
24
27
|
catch {
|
|
28
|
+
// Check local installation
|
|
29
|
+
try {
|
|
30
|
+
const localMkcert = node_path_1.default.join(node_os_1.default.homedir(), ".lasso", "bin", "mkcert");
|
|
31
|
+
if (node_fs_1.default.existsSync(localMkcert)) {
|
|
32
|
+
(0, node_child_process_1.execFileSync)(localMkcert, ["-version"], { stdio: "ignore" });
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch { }
|
|
25
37
|
return false;
|
|
26
38
|
}
|
|
27
39
|
}
|
|
28
|
-
|
|
40
|
+
function getMkcertPath() {
|
|
41
|
+
// Check local installation first
|
|
42
|
+
const localMkcert = node_path_1.default.join(node_os_1.default.homedir(), ".lasso", "bin", "mkcert");
|
|
43
|
+
if (node_fs_1.default.existsSync(localMkcert)) {
|
|
44
|
+
return localMkcert;
|
|
45
|
+
}
|
|
46
|
+
return "mkcert";
|
|
47
|
+
}
|
|
48
|
+
async function downloadMkcert() {
|
|
49
|
+
const platform = node_os_1.default.platform();
|
|
50
|
+
const arch = node_os_1.default.arch();
|
|
51
|
+
let downloadUrl;
|
|
52
|
+
let binaryName;
|
|
53
|
+
// Determine the correct binary for the platform
|
|
54
|
+
if (platform === "darwin") {
|
|
55
|
+
if (arch === "x64") {
|
|
56
|
+
downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-darwin-amd64";
|
|
57
|
+
binaryName = "mkcert-darwin-amd64";
|
|
58
|
+
}
|
|
59
|
+
else if (arch === "arm64") {
|
|
60
|
+
downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-darwin-arm64";
|
|
61
|
+
binaryName = "mkcert-darwin-arm64";
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return { ok: false, error: `Unsupported architecture: ${arch}` };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (platform === "linux") {
|
|
68
|
+
if (arch === "x64") {
|
|
69
|
+
downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64";
|
|
70
|
+
binaryName = "mkcert-linux-amd64";
|
|
71
|
+
}
|
|
72
|
+
else if (arch === "arm64") {
|
|
73
|
+
downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-arm64";
|
|
74
|
+
binaryName = "mkcert-linux-arm64";
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return { ok: false, error: `Unsupported architecture: ${arch}` };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return { ok: false, error: `Unsupported platform: ${platform}` };
|
|
82
|
+
}
|
|
29
83
|
return new Promise((resolve) => {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
84
|
+
const protocol = downloadUrl.startsWith("https") ? node_https_1.default : node_http_1.default;
|
|
85
|
+
const tempDir = node_os_1.default.tmpdir();
|
|
86
|
+
const tempPath = node_path_1.default.join(tempDir, binaryName);
|
|
87
|
+
console.log(`[Lasso] Downloading mkcert from ${downloadUrl}...`);
|
|
88
|
+
const file = node_fs_1.default.createWriteStream(tempPath);
|
|
89
|
+
protocol.get(downloadUrl, (response) => {
|
|
90
|
+
if (response.statusCode !== 200) {
|
|
91
|
+
node_fs_1.default.unlinkSync(tempPath);
|
|
92
|
+
return resolve({ ok: false, error: `Failed to download mkcert: ${response.statusCode}` });
|
|
39
93
|
}
|
|
40
|
-
|
|
41
|
-
|
|
94
|
+
response.pipe(file);
|
|
95
|
+
file.on("finish", () => {
|
|
96
|
+
file.close();
|
|
97
|
+
node_fs_1.default.chmodSync(tempPath, 0o755);
|
|
98
|
+
console.log(`[Lasso] ✓ mkcert downloaded to ${tempPath}`);
|
|
99
|
+
resolve({ ok: true, path: tempPath });
|
|
100
|
+
});
|
|
101
|
+
}).on("error", (error) => {
|
|
102
|
+
node_fs_1.default.unlinkSync(tempPath);
|
|
103
|
+
resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async function installMkcert() {
|
|
108
|
+
const platform = node_os_1.default.platform();
|
|
109
|
+
// Try package manager first
|
|
110
|
+
if (platform === "darwin") {
|
|
111
|
+
try {
|
|
112
|
+
(0, node_child_process_1.execFileSync)("brew", ["--version"], { stdio: "ignore" });
|
|
113
|
+
console.log("[Lasso] Installing mkcert via Homebrew...");
|
|
114
|
+
const installResult = await new Promise((resolve) => {
|
|
115
|
+
const install = (0, node_child_process_1.spawn)("brew", ["install", "mkcert", "nss"], { stdio: "inherit" });
|
|
116
|
+
install.on("close", (code) => {
|
|
117
|
+
if (code === 0)
|
|
118
|
+
resolve({ ok: true });
|
|
119
|
+
else
|
|
120
|
+
resolve({ ok: false, error: `Homebrew install failed with code ${code}` });
|
|
121
|
+
});
|
|
122
|
+
install.on("error", (error) => {
|
|
123
|
+
resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
if (installResult.ok) {
|
|
127
|
+
(0, node_child_process_1.execFileSync)("mkcert", ["-install"], { stdio: "ignore" });
|
|
128
|
+
console.log("[Lasso] ✓ mkcert installed and CA configured");
|
|
129
|
+
return { ok: true };
|
|
42
130
|
}
|
|
43
131
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
132
|
+
catch {
|
|
133
|
+
console.log("[Lasso] Homebrew not available, trying direct download...");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (platform === "linux") {
|
|
137
|
+
try {
|
|
138
|
+
(0, node_child_process_1.execFileSync)("apt-get", ["--version"], { stdio: "ignore" });
|
|
139
|
+
console.log("[Lasso] Installing mkcert via apt-get...");
|
|
140
|
+
const installResult = await new Promise((resolve) => {
|
|
141
|
+
const install = (0, node_child_process_1.spawn)("sudo", ["apt-get", "install", "-y", "mkcert"], { stdio: "inherit" });
|
|
142
|
+
install.on("close", (code) => {
|
|
143
|
+
if (code === 0)
|
|
144
|
+
resolve({ ok: true });
|
|
145
|
+
else
|
|
146
|
+
resolve({ ok: false, error: `apt-get install failed with code ${code}` });
|
|
147
|
+
});
|
|
148
|
+
install.on("error", (error) => {
|
|
149
|
+
resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
if (installResult.ok) {
|
|
153
|
+
(0, node_child_process_1.execFileSync)("mkcert", ["-install"], { stdio: "ignore" });
|
|
154
|
+
console.log("[Lasso] ✓ mkcert installed and CA configured");
|
|
155
|
+
return { ok: true };
|
|
60
156
|
}
|
|
61
157
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
158
|
+
catch {
|
|
159
|
+
try {
|
|
160
|
+
(0, node_child_process_1.execFileSync)("dnf", ["--version"], { stdio: "ignore" });
|
|
161
|
+
console.log("[Lasso] Installing mkcert via dnf...");
|
|
162
|
+
const installResult = await new Promise((resolve) => {
|
|
163
|
+
const install = (0, node_child_process_1.spawn)("sudo", ["dnf", "install", "-y", "mkcert"], { stdio: "inherit" });
|
|
164
|
+
install.on("close", (code) => {
|
|
165
|
+
if (code === 0)
|
|
166
|
+
resolve({ ok: true });
|
|
167
|
+
else
|
|
168
|
+
resolve({ ok: false, error: `dnf install failed with code ${code}` });
|
|
169
|
+
});
|
|
170
|
+
install.on("error", (error) => {
|
|
171
|
+
resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
if (installResult.ok) {
|
|
71
175
|
(0, node_child_process_1.execFileSync)("mkcert", ["-install"], { stdio: "ignore" });
|
|
72
176
|
console.log("[Lasso] ✓ mkcert installed and CA configured");
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
177
|
+
return { ok: true };
|
|
77
178
|
}
|
|
78
179
|
}
|
|
79
|
-
|
|
80
|
-
|
|
180
|
+
catch {
|
|
181
|
+
console.log("[Lasso] Package manager not available, trying direct download...");
|
|
81
182
|
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Fallback: Download mkcert binary directly from GitHub
|
|
186
|
+
console.log("[Lasso] Downloading mkcert binary from GitHub...");
|
|
187
|
+
const downloadResult = await downloadMkcert();
|
|
188
|
+
if (!downloadResult.ok || !downloadResult.path) {
|
|
189
|
+
return { ok: false, error: downloadResult.error || "Failed to download mkcert binary" };
|
|
190
|
+
}
|
|
191
|
+
// Copy binary to a permanent location
|
|
192
|
+
const binDir = node_path_1.default.join(node_os_1.default.homedir(), ".lasso", "bin");
|
|
193
|
+
node_fs_1.default.mkdirSync(binDir, { recursive: true, mode: 0o755 });
|
|
194
|
+
const mkcertPath = node_path_1.default.join(binDir, "mkcert");
|
|
195
|
+
node_fs_1.default.copyFileSync(downloadResult.path, mkcertPath);
|
|
196
|
+
node_fs_1.default.chmodSync(mkcertPath, 0o755);
|
|
197
|
+
// Clean up temp file
|
|
198
|
+
try {
|
|
199
|
+
node_fs_1.default.unlinkSync(downloadResult.path);
|
|
200
|
+
}
|
|
201
|
+
catch { }
|
|
202
|
+
// Install the local CA using the downloaded binary
|
|
203
|
+
try {
|
|
204
|
+
(0, node_child_process_1.execFileSync)(mkcertPath, ["-install"], { stdio: "inherit" });
|
|
205
|
+
console.log("[Lasso] ✓ mkcert installed and CA configured");
|
|
206
|
+
return { ok: true };
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
210
|
+
}
|
|
87
211
|
}
|
|
88
212
|
async function ensureHostCertificate(onProgress) {
|
|
89
213
|
node_fs_1.default.mkdirSync(paths_1.HOST_DIR, { recursive: true, mode: 0o700 });
|
|
214
|
+
// Check if certificate exists and is trusted
|
|
90
215
|
if (hasCertificate()) {
|
|
91
216
|
const certStatus = hostCertificateStatus();
|
|
92
|
-
|
|
217
|
+
// If certificate exists but is not trusted and mkcert is available, regenerate it
|
|
218
|
+
if (!certStatus.trusted && isMkcertInstalled()) {
|
|
219
|
+
onProgress?.("Regenerating certificate with mkcert for trusted SSL...");
|
|
220
|
+
try {
|
|
221
|
+
node_fs_1.default.unlinkSync(exports.TLS_CERT_FILE);
|
|
222
|
+
node_fs_1.default.unlinkSync(exports.TLS_KEY_FILE);
|
|
223
|
+
}
|
|
224
|
+
catch { }
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
return { ok: true, trusted: certStatus.trusted };
|
|
228
|
+
}
|
|
93
229
|
}
|
|
94
230
|
onProgress?.("Generating SSL certificate...");
|
|
95
231
|
// Try mkcert first - it creates system-trusted certificates
|
|
@@ -104,7 +240,8 @@ async function ensureHostCertificate(onProgress) {
|
|
|
104
240
|
if (isMkcertInstalled()) {
|
|
105
241
|
try {
|
|
106
242
|
onProgress?.("Creating trusted certificate with mkcert...");
|
|
107
|
-
|
|
243
|
+
const mkcertPath = getMkcertPath();
|
|
244
|
+
(0, node_child_process_1.execFileSync)(mkcertPath, ["-cert-file", exports.TLS_CERT_FILE, "-key-file", exports.TLS_KEY_FILE, "localhost", "127.0.0.1", "::1", "*.lasso"], { stdio: "ignore" });
|
|
108
245
|
node_fs_1.default.chmodSync(exports.TLS_KEY_FILE, 0o600);
|
|
109
246
|
onProgress?.("✓ SSL certificate ready (trusted)");
|
|
110
247
|
return { ok: true, trusted: true };
|
package/package.json
CHANGED