Add SSH cert flows and user service installer

This commit is contained in:
Eric Wendland 2026-05-16 00:17:08 +02:00
commit f302342b1c
21 changed files with 2158 additions and 14 deletions

View file

@ -18,5 +18,6 @@ geth-cli = { path = "../geth-cli" }
[dev-dependencies]
geth-cas = { path = "../geth-cas" }
geth-config = { path = "../geth-config" }
geth-control = { path = "../geth-control" }
geth-node = { path = "../geth-node" }
tempfile.workspace = true

View file

@ -103,3 +103,72 @@ fn initialized_node_can_roundtrip_cas_blob() {
b"hello geth integration"
);
}
#[test]
fn ssh_cert_request_approval_and_revocation_export_use_local_state() {
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 public_key_path = home.path().join("id_ed25519.pub");
std::fs::write(&public_key_path, "ssh-ed25519 AAAATEST eric@geth\n").expect("write pubkey");
let response = geth_node::handle_request(
&node,
geth_control::ControlRequest::SshCertRequest {
public_key_path: public_key_path.clone(),
cert_kind: "user".to_owned(),
principals: vec!["eric".to_owned()],
requested_validity: Some("+52w".to_owned()),
renewal_of: None,
reason: Some("renewal".to_owned()),
},
)
.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: home.path().join("ca_sk"),
valid_for: Some("+4w".to_owned()),
serial: Some(42),
out: None,
},
)
.expect("approve cert");
match response {
geth_control::ControlResponse::SshCertApproved { approval } => {
assert_eq!(approval.request_id.to_string(), request_id);
assert!(approval.signing_command.contains(&"ssh-keygen".to_owned()));
assert!(approval.signing_command.contains(&"42".to_owned()));
}
other => panic!("unexpected response: {other:?}"),
}
let export_path = home.path().join("revocations.jsonl");
geth_node::handle_request(
&node,
geth_control::ControlRequest::SshRevocationAdd {
kind: "public-key".to_owned(),
target: "ssh:blake3:test".to_owned(),
reason: Some("lost key".to_owned()),
},
)
.expect("add revocation");
geth_node::handle_request(
&node,
geth_control::ControlRequest::SshRevocationExport {
out: export_path.clone(),
},
)
.expect("export revocations");
assert!(
std::fs::read_to_string(export_path)
.expect("read revocations")
.contains("lost key")
);
}