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}