Compare commits
21 Commits
Author | SHA1 | Date |
---|---|---|
|
b94cda0b12 | |
|
dfe08bdecb | |
|
79a5f9f3d9 | |
|
466373359c | |
|
b46e4188d8 | |
|
6bcef8f94e | |
|
cf6857f13b | |
|
9c2cff370d | |
|
1a4ff6781b | |
|
f15dca4a3b | |
|
43122a21e5 | |
|
eb59f3603b | |
|
72910f23e9 | |
|
4c258afd9b | |
|
aa67a0270a | |
|
60721592e5 | |
|
9e67d90e19 | |
|
afc4798d4c | |
|
6bcc73aeff | |
|
d4e7325c06 | |
|
9fe7230d31 |
85
CHANGELOG.md
85
CHANGELOG.md
|
@ -1,5 +1,90 @@
|
|||
# Change Log
|
||||
|
||||
## v0.41.0
|
||||
|
||||
Released on 2025-05-29
|
||||
|
||||
### Breaking Changes :warning:
|
||||
|
||||
* cleanup(engine)!: only consider .yaml/.yml rule files [[#3551](https://github.com/falcosecurity/falco/pull/3551)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* cleanup(userspace)!: deprecate print of `container.info` [[#3543](https://github.com/falcosecurity/falco/pull/3543)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* cleanup(userspace/falco)!: drop deprecated in 0.40.0 CLI flags. [[#3496](https://github.com/falcosecurity/falco/pull/3496)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
### Major Changes
|
||||
|
||||
* new(falco): add json_include_output_fields option [[#3527](https://github.com/falcosecurity/falco/pull/3527)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* new(build,userspace): switch to use container plugin [[#3482](https://github.com/falcosecurity/falco/pull/3482)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* new(docker,scripts,ci): use an override config file to enable ISO 8601 output timeformat on docker images [[#3488](https://github.com/falcosecurity/falco/pull/3488)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* chore(build): update falcoctl to v0.11.2, rules for artifact follow to v4 [[#3580](https://github.com/falcosecurity/falco/pull/3580)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update(cmake): bumped falcoctl to 0.11.1 and rules to 4.0.0. [[#3577](https://github.com/falcosecurity/falco/pull/3577)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(containers): update opencontainers labels [[#3575](https://github.com/falcosecurity/falco/pull/3575)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update(metrics): improve restart/hot_reload conditions inspection [[#3562](https://github.com/falcosecurity/falco/pull/3562)] - [@incertum](https://github.com/incertum)
|
||||
* update: empty `values` in `exceptions` won't emit a warning anymore [[#3529](https://github.com/falcosecurity/falco/pull/3529)] - [@leogr](https://github.com/leogr)
|
||||
* chore(falco.yaml): enable libs_logger by default with info level [[#3507](https://github.com/falcosecurity/falco/pull/3507)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(metrics/prometheus): gracefully handle multiple event sources, avoid erroneous duplicate metrics [[#3563](https://github.com/falcosecurity/falco/pull/3563)] - [@incertum](https://github.com/incertum)
|
||||
* fix(ci): properly install rpm systemd-rpm-macro package on building packages pipeline [[#3521](https://github.com/falcosecurity/falco/pull/3521)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(userspace/falco): init cmdline options after loading all config files [[#3493](https://github.com/falcosecurity/falco/pull/3493)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(cmake): add support for 16K kernel page to jemalloc [[#3490](https://github.com/falcosecurity/falco/pull/3490)] - [@Darkness4](https://github.com/Darkness4)
|
||||
* fix(userspace/falco): fix jemalloc enabled in minimal build. [[#3478](https://github.com/falcosecurity/falco/pull/3478)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `4ccf111` to `cb17833` [[#3572](https://github.com/falcosecurity/falco/pull/3572)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(cmake/rules): bump to falco-rules-4.0.0-rc1 [[#3567](https://github.com/falcosecurity/falco/pull/3567)] - [@leogr](https://github.com/leogr)
|
||||
* cleanup(userspace/falco): drop unused `libs_metrics_collector` variable. [[#3566](https://github.com/falcosecurity/falco/pull/3566)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(cmake): update libs and driver to latest master [[#3564](https://github.com/falcosecurity/falco/pull/3564)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* fix(build): fixed container custom_target `sed` command. [[#3556](https://github.com/falcosecurity/falco/pull/3556)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `ae6ed41` to `4ccf111` [[#3555](https://github.com/falcosecurity/falco/pull/3555)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* fix(cmake): fix bundled c-ares cmake issue with e.g. SLES [[#3559](https://github.com/falcosecurity/falco/pull/3559)] - [@terror96](https://github.com/terror96)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `1d2c6b1` to `ae6ed41` [[#3553](https://github.com/falcosecurity/falco/pull/3553)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* chore: revert "chore(deps): Bump submodules/falcosecurity-rules from `1d2c6b1` to `371e431`" [[#3552](https://github.com/falcosecurity/falco/pull/3552)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(cmake): update libs and driver to latest master [[#3550](https://github.com/falcosecurity/falco/pull/3550)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3549](https://github.com/falcosecurity/falco/pull/3549)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(adopters): added SafeDep as adopter [[#3548](https://github.com/falcosecurity/falco/pull/3548)] - [@KunalSin9h](https://github.com/KunalSin9h)
|
||||
* update(cmake): update libs and driver to latest master [[#3547](https://github.com/falcosecurity/falco/pull/3547)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3541](https://github.com/falcosecurity/falco/pull/3541)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* fix(userspace): fixed engine `openssl` dep. [[#3535](https://github.com/falcosecurity/falco/pull/3535)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(userspace/falco): fix outputs_http timeout [[#3523](https://github.com/falcosecurity/falco/pull/3523)] - [@benierc](https://github.com/benierc)
|
||||
* fix(ci): use clang-19 to build modern_ebpf skeleton. [[#3537](https://github.com/falcosecurity/falco/pull/3537)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(cmake): update libs and driver to latest master [[#3531](https://github.com/falcosecurity/falco/pull/3531)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3530](https://github.com/falcosecurity/falco/pull/3530)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3525](https://github.com/falcosecurity/falco/pull/3525)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3520](https://github.com/falcosecurity/falco/pull/3520)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3516](https://github.com/falcosecurity/falco/pull/3516)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* docs(README.md): cleanups and enhancements [[#3514](https://github.com/falcosecurity/falco/pull/3514)] - [@leogr](https://github.com/leogr)
|
||||
* update(cmake): update libs and driver to latest master [[#3511](https://github.com/falcosecurity/falco/pull/3511)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `1d2c6b1` to `371e431` [[#3510](https://github.com/falcosecurity/falco/pull/3510)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(cmake): update libs and driver to latest master [[#3508](https://github.com/falcosecurity/falco/pull/3508)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3506](https://github.com/falcosecurity/falco/pull/3506)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* fix(userspace/falco): when counting `-M` timeout, do not account for async events [[#3505](https://github.com/falcosecurity/falco/pull/3505)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `d8415c1` to `1d2c6b1` [[#3504](https://github.com/falcosecurity/falco/pull/3504)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* docs(proposals): correct typo in example [[#3499](https://github.com/falcosecurity/falco/pull/3499)] - [@leogr](https://github.com/leogr)
|
||||
* fix(docker): fixed entrypoints paths with new docker context. [[#3492](https://github.com/falcosecurity/falco/pull/3492)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* feat(falco/app): move actions not using config before `load_config` [[#3483](https://github.com/falcosecurity/falco/pull/3483)] - [@ekoops](https://github.com/ekoops)
|
||||
* refactor(falco/app): apply early return pattern in actions code [[#3484](https://github.com/falcosecurity/falco/pull/3484)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `abf6637` to `d8415c1` [[#3489](https://github.com/falcosecurity/falco/pull/3489)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* Add NETWAYS Web Services to ADOPTERS.md [[#3487](https://github.com/falcosecurity/falco/pull/3487)] - [@mocdaniel](https://github.com/mocdaniel)
|
||||
* chore: add back Falco static package to the release template. [[#3472](https://github.com/falcosecurity/falco/pull/3472)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
### Statistics
|
||||
|
||||
| MERGED PRS | NUMBER |
|
||||
|-----------------|--------|
|
||||
| Not user-facing | 36 |
|
||||
| Release note | 17 |
|
||||
| Total | 53 |
|
||||
|
||||
## v0.40.0
|
||||
|
||||
Released on 2025-01-28
|
||||
|
|
|
@ -267,6 +267,12 @@ if(NOT WIN32
|
|||
AND NOT MUSL_OPTIMIZED_BUILD
|
||||
)
|
||||
include(falcoctl)
|
||||
set(CONTAINER_VERSION "0.2.4")
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(CONTAINER_HASH "2b6cf7c014fa29dffbc063582343402b863581218e704ca8021bc971c3e029fc")
|
||||
else() # arm64
|
||||
set(CONTAINER_HASH "ad96c2baa299fa51b6be07a93b21dd03fe6e2a9bea44cc13ea50a346e5d22774")
|
||||
endif()
|
||||
include(container_plugin)
|
||||
|
||||
# Generate a binary_dir/falco.yaml that automatically enables the plugin to be used for local
|
||||
|
|
|
@ -35,9 +35,9 @@ else()
|
|||
# FALCOSECURITY_LIBS_VERSION. 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 "9c2734a64338abff04c4a8274d3770e40c964e21")
|
||||
set(DRIVER_VERSION "8.1.0+driver")
|
||||
set(DRIVER_CHECKSUM
|
||||
"SHA256=8094cfb04c77b317a4e5a69cf8556dccb54067d1decf9ec920c7cc3fa1ea831a"
|
||||
"SHA256=182e6787bf86249a846a3baeb4dcd31578b76d4a13efa16ce3f44d66b18a77a6"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -20,16 +20,16 @@ option(ADD_FALCOCTL_DEPENDENCY "Add falcoctl dependency while building falco" ON
|
|||
if(ADD_FALCOCTL_DEPENDENCY)
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} FALCOCTL_SYSTEM_NAME)
|
||||
|
||||
set(FALCOCTL_VERSION "0.11.0")
|
||||
set(FALCOCTL_VERSION "0.11.2")
|
||||
|
||||
message(STATUS "Building with falcoctl: ${FALCOCTL_VERSION}")
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "amd64")
|
||||
set(FALCOCTL_HASH "b9d0e0f50813e7172a945f36f70c5c3c16a677ab4c85b35b6f7a155bc92768fc")
|
||||
set(FALCOCTL_HASH "8d55818987c90e54f7406e1c1441a18df1f485db858bb0b3efda5db217be3b48")
|
||||
else() # aarch64
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "arm64")
|
||||
set(FALCOCTL_HASH "689c625d1d414cbf53d39ef94083a53dda3ea4ac4908799fb85f4519e21442e0")
|
||||
set(FALCOCTL_HASH "7c36404b5b7a515df25e7dc6d827a74ebc8526b1b49850954bbdd40860961bc2")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
|
|
|
@ -42,9 +42,9 @@ else()
|
|||
# version (or branch, or commit) just pass the variable - ie., `cmake
|
||||
# -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "9c2734a64338abff04c4a8274d3770e40c964e21")
|
||||
set(FALCOSECURITY_LIBS_VERSION "0.21.0")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM
|
||||
"SHA256=8094cfb04c77b317a4e5a69cf8556dccb54067d1decf9ec920c7cc3fa1ea831a"
|
||||
"SHA256=9e977001dd42586df42a5dc7e7a948c297124865a233402e44bdec68839d322a"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2024 The Falco Authors.
|
||||
# Copyright (C) 2025 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
|
||||
|
@ -18,9 +18,9 @@ include(ExternalProject)
|
|||
|
||||
if(NOT DEFINED FALCOSECURITY_RULES_FALCO_PATH)
|
||||
# falco_rules.yaml
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-3.2.0")
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-4.0.0")
|
||||
set(FALCOSECURITY_RULES_FALCO_CHECKSUM
|
||||
"SHA256=b3990bf0209cfbf6a903b361e458a1f5851a9a5aeee808ad26a5ddbe1377157d"
|
||||
"SHA256=132320ddbfa1e2580981ed1bdd3ee3d0128a1e2306b2bee8978d1f0a930d6127"
|
||||
)
|
||||
set(FALCOSECURITY_RULES_FALCO_PATH
|
||||
"${PROJECT_BINARY_DIR}/falcosecurity-rules-falco-prefix/src/falcosecurity-rules-falco/falco_rules.yaml"
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
FROM debian:buster
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
LABEL org.opencontainers.image.source="https://github.com/falcosecurity/falco"
|
||||
LABEL org.opencontainers.image.authors='The Falco Authors https://falco.org' \
|
||||
org.opencontainers.image.url='https://falco.org' \
|
||||
org.opencontainers.image.source='https://github.com/falcosecurity/falco' \
|
||||
org.opencontainers.image.vendor='Falco Organization' \
|
||||
org.opencontainers.image.licenses='Apache-2.0' \
|
||||
maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
LABEL usage="docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc:ro falcosecurity/falco-driver-loader:latest-buster [driver] [options]"
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
ARG FALCO_IMAGE_TAG=latest
|
||||
FROM docker.io/falcosecurity/falco:${FALCO_IMAGE_TAG}-debian
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
LABEL org.opencontainers.image.source="https://github.com/falcosecurity/falco"
|
||||
LABEL org.opencontainers.image.authors='The Falco Authors https://falco.org' \
|
||||
org.opencontainers.image.url='https://falco.org' \
|
||||
org.opencontainers.image.source='https://github.com/falcosecurity/falco' \
|
||||
org.opencontainers.image.vendor='Falco Organization' \
|
||||
org.opencontainers.image.licenses='Apache-2.0' \
|
||||
maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
LABEL usage="docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc:ro falcosecurity/falco-driver-loader:latest [driver] [options]"
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
FROM debian:12-slim
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
LABEL org.opencontainers.image.source="https://github.com/falcosecurity/falco/docker/falco-debian"
|
||||
LABEL org.opencontainers.image.authors='The Falco Authors https://falco.org' \
|
||||
org.opencontainers.image.url='https://falco.org' \
|
||||
org.opencontainers.image.source='https://github.com/falcosecurity/falco' \
|
||||
org.opencontainers.image.vendor='Falco Organization' \
|
||||
org.opencontainers.image.licenses='Apache-2.0' \
|
||||
maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /proc:/host/proc:ro -v /etc:/host/etc:ro falcosecurity/falco:latest-debian"
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
FROM cgr.dev/chainguard/wolfi-base
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
LABEL org.opencontainers.image.source="https://github.com/falcosecurity/falco"
|
||||
LABEL org.opencontainers.image.authors='The Falco Authors https://falco.org' \
|
||||
org.opencontainers.image.url='https://falco.org' \
|
||||
org.opencontainers.image.source='https://github.com/falcosecurity/falco' \
|
||||
org.opencontainers.image.vendor='Falco Organization' \
|
||||
org.opencontainers.image.licenses='Apache-2.0' \
|
||||
maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /proc:/host/proc:ro -v /etc:/host/etc:ro falcosecurity/falco:latest"
|
||||
# NOTE: for the "least privileged" use case, please refer to the official documentation
|
||||
|
|
|
@ -10,7 +10,7 @@ artifact:
|
|||
every: 6h0m0s
|
||||
falcoVersions: http://localhost:8765/versions
|
||||
refs:
|
||||
- falco-rules:3
|
||||
- falco-rules:4
|
||||
indexes:
|
||||
- name: falcosecurity
|
||||
url: https://falcosecurity.github.io/falcoctl/index.yaml
|
||||
|
|
|
@ -66,6 +66,10 @@ falco::app::run_result falco::app::actions::load_config(const falco::app::state&
|
|||
}
|
||||
}
|
||||
|
||||
s.config->m_falco_reload_ts = (int64_t)std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
s.config->m_buffered_outputs = !s.options.unbuffered_outputs;
|
||||
|
||||
return apply_deprecated_options(s);
|
||||
|
|
|
@ -235,6 +235,12 @@ static falco::app::run_result do_inspect(
|
|||
}
|
||||
|
||||
// for capture mode, the source name can change at every event
|
||||
// TODO: This may currently cause issues for multiple event sources. We are deferring
|
||||
// the fix to Falco 0.42.0.
|
||||
// For multiple event sources, it generates `n` metrics logs per source at a time, as
|
||||
// expected, with the engine_name correctly reflected. However, the order may interfere,
|
||||
// as the correct inspector for the syscalls event source seems to never get passed,
|
||||
// resulting in most metrics being missing.
|
||||
stats_collector.collect(inspector,
|
||||
inspector->event_sources()[source_engine_idx],
|
||||
num_evts);
|
||||
|
|
|
@ -214,7 +214,15 @@ public:
|
|||
gvisor_config m_gvisor = {};
|
||||
|
||||
yaml_helper m_config;
|
||||
|
||||
//
|
||||
// Runtime-Generated values (not user-configurable)
|
||||
//
|
||||
|
||||
// JSON schema generated from a hardcoded string
|
||||
nlohmann::json m_config_schema;
|
||||
// Timestamp of most recent configuration reload
|
||||
int64_t m_falco_reload_ts{0};
|
||||
|
||||
private:
|
||||
void merge_config_files(const std::string& config_name, config_loaded_res& res);
|
||||
|
|
|
@ -31,8 +31,36 @@ namespace fs = std::filesystem;
|
|||
|
||||
/*!
|
||||
\class falco_metrics
|
||||
\brief This class is used to convert the metrics provided by the application
|
||||
and falco libs into a string to be return by the metrics endpoint.
|
||||
\brief Converts metrics provided by the application and Falco libraries into a formatted string
|
||||
for the metrics endpoint.
|
||||
|
||||
## Metrics Overview
|
||||
This section explains why looping over inspectors is necessary.
|
||||
Falco utilizes multiple inspectors when loading plugins with an event source.
|
||||
Most metrics should only be retrieved once, ideally by the syscalls inspector if applicable.
|
||||
To maximize metrics retrieval and prevent duplicate data, the syscalls inspector is always
|
||||
positioned at index 0 in the loop when it exists.
|
||||
|
||||
Wrapper fields: See https://falco.org/docs/concepts/metrics/
|
||||
- `engine_name` and `event_source` are pushed for each inspector.
|
||||
- All other wrapper fields are agnostic and should be retrieved once.
|
||||
|
||||
## Metrics Collection Behavior
|
||||
- `rules_counters_enabled` -> Agnostic; resides in falco; retrieved from the state, not an
|
||||
inspector; only performed once.
|
||||
- `resource_utilization_enabled` -> Agnostic; resides in libs; inspector is irrelevant;
|
||||
only performed once.
|
||||
- `state_counters_enabled` -> Semi-agnostic; resides in libs; must be retrieved by the syscalls
|
||||
inspector if applicable.
|
||||
- `kernel_event_counters_enabled` -> Resides in libs; must be retrieved by the syscalls
|
||||
inspector; not available for other inspectors.
|
||||
- `kernel_event_counters_per_cpu_enabled` -> Resides in libs; must be retrieved by the syscalls
|
||||
inspector; not available for other inspectors.
|
||||
- `libbpf_stats_enabled` -> Resides in libs; must be retrieved by the syscalls inspector;
|
||||
not available for other inspectors.
|
||||
- `plugins_metrics_enabled` -> Must be retrieved for each inspector.
|
||||
- `jemalloc_stats_enabled` -> Agnostic; resides in falco; inspector is irrelevant;
|
||||
only performed once.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -42,108 +70,354 @@ namespace fs = std::filesystem;
|
|||
|
||||
https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format
|
||||
*/
|
||||
const std::string falco_metrics::content_type = "text/plain; version=0.0.4";
|
||||
const std::string falco_metrics::content_type_prometheus = "text/plain; version=0.0.4";
|
||||
|
||||
/*!
|
||||
\brief this method takes an application \c state and returns a textual representation of
|
||||
its configured metrics.
|
||||
std::string falco_metrics::falco_to_text_prometheus(
|
||||
const falco::app::state& state,
|
||||
libs::metrics::prometheus_metrics_converter& prometheus_metrics_converter,
|
||||
std::vector<metrics_v2>& additional_wrapper_metrics) {
|
||||
std::string prometheus_text;
|
||||
|
||||
The current implementation returns a Prometheus exposition formatted string.
|
||||
*/
|
||||
std::string falco_metrics::to_text(const falco::app::state& state) {
|
||||
// # HELP falcosecurity_falco_version_info https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_version_info gauge
|
||||
// falcosecurity_falco_version_info{version="0.41.0-100+334ca42"} 1
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"version",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"version", FALCO_VERSION}});
|
||||
|
||||
#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
|
||||
// Note that the rule counter metrics are retrieved from the state, not from any inspector
|
||||
// Distinguish between config and rules files using labels, following Prometheus best
|
||||
// practices: https://prometheus.io/docs/practices/naming/#labels
|
||||
|
||||
// # HELP falcosecurity_falco_sha256_rules_files_info https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_sha256_rules_files_info gauge
|
||||
// falcosecurity_falco_sha256_rules_files_info{file_name="falco_rules.yaml",sha256="6f0078862a26528cb50a860f9ebebbfbe3162e5009187089c73cb0cdf91d0b06"}
|
||||
// 1
|
||||
for(const auto& item : state.config.get()->m_loaded_rules_filenames_sha256sum) {
|
||||
fs::path fs_path = item.first;
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"sha256_rules_files",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"file_name", fs_path.filename()}, {"sha256", item.second}});
|
||||
}
|
||||
|
||||
// # HELP falcosecurity_falco_sha256_config_files_info https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_sha256_config_files_info gauge
|
||||
// falcosecurity_falco_sha256_config_files_info{file_name="falco.yaml",sha256="f97de5fa6f513b5e07cd9f29ee9904ee4267cb120ef6501f8555543d5a98dd1c"}
|
||||
// 1
|
||||
for(const auto& item : state.config.get()->m_loaded_configs_filenames_sha256sum) {
|
||||
fs::path fs_path = item.first;
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"sha256_config_files",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"file_name", fs_path.filename()}, {"sha256", item.second}});
|
||||
}
|
||||
|
||||
#endif
|
||||
// # HELP falcosecurity_falco_outputs_queue_num_drops_total https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_outputs_queue_num_drops_total counter
|
||||
// falcosecurity_falco_outputs_queue_num_drops_total 0
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"outputs_queue_num_drops",
|
||||
METRICS_V2_MISC,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
state.outputs->get_outputs_queue_num_drops()));
|
||||
|
||||
// # HELP falcosecurity_falco_reload_timestamp_nanoseconds https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_reload_timestamp_nanoseconds gauge
|
||||
// falcosecurity_falco_reload_timestamp_nanoseconds 1748338536592811359
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"reload_ts",
|
||||
METRICS_V2_MISC,
|
||||
METRIC_VALUE_TYPE_S64,
|
||||
METRIC_VALUE_UNIT_TIME_TIMESTAMP_NS,
|
||||
METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT,
|
||||
state.config->m_falco_reload_ts));
|
||||
|
||||
if(state.config->m_metrics_flags & METRICS_V2_RULE_COUNTERS) {
|
||||
// rules_counters_enabled
|
||||
const stats_manager& rule_stats_manager = state.engine->get_rule_stats_manager();
|
||||
const indexed_vector<falco_rule>& rules = state.engine->get_rules();
|
||||
const std::vector<std::unique_ptr<std::atomic<uint64_t>>>& rules_by_id =
|
||||
rule_stats_manager.get_by_rule_id();
|
||||
// Distinguish between rules counters using labels, following Prometheus best
|
||||
// practices: https://prometheus.io/docs/practices/naming/#labels
|
||||
for(size_t i = 0; i < rules_by_id.size(); i++) {
|
||||
auto rule = rules.at(i);
|
||||
auto count = rules_by_id[i]->load();
|
||||
if(count > 0) {
|
||||
// # HELP falcosecurity_falco_rules_matches_total https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_rules_matches_total counter
|
||||
// falcosecurity_falco_rules_matches_total{priority="4",rule_name="Read sensitive
|
||||
// file
|
||||
// untrusted",source="syscall",tag_T1555="true",tag_container="true",tag_filesystem="true",tag_host="true",tag_maturity_stable="true",tag_mitre_credential_access="true"}
|
||||
// 32 # HELP falcosecurity_falco_rules_matches_total https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_rules_matches_total counter
|
||||
// falcosecurity_falco_rules_matches_total{priority="5",rule_name="Terminal shell in
|
||||
// container",source="syscall",tag_T1059="true",tag_container="true",tag_maturity_stable="true",tag_mitre_execution="true",tag_shell="true"}
|
||||
// 1
|
||||
auto metric = libs::metrics::libsinsp_metrics::new_metric(
|
||||
"rules_matches",
|
||||
METRICS_V2_RULE_COUNTERS,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
count);
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
std::map<std::string, std::string> const_labels = {
|
||||
{"rule_name", rule->name},
|
||||
{"priority", std::to_string(rule->priority)},
|
||||
{"source", rule->source},
|
||||
};
|
||||
std::for_each(rule->tags.cbegin(),
|
||||
rule->tags.cend(),
|
||||
[&const_labels](std::string const& tag) {
|
||||
const_labels.emplace(std::string{"tag_"} + tag, "true");
|
||||
});
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric,
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
const_labels);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAS_JEMALLOC
|
||||
if(state.config->m_metrics_flags & METRICS_V2_JEMALLOC_STATS) {
|
||||
// jemalloc_stats_enabled
|
||||
nlohmann::json j;
|
||||
malloc_stats_print(
|
||||
[](void* to, const char* from) {
|
||||
nlohmann::json* j = (nlohmann::json*)to;
|
||||
*j = nlohmann::json::parse(from);
|
||||
},
|
||||
&j,
|
||||
"Jmdablxeg");
|
||||
const auto& j_stats = j["jemalloc"]["stats"];
|
||||
for(auto it = j_stats.begin(); it != j_stats.end(); ++it) {
|
||||
if(it.value().is_number_unsigned()) {
|
||||
std::uint64_t val = it.value().template get<std::uint64_t>();
|
||||
std::string key = "jemalloc." + it.key();
|
||||
auto metric = libs::metrics::libsinsp_metrics::new_metric(
|
||||
key.c_str(),
|
||||
METRICS_V2_JEMALLOC_STATS,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_MEMORY_BYTES,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
val);
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric,
|
||||
"falcosecurity",
|
||||
"falco");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return prometheus_text;
|
||||
}
|
||||
|
||||
std::string falco_metrics::sources_to_text_prometheus(
|
||||
const falco::app::state& state,
|
||||
libs::metrics::prometheus_metrics_converter& prometheus_metrics_converter,
|
||||
std::vector<metrics_v2>& additional_wrapper_metrics) {
|
||||
static const char* all_driver_engines[] = {BPF_ENGINE,
|
||||
KMOD_ENGINE,
|
||||
MODERN_BPF_ENGINE,
|
||||
SOURCE_PLUGIN_ENGINE,
|
||||
NODRIVER_ENGINE,
|
||||
GVISOR_ENGINE};
|
||||
static re2::RE2 drops_buffer_pattern("n_drops_buffer_([^_]+(?:_[^_]+)*)_(enter|exit)$");
|
||||
static re2::RE2 cpu_pattern("(\\d+)");
|
||||
|
||||
std::vector<std::shared_ptr<sinsp>> inspectors;
|
||||
std::vector<libs::metrics::libs_metrics_collector> metrics_collectors;
|
||||
std::string prometheus_text;
|
||||
bool agent_info_written = false;
|
||||
bool machine_info_written = false;
|
||||
|
||||
// Then, source-bound metrics
|
||||
for(const auto& source : state.enabled_sources) {
|
||||
auto source_info = state.source_infos.at(source);
|
||||
auto source_inspector = source_info->inspector;
|
||||
inspectors.emplace_back(source_inspector);
|
||||
metrics_collectors.emplace_back(
|
||||
libs::metrics::libs_metrics_collector(source_inspector.get(),
|
||||
state.config->m_metrics_flags));
|
||||
}
|
||||
libs::metrics::prometheus_metrics_converter prometheus_metrics_converter;
|
||||
std::string prometheus_text;
|
||||
|
||||
for(auto inspector : inspectors) {
|
||||
// Falco wrapper metrics
|
||||
//
|
||||
for(size_t i = 0; i < sizeof(all_driver_engines) / sizeof(const char*); i++) {
|
||||
if(inspector->check_current_engine(all_driver_engines[i])) {
|
||||
// First thing: list of enabled engine names
|
||||
|
||||
// Falco wrapper metrics Part A: Repeated for each inspector, accounting for plugins w/
|
||||
// event sources
|
||||
|
||||
/* Examples ...
|
||||
# HELP falcosecurity_scap_engine_name_info https://falco.org/docs/metrics/
|
||||
# TYPE falcosecurity_scap_engine_name_info gauge
|
||||
falcosecurity_scap_engine_name_info{engine_name="source_plugin",evt_source="dummy"} 1
|
||||
# HELP falcosecurity_scap_engine_name_info https://falco.org/docs/metrics/
|
||||
# TYPE falcosecurity_scap_engine_name_info gauge
|
||||
falcosecurity_scap_engine_name_info{engine_name="bpf",evt_source="syscall"} 1
|
||||
*/
|
||||
|
||||
for(size_t j = 0; j < sizeof(all_driver_engines) / sizeof(const char*); j++) {
|
||||
if(source_inspector->check_current_engine(all_driver_engines[j])) {
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"engine_name",
|
||||
"falcosecurity",
|
||||
"scap",
|
||||
{{"engine_name", all_driver_engines[i]}});
|
||||
{{"engine_name", std::string(all_driver_engines[j])},
|
||||
{"evt_source", source}});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const scap_agent_info* agent_info = inspector->get_agent_info();
|
||||
const scap_machine_info* machine_info = inspector->get_machine_info();
|
||||
libs::metrics::libs_metrics_collector libs_metrics_collector(inspector.get(), 0);
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"version",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"version", FALCO_VERSION}});
|
||||
// Inspectors' metrics collectors
|
||||
// Libs metrics categories
|
||||
//
|
||||
// resource_utilization_enabled
|
||||
// state_counters_enabled
|
||||
// kernel_event_counters_enabled
|
||||
// kernel_event_counters_per_cpu_enabled
|
||||
// libbpf_stats_enabled
|
||||
auto metrics_collector =
|
||||
libs::metrics::libs_metrics_collector(source_inspector.get(),
|
||||
state.config->m_metrics_flags);
|
||||
metrics_collector.snapshot();
|
||||
auto metrics_snapshot = metrics_collector.get_metrics();
|
||||
|
||||
// Source plugin
|
||||
if(source != falco_common::syscall_source) {
|
||||
// Performed repeatedly for each inspectors' libs metrics collector
|
||||
for(auto& metric : metrics_snapshot) {
|
||||
if(metric.flags & METRICS_V2_PLUGINS) {
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric,
|
||||
"falcosecurity",
|
||||
"plugins");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Source syscall
|
||||
for(auto& metric : metrics_snapshot) {
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
std::string prometheus_subsystem = "scap";
|
||||
|
||||
if(metric.flags & METRICS_V2_RESOURCE_UTILIZATION) {
|
||||
prometheus_subsystem = "falco";
|
||||
}
|
||||
|
||||
if(metric.flags & METRICS_V2_PLUGINS) {
|
||||
prometheus_subsystem = "plugins";
|
||||
}
|
||||
|
||||
// raw incoming in form of for example n_evts_cpu_15 or n_drops_cpu_15
|
||||
if(strncmp(metric.name, "n_evts_cpu", 10) == 0 ||
|
||||
strncmp(metric.name, "n_drops_cpu", 11) == 0) // prefix match
|
||||
{
|
||||
std::string name_str(metric.name);
|
||||
std::string cpu_number;
|
||||
if(re2::RE2::PartialMatch(name_str, cpu_pattern, &cpu_number)) {
|
||||
re2::RE2::GlobalReplace(&name_str, cpu_pattern, "");
|
||||
// possible double __ will be sanitized within libs
|
||||
auto metric_new = libs::metrics::libsinsp_metrics::new_metric(
|
||||
name_str.c_str(),
|
||||
METRICS_V2_KERNEL_COUNTERS_PER_CPU,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
metric.value.u64);
|
||||
const std::map<std::string, std::string>& const_labels = {
|
||||
{"cpu", cpu_number}};
|
||||
/* Examples ...
|
||||
# HELP falcosecurity_scap_n_evts_cpu_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_scap_n_evts_cpu_total counter
|
||||
falcosecurity_scap_n_evts_cpu_total{cpu="7"} 237
|
||||
# HELP falcosecurity_scap_n_drops_cpu_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_scap_n_drops_cpu_total counter
|
||||
falcosecurity_scap_n_drops_cpu_total{cpu="7"} 0
|
||||
*/
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric_new,
|
||||
"falcosecurity",
|
||||
prometheus_subsystem,
|
||||
const_labels);
|
||||
}
|
||||
} else if(strcmp(metric.name, "n_drops_buffer_total") == 0) {
|
||||
// Skip the libs aggregate metric since we distinguish between buffer drops
|
||||
// using labels similar to the rules_matches
|
||||
continue;
|
||||
} else if(strncmp(metric.name, "n_drops_buffer", 14) == 0) // prefix match
|
||||
{
|
||||
std::string drop;
|
||||
std::string dir;
|
||||
std::string name_str(metric.name);
|
||||
if(re2::RE2::FullMatch(name_str, drops_buffer_pattern, &drop, &dir)) {
|
||||
auto metric_new = libs::metrics::libsinsp_metrics::new_metric(
|
||||
"n_drops_buffer",
|
||||
METRICS_V2_KERNEL_COUNTERS,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
metric.value.u64);
|
||||
const std::map<std::string, std::string>& const_labels = {{"drop", drop},
|
||||
{"dir", dir}};
|
||||
/* Examples ...
|
||||
# HELP falcosecurity_scap_n_drops_buffer_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_scap_n_drops_buffer_total counter
|
||||
falcosecurity_scap_n_drops_buffer_total{dir="enter",drop="clone_fork"} 0
|
||||
# HELP falcosecurity_scap_n_drops_buffer_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_scap_n_drops_buffer_total counter
|
||||
falcosecurity_scap_n_drops_buffer_total{dir="exit",drop="clone_fork"} 0
|
||||
*/
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric_new,
|
||||
"falcosecurity",
|
||||
prometheus_subsystem,
|
||||
const_labels);
|
||||
}
|
||||
} else {
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric,
|
||||
"falcosecurity",
|
||||
prometheus_subsystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Source wrapper metrics Part B: Agnostic, performed only once.
|
||||
if(agent_info_written && machine_info_written) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const scap_agent_info* agent_info = nullptr;
|
||||
if(!agent_info_written) {
|
||||
agent_info = source_inspector->get_agent_info();
|
||||
}
|
||||
const scap_machine_info* machine_info = nullptr;
|
||||
if(!machine_info_written) {
|
||||
machine_info = source_inspector->get_machine_info();
|
||||
}
|
||||
|
||||
// Not all scap engines report agent and machine infos.
|
||||
// However, recent lib refactors enable a linux lite platform, allowing non-syscall
|
||||
// inspectors to retrieve these metrics if the syscall inspector is unavailable.
|
||||
// We only push these info once.
|
||||
if(agent_info) {
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"kernel_release",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"kernel_release", agent_info->uname_r}});
|
||||
}
|
||||
if(machine_info) {
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"hostname",
|
||||
"falcosecurity",
|
||||
"evt",
|
||||
{{"hostname", machine_info->hostname}});
|
||||
}
|
||||
|
||||
#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
|
||||
// Distinguish between config and rules files using labels, following Prometheus best
|
||||
// practices: https://prometheus.io/docs/practices/naming/#labels
|
||||
for(const auto& item : state.config.get()->m_loaded_rules_filenames_sha256sum) {
|
||||
fs::path fs_path = item.first;
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"sha256_rules_files",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"file_name", fs_path.filename()}, {"sha256", item.second}});
|
||||
}
|
||||
|
||||
for(const auto& item : state.config.get()->m_loaded_configs_filenames_sha256sum) {
|
||||
fs::path fs_path = item.first;
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"sha256_config_files",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"file_name", fs_path.filename()}, {"sha256", item.second}});
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for(const std::string& source : inspector->event_sources()) {
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"evt_source",
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
{{"evt_source", source}});
|
||||
}
|
||||
std::vector<metrics_v2> additional_wrapper_metrics;
|
||||
|
||||
if(agent_info) {
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"start_ts",
|
||||
METRICS_V2_MISC,
|
||||
|
@ -151,8 +425,25 @@ std::string falco_metrics::to_text(const falco::app::state& state) {
|
|||
METRIC_VALUE_UNIT_TIME_TIMESTAMP_NS,
|
||||
METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT,
|
||||
agent_info->start_ts_epoch));
|
||||
auto now = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"duration_sec",
|
||||
METRICS_V2_MISC,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_TIME_S_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
(uint64_t)((now - agent_info->start_ts_epoch) / ONE_SECOND_IN_NS)));
|
||||
agent_info_written = true;
|
||||
}
|
||||
|
||||
if(machine_info) {
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
"hostname",
|
||||
"falcosecurity",
|
||||
"evt",
|
||||
{{"hostname", machine_info->hostname}});
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"host_boot_ts",
|
||||
METRICS_V2_MISC,
|
||||
|
@ -167,225 +458,41 @@ std::string falco_metrics::to_text(const falco::app::state& state) {
|
|||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT,
|
||||
machine_info->num_cpus));
|
||||
machine_info_written = true;
|
||||
}
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"outputs_queue_num_drops",
|
||||
METRICS_V2_MISC,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
state.outputs->get_outputs_queue_num_drops()));
|
||||
} // End inspector loop
|
||||
|
||||
return prometheus_text;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this method takes an application \c state and returns a textual representation of
|
||||
its configured metrics.
|
||||
|
||||
The current implementation returns a Prometheus exposition formatted string.
|
||||
*/
|
||||
std::string falco_metrics::to_text_prometheus(const falco::app::state& state) {
|
||||
libs::metrics::prometheus_metrics_converter prometheus_metrics_converter;
|
||||
std::string prometheus_text;
|
||||
|
||||
std::vector<metrics_v2> additional_wrapper_metrics;
|
||||
|
||||
// Falco global metrics, once
|
||||
prometheus_text += falco_to_text_prometheus(state,
|
||||
prometheus_metrics_converter,
|
||||
additional_wrapper_metrics);
|
||||
// Metrics for each source
|
||||
prometheus_text += sources_to_text_prometheus(state,
|
||||
prometheus_metrics_converter,
|
||||
additional_wrapper_metrics);
|
||||
|
||||
for(auto metric : additional_wrapper_metrics) {
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(metric,
|
||||
"falcosecurity",
|
||||
"falco");
|
||||
}
|
||||
|
||||
if(agent_info) {
|
||||
auto now = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"duration_sec",
|
||||
METRICS_V2_MISC,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_TIME_S_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
(uint64_t)((now - agent_info->start_ts_epoch) / ONE_SECOND_IN_NS)));
|
||||
}
|
||||
|
||||
for(auto metric : additional_wrapper_metrics) {
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(metric,
|
||||
"falcosecurity",
|
||||
"falco");
|
||||
}
|
||||
|
||||
// Falco metrics categories
|
||||
//
|
||||
// rules_counters_enabled
|
||||
if(state.config->m_metrics_flags & METRICS_V2_RULE_COUNTERS) {
|
||||
const stats_manager& rule_stats_manager = state.engine->get_rule_stats_manager();
|
||||
const indexed_vector<falco_rule>& rules = state.engine->get_rules();
|
||||
const std::vector<std::unique_ptr<std::atomic<uint64_t>>>& rules_by_id =
|
||||
rule_stats_manager.get_by_rule_id();
|
||||
// Distinguish between rules counters using labels, following Prometheus best practices:
|
||||
// https://prometheus.io/docs/practices/naming/#labels
|
||||
for(size_t i = 0; i < rules_by_id.size(); i++) {
|
||||
auto rule = rules.at(i);
|
||||
auto count = rules_by_id[i]->load();
|
||||
if(count > 0) {
|
||||
/* Examples ...
|
||||
# HELP falcosecurity_falco_rules_matches_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_falco_rules_matches_total counter
|
||||
falcosecurity_falco_rules_matches_total{priority="4",rule_name="Read
|
||||
sensitive file
|
||||
untrusted",source="syscall",tag_T1555="true",tag_container="true",tag_filesystem="true",tag_host="true",tag_maturity_stable="true",tag_mitre_credential_access="true"}
|
||||
10 # HELP falcosecurity_falco_rules_matches_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_falco_rules_matches_total counter
|
||||
falcosecurity_falco_rules_matches_total{priority="5",rule_name="Unexpected
|
||||
UDP
|
||||
Traffic",source="syscall",tag_TA0011="true",tag_container="true",tag_host="true",tag_maturity_incubating="true",tag_mitre_exfiltration="true",tag_network="true"}
|
||||
1
|
||||
*/
|
||||
auto metric = libs::metrics::libsinsp_metrics::new_metric(
|
||||
"rules_matches",
|
||||
METRICS_V2_RULE_COUNTERS,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
rules_by_id[i]->load());
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
std::map<std::string, std::string> const_labels = {
|
||||
{"rule_name", rule->name},
|
||||
{"priority", std::to_string(rule->priority)},
|
||||
{"source", rule->source},
|
||||
};
|
||||
std::for_each(rule->tags.cbegin(),
|
||||
rule->tags.cend(),
|
||||
[&const_labels](std::string const& tag) {
|
||||
const_labels.emplace(std::string{"tag_"} + tag, "true");
|
||||
});
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric,
|
||||
"falcosecurity",
|
||||
"falco",
|
||||
const_labels);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAS_JEMALLOC
|
||||
if(state.config->m_metrics_flags & METRICS_V2_JEMALLOC_STATS) {
|
||||
nlohmann::json j;
|
||||
malloc_stats_print(
|
||||
[](void* to, const char* from) {
|
||||
nlohmann::json* j = (nlohmann::json*)to;
|
||||
*j = nlohmann::json::parse(from);
|
||||
},
|
||||
&j,
|
||||
"Jmdablxeg");
|
||||
const auto& j_stats = j["jemalloc"]["stats"];
|
||||
for(auto it = j_stats.begin(); it != j_stats.end(); ++it) {
|
||||
if(it.value().is_number_unsigned()) {
|
||||
std::uint64_t val = it.value().template get<std::uint64_t>();
|
||||
std::string key = "jemalloc." + it.key();
|
||||
auto metric = libs::metrics::libsinsp_metrics::new_metric(
|
||||
key.c_str(),
|
||||
METRICS_V2_JEMALLOC_STATS,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_MEMORY_BYTES,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
val);
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric,
|
||||
"falcosecurity",
|
||||
"falco");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Libs metrics categories
|
||||
//
|
||||
// resource_utilization_enabled
|
||||
// state_counters_enabled
|
||||
// kernel_event_counters_enabled
|
||||
// libbpf_stats_enabled
|
||||
for(auto metrics_collector : metrics_collectors) {
|
||||
metrics_collector.snapshot();
|
||||
auto metrics_snapshot = metrics_collector.get_metrics();
|
||||
|
||||
for(auto& metric : metrics_snapshot) {
|
||||
prometheus_metrics_converter.convert_metric_to_unit_convention(metric);
|
||||
std::string prometheus_subsystem = "scap";
|
||||
|
||||
if(metric.flags & METRICS_V2_RESOURCE_UTILIZATION) {
|
||||
prometheus_subsystem = "falco";
|
||||
}
|
||||
|
||||
if(metric.flags & METRICS_V2_PLUGINS) {
|
||||
prometheus_subsystem = "plugins";
|
||||
}
|
||||
|
||||
// raw incoming in form of for example n_evts_cpu_15 or n_drops_cpu_15
|
||||
if(strncmp(metric.name, "n_evts_cpu", 10) == 0 ||
|
||||
strncmp(metric.name, "n_drops_cpu", 11) == 0) // prefix match
|
||||
{
|
||||
std::string name_str(metric.name);
|
||||
re2::RE2 pattern("(\\d+)");
|
||||
std::string cpu_number;
|
||||
if(re2::RE2::PartialMatch(name_str, pattern, &cpu_number)) {
|
||||
re2::RE2::GlobalReplace(&name_str, pattern, "");
|
||||
// possible double __ will be sanitized within libs
|
||||
auto metric_new = libs::metrics::libsinsp_metrics::new_metric(
|
||||
name_str.c_str(),
|
||||
METRICS_V2_KERNEL_COUNTERS_PER_CPU,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
metric.value.u64);
|
||||
const std::map<std::string, std::string>& const_labels = {{"cpu", cpu_number}};
|
||||
/* Examples ...
|
||||
# HELP falcosecurity_scap_n_evts_cpu_total https://falco.org/docs/metrics/
|
||||
# TYPE falcosecurity_scap_n_evts_cpu_total counter
|
||||
falcosecurity_scap_n_evts_cpu_total{cpu="7"} 237
|
||||
# HELP falcosecurity_scap_n_drops_cpu_total https://falco.org/docs/metrics/
|
||||
# TYPE falcosecurity_scap_n_drops_cpu_total counter
|
||||
falcosecurity_scap_n_drops_cpu_total{cpu="7"} 0
|
||||
*/
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric_new,
|
||||
"falcosecurity",
|
||||
prometheus_subsystem,
|
||||
const_labels);
|
||||
}
|
||||
} else if(strcmp(metric.name, "n_drops_buffer_total") == 0) {
|
||||
// Skip the libs aggregate metric since we distinguish between buffer drops using
|
||||
// labels similar to the rules_matches
|
||||
continue;
|
||||
} else if(strncmp(metric.name, "n_drops_buffer", 14) == 0) // prefix match
|
||||
{
|
||||
re2::RE2 pattern("n_drops_buffer_([^_]+(?:_[^_]+)*)_(enter|exit)$");
|
||||
std::string drop;
|
||||
std::string dir;
|
||||
std::string name_str(metric.name);
|
||||
if(re2::RE2::FullMatch(name_str, pattern, &drop, &dir)) {
|
||||
auto metric_new = libs::metrics::libsinsp_metrics::new_metric(
|
||||
"n_drops_buffer",
|
||||
METRICS_V2_KERNEL_COUNTERS,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
metric.value.u64);
|
||||
const std::map<std::string, std::string>& const_labels = {{"drop", drop},
|
||||
{"dir", dir}};
|
||||
/* Examples ...
|
||||
# HELP falcosecurity_scap_n_drops_buffer_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_scap_n_drops_buffer_total counter
|
||||
falcosecurity_scap_n_drops_buffer_total{dir="enter",drop="clone_fork"} 0
|
||||
# HELP falcosecurity_scap_n_drops_buffer_total
|
||||
https://falco.org/docs/metrics/ # TYPE
|
||||
falcosecurity_scap_n_drops_buffer_total counter
|
||||
falcosecurity_scap_n_drops_buffer_total{dir="exit",drop="clone_fork"} 0
|
||||
*/
|
||||
prometheus_text +=
|
||||
prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric_new,
|
||||
"falcosecurity",
|
||||
prometheus_subsystem,
|
||||
const_labels);
|
||||
}
|
||||
} else {
|
||||
prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus(
|
||||
metric,
|
||||
"falcosecurity",
|
||||
prometheus_subsystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
return prometheus_text;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,16 @@ struct state;
|
|||
|
||||
class falco_metrics {
|
||||
public:
|
||||
static const std::string content_type;
|
||||
static std::string to_text(const falco::app::state& state);
|
||||
static const std::string content_type_prometheus;
|
||||
static std::string to_text_prometheus(const falco::app::state& state);
|
||||
|
||||
private:
|
||||
static std::string falco_to_text_prometheus(
|
||||
const falco::app::state& state,
|
||||
libs::metrics::prometheus_metrics_converter& prometheus_metrics_converter,
|
||||
std::vector<metrics_v2>& additional_wrapper_metrics);
|
||||
static std::string sources_to_text_prometheus(
|
||||
const falco::app::state& state,
|
||||
libs::metrics::prometheus_metrics_converter& prometheus_metrics_converter,
|
||||
std::vector<metrics_v2>& additional_wrapper_metrics);
|
||||
};
|
||||
|
|
|
@ -233,7 +233,6 @@ void stats_writer::worker() noexcept {
|
|||
bool use_file = !m_config->m_metrics_output_file.empty();
|
||||
auto tick = stats_writer::get_ticker();
|
||||
auto last_tick = tick;
|
||||
auto first_tick = tick;
|
||||
|
||||
while(true) {
|
||||
// blocks until a message becomes availables
|
||||
|
@ -244,35 +243,33 @@ void stats_writer::worker() noexcept {
|
|||
return;
|
||||
}
|
||||
|
||||
// this helps waiting for the first tick
|
||||
tick = stats_writer::get_ticker();
|
||||
if(first_tick != tick) {
|
||||
if(last_tick != tick) {
|
||||
m_total_samples++;
|
||||
}
|
||||
last_tick = tick;
|
||||
|
||||
try {
|
||||
if(use_outputs) {
|
||||
std::string rule = "Falco internal: metrics snapshot";
|
||||
std::string msg = "Falco metrics snapshot";
|
||||
m_outputs->handle_msg(m.ts,
|
||||
falco_common::PRIORITY_INFORMATIONAL,
|
||||
msg,
|
||||
rule,
|
||||
m.output_fields);
|
||||
}
|
||||
if(last_tick != tick) {
|
||||
m_total_samples++;
|
||||
}
|
||||
last_tick = tick;
|
||||
|
||||
if(use_file) {
|
||||
nlohmann::json jmsg;
|
||||
jmsg["sample"] = m_total_samples;
|
||||
jmsg["output_fields"] = m.output_fields;
|
||||
m_file_output << jmsg.dump() << std::endl;
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
falco_logger::log(falco_logger::level::ERR,
|
||||
"stats_writer (worker): " + std::string(e.what()) + "\n");
|
||||
try {
|
||||
if(use_outputs) {
|
||||
std::string rule = "Falco internal: metrics snapshot";
|
||||
std::string msg = "Falco metrics snapshot";
|
||||
m_outputs->handle_msg(m.ts,
|
||||
falco_common::PRIORITY_INFORMATIONAL,
|
||||
msg,
|
||||
rule,
|
||||
m.output_fields);
|
||||
}
|
||||
|
||||
if(use_file) {
|
||||
nlohmann::json jmsg;
|
||||
jmsg["sample"] = m_total_samples;
|
||||
jmsg["output_fields"] = m.output_fields;
|
||||
m_file_output << jmsg.dump() << std::endl;
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
falco_logger::log(falco_logger::level::ERR,
|
||||
"stats_writer (worker): " + std::string(e.what()) + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,6 +350,7 @@ void stats_writer::collector::get_metrics_output_fields_wrapper(
|
|||
/* Wrapper fields useful for statistical analyses and attributions. Always enabled. */
|
||||
output_fields["evt.time"] =
|
||||
now; /* Some ETLs may prefer a consistent timestamp within output_fields. */
|
||||
output_fields["falco.reload_ts"] = m_writer->m_config->m_falco_reload_ts;
|
||||
output_fields["falco.version"] = FALCO_VERSION;
|
||||
if(agent_info) {
|
||||
output_fields["falco.start_ts"] = agent_info->start_ts_epoch;
|
||||
|
@ -659,6 +657,7 @@ void stats_writer::collector::collect(const std::shared_ptr<sinsp>& inspector,
|
|||
num_evts,
|
||||
now,
|
||||
stats_snapshot_time_delta_sec);
|
||||
|
||||
get_metrics_output_fields_additional(output_fields, stats_snapshot_time_delta_sec);
|
||||
|
||||
/* Send message in the queue */
|
||||
|
|
|
@ -82,7 +82,9 @@ public:
|
|||
double stats_snapshot_time_delta_sec);
|
||||
|
||||
std::shared_ptr<stats_writer> m_writer;
|
||||
stats_writer::ticker_t m_last_tick = 0;
|
||||
// Init m_last_tick w/ invalid value to enable metrics logging immediately after
|
||||
// startup/reload
|
||||
stats_writer::ticker_t m_last_tick = std::numeric_limits<ticker_t>::max();
|
||||
uint64_t m_last_now = 0;
|
||||
uint64_t m_last_n_evts = 0;
|
||||
uint64_t m_last_n_drops = 0;
|
||||
|
|
|
@ -60,7 +60,8 @@ void falco_webserver::start(const falco::app::state &state,
|
|||
|
||||
if(state.config->m_metrics_enabled && webserver_config.m_prometheus_metrics_enabled) {
|
||||
m_server->Get("/metrics", [&state](const httplib::Request &, httplib::Response &res) {
|
||||
res.set_content(falco_metrics::to_text(state), falco_metrics::content_type);
|
||||
res.set_content(falco_metrics::to_text_prometheus(state),
|
||||
falco_metrics::content_type_prometheus);
|
||||
});
|
||||
}
|
||||
// run server in a separate thread
|
||||
|
|
Loading…
Reference in New Issue