use serde::Serialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[non_exhaustive]
pub enum SourceKind {
Usbstor,
MountedDevices,
SetupApi,
PartitionDiag,
KernelPnp,
Lnk,
JumpList,
LinuxKernelLog,
VolumeInfoCache,
MountPoints2,
EmdMgmt,
DeviceImage,
AppleIPod,
MacosUsb,
MacosUnifiedLog,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[non_exhaustive]
pub enum ArtifactContainer {
SystemHive,
SetupApiLog,
EventLog,
LnkFile,
KernelLog,
SoftwareHive,
UserHive,
DeviceMedia,
MacosPlist,
}
impl SourceKind {
#[must_use]
pub const fn container(self) -> ArtifactContainer {
match self {
Self::Usbstor | Self::MountedDevices => ArtifactContainer::SystemHive,
Self::SetupApi => ArtifactContainer::SetupApiLog,
Self::PartitionDiag | Self::KernelPnp => ArtifactContainer::EventLog,
Self::Lnk | Self::JumpList => ArtifactContainer::LnkFile,
Self::LinuxKernelLog => ArtifactContainer::KernelLog,
Self::VolumeInfoCache | Self::EmdMgmt => ArtifactContainer::SoftwareHive,
Self::MountPoints2 => ArtifactContainer::UserHive,
Self::DeviceImage => ArtifactContainer::DeviceMedia,
Self::AppleIPod | Self::MacosUsb | Self::MacosUnifiedLog => {
ArtifactContainer::MacosPlist
}
}
}
#[must_use]
pub fn clock_is_local(self) -> bool {
matches!(self, Self::SetupApi | Self::LinuxKernelLog)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[non_exhaustive]
pub enum Attribute {
FirstConnected,
LastConnected,
LastRemoved,
VolumeName,
VolumeSerial,
AccessedFile,
DriveLetter,
Encryption,
DeviceClass,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
pub enum Value {
Timestamp(i64),
Text(String),
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
pub struct Provenance {
pub source: SourceKind,
pub locator: String,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
pub struct DeviceKey(pub String);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn linux_kernel_log_is_its_own_container_with_a_local_clock() {
assert_eq!(
SourceKind::LinuxKernelLog.container(),
ArtifactContainer::KernelLog
);
assert!(SourceKind::LinuxKernelLog.clock_is_local());
}
#[test]
fn registry_source_lives_in_the_system_hive_container_in_utc() {
assert_eq!(
SourceKind::Usbstor.container(),
ArtifactContainer::SystemHive
);
assert!(!SourceKind::Usbstor.clock_is_local());
}
#[test]
fn volume_info_cache_is_the_software_hive_a_distinct_container_from_system() {
assert_eq!(
SourceKind::VolumeInfoCache.container(),
ArtifactContainer::SoftwareHive
);
assert_ne!(
SourceKind::VolumeInfoCache.container(),
SourceKind::Usbstor.container()
);
assert!(!SourceKind::VolumeInfoCache.clock_is_local());
}
#[test]
fn mountpoints2_is_a_per_user_hive_container() {
assert_eq!(
SourceKind::MountPoints2.container(),
ArtifactContainer::UserHive
);
assert_ne!(
SourceKind::MountPoints2.container(),
SourceKind::VolumeInfoCache.container()
);
assert!(!SourceKind::MountPoints2.clock_is_local());
}
#[test]
fn emdmgmt_shares_the_software_hive_container() {
assert_eq!(
SourceKind::EmdMgmt.container(),
ArtifactContainer::SoftwareHive
);
}
#[test]
fn macos_unified_log_shares_the_macos_artifact_container() {
assert_eq!(
SourceKind::MacosUnifiedLog.container(),
ArtifactContainer::MacosPlist
);
assert!(!SourceKind::MacosUnifiedLog.clock_is_local());
}
#[test]
fn macos_usb_shares_the_macos_artifact_container() {
assert_eq!(
SourceKind::MacosUsb.container(),
ArtifactContainer::MacosPlist
);
assert!(!SourceKind::MacosUsb.clock_is_local());
}
#[test]
fn apple_ipod_is_a_macos_plist_container() {
assert_eq!(
SourceKind::AppleIPod.container(),
ArtifactContainer::MacosPlist
);
assert!(!SourceKind::AppleIPod.clock_is_local());
}
#[test]
fn device_image_is_its_own_device_media_container() {
assert_eq!(
SourceKind::DeviceImage.container(),
ArtifactContainer::DeviceMedia
);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Claim {
pub device: DeviceKey,
pub attribute: Attribute,
pub value: Value,
pub provenance: Provenance,
}