diff --git a/benches/write_allowed_signers.rs b/benches/write_allowed_signers.rs index ae7c00f..e45367e 100644 --- a/benches/write_allowed_signers.rs +++ b/benches/write_allowed_signers.rs @@ -9,31 +9,31 @@ pub fn criterion_benchmark(c: &mut Criterion) { .into_temp_path() .to_path_buf(), vec![ - Entry { - principals: vec!["j.snow@wall.com".to_string()], - valid_after: None, - valid_before: None, - key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGtQUDZWhs8k/cZcykMkaoX7ZE7DXld8TP79HyddMVTS" - .parse() - .unwrap(), - }, - Entry { - principals: vec!["ian.malcom@acme.corp".to_string()], - valid_after: Some(Local.with_ymd_and_hms(2024, 4, 11, 22, 00, 00).unwrap()), - valid_before: None, - key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILWtK6WxXw7NVhbn6fTQ0dECF8y98fahSIsqKMh+sSo9" - .parse() - .unwrap(), - }, - Entry { - principals: vec!["cwoods@universal.exports".to_string()], - valid_after: None, - valid_before: Some(Local.with_ymd_and_hms(2030, 1, 1, 0, 0, 0).unwrap()), - key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJHDGMF+tZQL3dcr1arPst+YP8v33Is0kAJVvyTKrxMw" - .parse() - .unwrap(), - }, - ], + Entry::new( + vec!["j.snow@wall.com".to_string()], + None, + None, + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGtQUDZWhs8k/cZcykMkaoX7ZE7DXld8TP79HyddMVTS" + .parse() + .unwrap(), + ), + Entry::new( + vec!["ian.malcom@acme.corp".to_string()], + Some(Local.with_ymd_and_hms(2024, 4, 11, 22, 00, 00).unwrap()), + None, + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILWtK6WxXw7NVhbn6fTQ0dECF8y98fahSIsqKMh+sSo9" + .parse() + .unwrap(), + ), + Entry::new( + vec!["cwoods@universal.exports".to_string()], + None, + Some(Local.with_ymd_and_hms(2030, 1, 1, 0, 0, 0).unwrap()), + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJHDGMF+tZQL3dcr1arPst+YP8v33Is0kAJVvyTKrxMw" + .parse() + .unwrap(), + ), + ], ); c.bench_function("write the signers file", |b| { diff --git a/src/allowed_signers/file.rs b/src/allowed_signers/file.rs index 8be5e3d..4f2d48b 100644 --- a/src/allowed_signers/file.rs +++ b/src/allowed_signers/file.rs @@ -59,10 +59,35 @@ impl File { /// An entry in the allowed signers file. #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Entry { - pub principals: Vec, - pub valid_after: Option>, - pub valid_before: Option>, - pub key: PublicKey, + principals: Vec, + valid_after: Option>, + valid_before: Option>, + key: PublicKey, +} + +impl Entry { + #[must_use] + /// Create a new signer entry. + /// + /// # Panics + /// If the provided principals are empty. + pub fn new( + principals: Vec, + valid_after: Option>, + valid_before: Option>, + key: PublicKey, + ) -> Self { + assert!( + !principals.is_empty(), + "signer entry requires at least one principal" + ); + Entry { + principals, + valid_after, + valid_before, + key, + } + } } impl fmt::Display for Entry { @@ -189,6 +214,12 @@ mod tests { ) } + #[test] + #[should_panic(expected = "signer entry requires at least one principal")] + fn new_entry_without_principal_panics() { + let _ = Entry::new(vec![], None, None, entry_jsnow().key); + } + #[rstest] #[case( entry_jsnow(), diff --git a/src/allowed_signers/signer.rs b/src/allowed_signers/signer.rs index 7bdae06..4e60852 100644 --- a/src/allowed_signers/signer.rs +++ b/src/allowed_signers/signer.rs @@ -66,12 +66,7 @@ impl Signer { Ok(keys .into_iter() - .map(|key| Entry { - principals: self.principals.clone(), - valid_after: None, - valid_before: None, - key, - }) + .map(|key| Entry::new(self.principals.clone(), None, None, key)) .collect()) } }