webapp: fix review findings (imaging types, NIC status, iPXE gates)
- imaging: coerce client payload and stored session fields to str/int, drop lists/dicts; tiles template guards pctype/current_stage; POST rejects non-object bodies and non-string serials. - nic_status: normalise every check-file entry; load nic.conf as-is with a [nic] fallback; split interface= lists; keep the check's binding while fresh, resolve wildcard sockets from the dnsmasq pin (never True for an excluded NIC); mark vanished NICs down; include role bridges; stale or future-dated files downgrade to warnings and drop evidence. - Overview renders the network pill in its own try and shows 'Network: unknown' when status fails. - ipxe_update: read every Authenticode signature (all WIN_CERTIFICATE entries plus nested SPC_NESTED_SIGNATURE) with openssl; shim swap and install need both Microsoft UEFI CA 2011 and 2023; install re-reads each file (snponly ipxe.efi only); staged.json schema version, older records shown stale and refused; uhci counts as native USB. - backups describe their files; risky rollbacks need a confirm flag. - mac_folders: guarded listdir, cached describe, configured TFTP root, warning for a shim without ipxe.efi. - evidence pack: years 2000..2100, 400 days inclusive. - a11y role=group on quick ranges; progress bar stays full during 'shim'. - tests/test_review_fixes.py: 29 unittest cases incl. both real shims.
This commit is contained in:
@@ -5,7 +5,8 @@
|
||||
{# Signer as a short chip; the long explanation goes in the row body (it is
|
||||
a safety warning, so never hover-only). #}
|
||||
{% macro sig_chip(info) -%}
|
||||
{% if info.kind == 'microsoft-2011' %}{{ ui.chip('MS UEFI CA 2011 only', 'warn') }}
|
||||
{% if info.dual %}{{ ui.chip('MS UEFI CA 2011 + 2023', 'ok') }}
|
||||
{% elif info.kind == 'microsoft-2011' %}{{ ui.chip('MS UEFI CA 2011 only', 'warn') }}
|
||||
{% elif info.kind == 'microsoft-2023' %}{{ ui.chip('MS UEFI CA 2023', 'ok') }}
|
||||
{% elif info.kind == 'microsoft' %}{{ ui.chip('Microsoft, other CA', 'neutral') }}
|
||||
{% elif info.kind == 'ipxe' %}{{ ui.chip('iPXE Secure Boot CA', 'ok') }}
|
||||
@@ -17,7 +18,8 @@
|
||||
|
||||
{% macro sig_text(info, chain_ok=none) -%}
|
||||
{% if info.kind == 'microsoft-2011' %}<div class="notice">Signed only under Microsoft Corporation UEFI CA 2011. That CA's signing period ended in 2026: machines that trust only the 2023 CA, or a DBX/SBAT revocation update, will refuse this file.</div>
|
||||
{% elif info.kind == 'microsoft-2023' %}<div class="sub">Signed under Microsoft UEFI CA 2023.</div>
|
||||
{% elif info.dual %}<div class="sub">Dual-signed: under Microsoft Corporation UEFI CA 2011 and Microsoft UEFI CA 2023.</div>
|
||||
{% elif info.kind == 'microsoft-2023' %}<div class="notice">Signed under Microsoft UEFI CA 2023 only, not dual-signed: machines that trust only the 2011 CA will refuse it.</div>
|
||||
{% elif info.kind == 'ipxe' %}<div class="sub">Chains to the iPXE Secure Boot CA, which the iPXE shim trusts.</div>
|
||||
{% elif info.kind == 'bios' %}<div class="sub">Legacy BIOS has no Secure Boot; the file is unsigned by design.</div>
|
||||
{% elif info.kind == 'unsigned' %}<div class="notice bad">Unsigned: Secure Boot firmware will refuse it.</div>
|
||||
@@ -149,7 +151,7 @@
|
||||
<div class="panel strip" role="status">
|
||||
<span class="pulse" aria-hidden="true"></span>
|
||||
<span id="ipxeJobText">{{ 'Starting' if job.state == 'queued' else (job.step | capitalize) }} {{ job.tag }}...</span>
|
||||
<div class="bar" aria-hidden="true"><div id="ipxeJobBar" style="width: {{ job.percent or 0 }}%"></div></div>
|
||||
<div class="bar" aria-hidden="true"><div id="ipxeJobBar" style="width: {{ 100 if job.step in ('verify', 'shim') else (job.percent or 0) }}%"></div></div>
|
||||
</div>
|
||||
{% elif job.state == 'error' %}
|
||||
<div class="errbox"><strong>Download of {{ job.tag }} failed:</strong> <span class="mono">{{ job.error }}</span></div>
|
||||
@@ -213,8 +215,9 @@
|
||||
<div class="sec-h"><div><h2 id="mac-h" class="sec">Per-client folders</h2>
|
||||
<div class="sub">With <span class="mono">tftp-unique-root=mac</span>, a client whose MAC has a folder gets every file from it, with no fallback to the root. Read-only here: installs do not update them.</div></div></div>
|
||||
{% for m in mac_folders %}
|
||||
<div class="rel-h"><strong class="mono">{{ m.mac }}</strong><span class="sub mono">/srv/tftp/{{ m.dir }}/</span>
|
||||
<div class="rel-h"><strong class="mono">{{ m.mac }}</strong><span class="sub mono">{{ tftp_root }}/{{ m.dir }}/</span>
|
||||
<span class="sub">{{ m.files | length }} file{{ 's' if m.files | length != 1 }}</span></div>
|
||||
{% for w in m.warnings or [] %}<div class="notice bad" style="margin: 0 24px 8px"><span>{{ w }}</span></div>{% endfor %}
|
||||
{% for f in m.files %}
|
||||
{% set i = f.info %}
|
||||
{% set chain_ok = i.chain_ok if i.chain_ok is defined else none %}
|
||||
@@ -229,7 +232,7 @@
|
||||
<div class="ibody">
|
||||
{{ sig_text(i, chain_ok) }}
|
||||
<dl class="kv">
|
||||
<dt>Path</dt><dd class="mono">/srv/tftp/{{ m.dir }}/{{ f.name }}</dd>
|
||||
<dt>Path</dt><dd class="mono">{{ tftp_root }}/{{ m.dir }}/{{ f.name }}</dd>
|
||||
<dt>Size</dt><dd>{{ "{:,}".format(i.size) }} B</dd>
|
||||
<dt>Modified</dt><dd class="mono">{{ i.modified | timestamp_fmt }}</dd>
|
||||
<dt>sha256</dt><dd class="mono">{{ i.sha256 }}</dd>
|
||||
@@ -289,6 +292,7 @@
|
||||
<div class="rel-h">
|
||||
<strong class="mono">{{ s.tag }}</strong>
|
||||
<span class="sub">verified {{ s.staged | local_dt }}</span>
|
||||
{% if s.stale %}{{ ui.chip('Stale: download again', 'warn') }}{% endif %}
|
||||
<span class="tip inl" data-tip="{{ s.tarball_sha256 }}"><span class="sub">tarball sha256 <span class="mono">{{ (s.tarball_sha256 or '')[:12] }}</span> matches GitHub</span></span>
|
||||
</div>
|
||||
{% for name, f in s.files.items() %}
|
||||
@@ -380,7 +384,8 @@
|
||||
</summary>
|
||||
<div class="ibody">
|
||||
{% if b.reason %}<div>{{ b.reason }}</div>{% endif %}
|
||||
{% for f in b.files %}<div><span class="mono">{{ f }}</span> <span class="muted">{{ b.versions[f] or '' }}</span></div>{% else %}<div class="muted">Empty backup.</div>{% endfor %}
|
||||
{% for f in b.files %}<div><span class="mono">{{ f }}</span> <span class="muted">{{ b.versions[f] or '' }}</span>{% if b.info and b.info[f] %} {{ sig_chip(b.info[f]) }}{% endif %}</div>{% else %}<div class="muted">Empty backup.</div>{% endfor %}
|
||||
{% for w in b.warnings or [] %}<div class="notice bad"><span>{{ w }}</span></div>{% endfor %}
|
||||
</div>
|
||||
</details>
|
||||
{% if b.files %}
|
||||
@@ -392,6 +397,8 @@
|
||||
onsubmit="return confirm(this.dataset.confirm);">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
||||
<input type="hidden" name="backup" value="{{ b.id }}">
|
||||
{% if b.warnings %}<label class="sub" style="display: flex; gap: 6px; align-items: flex-start; white-space: normal; padding: 6px 10px">
|
||||
<input type="checkbox" name="confirm" value="1" required> Restore anyway: {{ b.warnings | join('; ') }}</label>{% endif %}
|
||||
<button type="submit">Restore these files</button>
|
||||
</form>
|
||||
{% endcall %}
|
||||
@@ -437,8 +444,8 @@ ls -l ipxeboot/x86_64-sb/</pre></li>
|
||||
<pre class="cmd mono">sbverify --list ipxe-shimx64.efi
|
||||
sbverify --list ipxeboot/x86_64-sb/ipxe.efi
|
||||
sbverify --list ipxeboot/x86_64-sb/snponly.efi</pre>
|
||||
The dual-signed shim shows <span class="mono">CN=Microsoft UEFI CA 2023</span> (sbverify lists the first signature only;
|
||||
the 2011 one is nested inside it). Fall back to the tarball's <span class="mono">shimx64.efi</span>
|
||||
The dual-signed shim shows <span class="mono">CN=Microsoft UEFI CA 2023</span> and <span class="mono">CN=Microsoft Corporation UEFI CA 2011</span>
|
||||
(depending on the sbverify version it lists both signatures or only the outer one; this page reads every signature, nested ones too). Fall back to the tarball's <span class="mono">shimx64.efi</span>
|
||||
(<span class="mono">CN=Microsoft Corporation UEFI CA 2011</span>) only if the dual-signed one is unavailable.
|
||||
<span class="mono">ipxe.efi</span> must show <span class="mono">CN=iPXE Secure Boot Intermediate ...</span> issued by
|
||||
<span class="mono">CN=iPXE Secure Boot CA</span>. The shim's <span class="mono">warning: data remaining ... gaps between PE/COFF sections?</span>
|
||||
@@ -484,7 +491,7 @@ install -m 0644 ipxe-shimx64.efi /srv/tftp/.ipxe-shim.efi.new &
|
||||
if (j.state !== 'queued' && j.state !== 'running') { location.reload(); return; }
|
||||
var step = j.step === 'download' ? 'Downloading' : j.step === 'verify' ? 'Verifying' : j.step === 'shim' ? 'Fetching the dual-signed shim for' : 'Starting';
|
||||
if (text) text.textContent = step + ' ' + (j.tag || '') + (j.step === 'download' && j.percent != null ? ' (' + j.percent + '%)' : '') + '...';
|
||||
if (bar) bar.style.width = (j.step === 'verify' ? 100 : (j.percent || 0)) + '%';
|
||||
if (bar) bar.style.width = ((j.step === 'verify' || j.step === 'shim') ? 100 : (j.percent || 0)) + '%';
|
||||
setTimeout(tick, 2000);
|
||||
})
|
||||
.catch(function () { setTimeout(tick, 5000); });
|
||||
|
||||
Reference in New Issue
Block a user