Make codec shape authority compile-time and fixed
This commit is contained in:
parent
bfe21dfb3f
commit
54cc167f81
4 changed files with 322 additions and 52 deletions
|
|
@ -5,6 +5,8 @@ use std::fmt;
|
|||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
use crate::records::SchemaType;
|
||||
|
||||
pub const MAX_SCHEMA_RECORD_BYTES: usize = 1024 * 1024;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -45,7 +47,7 @@ impl std::error::Error for CodecError {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error when serialization fails or the encoded value exceeds the generic limit.
|
||||
pub fn encode<T: Serialize>(record: &T) -> Result<Vec<u8>, CodecError> {
|
||||
pub fn encode<T: SchemaType + Serialize>(record: &T) -> Result<Vec<u8>, CodecError> {
|
||||
let encoded = postcard::to_stdvec(record).map_err(CodecError::MalformedPayload)?;
|
||||
if encoded.len() > MAX_SCHEMA_RECORD_BYTES {
|
||||
return Err(CodecError::RecordTooLarge {
|
||||
|
|
@ -63,7 +65,7 @@ pub fn encode<T: Serialize>(record: &T) -> Result<Vec<u8>, CodecError> {
|
|||
/// Returns an error for oversized, malformed, trailing, or non-minimal Postcard input.
|
||||
pub fn decode<T>(encoded: &[u8]) -> Result<T, CodecError>
|
||||
where
|
||||
T: DeserializeOwned + Serialize,
|
||||
T: DeserializeOwned + SchemaType + Serialize,
|
||||
{
|
||||
if encoded.len() > MAX_SCHEMA_RECORD_BYTES {
|
||||
return Err(CodecError::RecordTooLarge {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,20 @@ use std::ffi::{OsStr, OsString};
|
|||
|
||||
use crate::codec::{CodecError, encode};
|
||||
use crate::identity::{ClientId, RequestId, SessionId};
|
||||
use crate::records::GenerationIdentity;
|
||||
use crate::records::{GenerationIdentity, SchemaType};
|
||||
use serde::Serialize;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct ClientEnrollmentBindingV1<'a> {
|
||||
generation_identity: &'a GenerationIdentity,
|
||||
cli_id: ClientId,
|
||||
}
|
||||
|
||||
impl SchemaType for ClientEnrollmentBindingV1<'_> {
|
||||
const NAME: &'static str = "ClientEnrollmentBindingV1";
|
||||
}
|
||||
|
||||
fn identifier_hex(bytes: &[u8]) -> String {
|
||||
use std::fmt::Write as _;
|
||||
|
||||
|
|
@ -22,7 +33,10 @@ pub fn client_enrollment_binding(
|
|||
generation_identity: &GenerationIdentity,
|
||||
cli_id: ClientId,
|
||||
) -> Result<String, CodecError> {
|
||||
let encoded = encode(&(generation_identity, cli_id))?;
|
||||
let encoded = encode(&ClientEnrollmentBindingV1 {
|
||||
generation_identity,
|
||||
cli_id,
|
||||
})?;
|
||||
Ok(format!(
|
||||
"lazaret-client-{}",
|
||||
identifier_hex(&Sha256::digest(encoded))
|
||||
|
|
@ -83,3 +97,27 @@ pub fn result_chunk_file_name(request_id: RequestId, sequence: u64) -> OsString
|
|||
pub fn is_ready_record(name: &OsStr) -> bool {
|
||||
name.as_encoded_bytes().ends_with(b".ready")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::identity::{
|
||||
ConfigurationFingerprint, CoordinatorId, DomainId, GenerationId, SandboxId,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn client_enrollment_binding_vector_is_stable() {
|
||||
let identity = GenerationIdentity {
|
||||
agent_profile: "trusted".into(),
|
||||
domain_id: DomainId::new([1; 32]),
|
||||
generation_id: GenerationId::new(2),
|
||||
configuration_fingerprint: ConfigurationFingerprint::new([4; 32]),
|
||||
coordinator_id: CoordinatorId::new([3; 32]),
|
||||
sandbox_id: SandboxId::new([5; 32]),
|
||||
};
|
||||
assert_eq!(
|
||||
client_enrollment_binding(&identity, ClientId::new([6; 32])).unwrap(),
|
||||
"lazaret-client-63c1e3cd11c3acb917053499be99acc57b3e67fdbb332dbf6d03a7b1540d478d"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::codec;
|
||||
use crate::identity::{ClientId, ConfigurationFingerprint, DomainId, SessionAnchorId, SessionId};
|
||||
use crate::records::ProtocolVersion;
|
||||
use crate::records::{ProtocolVersion, SchemaType};
|
||||
|
||||
pub const BOOTSTRAP_WAITER_SOCKET_NAME: &str = "wait.sock";
|
||||
pub const PRIVATE_CLIENT_BOOTSTRAP_ROLE: &str = "--lazaret-private-client-bootstrap-v1";
|
||||
|
|
@ -44,7 +44,7 @@ impl std::error::Error for BootstrapWaiterFrameError {}
|
|||
///
|
||||
/// # Errors
|
||||
/// Refuses oversized or unencodable records and stream write failures.
|
||||
pub fn write_waiter_frame<T: Serialize>(
|
||||
pub fn write_waiter_frame<T: SchemaType + Serialize>(
|
||||
stream: &mut impl Write,
|
||||
record: &T,
|
||||
) -> Result<(), BootstrapWaiterFrameError> {
|
||||
|
|
@ -64,7 +64,7 @@ pub fn write_waiter_frame<T: Serialize>(
|
|||
/// Refuses oversized, malformed, or incomplete frames and stream read failures.
|
||||
pub fn read_waiter_frame<T>(stream: &mut impl Read) -> Result<T, BootstrapWaiterFrameError>
|
||||
where
|
||||
T: serde::de::DeserializeOwned + Serialize,
|
||||
T: SchemaType + serde::de::DeserializeOwned + Serialize,
|
||||
{
|
||||
let mut length = [0_u8; 4];
|
||||
stream.read_exact(&mut length).map_err(failure)?;
|
||||
|
|
|
|||
|
|
@ -2,29 +2,30 @@ use super::{
|
|||
AddressFamily, AddressFamilyDisposition, ArtifactLease, ArtifactState, ClientEnrollmentRequest,
|
||||
ClientEnrollmentResponse, ConfigurationFingerprintRecordV1, ControlRequest, ControlResponse,
|
||||
DefaultAction, DeniedDestinationObservation, DerivedNetworkPolicy, DeveloperDecision,
|
||||
DeveloperDecisionKind, DnsObservation, Domain, DomainStore, EnvironmentReference,
|
||||
EscalationOutcome, Generation, GenerationIdentity, GitRoutingOwnership, GuestProcessIdentity,
|
||||
HelperOwnership, HostProcessIdentity, HostProcessOwnershipSlot, InteractiveSessionBatch,
|
||||
InteractiveSessionEvent, InteractiveSessionMessage, InteractiveSessionRequest, Mailbox,
|
||||
MailboxCancellation, MailboxRequest, MailboxResult, MailboxResultAck, MailboxResultChunk,
|
||||
MountIdentity, NamespaceIdentity, NetworkObservation, NetworkOwnership,
|
||||
NetworkReachabilityProbe, NetworkReadinessAttestation, NetworkReadinessEvidence,
|
||||
NetworkReadinessIdentity, NonInteractiveOutput, NonInteractiveSessionMessage,
|
||||
NonInteractiveSessionRequest, Participant, ParticipantOwnership, ParticipantState,
|
||||
PermittedDestinationObservation, PersistedHostProcessOwnership, PidfsProcessAuthorityV1,
|
||||
PidfsProcessIdentityV1, PolicyAction, PolicyDelivery, PrefixRule, PrepareOperation,
|
||||
PrepareStageState, PreparedArtifact, PreparedLowerOwnership, ProcessOwnershipCommitAck,
|
||||
ProcessOwnershipMessageVersion, ProtocolCredential, ProtocolCredentialRole,
|
||||
ProtocolPublicationIdentity, PtyIdentity, PublicationOwnership, ResolvedAutoApprovalRule,
|
||||
ResolvedNetworkReadinessV1, ResolvedVolume, Resolver, ResultStream, SandboxCredentialBundle,
|
||||
SandboxOwnership, Session, SessionBinding, SessionClose, SessionExit, SessionExitOutcome,
|
||||
SessionRegistrationRequest, SessionRegistrationResponse, SessionRequestCapability,
|
||||
SessionTerminal, SessionTerminalEvent, SessionTerminalMessage, SessionTerminalState,
|
||||
SignedProtocolRecord, StagedProcessOwnership, StateAnchorOwnership, StateAnchorReleaseEvidence,
|
||||
StorageCatalog, StoreMetadata, TerminalInput, TerminalOutput, TerminalPrompt, TerminalResize,
|
||||
TerminalSignal, TerminalSignalKind, TlsCredential, TlsRole, TrustManifest,
|
||||
TrustedHostConfigurationV1,
|
||||
DeveloperDecisionKind, DnsObservation, Domain, DomainStore, DomainStoreMetadata,
|
||||
EnvironmentReference, EscalationOutcome, Generation, GenerationIdentity, GitRoutingOwnership,
|
||||
GuestProcessIdentity, HelperOwnership, HostProcessIdentity, HostProcessOwnershipSlot,
|
||||
InteractiveSessionBatch, InteractiveSessionEvent, InteractiveSessionMessage,
|
||||
InteractiveSessionRequest, Mailbox, MailboxCancellation, MailboxRequest, MailboxResult,
|
||||
MailboxResultAck, MailboxResultChunk, MountIdentity, NamespaceIdentity, NetworkObservation,
|
||||
NetworkOwnership, NetworkReachabilityProbe, NetworkReadinessAttestation,
|
||||
NetworkReadinessEvidence, NetworkReadinessIdentity, NonInteractiveOutput,
|
||||
NonInteractiveSessionMessage, NonInteractiveSessionRequest, Participant, ParticipantOwnership,
|
||||
ParticipantState, PermittedDestinationObservation, PersistedHostProcessOwnership,
|
||||
PidfsProcessAuthorityV1, PidfsProcessIdentityV1, PolicyAction, PolicyDelivery, PrefixRule,
|
||||
PrepareOperation, PrepareStageState, PreparedArtifact, PreparedLowerOwnership,
|
||||
ProcessOwnershipCommitAck, ProcessOwnershipMessageVersion, ProtocolCredential,
|
||||
ProtocolCredentialRole, ProtocolPublicationIdentity, PtyIdentity, PublicationOwnership,
|
||||
ResolvedAutoApprovalRule, ResolvedNetworkReadinessV1, ResolvedVolume, Resolver, ResultStream,
|
||||
SandboxCredentialBundle, SandboxOwnership, Session, SessionBinding, SessionClose, SessionExit,
|
||||
SessionExitOutcome, SessionRegistrationRequest, SessionRegistrationResponse,
|
||||
SessionRequestCapability, SessionTerminal, SessionTerminalEvent, SessionTerminalMessage,
|
||||
SessionTerminalState, SignedProtocolRecord, StagedProcessOwnership, StateAnchorOwnership,
|
||||
StateAnchorReleaseEvidence, StorageCatalog, StorageCatalogMetadata, StoreMetadata,
|
||||
TerminalInput, TerminalOutput, TerminalPrompt, TerminalResize, TerminalSignal,
|
||||
TerminalSignalKind, TlsCredential, TlsRole, TrustManifest, TrustedHostConfigurationV1,
|
||||
};
|
||||
use crate::protocol::{BootstrapWaitOutcome, BootstrapWaitRequest};
|
||||
|
||||
pub trait SchemaType {
|
||||
const NAME: &'static str;
|
||||
|
|
@ -44,6 +45,8 @@ macro_rules! schema_types {
|
|||
|
||||
schema_types!(
|
||||
"StoreMetadata" => StoreMetadata,
|
||||
"DomainStoreMetadata" => DomainStoreMetadata,
|
||||
"StorageCatalogMetadata" => StorageCatalogMetadata,
|
||||
"Domain" => Domain,
|
||||
"Generation" => Generation,
|
||||
"Participant" => Participant,
|
||||
|
|
@ -146,4 +149,6 @@ schema_types!(
|
|||
"DomainStore" => DomainStore,
|
||||
"StorageCatalog" => StorageCatalog,
|
||||
"PrepareStageState" => PrepareStageState,
|
||||
"BootstrapWaitRequest" => BootstrapWaitRequest,
|
||||
"BootstrapWaitOutcome" => BootstrapWaitOutcome,
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue