feat: complete session preferences and PAM fixture gates
This commit is contained in:
133
crates/latchd-auth/tests/pam_fixture.rs
Normal file
133
crates/latchd-auth/tests/pam_fixture.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
use std::env;
|
||||
|
||||
use latchd_auth::AuthService;
|
||||
use latchd_core::{
|
||||
accounts::Identity,
|
||||
config::Config,
|
||||
error::Error,
|
||||
session::{self, SessionDescriptor, SessionKind},
|
||||
};
|
||||
|
||||
fn fixture_service() -> String {
|
||||
env::var("LATCHD_PAM_FIXTURE_SERVICE")
|
||||
.expect("LATCHD_PAM_FIXTURE_SERVICE must point at the disposable PAM fixture")
|
||||
}
|
||||
|
||||
fn session_fixture_service() -> String {
|
||||
env::var("LATCHD_PAM_SESSION_FIXTURE_SERVICE")
|
||||
.expect("LATCHD_PAM_SESSION_FIXTURE_SERVICE must point at the disposable PAM fixture")
|
||||
}
|
||||
|
||||
fn assert_sanitized_pam_failure(result: Result<(), Error>, secret: &str) {
|
||||
let error = result.expect_err("the fault-injection PAM fixture must reject the operation");
|
||||
match error {
|
||||
Error::Pam {
|
||||
status, message, ..
|
||||
} => {
|
||||
assert_ne!(status, 0);
|
||||
assert!(!message.contains(secret));
|
||||
}
|
||||
_ => panic!("fault-injection fixture returned a non-PAM error"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires the disposable PAM fixture installed by the Docker/VM harness"]
|
||||
fn authentication_fault_is_rejected_without_secret_leakage() {
|
||||
let service = AuthService::new().expect("PAM worker should start");
|
||||
let secret = "fixture-auth-secret";
|
||||
let result = service.authenticate("root".into(), secret.as_bytes().to_vec(), fixture_service());
|
||||
let error = match result {
|
||||
Ok(_) => panic!("pam_deny fixture must reject authentication"),
|
||||
Err(error) => error,
|
||||
};
|
||||
match error {
|
||||
Error::Pam {
|
||||
status, message, ..
|
||||
} => {
|
||||
assert_ne!(status, 0);
|
||||
assert!(!message.contains(secret));
|
||||
}
|
||||
_ => panic!("fault-injection fixture returned a non-PAM error"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires the disposable PAM fixture installed by the Docker/VM harness"]
|
||||
fn password_change_fault_is_rejected_without_secret_leakage() {
|
||||
let service = AuthService::new().expect("PAM worker should start");
|
||||
assert_sanitized_pam_failure(
|
||||
service.change_password(
|
||||
"root".into(),
|
||||
b"fixture-old-secret".to_vec(),
|
||||
b"fixture-new-secret".to_vec(),
|
||||
fixture_service(),
|
||||
),
|
||||
"fixture-new-secret",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires the disposable PAM fixture installed by the Docker/VM harness"]
|
||||
fn selected_session_metadata_reaches_pam_before_open() {
|
||||
let service = AuthService::new().expect("PAM worker should start");
|
||||
let ticket = service
|
||||
.authenticate("root".into(), Vec::new(), session_fixture_service())
|
||||
.expect("permit fixture should authenticate root");
|
||||
let identity = Identity {
|
||||
username: "root".into(),
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
home: "/root".into(),
|
||||
shell: "/bin/sh".into(),
|
||||
};
|
||||
let descriptor = SessionDescriptor {
|
||||
kind: SessionKind::Wayland,
|
||||
title: "Niri fixture".into(),
|
||||
argv: vec!["/bin/true".into()],
|
||||
current_desktop: Some("niri".into()),
|
||||
session_desktop: Some("niri".into()),
|
||||
};
|
||||
let spec = session::build_spec(&identity, &Config::default(), &descriptor)
|
||||
.expect("fixture session should build");
|
||||
|
||||
service
|
||||
.run_session(ticket, spec)
|
||||
.expect("PAM must receive the selected graphical session metadata");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires the disposable PAM fixture installed by the Docker/VM harness"]
|
||||
fn pam_runtime_environment_reaches_the_session_child() {
|
||||
let service = AuthService::new().expect("PAM worker should start");
|
||||
let ticket = service
|
||||
.authenticate("root".into(), Vec::new(), session_fixture_service())
|
||||
.expect("permit fixture should authenticate root");
|
||||
let identity = Identity {
|
||||
username: "root".into(),
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
home: "/root".into(),
|
||||
shell: "/bin/sh".into(),
|
||||
};
|
||||
let descriptor = SessionDescriptor {
|
||||
kind: SessionKind::Wayland,
|
||||
title: "PAM environment fixture".into(),
|
||||
argv: vec![
|
||||
"/bin/sh".into(),
|
||||
"-c".into(),
|
||||
"test \"$XDG_SESSION_ID\" = fixture-session && \
|
||||
test \"$XDG_RUNTIME_DIR\" = /tmp/latchd-runtime-fixture && \
|
||||
test \"$DBUS_SESSION_BUS_ADDRESS\" = unix:path=/tmp/latchd-runtime-fixture/bus"
|
||||
.into(),
|
||||
],
|
||||
current_desktop: Some("niri".into()),
|
||||
session_desktop: Some("niri".into()),
|
||||
};
|
||||
let spec = session::build_spec(&identity, &Config::default(), &descriptor)
|
||||
.expect("fixture session should build");
|
||||
|
||||
service
|
||||
.run_session(ticket, spec)
|
||||
.expect("the child must receive runtime values produced by PAM");
|
||||
}
|
||||
Reference in New Issue
Block a user