Record SSH-signed keychain init ops

This commit is contained in:
Eric Wendland 2026-05-19 16:04:20 +02:00
commit 48a83c5a26
12 changed files with 283 additions and 18 deletions

View file

@ -70,6 +70,14 @@ impl Store {
op_json TEXT NOT NULL,
created_at_ms INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS keychain_signatures (
op_id TEXT NOT NULL,
signer TEXT NOT NULL,
namespace TEXT NOT NULL,
signature BLOB NOT NULL,
created_at_ms INTEGER NOT NULL,
PRIMARY KEY (op_id, signer, namespace)
);
CREATE TABLE IF NOT EXISTS auth_ops (
op_id TEXT PRIMARY KEY,
resource_id TEXT NOT NULL,
@ -921,6 +929,44 @@ impl Store {
.map_err(StoreError::from)
}
pub fn insert_keychain_signature(
&self,
signature: &StoredKeychainSignature,
) -> Result<(), StoreError> {
self.conn.execute(
r#"INSERT OR REPLACE INTO keychain_signatures(
op_id, signer, namespace, signature, created_at_ms
)
VALUES (?1, ?2, ?3, ?4, ?5)"#,
params![
signature.op_id,
signature.signer,
signature.namespace,
signature.signature,
signature.created_at_ms
],
)?;
Ok(())
}
pub fn list_keychain_signatures(&self) -> Result<Vec<StoredKeychainSignature>, StoreError> {
let mut stmt = self.conn.prepare(
r#"SELECT op_id, signer, namespace, signature, created_at_ms
FROM keychain_signatures ORDER BY created_at_ms, op_id, signer, namespace"#,
)?;
let rows = stmt.query_map([], |row| {
Ok(StoredKeychainSignature {
op_id: row.get(0)?,
signer: row.get(1)?,
namespace: row.get(2)?,
signature: row.get(3)?,
created_at_ms: row.get(4)?,
})
})?;
rows.collect::<Result<Vec<_>, _>>()
.map_err(StoreError::from)
}
pub fn insert_ssh_cert_request(
&self,
request: &StoredSshCertRequest,
@ -1292,6 +1338,15 @@ pub struct StoredKeychainOp {
pub created_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StoredKeychainSignature {
pub op_id: String,
pub signer: String,
pub namespace: String,
pub signature: Vec<u8>,
pub created_at_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StoredSshCertRequest {
pub request_id: String,
@ -1486,6 +1541,29 @@ mod tests {
);
}
#[test]
fn keychain_signatures_roundtrip() {
let store = Store::open_memory().expect("open");
let signature = StoredKeychainSignature {
op_id: "op:keychain:1".to_owned(),
signer: "ssh:blake3:admin".to_owned(),
namespace: "geth.keychain.v1@geth.local".to_owned(),
signature: b"-----BEGIN SSH SIGNATURE-----".to_vec(),
created_at_ms: 3,
};
store
.insert_keychain_signature(&signature)
.expect("insert signature");
assert_eq!(
store
.list_keychain_signatures()
.expect("list keychain signatures"),
vec![signature]
);
}
#[test]
fn cas_pins_roundtrip() {
let store = Store::open_memory().expect("open");