Skip to content

How to create a plugin

This page will guide you through the process of creating a plugin.

Programming Language

A plugin can be created in virtually any language (C/C++, Rust, Python, Go and many other languages) as plugins are built using WebAssembly (wasm).

Interfaces

A plugin, regardless of the langage of implementation, needs to expose the following interfaces:

InterfaceWhat it does
create(config, name, params) -> result<string, string>Create a detection on the remote system
read(config, name, params) -> result<string, string>Get/Read a detection from the remote system
update(config, name, params) -> result<string, string>Update a detection on the remote system
delete(config, name, params) -> result<string, string>Remove a detection from the remote system
load() -> metadataLoad the plugin and return its metadata
settings() -> stringReturns the expected configuration/ KCL ?
schema() -> stringReturn the schema ?
ping(config) -> result<bool: string>Open a connection to the remote system
Details

Plugin interfaces are defined in the Plugin Wasm Interface Type (WIT). Always refer to this file to ensure your interfaces return the appropriate data types.

Python plugin

This section will guide you through the creation of a python plugin. We'll target Splunk for demonstration purpose but note that we have an official Splunk plugin written in Rust.

Python Global Interpreter (GIL)

As a python developper, your probably know that python is a slow language and that's mainly a consequence of the Python Global Interpreter (GIL). Guess what? Compiling your python code in WebAssembly will actually make it fly!

Package manager

In this guide, we'll use Poetry to manage python packages but feel free to use your prefered package manager, pip, conda or anything else.

First things first, we create our new python app

bash
poetry new pysplunk

Dependencies

Then, we need to install componentize-py, a tool to convert a Python application to a WebAssembly component.

bash
cd pysplunk
poetry add componentize-py

WIT

Next, we copy the wit files from logcraft-cli into our python app. These files are basically defining the contracts between the cli and the plugin.

bash
~$ cd pysplunk
~$ cp -r ~/logcraft-cli/wit pysplunk/wit
~$ ls -1 pysplunk/wit
world.wit
plugin.wit
~$

Bindings

The step is optional as it only creates python bindings in the working directory to integrate with your IDE. When we'll build the application, these bindings will also be generated automatically.

bash
poetry run componentize-py --wit-path pysplunk/wit --world plugins bindings pysplunk

This will result in a new directory plugins that contains the bindings in pysplunk.

App

Then, we'll create a main.py that will hold the main code for our plugin where we'll implement the interfaces expected by the WIT files.

python
#!/usr/bin/env python3
from plugins import Plugins
from plugins.exports.plugin import Metadata
from plugins.types import Err, Ok, Some, Result


class Plugin(Plugins):
    def load(self) -> Metadata:
        return Metadata("my-plugin", "0.1.0", "The Batman", "This is a famous plugin")

    def settings(self):
        pass

    def schema(self):
        pass

    def create(self, config: str, name: str, params: str):
        pass

    def read(self, config: str, name: str, params: str):
        pass

    def update(self, config: str, name: str, params: str):
        pass

    def delete(self, config: str, name: str, params: str):
        pass

    def ping(self, config: str) -> int:
        pass

The class name is important as it is derivated from the WIT files, hence your plugin must start with:

python
class Plugin(Plugins):

Naming Convention (kebab-case)

Regarding the load() function, make sure that the name given to your plugin respect kebab-case (i.e. all lowercase, alphanumerical and hyphens between words), here my-plugin, as this will end up in your lgc.yaml file!

Finally, compile the plugin:

bash
poetry run componentize-py --wit-path pysplunk/wit --world plugins componentize -p pysplunk main -o my-plugin.wasm

Congratulations, your plugin can now be installed in LogCraft CLI:

bash
lgc plugins install my-plugin.wasm