SAML SSO (the config was storage-only since v0.4.5; now it logs you in):
- New openpxe-core::saml — pure-Rust SP built on bergshamra (XML-DSig +
exclusive c14n via RustCrypto, no OpenSSL/xmlsec/libxml2). The static
musl binary stays C-free; samael was rejected for hard-requiring OpenSSL.
* metadata.rs — parse IdP EntityDescriptor (SSO URLs + signing certs),
build our SP metadata.
* authn_request.rs — build + HTTP-Redirect-encode AuthnRequests.
* response.rs — verify the signature against the pinned IdP cert
(trusted_keys_only + strict_verification for XSW),
then enforce Status/Destination/Audience/time-bounds/
signature-scope. Stateless; returns the IDs the HTTP
layer needs.
- http-api saml_routes: GET /api/sso/login (302 to IdP), POST /api/sso/acs
(verify -> InResponseTo correlation / IdP-initiated gating / assertion
replay guard -> mint operator session -> 302), GET /api/sso/metadata.
Added to the pre-auth allowlist; /api/sso config stays gated.
- SsoConfig gains entity_id (SP Entity ID, defaults to public base URL)
and allow_idp_initiated (default off), mirroring FleetDM.
- Access model: any IdP-authenticated, cryptographically-verified user gets
an operator session (single-tier; local admin remains the fallback owner).
- Login page: the "Sign in with <IdP>" button now drives the real flow and
surfaces sso_error redirects.
UI consolidation:
- Removed the Advanced sidebar tab; folded its webhook-notifications +
API-reference cards into a collapsible "Advanced" disclosure at the
bottom of Settings.
- Merged the Storage tab's separate SMB and NFS cards into one "Remote
shares" card with a protocol dropdown and a unified, protocol-badged
table. No backend changes — same /api/smb-shares + /api/nfs-shares.
Tests: 17 SAML core tests (accept + reject tampered/unsigned/wrong-key/
wrong-audience/expired/future/wrong-issuer/non-success) and 6 ACS
integration tests (happy path, IdP-initiated gating, SP correlation,
replay, garbage). Full workspace: 206 tests green, clippy clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
64 lines
2.1 KiB
TOML
64 lines
2.1 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
|
|
mime.workspace = true
|
|
mime_guess.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"
|
|
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 }
|