Add OpenSSH certificate signing path

This commit is contained in:
Eric Wendland 2026-05-19 15:56:47 +02:00
commit 91c65e367d
9 changed files with 160 additions and 13 deletions

View file

@ -1392,6 +1392,7 @@ fn ssh_cert_request_approval_and_revocation_export_use_local_state() {
valid_for: Some("+4w".to_owned()),
serial: Some(42),
out: None,
sign: false,
subject: None,
},
)
@ -1591,6 +1592,92 @@ fn ssh_cert_and_revocation_commands_check_subject_capabilities() {
.expect("authorized revocation add");
}
#[test]
fn ssh_cert_approve_can_sign_and_import_with_openssh_key() {
if Command::new("ssh-keygen").arg("-?").output().is_err() {
return;
}
let home = tempfile::tempdir().expect("tempdir");
let paths = geth_config::GethPaths::from_home(home.path());
let node = geth_node::init_node(&paths).expect("init node");
let ca_key_path = home.path().join("ca_ed25519");
let user_key_path = home.path().join("user_ed25519");
for key_path in [&ca_key_path, &user_key_path] {
let status = Command::new("ssh-keygen")
.arg("-q")
.arg("-t")
.arg("ed25519")
.arg("-N")
.arg("")
.arg("-f")
.arg(key_path)
.status()
.expect("generate ssh key");
assert!(status.success());
}
let response = geth_node::handle_request(
&node,
geth_control::ControlRequest::SshCertRequest {
public_key_path: user_key_path.with_extension("pub"),
cert_kind: "user".to_owned(),
principals: vec!["eric".to_owned()],
requested_validity: Some("+1w".to_owned()),
renewal_of: None,
reason: Some("sign now".to_owned()),
subject: None,
},
)
.expect("request cert");
let request_id = match response {
geth_control::ControlResponse::SshCertRequested { request } => request.id.to_string(),
other => panic!("unexpected response: {other:?}"),
};
let response = geth_node::handle_request(
&node,
geth_control::ControlRequest::SshCertApprove {
request_id: request_id.clone(),
ca_key_path,
valid_for: Some("+1w".to_owned()),
serial: Some(7),
out: None,
sign: true,
subject: None,
},
)
.expect("approve and sign cert");
match response {
geth_control::ControlResponse::SshCertApproved { approval } => {
assert!(approval.signed);
assert!(approval.certificate_id.is_some());
assert!(approval.note.contains("signed with ssh-keygen"));
}
other => panic!("unexpected response: {other:?}"),
}
let response = geth_node::handle_request(
&node,
geth_control::ControlRequest::SshCertList { subject: None },
)
.expect("list certs");
match response {
geth_control::ControlResponse::SshCertList {
requests,
certificates,
} => {
assert_eq!(certificates.len(), 1);
assert_eq!(certificates[0].request_id.to_string(), request_id);
assert_eq!(
requests[0].status,
geth_ssh_identity::SshCertRequestStatus::Signed
);
}
other => panic!("unexpected response: {other:?}"),
}
}
#[test]
fn ssh_revocation_export_can_write_binary_openssh_krl() {
if Command::new("ssh-keygen").arg("-?").output().is_err() {