<aside> 💡 The code for this project can be found here https://github.com/SubconsciousCompute/tetragon-grpc-client
</aside>
Tetragon is a powerful tool that offers eBPF-based Security Observability and Runtime Enforcement, providing real-time security event detection and reaction capabilities, especially in Kubernetes environments.
Tetragon has a gRPC API and we’re interested in the getevents function. This function returns a stream which will send system process events. We’ll begin by setting up Tetragon and reading this stream through the tetra cli application:

Download the Tetragon package
Extract the tarball and run the install.sh script
Check its status:
sudo systemctl status tetragon
Run the tetra cli to check if you’re getting events
sudo tetra --server-address unix:///var/run/tetragon/tetragon.sock getevents
You should get some JSON output
The API will be running on a Unix Domain Socket /var/run/tetragon/tetragon.sock. Our gRPC client will connect to this socket & get the events.
First we’ll need to get the proto files used for the Tetragon API. Luckily it’s mentioned in the documentation. We’ll add it as a submodule to our repository & symlink the relevant folder to a proto directory.
cargo new tetragon-grpc-client
cd tetragon-grpc-client
git submodule add <https://github.com/cilium/tetragon.git> tetragon/
ln -s ./tetragon/api/v1/ proto
Then our dependencies:
cargo add tonic prost prost-types
and dev dependencies. You may also need protoc (a proto compiler) if it is not installed.
# sudo apt install -y protobuf-compiler
cargo add --dev tonic-build
We’ll create a bulid.rs file to compile our proto files, but before we do that, make sure to install the the protoc Protocol Buffers compiler. The tonic examples readme might be of some help on setting this up. Once we have that create the build.rs at the root of your directory:
fn main() -> Result<(), Box<dyn std::error::Error>> {
match tonic_build::configure().build_server(false).compile(
&[
"proto/tetragon/capabilities.proto",
"proto/tetragon/tetragon.proto",
"proto/tetragon/stack.proto",
"proto/tetragon/events.proto",
"proto/tetragon/sensors.proto",
],
&["proto"],
) {
Ok(_) => Ok(()),
Err(e) => {
// NOTE: print errors in a readable format
eprintln!("{}", e);
Err("Failed".into())
}
}
}
In build.rs file, we use tonic-build to compile the proto files and generate Rust code we can include in our program. Additionally we extract the error to print it with new lines.
Then in our main.rs we can add the following:
pub mod tetragon {
// NOTE: Since this is generated by tonic theres nothing else we can do.
#![allow(clippy::large_enum_variant)]
tonic::include_proto!("tetragon");
}
You’ll want to allow some clippy warnings as the generated code cannot be changed from our side. The include_proto! macro gives us access to the generated rust code inside our program. We can just import the types and create a program like so: