crates/gunnar-grpc/tests/key_enrolling.rs
//! **A key the installer FED a primary, and its pairing loop has not enrolled
//! yet, is answered `Unavailable [key-enrolling]` — ask again — never
//! `Unauthenticated`** (cov-E r3 2026-10-06, run 3).
//!
//! MEASURED: the front's twin-certification loop called the primary with the
//! front's certify key from 14:39:18 on, and every answer for five minutes was
//! "Unauthenticated: the credential did not verify against any registered
//! key" — while the primary was enrolling that very key (its fed principals
//! took 4 m 47 s on a starved box, the certify key sixth in line). The log
//! gate failed the install on the retry loop. An enrolment that is not yet
//! possible is a "not yet", not a "who are you".
//!
//! Only the HOLDER of the fed key is told so: the signature is checked against
//! the fed key first, so a stranger presenting its fingerprint learns nothing
//! and is `NotVerified` as before.
use std::sync::Arc;
use gunnar_grpc::auth::{AuthFailure, AuthGate};
use gunnar_grpc::{
sign_credential_for, AuthMode, ControlPlane, MemoryControlPlane, CREDENTIAL_METADATA_KEY,
KEY_ENROLLING,
};
use gunnar_proto::PrincipalKind;
use tonic::Code;
fn mint() -> ssh_key::PrivateKey {
ssh_key::PrivateKey::random(
&mut rand::rand_core::UnwrapErr(rand::rngs::SysRng),
ssh_key::Algorithm::Ed25519,
)
.expect("mint an ed25519 key")
}
fn openssh_of(key: &ssh_key::PrivateKey) -> String {
key.public_key()
.to_openssh()
.expect("render the public key")
}
fn fingerprint_of(key: &ssh_key::PrivateKey) -> String {
key.public_key()
.fingerprint(ssh_key::HashAlg::Sha256)
.to_string()
}
fn now_ms() -> i64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("after 1970")
.as_millis() as i64
}
fn presented(credential: &gunnar_grpc::Credential) -> tonic::metadata::MetadataMap {
let mut metadata = tonic::metadata::MetadataMap::new();
metadata.insert(
CREDENTIAL_METADATA_KEY,
credential.to_header_value().parse().expect("ascii"),
);
metadata
}
/// A primary whose installer fed it `fed` (the front's certify key) and whose
/// pairing loop has not enrolled it yet.
fn primary_awaiting(fed: &ssh_key::PrivateKey) -> (Arc<MemoryControlPlane>, AuthGate) {
let plane = Arc::new(MemoryControlPlane::new());
plane.await_enrolment(&fingerprint_of(fed), &openssh_of(fed));
let control: Arc<dyn ControlPlane> = plane.clone();
(plane, AuthGate::new(control, AuthMode::Required))
}
#[test]
fn the_holder_of_a_fed_key_not_enrolled_yet_is_told_to_ask_again_not_that_it_is_unknown() {
let certify = mint();
let (_, gate) = primary_awaiting(&certify);
let credential = sign_credential_for(&certify, now_ms(), "nonce-enrolling-01", "Admin.Health")
.expect("sign");
let refused = gate.authenticate_bound(&presented(&credential), now_ms(), Some("Admin.Health"));
assert_eq!(
refused,
Err(AuthFailure::Enrolling),
"the front's certify key, fed to this primary and not enrolled yet, was answered as a stranger's"
);
let status = AuthFailure::Enrolling.status();
assert_eq!(
status.code(),
Code::Unavailable,
"a key being enrolled is a `not yet`: Unavailable, never Unauthenticated"
);
assert!(
status.message().contains(KEY_ENROLLING),
"the answer carries its tag, so the caller and the request log can key on it: {}",
status.message()
);
assert_eq!(AuthFailure::Enrolling.reason(), "enrolling");
}
#[test]
fn a_stranger_naming_a_fed_keys_fingerprint_is_not_verified_as_before() {
let certify = mint();
let stranger = mint();
let (_, gate) = primary_awaiting(&certify);
// The fed key's fingerprint on the header, the stranger's signature under it.
let mut credential =
sign_credential_for(&stranger, now_ms(), "nonce-enrolling-02", "Admin.Health")
.expect("sign");
credential.fingerprint = fingerprint_of(&certify);
assert_eq!(
gate.authenticate_bound(&presented(&credential), now_ms(), Some("Admin.Health")),
Err(AuthFailure::NotVerified),
"a stranger naming a fed key's fingerprint must learn nothing: NotVerified, as for any unknown key"
);
// And a key nobody fed is unknown, as ever.
let unknown = sign_credential_for(&stranger, now_ms(), "nonce-enrolling-03", "Admin.Health")
.expect("sign");
assert_eq!(
gate.authenticate_bound(&presented(&unknown), now_ms(), Some("Admin.Health")),
Err(AuthFailure::NotVerified)
);
}
#[test]
fn once_the_pairing_loop_enrolled_it_the_fed_key_is_a_caller() {
let certify = mint();
let (plane, gate) = primary_awaiting(&certify);
let principal = plane
.add_principal("front-certify", "front-certify", PrincipalKind::Machine)
.expect("principal");
plane
.add_key(
&principal.id,
&openssh_of(&certify),
"fed by the installer",
None,
"",
None,
)
.expect("key registered");
let credential = sign_credential_for(&certify, now_ms(), "nonce-enrolling-04", "Admin.Health")
.expect("sign");
let caller = gate
.authenticate_bound(&presented(&credential), now_ms(), Some("Admin.Health"))
.expect("the enrolled key verifies");
assert_eq!(caller.principal_id, "front-certify");
}