falco_plugin/plugin/source/mod.rs
1use crate::plugin::base::Plugin;
2use crate::plugin::source::wrappers::SourcePluginExported;
3use crate::source::{EventBatch, EventInput};
4use falco_event::events::types::PPME_PLUGINEVENT_E as PluginEvent;
5use falco_event::events::Event;
6use falco_event::events::EventMetadata;
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 events of type [`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 events of type [`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 /// # List sample open parameters
52 ///
53 /// Return a list of suggested open parameters supported by this plugin.
54 /// Any of the values in the returned list are valid parameters for open().
55 ///
56 /// The default implementation returns an empty string, but you can use
57 /// [`crate::source::serialize_open_params`] and [`crate::source::OpenParam`] to build
58 /// a description of what the [`SourcePlugin::open`] method expects.
59 ///
60 /// **Note**: as of API version 3.4.0, this appears unused.
61 fn list_open_params(&mut self) -> Result<&CStr, anyhow::Error> {
62 Ok(c"")
63 }
64
65 /// # Open a capture instance
66 ///
67 /// This method receives the `open` parameter from Falco configuration and returns
68 /// a new instance of the source plugin.
69 fn open(&mut self, params: Option<&str>) -> Result<Self::Instance, anyhow::Error>;
70
71 /// # Close a capture instance
72 ///
73 /// The default implementation does nothing, leaving all cleanup to the instance type's
74 /// [`Drop`] implementation, if any.
75 fn close(&mut self, _instance: &mut Self::Instance) {}
76
77 /// # Render an event to string
78 ///
79 /// This string will be available as `%evt.plugininfo` in Falco rules. You may consider
80 /// using the helpers from [`crate::strings`] to build the resulting CString.
81 fn event_to_string(&mut self, event: &EventInput) -> Result<CString, anyhow::Error>;
82}
83
84/// Information about capture progress
85#[derive(Debug)]
86pub struct ProgressInfo<'a> {
87 /// Progress percentage (0.0-100.0)
88 pub value: f64,
89 /// Optional detailed message about the progress
90 pub detail: Option<&'a CStr>,
91}
92
93pub(crate) struct SourcePluginInstanceWrapper<I: SourcePluginInstance> {
94 pub(crate) instance: I,
95 pub(crate) batch: bumpalo::Bump,
96}
97
98/// # An open instance of a source plugin
99pub trait SourcePluginInstance {
100 /// # The [`SourcePlugin`] this instance belongs to.
101 ///
102 /// Source plugin and instance types must correspond 1:1 to each other.
103 type Plugin: SourcePlugin<Instance = Self>;
104
105 /// # Fill the next batch of events
106 ///
107 /// This is the most important method for the source plugin implementation. It is responsible
108 /// for actually generating the events for the main event loop.
109 ///
110 /// For performance, events are returned in batches. Of course, it's entirely valid to have
111 /// just a single event in a batch.
112 ///
113 /// ## Returning one or more events
114 ///
115 /// For each event that is ready, pass it to `batch.add()` to add it to the current batch
116 /// to be returned.
117 ///
118 /// ```ignore
119 /// fn next_batch(
120 /// &mut self,
121 /// plugin: &mut Self::Plugin,
122 /// batch: &mut EventBatch,
123 /// ) -> Result<(), anyhow::Error> {
124 /// let mut event = Vec::new();
125 /// // ...
126 /// let event = Self::plugin_event(&event);
127 /// batch.add(event)?;
128 /// Ok(())
129 /// }
130 /// ```
131 ///
132 /// ## Returning no events, temporarily
133 ///
134 /// If there are no events to return at the moment but there might be later, you should
135 /// return [`FailureReason::Timeout`](`crate::FailureReason::Timeout`) as the error. The plugin framework will retry the call
136 /// to `next_batch` later.
137 ///
138 /// ```ignore
139 /// fn next_batch(
140 /// &mut self,
141 /// plugin: &mut Self::Plugin,
142 /// batch: &mut EventBatch,
143 /// ) -> Result<(), anyhow::Error> {
144 /// std::thread::sleep(Duration::from_millis(100));
145 /// Err(anyhow::anyhow!("no events right now").context(FailureReason::Timeout))
146 /// }
147 /// ```
148 ///
149 /// ## Returning no events, permanently
150 ///
151 /// If there will be no more events coming from this instance, you should return\
152 /// [`FailureReason::Eof`](`crate::FailureReason::Eof`) as the error. The plugin framework will end the capture and shut down
153 /// gracefully.
154 ///
155 /// ```ignore
156 /// fn next_batch(
157 /// &mut self,
158 /// plugin: &mut Self::Plugin,
159 /// batch: &mut EventBatch,
160 /// ) -> Result<(), anyhow::Error> {
161 /// Err(anyhow::anyhow!("no more events").context(FailureReason::Eof))
162 /// }
163 /// ```
164 ///
165 /// ## Timing considerations
166 ///
167 /// This method is effectively called in a loop by Falco and there's a delicate balance of
168 /// how much time to spend here waiting for events. On the one hand, you don't want to poll
169 /// in a tight loop, since that leads to excessive CPU usage. On the other hand, you don't
170 /// want to sleep forever waiting for an event, since it may block other tasks running in the
171 /// main event loop thread. As a rule of thumb, waiting up to 10-100 milliseconds for an event
172 /// works fine.
173 fn next_batch(
174 &mut self,
175 plugin: &mut Self::Plugin,
176 batch: &mut EventBatch,
177 ) -> Result<(), anyhow::Error>;
178
179 /// # Get progress information
180 ///
181 /// If your plugin reads from a source that has a well-defined end (like a file),
182 /// you can use this method to report progress information.
183 ///
184 /// It consists of a percentage (0.0-100.0) and an optional description containing more
185 /// details about the progress (e.g. bytes read/bytes total).
186 fn get_progress(&mut self) -> ProgressInfo {
187 ProgressInfo {
188 value: 0.0,
189 detail: None,
190 }
191 }
192
193 /// # A helper for generating plugin events
194 ///
195 /// If your plugin defines a PLUGIN_ID and a source name, the only allowed events are
196 /// of type [`PluginEvent`] and effectively the only customizable field is the event data
197 /// (which is a generic byte buffer).
198 ///
199 /// This method makes it easy to generate such events: just pass it the event data and get
200 /// the complete event, with all the metadata set to reasonable defaults.
201 fn plugin_event(data: &[u8]) -> Event<PluginEvent> {
202 let event = PluginEvent {
203 plugin_id: Some(Self::Plugin::PLUGIN_ID),
204 event_data: Some(data),
205 };
206
207 let metadata = EventMetadata::default();
208
209 Event {
210 metadata,
211 params: event,
212 }
213 }
214}