Require signed SSH metadata provenance
This commit is contained in:
parent
c5548e4df9
commit
6e04e786c2
8 changed files with 414 additions and 45 deletions
|
|
@ -186,14 +186,16 @@ impl Store {
|
|||
renewal_of TEXT,
|
||||
reason TEXT,
|
||||
status TEXT NOT NULL,
|
||||
created_at_ms INTEGER NOT NULL
|
||||
created_at_ms INTEGER NOT NULL,
|
||||
provenance_json TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS ssh_certificates (
|
||||
cert_id TEXT PRIMARY KEY,
|
||||
request_id TEXT NOT NULL,
|
||||
certificate TEXT NOT NULL,
|
||||
certificate_fingerprint TEXT NOT NULL,
|
||||
imported_at_ms INTEGER NOT NULL
|
||||
imported_at_ms INTEGER NOT NULL,
|
||||
provenance_json TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS ssh_revocations (
|
||||
revocation_id TEXT PRIMARY KEY,
|
||||
|
|
@ -201,7 +203,8 @@ impl Store {
|
|||
target TEXT NOT NULL,
|
||||
reason TEXT,
|
||||
created_at_ms INTEGER NOT NULL,
|
||||
published INTEGER NOT NULL DEFAULT 0
|
||||
published INTEGER NOT NULL DEFAULT 0,
|
||||
provenance_json TEXT
|
||||
);
|
||||
INSERT OR IGNORE INTO meta(key, value) VALUES ('schema_version', '1');
|
||||
"#,
|
||||
|
|
@ -211,6 +214,9 @@ impl Store {
|
|||
"signer_public_key",
|
||||
"TEXT NOT NULL DEFAULT ''",
|
||||
)?;
|
||||
self.add_column_if_missing("ssh_cert_requests", "provenance_json", "TEXT")?;
|
||||
self.add_column_if_missing("ssh_certificates", "provenance_json", "TEXT")?;
|
||||
self.add_column_if_missing("ssh_revocations", "provenance_json", "TEXT")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -1001,8 +1007,9 @@ impl Store {
|
|||
self.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
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)"#,
|
||||
principals_json, requested_validity, renewal_of, reason, status, created_at_ms,
|
||||
provenance_json
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"#,
|
||||
params![
|
||||
request.request_id,
|
||||
request.requester_node,
|
||||
|
|
@ -1014,7 +1021,8 @@ impl Store {
|
|||
request.renewal_of,
|
||||
request.reason,
|
||||
request.status,
|
||||
request.created_at_ms
|
||||
request.created_at_ms,
|
||||
request.provenance_json
|
||||
],
|
||||
)?;
|
||||
Ok(())
|
||||
|
|
@ -1026,7 +1034,8 @@ impl Store {
|
|||
) -> Result<Option<StoredSshCertRequest>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT request_id, requester_node, public_key, public_key_fingerprint, cert_kind,
|
||||
principals_json, requested_validity, renewal_of, reason, status, created_at_ms
|
||||
principals_json, requested_validity, renewal_of, reason, status, created_at_ms,
|
||||
provenance_json
|
||||
FROM ssh_cert_requests WHERE request_id = ?1"#,
|
||||
)?;
|
||||
let mut rows = stmt.query(params![request_id])?;
|
||||
|
|
@ -1052,7 +1061,8 @@ impl Store {
|
|||
pub fn list_ssh_cert_requests(&self) -> Result<Vec<StoredSshCertRequest>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT request_id, requester_node, public_key, public_key_fingerprint, cert_kind,
|
||||
principals_json, requested_validity, renewal_of, reason, status, created_at_ms
|
||||
principals_json, requested_validity, renewal_of, reason, status, created_at_ms,
|
||||
provenance_json
|
||||
FROM ssh_cert_requests ORDER BY created_at_ms, request_id"#,
|
||||
)?;
|
||||
let rows = stmt.query_map([], stored_ssh_cert_request_from_row)?;
|
||||
|
|
@ -1066,7 +1076,8 @@ impl Store {
|
|||
) -> Result<Vec<StoredSshCertRequest>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT request_id, requester_node, public_key, public_key_fingerprint, cert_kind,
|
||||
principals_json, requested_validity, renewal_of, reason, status, created_at_ms
|
||||
principals_json, requested_validity, renewal_of, reason, status, created_at_ms,
|
||||
provenance_json
|
||||
FROM ssh_cert_requests WHERE created_at_ms >= ?1 ORDER BY created_at_ms, request_id"#,
|
||||
)?;
|
||||
let rows = stmt.query_map(params![since_ms], stored_ssh_cert_request_from_row)?;
|
||||
|
|
@ -1080,14 +1091,16 @@ impl Store {
|
|||
) -> Result<(), StoreError> {
|
||||
self.conn.execute(
|
||||
r#"INSERT OR REPLACE INTO ssh_certificates(
|
||||
cert_id, request_id, certificate, certificate_fingerprint, imported_at_ms
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5)"#,
|
||||
cert_id, request_id, certificate, certificate_fingerprint, imported_at_ms,
|
||||
provenance_json
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6)"#,
|
||||
params![
|
||||
certificate.cert_id,
|
||||
certificate.request_id,
|
||||
certificate.certificate,
|
||||
certificate.certificate_fingerprint,
|
||||
certificate.imported_at_ms
|
||||
certificate.imported_at_ms,
|
||||
certificate.provenance_json
|
||||
],
|
||||
)?;
|
||||
Ok(())
|
||||
|
|
@ -1096,6 +1109,7 @@ impl Store {
|
|||
pub fn list_ssh_certificates(&self) -> Result<Vec<StoredSshCertificate>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT cert_id, request_id, certificate, certificate_fingerprint, imported_at_ms
|
||||
, provenance_json
|
||||
FROM ssh_certificates ORDER BY imported_at_ms, cert_id"#,
|
||||
)?;
|
||||
let rows = stmt.query_map([], |row| {
|
||||
|
|
@ -1105,6 +1119,7 @@ impl Store {
|
|||
certificate: row.get(2)?,
|
||||
certificate_fingerprint: row.get(3)?,
|
||||
imported_at_ms: row.get(4)?,
|
||||
provenance_json: row.get(5)?,
|
||||
})
|
||||
})?;
|
||||
rows.collect::<Result<Vec<_>, _>>()
|
||||
|
|
@ -1117,6 +1132,7 @@ impl Store {
|
|||
) -> Result<Vec<StoredSshCertificate>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT cert_id, request_id, certificate, certificate_fingerprint, imported_at_ms
|
||||
, provenance_json
|
||||
FROM ssh_certificates WHERE imported_at_ms >= ?1 ORDER BY imported_at_ms, cert_id"#,
|
||||
)?;
|
||||
let rows = stmt.query_map(params![since_ms], |row| {
|
||||
|
|
@ -1126,6 +1142,7 @@ impl Store {
|
|||
certificate: row.get(2)?,
|
||||
certificate_fingerprint: row.get(3)?,
|
||||
imported_at_ms: row.get(4)?,
|
||||
provenance_json: row.get(5)?,
|
||||
})
|
||||
})?;
|
||||
rows.collect::<Result<Vec<_>, _>>()
|
||||
|
|
@ -1138,15 +1155,16 @@ impl Store {
|
|||
) -> Result<(), StoreError> {
|
||||
self.conn.execute(
|
||||
r#"INSERT OR REPLACE INTO ssh_revocations(
|
||||
revocation_id, kind, target, reason, created_at_ms, published
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6)"#,
|
||||
revocation_id, kind, target, reason, created_at_ms, published, provenance_json
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"#,
|
||||
params![
|
||||
revocation.revocation_id,
|
||||
revocation.kind,
|
||||
revocation.target,
|
||||
revocation.reason,
|
||||
revocation.created_at_ms,
|
||||
if revocation.published { 1_i64 } else { 0_i64 }
|
||||
if revocation.published { 1_i64 } else { 0_i64 },
|
||||
revocation.provenance_json
|
||||
],
|
||||
)?;
|
||||
Ok(())
|
||||
|
|
@ -1155,6 +1173,7 @@ impl Store {
|
|||
pub fn list_ssh_revocations(&self) -> Result<Vec<StoredSshRevocation>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT revocation_id, kind, target, reason, created_at_ms, published
|
||||
, provenance_json
|
||||
FROM ssh_revocations ORDER BY created_at_ms, revocation_id"#,
|
||||
)?;
|
||||
let rows = stmt.query_map([], |row| {
|
||||
|
|
@ -1165,6 +1184,7 @@ impl Store {
|
|||
reason: row.get(3)?,
|
||||
created_at_ms: row.get(4)?,
|
||||
published: row.get::<_, i64>(5)? != 0,
|
||||
provenance_json: row.get(6)?,
|
||||
})
|
||||
})?;
|
||||
rows.collect::<Result<Vec<_>, _>>()
|
||||
|
|
@ -1177,6 +1197,7 @@ impl Store {
|
|||
) -> Result<Vec<StoredSshRevocation>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT revocation_id, kind, target, reason, created_at_ms, published
|
||||
, provenance_json
|
||||
FROM ssh_revocations WHERE created_at_ms >= ?1 ORDER BY created_at_ms, revocation_id"#,
|
||||
)?;
|
||||
let rows = stmt.query_map(params![since_ms], |row| {
|
||||
|
|
@ -1187,6 +1208,7 @@ impl Store {
|
|||
reason: row.get(3)?,
|
||||
created_at_ms: row.get(4)?,
|
||||
published: row.get::<_, i64>(5)? != 0,
|
||||
provenance_json: row.get(6)?,
|
||||
})
|
||||
})?;
|
||||
rows.collect::<Result<Vec<_>, _>>()
|
||||
|
|
@ -1213,6 +1235,7 @@ fn stored_ssh_cert_request_from_row(
|
|||
reason: row.get(8)?,
|
||||
status: row.get(9)?,
|
||||
created_at_ms: row.get(10)?,
|
||||
provenance_json: row.get(11)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1388,6 +1411,7 @@ pub struct StoredSshCertRequest {
|
|||
pub reason: Option<String>,
|
||||
pub status: String,
|
||||
pub created_at_ms: i64,
|
||||
pub provenance_json: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
|
@ -1397,6 +1421,7 @@ pub struct StoredSshCertificate {
|
|||
pub certificate: String,
|
||||
pub certificate_fingerprint: String,
|
||||
pub imported_at_ms: i64,
|
||||
pub provenance_json: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
|
@ -1407,6 +1432,7 @@ pub struct StoredSshRevocation {
|
|||
pub reason: Option<String>,
|
||||
pub created_at_ms: i64,
|
||||
pub published: bool,
|
||||
pub provenance_json: Option<String>,
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
@ -1445,6 +1471,7 @@ mod tests {
|
|||
reason: Some("renewal".to_owned()),
|
||||
status: "pending".to_owned(),
|
||||
created_at_ms: 1,
|
||||
provenance_json: Some(r#"{"test":true}"#.to_owned()),
|
||||
};
|
||||
store
|
||||
.insert_ssh_cert_request(&request)
|
||||
|
|
@ -1463,6 +1490,7 @@ mod tests {
|
|||
reason: Some("lost key".to_owned()),
|
||||
created_at_ms: 2,
|
||||
published: true,
|
||||
provenance_json: Some(r#"{"test":true}"#.to_owned()),
|
||||
};
|
||||
store
|
||||
.insert_ssh_revocation(&revocation)
|
||||
|
|
|
|||
Loading…
Reference in a new issue