falco_event_schema

Crates.iofalco_event_schema
lib.rsfalco_event_schema
version0.5.0
created_at2025-09-24 10:40:21.914132+00
updated_at2025-09-24 10:40:21.914132+00
descriptionSchema definitions for Falco events
homepagehttps://falcosecurity.github.io/plugin-sdk-rs/falco_event_schema/
repositoryhttps://github.com/falcosecurity/plugin-sdk-rs
max_upload_size
id1852905
size645,619
Grzegorz Nosek (gnosek)

documentation

README

Falco event schema

This crate provides a strongly typed representation of the Falco event schema, allowing you to load and work with Falco events in a type-safe manner.

Autogenerated event types

The [events] module contains the strongly typed event types, which are generated from the Falco event schema, one for each event type. It also provides a generic enum, [events::AnyEvent], which encompasses all known event types.

Field types

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.

Autogenerated enums and bitflags

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.

Autogenerated dynamic value types

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].

Cnverting raw events to typed events

There are several 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, the easiest way is to call [falco_event::events::RawEvent::load] with the appropriate generic type, for example:

# fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# use falco_event::events::RawEvent;
# let event = RawEvent {
#    metadata: Default::default(),
#    len: 0,
#    event_type: 0,
#    nparams: 0,
#    payload: &[],
# };
use falco_event_schema::events;
use falco_event::events::EventPayload;

let openat2_e_event = event.load::<events::PPME_SYSCALL_OPENAT2_E>()?;
// openat2_e_event is Event<events::PPME_SYSCALL_OPENAT2_E>
// ...

# Ok(())
# }

For parsing an event that belongs to one of several types, it might be best to create a custom enum, describing those particular types, for example:

# fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# use falco_event::events::RawEvent;
# let event = RawEvent {
#    metadata: Default::default(),
#    len: 0,
#    event_type: 0,
#    nparams: 0,
#    payload: &[],
# };
use falco_event_schema::events;

#[derive(falco_event::AnyEvent)]
enum OpenAt2Event<'a> {
  OpenAt2Enter(events::PPME_SYSCALL_OPENAT2_E<'a>),
  OpenAt2Exit(events::PPME_SYSCALL_OPENAT2_X<'a>),
}

let openat2_event = event.load::<OpenAt2Event>()?;
// openat2_event is Event<OpenAt2Event>
// ...

# Ok(())
# }

This is mostly equivalent to a match you can write by hand:

# fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# use falco_event::events::RawEvent;
# let event = RawEvent {
#    metadata: Default::default(),
#    len: 0,
#    event_type: 0,
#    nparams: 0,
#    payload: &[],
# };
use falco_event_schema::events;
use falco_event::events::EventPayload;

match event.event_type {
    events::PPME_SYSCALL_OPENAT2_E::ID => {
        let openat2_e_event = event.load::<events::PPME_SYSCALL_OPENAT2_E>()?;
        // openat2_e_event is Event<events::PPME_SYSCALL_OPENAT2_E>
        // ...
    }
    events::PPME_SYSCALL_OPENAT2_X::ID => {
        let openat2_x_event = event.load::<events::PPME_SYSCALL_OPENAT2_X>()?;
        // openat2_x_event is Event<events::PPME_SYSCALL_OPENAT2_X>
        // ...
    }
    _ => (),
}

# Ok(())
# }

Note: [falco_event::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_schema::events;

if let Ok(openat2_e_event) = event.load::<events::PPME_SYSCALL_OPENAT2_E>() {
    // openat2_e_event is Event<events::PPME_SYSCALL_OPENAT2_E>
    // ...
} else if let Ok(openat2_x_event) = event.load::<events::PPME_SYSCALL_OPENAT2_X>() {
    // openat2_x_event is Event<events::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 call load::<AnyEvent>(), where [events::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 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.

Commit count: 560

cargo fmt