mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-26 22:52:14 +00:00
Compare commits
22 Commits
fix/use_pl
...
new/static
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a669f40d64 | ||
|
|
d978f0c3fc | ||
|
|
8cf9b35b0e | ||
|
|
6e4ccb0007 | ||
|
|
44b7352180 | ||
|
|
13991f1ea7 | ||
|
|
10226a6c87 | ||
|
|
e558c4f5a5 | ||
|
|
0ba0dd8671 | ||
|
|
305ed75268 | ||
|
|
390a13bd40 | ||
|
|
67542ec88e | ||
|
|
e3943ccac3 | ||
|
|
95968defa5 | ||
|
|
6411eed4a7 | ||
|
|
c5364be191 | ||
|
|
ce4d28ef90 | ||
|
|
3b068919d0 | ||
|
|
3e4566e5af | ||
|
|
9cb4c09500 | ||
|
|
8196ee3b83 | ||
|
|
af7192bdc3 |
27
.github/workflows/ci.yml
vendored
27
.github/workflows/ci.yml
vendored
@@ -23,6 +23,13 @@ jobs:
|
||||
arch: x86_64
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
build-dev-packages-arm64:
|
||||
needs: [fetch-version]
|
||||
uses: ./.github/workflows/reusable_build_packages.yaml
|
||||
with:
|
||||
arch: aarch64
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
test-dev-packages:
|
||||
needs: [fetch-version, build-dev-packages]
|
||||
uses: ./.github/workflows/reusable_test_packages.yaml
|
||||
@@ -35,6 +42,16 @@ jobs:
|
||||
static: ${{ matrix.static != '' && true || false }}
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
test-dev-packages-arm64:
|
||||
needs: [fetch-version, build-dev-packages]
|
||||
uses: ./.github/workflows/reusable_test_packages.yaml
|
||||
strategy:
|
||||
fail-fast: false
|
||||
with:
|
||||
arch: aarch64
|
||||
static: ${{ matrix.static != '' && true || false }}
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
build-dev-minimal:
|
||||
uses: ./.github/workflows/reusable_build_dev.yaml
|
||||
with:
|
||||
@@ -42,7 +59,15 @@ jobs:
|
||||
git_ref: ${{ github.event.pull_request.head.sha }}
|
||||
minimal: true
|
||||
build_type: Debug
|
||||
|
||||
|
||||
build-dev-minimal-arm64:
|
||||
uses: ./.github/workflows/reusable_build_dev.yaml
|
||||
with:
|
||||
arch: aarch64
|
||||
git_ref: ${{ github.event.pull_request.head.sha }}
|
||||
minimal: true
|
||||
build_type: Debug
|
||||
|
||||
# builds using system deps, checking out the PR's code
|
||||
# note: this also runs a command that generates an output of form: "<engine_version> <some_hash>",
|
||||
# of which <some_hash> is computed by hashing in order the following:
|
||||
|
||||
4
.github/workflows/codeql.yaml
vendored
4
.github/workflows/codeql.yaml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
run: sudo apt update -y
|
||||
|
||||
- name: Install build dependencies
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm git -y
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev libprotobuf-dev protobuf-compiler libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm git -y
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
|
||||
17
.github/workflows/reusable_build_dev.yaml
vendored
17
.github/workflows/reusable_build_dev.yaml
vendored
@@ -27,14 +27,13 @@ on:
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-22.04' }}
|
||||
container: ${{ (inputs.arch == 'aarch64' && 'ubuntu:22.04') || '' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-22.04' }}
|
||||
outputs:
|
||||
cmdout: ${{ steps.run_cmd.outputs.out }}
|
||||
cmdout: ${{ steps.run_cmd.outputs.out }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
@@ -44,14 +43,14 @@ jobs:
|
||||
|
||||
- name: Update base image
|
||||
run: sudo apt update -y
|
||||
|
||||
|
||||
- name: Install build dependencies
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libjq-dev libelf-dev libyaml-cpp-dev cmake build-essential git -y
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libelf-dev libyaml-cpp-dev cmake build-essential git -y
|
||||
|
||||
- name: Install build dependencies (non-minimal)
|
||||
if: inputs.minimal != true
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libc-ares-dev libprotobuf-dev protobuf-compiler libgrpc++-dev protobuf-compiler-grpc rpm libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm -y
|
||||
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev libprotobuf-dev protobuf-compiler libgrpc++-dev protobuf-compiler-grpc rpm libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm -y
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
mkdir build
|
||||
@@ -74,7 +73,7 @@ jobs:
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
pushd build
|
||||
sudo ./unit_tests/falco_unit_tests
|
||||
sudo ./unit_tests/falco_unit_tests
|
||||
popd
|
||||
|
||||
- name: Run command
|
||||
|
||||
2
.github/workflows/reusable_build_docker.yaml
vendored
2
.github/workflows/reusable_build_docker.yaml
vendored
@@ -27,7 +27,7 @@ on:
|
||||
jobs:
|
||||
build-docker:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
env:
|
||||
TARGETARCH: ${{ (inputs.arch == 'aarch64' && 'arm64') || 'amd64' }}
|
||||
steps:
|
||||
|
||||
14
.github/workflows/reusable_build_packages.yaml
vendored
14
.github/workflows/reusable_build_packages.yaml
vendored
@@ -14,7 +14,7 @@ on:
|
||||
jobs:
|
||||
build-modern-bpf-skeleton:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
container: fedora:latest
|
||||
steps:
|
||||
# Always install deps before invoking checkout action, to properly perform a full clone.
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
build-packages:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
needs: [build-modern-bpf-skeleton]
|
||||
container: centos:7
|
||||
steps:
|
||||
@@ -119,9 +119,7 @@ jobs:
|
||||
${{ github.workspace }}/build/falco-*.rpm
|
||||
|
||||
build-musl-package:
|
||||
# x86_64 only for now
|
||||
if: ${{ inputs.arch == 'x86_64' }}
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
container: alpine:3.17
|
||||
steps:
|
||||
# Always install deps before invoking checkout action, to properly perform a full clone.
|
||||
@@ -152,14 +150,14 @@ jobs:
|
||||
- name: Rename static package
|
||||
run: |
|
||||
cd build
|
||||
mv falco-${{ inputs.version }}-x86_64.tar.gz falco-${{ inputs.version }}-static-x86_64.tar.gz
|
||||
mv falco-${{ inputs.version }}-${{ inputs.arch }}.tar.gz falco-${{ inputs.version }}-static-${{ inputs.arch }}.tar.gz
|
||||
|
||||
- name: Upload Falco static package
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-static-x86_64.tar.gz
|
||||
name: falco-${{ inputs.version }}-static-${{ inputs.arch }}.tar.gz
|
||||
path: |
|
||||
${{ github.workspace }}/build/falco-${{ inputs.version }}-static-x86_64.tar.gz
|
||||
${{ github.workspace }}/build/falco-${{ inputs.version }}-static-${{ inputs.arch }}.tar.gz
|
||||
|
||||
build-wasm-package:
|
||||
if: ${{ inputs.arch == 'x86_64' }}
|
||||
|
||||
11
.github/workflows/reusable_publish_packages.yaml
vendored
11
.github/workflows/reusable_publish_packages.yaml
vendored
@@ -70,8 +70,14 @@ jobs:
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-static-x86_64.tar.gz
|
||||
path: /tmp/falco-build-bin-static
|
||||
|
||||
- name: Import gpg key
|
||||
|
||||
- name: Download static binary aarch64
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-static-aarch64.tar.gz
|
||||
path: /tmp/falco-build-bin-static
|
||||
|
||||
- name: Import gpg key
|
||||
env:
|
||||
GPG_KEY: ${{ secrets.GPG_KEY }}
|
||||
run: printenv GPG_KEY | gpg --import -
|
||||
@@ -93,6 +99,7 @@ jobs:
|
||||
- name: Publish static
|
||||
run: |
|
||||
./scripts/publish-bin -f /tmp/falco-build-bin-static/falco-${{ inputs.version }}-static-x86_64.tar.gz -r bin${{ inputs.bucket_suffix }} -a x86_64
|
||||
./scripts/publish-bin -f /tmp/falco-build-bin-static/falco-${{ inputs.version }}-static-aarch64.tar.gz -r bin${{ inputs.bucket_suffix }} -a aarch64
|
||||
|
||||
publish-packages-deb:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
12
.github/workflows/reusable_test_packages.yaml
vendored
12
.github/workflows/reusable_test_packages.yaml
vendored
@@ -19,7 +19,7 @@ on:
|
||||
jobs:
|
||||
test-packages:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
@@ -44,9 +44,7 @@ jobs:
|
||||
cd falco-${{ inputs.version }}-${{ inputs.arch }}
|
||||
sudo cp -r * /
|
||||
|
||||
# x86_64 job run on ubuntu-22.04 and here we can install kernel-headers
|
||||
- name: Install dependencies for falco-driver-loader tests on x86
|
||||
if: ${{ inputs.arch == 'x86_64' }}
|
||||
- name: Install dependencies for falco-driver-loader tests
|
||||
run: |
|
||||
sudo apt update -y
|
||||
sudo apt install -y --no-install-recommends build-essential clang make llvm gcc dkms linux-headers-$(uname -r)
|
||||
@@ -63,8 +61,6 @@ jobs:
|
||||
go generate ./...
|
||||
popd
|
||||
|
||||
# Right now we are not able to install kernel-headers on our ARM64 self-hosted runner.
|
||||
# For this reason, we disable the falco-driver-loader tests, which require kernel headers on the host.
|
||||
- name: Run regression tests
|
||||
env:
|
||||
# fixme(leogr): this is a workaround for https://github.com/falcosecurity/falco/issues/2784
|
||||
@@ -75,9 +71,7 @@ jobs:
|
||||
if ${{ inputs.static && 'false' || 'true' }}; then
|
||||
./build/falcoctl.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
./build/k8saudit.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
if ${{ inputs.arch == 'x86_64' && 'true' || 'false' }}; then
|
||||
sudo ./build/falco-driver-loader.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
fi
|
||||
sudo ./build/falco-driver-loader.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
fi
|
||||
cat ./report.txt | go-junit-report -set-exit-code > report.xml
|
||||
popd
|
||||
|
||||
@@ -34,8 +34,8 @@ else()
|
||||
# In case you want to test against another driver version (or branch, or commit) just pass the variable -
|
||||
# ie., `cmake -DDRIVER_VERSION=dev ..`
|
||||
if(NOT DRIVER_VERSION)
|
||||
set(DRIVER_VERSION "7cbc03a535ead9d530f7b77ffd68766d5e22da74")
|
||||
set(DRIVER_CHECKSUM "SHA256=94d110ad1738cce2635fd15d41701bea5e061fd9a5a4be3f2ee8ec7a28fe50cc")
|
||||
set(DRIVER_VERSION "000d576ef877cb115cbb56f97187a1d62221e2bd")
|
||||
set(DRIVER_CHECKSUM "SHA256=4f078e3e448ba1d4ca2eff55a361a9a9d048f3a967fb4d91f0c91aa6fa22d5d2")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
|
||||
@@ -26,17 +26,17 @@ if(FALCOSECURITY_LIBS_SOURCE_DIR)
|
||||
else()
|
||||
# FALCOSECURITY_LIBS_REPO accepts a repository name (<org name>/<repo name>) alternative to the falcosecurity/libs repository.
|
||||
# In case you want to test against a fork of falcosecurity/libs just pass the variable -
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_REPO=<your-gh-handle>/libs ..`
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_REPO=<your-gh-handle>/libs ..`
|
||||
if (NOT FALCOSECURITY_LIBS_REPO)
|
||||
set(FALCOSECURITY_LIBS_REPO "falcosecurity/libs")
|
||||
endif()
|
||||
|
||||
# FALCOSECURITY_LIBS_VERSION accepts a git reference (branch name, commit hash, or tag) to the falcosecurity/libs repository.
|
||||
# In case you want to test against another falcosecurity/libs version (or branch, or commit) just pass the variable -
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "7cbc03a535ead9d530f7b77ffd68766d5e22da74")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=94d110ad1738cce2635fd15d41701bea5e061fd9a5a4be3f2ee8ec7a28fe50cc")
|
||||
set(FALCOSECURITY_LIBS_VERSION "000d576ef877cb115cbb56f97187a1d62221e2bd")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=4f078e3e448ba1d4ca2eff55a361a9a9d048f3a967fb4d91f0c91aa6fa22d5d2")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
@@ -84,12 +84,10 @@ set(CREATE_TEST_TARGETS OFF CACHE BOOL "")
|
||||
set(BUILD_LIBSCAP_EXAMPLES OFF CACHE BOOL "")
|
||||
|
||||
set(USE_BUNDLED_TBB ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_B64 ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_JSONCPP ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_VALIJSON ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_RE2 ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_UTHASH ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_TINYDIR ON CACHE BOOL "")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${FALCOSECURITY_LIBS_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(LIBYAML_SRC "${PROJECT_BINARY_DIR}/libyaml-prefix/src/libyaml")
|
||||
set(LIBYAML_INSTALL_DIR "${LIBYAML_SRC}/target")
|
||||
message(STATUS "Using bundled libyaml in '${LIBYAML_SRC}'")
|
||||
set(LIBYAML_LIB "${LIBYAML_SRC}/src/.libs/libyaml.a")
|
||||
externalproject_add(
|
||||
libyaml
|
||||
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
|
||||
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
|
||||
CONFIGURE_COMMAND ./configure --prefix=${LIBYAML_INSTALL_DIR} CFLAGS=-fPIC CPPFLAGS=-fPIC --enable-static=true --enable-shared=false
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${LIBYAML_LIB}
|
||||
INSTALL_COMMAND ${CMD_MAKE} install
|
||||
)
|
||||
@@ -19,17 +19,26 @@ RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
bc \
|
||||
bison \
|
||||
ca-certificates \
|
||||
clang \
|
||||
curl \
|
||||
dkms \
|
||||
dwarves \
|
||||
flex \
|
||||
gcc \
|
||||
gcc-11 \
|
||||
gnupg2 \
|
||||
jq \
|
||||
libelf1 \
|
||||
libc6-dev \
|
||||
libelf-dev \
|
||||
libssl-dev \
|
||||
llvm \
|
||||
make \
|
||||
netcat-openbsd \
|
||||
patchelf \
|
||||
xz-utils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -s https://falco.org/repo/falcosecurity-packages.asc | apt-key add - \
|
||||
|
||||
24
falco.yaml
24
falco.yaml
@@ -917,13 +917,22 @@ syscall_event_drops:
|
||||
# number of CPUs to determine overall usage. Memory metrics are provided in raw
|
||||
# units (`kb` for `RSS`, `PSS` and `VSZ` or `bytes` for `container_memory_used`)
|
||||
# and can be uniformly converted to megabytes (MB) using the
|
||||
# `convert_memory_to_mb` functionality. In environments such as Kubernetes, it
|
||||
# is crucial to track Falco's container memory usage. To customize the path of
|
||||
# the memory metric file, you can create an environment variable named
|
||||
# `FALCO_CGROUP_MEM_PATH` and set it to the desired file path. By default, Falco
|
||||
# uses the file `/sys/fs/cgroup/memory/memory.usage_in_bytes` to monitor
|
||||
# container memory usage, which aligns with Kubernetes'
|
||||
# `container_memory_working_set_bytes` metric.
|
||||
# `convert_memory_to_mb` functionality. In environments such as Kubernetes when
|
||||
# deployed as daemonset, it is crucial to track Falco's container memory usage.
|
||||
# To customize the path of the memory metric file, you can create an environment
|
||||
# variable named `FALCO_CGROUP_MEM_PATH` and set it to the desired file path. By
|
||||
# default, Falco uses the file `/sys/fs/cgroup/memory/memory.usage_in_bytes` to
|
||||
# monitor container memory usage, which aligns with Kubernetes'
|
||||
# `container_memory_working_set_bytes` metric. Finally, we emit the overall host
|
||||
# CPU and memory usages, along with the total number of processes and open file
|
||||
# descriptors (fds) on the host, obtained from the proc file system unrelated to
|
||||
# Falco's monitoring. These metrics help assess Falco's usage in relation to the
|
||||
# server's workload intensity.
|
||||
#
|
||||
# `state_counters_enabled`: Emit counters related to Falco's state engine, including
|
||||
# added, removed threads or file descriptors (fds), and failed lookup, store, or
|
||||
# retrieve actions in relation to Falco's underlying process cache table (threadtable).
|
||||
# We also log the number of currently cached containers if applicable.
|
||||
#
|
||||
# `kernel_event_counters_enabled`: Emit kernel side event and drop counters, as
|
||||
# an alternative to `syscall_event_drops`, but with some differences. These
|
||||
@@ -956,6 +965,7 @@ metrics:
|
||||
output_rule: true
|
||||
# output_file: /tmp/falco_stats.jsonl
|
||||
resource_utilization_enabled: true
|
||||
state_counters_enabled: true
|
||||
kernel_event_counters_enabled: true
|
||||
libbpf_stats_enabled: true
|
||||
convert_memory_to_mb: true
|
||||
|
||||
@@ -68,6 +68,25 @@ if [ "$1" = "configure" ]; then
|
||||
esac
|
||||
fi
|
||||
clear
|
||||
else
|
||||
case $FALCO_DRIVER_CHOICE in
|
||||
module | kmod )
|
||||
chosen_driver="kmod"
|
||||
;;
|
||||
bpf | ebpf | eBPF )
|
||||
chosen_driver="bpf"
|
||||
;;
|
||||
modern-bpf | modern-ebpf | modern-eBPF )
|
||||
chosen_driver="modern-bpf"
|
||||
;;
|
||||
esac
|
||||
case $FALCOCTL_ENABLED in
|
||||
yes )
|
||||
;;
|
||||
no )
|
||||
systemctl --system mask falcoctl-artifact-follow.service || true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -67,6 +67,25 @@ if [ $1 -ge 1 ]; then
|
||||
esac
|
||||
fi
|
||||
clear
|
||||
else
|
||||
case $FALCO_DRIVER_CHOICE in
|
||||
module | kmod )
|
||||
chosen_driver="kmod"
|
||||
;;
|
||||
bpf | ebpf | eBPF )
|
||||
chosen_driver="bpf"
|
||||
;;
|
||||
modern-bpf | modern-ebpf | modern-eBPF )
|
||||
chosen_driver="modern-bpf"
|
||||
;;
|
||||
esac
|
||||
case $FALCOCTL_ENABLED in
|
||||
yes )
|
||||
;;
|
||||
no )
|
||||
systemctl --system mask falcoctl-artifact-follow.service || true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
Submodule submodules/falcosecurity-testing updated: 92c313f5ca...3e2d5e2abe
@@ -72,22 +72,3 @@ TEST(FalcoUtils, parse_prometheus_interval)
|
||||
*/
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("200"), 0UL);
|
||||
}
|
||||
|
||||
TEST(FalcoUtils, decode_url)
|
||||
{
|
||||
ASSERT_EQ(
|
||||
falco::utils::decode_uri("https://www.example.com?key1=value+1&key2=value%40%21%242&key3=value%253", true),
|
||||
"https://www.example.com?key1=value 1&key2=value@!$2&key3=value%3");
|
||||
|
||||
ASSERT_EQ(
|
||||
falco::utils::decode_uri("https://download.falco.org/?prefix=driver/3.0.1%2Bdriver/x86_64/", true),
|
||||
"https://download.falco.org/?prefix=driver/3.0.1+driver/x86_64/");
|
||||
|
||||
ASSERT_EQ(
|
||||
falco::utils::decode_uri("https://example.com/hello%20world", true),
|
||||
"https://example.com/hello world");
|
||||
|
||||
ASSERT_EQ(
|
||||
falco::utils::decode_uri("https://example.com/helloworld", true),
|
||||
"https://example.com/helloworld");
|
||||
}
|
||||
|
||||
@@ -37,17 +37,17 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST)
|
||||
{
|
||||
libsinsp::filter::ast::pos_info macro_pos(12, 85, 27);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> filter_and;
|
||||
filter_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
|
||||
filter_and.push_back(libsinsp::filter::ast::not_expr::create(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos)));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::and_expr::create(filter_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::and_expr::create(filter_and);
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_and;
|
||||
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
|
||||
expected_and.push_back(libsinsp::filter::ast::not_expr::create(clone(macro.get())));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected = std::move(libsinsp::filter::ast::and_expr::create(expected_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected = libsinsp::filter::ast::and_expr::create(expected_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -71,9 +71,9 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_single_node)
|
||||
{
|
||||
libsinsp::filter::ast::pos_info macro_pos(12, 85, 27);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -102,18 +102,18 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_multiple_macros)
|
||||
libsinsp::filter::ast::pos_info a_macro_pos(11, 75, 43);
|
||||
libsinsp::filter::ast::pos_info b_macro_pos(91, 21, 9);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = std::move(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro = std::move(libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists");
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro = libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists");
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> filter_or;
|
||||
filter_or.push_back(libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos));
|
||||
filter_or.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::or_expr::create(filter_or));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::or_expr::create(filter_or);
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_or;
|
||||
expected_or.push_back(clone(a_macro.get()));
|
||||
expected_or.push_back(clone(b_macro.get()));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = std::move(libsinsp::filter::ast::or_expr::create(expected_or));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = libsinsp::filter::ast::or_expr::create(expected_or);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_A_NAME, a_macro);
|
||||
@@ -149,17 +149,17 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_nested_macros)
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> a_macro_and;
|
||||
a_macro_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
a_macro_and.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = std::move(libsinsp::filter::ast::and_expr::create(a_macro_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::and_expr::create(a_macro_and);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro = std::move(
|
||||
libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro =
|
||||
libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists");
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_and;
|
||||
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = std::move(libsinsp::filter::ast::and_expr::create(expected_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = libsinsp::filter::ast::and_expr::create(expected_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_A_NAME, a_macro);
|
||||
@@ -196,7 +196,7 @@ TEST(MacroResolver, should_find_unknown_macros)
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> filter_and;
|
||||
filter_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
|
||||
filter_and.push_back(libsinsp::filter::ast::not_expr::create(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos)));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::and_expr::create(filter_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::and_expr::create(filter_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
ASSERT_FALSE(resolver.run(filter));
|
||||
@@ -214,9 +214,9 @@ TEST(MacroResolver, should_find_unknown_nested_macros)
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> a_macro_and;
|
||||
a_macro_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
a_macro_and.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = std::move(libsinsp::filter::ast::and_expr::create(a_macro_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::and_expr::create(a_macro_and);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
auto expected_filter = clone(a_macro.get());
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
@@ -237,9 +237,9 @@ TEST(MacroResolver, should_undefine_macro)
|
||||
libsinsp::filter::ast::pos_info macro_pos_1(12, 9, 3);
|
||||
libsinsp::filter::ast::pos_info macro_pos_2(9, 6, 3);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_1));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_2));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_1);
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_2);
|
||||
filter_macro_resolver resolver;
|
||||
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -262,8 +262,8 @@ TEST(MacroResolver, should_undefine_macro)
|
||||
TEST(MacroResolver, should_clone_macro_AST)
|
||||
{
|
||||
libsinsp::filter::ast::pos_info macro_pos(5, 2, 8888);
|
||||
std::shared_ptr<libsinsp::filter::ast::unary_check_expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::unary_check_expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos);
|
||||
filter_macro_resolver resolver;
|
||||
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
|
||||
@@ -195,7 +195,7 @@ std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_c
|
||||
// read rules YAML file and collect its definitions
|
||||
rule_loader::reader reader;
|
||||
if (reader.read(cfg, m_rule_collector))
|
||||
{
|
||||
{
|
||||
// compile the definitions (resolve macro/list refs, exceptions, ...)
|
||||
m_last_compile_output = std::make_unique<rule_loader::compiler::compile_output>();
|
||||
rule_loader::compiler().compile(cfg, m_rule_collector, *m_last_compile_output.get());
|
||||
@@ -384,7 +384,7 @@ libsinsp::events::set<ppm_sc_code> falco_engine::sc_codes_for_ruleset(const std:
|
||||
{
|
||||
return find_source(source)->ruleset->enabled_sc_codes(find_ruleset_id(ruleset));
|
||||
}
|
||||
|
||||
|
||||
libsinsp::events::set<ppm_event_code> falco_engine::event_codes_for_ruleset(const std::string &source, const std::string &ruleset)
|
||||
{
|
||||
return find_source(source)->ruleset->enabled_event_codes(find_ruleset_id(ruleset));
|
||||
@@ -505,17 +505,17 @@ std::size_t falco_engine::add_source(const std::string &source,
|
||||
return m_sources.insert(src, source);
|
||||
}
|
||||
|
||||
template <typename T> inline Json::Value sequence_to_json_array(const T& seq)
|
||||
template <typename T> inline nlohmann::json sequence_to_json_array(const T& seq)
|
||||
{
|
||||
Json::Value ret = Json::arrayValue;
|
||||
for (auto it = seq.begin(); it != seq.end(); it++)
|
||||
nlohmann::json ret = nlohmann::json::array();
|
||||
for (const auto& v : seq)
|
||||
{
|
||||
ret.append(*it);
|
||||
ret.push_back(v);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void falco_engine::describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins, bool json) const
|
||||
nlohmann::json falco_engine::describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
// use previously-loaded collector definitions and the compiled
|
||||
// output of rules, macros, and lists.
|
||||
@@ -524,103 +524,69 @@ void falco_engine::describe_rule(std::string *rule, const std::vector<std::share
|
||||
throw falco_exception("rules most be loaded before describing them");
|
||||
}
|
||||
|
||||
if(!json)
|
||||
{
|
||||
static const char *rule_fmt = "%-50s %s\n";
|
||||
fprintf(stdout, rule_fmt, "Rule", "Description");
|
||||
fprintf(stdout, rule_fmt, "----", "-----------");
|
||||
if(!rule)
|
||||
{
|
||||
for(auto &r : m_rules)
|
||||
{
|
||||
auto str = falco::utils::wrap_text(r.description, 51, 110) + "\n";
|
||||
fprintf(stdout, rule_fmt, r.name.c_str(), str.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto r = m_rules.at(*rule);
|
||||
if(r == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto str = falco::utils::wrap_text(r->description, 51, 110) + "\n";
|
||||
fprintf(stdout, rule_fmt, r->name.c_str(), str.c_str());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// use collected and compiled info to print a json output
|
||||
Json::FastWriter writer;
|
||||
std::string json_str;
|
||||
nlohmann::json output;
|
||||
if(!rule)
|
||||
{
|
||||
// In this case we build json information about
|
||||
// all rules, macros and lists
|
||||
Json::Value output;
|
||||
|
||||
// Store required engine version
|
||||
auto required_engine_version = m_rule_collector.required_engine_version();
|
||||
output["required_engine_version"] = required_engine_version.version.as_string();
|
||||
|
||||
// Store required plugin versions
|
||||
Json::Value plugin_versions = Json::arrayValue;
|
||||
nlohmann::json plugin_versions = nlohmann::json::array();
|
||||
auto required_plugin_versions = m_rule_collector.required_plugin_versions();
|
||||
for(const auto& req : required_plugin_versions)
|
||||
{
|
||||
Json::Value r;
|
||||
nlohmann::json r;
|
||||
r["name"] = req.at(0).name;
|
||||
r["version"] = req.at(0).version;
|
||||
|
||||
Json::Value alternatives = Json::arrayValue;
|
||||
nlohmann::json alternatives = nlohmann::json::array();
|
||||
for(size_t i = 1; i < req.size(); i++)
|
||||
{
|
||||
Json::Value alternative;
|
||||
nlohmann::json alternative;
|
||||
alternative["name"] = req[i].name;
|
||||
alternative["version"] = req[i].version;
|
||||
alternatives.append(alternative);
|
||||
alternatives.push_back(std::move(alternative));
|
||||
}
|
||||
r["alternatives"] = alternatives;
|
||||
|
||||
plugin_versions.append(r);
|
||||
r["alternatives"] = std::move(alternatives);
|
||||
|
||||
plugin_versions.push_back(std::move(r));
|
||||
}
|
||||
output["required_plugin_versions"] = plugin_versions;
|
||||
output["required_plugin_versions"] = std::move(plugin_versions);
|
||||
|
||||
// Store information about rules
|
||||
Json::Value rules_array = Json::arrayValue;
|
||||
nlohmann::json rules_array = nlohmann::json::array();
|
||||
for(const auto& r : m_last_compile_output->rules)
|
||||
{
|
||||
auto info = m_rule_collector.rules().at(r.name);
|
||||
Json::Value rule;
|
||||
nlohmann::json rule;
|
||||
get_json_details(rule, r, *info, plugins);
|
||||
rules_array.append(rule);
|
||||
rules_array.push_back(std::move(rule));
|
||||
}
|
||||
output["rules"] = rules_array;
|
||||
|
||||
output["rules"] = std::move(rules_array);
|
||||
|
||||
// Store information about macros
|
||||
Json::Value macros_array = Json::arrayValue;
|
||||
nlohmann::json macros_array = nlohmann::json::array();
|
||||
for(const auto &m : m_last_compile_output->macros)
|
||||
{
|
||||
auto info = m_rule_collector.macros().at(m.name);
|
||||
Json::Value macro;
|
||||
nlohmann::json macro;
|
||||
get_json_details(macro, m, *info, plugins);
|
||||
macros_array.append(macro);
|
||||
macros_array.push_back(std::move(macro));
|
||||
}
|
||||
output["macros"] = macros_array;
|
||||
output["macros"] = std::move(macros_array);
|
||||
|
||||
// Store information about lists
|
||||
Json::Value lists_array = Json::arrayValue;
|
||||
// Store information about lists
|
||||
nlohmann::json lists_array = nlohmann::json::array();
|
||||
for(const auto &l : m_last_compile_output->lists)
|
||||
{
|
||||
auto info = m_rule_collector.lists().at(l.name);
|
||||
Json::Value list;
|
||||
nlohmann::json list;
|
||||
get_json_details(list, l, *info, plugins);
|
||||
lists_array.append(list);
|
||||
lists_array.push_back(std::move(list));
|
||||
}
|
||||
output["lists"] = lists_array;
|
||||
|
||||
json_str = writer.write(output);
|
||||
output["lists"] = std::move(lists_array);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -631,21 +597,24 @@ void falco_engine::describe_rule(std::string *rule, const std::vector<std::share
|
||||
throw falco_exception("Rule \"" + *rule + "\" is not loaded");
|
||||
}
|
||||
auto r = m_rules.at(ri->name);
|
||||
Json::Value rule;
|
||||
|
||||
nlohmann::json rule;
|
||||
get_json_details(rule, *r, *ri, plugins);
|
||||
json_str = writer.write(rule);
|
||||
nlohmann::json rules_array = nlohmann::json::array();
|
||||
rules_array.push_back(std::move(rule));
|
||||
output["rules"] = std::move(rules_array);
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s", json_str.c_str());
|
||||
return output;
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(
|
||||
Json::Value &out,
|
||||
nlohmann::json &out,
|
||||
const falco_rule &r,
|
||||
const rule_loader::rule_info &info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value rule_info;
|
||||
nlohmann::json rule_info;
|
||||
|
||||
// Fill general rule information
|
||||
rule_info["name"] = r.name;
|
||||
@@ -656,7 +625,7 @@ void falco_engine::get_json_details(
|
||||
rule_info["enabled"] = info.enabled;
|
||||
rule_info["source"] = r.source;
|
||||
rule_info["tags"] = sequence_to_json_array(info.tags);
|
||||
out["info"] = rule_info;
|
||||
out["info"] = std::move(rule_info);
|
||||
|
||||
// Parse rule condition and build the non-compiled AST
|
||||
// Assumption: no error because rules have already been loaded.
|
||||
@@ -665,7 +634,7 @@ void falco_engine::get_json_details(
|
||||
// get details related to the condition's filter
|
||||
filter_details details;
|
||||
filter_details compiled_details;
|
||||
Json::Value json_details;
|
||||
nlohmann::json json_details;
|
||||
for(const auto &m : m_rule_collector.macros())
|
||||
{
|
||||
details.known_macros.insert(m.name);
|
||||
@@ -720,15 +689,15 @@ void falco_engine::get_json_details(
|
||||
else
|
||||
{
|
||||
exception_operators.insert(e.comps.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
out["details"]["exception_names"] = sequence_to_json_array(exception_names);
|
||||
out["details"]["exception_operators"] = sequence_to_json_array(exception_operators);
|
||||
|
||||
// Store event types
|
||||
Json::Value events;
|
||||
nlohmann::json events;
|
||||
get_json_evt_types(events, info.source, r.condition.get());
|
||||
out["details"]["events"] = events;
|
||||
out["details"]["events"] = std::move(events);
|
||||
|
||||
// Store compiled condition and output
|
||||
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(r.condition.get());
|
||||
@@ -739,25 +708,25 @@ void falco_engine::get_json_details(
|
||||
// - The fields used in the rule's condition, output, and exceptions
|
||||
// - The evt types used in the rule's condition checks, that can potentially
|
||||
// match plugin-provided async events
|
||||
Json::Value used_plugins;
|
||||
nlohmann::json used_plugins;
|
||||
// note: making a union of conditions's and output's fields
|
||||
// note: the condition's AST accounts for all the resolved refs and exceptions
|
||||
compiled_details.fields.insert(out_fields.begin(), out_fields.end());
|
||||
get_json_used_plugins(used_plugins, info.source, compiled_details.evtnames, compiled_details.fields, plugins);
|
||||
out["details"]["plugins"] = used_plugins;
|
||||
out["details"]["plugins"] = std::move(used_plugins);
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_macro& m,
|
||||
const rule_loader::macro_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value macro_info;
|
||||
nlohmann::json macro_info;
|
||||
|
||||
macro_info["name"] = m.name;
|
||||
macro_info["condition"] = info.cond;
|
||||
out["info"] = macro_info;
|
||||
out["info"] = std::move(macro_info);
|
||||
|
||||
// Parse the macro condition and build the non-compiled AST
|
||||
// Assumption: no exception because rules have already been loaded.
|
||||
@@ -766,7 +735,7 @@ void falco_engine::get_json_details(
|
||||
// get details related to the condition's filter
|
||||
filter_details details;
|
||||
filter_details compiled_details;
|
||||
Json::Value json_details;
|
||||
nlohmann::json json_details;
|
||||
for(const auto &m : m_rule_collector.macros())
|
||||
{
|
||||
details.known_macros.insert(m.name);
|
||||
@@ -787,9 +756,9 @@ void falco_engine::get_json_details(
|
||||
out["details"]["condition_fields"] = sequence_to_json_array(compiled_details.fields);
|
||||
|
||||
// Store event types
|
||||
Json::Value events;
|
||||
nlohmann::json events;
|
||||
get_json_evt_types(events, "", m.condition.get());
|
||||
out["details"]["events"] = events;
|
||||
out["details"]["events"] = std::move(events);
|
||||
|
||||
// Store compiled condition
|
||||
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(m.condition.get());
|
||||
@@ -800,20 +769,20 @@ void falco_engine::get_json_details(
|
||||
// if a macro uses a plugin's field, we can't be sure which plugin actually
|
||||
// is used until we resolve the macro ref in a rule providing a source for
|
||||
// disambiguation.
|
||||
out["details"]["plugins"] = Json::arrayValue;
|
||||
out["details"]["plugins"] = nlohmann::json::array();
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_list& l,
|
||||
const rule_loader::list_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value list_info;
|
||||
nlohmann::json list_info;
|
||||
list_info["name"] = l.name;
|
||||
|
||||
// note: the syntactic definitions still has the list refs unresolved
|
||||
Json::Value items = Json::arrayValue;
|
||||
nlohmann::json items = nlohmann::json::array();
|
||||
std::unordered_set<std::string> lists;
|
||||
for(const auto &i : info.items)
|
||||
{
|
||||
@@ -825,19 +794,19 @@ void falco_engine::get_json_details(
|
||||
lists.insert(i);
|
||||
continue;
|
||||
}
|
||||
items.append(i);
|
||||
items.push_back(std::move(i));
|
||||
}
|
||||
|
||||
list_info["items"] = items;
|
||||
out["info"] = list_info;
|
||||
list_info["items"] = std::move(items);
|
||||
out["info"] = std::move(list_info);
|
||||
out["details"]["used"] = l.used;
|
||||
out["details"]["lists"] = sequence_to_json_array(lists);
|
||||
out["details"]["items_compiled"] = sequence_to_json_array(l.items);
|
||||
out["details"]["plugins"] = Json::arrayValue; // always empty
|
||||
out["details"]["plugins"] = nlohmann::json::array(); // always empty
|
||||
}
|
||||
|
||||
void falco_engine::get_json_evt_types(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
libsinsp::filter::ast::expr* ast) const
|
||||
{
|
||||
@@ -860,7 +829,7 @@ void falco_engine::get_json_evt_types(
|
||||
}
|
||||
|
||||
void falco_engine::get_json_used_plugins(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
const std::unordered_set<std::string>& evtnames,
|
||||
const std::unordered_set<std::string>& fields,
|
||||
@@ -869,14 +838,17 @@ void falco_engine::get_json_used_plugins(
|
||||
// note: condition and output fields may have an argument, so
|
||||
// we need to isolate the field names
|
||||
std::unordered_set<std::string> fieldnames;
|
||||
for (auto f: fields)
|
||||
for (const auto &f: fields)
|
||||
{
|
||||
auto argpos = f.find('[');
|
||||
if (argpos != std::string::npos)
|
||||
{
|
||||
f = f.substr(0, argpos);
|
||||
fieldnames.insert(f.substr(0, argpos));
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldnames.insert(f);
|
||||
}
|
||||
fieldnames.insert(f);
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> used_plugins;
|
||||
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
// Print details on the given rule. If rule is NULL, print
|
||||
// details on all rules.
|
||||
//
|
||||
void describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins, bool json) const;
|
||||
nlohmann::json describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
|
||||
//
|
||||
// Print statistics on how many events matched each rule.
|
||||
@@ -315,26 +315,26 @@ private:
|
||||
|
||||
// Retrieve json details from rules, macros, lists
|
||||
void get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_rule& r,
|
||||
const rule_loader::rule_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_macro& m,
|
||||
const rule_loader::macro_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_list& l,
|
||||
const rule_loader::list_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_evt_types(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
libsinsp::filter::ast::expr* ast) const;
|
||||
void get_json_used_plugins(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
const std::unordered_set<std::string>& evttypes,
|
||||
const std::unordered_set<std::string>& fields,
|
||||
|
||||
@@ -20,7 +20,7 @@ limitations under the License.
|
||||
|
||||
// The version of this Falco engine
|
||||
#define FALCO_ENGINE_VERSION_MAJOR 0
|
||||
#define FALCO_ENGINE_VERSION_MINOR 27
|
||||
#define FALCO_ENGINE_VERSION_MINOR 28
|
||||
#define FALCO_ENGINE_VERSION_PATCH 0
|
||||
|
||||
#define FALCO_ENGINE_VERSION \
|
||||
@@ -34,4 +34,4 @@ limitations under the License.
|
||||
// It represents the fields supported by this version of Falco,
|
||||
// the event types, and the underlying driverevent schema. It's used to
|
||||
// detetect changes in engine version in our CI jobs.
|
||||
#define FALCO_ENGINE_CHECKSUM "dbc34e88ab420320994d85f155dee6baff2dd018aacc00e249f897edc8b1e0f4"
|
||||
#define FALCO_ENGINE_CHECKSUM "5d488b68856d70300ae37453295383821822d8423af170eb28e1bef52042f0b3"
|
||||
|
||||
@@ -20,7 +20,6 @@ limitations under the License.
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
|
||||
#include "falco_common.h"
|
||||
#include "falco_utils.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -161,80 +160,6 @@ void readfile(const std::string& filename, std::string& data)
|
||||
return;
|
||||
}
|
||||
|
||||
// URI-decodes the given string by replacing percent-encoded
|
||||
// characters with the actual character. Returns the decoded string.
|
||||
//
|
||||
// When plus_as_space is true, non-encoded plus signs in the query are decoded as spaces.
|
||||
// (http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1)
|
||||
std::string decode_uri(const std::string& str, bool plus_as_space)
|
||||
{
|
||||
std::string decoded_str;
|
||||
bool in_query = false;
|
||||
std::string::const_iterator it = str.begin();
|
||||
std::string::const_iterator end = str.end();
|
||||
while(it != end)
|
||||
{
|
||||
char c = *it++;
|
||||
if(c == '?')
|
||||
{
|
||||
in_query = true;
|
||||
}
|
||||
// spaces may be encoded as plus signs in the query
|
||||
if(in_query && plus_as_space && c == '+')
|
||||
{
|
||||
c = ' ';
|
||||
}
|
||||
else if(c == '%')
|
||||
{
|
||||
if (it == end)
|
||||
{
|
||||
throw falco_exception("URI encoding: no hex digit following percent sign in " + str);
|
||||
}
|
||||
char hi = *it++;
|
||||
if (it == end)
|
||||
{
|
||||
throw falco_exception("URI encoding: two hex digits must follow percent sign in " + str);
|
||||
}
|
||||
char lo = *it++;
|
||||
if (hi >= '0' && hi <= '9')
|
||||
{
|
||||
c = hi - '0';
|
||||
}
|
||||
else if (hi >= 'A' && hi <= 'F')
|
||||
{
|
||||
c = hi - 'A' + 10;
|
||||
}
|
||||
else if (hi >= 'a' && hi <= 'f')
|
||||
{
|
||||
c = hi - 'a' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw falco_exception("URI encoding: not a hex digit found in " + str);
|
||||
}
|
||||
c *= 16;
|
||||
if (lo >= '0' && lo <= '9')
|
||||
{
|
||||
c += lo - '0';
|
||||
}
|
||||
else if (lo >= 'A' && lo <= 'F')
|
||||
{
|
||||
c += lo - 'A' + 10;
|
||||
}
|
||||
else if (lo >= 'a' && lo <= 'f')
|
||||
{
|
||||
c += lo - 'a' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw falco_exception("URI encoding: not a hex digit");
|
||||
}
|
||||
}
|
||||
decoded_str += c;
|
||||
}
|
||||
return decoded_str;
|
||||
}
|
||||
|
||||
namespace network
|
||||
{
|
||||
bool is_unix_scheme(const std::string& url)
|
||||
|
||||
@@ -52,8 +52,6 @@ void readfile(const std::string& filename, std::string& data);
|
||||
|
||||
uint32_t hardware_concurrency();
|
||||
|
||||
std::string decode_uri(const std::string& str, bool plus_as_space);
|
||||
|
||||
namespace network
|
||||
{
|
||||
static const std::string UNIX_SCHEME("unix://");
|
||||
|
||||
@@ -22,12 +22,12 @@ limitations under the License.
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
struct filter_details
|
||||
struct filter_details
|
||||
{
|
||||
// input macros and lists
|
||||
std::unordered_set<std::string> known_macros;
|
||||
std::unordered_set<std::string> known_lists;
|
||||
|
||||
|
||||
// output details
|
||||
std::unordered_set<std::string> fields;
|
||||
std::unordered_set<std::string> macros;
|
||||
@@ -47,25 +47,23 @@ public:
|
||||
/*!
|
||||
\brief Visits a filter AST and stores details about macros, lists,
|
||||
fields and operators used.
|
||||
\param filter The filter AST to be processed.
|
||||
\param details Helper structure used to state known macros and
|
||||
\param filter The filter AST to be processed.
|
||||
\param details Helper structure used to state known macros and
|
||||
lists on input, and to store all the retrieved details as output.
|
||||
*/
|
||||
void run(libsinsp::filter::ast::expr* filter,
|
||||
filter_details& details);
|
||||
|
||||
|
||||
private:
|
||||
struct visitor : public libsinsp::filter::ast::expr_visitor
|
||||
{
|
||||
visitor(filter_details& details) :
|
||||
visitor(filter_details& details) :
|
||||
m_details(details),
|
||||
m_expect_list(false),
|
||||
m_expect_macro(false),
|
||||
m_expect_evtname(false) {}
|
||||
visitor(visitor&&) = default;
|
||||
visitor& operator = (visitor&&) = default;
|
||||
visitor(const visitor&) = delete;
|
||||
visitor& operator = (const visitor&) = delete;
|
||||
|
||||
void visit(libsinsp::filter::ast::and_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::or_expr* e) override;
|
||||
|
||||
@@ -61,7 +61,7 @@ class filter_macro_resolver
|
||||
|
||||
/*!
|
||||
\brief used in get_{resolved,unknown}_macros and get_errors
|
||||
to represent an identifier/string value along with an AST position.
|
||||
to represent an identifier/string value along with an AST position.
|
||||
*/
|
||||
typedef std::pair<std::string,libsinsp::filter::ast::pos_info> value_info;
|
||||
|
||||
@@ -103,10 +103,6 @@ class filter_macro_resolver
|
||||
m_unknown_macros(unknown_macros),
|
||||
m_resolved_macros(resolved_macros),
|
||||
m_macros(macros) {}
|
||||
visitor(visitor&&) = default;
|
||||
visitor& operator = (visitor&&) = default;
|
||||
visitor(const visitor&) = delete;
|
||||
visitor& operator = (const visitor&) = delete;
|
||||
|
||||
std::vector<std::string> m_macros_path;
|
||||
std::unique_ptr<libsinsp::filter::ast::expr> m_node_substitute;
|
||||
|
||||
@@ -562,10 +562,8 @@ rule_loader::rule_load_exception::~rule_load_exception()
|
||||
{
|
||||
}
|
||||
|
||||
const char* rule_loader::rule_load_exception::what()
|
||||
const char* rule_loader::rule_load_exception::what() const noexcept
|
||||
{
|
||||
errstr = falco::load_result::error_code_str(ec) + ": "
|
||||
+ msg.c_str();
|
||||
|
||||
return errstr.c_str();
|
||||
// const + noexcept: can't use functions that change the object or throw
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
@@ -209,18 +209,12 @@ namespace rule_loader
|
||||
public:
|
||||
rule_load_exception(falco::load_result::error_code ec, const std::string& msg, const context& ctx);
|
||||
virtual ~rule_load_exception();
|
||||
rule_load_exception(rule_load_exception&&) = default;
|
||||
rule_load_exception& operator = (rule_load_exception&&) = default;
|
||||
rule_load_exception(const rule_load_exception&) = default;
|
||||
rule_load_exception& operator = (const rule_load_exception&) = default;
|
||||
|
||||
const char* what();
|
||||
const char* what() const noexcept override;
|
||||
|
||||
falco::load_result::error_code ec;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
|
||||
std::string errstr;
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -278,10 +272,6 @@ namespace rule_loader
|
||||
{
|
||||
res.reset(new result(name));
|
||||
}
|
||||
configuration(configuration&&) = default;
|
||||
configuration& operator = (configuration&&) = default;
|
||||
configuration(const configuration&) = delete;
|
||||
configuration& operator = (const configuration&) = delete;
|
||||
|
||||
// inputs
|
||||
const std::string& content;
|
||||
|
||||
@@ -50,12 +50,6 @@ static void paren_item(std::string& e)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_operator_defined(const std::string& op)
|
||||
{
|
||||
auto ops = libsinsp::filter::parser::supported_operators();
|
||||
return find(ops.begin(), ops.end(), op) != ops.end();
|
||||
}
|
||||
|
||||
static inline bool is_operator_for_list(const std::string& op)
|
||||
{
|
||||
auto ops = libsinsp::filter::parser::supported_operators(true);
|
||||
@@ -83,12 +77,12 @@ static void build_rule_exception_infos(
|
||||
std::string& condition)
|
||||
{
|
||||
std::string tmp;
|
||||
for (auto &ex : exceptions)
|
||||
for (const auto &ex : exceptions)
|
||||
{
|
||||
std::string icond;
|
||||
if(!ex.fields.is_list)
|
||||
{
|
||||
for (auto &val : ex.values)
|
||||
for (const auto &val : ex.values)
|
||||
{
|
||||
THROW(val.is_list,
|
||||
"Expected values array to contain a list of strings",
|
||||
@@ -107,7 +101,7 @@ static void build_rule_exception_infos(
|
||||
else
|
||||
{
|
||||
icond = "(";
|
||||
for (auto &values : ex.values)
|
||||
for (const auto &values : ex.values)
|
||||
{
|
||||
THROW(ex.fields.items.size() != values.items.size(),
|
||||
"Fields and values lists must have equal length",
|
||||
@@ -116,13 +110,13 @@ static void build_rule_exception_infos(
|
||||
icond += "(";
|
||||
uint32_t k = 0;
|
||||
std::string istr;
|
||||
for (auto &field : ex.fields.items)
|
||||
for (const auto &field : ex.fields.items)
|
||||
{
|
||||
icond += k == 0 ? "" : " and ";
|
||||
if (values.items[k].is_list)
|
||||
{
|
||||
istr = "(";
|
||||
for (auto &v : values.items[k].items)
|
||||
for (const auto &v : values.items[k].items)
|
||||
{
|
||||
tmp = v.item;
|
||||
quote_item(tmp);
|
||||
@@ -212,7 +206,7 @@ static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
}
|
||||
// create substitution string by concatenating all values
|
||||
std::string sub = "";
|
||||
for (auto &v : list.items)
|
||||
for (const auto &v : list.items)
|
||||
{
|
||||
if (!sub.empty())
|
||||
{
|
||||
@@ -262,7 +256,7 @@ static void resolve_macros(
|
||||
const rule_loader::context &ctx)
|
||||
{
|
||||
filter_macro_resolver macro_resolver;
|
||||
for (auto &m : infos)
|
||||
for (const auto &m : infos)
|
||||
{
|
||||
if (m.index < visibility)
|
||||
{
|
||||
@@ -287,7 +281,7 @@ static void resolve_macros(
|
||||
THROW(true, errmsg, cond_ctx);
|
||||
}
|
||||
|
||||
for (auto &it : macro_resolver.get_resolved_macros())
|
||||
for (const auto &it : macro_resolver.get_resolved_macros())
|
||||
{
|
||||
macros.at(it.first)->used = true;
|
||||
}
|
||||
@@ -346,13 +340,13 @@ void rule_loader::compiler::compile_list_infos(
|
||||
indexed_vector<falco_list>& out) const
|
||||
{
|
||||
std::string tmp;
|
||||
std::vector<std::string> used;
|
||||
for (auto &list : col.lists())
|
||||
std::list<std::string> used;
|
||||
falco_list v;
|
||||
for (const auto &list : col.lists())
|
||||
{
|
||||
falco_list v;
|
||||
v.name = list.name;
|
||||
v.items.clear();
|
||||
for (auto &item : list.items)
|
||||
for (const auto &item : list.items)
|
||||
{
|
||||
const auto ref = col.lists().at(item);
|
||||
if (ref && ref->index < list.visibility)
|
||||
@@ -375,7 +369,7 @@ void rule_loader::compiler::compile_list_infos(
|
||||
auto list_id = out.insert(v, v.name);
|
||||
out.at(list_id)->id = list_id;
|
||||
}
|
||||
for (auto &v : used)
|
||||
for (const auto &v : used)
|
||||
{
|
||||
out.at(v)->used = true;
|
||||
}
|
||||
@@ -388,7 +382,7 @@ void rule_loader::compiler::compile_macros_infos(
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& out) const
|
||||
{
|
||||
for (auto &m : col.macros())
|
||||
for (const auto &m : col.macros())
|
||||
{
|
||||
falco_macro entry;
|
||||
entry.name = m.name;
|
||||
@@ -422,7 +416,7 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
std::string err, condition;
|
||||
std::set<falco::load_result::load_result::warning_code> warn_codes;
|
||||
filter_warning_resolver warn_resolver;
|
||||
for (auto &r : col.rules())
|
||||
for (const auto &r : col.rules())
|
||||
{
|
||||
// skip the rule if it has an unknown source
|
||||
if (r.unknown_source)
|
||||
@@ -453,7 +447,7 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
warn_codes.clear();
|
||||
if (warn_resolver.run(rule.condition.get(), warn_codes))
|
||||
{
|
||||
for (auto &w : warn_codes)
|
||||
for (const auto &w : warn_codes)
|
||||
{
|
||||
cfg.res->add_warning(w, "", r.ctx);
|
||||
}
|
||||
@@ -555,7 +549,7 @@ void rule_loader::compiler::compile(
|
||||
}
|
||||
|
||||
// print info on any dangling lists or macros that were not used anywhere
|
||||
for (auto &m : out.macros)
|
||||
for (const auto &m : out.macros)
|
||||
{
|
||||
if (!m.used)
|
||||
{
|
||||
@@ -565,7 +559,7 @@ void rule_loader::compiler::compile(
|
||||
macro_info_from_name(col, m.name)->ctx);
|
||||
}
|
||||
}
|
||||
for (auto &l : out.lists)
|
||||
for (const auto &l : out.lists)
|
||||
{
|
||||
if (!l.used)
|
||||
{
|
||||
|
||||
@@ -35,10 +35,6 @@ class stats_manager
|
||||
public:
|
||||
stats_manager();
|
||||
virtual ~stats_manager();
|
||||
stats_manager(stats_manager&&) = default;
|
||||
stats_manager& operator = (stats_manager&&) = default;
|
||||
stats_manager(const stats_manager&) = default;
|
||||
stats_manager& operator = (const stats_manager&) = default;
|
||||
|
||||
/*!
|
||||
\brief Erases the internal state and statistics data
|
||||
|
||||
@@ -36,6 +36,7 @@ set(
|
||||
app/actions/print_generated_gvisor_config.cpp
|
||||
app/actions/print_help.cpp
|
||||
app/actions/print_ignored_events.cpp
|
||||
app/actions/print_kernel_version.cpp
|
||||
app/actions/print_plugin_info.cpp
|
||||
app/actions/print_support.cpp
|
||||
app/actions/print_syscall_events.cpp
|
||||
|
||||
@@ -41,6 +41,7 @@ falco::app::run_result load_rules_files(falco::app::state& s);
|
||||
falco::app::run_result print_generated_gvisor_config(falco::app::state& s);
|
||||
falco::app::run_result print_help(falco::app::state& s);
|
||||
falco::app::run_result print_ignored_events(falco::app::state& s);
|
||||
falco::app::run_result print_kernel_version(falco::app::state& s);
|
||||
falco::app::run_result print_page_size(falco::app::state& s);
|
||||
falco::app::run_result print_plugin_info(falco::app::state& s);
|
||||
falco::app::run_result print_support(falco::app::state& s);
|
||||
|
||||
@@ -20,14 +20,6 @@ limitations under the License.
|
||||
#include <sys/stat.h>
|
||||
#include <filesystem>
|
||||
|
||||
#ifndef CPPPATH_SEP
|
||||
#ifdef _MSC_VER
|
||||
#define CPPPATH_SEP "\\"
|
||||
#else
|
||||
#define CPPPATH_SEP "/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ limitations under the License.
|
||||
#include "../state.h"
|
||||
#include "../run_result.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace falco {
|
||||
namespace app {
|
||||
namespace actions {
|
||||
@@ -29,6 +31,8 @@ void print_enabled_event_sources(falco::app::state& s);
|
||||
void activate_interesting_kernel_tracepoints(falco::app::state& s, std::unique_ptr<sinsp>& inspector);
|
||||
void check_for_ignored_events(falco::app::state& s);
|
||||
void format_plugin_info(std::shared_ptr<sinsp_plugin> p, std::ostream& os);
|
||||
void format_described_rules_as_text(const nlohmann::json& v, std::ostream& os);
|
||||
|
||||
falco::app::run_result open_offline_inspector(falco::app::state& s);
|
||||
falco::app::run_result open_live_inspector(
|
||||
falco::app::state& s,
|
||||
|
||||
@@ -16,6 +16,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
#include "helpers.h"
|
||||
#include "falco_utils.h"
|
||||
#include <plugin_manager.h>
|
||||
|
||||
#include <unordered_set>
|
||||
@@ -126,3 +127,22 @@ void falco::app::actions::format_plugin_info(std::shared_ptr<sinsp_plugin> p, st
|
||||
os << " - Async Events" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void format_two_columns(std::ostream& os, const std::string& l, const std::string& r)
|
||||
{
|
||||
static constexpr const int s_max_line_len = 4096;
|
||||
char buf[s_max_line_len];
|
||||
snprintf(buf, sizeof(buf) - 1, "%-50s %s", l.c_str(), r.c_str());
|
||||
os << buf << std::endl;
|
||||
}
|
||||
|
||||
void falco::app::actions::format_described_rules_as_text(const nlohmann::json& v, std::ostream& os)
|
||||
{
|
||||
format_two_columns(os, "Rule", "Description");
|
||||
format_two_columns(os, "----", "-----------");
|
||||
for(const auto &r : v["rules"])
|
||||
{
|
||||
auto str = falco::utils::wrap_text(r["info"]["description"], 51, 110) + "\n";
|
||||
format_two_columns(os, r["info"]["name"], str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,11 @@ falco::app::run_result falco::app::actions::open_live_inspector(
|
||||
{
|
||||
try
|
||||
{
|
||||
if((s.config->m_metrics_flags & PPM_SCAP_STATS_STATE_COUNTERS))
|
||||
{
|
||||
inspector->set_sinsp_stats_v2_enabled();
|
||||
}
|
||||
|
||||
if (source != falco_common::syscall_source) /* Plugin engine */
|
||||
{
|
||||
for (const auto& p: inspector->get_plugin_manager()->plugins())
|
||||
|
||||
@@ -155,17 +155,22 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
|
||||
s.engine->enable_rule_by_tag(s.options.enabled_rule_tags, true);
|
||||
}
|
||||
|
||||
if (s.options.describe_all_rules)
|
||||
// printout of `-L` option
|
||||
if (s.options.describe_all_rules || !s.options.describe_rule.empty())
|
||||
{
|
||||
std::string* rptr = !s.options.describe_rule.empty() ? &(s.options.describe_rule) : nullptr;
|
||||
const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins();
|
||||
s.engine->describe_rule(NULL, plugins, s.config->m_json_output);
|
||||
return run_result::exit();
|
||||
}
|
||||
auto out = s.engine->describe_rule(rptr, plugins);
|
||||
|
||||
if (!s.config->m_json_output)
|
||||
{
|
||||
format_described_rules_as_text(out, std::cout);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << out.dump() << std::endl;
|
||||
}
|
||||
|
||||
if (!s.options.describe_rule.empty())
|
||||
{
|
||||
const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins();
|
||||
s.engine->describe_rule(&(s.options.describe_rule), plugins, s.config->m_json_output);
|
||||
return run_result::exit();
|
||||
}
|
||||
|
||||
|
||||
49
userspace/falco/app/actions/print_kernel_version.cpp
Normal file
49
userspace/falco/app/actions/print_kernel_version.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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.
|
||||
*/
|
||||
|
||||
#include "actions.h"
|
||||
#include "helpers.h"
|
||||
#include "../app.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <errno.h>
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::print_kernel_version(falco::app::state& s)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// We print this info only when a kernel driver is injected
|
||||
if(s.is_modern_ebpf() || s.is_ebpf() || s.is_kmod())
|
||||
{
|
||||
std::ifstream input_file("/proc/version");
|
||||
if(!input_file.is_open())
|
||||
{
|
||||
// We don't want to fail, we just need to log something
|
||||
falco_logger::log(falco_logger::level::INFO, "Cannot read under '/proc/version' (err_message: '" + std::string(strerror(errno)) + "', err_code: " + std::to_string(errno) + "). No info provided, go on.");
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
std::stringstream buffer;
|
||||
buffer << input_file.rdbuf();
|
||||
std::string contents(buffer.str());
|
||||
falco_logger::log(falco_logger::level::INFO, "System info: " + contents);
|
||||
}
|
||||
#endif
|
||||
return run_result::ok();
|
||||
}
|
||||
@@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "actions.h"
|
||||
#include "../../versions_info.h"
|
||||
|
||||
|
||||
@@ -45,16 +45,12 @@ class source_sync_context
|
||||
public:
|
||||
source_sync_context(falco::semaphore& s)
|
||||
: m_finished(false), m_joined(false), m_semaphore(s) { }
|
||||
source_sync_context(source_sync_context&&) = default;
|
||||
source_sync_context& operator = (source_sync_context&&) = default;
|
||||
source_sync_context(const source_sync_context&) = delete;
|
||||
source_sync_context& operator = (const source_sync_context&) = delete;
|
||||
|
||||
inline void finish()
|
||||
{
|
||||
bool v = false;
|
||||
while (!m_finished.compare_exchange_weak(
|
||||
v, true,
|
||||
v, true,
|
||||
std::memory_order_seq_cst,
|
||||
std::memory_order_seq_cst))
|
||||
{
|
||||
@@ -70,7 +66,7 @@ public:
|
||||
{
|
||||
bool v = false;
|
||||
while (!m_joined.compare_exchange_weak(
|
||||
v, true,
|
||||
v, true,
|
||||
std::memory_order_seq_cst,
|
||||
std::memory_order_seq_cst))
|
||||
{
|
||||
@@ -90,7 +86,7 @@ public:
|
||||
{
|
||||
return m_finished.load(std::memory_order_seq_cst);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// set to true when the event processing loop finishes
|
||||
std::atomic<bool> m_finished;
|
||||
@@ -102,12 +98,6 @@ private:
|
||||
|
||||
struct live_context
|
||||
{
|
||||
live_context() = default;
|
||||
live_context(live_context&&) = default;
|
||||
live_context& operator = (live_context&&) = default;
|
||||
live_context(const live_context&) = default;
|
||||
live_context& operator = (const live_context&) = default;
|
||||
|
||||
// the name of the source of which events are processed
|
||||
std::string source;
|
||||
// the result of the event processing loop
|
||||
@@ -269,7 +259,7 @@ static falco::app::run_result do_inspect(
|
||||
}
|
||||
return run_result::fatal(msg);
|
||||
}
|
||||
|
||||
|
||||
// for capture mode, the source name can change at every event
|
||||
stats_collector.collect(inspector, inspector->event_sources()[source_engine_idx], num_evts);
|
||||
}
|
||||
@@ -325,7 +315,7 @@ static falco::app::run_result do_inspect(
|
||||
s.outputs->handle_event(rule_res.evt, rule_res.rule, rule_res.source, rule_res.priority_num, rule_res.format, rule_res.tags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
num_evts++;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ limitations under the License.
|
||||
#include "actions.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#include <plugin_manager.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace falco::app;
|
||||
@@ -121,15 +123,33 @@ falco::app::run_result falco::app::actions::validate_rules_files(falco::app::sta
|
||||
}
|
||||
}
|
||||
|
||||
// printout of `-L` option
|
||||
nlohmann::json describe_res;
|
||||
if (successful && (s.options.describe_all_rules || !s.options.describe_rule.empty()))
|
||||
{
|
||||
std::string* rptr = !s.options.describe_rule.empty() ? &(s.options.describe_rule) : nullptr;
|
||||
const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins();
|
||||
describe_res = s.engine->describe_rule(rptr, plugins);
|
||||
}
|
||||
|
||||
if(s.config->m_json_output)
|
||||
{
|
||||
nlohmann::json res;
|
||||
res["falco_load_results"] = results;
|
||||
printf("%s\n", res.dump().c_str());
|
||||
if (!describe_res.empty() && successful)
|
||||
{
|
||||
res["falco_describe_results"] = std::move(describe_res);
|
||||
}
|
||||
std::cout << res.dump() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s\n", summary.c_str());
|
||||
std::cout << summary << std::endl;
|
||||
if (!describe_res.empty() && successful)
|
||||
{
|
||||
std::cout << std::endl;
|
||||
format_described_rules_as_text(describe_res, std::cout);
|
||||
}
|
||||
}
|
||||
|
||||
if(successful)
|
||||
|
||||
@@ -62,6 +62,7 @@ bool falco::app::run(falco::app::state& s, bool& restart, std::string& errstr)
|
||||
std::list<app_action> run_steps = {
|
||||
falco::app::actions::load_config,
|
||||
falco::app::actions::print_help,
|
||||
falco::app::actions::print_kernel_version,
|
||||
falco::app::actions::print_version,
|
||||
falco::app::actions::print_page_size,
|
||||
falco::app::actions::print_generated_gvisor_config,
|
||||
|
||||
@@ -57,15 +57,11 @@ public:
|
||||
m_watched_dirs(watch_dirs),
|
||||
m_watched_files(watch_files) { }
|
||||
virtual ~restart_handler();
|
||||
restart_handler(restart_handler&&) = default;
|
||||
restart_handler& operator = (restart_handler&&) = default;
|
||||
restart_handler(const restart_handler&) = delete;
|
||||
restart_handler& operator = (const restart_handler&) = delete;
|
||||
|
||||
bool start(std::string& err);
|
||||
void stop();
|
||||
void trigger();
|
||||
|
||||
|
||||
private:
|
||||
void watcher_loop() noexcept;
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ struct state
|
||||
source_info& operator = (source_info&&) = default;
|
||||
source_info(const source_info&) = default;
|
||||
source_info& operator = (const source_info&) = default;
|
||||
|
||||
|
||||
// The index of the given event source in the state's falco_engine,
|
||||
// as returned by falco_engine::add_source
|
||||
std::size_t engine_idx;
|
||||
@@ -93,10 +93,6 @@ struct state
|
||||
}
|
||||
|
||||
~state() = default;
|
||||
state(state&&) = default;
|
||||
state& operator = (state&&) = default;
|
||||
state(const state&) = default;
|
||||
state& operator = (const state&) = default;
|
||||
|
||||
std::string cmdline;
|
||||
falco::app::options options;
|
||||
@@ -145,7 +141,7 @@ struct state
|
||||
falco_webserver webserver;
|
||||
#endif
|
||||
|
||||
inline bool is_capture_mode() const
|
||||
inline bool is_capture_mode() const
|
||||
{
|
||||
return config->m_engine_mode == engine_kind_t::REPLAY;
|
||||
}
|
||||
@@ -155,6 +151,11 @@ struct state
|
||||
return config->m_engine_mode == engine_kind_t::GVISOR;
|
||||
}
|
||||
|
||||
inline bool is_kmod() const
|
||||
{
|
||||
return config->m_engine_mode == engine_kind_t::KMOD;
|
||||
}
|
||||
|
||||
inline bool is_ebpf() const
|
||||
{
|
||||
return config->m_engine_mode == engine_kind_t::EBPF;
|
||||
@@ -170,7 +171,7 @@ struct state
|
||||
return config->m_engine_mode == engine_kind_t::NONE;
|
||||
}
|
||||
|
||||
inline bool is_source_enabled(const std::string& src) const
|
||||
inline bool is_source_enabled(const std::string& src) const
|
||||
{
|
||||
return enabled_sources.find(falco_common::syscall_source) != enabled_sources.end();
|
||||
}
|
||||
|
||||
@@ -30,13 +30,6 @@ namespace falco
|
||||
class atomic_signal_handler
|
||||
{
|
||||
public:
|
||||
atomic_signal_handler(): m_triggered(false), m_handled(false) { }
|
||||
atomic_signal_handler(atomic_signal_handler&&) = default;
|
||||
atomic_signal_handler& operator = (atomic_signal_handler&&) = default;
|
||||
atomic_signal_handler(const atomic_signal_handler&) = delete;
|
||||
atomic_signal_handler& operator = (const atomic_signal_handler&) = delete;
|
||||
~atomic_signal_handler() = default;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the underlying atomic implementation
|
||||
* is lock-free as per C++ standard semantics.
|
||||
@@ -95,7 +88,7 @@ namespace falco
|
||||
* performed. After the first handler has been performed, every
|
||||
* other invocation of handle() will be skipped and return false
|
||||
* up until the next invocation of reset().
|
||||
*
|
||||
*
|
||||
* @param f The action to perform.
|
||||
* @return true If the action has been performed.
|
||||
* @return false If the action has not been performed.
|
||||
@@ -134,7 +127,7 @@ namespace falco
|
||||
|
||||
private:
|
||||
std::mutex m_mtx;
|
||||
std::atomic<bool> m_triggered;
|
||||
std::atomic<bool> m_handled;
|
||||
std::atomic<bool> m_triggered{false};
|
||||
std::atomic<bool> m_handled{false};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -69,9 +69,7 @@ falco_configuration::falco_configuration():
|
||||
m_metrics_interval(5000),
|
||||
m_metrics_stats_rule_enabled(false),
|
||||
m_metrics_output_file(""),
|
||||
m_metrics_resource_utilization_enabled(true),
|
||||
m_metrics_kernel_event_counters_enabled(true),
|
||||
m_metrics_libbpf_stats_enabled(true),
|
||||
m_metrics_flags((PPM_SCAP_STATS_KERNEL_COUNTERS | PPM_SCAP_STATS_LIBBPF_STATS | PPM_SCAP_STATS_RESOURCE_UTILIZATION | PPM_SCAP_STATS_STATE_COUNTERS)),
|
||||
m_metrics_convert_memory_to_mb(true),
|
||||
m_metrics_include_empty_values(false)
|
||||
{
|
||||
@@ -453,9 +451,29 @@ void falco_configuration::load_yaml(const std::string& config_name, const yaml_h
|
||||
m_metrics_interval = falco::utils::parse_prometheus_interval(m_metrics_interval_str);
|
||||
m_metrics_stats_rule_enabled = config.get_scalar<bool>("metrics.output_rule", false);
|
||||
m_metrics_output_file = config.get_scalar<std::string>("metrics.output_file", "");
|
||||
m_metrics_resource_utilization_enabled = config.get_scalar<bool>("metrics.resource_utilization_enabled", true);
|
||||
m_metrics_kernel_event_counters_enabled = config.get_scalar<bool>("metrics.kernel_event_counters_enabled", true);
|
||||
m_metrics_libbpf_stats_enabled = config.get_scalar<bool>("metrics.libbpf_stats_enabled", true);
|
||||
|
||||
m_metrics_flags = 0;
|
||||
if (config.get_scalar<bool>("metrics.resource_utilization_enabled", true))
|
||||
{
|
||||
m_metrics_flags |= PPM_SCAP_STATS_RESOURCE_UTILIZATION;
|
||||
|
||||
}
|
||||
if (config.get_scalar<bool>("metrics.state_counters_enabled", true))
|
||||
{
|
||||
m_metrics_flags |= PPM_SCAP_STATS_STATE_COUNTERS;
|
||||
|
||||
}
|
||||
if (config.get_scalar<bool>("metrics.kernel_event_counters_enabled", true))
|
||||
{
|
||||
m_metrics_flags |= PPM_SCAP_STATS_KERNEL_COUNTERS;
|
||||
|
||||
}
|
||||
if (config.get_scalar<bool>("metrics.libbpf_stats_enabled", true))
|
||||
{
|
||||
m_metrics_flags |= PPM_SCAP_STATS_LIBBPF_STATS;
|
||||
|
||||
}
|
||||
|
||||
m_metrics_convert_memory_to_mb = config.get_scalar<bool>("metrics.convert_memory_to_mb", true);
|
||||
m_metrics_include_empty_values = config.get_scalar<bool>("metrics.include_empty_values", false);
|
||||
|
||||
|
||||
@@ -55,45 +55,38 @@ enum class engine_kind_t : uint8_t
|
||||
class falco_configuration
|
||||
{
|
||||
public:
|
||||
|
||||
typedef struct {
|
||||
public:
|
||||
struct plugin_config {
|
||||
std::string m_name;
|
||||
std::string m_library_path;
|
||||
std::string m_init_config;
|
||||
std::string m_open_params;
|
||||
} plugin_config;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
public:
|
||||
struct kmod_config {
|
||||
int16_t m_buf_size_preset;
|
||||
bool m_drop_failed_exit;
|
||||
} kmod_config;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
public:
|
||||
struct ebpf_config {
|
||||
std::string m_probe_path;
|
||||
int16_t m_buf_size_preset;
|
||||
bool m_drop_failed_exit;
|
||||
} ebpf_config;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
public:
|
||||
struct modern_ebpf_config {
|
||||
uint16_t m_cpus_for_each_buffer;
|
||||
int16_t m_buf_size_preset;
|
||||
bool m_drop_failed_exit;
|
||||
} modern_ebpf_config;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
public:
|
||||
struct replay_config {
|
||||
std::string m_capture_file;
|
||||
} replay_config;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
public:
|
||||
struct gvisor_config {
|
||||
std::string m_config;
|
||||
std::string m_root;
|
||||
} gvisor_config;
|
||||
};
|
||||
|
||||
falco_configuration();
|
||||
virtual ~falco_configuration() = default;
|
||||
@@ -158,9 +151,7 @@ public:
|
||||
uint64_t m_metrics_interval;
|
||||
bool m_metrics_stats_rule_enabled;
|
||||
std::string m_metrics_output_file;
|
||||
bool m_metrics_resource_utilization_enabled;
|
||||
bool m_metrics_kernel_event_counters_enabled;
|
||||
bool m_metrics_libbpf_stats_enabled;
|
||||
uint32_t m_metrics_flags;
|
||||
bool m_metrics_convert_memory_to_mb;
|
||||
bool m_metrics_include_empty_values;
|
||||
std::vector<plugin_config> m_plugins;
|
||||
|
||||
@@ -65,7 +65,7 @@ falco_outputs::falco_outputs(
|
||||
{
|
||||
add_output(output);
|
||||
}
|
||||
m_outputs_queue_num_drops = {0};
|
||||
m_outputs_queue_num_drops = 0;
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_queue.set_capacity(outputs_queue_capacity);
|
||||
m_worker_thread = std::thread(&falco_outputs::worker, this);
|
||||
|
||||
@@ -32,11 +32,6 @@ namespace falco
|
||||
* @brief Creates a semaphore with the given initial counter value
|
||||
*/
|
||||
semaphore(int c = 0): count(c) {}
|
||||
semaphore(semaphore&&) = default;
|
||||
semaphore& operator = (semaphore&&) = default;
|
||||
semaphore(const semaphore&) = delete;
|
||||
semaphore& operator = (const semaphore&) = delete;
|
||||
~semaphore() = default;
|
||||
|
||||
/**
|
||||
* @brief Increments the internal counter and unblocks acquirers
|
||||
|
||||
@@ -20,7 +20,6 @@ limitations under the License.
|
||||
#endif
|
||||
#include <ctime>
|
||||
#include <csignal>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <atomic>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
@@ -40,8 +39,8 @@ static timer_t s_timerid;
|
||||
#else
|
||||
static uint16_t s_timerid;
|
||||
#endif
|
||||
// note: Workaround for older GLIBC versions (< 2.35), where calling timer_delete()
|
||||
// with an invalid timer ID not returned by timer_create() causes a segfault because of
|
||||
// note: Workaround for older GLIBC versions (< 2.35), where calling timer_delete()
|
||||
// with an invalid timer ID not returned by timer_create() causes a segfault because of
|
||||
// a bug in GLIBC (https://sourceware.org/bugzilla/show_bug.cgi?id=28257).
|
||||
// Just performing a nullptr check is not enough as even after creating the timer, s_timerid
|
||||
// remains a nullptr somehow.
|
||||
@@ -132,7 +131,7 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err)
|
||||
// delete any previously set timer
|
||||
if (s_timerid_exists)
|
||||
{
|
||||
if (timer_delete(s_timerid) == -1)
|
||||
if (timer_delete(s_timerid) == -1)
|
||||
{
|
||||
err = std::string("Could not delete previous timer: ") + strerror(errno);
|
||||
return false;
|
||||
@@ -140,7 +139,7 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err)
|
||||
s_timerid_exists = false;
|
||||
}
|
||||
|
||||
if (timer_create(CLOCK_MONOTONIC, &sev, &s_timerid) == -1)
|
||||
if (timer_create(CLOCK_MONOTONIC, &sev, &s_timerid) == -1)
|
||||
{
|
||||
err = std::string("Could not create periodic timer: ") + strerror(errno);
|
||||
return false;
|
||||
@@ -151,7 +150,7 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string &err)
|
||||
timer.it_value.tv_nsec = (interval_msec % 1000) * 1000 * 1000;
|
||||
timer.it_interval = timer.it_value;
|
||||
|
||||
if (timer_settime(s_timerid, 0, &timer, NULL) == -1)
|
||||
if (timer_settime(s_timerid, 0, &timer, NULL) == -1)
|
||||
{
|
||||
err = std::string("Could not set up periodic timer: ") + strerror(errno);
|
||||
return false;
|
||||
@@ -265,7 +264,7 @@ void stats_writer::worker() noexcept
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// this helps waiting for the first tick
|
||||
tick = stats_writer::get_ticker();
|
||||
if (first_tick != tick)
|
||||
@@ -302,7 +301,7 @@ void stats_writer::worker() noexcept
|
||||
}
|
||||
|
||||
stats_writer::collector::collector(const std::shared_ptr<stats_writer>& writer)
|
||||
: m_writer(writer), m_last_tick(0), m_samples(0),
|
||||
: m_writer(writer), m_last_tick(0),
|
||||
m_last_now(0), m_last_n_evts(0), m_last_n_drops(0), m_last_num_evts(0)
|
||||
{
|
||||
}
|
||||
@@ -343,7 +342,7 @@ void stats_writer::collector::get_metrics_output_fields_wrapper(
|
||||
if (m_last_num_evts != 0 && stats_snapshot_time_delta_sec > 0)
|
||||
{
|
||||
/* Successfully processed userspace event rate. */
|
||||
output_fields["falco.evts_rate_sec"] = (double)((num_evts - m_last_num_evts) / (double)stats_snapshot_time_delta_sec);
|
||||
output_fields["falco.evts_rate_sec"] = std::round((double)((num_evts - m_last_num_evts) / (double)stats_snapshot_time_delta_sec) * 10.0) / 10.0; // round to 1 decimal
|
||||
}
|
||||
output_fields["falco.num_evts"] = num_evts;
|
||||
output_fields["falco.num_evts_prev"] = m_last_num_evts;
|
||||
@@ -358,60 +357,74 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
||||
const scap_agent_info* agent_info = inspector->get_agent_info();
|
||||
|
||||
#if !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
|
||||
/* Resource utilization, CPU and memory usage etc. */
|
||||
uint32_t nstats = 0;
|
||||
int32_t rc = 0;
|
||||
if (m_writer->m_config->m_metrics_resource_utilization_enabled)
|
||||
uint32_t flags = m_writer->m_config->m_metrics_flags;
|
||||
|
||||
auto buffer = inspector->get_sinsp_stats_v2_buffer();
|
||||
auto sinsp_stats_v2 = inspector->get_sinsp_stats_v2();
|
||||
sinsp_thread_manager* thread_manager = inspector->m_thread_manager;
|
||||
const scap_stats_v2* sinsp_stats_v2_snapshot = libsinsp::stats::get_sinsp_stats_v2(flags, agent_info, thread_manager, sinsp_stats_v2, buffer, &nstats, &rc);
|
||||
|
||||
if (sinsp_stats_v2_snapshot && rc == 0 && nstats > 0)
|
||||
{
|
||||
const scap_stats_v2* utilization;
|
||||
auto buffer = inspector->get_sinsp_stats_v2_buffer();
|
||||
utilization = libsinsp::resource_utilization::get_resource_utilization(agent_info, buffer, &nstats, &rc);
|
||||
if (utilization && rc == 0 && nstats > 0)
|
||||
for(uint32_t stat = 0; stat < nstats; stat++)
|
||||
{
|
||||
for(uint32_t stat = 0; stat < nstats; stat++)
|
||||
if (sinsp_stats_v2_snapshot[stat].name[0] == '\0')
|
||||
{
|
||||
char metric_name[STATS_NAME_MAX] = "falco.";
|
||||
strlcat(metric_name, utilization[stat].name, sizeof(metric_name));
|
||||
switch(utilization[stat].type)
|
||||
break;
|
||||
}
|
||||
char metric_name[STATS_NAME_MAX] = "falco.";
|
||||
strlcat(metric_name, sinsp_stats_v2_snapshot[stat].name, sizeof(metric_name));
|
||||
switch(sinsp_stats_v2_snapshot[stat].type)
|
||||
{
|
||||
case STATS_VALUE_TYPE_U64:
|
||||
if (sinsp_stats_v2_snapshot[stat].value.u64 == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
{
|
||||
case STATS_VALUE_TYPE_U64:
|
||||
if (utilization[stat].value.u64 == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (m_writer->m_config->m_metrics_convert_memory_to_mb && strncmp(utilization[stat].name, "container_memory_used", 22) == 0) // exact str match
|
||||
{
|
||||
output_fields[metric_name] = (uint64_t)(utilization[stat].value.u64 / (double)1024 / (double)1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_fields[metric_name] = utilization[stat].value.u64;
|
||||
}
|
||||
break;
|
||||
case STATS_VALUE_TYPE_U32:
|
||||
if (utilization[stat].value.u32 == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (m_writer->m_config->m_metrics_convert_memory_to_mb && strncmp(utilization[stat].name, "memory_", 7) == 0) // prefix match
|
||||
{
|
||||
output_fields[metric_name] = (uint32_t)(utilization[stat].value.u32 / (double)1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_fields[metric_name] = utilization[stat].value.u32;
|
||||
}
|
||||
break;
|
||||
case STATS_VALUE_TYPE_D:
|
||||
if (utilization[stat].value.d == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
{
|
||||
break;
|
||||
}
|
||||
output_fields[metric_name] = utilization[stat].value.d;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (m_writer->m_config->m_metrics_convert_memory_to_mb)
|
||||
{
|
||||
if (strncmp(sinsp_stats_v2_snapshot[stat].name, "container_memory_used", 22) == 0) // exact str match
|
||||
{
|
||||
output_fields[metric_name] = (uint64_t)(sinsp_stats_v2_snapshot[stat].value.u64 / (double)1024 / (double)1024);
|
||||
|
||||
} else if (strncmp(sinsp_stats_v2_snapshot[stat].name, "memory_", 7) == 0) // prefix match
|
||||
{
|
||||
output_fields[metric_name] = (uint64_t)(sinsp_stats_v2_snapshot[stat].value.u64 / (double)1024);
|
||||
} else
|
||||
{
|
||||
output_fields[metric_name] = sinsp_stats_v2_snapshot[stat].value.u64;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output_fields[metric_name] = sinsp_stats_v2_snapshot[stat].value.u64;
|
||||
}
|
||||
break;
|
||||
case STATS_VALUE_TYPE_U32:
|
||||
if (sinsp_stats_v2_snapshot[stat].value.u32 == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (m_writer->m_config->m_metrics_convert_memory_to_mb && strncmp(sinsp_stats_v2_snapshot[stat].name, "memory_", 7) == 0) // prefix match
|
||||
{
|
||||
output_fields[metric_name] = (uint32_t)(sinsp_stats_v2_snapshot[stat].value.u32 / (double)1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_fields[metric_name] = sinsp_stats_v2_snapshot[stat].value.u32;
|
||||
}
|
||||
break;
|
||||
case STATS_VALUE_TYPE_D:
|
||||
if (sinsp_stats_v2_snapshot[stat].value.d == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
{
|
||||
break;
|
||||
}
|
||||
output_fields[metric_name] = sinsp_stats_v2_snapshot[stat].value.d;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,18 +437,16 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
||||
/* Kernel side stats counters and libbpf stats if applicable. */
|
||||
nstats = 0;
|
||||
rc = 0;
|
||||
uint32_t flags = 0;
|
||||
if (!(inspector->check_current_engine(BPF_ENGINE) || inspector->check_current_engine(MODERN_BPF_ENGINE)))
|
||||
{
|
||||
flags &= ~PPM_SCAP_STATS_LIBBPF_STATS;
|
||||
}
|
||||
|
||||
if (m_writer->m_config->m_metrics_kernel_event_counters_enabled)
|
||||
{
|
||||
flags |= PPM_SCAP_STATS_KERNEL_COUNTERS;
|
||||
}
|
||||
if (m_writer->m_config->m_metrics_libbpf_stats_enabled && (inspector->check_current_engine(BPF_ENGINE) || inspector->check_current_engine(MODERN_BPF_ENGINE)))
|
||||
{
|
||||
flags |= PPM_SCAP_STATS_LIBBPF_STATS;
|
||||
}
|
||||
const scap_stats_v2* stats_v2 = inspector->get_capture_stats_v2(flags, &nstats, &rc);
|
||||
if (stats_v2 && nstats > 0 && rc == 0)
|
||||
// Note: ENGINE_FLAG_BPF_STATS_ENABLED check has been moved to libs, that is, when libbpf stats is not enabled
|
||||
// in the kernel settings we won't collect them even if the end user enabled the libbpf stats option
|
||||
|
||||
const scap_stats_v2* scap_stats_v2_snapshot = inspector->get_capture_stats_v2(flags, &nstats, &rc);
|
||||
if (scap_stats_v2_snapshot && nstats > 0 && rc == 0)
|
||||
{
|
||||
/* Cache n_evts and n_drops to derive n_drops_perc. */
|
||||
uint64_t n_evts = 0;
|
||||
@@ -444,24 +455,28 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
||||
uint64_t n_drops_delta = 0;
|
||||
for(uint32_t stat = 0; stat < nstats; stat++)
|
||||
{
|
||||
if (scap_stats_v2_snapshot[stat].name[0] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
// todo: as we expand scap_stats_v2 prefix may be pushed to scap or we may need to expand
|
||||
// functionality here for example if we add userspace syscall counters that should be prefixed w/ `falco.`
|
||||
char metric_name[STATS_NAME_MAX] = "scap.";
|
||||
strlcat(metric_name, stats_v2[stat].name, sizeof(metric_name));
|
||||
switch(stats_v2[stat].type)
|
||||
strlcat(metric_name, scap_stats_v2_snapshot[stat].name, sizeof(metric_name));
|
||||
switch(scap_stats_v2_snapshot[stat].type)
|
||||
{
|
||||
case STATS_VALUE_TYPE_U64:
|
||||
/* Always send high level n_evts related fields, even if zero. */
|
||||
if (strncmp(stats_v2[stat].name, "n_evts", 7) == 0) // exact not prefix match here
|
||||
if (strncmp(scap_stats_v2_snapshot[stat].name, "n_evts", 7) == 0) // exact not prefix match here
|
||||
{
|
||||
n_evts = stats_v2[stat].value.u64;
|
||||
n_evts = scap_stats_v2_snapshot[stat].value.u64;
|
||||
output_fields[metric_name] = n_evts;
|
||||
output_fields["scap.n_evts_prev"] = m_last_n_evts;
|
||||
n_evts_delta = n_evts - m_last_n_evts;
|
||||
if (n_evts_delta != 0 && stats_snapshot_time_delta_sec > 0)
|
||||
{
|
||||
/* n_evts is total number of kernel side events. */
|
||||
output_fields["scap.evts_rate_sec"] = (double)(n_evts_delta / stats_snapshot_time_delta_sec);
|
||||
output_fields["scap.evts_rate_sec"] = std::round((double)(n_evts_delta / stats_snapshot_time_delta_sec) * 10.0) / 10.0; // round to 1 decimal
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -470,16 +485,16 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
||||
m_last_n_evts = n_evts;
|
||||
}
|
||||
/* Always send high level n_drops related fields, even if zero. */
|
||||
else if (strncmp(stats_v2[stat].name, "n_drops", 8) == 0) // exact not prefix match here
|
||||
else if (strncmp(scap_stats_v2_snapshot[stat].name, "n_drops", 8) == 0) // exact not prefix match here
|
||||
{
|
||||
n_drops = stats_v2[stat].value.u64;
|
||||
n_drops = scap_stats_v2_snapshot[stat].value.u64;
|
||||
output_fields[metric_name] = n_drops;
|
||||
output_fields["scap.n_drops_prev"] = m_last_n_drops;
|
||||
n_drops_delta = n_drops - m_last_n_drops;
|
||||
if (n_drops_delta != 0 && stats_snapshot_time_delta_sec > 0)
|
||||
{
|
||||
/* n_drops is total number of kernel side event drops. */
|
||||
output_fields["scap.evts_drop_rate_sec"] = (double)(n_drops_delta / stats_snapshot_time_delta_sec);
|
||||
output_fields["scap.evts_drop_rate_sec"] = std::round((double)(n_drops_delta / stats_snapshot_time_delta_sec) * 10.0) / 10.0; // round to 1 decimal
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -487,11 +502,11 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
||||
}
|
||||
m_last_n_drops = n_drops;
|
||||
}
|
||||
if (stats_v2[stat].value.u64 == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
if (scap_stats_v2_snapshot[stat].value.u64 == 0 && !m_writer->m_config->m_metrics_include_empty_values)
|
||||
{
|
||||
break;
|
||||
}
|
||||
output_fields[metric_name] = stats_v2[stat].value.u64;
|
||||
output_fields[metric_name] = scap_stats_v2_snapshot[stat].value.u64;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
This class is not thread-safe.
|
||||
*/
|
||||
class collector
|
||||
{
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Initializes the collector with the given writer
|
||||
@@ -74,11 +74,8 @@ public:
|
||||
*/
|
||||
void get_metrics_output_fields_additional(nlohmann::json& output_fields, const std::shared_ptr<sinsp>& inspector, double stats_snapshot_time_delta_sec, const std::string& src);
|
||||
|
||||
|
||||
std::shared_ptr<stats_writer> m_writer;
|
||||
stats_writer::ticker_t m_last_tick;
|
||||
uint64_t m_samples;
|
||||
scap_stats m_last_stats;
|
||||
uint64_t m_last_now;
|
||||
uint64_t m_last_n_evts;
|
||||
uint64_t m_last_n_drops;
|
||||
|
||||
Reference in New Issue
Block a user