machine_krb/lib.rs
1//! Active Directory machine-account Kerberos plumbing for Linux clients.
2//!
3//! This crate keeps a **machine-account Kerberos ticket** fresh on an
4//! AD-joined Linux device and answers "is this device *properly* joined?".
5//! The motivating case is **compound authentication** (a.k.a. FAST armoring):
6//! some KDC policies only issue a service ticket when the request is armored
7//! with the *device's* machine ticket — so a client (an RDP session, a GSSAPI
8//! LDAP bind, …) needs that machine ticket sitting in a cache, always valid.
9//!
10//! It deliberately shells out to the system MIT krb5 tools (absolute paths —
11//! see [`Tools`]) instead of reimplementing Kerberos: the system `kinit`
12//! already handles PKINIT, FAST and the distro's crypto policy correctly.
13//!
14//! # Example
15//!
16//! ```no_run
17//! use std::path::Path;
18//! use machine_krb::{ArmorCache, MachineIdentity, Tools};
19//!
20//! let tools = Tools::default();
21//! let id = MachineIdentity::discover(&tools, "/etc/krb5.keytab")?;
22//! let gid = machine_krb::lookup_gid(&tools, "machine-krb")?;
23//! machine_krb::prepare_dir(Path::new("/run/machine-krb"), Some(gid))?; // root:machine-krb 0750
24//! let cache = ArmorCache::new("/run/machine-krb/armor.ccache");
25//! let how = cache.ensure(&tools, &id)?; // Renewed (cheap) or Minted (keytab)
26//! cache.set_access(gid)?; // root:machine-krb 0640
27//! println!("{}: {how:?}", id.principal);
28//! # Ok::<(), machine_krb::Error>(())
29//! ```
30//!
31//! Practically everything here needs root: minting and deep join checks read
32//! `/etc/krb5.keytab`, and even renewing rewrites the cache file — which under
33//! the `root:<group>` 0640/0750 layout above only root can do. Group members
34//! *consume* the armor ticket; they don't maintain it. Only reading a cache
35//! ([`ArmorCache::is_valid`]/[`ArmorCache::klist_text`]) and the shallow join
36//! check work unprivileged.
37
38mod ccache;
39mod error;
40mod exec;
41mod identity;
42mod join;
43
44pub use ccache::{ArmorCache, Freshness, lookup_gid, prepare_dir};
45pub use error::{Error, Result};
46pub use exec::Tools;
47pub use identity::MachineIdentity;
48pub use join::{JoinStatus, check as check_join, verify_credential};