easy-devops 0.1.5 → 0.1.6
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/cli/managers/ssl-manager.js +124 -51
- package/package.json +1 -1
|
@@ -249,7 +249,6 @@ async function installCertbot() {
|
|
|
249
249
|
|
|
250
250
|
// ── Shared helpers ────────────────────────────────────────────────────────────
|
|
251
251
|
|
|
252
|
-
// Check multiple possible certbot locations — some methods install to different paths
|
|
253
252
|
async function verifyCertbot() {
|
|
254
253
|
const whereResult = await run('where.exe certbot 2>$null');
|
|
255
254
|
if (whereResult.success && whereResult.stdout.trim()) return true;
|
|
@@ -265,43 +264,105 @@ async function installCertbot() {
|
|
|
265
264
|
return false;
|
|
266
265
|
}
|
|
267
266
|
|
|
268
|
-
//
|
|
267
|
+
// Try every possible download mechanism — one may work even when others fail
|
|
269
268
|
const hasCurl = (await run('where.exe curl.exe 2>$null')).success;
|
|
269
|
+
|
|
270
270
|
async function downloadFile(url, dest) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
{
|
|
271
|
+
// 1. Invoke-WebRequest with TLS 1.2 forced
|
|
272
|
+
let r = await run(
|
|
273
|
+
`[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $ProgressPreference='SilentlyContinue'; Invoke-WebRequest -Uri '${url}' -OutFile '${dest}' -UseBasicParsing -TimeoutSec 60`,
|
|
274
|
+
{ timeout: 70000 },
|
|
275
|
+
);
|
|
276
|
+
if (r.success) return true;
|
|
277
|
+
|
|
278
|
+
// 2. System.Net.WebClient (different .NET code path)
|
|
279
|
+
r = await run(
|
|
280
|
+
`[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('${url}','${dest}')`,
|
|
281
|
+
{ timeout: 70000 },
|
|
282
|
+
);
|
|
283
|
+
if (r.success) return true;
|
|
284
|
+
|
|
285
|
+
// 3. BITS (Background Intelligent Transfer Service)
|
|
286
|
+
r = await run(
|
|
287
|
+
`Start-BitsTransfer -Source '${url}' -Destination '${dest}' -ErrorAction Stop`,
|
|
288
|
+
{ timeout: 70000 },
|
|
274
289
|
);
|
|
275
|
-
if (
|
|
290
|
+
if (r.success) return true;
|
|
291
|
+
|
|
292
|
+
// 4. curl.exe (independent TLS stack)
|
|
276
293
|
if (hasCurl) {
|
|
277
|
-
|
|
278
|
-
|
|
294
|
+
r = await run(
|
|
295
|
+
`curl.exe -L --ssl-no-revoke --silent --show-error --max-time 60 -o '${dest}' '${url}'`,
|
|
296
|
+
{ timeout: 70000 },
|
|
297
|
+
);
|
|
298
|
+
if (r.success) return true;
|
|
279
299
|
}
|
|
300
|
+
|
|
301
|
+
// 5. System.Net.Http.HttpClient (most modern .NET stack)
|
|
302
|
+
r = await run(
|
|
303
|
+
`[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $hc=[System.Net.Http.HttpClient]::new(); $hc.DefaultRequestHeaders.Add('User-Agent','Mozilla/5.0'); $bytes=$hc.GetByteArrayAsync('${url}').GetAwaiter().GetResult(); [System.IO.File]::WriteAllBytes('${dest}',$bytes)`,
|
|
304
|
+
{ timeout: 70000 },
|
|
305
|
+
);
|
|
306
|
+
if (r.success) return true;
|
|
307
|
+
|
|
280
308
|
return false;
|
|
281
309
|
}
|
|
282
310
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
311
|
+
async function runNsisInstaller(exePath) {
|
|
312
|
+
await run(
|
|
313
|
+
`$p = Start-Process -FilePath '${exePath}' -ArgumentList '/S' -PassThru -Wait; $p.ExitCode`,
|
|
314
|
+
{ timeout: 120000 },
|
|
315
|
+
);
|
|
316
|
+
await new Promise(res => setTimeout(res, 4000));
|
|
317
|
+
return verifyCertbot();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
let methodNum = 0;
|
|
321
|
+
function step(label) {
|
|
322
|
+
methodNum++;
|
|
323
|
+
console.log(chalk.gray(`\n [${methodNum}] ${label}\n`));
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ── Method 1: pip / pip3 (PyPI CDN — completely different from GitHub/EFF) ────
|
|
327
|
+
for (const pip of ['pip', 'pip3']) {
|
|
328
|
+
const check = await run(`where.exe ${pip} 2>$null`);
|
|
329
|
+
if (check.success && check.stdout.trim()) {
|
|
330
|
+
step(`Trying ${pip} install certbot ...`);
|
|
331
|
+
const exitCode = await runLive(`${pip} install certbot`, { timeout: 180000 });
|
|
332
|
+
if (exitCode === 0 || await verifyCertbot()) return { success: true };
|
|
333
|
+
console.log(chalk.yellow(` ${pip} did not install certbot, trying next...\n`));
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ── Method 2: winget ──────────────────────────────────────────────────────────
|
|
339
|
+
if ((await run('where.exe winget 2>$null')).success) {
|
|
340
|
+
step('Trying winget ...');
|
|
287
341
|
const exitCode = await runLive(
|
|
288
342
|
'winget install -e --id EFF.Certbot --accept-package-agreements --accept-source-agreements',
|
|
289
343
|
{ timeout: 180000 },
|
|
290
344
|
);
|
|
291
345
|
if (exitCode === 0 || await verifyCertbot()) return { success: true };
|
|
292
|
-
console.log(chalk.yellow(' winget did not install certbot, trying next
|
|
346
|
+
console.log(chalk.yellow(' winget did not install certbot, trying next...\n'));
|
|
293
347
|
}
|
|
294
348
|
|
|
295
|
-
// ── Method
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
console.log(chalk.gray('\n [2/4] Trying Chocolatey ...\n'));
|
|
349
|
+
// ── Method 3: Chocolatey ──────────────────────────────────────────────────────
|
|
350
|
+
if ((await run('where.exe choco 2>$null')).success) {
|
|
351
|
+
step('Trying Chocolatey ...');
|
|
299
352
|
const exitCode = await runLive('choco install certbot -y', { timeout: 180000 });
|
|
300
353
|
if (exitCode === 0 || await verifyCertbot()) return { success: true };
|
|
301
|
-
console.log(chalk.yellow(' Chocolatey did not install certbot, trying next
|
|
354
|
+
console.log(chalk.yellow(' Chocolatey did not install certbot, trying next...\n'));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// ── Method 4: Scoop ───────────────────────────────────────────────────────────
|
|
358
|
+
if ((await run('where.exe scoop 2>$null')).success) {
|
|
359
|
+
step('Trying Scoop ...');
|
|
360
|
+
const exitCode = await runLive('scoop install certbot', { timeout: 180000 });
|
|
361
|
+
if (exitCode === 0 || await verifyCertbot()) return { success: true };
|
|
362
|
+
console.log(chalk.yellow(' Scoop did not install certbot, trying next...\n'));
|
|
302
363
|
}
|
|
303
364
|
|
|
304
|
-
// ── Method
|
|
365
|
+
// ── Method 5: Direct installer download (multiple sources × multiple methods) ─
|
|
305
366
|
const INSTALLER_FILENAME = 'certbot-beta-installer-win_amd64_signed.exe';
|
|
306
367
|
const INSTALLER_DEST = `$env:TEMP\\${INSTALLER_FILENAME}`;
|
|
307
368
|
const downloadSources = [
|
|
@@ -309,46 +370,58 @@ async function installCertbot() {
|
|
|
309
370
|
`https://dl.eff.org/${INSTALLER_FILENAME}`,
|
|
310
371
|
];
|
|
311
372
|
|
|
312
|
-
let downloaded = false;
|
|
313
373
|
for (const url of downloadSources) {
|
|
314
374
|
const label = new URL(url).hostname;
|
|
315
|
-
|
|
316
|
-
if (await downloadFile(url, INSTALLER_DEST)) {
|
|
317
|
-
|
|
375
|
+
step(`Downloading installer from ${label} ...`);
|
|
376
|
+
if (await downloadFile(url, INSTALLER_DEST)) {
|
|
377
|
+
console.log(chalk.gray(' Running installer silently ...\n'));
|
|
378
|
+
const ok = await runNsisInstaller(INSTALLER_DEST);
|
|
379
|
+
await run(`Remove-Item -Force '${INSTALLER_DEST}' -ErrorAction SilentlyContinue`);
|
|
380
|
+
if (ok) return { success: true };
|
|
381
|
+
console.log(chalk.yellow(' Installer ran but certbot not detected, trying next...\n'));
|
|
382
|
+
} else {
|
|
383
|
+
console.log(chalk.yellow(` Could not download from ${label}`));
|
|
384
|
+
}
|
|
318
385
|
}
|
|
319
386
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
`$p = Start-Process -FilePath "${INSTALLER_DEST}" -ArgumentList '/S' -PassThru -Wait; $p.ExitCode`,
|
|
325
|
-
{ timeout: 120000 },
|
|
326
|
-
);
|
|
327
|
-
await run(`Remove-Item -Force "${INSTALLER_DEST}" -ErrorAction SilentlyContinue`);
|
|
328
|
-
// Allow a few seconds for the installer to finish writing files
|
|
329
|
-
await new Promise(r => setTimeout(r, 4000));
|
|
330
|
-
if (await verifyCertbot()) return { success: true };
|
|
331
|
-
console.log(chalk.yellow(' Installer ran but certbot not found, trying pip...\n'));
|
|
332
|
-
}
|
|
387
|
+
// ── Method 6: Local file (user manually copies the installer to the server) ───
|
|
388
|
+
console.log(chalk.yellow('\n All automatic methods failed.'));
|
|
389
|
+
console.log(chalk.gray(' If you have the certbot installer on this machine, enter its path below.'));
|
|
390
|
+
console.log(chalk.gray(` (Download it on another PC: https://certbot.eff.org/instructions?ws=other&os=windows)\n`));
|
|
333
391
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
392
|
+
let localChoice;
|
|
393
|
+
try {
|
|
394
|
+
({ localChoice } = await inquirer.prompt([{
|
|
395
|
+
type: 'list',
|
|
396
|
+
name: 'localChoice',
|
|
397
|
+
message: 'What would you like to do?',
|
|
398
|
+
choices: ['Specify local installer path', 'Cancel'],
|
|
399
|
+
}]));
|
|
400
|
+
} catch { return { success: false }; }
|
|
401
|
+
|
|
402
|
+
if (localChoice === 'Specify local installer path') {
|
|
403
|
+
let localPath;
|
|
404
|
+
try {
|
|
405
|
+
({ localPath } = await inquirer.prompt([{
|
|
406
|
+
type: 'input',
|
|
407
|
+
name: 'localPath',
|
|
408
|
+
message: 'Full path to certbot installer (.exe):',
|
|
409
|
+
validate: v => v.trim().length > 0 || 'Required',
|
|
410
|
+
}]));
|
|
411
|
+
} catch { return { success: false }; }
|
|
412
|
+
|
|
413
|
+
const exists = await run(`Test-Path '${localPath.trim()}'`);
|
|
414
|
+
if (exists.stdout.trim().toLowerCase() !== 'true') {
|
|
415
|
+
console.log(chalk.red(` File not found: ${localPath}\n`));
|
|
416
|
+
return { success: false };
|
|
347
417
|
}
|
|
418
|
+
|
|
419
|
+
step('Running local installer silently ...');
|
|
420
|
+
const ok = await runNsisInstaller(localPath.trim());
|
|
421
|
+
if (ok) return { success: true };
|
|
422
|
+
console.log(chalk.red(' Installer ran but certbot was not detected.\n'));
|
|
348
423
|
}
|
|
349
424
|
|
|
350
|
-
// All methods exhausted
|
|
351
|
-
console.log(chalk.gray('\n Manual install: https://certbot.eff.org/instructions?ws=other&os=windows\n'));
|
|
352
425
|
return { success: false };
|
|
353
426
|
}
|
|
354
427
|
|
package/package.json
CHANGED