infracensus-collector 1.6.0 → 1.6.2
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/index.js +61 -22
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1198,6 +1198,22 @@ function cleanCommandOutput(raw, command, prompt) {
|
|
|
1198
1198
|
}
|
|
1199
1199
|
return lines2.join("\n");
|
|
1200
1200
|
}
|
|
1201
|
+
var ENABLE_DETAIL = {
|
|
1202
|
+
/** The session never settled — there was no prompt to elevate FROM. */
|
|
1203
|
+
noPrompt: "the session never returned a usable prompt",
|
|
1204
|
+
/**
|
|
1205
|
+
* It asked, we answered, it stayed in user mode: the secret is wrong.
|
|
1206
|
+
* `enablePassword` falls back to the LOGIN password when a credential
|
|
1207
|
+
* carries no enable field, so "nothing was supplied" and "the wrong thing
|
|
1208
|
+
* was" reach the device identically — and the fix differs, which is the
|
|
1209
|
+
* whole reason these are two sentences.
|
|
1210
|
+
*/
|
|
1211
|
+
borrowedLoginPasswordRejected: "this credential carries no enable secret, so the login password was offered instead and the device refused it",
|
|
1212
|
+
/** It asked, we answered with this credential's own secret, it refused. */
|
|
1213
|
+
secretRejected: "the device rejected this credential's enable secret",
|
|
1214
|
+
/** It never asked at all — the account is not permitted to elevate. */
|
|
1215
|
+
neverAsked: "the device never asked to be unlocked and stayed in user mode \u2014 the account is probably not permitted to enable"
|
|
1216
|
+
};
|
|
1201
1217
|
async function gatherViaShell(conn, commands, perCommandTimeoutMs, signal, enablePassword, onDebug, usedLoginPasswordAsSecret = false) {
|
|
1202
1218
|
const stream = await openShell(conn);
|
|
1203
1219
|
let buf = "";
|
|
@@ -1231,7 +1247,7 @@ async function gatherViaShell(conn, commands, perCommandTimeoutMs, signal, enabl
|
|
|
1231
1247
|
stream.write("\r");
|
|
1232
1248
|
let prompt = await readUntilPrompt(8e3);
|
|
1233
1249
|
let elevated = prompt != null && prompt.endsWith("#");
|
|
1234
|
-
if (prompt === null) enableDetail =
|
|
1250
|
+
if (prompt === null) enableDetail = ENABLE_DETAIL.noPrompt;
|
|
1235
1251
|
if (prompt && prompt.endsWith(">")) {
|
|
1236
1252
|
buf = "";
|
|
1237
1253
|
stream.write("enable\r");
|
|
@@ -1251,14 +1267,7 @@ async function gatherViaShell(conn, commands, perCommandTimeoutMs, signal, enabl
|
|
|
1251
1267
|
}
|
|
1252
1268
|
elevated = prompt != null && prompt.endsWith("#");
|
|
1253
1269
|
if (!elevated) {
|
|
1254
|
-
enableDetail = askedForSecret ?
|
|
1255
|
-
// It asked and we answered, and it stayed in user mode: the secret is
|
|
1256
|
-
// wrong. `enablePassword` falls back to the LOGIN password when the
|
|
1257
|
-
// credential carries no enable field, so "no enable secret was
|
|
1258
|
-
// supplied" and "the wrong one was" reach the device identically —
|
|
1259
|
-
// and the fix differs.
|
|
1260
|
-
usedLoginPasswordAsSecret ? "the device asked for an enable secret and rejected the login password \u2014 this credential carries no enable secret of its own" : "the device rejected the enable secret on this credential"
|
|
1261
|
-
) : "the device never asked for an enable secret and stayed in user mode \u2014 the account is probably not permitted to enable";
|
|
1270
|
+
enableDetail = askedForSecret ? usedLoginPasswordAsSecret ? ENABLE_DETAIL.borrowedLoginPasswordRejected : ENABLE_DETAIL.secretRejected : ENABLE_DETAIL.neverAsked;
|
|
1262
1271
|
onDebug?.(`enable did not elevate (${enableDetail})`);
|
|
1263
1272
|
}
|
|
1264
1273
|
}
|
|
@@ -14895,6 +14904,7 @@ ${tokenCss()}
|
|
|
14895
14904
|
.runrow .when { font-variant-numeric: tabular-nums; }
|
|
14896
14905
|
.outcome-finished { color: var(--ok); } .outcome-failed { color: var(--bad); }
|
|
14897
14906
|
.outcome-incomplete { color: var(--warn); }
|
|
14907
|
+
.outcome-running { color: var(--accent); }
|
|
14898
14908
|
/* THE RUN DETAIL. An operator opening a finished run wants four things \u2014 how
|
|
14899
14909
|
far each stage got, when it ran, what it was pointed at, and what it found
|
|
14900
14910
|
\u2014 and wants each in the same place every time. Labelled blocks, not the
|
|
@@ -15963,11 +15973,18 @@ ${tokenCss()}
|
|
|
15963
15973
|
$("runTargets").value = (s.scanDefaults.targets || []).join(", ");
|
|
15964
15974
|
}
|
|
15965
15975
|
renderLive(s.scanProgress || null);
|
|
15966
|
-
// A run that has just ENDED is the moment the history gained a row, and
|
|
15967
|
-
//
|
|
15968
|
-
//
|
|
15976
|
+
// A run that has just ENDED is the moment the history gained a row, and the
|
|
15977
|
+
// moment somebody wants to read it.
|
|
15978
|
+
//
|
|
15979
|
+
// It is also re-read WHILE one runs, which it deliberately was not before:
|
|
15980
|
+
// the detail used to be a fold of a finished run, so nothing in it changed
|
|
15981
|
+
// between two polls of a scan in flight. It now carries that run's stages
|
|
15982
|
+
// and the addresses it has found so far, both of which land as the scan
|
|
15983
|
+
// goes \u2014 a panel somebody opened to watch their own scan cannot be a
|
|
15984
|
+
// snapshot of the moment they opened it. Bounded twice over: only while the
|
|
15985
|
+
// panel is open, and only while something is actually running.
|
|
15969
15986
|
const running = !!s.scanProgress;
|
|
15970
|
-
if (
|
|
15987
|
+
if ($("histWrap").open && (running || (wasRunning && !running))) loadRuns();
|
|
15971
15988
|
wasRunning = running;
|
|
15972
15989
|
$("lastPollAt").textContent = fmt(s.daemon && s.daemon.lastPollAt);
|
|
15973
15990
|
$("lastPushAt").textContent = fmt(s.daemon && s.daemon.lastPushAt);
|
|
@@ -16658,9 +16675,16 @@ ${tokenCss()}
|
|
|
16658
16675
|
const sum = el("summary");
|
|
16659
16676
|
sum.appendChild(el("span", { class: "when", text: fmt(run.startedAt) }));
|
|
16660
16677
|
sum.appendChild(el("span", { text: run.mode }));
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16678
|
+
// A run the LEDGER calls running is only reported as running if a scan is
|
|
16679
|
+
// actually in flight. The ledger cannot tell a live daemon from one killed
|
|
16680
|
+
// between two polls; the status poll can, and it is the half of the answer
|
|
16681
|
+
// this side of the page holds.
|
|
16682
|
+
const live = run.outcome === "running" && wasRunning;
|
|
16683
|
+
const state = run.outcome === "running" && !live ? "stopped" : run.outcome;
|
|
16684
|
+
sum.appendChild(el("span", { class: "outcome-" + (live ? "running" : state), text:
|
|
16685
|
+
state === "finished" ? "finished"
|
|
16686
|
+
: state === "failed" ? "failed"
|
|
16687
|
+
: live ? "running now"
|
|
16664
16688
|
: "no end recorded" }));
|
|
16665
16689
|
if (run.durationMs) {
|
|
16666
16690
|
sum.appendChild(el("span", { class: "dim", text: Math.round(run.durationMs / 1000) + "s" }));
|
|
@@ -16683,13 +16707,22 @@ ${tokenCss()}
|
|
|
16683
16707
|
// \u2500\u2500 CURRENT STAGE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
16684
16708
|
// Where the run got to, in one sentence, at the top. A run that died has
|
|
16685
16709
|
// its reason HERE rather than as a note somewhere further down.
|
|
16710
|
+
// The last stage the run reported is what it is DOING, which is the
|
|
16711
|
+
// sentence somebody watching their own scan is looking for. A finished run
|
|
16712
|
+
// has no use for it; a live one has nothing else.
|
|
16713
|
+
const latest = run.phases && run.phases.length ? run.phases[run.phases.length - 1] : null;
|
|
16686
16714
|
block("Current stage", [
|
|
16687
16715
|
el("div", {
|
|
16688
|
-
class:
|
|
16716
|
+
class: state === "failed" ? "bad" : state === "incomplete" || state === "stopped" ? "warntext" : "",
|
|
16689
16717
|
text:
|
|
16690
|
-
|
|
16691
|
-
:
|
|
16692
|
-
:
|
|
16718
|
+
state === "finished" ? "Scan complete."
|
|
16719
|
+
: state === "failed" ? (run.reason || "The run failed.")
|
|
16720
|
+
: live ? (latest && latest.note ? latest.note
|
|
16721
|
+
: latest ? "Running: " + latest.phase
|
|
16722
|
+
: "Running.")
|
|
16723
|
+
: state === "stopped"
|
|
16724
|
+
? "This run has no end recorded and no scan is in flight, so the collector stopped before it finished."
|
|
16725
|
+
: "A later run started before this one recorded an end, so it was interrupted.",
|
|
16693
16726
|
}),
|
|
16694
16727
|
]);
|
|
16695
16728
|
|
|
@@ -18229,7 +18262,10 @@ function runHistoryFromEvents(events, limit = HISTORY_LIMIT) {
|
|
|
18229
18262
|
targets: Array.isArray(start.targets) ? start.targets : [],
|
|
18230
18263
|
collectorId: start.collectorId ?? null,
|
|
18231
18264
|
lastEventAt: start.ts ?? null,
|
|
18232
|
-
|
|
18265
|
+
// Nothing has contradicted it yet. The scan below downgrades this to
|
|
18266
|
+
// `incomplete` the moment a NEWER run-started proves it was abandoned,
|
|
18267
|
+
// and to a verdict when one arrives.
|
|
18268
|
+
outcome: "running",
|
|
18233
18269
|
reason: null,
|
|
18234
18270
|
devices: null,
|
|
18235
18271
|
durationMs: null,
|
|
@@ -18243,7 +18279,10 @@ function runHistoryFromEvents(events, limit = HISTORY_LIMIT) {
|
|
|
18243
18279
|
for (let j = i + 1; j < events.length; j += 1) {
|
|
18244
18280
|
const e = events[j];
|
|
18245
18281
|
if (!e) continue;
|
|
18246
|
-
if (e.event === "run-started")
|
|
18282
|
+
if (e.event === "run-started") {
|
|
18283
|
+
run2.outcome = "incomplete";
|
|
18284
|
+
break;
|
|
18285
|
+
}
|
|
18247
18286
|
if (e.ts) run2.lastEventAt = e.ts;
|
|
18248
18287
|
if (e.event === "run-finished") {
|
|
18249
18288
|
run2.outcome = "finished";
|