Introspection (the headline): detection is now probe-based. Instead of
grepping raw sectors for filename strings, we walk the ISO9660
directory tree and check whether the well-known boot files actually
exist — and the same probes run over NFS READ3 / SFTP seek-reads, so
share-hosted ISOs finally classify instead of registering as Unknown.
iso-store:
- New iso_fs module: the read-only ISO9660 walker (generalized from
http-api) over an IsoReadAt trait — local files, NFS, SFTP, and the
in-memory test images all share it. Iterative walk, 4 MiB directory
cap, strict-mastering trailing-dot normalization (VMLINUZ.;1 now
matches /vmlinuz), CachingReadAt collapses repeated directory reads
during the probe pass (~60 → ~6 round-trips per remote ISO).
- introspect.rs rewritten (INTROSPECT_REV 2): PVD label → El Torito →
/sources/boot.wim probe → verified Linux kernel+initrd probe table →
local-only 16 MiB UDF-Windows scan → filename-token fallback.
* Fixes the false-Windows bug: any Linux ISO shipping GRUB/syslinux
chainload modules contains the literal "bootmgr", so gparted-live
classified as WindowsPe. Linux probes now run first; the byte scan
only sees ISOs nothing else claimed. Local ISOs re-probe once on
startup via the rev bump — no re-upload.
* Kernel entries are emitted only when kernel+initrd verifiably
exist (no more guessed paths that 404 at boot). Debian-live /
d-i netinst / CoreOS shapes classify for the UI but keep their
working sanboot entries (their boot protocols need args we don't
render yet; CoreOS additionally needs its embedded ignition).
* Label + filename vocab extended: rhcos/coreos/openshift/okd,
gparted/clonezilla/kali/tails, almalinux/rocky, sles, manjaro.
- NFS + SFTP managers: per-ISO IsoReadAt readers (READ3-at-offset with
short-read looping / seek+read_exact), background introspection pass
after each scan — entries register instantly with a provisional
filename-based report (rev 0, optimistic sanboot preserved) and
upgrade in place as probes land (30s/ISO timeout, failures keep the
provisional). locate_in_iso() exposes the walker to the HTTP layer.
- remote_cache: introspection results persisted per protocol keyed
share/path@size and gated on INTROSPECT_REV — container restarts
re-probe only new/replaced ISOs; upgrades re-probe exactly once.
- SMB: smbclient can't seek, so SMB ISOs get the filename-token family
(rev stays 0 → sanboot entry + "awaiting introspection" label).
- IsoStore::update_external_introspection swaps in completed reports
and regenerates boot entries, preserving category/password.
http-api:
- /iso/{id}/{*path} now serves files from inside NFS/SFTP-hosted ISOs
(remote ISO9660 lookup + ranged share stream) — verified kernel
entries on remote Linux ISOs are actually bootable, end to end.
- iso_fs.rs deleted in favor of the shared iso-store module.
- full_flow fixtures build real directory trees via the shared
test-image builder (new iso-store feature) — a label-only blob no
longer earns a kernel entry, by design.
webui:
- Available images: paged 5 per page with a quiet footer pager
(Showing X–Y of N · Prev/Next), filter-then-paginate, page resets on
search input. Fifty images is five clean pages, not a scroll wall.
- Hosts/Queue profile: "Unattended file (in Storage → Advanced)" so
the picker says where the files live.
- Row badge keys on introspect_rev: probed remote ISOs read like local
ones; un-probed say "awaiting introspection".
Validation: clippy pedantic clean, fmt clean, 316 workspace tests
green (+17: walker, probe shapes incl. gparted regression + CoreOS,
filename table, cache round-trips), webui syntax-checked.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
72 lines
2.6 KiB
TOML
72 lines
2.6 KiB
TOML
[package]
|
|
name = "openpxe-http-api"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
authors.workspace = true
|
|
# v0.5.0: inherit the workspace repository so CARGO_PKG_REPOSITORY is
|
|
# populated at build time — the About-tab update check derives the
|
|
# Gitea releases API URL from it.
|
|
repository.workspace = true
|
|
description = "HTTP server: ISO uploads, iPXE script generation, ISO streaming"
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[dependencies]
|
|
openpxe-core.workspace = true
|
|
openpxe-iso-store.workspace = true
|
|
openpxe-ipxe-assets.workspace = true
|
|
openpxe-webui.workspace = true
|
|
tokio.workspace = true
|
|
tokio-util.workspace = true
|
|
tokio-stream.workspace = true
|
|
time.workspace = true
|
|
axum.workspace = true
|
|
tower.workspace = true
|
|
tower-http.workspace = true
|
|
hyper.workspace = true
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
tracing.workspace = true
|
|
thiserror.workspace = true
|
|
anyhow.workspace = true
|
|
bytes.workspace = true
|
|
futures.workspace = true
|
|
uuid.workspace = true
|
|
# v0.4.5 Forms auth: lock-free session store and cookie helpers.
|
|
parking_lot.workspace = true
|
|
# v0.5.0: outbound HTTP for chat webhooks (Slack/Teams/Discord) and the
|
|
# About-tab "check for updates" call to the Gitea releases API; SMTP for
|
|
# email notifications. Both use rustls so the static musl binary stays
|
|
# OpenSSL-free.
|
|
reqwest.workspace = true
|
|
lettre.workspace = true
|
|
# v0.5.1: decode the base64 SAMLResponse at the ACS endpoint.
|
|
base64.workspace = true
|
|
|
|
[dev-dependencies]
|
|
tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread", "time"] }
|
|
tower = { workspace = true }
|
|
tempfile = "3.12"
|
|
# v0.7.4: probe-based introspection verifies kernel paths against the
|
|
# real ISO9660 tree, so the full-flow tests synthesize images with the
|
|
# shared test builder instead of label-only blobs.
|
|
openpxe-iso-store = { workspace = true, features = ["test-image"] }
|
|
serde_json = { workspace = true }
|
|
time = { workspace = true }
|
|
# v0.4.61: integration tests need to generate real PNG bytes for the
|
|
# `/branding/pxe-logo` compositor; hand-rolled CRCs are too fragile.
|
|
image = { version = "0.25", default-features = false, features = ["png"] }
|
|
# v0.5.1: the SAML ACS integration tests mint a throwaway IdP keypair
|
|
# (rcgen) and sign a SAMLResponse with bergshamra so the happy-path,
|
|
# replay, and IdP-initiated-gating flows exercise real signatures.
|
|
rcgen = "0.13"
|
|
bergshamra = { workspace = true }
|
|
# v0.5.4: snapshot the generated iPXE menu so any unintended drift (a
|
|
# dropped line, reordered item) is caught and reviewed, not silently shipped.
|
|
insta = "1.40"
|
|
# v0.5.4: stand up a mock HTTP server to exercise the SAML metadata-URL
|
|
# fetch path (previously untested because it did a real network GET).
|
|
wiremock = "0.6"
|