Skip to content

Commit

Permalink
new(plugins): introduce new k8smeta plugin
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 committed Dec 11, 2023
1 parent f1e9c79 commit 591116e
Show file tree
Hide file tree
Showing 23 changed files with 3,524 additions and 0 deletions.
6 changes: 6 additions & 0 deletions plugins/k8smeta/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.so
*.a
*.o
.vscode
build*
libk8smeta.so
72 changes: 72 additions & 0 deletions plugins/k8smeta/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
cmake_minimum_required(VERSION 3.22)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")

option(BUILD_TESTS "Enable test" ON)

# project metadata
project(
k8smeta
VERSION 0.1.0
DESCRIPTION "Falco Kubernetes enrichment Plugin"
LANGUAGES CXX)

# dependencies
include(FetchContent)
include(grpc)
include(spdlog)
include(plugin-sdk-cpp)
include(k8s-metacollector)

set(PROTO_PATH "${K8S_METACOLLECTOR_DIR}/metadata/metadata.proto")

get_filename_component(meta_proto "${PROTO_PATH}" ABSOLUTE)
get_filename_component(meta_proto_path "${meta_proto}" PATH)

# Generated sources
set(PROTO_GENERATED_INCLUDE "${CMAKE_BINARY_DIR}/generated")
if(NOT EXISTS "${PROTO_GENERATED_INCLUDE}")
file(MAKE_DIRECTORY "${PROTO_GENERATED_INCLUDE}")
endif()

set(meta_proto_srcs "${PROTO_GENERATED_INCLUDE}/metadata.pb.cc")
set(meta_proto_hdrs "${PROTO_GENERATED_INCLUDE}/metadata.pb.h")
set(meta_grpc_srcs "${PROTO_GENERATED_INCLUDE}/metadata.grpc.pb.cc")
set(meta_grpc_hdrs "${PROTO_GENERATED_INCLUDE}/metadata.grpc.pb.h")
add_custom_command(
OUTPUT "${meta_proto_srcs}" "${meta_proto_hdrs}" "${meta_grpc_srcs}"
"${meta_grpc_hdrs}"
COMMAND
${_PROTOBUF_PROTOC} ARGS --grpc_out "${PROTO_GENERATED_INCLUDE}" --cpp_out
"${PROTO_GENERATED_INCLUDE}" -I "${meta_proto_path}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" "${meta_proto}"
DEPENDS "${meta_proto}")

# project target
file(GLOB_RECURSE K8S_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_library(k8smeta SHARED ${K8S_SOURCES} ${meta_grpc_srcs} ${meta_grpc_hdrs}
${meta_proto_srcs} ${meta_proto_hdrs})
set_target_properties(k8smeta PROPERTIES CXX_EXTENSIONS OFF)

# project compilation options
target_compile_options(k8smeta PRIVATE "-fPIC")
target_compile_options(k8smeta PRIVATE "-Wl,-z,relro,-z,now")
target_compile_options(k8smeta PRIVATE "-fstack-protector-strong")
# When compiling in Debug mode, this will define the DEBUG symbol for use in
# your code.
target_compile_options(k8smeta PUBLIC "$<$<CONFIG:DEBUG>:-DDEBUG>")
target_compile_features(k8smeta PUBLIC cxx_std_17)

# project includes
target_include_directories(
k8smeta PRIVATE "${PLUGIN_SDK_INLCUDE}" "${PROTO_GENERATED_INCLUDE}"
"${SPDLOG_INLCUDE}")

# project linked libraries
target_link_libraries(k8smeta ${_REFLECTION} ${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF} re2::re2)

# Testing
if(BUILD_TESTS)
add_subdirectory(test)
endif()
29 changes: 29 additions & 0 deletions plugins/k8smeta/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2023 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#


NAME := k8smeta
OUTPUT := lib$(NAME).so

all: $(OUTPUT)

clean:
rm -rf build $(OUTPUT)

# This Makefile requies CMake installed on the system
$(OUTPUT):
mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release ../ && make k8smeta -j6 && cp ./$(OUTPUT) ../$(OUTPUT)

readme:
@$(READMETOOL) -p ./$(OUTPUT) -f README.md
79 changes: 79 additions & 0 deletions plugins/k8smeta/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Kubernetes Audit Events Plugin

## Introduction

This plugin enriches Falco syscall flow with Kubernetes Metadata coming from the API server.
The plugin uses a GRPC channel to communicate with a remote [collector](https://github.com/falcosecurity/k8s-metacollector). The collector is indipendent from the plugin and should be deployed as a separate component. The main role of the plugin is to associate each syscall with information about the pod in which they are thrown.

### Functionality

TODO

## Capabilities

The `k8smeta` plugin implements these capabilities:
* `extraction`
* `parsing`
* `async`

### Supported Fields

<!-- README-PLUGIN-FIELDS -->
| NAME | TYPE | ARG | DESCRIPTION |
|----------------------------|-----------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `k8sres.pod.name` | `string` | None | Kubernetes pod name. |
| `k8sres.pod.id` | `string` | None | Kubernetes pod ID. |
| `k8sres.pod.label` | `string` | Key, Required | Kubernetes pod label. E.g. 'k8sres.pod.label[foo]'. |
| `k8sres.pod.labels` | `string (list)` | None | Kubernetes pod comma-separated key/value labels. E.g. '(foo1:bar1,foo2:bar2)'. |
| `k8sres.pod.ip` | `string` | None | Kubernetes pod ip |
| `k8sres.ns.name` | `string` | None | Kubernetes namespace name. |
| `k8sres.ns.id` | `string` | None | Kubernetes namespace ID. |
| `k8sres.ns.label` | `string` | Key, Required | Kubernetes namespace label. E.g. 'k8sres.ns.label[foo]'. |
| `k8sres.ns.labels` | `string (list)` | None | Kubernetes namespace comma-separated key/value labels. E.g. '(foo1:bar1,foo2:bar2)'. |
| `k8sres.deployment.name` | `string` | None | Kubernetes deployment name. |
| `k8sres.deployment.id` | `string` | None | Kubernetes deployment ID. |
| `k8sres.deployment.label` | `string` | Key, Required | Kubernetes deployment label. E.g. 'k8sres.rs.label[foo]'. |
| `k8sres.deployment.labels` | `string (list)` | None | Kubernetes deployment comma-separated key/value labels. E.g. '(foo1:bar1,foo2:bar2)'. |
| `k8sres.svc.name` | `string (list)` | None | Kubernetes services name. Return a list with all the names of the services associated with the current pod. E.g. '(service1,service2)' |
| `k8sres.svc.id` | `string (list)` | None | Kubernetes services ID. Return a list with all the IDs of the services associated with the current pod. E.g. '(88279776-941c-491e-8da1-95ef30f50fe8,149e72f4-a570-4282-bfa0-25307c5007e8)' |
| `k8sres.svc.label` | `string (list)` | Key, Required | Kubernetes services label. If the services associated with the current pod have a label with this name, return the list of label's values. E.g. if the current pod has 2 services associated and both have the 'foo' label, 'k8sres.svc.label[foo]' will return '(service1-label-value,service2-label-value) |
| `k8sres.svc.labels` | `string (list)` | None | Kubernetes services labels. Return a list with all the comma-separated key/value labels of the services associated with the current pod. E.g. '(foo1:bar1,foo2:bar2)' |
| `k8sres.rs.name` | `string` | None | Kubernetes replica set name. |
| `k8sres.rs.id` | `string` | None | Kubernetes replica set ID. |
| `k8sres.rs.label` | `string` | Key, Required | Kubernetes replica set label. E.g. 'k8sres.rs.label[foo]'. |
| `k8sres.rs.labels` | `string (list)` | None | Kubernetes replica set comma-separated key/value labels. E.g. '(foo1:bar1,foo2:bar2)'. |
| `k8sres.rc.name` | `string` | None | Kubernetes replication controller name. |
| `k8sres.rc.id` | `string` | None | Kubernetes replication controller ID. |
| `k8sres.rc.label` | `string` | Key, Required | Kubernetes replication controller label. E.g. 'k8sres.rc.label[foo]'. |
| `k8sres.rc.labels` | `string (list)` | None | Kubernetes replication controller comma-separated key/value labels. E.g. '(foo1:bar1,foo2:bar2)'. |
<!-- /README-PLUGIN-FIELDS -->

## Usage

### Configuration

Here's an example of configuration of `falco.yaml`:

```yaml
load_plugins: [k8smeta]

plugins:
- name: k8smeta
library_path: libk8smeta.so
init_config:
collectorPort: 45000
collectorHostname: localhost
nodename: kind-control-plane
```
**Initialization Config**:
TODO
**Open Parameters**:
The plugin doesn't have open params
### Rule Example
To see how to use the plugin fields in a Falco rule check the example rule `/k8smeta/test/rules/example_rule.yaml`.
35 changes: 35 additions & 0 deletions plugins/k8smeta/cmake/modules/grpc.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# This cmake module is adapted from the grpc repo:
# `examples/cpp/cmake/common.cmake`

message(STATUS "Fetching grpc at 'https://github.com/grpc/grpc'")

find_package(Threads REQUIRED)

# See:
# https://github.com/protocolbuffers/protobuf/issues/12185#issuecomment-1594685860
set(ABSL_ENABLE_INSTALL ON)

# To solve:
#
# CMake Warning at build/_deps/grpc-src/third_party/abseil-cpp/CMakeLists.txt:77
# (message): A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON
# for CMake 3.8 and up. We recommend enabling this option to ensure your
# project still builds correctly
set(ABSL_PROPAGATE_CXX_STD ON)

FetchContent_Declare(
gRPC
GIT_REPOSITORY https://github.com/grpc/grpc
GIT_TAG v1.44.0
GIT_PROGRESS TRUE)

set(FETCHCONTENT_QUIET OFF)
FetchContent_MakeAvailable(gRPC)

set(_PROTOBUF_LIBPROTOBUF libprotobuf)
set(_REFLECTION grpc++_reflection)
set(_PROTOBUF_PROTOC $<TARGET_FILE:protoc>)
set(_GRPC_GRPCPP grpc++)
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:grpc_cpp_plugin>)

message(STATUS "Using grpc at '${gRPC_SOURCE_DIR}'")
14 changes: 14 additions & 0 deletions plugins/k8smeta/cmake/modules/k8s-metacollector.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
message(
STATUS
"Fetching k8s-metacollector at 'https://github.com/falcosecurity/k8s-metacollector.git'"
)

# Download a non cmake project
FetchContent_Declare(
k8s-metacollector
GIT_REPOSITORY https://github.com/falcosecurity/k8s-metacollector.git
GIT_TAG 982c40ac128cc94557b98d81210cbb13e7825129
CONFIGURE_COMMAND "" BUILD_COMMAND "")

FetchContent_Populate(k8s-metacollector)
set(K8S_METACOLLECTOR_DIR "${k8s-metacollector_SOURCE_DIR}")
11 changes: 11 additions & 0 deletions plugins/k8smeta/cmake/modules/libs.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
message(STATUS "Fetching libs at 'https://github.com/falcosecurity/libs.git'")

# Just populate it we don't want to build it
FetchContent_Declare(
libs
GIT_REPOSITORY https://github.com/falcosecurity/libs.git
GIT_TAG 8fee2fb4791d50ec5ee4808e5ed235c8b1b309f3
CONFIGURE_COMMAND "" BUILD_COMMAND "")

FetchContent_Populate(libs)
set(LIBS_DIR "${libs_SOURCE_DIR}")
13 changes: 13 additions & 0 deletions plugins/k8smeta/cmake/modules/plugin-sdk-cpp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
message(
STATUS
"Fetching plugin-sdk-cpp at 'https://github.com/falcosecurity/plugin-sdk-cpp.git'"
)

FetchContent_Declare(
plugin-sdk-cpp
GIT_REPOSITORY https://github.com/falcosecurity/plugin-sdk-cpp.git
GIT_TAG 2097bdb5a5d77f3f38162da1f438382912465340)

FetchContent_MakeAvailable(plugin-sdk-cpp)
set(PLUGIN_SDK_INLCUDE "${plugin-sdk-cpp_SOURCE_DIR}/include")
message(STATUS "Using plugin-sdk-cpp include at '${PLUGIN_SDK_INLCUDE}'")
11 changes: 11 additions & 0 deletions plugins/k8smeta/cmake/modules/spdlog.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
message(STATUS "Fetching spdlog at at 'https://github.com/gabime/spdlog'")

# Header only library
FetchContent_Declare(
spdlog
GIT_REPOSITORY "https://github.com/gabime/spdlog.git"
GIT_TAG v1.12.0)

FetchContent_MakeAvailable(spdlog)
set(SPDLOG_INLCUDE "${spdlog_SOURCE_DIR}/include")
message(STATUS "Using spdlog include at '${SPDLOG_INLCUDE}'")
Loading

0 comments on commit 591116e

Please sign in to comment.