use serde::{Deserialize, Serialize}; pub const OPAQUE_ID_BYTES: usize = 32; pub const SHA256_BYTES: usize = 32; pub const BOOT_ID_BYTES: usize = 16; macro_rules! opaque_identity { ($($name:ident),+ $(,)?) => { $( #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct $name([u8; OPAQUE_ID_BYTES]); impl $name { #[must_use] pub const fn new(bytes: [u8; OPAQUE_ID_BYTES]) -> Self { Self(bytes) } #[must_use] pub const fn as_bytes(&self) -> &[u8; OPAQUE_ID_BYTES] { &self.0 } } )+ }; } macro_rules! digest_identity { ($($name:ident),+ $(,)?) => { $( #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct $name([u8; SHA256_BYTES]); impl $name { #[must_use] pub const fn new(bytes: [u8; SHA256_BYTES]) -> Self { Self(bytes) } #[must_use] pub const fn as_bytes(&self) -> &[u8; SHA256_BYTES] { &self.0 } } )+ }; } macro_rules! numeric_identity { ($($name:ident($inner:ty)),+ $(,)?) => { $( #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct $name($inner); impl $name { #[must_use] pub const fn new(value: $inner) -> Self { Self(value) } #[must_use] pub const fn get(self) -> $inner { self.0 } } )+ }; } opaque_identity!( DomainId, CoordinatorId, NetworkSidecarId, SandboxId, ClientId, SessionId, SessionAnchorId, RequestId, PreparedArtifactId, PrepareOperationId, ProtocolCredentialId, CapabilityId, ContainerId, PolicyId, ); digest_identity!( ConfigurationFingerprint, DerivedPolicyDigest, ReadinessFingerprint, BundleDigest, SelectedManifestDigest, IdMapDigest, CertificateDigest, TrustManifestDigest, RequestDigest, StreamDigest, ); numeric_identity!( GenerationId(u64), HostPidLocator(u32), ProcessStartTimeTicks(u64), GuestProcessId(u32), GuestProcessStartTimeTicks(u64), GuestProcessGroupId(u32), FileDescriptor(i32), DeviceId(u64), InodeId(u64), PidfsDeviceId(u64), PidfsInodeId(u64), MountId(u64), ); #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct BootId([u8; BOOT_ID_BYTES]); impl BootId { #[must_use] pub const fn new(bytes: [u8; BOOT_ID_BYTES]) -> Self { Self(bytes) } #[must_use] pub const fn as_bytes(&self) -> &[u8; BOOT_ID_BYTES] { &self.0 } } #[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct HostPath(Vec); impl HostPath { #[must_use] pub const fn new(bytes: Vec) -> Self { Self(bytes) } #[must_use] pub fn as_bytes(&self) -> &[u8] { &self.0 } } #[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct SourceIdentity(Vec); impl SourceIdentity { #[must_use] pub const fn new(bytes: Vec) -> Self { Self(bytes) } #[must_use] pub fn as_bytes(&self) -> &[u8] { &self.0 } } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct PidfsProcessAuthorityV1 { pub boot_id: BootId, pub pidfs_st_dev: PidfsDeviceId, pub pidfs_st_ino: PidfsInodeId, } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct PidfsProcessIdentityV1 { authority: PidfsProcessAuthorityV1, host_pid: HostPidLocator, start_time_ticks: ProcessStartTimeTicks, } impl PidfsProcessIdentityV1 { #[must_use] pub const fn new( authority: PidfsProcessAuthorityV1, host_pid: HostPidLocator, start_time_ticks: ProcessStartTimeTicks, ) -> Self { Self { authority, host_pid, start_time_ticks, } } #[must_use] pub const fn authority(&self) -> PidfsProcessAuthorityV1 { self.authority } #[must_use] pub const fn host_pid(&self) -> HostPidLocator { self.host_pid } #[must_use] pub const fn start_time_ticks(&self) -> ProcessStartTimeTicks { self.start_time_ticks } #[must_use] pub fn has_same_authority(&self, other: &Self) -> bool { self.authority == other.authority } } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct NamespaceIdentity { pub device: DeviceId, pub inode: InodeId, } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct MountIdentity { pub mount_id: MountId, pub device: DeviceId, pub inode: InodeId, } #[cfg(test)] mod tests { use std::any::TypeId; use std::collections::HashSet; use super::{ BootId, ContainerId, CoordinatorId, DeviceId, DomainId, GenerationId, GuestProcessId, GuestProcessStartTimeTicks, HostPidLocator, MountIdentity, NamespaceIdentity, NetworkSidecarId, PidfsDeviceId, PidfsInodeId, PidfsProcessAuthorityV1, PidfsProcessIdentityV1, PreparedArtifactId, ProcessStartTimeTicks, RequestId, SandboxId, SessionId, }; #[test] fn identity_categories_are_nominally_distinct() { let identities = [ TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), ]; assert_eq!( identities.into_iter().collect::>().len(), identities.len() ); } }