falco_plugin/plugin/source/
mod.rs

1use crate::event::PluginEvent;
2use crate::plugin::base::Plugin;
3use crate::plugin::source::wrappers::SourcePluginExported;
4use crate::source::{EventBatch, EventInput};
5use falco_event::events::{AnyEventPayload, EventMetadata};
6use falco_event::events::{Event, RawEvent};
7use std::ffi::{CStr, CString};
8
9pub mod event_batch;
10pub mod open_params;
11#[doc(hidden)]
12pub mod wrappers;
13
14/// Support for event sourcing plugins
15pub trait SourcePlugin: Plugin + SourcePluginExported {
16    /// # Instance type
17    ///
18    /// Each source plugin defines an instance type. The instance is the object responsible
19    /// for actual generation of events. The plugin type mostly serves as a way to create
20    /// and destroy instances.
21    ///
22    /// **Note**: while there may be multiple instances for a particular plugin, there will be
23    /// at most one at any given time.
24    type Instance: SourcePluginInstance<Plugin = Self>;
25
26    /// # Event source name
27    ///
28    /// This string describes the event source. One notable event source name is `syscall`,
29    /// for plugins collecting syscall information.
30    ///
31    /// If the plugin defines both `EVENT_SOURCE` (as a non-empty string) and `PLUGIN_ID`
32    /// (as a non-zero value), it will only be allowed to emit plugin events (e.g. [`crate::event::PluginEvent`])
33    /// with the `plugin_id` field matching `PLUGIN_ID` in the definition of this trait.
34    ///
35    /// This constant must be a non-empty string if `PLUGIN_ID` is set.
36    const EVENT_SOURCE: &'static CStr;
37
38    /// # Plugin ID
39    ///
40    /// This is the unique ID of the plugin.
41    ///
42    /// If the plugin defines both `EVENT_SOURCE` (as a non-empty string) and `PLUGIN_ID`
43    /// (as a non-zero value), it will only be allowed to emit plugin events (e.g. [`crate::event::PluginEvent`])
44    /// with the `plugin_id` field matching `PLUGIN_ID` in the definition of this trait.
45    ///
46    /// > EVERY PLUGIN WITH EVENT SOURCING CAPABILITY IMPLEMENTING A SPECIFIC EVENT SOURCE MUST
47    /// > OBTAIN AN OFFICIAL ID FROM THE FALCOSECURITY ORGANIZATION, OTHERWISE IT WON'T PROPERLY
48    /// > COEXIST WITH OTHER PLUGINS.
49    const PLUGIN_ID: u32;
50
51    /// # Event type handled by this plugin
52    ///
53    /// The SDK does not enforce limits on the events generated, but you can make your life
54    /// a bit easier in `event_to_string` by specifying the event type your plugin generates here.
55    /// Events will be parsed into this type before being passed to the plugin, so you can
56    /// work directly on the deserialized form and don't need to worry about validating
57    /// the events.
58    ///
59    /// If an event fails this conversion, an error will be returned from the SDK and your
60    /// string formatting code won't be called.
61    ///
62    /// If you don't want any specific validation/conversion to be performed, specify the type as
63    /// ```
64    /// type Event<'a> = falco_event::events::RawEvent<'a>;
65    /// ```
66    type Event<'a>: AnyEventPayload + TryFrom<&'a RawEvent<'a>>
67    where
68        Self: 'a;
69
70    /// # List sample open parameters
71    ///
72    /// Return a list of suggested open parameters supported by this plugin.
73    /// Any of the values in the returned list are valid parameters for open().
74    ///
75    /// The default implementation returns an empty string, but you can use
76    /// [`crate::source::serialize_open_params`] and [`crate::source::OpenParam`] to build
77    /// a description of what the [`SourcePlugin::open`] method expects.
78    ///
79    /// **Note**: as of API version 3.4.0, this appears unused.
80    fn list_open_params(&mut self) -> Result<&CStr, anyhow::Error> {
81        Ok(c"")
82    }
83
84    /// # Open a capture instance
85    ///
86    /// This method receives the `open` parameter from Falco configuration and returns
87    /// a new instance of the source plugin.
88    fn open(&mut self, params: Option<&str>) -> Result<Self::Instance, anyhow::Error>;
89
90    /// # Close a capture instance
91    ///
92    /// The default implementation does nothing, leaving all cleanup to the instance type's
93    /// [`Drop`] implementation, if any.
94    fn close(&mut self, _instance: &mut Self::Instance) {}
95
96    /// # Render an event to string
97    ///
98    /// This string will be available as `%evt.plugininfo` in Falco rules. You may consider
99    /// using the helpers from [`crate::strings`] to build the resulting CString.
100    fn event_to_string(
101        &mut self,
102        event: &EventInput<Self::Event<'_>>,
103    ) -> Result<CString, anyhow::Error>;
104}
105
106/// Information about capture progress
107#[derive(Debug)]
108pub struct ProgressInfo<'a> {
109    /// Progress percentage (0.0-100.0)
110    pub value: f64,
111    /// Optional detailed message about the progress
112    pub detail: Option<&'a CStr>,
113}
114
115pub(crate) struct SourcePluginInstanceWrapper<I: SourcePluginInstance> {
116    pub(crate) instance: I,
117    pub(crate) batch: bumpalo::Bump,
118}
119
120/// # An open instance of a source plugin
121pub trait SourcePluginInstance {
122    /// # The [`SourcePlugin`] this instance belongs to.
123    ///
124    /// Source plugin and instance types must correspond 1:1 to each other.
125    type Plugin: SourcePlugin<Instance = Self>;
126
127    /// # Fill the next batch of events
128    ///
129    /// This is the most important method for the source plugin implementation. It is responsible
130    /// for actually generating the events for the main event loop.
131    ///
132    /// For performance, events are returned in batches. Of course, it's entirely valid to have
133    /// just a single event in a batch.
134    ///
135    /// ## Returning one or more events
136    ///
137    /// For each event that is ready, pass it to `batch.add()` to add it to the current batch
138    /// to be returned.
139    ///
140    /// ```ignore
141    /// fn next_batch(
142    ///     &mut self,
143    ///     plugin: &mut Self::Plugin,
144    ///     batch: &mut EventBatch,
145    /// ) -> Result<(), anyhow::Error> {
146    ///     let mut event = Vec::new();
147    ///     // ...
148    ///     let event = Self::plugin_event(&event);
149    ///     batch.add(event)?;
150    ///     Ok(())
151    /// }
152    /// ```
153    ///
154    /// ## Returning no events, temporarily
155    ///
156    /// If there are no events to return at the moment but there might be later, you should
157    /// return [`FailureReason::Timeout`](`crate::FailureReason::Timeout`) as the error. The plugin framework will retry the call
158    /// to `next_batch` later.
159    ///
160    /// ```ignore
161    /// fn next_batch(
162    ///     &mut self,
163    ///     plugin: &mut Self::Plugin,
164    ///     batch: &mut EventBatch,
165    /// ) -> Result<(), anyhow::Error> {
166    ///     std::thread::sleep(Duration::from_millis(100));
167    ///     Err(anyhow::anyhow!("no events right now").context(FailureReason::Timeout))
168    /// }
169    /// ```
170    ///
171    /// ## Returning no events, permanently
172    ///
173    /// If there will be no more events coming from this instance, you should return\
174    /// [`FailureReason::Eof`](`crate::FailureReason::Eof`) as the error. The plugin framework will end the capture and shut down
175    /// gracefully.
176    ///
177    /// ```ignore
178    /// fn next_batch(
179    ///     &mut self,
180    ///     plugin: &mut Self::Plugin,
181    ///     batch: &mut EventBatch,
182    /// ) -> Result<(), anyhow::Error> {
183    ///     Err(anyhow::anyhow!("no more events").context(FailureReason::Eof))
184    /// }
185    /// ```
186    ///
187    /// ## Timing considerations
188    ///
189    /// This method is effectively called in a loop by Falco and there's a delicate balance of
190    /// how much time to spend here waiting for events. On the one hand, you don't want to poll
191    /// in a tight loop, since that leads to excessive CPU usage. On the other hand, you don't
192    /// want to sleep forever waiting for an event, since it may block other tasks running in the
193    /// main event loop thread. As a rule of thumb, waiting up to 10-100 milliseconds for an event
194    /// works fine.
195    fn next_batch(
196        &mut self,
197        plugin: &mut Self::Plugin,
198        batch: &mut EventBatch,
199    ) -> Result<(), anyhow::Error>;
200
201    /// # Get progress information
202    ///
203    /// If your plugin reads from a source that has a well-defined end (like a file),
204    /// you can use this method to report progress information.
205    ///
206    /// It consists of a percentage (0.0-100.0) and an optional description containing more
207    /// details about the progress (e.g. bytes read/bytes total).
208    fn get_progress(&mut self) -> ProgressInfo<'_> {
209        ProgressInfo {
210            value: 0.0,
211            detail: None,
212        }
213    }
214
215    /// # A helper for generating plugin events
216    ///
217    /// If your plugin defines a PLUGIN_ID and a source name, the only allowed events are
218    /// plugin events (e.g. [`crate::event::PluginEvent`]), and effectively the only customizable
219    /// field is the event data (which is a generic byte buffer).
220    ///
221    /// This method makes it easy to generate such events: just pass it the event data and get
222    /// the complete event, with all the metadata set to reasonable defaults.
223    fn plugin_event(data: &[u8]) -> Event<PluginEvent<&[u8]>> {
224        let event = PluginEvent {
225            plugin_id: Self::Plugin::PLUGIN_ID,
226            event_data: data,
227        };
228
229        let metadata = EventMetadata::default();
230
231        Event {
232            metadata,
233            params: event,
234        }
235    }
236}