Require signed SSH metadata provenance
This commit is contained in:
parent
c5548e4df9
commit
6e04e786c2
8 changed files with 414 additions and 45 deletions
|
|
@ -117,6 +117,16 @@ impl std::str::FromStr for SshCertRequestStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SshRecordProvenance {
|
||||
pub namespace: String,
|
||||
pub signer_node: NodeId,
|
||||
pub signer_agent: String,
|
||||
pub signer_public_key: String,
|
||||
pub signature_hex: String,
|
||||
pub signed_at: UnixMillis,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SshCertRequest {
|
||||
pub id: SshCertRequestId,
|
||||
|
|
@ -130,6 +140,7 @@ pub struct SshCertRequest {
|
|||
pub reason: Option<String>,
|
||||
pub status: SshCertRequestStatus,
|
||||
pub created_at: UnixMillis,
|
||||
pub provenance: Option<SshRecordProvenance>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
@ -154,6 +165,7 @@ pub struct SshCertificateRecord {
|
|||
pub certificate: String,
|
||||
pub certificate_fingerprint: String,
|
||||
pub imported_at: UnixMillis,
|
||||
pub provenance: Option<SshRecordProvenance>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
@ -205,6 +217,85 @@ pub struct SshRevocationEntry {
|
|||
pub reason: Option<String>,
|
||||
pub created_at: UnixMillis,
|
||||
pub published: bool,
|
||||
pub provenance: Option<SshRecordProvenance>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SshCertRequestSigningPayload {
|
||||
pub id: SshCertRequestId,
|
||||
pub requester_node: NodeId,
|
||||
pub public_key: String,
|
||||
pub public_key_fingerprint: String,
|
||||
pub cert_kind: SshCertKind,
|
||||
pub principals: Vec<String>,
|
||||
pub requested_validity: Option<String>,
|
||||
pub renewal_of: Option<SshCertId>,
|
||||
pub reason: Option<String>,
|
||||
pub status: SshCertRequestStatus,
|
||||
pub created_at: UnixMillis,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SshCertificateSigningPayload {
|
||||
pub id: SshCertId,
|
||||
pub request_id: SshCertRequestId,
|
||||
pub certificate: String,
|
||||
pub certificate_fingerprint: String,
|
||||
pub imported_at: UnixMillis,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SshRevocationSigningPayload {
|
||||
pub id: SshRevocationId,
|
||||
pub kind: SshRevocationKind,
|
||||
pub target: String,
|
||||
pub reason: Option<String>,
|
||||
pub created_at: UnixMillis,
|
||||
pub published: bool,
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn ssh_cert_request_signing_payload(request: &SshCertRequest) -> SshCertRequestSigningPayload {
|
||||
SshCertRequestSigningPayload {
|
||||
id: request.id.clone(),
|
||||
requester_node: request.requester_node.clone(),
|
||||
public_key: request.public_key.clone(),
|
||||
public_key_fingerprint: request.public_key_fingerprint.clone(),
|
||||
cert_kind: request.cert_kind.clone(),
|
||||
principals: request.principals.clone(),
|
||||
requested_validity: request.requested_validity.clone(),
|
||||
renewal_of: request.renewal_of.clone(),
|
||||
reason: request.reason.clone(),
|
||||
status: request.status.clone(),
|
||||
created_at: request.created_at,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn ssh_certificate_signing_payload(
|
||||
certificate: &SshCertificateRecord,
|
||||
) -> SshCertificateSigningPayload {
|
||||
SshCertificateSigningPayload {
|
||||
id: certificate.id.clone(),
|
||||
request_id: certificate.request_id.clone(),
|
||||
certificate: certificate.certificate.clone(),
|
||||
certificate_fingerprint: certificate.certificate_fingerprint.clone(),
|
||||
imported_at: certificate.imported_at,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn ssh_revocation_signing_payload(
|
||||
revocation: &SshRevocationEntry,
|
||||
) -> SshRevocationSigningPayload {
|
||||
SshRevocationSigningPayload {
|
||||
id: revocation.id.clone(),
|
||||
kind: revocation.kind.clone(),
|
||||
target: revocation.target.clone(),
|
||||
reason: revocation.reason.clone(),
|
||||
created_at: revocation.created_at,
|
||||
published: revocation.published,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
@ -449,6 +540,7 @@ mod tests {
|
|||
reason: Some("bootstrap".to_owned()),
|
||||
status: SshCertRequestStatus::Pending,
|
||||
created_at: UnixMillis(1),
|
||||
provenance: None,
|
||||
};
|
||||
let json = serde_json::to_string(&request).expect("json");
|
||||
let decoded: SshCertRequest = serde_json::from_str(&json).expect("decode");
|
||||
|
|
@ -469,6 +561,7 @@ mod tests {
|
|||
reason: None,
|
||||
status: SshCertRequestStatus::Pending,
|
||||
created_at: UnixMillis(1),
|
||||
provenance: None,
|
||||
};
|
||||
let command = build_ssh_cert_sign_command(
|
||||
&request,
|
||||
|
|
@ -492,6 +585,7 @@ mod tests {
|
|||
reason: None,
|
||||
created_at: UnixMillis(1),
|
||||
published: false,
|
||||
provenance: None,
|
||||
},
|
||||
SshRevocationEntry {
|
||||
id: "ssh-revocation:2".into(),
|
||||
|
|
@ -500,6 +594,7 @@ mod tests {
|
|||
reason: None,
|
||||
created_at: UnixMillis(2),
|
||||
published: false,
|
||||
provenance: None,
|
||||
},
|
||||
SshRevocationEntry {
|
||||
id: "ssh-revocation:3".into(),
|
||||
|
|
@ -508,6 +603,7 @@ mod tests {
|
|||
reason: None,
|
||||
created_at: UnixMillis(3),
|
||||
published: false,
|
||||
provenance: None,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -552,6 +648,7 @@ mod tests {
|
|||
reason: None,
|
||||
created_at: UnixMillis(1),
|
||||
published: false,
|
||||
provenance: None,
|
||||
};
|
||||
|
||||
assert!(openssh_krl_spec_line(&entry).is_err());
|
||||
|
|
@ -586,6 +683,7 @@ mod tests {
|
|||
reason: Some("test".to_owned()),
|
||||
created_at: UnixMillis(1),
|
||||
published: true,
|
||||
provenance: None,
|
||||
};
|
||||
let krl_path = dir.path().join("revoked.krl");
|
||||
|
||||
|
|
@ -666,6 +764,7 @@ mod tests {
|
|||
reason: Some("test certificate revocation".to_owned()),
|
||||
created_at: UnixMillis(1),
|
||||
published: true,
|
||||
provenance: None,
|
||||
};
|
||||
let krl_path = dir.path().join("revoked-certs.krl");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue