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]>
44 lines
1.3 KiB
TOML
44 lines
1.3 KiB
TOML
[package]
|
|
name = "openpxe-core"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
authors.workspace = true
|
|
description = "Shared types, config, and arch detection for OpenPXE"
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[dependencies]
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
toml.workspace = true
|
|
thiserror.workspace = true
|
|
anyhow.workspace = true
|
|
tracing.workspace = true
|
|
tracing-subscriber.workspace = true
|
|
time.workspace = true
|
|
uuid.workspace = true
|
|
parking_lot.workspace = true
|
|
tokio = { workspace = true, features = ["sync", "rt", "macros", "time"] }
|
|
# bcrypt for the admin Forms auth (v0.4.5). Already in the workspace
|
|
# for per-ISO boot passwords; just re-exported here.
|
|
bcrypt.workspace = true
|
|
|
|
# v0.5.1: pure-Rust SAML 2.0 SP. bergshamra = XML-DSig verify + exclusive
|
|
# c14n (no OpenSSL/C). roxmltree/quick-xml parse + build SAML XML;
|
|
# x509-parser pulls the IdP signing cert out of metadata; flate2+base64
|
|
# encode the HTTP-Redirect binding's SAMLRequest.
|
|
bergshamra.workspace = true
|
|
roxmltree.workspace = true
|
|
quick-xml.workspace = true
|
|
x509-parser.workspace = true
|
|
flate2.workspace = true
|
|
base64.workspace = true
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3.12"
|
|
# v0.5.1: generate a throwaway self-signed signing cert/key so SAML
|
|
# verification tests can produce genuinely signed SAMLResponses.
|
|
rcgen = "0.13"
|