Crates.io | falco_event |
lib.rs | falco_event |
version | |
source | src |
created_at | 2024-03-13 13:38:42.893774 |
updated_at | 2024-12-17 08:30:23.594642 |
description | Type-safe wrappers for Falco events |
homepage | https://falcosecurity.github.io/plugin-sdk-rs/falco_event/ |
repository | https://github.com/falcosecurity/plugin-sdk-rs |
max_upload_size | |
id | 1171686 |
Cargo.toml error: | TOML parse error at line 17, column 1 | 17 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
This crate provides support for working with Falco events.
The events may come in multiple forms:
Since the parsed events are strongly typed, we need type definitions for every field that exists
in the event schema. These types are available in [fields::types
] under names used by the C API.
See [fields::types
] for information about the specific types available.
Some fields in the event types are defined as PT_FLAGS
or PT_ENUMFLAGS
. These are available
in the Rust SDK as enums (PT_ENUMFLAGS
) or as structs generated by the bitflags
crate (PT_FLAGS
).
All these types live in the [fields::event_flags
] module.
Some event fields take different types, based on e.g. syscall parameters. These are encoded as
the PT_DYN
type in the Falco event table and are available as Rust enums in [fields::dynamic_params
].
To read an event from a &[u8]
to a [events::RawEvent
], use [events::RawEvent::from
].
It does some basic sanity checking on the slice, but does not validate e.g. that all event
parameters are present and the event is not truncated.
There also exists [events::RawEvent::from_ptr
], which is useful if all you have is a raw pointer,
but it's unsafe for two reasons:
This method creates a slice from the pointer (based on the discovered length) and passes it
to [events::RawEvent::from
].
There are two methods you can use to further refine the event type, depending on your use case.
If you are expecting an event of a particular type (or a handful of types), you can match
on [events::RawEvent::event_type
] and call [events::RawEvent::load
] with the appropriate
generic type, for example:
# use falco_event::events::RawEvent;
# let event = RawEvent {
# metadata: Default::default(),
# len: 0,
# event_type: 0,
# nparams: 0,
# payload: &[],
# };
use falco_event::events::types::EventType;
use falco_event::events::types;
use falco_event::num_traits::FromPrimitive;
match EventType::from_u16(event.event_type) {
Some(EventType::SYSCALL_OPENAT2_E) => {
let openat2_e_event = event.load::<types::PPME_SYSCALL_OPENAT2_E>()?;
// openat2_e_event is Event<types::PPME_SYSCALL_OPENAT2_E>
// ...
}
Some(EventType::SYSCALL_OPENAT2_X) => {
let openat2_x_event = event.load::<types::PPME_SYSCALL_OPENAT2_X>()?;
// openat2_x_event is Event<types::PPME_SYSCALL_OPENAT2_X>
// ...
}
_ => (),
}
# Result::<(), anyhow::Error>::Ok(())
Note: [events::RawEvent::load] validates the event type internally too, so you can also use an if-let chain:
# use falco_event::events::RawEvent;
# let event = RawEvent {
# metadata: Default::default(),
# len: 0,
# event_type: 0,
# nparams: 0,
# payload: &[],
# };
use falco_event::events::types::EventType;
use falco_event::events::types;
if let Ok(openat2_e_event) = event.load::<types::PPME_SYSCALL_OPENAT2_E>() {
// openat2_e_event is Event<types::PPME_SYSCALL_OPENAT2_E>
// ...
} else if let Ok(openat2_x_event) = event.load::<types::PPME_SYSCALL_OPENAT2_X>() {
// openat2_x_event is Event<types::PPME_SYSCALL_OPENAT2_X>
// ...
}
On the other hand, if you do not expect any particular event type, but still want to have it
as a strongly typed struct, you can use [events::RawEvent::load_any], which returns
an Event<AnyEvent>
, where [events::types::AnyEvent] is a large enum, encompassing all known event
types.
Please note that the available methods in this case are very limited. Realistically, you can only expect a [std::fmt::Debug] implementation, though this may change over time. You can still match each individual variant and access its fields, but note that explicit matching might be preferred: you do not pay the cost of building the type-safe representation of events you're not interested in.
There is a trait ([events::EventToBytes]) that writes a serialized form of an event to a writer
(i.e. a type that implements [std::io::Write], for example Vec<u8>
).
serde
]Once you enable the serde
feature of this crate, the following types gain serialization and deserialization
support:
PT_*
field types (many are Rust stdlib built-ins and support (de)serialization regardless)events::types
] events (see the module documentation for details regarding owned/borrowed types)Event<AnyEvent>
(but not other Event<T>
types, to avoid ambiguous serialization results and subsequent
deserialization issues)Note: you can serialize an event wrapping either the borrowed or
owned variant of AnyEvent
, but can only deserialize to the owned variant.