Skip to content

Commit

Permalink
new Container enum
Browse files Browse the repository at this point in the history
Signed-off-by: qjerome <qjerome@rawsec.lu>
  • Loading branch information
qjerome committed Jan 18, 2024
1 parent d24fc25 commit a26220e
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 44 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion kunai/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ aya = { git = "https://github.com/aya-rs/aya", branch = "main", features = [
gene = { git = "https://github.com/0xrawsec/gene-rs", branch = "main" }
event_derive = { git = "https://github.com/0xrawsec/gene-rs", branch = "main" }

kunai-common = { path = "../kunai-common", features = ["user"] }
kunai-macros = { path = "../kunai-common/src/kunai-macros" }

# part of tokio framework
bytes = "1"
futures = "0.3"

aya-log = { git = "https://github.com/aya-rs/aya", branch = "main" }
aya-obj = { git = "https://github.com/aya-rs/aya", branch = "main" }
kunai-common = { path = "../kunai-common", features = ["user"] }
anyhow = "1.0.68"
env_logger = "0.10"
log = "0.4"
Expand Down
45 changes: 5 additions & 40 deletions kunai/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use clap::Parser;
use env_logger::Builder;
use gene::rules::MAX_SEVERITY;
use gene::Engine;
use kunai::containers::Container;
use kunai::events::{
BpfProgLoadData, BpfProgTypeInfo, BpfSocketFilterData, CloneData, ConnectData, DnsQueryData,
ExecveData, ExitData, FileRenameData, FilterInfo, InitModuleData, KunaiEvent, MountData,
Expand All @@ -17,7 +18,6 @@ use kunai::{cache, util};
use kunai_common::bpf_events::{
self, event, mut_event, EncodedEvent, Event, PrctlOption, Type, MAX_BPF_EVENT_SIZE,
};
use kunai_common::cgroup::Cgroup;
use kunai_common::config::{BpfConfig, Filter};
use kunai_common::inspect_err;

Expand Down Expand Up @@ -67,7 +67,7 @@ struct CorrelationData {
image: PathBuf,
command_line: Vec<String>,
resolved: HashMap<IpAddr, String>,
container: Option<String>,
container: Option<Container>,
info: CorrInfo,
}

Expand Down Expand Up @@ -117,41 +117,6 @@ struct EventProcessor {
}

impl EventProcessor {
#[inline]
fn container_type_from_cgroup(cgrp: &Cgroup) -> Option<String> {
let s: Vec<String> = cgrp.to_vec();

if let Some(last) = s.last() {
if last.starts_with("docker-") {
return Some("docker".into());
}
}

if let Some(first) = s.get(1) {
if first.starts_with("lxc.payload.") {
return Some("lxc".into());
}
}

None
}

#[inline]
fn container_type_from_ancestors(ancestors: Vec<String>) -> Option<String> {
for a in ancestors {
match a.as_str() {
"/usr/bin/firejail" => return Some("firejail".into()),
"/usr/bin/containerd-shim-runc-v2" => return Some("docker".into()),
_ => {}
};

if a.starts_with("/snap/lxd/") && a.ends_with("/bin/lxd/") {
return Some("lxc".into());
}
}
None
}

pub fn init(config: Config, receiver: Receiver<EncodedEvent>) -> anyhow::Result<()> {
let output = match &config.output.as_str() {
&"stdout" => String::from("/dev/stdout"),
Expand Down Expand Up @@ -826,11 +791,11 @@ impl EventProcessor {

let cgroup = event.data.cgroup;

let mut container_type = Self::container_type_from_cgroup(&cgroup);
let mut container_type = Container::from_cgroup(&cgroup);

if container_type.is_none() {
let ancestors = self.get_ancestors(&info);
container_type = Self::container_type_from_ancestors(ancestors);
container_type = Container::from_ancestors(ancestors);
}

// we insert only if not existing
Expand Down Expand Up @@ -866,7 +831,7 @@ impl EventProcessor {
if mnt_ns != self.system_info.mount_ns {
container = Some(kunai::info::ContainerInfo {
name: self.cache.get_hostname(mnt_ns).unwrap_or("?".into()),
ty: cd.and_then(|cd| cd.container.clone()),
ty: cd.and_then(|cd| cd.container),
});
}

Expand Down
120 changes: 120 additions & 0 deletions kunai/src/containers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use core::str::FromStr;
use gene::FieldGetter;
use kunai_common::cgroup::Cgroup;
use kunai_macros::StrEnum;
use serde::{Deserialize, Serialize};

#[derive(StrEnum, Debug, PartialEq, Clone, Copy)]
pub enum Container {
#[str("lxc")]
Lxc,
#[str("docker")]
Docker,
#[str("firejail")]
Firejail,
}

impl Serialize for Container {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}

impl<'de> Deserialize<'de> for Container {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
// Deserialization logic goes here
struct ContainerVisitor;
const VARIANTS: &'static [&'static str] = &Container::variants_str();

impl<'de> serde::de::Visitor<'de> for ContainerVisitor {
type Value = Container;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a valid representation of Container enum")
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Container::from_str(value)
.map_err(|_| serde::de::Error::unknown_variant(value, VARIANTS))
}
}

deserializer.deserialize_str(ContainerVisitor)
}
}

impl FieldGetter for Container {
fn get_from_iter(
&self,
i: core::slice::Iter<'_, std::string::String>,
) -> Option<gene::FieldValue> {
if i.len() > 0 {
return None;
}
return Some(self.as_str().into());
}
}

impl Container {
#[inline]
pub fn from_cgroup(cgrp: &Cgroup) -> Option<Container> {
let s: Vec<String> = cgrp.to_vec();

if let Some(last) = s.last() {
if last.starts_with("docker-") {
return Some(Container::Docker);
}
}

if let Some(first) = s.get(1) {
if first.starts_with("lxc.payload.") {
return Some(Container::Lxc);
}
}

None
}

#[inline]
pub fn from_ancestors(ancestors: Vec<String>) -> Option<Container> {
for a in ancestors {
match a.as_str() {
"/usr/bin/firejail" => return Some(Container::Firejail),
"/usr/bin/containerd-shim-runc-v2" => return Some(Container::Docker),
_ => {}
};

if a.starts_with("/snap/lxd/") && a.ends_with("/bin/lxd/") {
return Some(Container::Lxc);
}
}
None
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_serde() {
let c = Container::Docker;

let ser = serde_json::to_string(&c).unwrap();
assert_eq!(ser, r#""docker""#);
let de: Container = serde_json::from_str(&ser).unwrap();
assert_eq!(de, Container::Docker);

// this is an unknown variant so we should get an error
assert!(serde_json::from_str::<'_, Container>(r#""lxk""#).is_err());
}
}
3 changes: 2 additions & 1 deletion kunai/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};

use crate::{
cache::Hashes,
containers::Container,
info::{ContainerInfo, StdEventInfo},
};

#[derive(FieldGetter, Serialize, Deserialize)]
pub struct ContainerSection {
pub name: String,
#[serde(rename = "type")]
pub ty: Option<String>,
pub ty: Option<Container>,
}

impl From<ContainerInfo> for ContainerSection {
Expand Down
4 changes: 2 additions & 2 deletions kunai/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use kunai_common::{
uuid::TaskUuid,
};

use crate::util::get_clk_tck;
use crate::{containers::Container, util::get_clk_tck};

#[derive(Debug, Clone, Copy)]
pub struct ProcFsTaskInfo {
Expand Down Expand Up @@ -95,7 +95,7 @@ pub struct HostInfo {
#[derive(Default, Debug, Clone)]
pub struct ContainerInfo {
pub name: String,
pub ty: Option<String>,
pub ty: Option<Container>,
}

#[derive(Default, Debug, Clone)]
Expand Down
1 change: 1 addition & 0 deletions kunai/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use compat::{KernelVersion, Programs};
pub mod cache;
pub mod compat;
pub mod config;
pub mod containers;
pub mod events;
pub mod info;
pub mod ioc;
Expand Down

0 comments on commit a26220e

Please sign in to comment.