Skip to content

Commit

Permalink
fix(src,cmake,go-worker): multiple fixes.
Browse files Browse the repository at this point in the history
First of all, podman had a runtime dep on `gpgme` (`libgpgme-dev`).
Install it through vcpkg (as static) to avoid linking issues for the library consumer.

Second, in go-worker Container struct, omit empty structured fields (slices, maps...),
to avoid wasting memory space (plus all the back and forth copies).

Finally, fixed some bugs all around the C++ implementation.

Signed-off-by: Federico Di Pierro <[email protected]>
  • Loading branch information
FedeDP committed Dec 3, 2024
1 parent 5d0176e commit 178eb89
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 113 deletions.
13 changes: 9 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ jobs:
fetch-depth: 0
submodules: 'recursive'

# Needed by containerd go package
- name: Install deps
run:
sudo apt-get install -y --no-install-recommends libbtrfs-dev libgpgme-dev
# Needed by containerd go package - build time dep, no runtime.
- name: Install plugin deps
run: sudo apt-get install -y --no-install-recommends libbtrfs-dev

- name: Setup Go
uses: actions/setup-go@v5
Expand All @@ -44,6 +43,12 @@ jobs:
env:
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"

# Needed by podman package - build and runtime dep.
# For the go-worker library, it is only a runtime dep,
# and is provided by plugin vcpkg configuration.
- name: Install go-worker executable deps
run: sudo apt-get install -y --no-install-recommends libgpgme-dev

- name: Build go-worker executable
run: make -C go-worker exe

Expand Down
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ include(plugin-sdk-cpp)
# vcpkg dependencies
find_package(re2 REQUIRED)
find_package(spdlog CONFIG REQUIRED)
## gpgme is vcpkg installed but comes with pkg-config
## It is a runtime dep of podman go package.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GPGME REQUIRED gpgme IMPORTED_TARGET)

file(GLOB_RECURSE SOURCES src/*.cpp)

Expand All @@ -47,4 +51,4 @@ target_compile_features(container PUBLIC cxx_std_17)
target_include_directories(container PRIVATE ${PLUGIN_SDK_INCLUDE} ${PLUGIN_SDK_DEPS_INCLUDE} ${WORKER_INCLUDE})

# project linked libraries
target_link_libraries(container PRIVATE spdlog::spdlog_header_only re2::re2 ${WORKER_LIB})
target_link_libraries(container PRIVATE spdlog::spdlog_header_only re2::re2 PkgConfig::GPGME ${WORKER_LIB})
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ OUTPUT := lib$(NAME).so

all: $(OUTPUT)

.PHONY: clean
clean:
rm -rf build $(OUTPUT)
make -C go-worker/ clean

# This Makefile requires CMake installed on the system
.PHONY: $(OUTPUT)
$(OUTPUT):
cmake -B build -S . && make -C build/ container -j6 && cp build/$(OUTPUT) $(OUTPUT)

Expand Down
10 changes: 5 additions & 5 deletions go-worker/pkg/container/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,21 +200,21 @@ type Container struct {
CPUShares int64 `json:"cpu_shares"`
CPUSetCPUCount int64 `json:"cpuset_cpu_count"`
CreatedTime int64 `json:"created_time"`
Env []string `json:"env"`
Env []string `json:"env,omitempty"`
FullID string `json:"full_id"`
HostIPC bool `json:"host_ipc"`
HostNetwork bool `json:"host_network"`
HostPID bool `json:"host_pid"`
Ip string `json:"ip"`
IsPodSandbox bool `json:"is_pod_sandbox"`
Labels map[string]string `json:"labels"`
Labels map[string]string `json:"labels,omitempty"`
MemoryLimit int64 `json:"memory_limit"`
SwapLimit int64 `json:"swap_limit"`
PodSandboxID string `json:"pod_sandbox_id"` // cri only
Privileged bool `json:"privileged"`
PodSandboxLabels map[string]string `json:"pod_sandbox_labels"` // cri only
PortMappings []portMapping `json:"port_mappings"`
Mounts []mount `json:"Mounts"`
PodSandboxLabels map[string]string `json:"pod_sandbox_labels,omitempty"` // cri only
PortMappings []portMapping `json:"port_mappings,omitempty"`
Mounts []mount `json:"Mounts,omitempty"`
HealthcheckProbe *probe `json:"Healthcheck,omitempty"`
LivenessProbe *probe `json:"LivenessProbe,omitempty"`
ReadinessProbe *probe `json:"ReadinessProbe,omitempty"`
Expand Down
65 changes: 34 additions & 31 deletions src/container_info_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,46 +70,49 @@ void from_json(const nlohmann::json& j, container_port_mapping& port) {
}

void from_json(const nlohmann::json& j, std::shared_ptr<container_info>& cinfo) {
std::shared_ptr<container_info> info = std::make_shared<container_info>();
const nlohmann::json& container = j["container"];
cinfo->m_type = container.value("type", CT_UNKNOWN);
cinfo->m_id = container.value("id", "");
cinfo->m_name = container.value("name", "");
cinfo->m_image = container.value("image", "");
cinfo->m_imagedigest = container.value("imagedigest", "");
cinfo->m_imageid = container.value("imageid", "");
cinfo->m_imagerepo = container.value("imagerepo", "");
cinfo->m_imagetag = container.value("imagetag", "");
cinfo->m_container_user = container.value("User", "");
cinfo->m_pod_sandbox_cniresult = container.value("cni_json", "");
cinfo->m_cpu_period = container.value("cpu_period", 0);
cinfo->m_cpu_quota = container.value("cpu_quota", 0);
cinfo->m_cpu_shares = container.value("cpu_shares", 0);
cinfo->m_cpuset_cpu_count = container.value("cpuset_cpu_count", 0);
cinfo->m_created_time = container.value("created_time", 0);
cinfo->m_env = container.value("env", std::vector<std::string>{});
cinfo->m_full_id = container.value("full_id", "");
cinfo->m_host_ipc = container.value("host_ipc", false);
cinfo->m_host_network = container.value("host_network", false);
cinfo->m_host_pid = container.value("host_pid", false);
cinfo->m_container_ip = container.value("ip", 0);
cinfo->m_is_pod_sandbox = container.value("is_pod_sandbox", false);
cinfo->m_labels = container.value("labels", std::map<std::string, std::string>{});
cinfo->m_memory_limit = container.value("memory_limit", 0);
cinfo->m_swap_limit = container.value("swap_limit", 0);
cinfo->m_pod_sandbox_id = container.value("pod_sandbox_id", "");
cinfo->m_privileged = container.value("privileged", false);
cinfo->m_pod_sandbox_labels = container.value("pod_sandbox_labels", std::map<std::string, std::string>{});
cinfo->m_port_mappings = container.value("port_mappings", std::vector<container_port_mapping>{});
cinfo->m_mounts = container.value("Mounts", std::vector<container_mount_info>{});
info->m_type = container.value("type", CT_UNKNOWN);
info->m_id = container.value("id", "");
info->m_name = container.value("name", "");
info->m_image = container.value("image", "");
info->m_imagedigest = container.value("imagedigest", "");
info->m_imageid = container.value("imageid", "");
info->m_imagerepo = container.value("imagerepo", "");
info->m_imagetag = container.value("imagetag", "");
info->m_container_user = container.value("User", "");
info->m_pod_sandbox_cniresult = container.value("cni_json", "");
info->m_cpu_period = container.value("cpu_period", 0);
info->m_cpu_quota = container.value("cpu_quota", 0);
info->m_cpu_shares = container.value("cpu_shares", 0);
info->m_cpuset_cpu_count = container.value("cpuset_cpu_count", 0);
info->m_created_time = container.value("created_time", 0);
info->m_env = container.value("env", std::vector<std::string>{});
info->m_full_id = container.value("full_id", "");
info->m_host_ipc = container.value("host_ipc", false);
info->m_host_network = container.value("host_network", false);
info->m_host_pid = container.value("host_pid", false);
info->m_container_ip = container.value("ip", "");
info->m_is_pod_sandbox = container.value("is_pod_sandbox", false);
info->m_labels = container.value("labels", std::map<std::string, std::string>{});
info->m_memory_limit = container.value("memory_limit", 0);
info->m_swap_limit = container.value("swap_limit", 0);
info->m_pod_sandbox_id = container.value("pod_sandbox_id", "");
info->m_privileged = container.value("privileged", false);
info->m_pod_sandbox_labels = container.value("pod_sandbox_labels", std::map<std::string, std::string>{});
info->m_port_mappings = container.value("port_mappings", std::vector<container_port_mapping>{});
info->m_mounts = container.value("Mounts", std::vector<container_mount_info>{});

for (int probe_type = container_health_probe::PT_HEALTHCHECK; probe_type <= container_health_probe::PT_READINESS_PROBE; probe_type++) {
const auto& probe_name = container_health_probe::probe_type_names[probe_type];
if (container.contains(probe_name)) {
container_health_probe probe = container.value(probe_name, container_health_probe());
probe.m_type = container_health_probe::probe_type(probe_type);
cinfo->m_health_probes.push_back(probe);
info->m_health_probes.push_back(probe);
}
}

cinfo = info;
}

void to_json(nlohmann::json& j, const container_mount_info& mount) {
Expand Down
12 changes: 6 additions & 6 deletions src/container_type.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#pragma once

enum container_type {
CT_DOCKER = 0, // TODO implement matcher
CT_DOCKER = 0,
CT_LXC = 1,
CT_LIBVIRT_LXC = 2,
CT_MESOS = 3, // deprecated
CT_RKT = 4, // deprecated
CT_CUSTOM = 5,
CT_CRI = 6, // TODO implement matcher
CT_CONTAINERD = 7, // TODO implement matcher
CT_CRIO = 8, // TODO implement matcher
CT_CRI = 6,
CT_CONTAINERD = 7,
CT_CRIO = 8,
CT_BPM = 9,
CT_STATIC = 10, // TODO implement matcher
CT_PODMAN = 11, // TODO implement matcher
CT_STATIC = 10,
CT_PODMAN = 11,

// Default value, may be changed if necessary
CT_UNKNOWN = 0xffff
Expand Down
25 changes: 7 additions & 18 deletions src/extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,20 +334,12 @@ static inline void concatenate_container_labels(const std::map<std::string, std:

bool my_plugin::extract(const falcosecurity::extract_fields_input& in) {
const auto evt_reader = in.get_event_reader();
int64_t thread_id = evt_reader.get_tid();
if(thread_id <= 0)
{
SPDLOG_INFO("unknown thread id for event num '{}' with type '{}'",
evt_reader.get_num(),
int32_t(evt_reader.get_type()));
return false;
}
auto thread_id = evt_reader.get_tid();

std::string container_id;
falcosecurity::table_entry thread_entry;
auto tr = in.get_table_reader();
try
{
try {
// retrieve the thread entry associated with this thread id
thread_entry = m_threads_table.get_entry(tr, thread_id);
// retrieve container_id from the entry
Expand All @@ -359,27 +351,24 @@ bool my_plugin::extract(const falcosecurity::extract_fields_input& in) {
SPDLOG_DEBUG("the plugin has no container_id info for the thread id '{}'", thread_id);
return false;
}
}
catch(falcosecurity::plugin_exception e)
{
SPDLOG_ERROR("cannot extract the container_id for the thread id '{}': {}",
} catch(falcosecurity::plugin_exception e) {
// Debug here since many events do not have thread id info (eg: schedswitch)
SPDLOG_DEBUG("cannot extract the container_id for the thread id '{}': {}",
thread_id, e.what());
return false;
}

// Try to find the entry associated with the pod_uid
auto it = m_containers.find(container_id);
if(it == m_containers.end())
{
if(it == m_containers.end()) {
SPDLOG_DEBUG("the plugin has no info for the container id '{}'", container_id);
return false;
}

auto cinfo = it->second;
auto& req = in.get_extract_request();
const auto field_id = req.get_field_id();
switch(field_id)
{
switch(field_id) {
case TYPE_CONTAINER_ID:
req.set_value(cinfo->m_id);
break;
Expand Down
3 changes: 1 addition & 2 deletions src/listening.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ bool my_plugin::capture_open(const falcosecurity::capture_listen_input& in) {
{
std::shared_ptr<container_info> info = nullptr;
auto container_id = compute_container_id_for_thread(e, tr, info);
m_container_id_field.write_value(tw, e,
(const char*)container_id.c_str());
m_container_id_field.write_value(tw, e, container_id);
return true;
});
return true;
Expand Down
87 changes: 42 additions & 45 deletions src/parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ bool my_plugin::parse_async_event(
falcosecurity::events::asyncevent_e_decoder ad(evt);
bool added = std::strcmp(ad.get_name(), ASYNC_EVENT_NAME_ADDED) == 0;
bool removed = std::strcmp(ad.get_name(), ASYNC_EVENT_NAME_REMOVED) == 0;
if(!added && !removed)
{
if(!added && !removed) {
// We are not interested in parsing async events that are not
// generated by our plugin.
// This is not an error, it could happen when we have more than one
Expand All @@ -60,14 +59,12 @@ bool my_plugin::parse_async_event(

uint32_t json_charbuf_len = 0;
char* json_charbuf_pointer = (char*)ad.get_data(json_charbuf_len);
if(json_charbuf_pointer == nullptr)
{
if(json_charbuf_pointer == nullptr) {
m_lasterr = "there is no payload in the async event";
SPDLOG_ERROR(m_lasterr);
return false;
}
auto json_event = nlohmann::json::parse(std::string(json_charbuf_pointer));

auto json_event = nlohmann::json::parse(json_charbuf_pointer);
auto cinfo = json_event.get<std::shared_ptr<container_info>>();
if (added) {
m_containers[cinfo->m_id] = cinfo;
Expand Down Expand Up @@ -138,15 +135,18 @@ std::string my_plugin::compute_container_id_for_thread(const falcosecurity::tabl
tr,
[&](const falcosecurity::table_entry& e)
{
if (!container_id.empty()) {
// Nothing more to do.
// Note: returning false would raise an exception
// instead of stopping the loop :/
return true;
}
// read the "second" field (aka: the cgroup path)
// from the current entry of the cgroups table
std::string cgroup;
m_cgroups_field_second.read_value(tr, e, cgroup);

if(!cgroup.empty()) {
if (m_mgr->match_cgroup(cgroup, container_id, info)) {
return false; // stop iterating
}
m_mgr->match_cgroup(cgroup, container_id, info);
}
return true;
}
Expand Down Expand Up @@ -224,47 +224,44 @@ void my_plugin::write_thread_category(const falcosecurity::table_entry& thread_e
bool my_plugin::parse_new_process_event(
const falcosecurity::parse_event_input& in) {
// get tid
int64_t thread_id = in.get_event_reader().get_tid();
if(thread_id <= 0)
{
SPDLOG_INFO("unknown thread id for event num '{}' with type '{}'",
in.get_event_reader().get_num(),
int32_t(in.get_event_reader().get_type()));
return false;
}
auto thread_id = in.get_event_reader().get_tid();

// compute container_id from tid->cgroups
auto& tr = in.get_table_reader();

// retrieve the thread entry associated with this thread id
auto thread_entry = m_threads_table.get_entry(tr, thread_id);

std::shared_ptr<container_info> info = nullptr;
auto container_id = compute_container_id_for_thread(thread_entry, tr, info);

// store container_id
auto& tw = in.get_table_writer();
m_container_id_field.write_value(tw, thread_entry,
(const char*)container_id.c_str());

if (info != nullptr) {
// Since the matcher also returned a container_info,
// it means we do not expect to receive any metadata from the go-worker,
// since the engine has no listener SDK.
// Just send the event now.
nlohmann::json j(info);
generate_async_event(j.dump().c_str(), true, ASYNC_HANDLER_DEFAULT);

// Immediately cache the container metadata
m_containers[info->m_id] = info;
}

// Write thread category field
if (container_id != HOST_CONTAINER_ID) {
write_thread_category(thread_entry, tr, tw);
try {
auto thread_entry = m_threads_table.get_entry(tr, thread_id);

std::shared_ptr<container_info> info = nullptr;
auto container_id = compute_container_id_for_thread(thread_entry, tr, info);

// store container_id
auto& tw = in.get_table_writer();
m_container_id_field.write_value(tw, thread_entry, container_id);

if (info != nullptr) {
// Since the matcher also returned a container_info,
// it means we do not expect to receive any metadata from the go-worker,
// since the engine has no listener SDK.
// Just send the event now.
nlohmann::json j(info);
generate_async_event(j.dump().c_str(), true, ASYNC_HANDLER_DEFAULT);

// Immediately cache the container metadata
m_containers[info->m_id] = info;
}

// Write thread category field
if (container_id != HOST_CONTAINER_ID) {
write_thread_category(thread_entry, tr, tw);
}
return true;
} catch (falcosecurity::plugin_exception &e) {
SPDLOG_ERROR("cannot attach container_id to new process event for the thread id '{}': {}",
thread_id, e.what());
return false;
}

return true;
}

bool my_plugin::parse_event(const falcosecurity::parse_event_input& in) {
Expand Down
3 changes: 2 additions & 1 deletion vcpkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"license": "MIT",
"dependencies": [
"re2",
"spdlog"
"spdlog",
"gpgme"
]
}

0 comments on commit 178eb89

Please sign in to comment.