Skip to content

Latest commit

 

History

History

README.md

Container metadata enrichment Plugin

Introduction

The container plugin enhances the Falco syscall source by providing additional information about container resources involved. You can find the comprehensive list of supported fields here.

Functionality

The plugin itself reimplements all the container-related logic that was already present in libs under the form of a plugin, that can be attached to any source.
Moreover, it aims to fix issues present in the current implementation, trying to be as quick as possible to gather container metadata information, to avoid losing a single event metadata.

Capabilities

The container plugin implements the following capabilities:

  • capture listening -> to attach container_id foreign key to all pre-existing threadinfos, once they have been scraped from procfs by sinsp
  • extraction -> to extract container.X fields
  • parsing -> to parse async and container events (the latter for backward compatibility with existing scap files), and clone/fork/execve events to attach container_id foreign key to any threads
  • async -> to generate events with container information and dump current plugin cache state when requested

It requires 3.10.0 plugin API version.

Architecture

The container plugin is split into 2 modules:

  • a C++ shared object that implements the 3 capabilities and holds the cache map <container_id,container_info>
  • a GO static library (linked inside the C++ shared object) that implements the worker logic to retrieve new containers' metadata leveraging existing SDKs

As soon as the plugin starts, the go-worker gets started as part of the async capability, passing to it plugin init config and a C++ callback to generate async events. Whenever the GO worker finds a new container, it immediately generates an async event through the aforementioned callback. The async event is then received by the C++ side as part of the parsing capability, and it enriches its own internal state cache. Every time a clone/fork/execve event gets parsed, we attach to its thread table entry the information about the container_id, extracted by looking at the cgroups field, in a foreign key. Once the extraction is requested for a thread, the container_id is then used as key to access our plugin's internal container metadata cache, and the requested infos extracted.

Note, however, that for some container engines, namely {bpm,lxc,libvirt_lcx}, we only support fetching generic info, ie: the container ID and the container type.
Given that there is no "listener" SDK to attach to, for these engines the async event is generated directly by the C++ code, as soon as the container ID is retrieved.

Plugin official name

container

Supported Fields

NAME TYPE ARG DESCRIPTION
container.id string None The truncated container ID (first 12 characters), e.g. 3ad7b26ded6d is extracted from the Linux cgroups by Falco within the kernel. Consequently, this field is reliably available and serves as the lookup key for Falco's synchronous or asynchronous requests against the container runtime socket to retrieve all other 'container.' information. One important aspect to be aware of is that if the process occurs on the host, meaning not in the container PID namespace, this field is set to a string called 'host'. In Kubernetes, pod sandbox container processes can exist where container.id matches k8s.pod.sandbox_id, lacking other 'container.' details.
container.full_id string None The full container ID, e.g. 3ad7b26ded6d8e7b23da7d48fe889434573036c27ae5a74837233de441c3601e. In contrast to container.id, we enrich this field as part of the container engine enrichment. In instances of userspace container engine lookup delays, this field may not be available yet.
container.name string None The container name. In instances of userspace container engine lookup delays, this field may not be available yet. One important aspect to be aware of is that if the process occurs on the host, meaning not in the container PID namespace, this field is set to a string called 'host'.
container.image string None The container image name (e.g. falcosecurity/falco:latest for docker). In instances of userspace container engine lookup delays, this field may not be available yet.
container.image.id string None The container image id (e.g. 6f7e2741b66b). In instances of userspace container engine lookup delays, this field may not be available yet.
container.type string None The container type, e.g. docker, cri-o, containerd etc.
container.privileged bool None 'true' for containers running as privileged, 'false' otherwise. In instances of userspace container engine lookup delays, this field may not be available yet.
container.mounts string None A space-separated list of mount information. Each item in the list has the format 'source:dest:mode:rdrw:propagation'. In instances of userspace container engine lookup delays, this field may not be available yet.
container.mount string Index, Key, Required Information about a single mount, specified by number (e.g. container.mount[0]) or mount source (container.mount[/usr/local]). The pathname can be a glob (container.mount[/usr/local/*]), in which case the first matching mount will be returned. The information has the format 'source:dest:mode:rdrw:propagation'. If there is no mount with the specified index or matching the provided source, returns the string "none" instead of a NULL value. In instances of userspace container engine lookup delays, this field may not be available yet.
container.mount.source string Index, Key, Required The mount source, specified by number (e.g. container.mount.source[0]) or mount destination (container.mount.source[/host/lib/modules]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet.
container.mount.dest string Index, Key, Required The mount destination, specified by number (e.g. container.mount.dest[0]) or mount source (container.mount.dest[/lib/modules]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet.
container.mount.mode string Index, Key, Required The mount mode, specified by number (e.g. container.mount.mode[0]) or mount source (container.mount.mode[/usr/local]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet.
container.mount.rdwr string Index, Key, Required The mount rdwr value, specified by number (e.g. container.mount.rdwr[0]) or mount source (container.mount.rdwr[/usr/local]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet.
container.mount.propagation string Index, Key, Required The mount propagation value, specified by number (e.g. container.mount.propagation[0]) or mount source (container.mount.propagation[/usr/local]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet.
container.image.repository string None The container image repository (e.g. falcosecurity/falco). In instances of userspace container engine lookup delays, this field may not be available yet.
container.image.tag string None The container image tag (e.g. stable, latest). In instances of userspace container engine lookup delays, this field may not be available yet.
container.image.digest string None The container image registry digest (e.g. sha256:d977378f890d445c15e51795296e4e5062f109ce6da83e0a355fc4ad8699d27). In instances of userspace container engine lookup delays, this field may not be available yet.
container.healthcheck string None The container's health check. Will be the null value ("N/A") if no healthcheck configured, "NONE" if configured but explicitly not created, and the healthcheck command line otherwise. In instances of userspace container engine lookup delays, this field may not be available yet.
container.liveness_probe string None The container's liveness probe. Will be the null value ("N/A") if no liveness probe configured, the liveness probe command line otherwise. In instances of userspace container engine lookup delays, this field may not be available yet.
container.readiness_probe string None The container's readiness probe. Will be the null value ("N/A") if no readiness probe configured, the readiness probe command line otherwise. In instances of userspace container engine lookup delays, this field may not be available yet.
container.start_ts abstime None Container start as epoch timestamp in nanoseconds based on proc.pidns_init_start_ts and extracted in the kernel and not from the container runtime socket / container engine.
container.duration reltime None Number of nanoseconds since container.start_ts.
container.ip string None The container's / pod's primary ip address as retrieved from the container engine. Only ipv4 addresses are tracked. Consider container.cni.json (CRI use case) for logging ip addresses for each network interface. In instances of userspace container engine lookup delays, this field may not be available yet.
container.cni.json string None The container's / pod's CNI result field from the respective pod status info. It contains ip addresses for each network interface exposed as unparsed escaped JSON string. Supported for CRI container engine (containerd, cri-o runtimes), optimized for containerd (some non-critical JSON keys removed). Useful for tracking ips (ipv4 and ipv6, dual-stack support) for each network interface (multi-interface support). In instances of userspace container engine lookup delays, this field may not be available yet.
container.host_pid bool None 'true' if the container is running in the host PID namespace, 'false' otherwise.
container.host_network bool None 'true' if the container is running in the host network namespace, 'false' otherwise.
container.host_ipc bool None 'true' if the container is running in the host IPC namespace, 'false' otherwise.
container.label string Key, Required Container label. E.g. 'container.label.foo'.
container.labels string None Container comma-separated key/value labels. E.g. 'foo1:bar1,foo2:bar2'.
proc.is_container_healthcheck bool None 'true' if this process is running as a part of the container's health check.
proc.is_container_liveness_probe bool None 'true' if this process is running as a part of the container's liveness probe.
proc.is_container_readiness_probe bool None 'true' if this process is running as a part of the container's readiness probe.
k8s.pod.name string None The Kubernetes pod name. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.ns.name string None The Kubernetes namespace name. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.pod.id string None [LEGACY] The Kubernetes pod UID, e.g. 3e41dc6b-08a8-44db-bc2a-3724b18ab19a. This legacy field points to k8s.pod.uid; however, the pod ID typically refers to the pod sandbox ID. We recommend using the semantically more accurate k8s.pod.uid field. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.pod.uid string None The Kubernetes pod UID, e.g. 3e41dc6b-08a8-44db-bc2a-3724b18ab19a. Note that the pod UID is a unique identifier assigned upon pod creation within Kubernetes, allowing the Kubernetes control plane to manage and track pods reliably. As such, it is fundamentally a different concept compared to the pod sandbox ID. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.pod.sandbox_id string None The truncated Kubernetes pod sandbox ID (first 12 characters), e.g 63060edc2d3a. The sandbox ID is specific to the container runtime environment. It is the equivalent of the container ID for the pod / sandbox and extracted from the Linux cgroups. As such, it differs from the pod UID. This field is extracted from the container runtime socket simultaneously as we look up the 'container.' fields. In cases of lookup delays, it may not be available yet. In Kubernetes, pod sandbox container processes can exist where container.id matches k8s.pod.sandbox_id, lacking other 'container.' details.
k8s.pod.full_sandbox_id string None The full Kubernetes pod / sandbox ID, e.g 63060edc2d3aa803ab559f2393776b151f99fc5b05035b21db66b3b62246ad6a. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.pod.label string Key, Required The Kubernetes pod label. The label can be accessed either with the familiar brackets notation, e.g. 'k8s.pod.label[foo]' or by appending a dot followed by the name, e.g. 'k8s.pod.label.foo'. The label name itself can include the original special characters such as '.', '-', '_' or '/' characters. For instance, 'k8s.pod.label[app.kubernetes.io/name]', 'k8s.pod.label.app.kubernetes.io/name' or 'k8s.pod.label[custom-label_one]' are all valid. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.pod.labels string None The Kubernetes pod comma-separated key/value labels. E.g. 'foo1:bar1,foo2:bar2'. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.pod.ip string None The Kubernetes pod ip, same as container.ip field as each container in a pod shares the network stack of the sandbox / pod. Only ipv4 addresses are tracked. Consider k8s.pod.cni.json for logging ip addresses for each network interface. This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.pod.cni.json string None The Kubernetes pod CNI result field from the respective pod status info, same as container.cni.json field. It contains ip addresses for each network interface exposed as unparsed escaped JSON string. Supported for CRI container engine (containerd, cri-o runtimes), optimized for containerd (some non-critical JSON keys removed). Useful for tracking ips (ipv4 and ipv6, dual-stack support) for each network interface (multi-interface support). This field is extracted from the container runtime socket simultaneously as we look up the 'container.*' fields. In cases of lookup delays, it may not be available yet.
k8s.rc.name string None Deprecated. Use k8smeta plugin instead.
k8s.rc.id string None Deprecated. Use k8smeta plugin instead.
k8s.rc.label string Key, Required Deprecated. Use k8smeta plugin instead.
k8s.rc.labels string None Deprecated. Use k8smeta plugin instead.
k8s.svc.name string None Deprecated. Use k8smeta plugin instead.
k8s.svc.id string None Deprecated. Use k8smeta plugin instead.
k8s.svc.label string Key, Required Deprecated. Use k8smeta plugin instead.
k8s.svc.labels string None Deprecated. Use k8smeta plugin instead.
k8s.ns.id string None Deprecated. Use k8smeta plugin instead.
k8s.ns.label string Key, Required Deprecated. Use k8smeta plugin instead.
k8s.ns.labels string None Deprecated. Use k8smeta plugin instead.
k8s.rs.name string None Deprecated. Use k8smeta plugin instead.
k8s.rs.id string None Deprecated. Use k8smeta plugin instead.
k8s.rs.label string Key, Required Deprecated. Use k8smeta plugin instead.
k8s.rs.labels string None Deprecated. Use k8smeta plugin instead.
k8s.deployment.name string None Deprecated. Use k8smeta plugin instead.
k8s.deployment.id string None Deprecated. Use k8smeta plugin instead.
k8s.deployment.label string Key, Required Deprecated. Use k8smeta plugin instead.
k8s.deployment.labels string None Deprecated. Use k8smeta plugin instead.

Requirements

Usage

Configuration

By default, all engines are enabled on default sockets:

  • Docker: [/var/run/docker.sock]
  • Podman: [/run/podman/podman.sock for root, + /run/user/$uid/podman/podman.sock for each user in the system]
  • Containerd: [/run/host-containerd/containerd.sock]
  • Cri: [/run/containerd/containerd.sock, /run/crio/crio.sock, /run/k3s/containerd/containerd.sock, /run/host-containerd/containerd.sock]

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

plugins:
  - name: container
    # path to the plugin .so file
    library_path: libcontainer.so
    init_config:
      label_max_len: 100 # (optional, default: 100; container labels larger than this won't be reported)
      with_size: false # (optional, default: false; whether to enable container size inspection, which is inherently slow)
      hooks: ['create', 'start'] # (optional, default: 'create'. Some fields might not be available in create hook, but we are guaranteed that it gets triggered before first process gets started)
      engines:
        docker:
          enabled: true
          sockets: ['/var/run/docker.sock']
        podman:
          enabled: true
          sockets: ['/run/podman/podman.sock', '/run/user/1000/podman/podman.sock']
        containerd:
          enabled: true
          sockets: ['/run/containerd/containerd.sock']
        cri:
          enabled: true
          sockets: ['/run/crio/crio.sock']
        lxc:
          enabled: false
        libvirt_lxc:
          enabled: false
        bpm:
          enabled: false  

load_plugins: [container]

Rules

This plugin doesn't provide any custom rule, you can use the default Falco ruleset and add the necessary container fields. Note: leveraging latest plugin SDK features, the plugin itself will expose certain fields as suggested output fields:

  • container.id
  • container.name

Running

This plugin requires Falco with version >= 0.41.0. The plugin is bundled within Falco, so you only need to run Falco as you would do normally.

Local development

Build and test

Build the plugin on a fresh Ubuntu 22.04 machine:

sudo apt update -y
sudo apt install -y cmake build-essential autoconf libtool pkg-config
git clone https://github.com/falcosecurity/plugins.git
cd plugins/container
make libcontainer.so

You can also run make exe from withing the go-worker folder to build a worker executable to test the go-worker implementation.