Import SSH revocation metadata

This commit is contained in:
Eric Wendland 2026-05-18 11:56:42 +02:00
commit 4c368253e4
11 changed files with 212 additions and 13 deletions

View file

@ -334,6 +334,33 @@ pub fn openssh_krl_spec(entries: &[SshRevocationEntry]) -> Result<String, SshIde
Ok(spec)
}
pub fn parse_openssh_krl_spec(
spec: &str,
) -> Result<Vec<(SshRevocationKind, String)>, SshIdentityError> {
let mut entries = Vec::new();
for line in spec.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let Some((directive, target)) = line.split_once(':') else {
return Err(SshIdentityError::InvalidKrlSpecLine(line.to_owned()));
};
let target = target.trim();
if target.is_empty() || target.bytes().any(|byte| byte == b'\n' || byte == b'\r') {
return Err(SshIdentityError::InvalidRevocationTarget(target.to_owned()));
}
let kind = match directive.trim() {
"key" => SshRevocationKind::PublicKey,
"serial" => SshRevocationKind::Serial,
"id" => SshRevocationKind::KeyId,
other => return Err(SshIdentityError::InvalidKrlSpecLine(other.to_owned())),
};
entries.push((kind, target.to_owned()));
}
Ok(entries)
}
pub fn write_openssh_krl(
entries: &[SshRevocationEntry],
out: &Path,
@ -394,6 +421,10 @@ pub enum SshIdentityError {
InvalidRevocationExportFormat(String),
#[error("invalid ssh revocation target: {0}")]
InvalidRevocationTarget(String),
#[error("invalid OpenSSH KRL specification line: {0}")]
InvalidKrlSpecLine(String),
#[error("binary OpenSSH KRL files cannot be enumerated; import JSONL or the KRL spec source")]
BinaryKrlImportUnsupported,
#[error("io error: {0}")]
Io(#[from] std::io::Error),
}
@ -485,6 +516,31 @@ mod tests {
assert!(spec.contains("key: ssh-ed25519 AAAA test\n"));
}
#[test]
fn openssh_krl_spec_import_parses_supported_directives() {
let parsed = parse_openssh_krl_spec(
r#"
# comment
serial: 42
id: node:laptop
key: ssh-ed25519 AAAA test
"#,
)
.expect("parse spec");
assert_eq!(
parsed,
vec![
(SshRevocationKind::Serial, "42".to_owned()),
(SshRevocationKind::KeyId, "node:laptop".to_owned()),
(
SshRevocationKind::PublicKey,
"ssh-ed25519 AAAA test".to_owned()
),
]
);
}
#[test]
fn openssh_krl_spec_rejects_multiline_targets() {
let entry = SshRevocationEntry {