fix: batch ssh sync imports

This commit is contained in:
Eric Wendland 2026-07-05 23:19:05 +02:00
commit 7c0399b2ef
3 changed files with 321 additions and 17 deletions

View file

@ -1353,7 +1353,34 @@ impl Store {
&self,
request: &StoredSshCertRequest,
) -> Result<(), StoreError> {
self.conn.execute(
Self::insert_ssh_cert_request_tx(&self.conn, request)
}
pub fn insert_ssh_distribution_records(
&self,
requests: &[StoredSshCertRequest],
certificates: &[StoredSshCertificate],
revocations: &[StoredSshRevocation],
) -> Result<(), StoreError> {
let tx = self.conn.unchecked_transaction()?;
for request in requests {
Self::insert_ssh_cert_request_tx(&tx, request)?;
}
for certificate in certificates {
Self::insert_ssh_certificate_tx(&tx, certificate)?;
}
for revocation in revocations {
Self::insert_ssh_revocation_tx(&tx, revocation)?;
}
tx.commit()?;
Ok(())
}
fn insert_ssh_cert_request_tx(
conn: &rusqlite::Connection,
request: &StoredSshCertRequest,
) -> Result<(), StoreError> {
conn.execute(
r#"INSERT OR REPLACE INTO ssh_cert_requests(
request_id, requester_node, public_key, public_key_fingerprint, cert_kind,
principals_json, requested_validity, renewal_of, reason, status, created_at_ms,
@ -1438,7 +1465,14 @@ impl Store {
&self,
certificate: &StoredSshCertificate,
) -> Result<(), StoreError> {
self.conn.execute(
Self::insert_ssh_certificate_tx(&self.conn, certificate)
}
fn insert_ssh_certificate_tx(
conn: &rusqlite::Connection,
certificate: &StoredSshCertificate,
) -> Result<(), StoreError> {
conn.execute(
r#"INSERT OR REPLACE INTO ssh_certificates(
cert_id, request_id, certificate, certificate_fingerprint, imported_at_ms,
provenance_json
@ -1502,7 +1536,14 @@ impl Store {
&self,
revocation: &StoredSshRevocation,
) -> Result<(), StoreError> {
self.conn.execute(
Self::insert_ssh_revocation_tx(&self.conn, revocation)
}
fn insert_ssh_revocation_tx(
conn: &rusqlite::Connection,
revocation: &StoredSshRevocation,
) -> Result<(), StoreError> {
conn.execute(
r#"INSERT OR REPLACE INTO ssh_revocations(
revocation_id, kind, target, reason, created_at_ms, published, provenance_json
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"#,
@ -1993,6 +2034,65 @@ mod tests {
);
}
#[test]
fn ssh_distribution_records_batch_commits_multiple_records() {
let store = Store::open_memory().expect("open");
let request = StoredSshCertRequest {
request_id: "ssh-cert-request:batch".to_owned(),
requester_node: "node:laptop".to_owned(),
public_key: "ssh-ed25519 AAAA test".to_owned(),
public_key_fingerprint: "ssh:blake3:test".to_owned(),
cert_kind: "user".to_owned(),
principals: vec!["eric".to_owned()],
requested_validity: Some("+52w".to_owned()),
renewal_of: None,
reason: Some("renewal".to_owned()),
status: "pending".to_owned(),
created_at_ms: 1,
provenance_json: Some(r#"{"test":true}"#.to_owned()),
};
let certificate = StoredSshCertificate {
cert_id: "ssh-cert:batch".to_owned(),
request_id: request.request_id.clone(),
certificate: "ssh-ed25519-cert-v01@openssh.com AAAA test".to_owned(),
certificate_fingerprint: "ssh:blake3:cert".to_owned(),
imported_at_ms: 2,
provenance_json: Some(r#"{"test":true}"#.to_owned()),
};
let revocation = StoredSshRevocation {
revocation_id: "ssh-revocation:batch".to_owned(),
kind: "public-key".to_owned(),
target: "ssh:blake3:test".to_owned(),
reason: Some("lost key".to_owned()),
created_at_ms: 3,
published: true,
provenance_json: Some(r#"{"test":true}"#.to_owned()),
};
store
.insert_ssh_distribution_records(
std::slice::from_ref(&request),
std::slice::from_ref(&certificate),
std::slice::from_ref(&revocation),
)
.expect("batch insert SSH records");
assert_eq!(
store
.get_ssh_cert_request("ssh-cert-request:batch")
.expect("get request"),
Some(request)
);
assert_eq!(
store.list_ssh_certificates().expect("list certificates"),
vec![certificate]
);
assert_eq!(
store.list_ssh_revocations().expect("list revocations"),
vec![revocation]
);
}
#[test]
fn peer_card_roundtrip() {
let store = Store::open_memory().expect("open");