mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-20 03:32:09 +00:00
Compare commits
79 Commits
temporary/
...
0.27.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7691dba3ff | ||
|
|
c736689f6f | ||
|
|
3bcd2ca70d | ||
|
|
2e443e7660 | ||
|
|
bec5121fa4 | ||
|
|
ee0b7daba0 | ||
|
|
b2bbb265b4 | ||
|
|
0d7068b048 | ||
|
|
7f33b08634 | ||
|
|
c2a05b3e64 | ||
|
|
581d67fa08 | ||
|
|
b7bda6d892 | ||
|
|
5eec26976d | ||
|
|
1916314583 | ||
|
|
8831c7f3c7 | ||
|
|
2cebe052a1 | ||
|
|
05282f3976 | ||
|
|
da4a5b1456 | ||
|
|
36e9c2ba17 | ||
|
|
0c8b4a2127 | ||
|
|
356b3e1451 | ||
|
|
9eb60f04ff | ||
|
|
ff29188cb2 | ||
|
|
4fb7e99c68 | ||
|
|
d03a1f4a9b | ||
|
|
574e7f433b | ||
|
|
f6fa18e7ec | ||
|
|
6beb9838d6 | ||
|
|
9a175cb1db | ||
|
|
32daac3e4d | ||
|
|
0a901e4f52 | ||
|
|
22732e9edb | ||
|
|
6a352338e3 | ||
|
|
f8b66d051b | ||
|
|
c237ddc738 | ||
|
|
9d31164a71 | ||
|
|
f433b449d9 | ||
|
|
44955004e3 | ||
|
|
a9dac551b8 | ||
|
|
df8e4e0545 | ||
|
|
321da3e5bf | ||
|
|
4b34b83739 | ||
|
|
5b558cd600 | ||
|
|
3b7401c2e5 | ||
|
|
aea12f4f3b | ||
|
|
f2637c8600 | ||
|
|
0a14d34e16 | ||
|
|
a1bdf3ed61 | ||
|
|
d3c41c2d97 | ||
|
|
90d71a8e92 | ||
|
|
8eb7d83ee8 | ||
|
|
3b78cda716 | ||
|
|
6ca4e11d8c | ||
|
|
6bc97ca9e7 | ||
|
|
71e56ac87c | ||
|
|
12b7ff9940 | ||
|
|
648bb6294f | ||
|
|
dada3db3f2 | ||
|
|
2b2856299c | ||
|
|
ec5b42074e | ||
|
|
0b516b7d42 | ||
|
|
4954593261 | ||
|
|
0eff0f6003 | ||
|
|
8d10a60e42 | ||
|
|
4d6636a030 | ||
|
|
55a93bce8b | ||
|
|
0f14821744 | ||
|
|
e0175b1e06 | ||
|
|
8be299939a | ||
|
|
9828c6aeb6 | ||
|
|
7ee0eb7e9c | ||
|
|
0f155c3a1f | ||
|
|
3258bdd990 | ||
|
|
9f41a390a7 | ||
|
|
7aa6fa9897 | ||
|
|
8dd9ebbdf9 | ||
|
|
0852a88a16 | ||
|
|
cea9c6a377 | ||
|
|
c055f02dd0 |
4
.circleci/OWNERS
Normal file
4
.circleci/OWNERS
Normal file
@@ -0,0 +1,4 @@
|
||||
approvers:
|
||||
- jonahjon
|
||||
reviewers:
|
||||
- jonahjon
|
||||
@@ -452,6 +452,25 @@ jobs:
|
||||
docker build --build-arg FALCO_IMAGE_TAG=master -t falcosecurity/falco-driver-loader:master docker/driver-loader
|
||||
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
|
||||
docker push falcosecurity/falco-driver-loader:master
|
||||
# Publish container images to AWS ECR Public
|
||||
"publish/container-images-aws-dev":
|
||||
docker:
|
||||
- image: docker:stable
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Build and publish falco to AWS
|
||||
command: |
|
||||
apk update
|
||||
apk add --update groff less py-pip
|
||||
pip install awscli
|
||||
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||
docker build --build-arg VERSION_BUCKET=deb-dev --build-arg FALCO_VERSION=${FALCO_VERSION} -t "public.ecr.aws/falcosecurity/falco:master" docker/falco
|
||||
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/falcosecurity
|
||||
docker push "public.ecr.aws/falcosecurity/falco:master"
|
||||
# Publish the packages
|
||||
"publish/packages":
|
||||
docker:
|
||||
@@ -518,6 +537,26 @@ jobs:
|
||||
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
|
||||
docker push "falcosecurity/falco-driver-loader:${CIRCLE_TAG}"
|
||||
docker push "falcosecurity/falco-driver-loader:latest"
|
||||
# Publish container images to AWS ECR Public
|
||||
"publish/container-images-aws":
|
||||
docker:
|
||||
- image: docker:stable
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Build and publish falco to AWS
|
||||
command: |
|
||||
apk update
|
||||
apk add --update groff less py-pip
|
||||
pip install awscli
|
||||
docker build --build-arg VERSION_BUCKET=deb --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "public.ecr.aws/falcosecurity/falco:${CIRCLE_TAG}" docker/falco
|
||||
docker tag "public.ecr.aws/falcosecurity/falco:${CIRCLE_TAG}" public.ecr.aws/falcosecurity/falco:latest
|
||||
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/falcosecurity
|
||||
docker push "public.ecr.aws/falcosecurity/falco:${CIRCLE_TAG}"
|
||||
docker push "public.ecr.aws/falcosecurity/falco:latest"
|
||||
workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
@@ -577,7 +616,16 @@ workflows:
|
||||
requires:
|
||||
- "publish/packages-dev"
|
||||
- "tests/driver-loader/integration"
|
||||
- "quality/static-analysis"
|
||||
- "publish/container-images-aws-dev":
|
||||
context: test-infra # contains Falco AWS credentials
|
||||
filters:
|
||||
tags:
|
||||
ignore: /.*/
|
||||
branches:
|
||||
only: master
|
||||
requires:
|
||||
- publish/docker-dev
|
||||
# - "quality/static-analysis" # This is temporarly disabled: https://github.com/falcosecurity/falco/issues/1526
|
||||
release:
|
||||
jobs:
|
||||
- "build/musl":
|
||||
@@ -620,3 +668,12 @@ workflows:
|
||||
only: /.*/
|
||||
branches:
|
||||
ignore: /.*/
|
||||
- "publish/container-images-aws":
|
||||
context: test-infra # contains Falco AWS credentials
|
||||
requires:
|
||||
- "publish/docker"
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
||||
20
.github/stale.yml
vendored
20
.github/stale.yml
vendored
@@ -1,20 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- cncf
|
||||
- roadmap
|
||||
- "help wanted"
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
Issues labeled "cncf", "roadmap" and "help wanted" will not be automatically closed.
|
||||
Please refer to a maintainer to get such label added if you think this should be kept open.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
74
CHANGELOG.md
74
CHANGELOG.md
@@ -1,5 +1,79 @@
|
||||
# Change Log
|
||||
|
||||
## v0.27.0
|
||||
|
||||
Released on 2021-01-18
|
||||
|
||||
### Major Changes
|
||||
|
||||
* new: Added falco engine version to grpc version service [[#1507](https://github.com/falcosecurity/falco/pull/1507)] - [@nibalizer](https://github.com/nibalizer)
|
||||
* BREAKING CHANGE: Users who run Falco without a config file will be unable to do that any more, Falco now expects a configuration file to be passed all the times. Developers may need to adjust their processes. [[#1494](https://github.com/falcosecurity/falco/pull/1494)] - [@nibalizer](https://github.com/nibalizer)
|
||||
* new: asynchronous outputs implementation, outputs channels will not block event processing anymore [[#1451](https://github.com/falcosecurity/falco/pull/1451)] - [@leogr](https://github.com/leogr)
|
||||
* new: slow outputs detection [[#1451](https://github.com/falcosecurity/falco/pull/1451)] - [@leogr](https://github.com/leogr)
|
||||
* new: `output_timeout` config option for slow outputs detection [[#1451](https://github.com/falcosecurity/falco/pull/1451)] - [@leogr](https://github.com/leogr)
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* build: bump b64 to v2.0.0.1 [[#1441](https://github.com/falcosecurity/falco/pull/1441)] - [@fntlnz](https://github.com/fntlnz)
|
||||
* rules(macro container_started): re-use `spawned_process` macro inside `container_started` macro [[#1449](https://github.com/falcosecurity/falco/pull/1449)] - [@leodido](https://github.com/leodido)
|
||||
* docs: reach out documentation [[#1472](https://github.com/falcosecurity/falco/pull/1472)] - [@fntlnz](https://github.com/fntlnz)
|
||||
* docs: Broken outputs.proto link [[#1493](https://github.com/falcosecurity/falco/pull/1493)] - [@deepskyblue86](https://github.com/deepskyblue86)
|
||||
* docs(README.md): correct broken links [[#1506](https://github.com/falcosecurity/falco/pull/1506)] - [@leogr](https://github.com/leogr)
|
||||
* docs(proposals): Exceptions handling proposal [[#1376](https://github.com/falcosecurity/falco/pull/1376)] - [@mstemm](https://github.com/mstemm)
|
||||
* docs: fix a broken link of README [[#1516](https://github.com/falcosecurity/falco/pull/1516)] - [@oke-py](https://github.com/oke-py)
|
||||
* docs: adding the kubernetes privileged use case to use cases [[#1484](https://github.com/falcosecurity/falco/pull/1484)] - [@fntlnz](https://github.com/fntlnz)
|
||||
* rules(Mkdir binary dirs): Adds exe_running_docker_save as an exception as this rules can be triggerred when a container is created. [[#1386](https://github.com/falcosecurity/falco/pull/1386)] - [@jhwbarlow](https://github.com/jhwbarlow)
|
||||
* rules(Create Hidden Files): Adds exe_running_docker_save as an exception as this rules can be triggerred when a container is created. [[#1386](https://github.com/falcosecurity/falco/pull/1386)] - [@jhwbarlow](https://github.com/jhwbarlow)
|
||||
* docs(.circleci): welcome Jonah (Amazon) as a new Falco CI maintainer [[#1518](https://github.com/falcosecurity/falco/pull/1518)] - [@leodido](https://github.com/leodido)
|
||||
* build: falcosecurity/falco:master also available on the AWS ECR Public registry [[#1512](https://github.com/falcosecurity/falco/pull/1512)] - [@leodido](https://github.com/leodido)
|
||||
* build: falcosecurity/falco:latest also available on the AWS ECR Public registry [[#1512](https://github.com/falcosecurity/falco/pull/1512)] - [@leodido](https://github.com/leodido)
|
||||
* update: gRPC clients can now subscribe to drop alerts via gRCP API [[#1451](https://github.com/falcosecurity/falco/pull/1451)] - [@leogr](https://github.com/leogr)
|
||||
* macro(allowed_k8s_users): exclude cloud-controller-manage to avoid false positives on k3s [[#1444](https://github.com/falcosecurity/falco/pull/1444)] - [@fntlnz](https://github.com/fntlnz)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(userspace/falco): use given priority in falco_outputs::handle_msg() [[#1450](https://github.com/falcosecurity/falco/pull/1450)] - [@leogr](https://github.com/leogr)
|
||||
* fix(userspace/engine): free formatters, if any [[#1447](https://github.com/falcosecurity/falco/pull/1447)] - [@leogr](https://github.com/leogr)
|
||||
* fix(scripts/falco-driver-loader): lsmod usage [[#1474](https://github.com/falcosecurity/falco/pull/1474)] - [@dnwe](https://github.com/dnwe)
|
||||
* fix: a bug that prevents Falco driver to be consumed by many Falco instances in some circumstances [[#1485](https://github.com/falcosecurity/falco/pull/1485)] - [@leodido](https://github.com/leodido)
|
||||
* fix: set `HOST_ROOT=/host` environment variable for the `falcosecurity/falco-no-driver` container image by default [[#1492](https://github.com/falcosecurity/falco/pull/1492)] - [@leogr](https://github.com/leogr)
|
||||
|
||||
|
||||
### Rule Changes
|
||||
|
||||
* rule(list user_known_change_thread_namespace_binaries): add crio and multus to the list [[#1501](https://github.com/falcosecurity/falco/pull/1501)] - [@Kaizhe](https://github.com/Kaizhe)
|
||||
* rule(Container Run as Root User): new rule created [[#1500](https://github.com/falcosecurity/falco/pull/1500)] - [@Kaizhe](https://github.com/Kaizhe)
|
||||
* rule(Linux Kernel Module injection detected): adds a new rule that detects when an LKM module is injected using `insmod` from a container (typically used by rootkits looking to obfuscate their behavior via kernel hooking). [[#1478](https://github.com/falcosecurity/falco/pull/1478)] - [@d1vious](https://github.com/d1vious)
|
||||
* rule(macro multipath_writing_conf): create and use the macro [[#1475](https://github.com/falcosecurity/falco/pull/1475)] - [@nmarier-coveo](https://github.com/nmarier-coveo)
|
||||
* rule(list falco_privileged_images): add calico/node without registry prefix to prevent false positive alerts [[#1457](https://github.com/falcosecurity/falco/pull/1457)] - [@czunker](https://github.com/czunker)
|
||||
* rule(Full K8s Administrative Access): use the right list of admin users (fix) [[#1454](https://github.com/falcosecurity/falco/pull/1454)] - [@mstemm](https://github.com/mstemm)
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* chore(cmake): remove unnecessary whitespace patch [[#1522](https://github.com/falcosecurity/falco/pull/1522)] - [@leogr](https://github.com/leogr)
|
||||
* remove stale bot in favor of the new lifecycle bot [[#1490](https://github.com/falcosecurity/falco/pull/1490)] - [@leodido](https://github.com/leodido)
|
||||
* chore(cmake): mark some variables as advanced [[#1496](https://github.com/falcosecurity/falco/pull/1496)] - [@deepskyblue86](https://github.com/deepskyblue86)
|
||||
* chore(cmake/modules): avoid useless rebuild [[#1495](https://github.com/falcosecurity/falco/pull/1495)] - [@deepskyblue86](https://github.com/deepskyblue86)
|
||||
* build: BUILD_BYPRODUCTS for civetweb [[#1489](https://github.com/falcosecurity/falco/pull/1489)] - [@fntlnz](https://github.com/fntlnz)
|
||||
* build: remove duplicate item from FALCO_SOURCES [[#1480](https://github.com/falcosecurity/falco/pull/1480)] - [@leodido](https://github.com/leodido)
|
||||
* build: make our integration tests report clear steps for CircleCI UI [[#1473](https://github.com/falcosecurity/falco/pull/1473)] - [@fntlnz](https://github.com/fntlnz)
|
||||
* further improvements outputs impl. [[#1443](https://github.com/falcosecurity/falco/pull/1443)] - [@leogr](https://github.com/leogr)
|
||||
* fix(test): make integration tests properly fail [[#1439](https://github.com/falcosecurity/falco/pull/1439)] - [@leogr](https://github.com/leogr)
|
||||
* Falco outputs refactoring [[#1412](https://github.com/falcosecurity/falco/pull/1412)] - [@leogr](https://github.com/leogr)
|
||||
|
||||
|
||||
|
||||
## v0.26.2
|
||||
|
||||
Released on 2020-11-10
|
||||
|
||||
### Major Changes
|
||||
|
||||
* update: DRIVERS_REPO now defaults to https://download.falco.org/driver [[#1460](https://github.com/falcosecurity/falco/pull/1460)] - [@leodido](https://github.com/leodido)
|
||||
|
||||
## v0.26.1
|
||||
|
||||
Released on 2020-10-01
|
||||
|
||||
@@ -19,6 +19,15 @@ option(BUILD_WARNINGS_AS_ERRORS "Enable building with -Wextra -Werror flags" OFF
|
||||
option(MINIMAL_BUILD "Build a minimal version of Falco, containing only the engine and basic input/output (EXPERIMENTAL)" OFF)
|
||||
option(MUSL_OPTIMIZED_BUILD "Enable if you want a musl optimized build" OFF)
|
||||
|
||||
# We shouldn't need to set this, see https://gitlab.kitware.com/cmake/cmake/-/issues/16419
|
||||
option(EP_UPDATE_DISCONNECTED "ExternalProject update disconnected" OFF)
|
||||
if (${EP_UPDATE_DISCONNECTED})
|
||||
set_property(
|
||||
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PROPERTY EP_UPDATE_DISCONNECTED TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
# Elapsed time
|
||||
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add a flag to enable this
|
||||
|
||||
@@ -115,20 +124,8 @@ set(CURSES_NEED_NCURSES TRUE)
|
||||
find_package(Curses REQUIRED)
|
||||
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
|
||||
|
||||
# libb64
|
||||
|
||||
set(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
|
||||
message(STATUS "Using bundled b64 in '${B64_SRC}'")
|
||||
set(B64_INCLUDE "${B64_SRC}/include")
|
||||
set(B64_LIB "${B64_SRC}/src/libb64.a")
|
||||
ExternalProject_Add(
|
||||
b64
|
||||
URL "https://github.com/libb64/libb64/archive/ce864b17ea0e24a91e77c7dd3eb2d1ac4175b3f0.tar.gz"
|
||||
URL_HASH "SHA256=d07173e66f435e5c77dbf81bd9313f8d0e4a3b4edd4105a62f4f8132ba932811"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
INSTALL_COMMAND "")
|
||||
# b64
|
||||
include(b64)
|
||||
|
||||
# yaml-cpp
|
||||
include(yaml-cpp)
|
||||
@@ -142,52 +139,16 @@ if(NOT MINIMAL_BUILD)
|
||||
endif()
|
||||
|
||||
# LuaJIT
|
||||
set(LUAJIT_SRC "${PROJECT_BINARY_DIR}/luajit-prefix/src/luajit/src")
|
||||
message(STATUS "Using bundled LuaJIT in '${LUAJIT_SRC}'")
|
||||
set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
|
||||
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
|
||||
ExternalProject_Add(
|
||||
luajit
|
||||
URL "https://github.com/LuaJIT/LuaJIT/archive/v2.0.3.tar.gz"
|
||||
URL_HASH "SHA256=8da3d984495a11ba1bce9a833ba60e18b532ca0641e7d90d97fafe85ff014baa"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
INSTALL_COMMAND "")
|
||||
include(luajit)
|
||||
|
||||
# Lpeg
|
||||
set(LPEG_SRC "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg")
|
||||
set(LPEG_LIB "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg/build/lpeg.a")
|
||||
message(STATUS "Using bundled lpeg in '${LPEG_SRC}'")
|
||||
set(LPEG_DEPENDENCIES "")
|
||||
list(APPEND LPEG_DEPENDENCIES "luajit")
|
||||
ExternalProject_Add(
|
||||
lpeg
|
||||
DEPENDS ${LPEG_DEPENDENCIES}
|
||||
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
|
||||
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
|
||||
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
include(lpeg)
|
||||
|
||||
# libyaml
|
||||
include(libyaml)
|
||||
|
||||
# lyaml
|
||||
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
|
||||
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
|
||||
message(STATUS "Using bundled lyaml in '${LYAML_SRC}'")
|
||||
ExternalProject_Add(
|
||||
lyaml
|
||||
DEPENDS luajit libyaml
|
||||
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
|
||||
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ./configure --enable-static CFLAGS=-I${LIBYAML_INSTALL_DIR}/include CPPFLAGS=-I${LIBYAML_INSTALL_DIR}/include LDFLAGS=-L${LIBYAML_INSTALL_DIR}/lib LIBS=-lyaml LUA=${LUAJIT_SRC}/luajit LUA_INCLUDE=-I${LUAJIT_INCLUDE}
|
||||
INSTALL_COMMAND sh -c
|
||||
"cp -R ${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/lib/* ${PROJECT_SOURCE_DIR}/userspace/engine/lua")
|
||||
include(lyaml)
|
||||
|
||||
# One TBB
|
||||
set(TBB_SRC "${PROJECT_BINARY_DIR}/tbb-prefix/src/tbb")
|
||||
@@ -220,6 +181,7 @@ if(NOT MINIMAL_BUILD)
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/include
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
|
||||
BUILD_BYPRODUCTS ${CIVETWEB_LIB}
|
||||
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
|
||||
endif()
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -26,22 +26,22 @@ If a rule is violated in a system, Falco will send an alert notifying the user o
|
||||
|
||||
### Installing Falco
|
||||
|
||||
If you would like to run Falco in **production** please adhere to the [official installation guide](https://falco.org/docs/installation/).
|
||||
If you would like to run Falco in **production** please adhere to the [official installation guide](https://falco.org/docs/getting-started/installation/).
|
||||
|
||||
##### Kubernetes
|
||||
|
||||
| Tool | Link | Note |
|
||||
|----------|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
|
||||
| Helm | [Chart Repository](https://github.com/falcosecurity/charts/tree/master/falco#introduction) | The Falco community offers regular helm chart releases. |
|
||||
| Minikube | [Tutorial](https://falco.org/docs/third-party/#minikube) | The Falco driver has been baked into minikube for easy deployment. |
|
||||
| Kind | [Tutorial](https://falco.org/docs/third-party/#kind) | Running Falco with kind requires a driver on the host system. |
|
||||
| GKE | [Tutorial](https://falco.org/docs/third-party/#gke) | We suggest using the eBPF driver for running Falco on GKE. |
|
||||
| Minikube | [Tutorial](https://falco.org/docs/getting-started/third-party/#minikube) | The Falco driver has been baked into minikube for easy deployment. |
|
||||
| Kind | [Tutorial](https://falco.org/docs/getting-started/third-party/#kind) | Running Falco with kind requires a driver on the host system. |
|
||||
| GKE | [Tutorial](https://falco.org/docs/getting-started/third-party/#gke) | We suggest using the eBPF driver for running Falco on GKE. |
|
||||
|
||||
### Developing
|
||||
|
||||
Falco is designed to be extensible such that it can be built into cloud-native applications and infrastructure.
|
||||
|
||||
Falco has a [gRPC](https://falco.org/docs/grpc/) endpoint and an API defined in [protobuf](https://github.com/falcosecurity/falco/blob/update-readme/userspace/falco/outputs.proto).
|
||||
Falco has a [gRPC](https://falco.org/docs/grpc/) endpoint and an API defined in [protobuf](https://github.com/falcosecurity/falco/blob/master/userspace/falco/outputs.proto).
|
||||
The Falco Project supports various SDKs for this endpoint.
|
||||
|
||||
##### SDKs
|
||||
@@ -65,6 +65,7 @@ For example, Falco can easily detect incidents including but not limited to:
|
||||
- Unexpected read of a sensitive file, such as `/etc/shadow`.
|
||||
- A non-device file is written to `/dev`.
|
||||
- A standard system binary, such as `ls`, is making an outbound network connection.
|
||||
- A privileged pod is started in a Kubernetes cluster.
|
||||
|
||||
### Documentation
|
||||
|
||||
|
||||
15
RELEASE.md
15
RELEASE.md
@@ -29,7 +29,7 @@ Before cutting a release we need to do some homework in the Falco repository. Th
|
||||
- Double-check if any hard-coded version number is present in the code, it should be not present anywhere:
|
||||
- If any, manually correct it then open an issue to automate version number bumping later
|
||||
- Versions table in the `README.md` update itself automatically
|
||||
- Generate the change log https://github.com/leodido/rn2md, or https://fs.fntlnz.wtf/falco/milestones-changelog.txt for the lazy people (it updates every 5 minutes)
|
||||
- Generate the change log https://github.com/leodido/rn2md:
|
||||
- If you review timeout errors with `rn2md` try to generate an GitHub Oauth access token and use `-t`
|
||||
- Add the latest changes on top the previous `CHANGELOG.md`
|
||||
- Submit a PR with the above modifications
|
||||
@@ -69,13 +69,12 @@ Now assume `x.y.z` is the new version.
|
||||
| deb | [](https://dl.bintray.com/falcosecurity/deb/stable/falco-x.y.z-x86_64.deb) |
|
||||
| tgz | [](https://dl.bintray.com/falcosecurity/bin/x86_64/falco-x.y.z-x86_64.deb) |
|
||||
|
||||
| Images |
|
||||
| --------------------------------------------------------------- |
|
||||
| `docker pull docker.io/falcosecurity/falco:_tag_` |
|
||||
| `docker pull docker.io/falcosecurity/falco-driver-loader:_tag_` |
|
||||
| `docker pull docker.io/falcosecurity/falco-no-driver:_tag_` |
|
||||
|
||||
<!-- Copy the relevant part of the changelog here -->
|
||||
| Images |
|
||||
| --------------------------------------------------------------------------- |
|
||||
| `docker pull docker.io/falcosecurity/falco:x.y.z` |
|
||||
| `docker pull public.ecr.aws/falcosecurity/falco:x.y.z` |
|
||||
| `docker pull docker.io/falcosecurity/falco-driver-loader:x.y.z` |
|
||||
| `docker pull docker.io/falcosecurity/falco-no-driver:x.y.z` |
|
||||
|
||||
### Statistics
|
||||
|
||||
|
||||
@@ -30,9 +30,15 @@ if(NOT CPACK_GENERATOR)
|
||||
endif()
|
||||
|
||||
message(STATUS "Using package generators: ${CPACK_GENERATOR}")
|
||||
|
||||
message(STATUS "Package architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
||||
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
endif()
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.falco.org")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0)")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# "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.
|
||||
#
|
||||
mark_as_advanced(OPENSSL_BINARY)
|
||||
if(NOT USE_BUNDLED_DEPS)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
message(STATUS "Found openssl: include: ${OPENSSL_INCLUDE_DIR}, lib: ${OPENSSL_LIBRARIES}")
|
||||
@@ -20,6 +21,8 @@ if(NOT USE_BUNDLED_DEPS)
|
||||
message(STATUS "Found openssl: binary: ${OPENSSL_BINARY}")
|
||||
endif()
|
||||
else()
|
||||
mark_as_advanced(OPENSSL_BUNDLE_DIR OPENSSL_INSTALL_DIR OPENSSL_INCLUDE_DIR
|
||||
OPENSSL_LIBRARY_SSL OPENSSL_LIBRARY_CRYPTO)
|
||||
set(OPENSSL_BUNDLE_DIR "${PROJECT_BINARY_DIR}/openssl-prefix/src/openssl")
|
||||
set(OPENSSL_INSTALL_DIR "${OPENSSL_BUNDLE_DIR}/target")
|
||||
set(OPENSSL_INCLUDE_DIR "${PROJECT_BINARY_DIR}/openssl-prefix/src/openssl/include")
|
||||
|
||||
27
cmake/modules/b64.cmake
Normal file
27
cmake/modules/b64.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (C) 2020 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(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
|
||||
message(STATUS "Using bundled b64 in '${B64_SRC}'")
|
||||
set(B64_INCLUDE "${B64_SRC}/include")
|
||||
set(B64_LIB "${B64_SRC}/src/libb64.a")
|
||||
externalproject_add(
|
||||
b64
|
||||
URL "https://github.com/libb64/libb64/archive/ce864b17ea0e24a91e77c7dd3eb2d1ac4175b3f0.tar.gz"
|
||||
URL_HASH "SHA256=d07173e66f435e5c77dbf81bd9313f8d0e4a3b4edd4105a62f4f8132ba932811"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${B64_LIB}
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
@@ -22,6 +22,7 @@ if(NOT USE_BUNDLED_DEPS)
|
||||
endif()
|
||||
|
||||
# c-ares
|
||||
mark_as_advanced(CARES_INCLUDE CARES_LIB)
|
||||
find_path(CARES_INCLUDE NAMES ares.h)
|
||||
find_library(CARES_LIB NAMES libcares.so)
|
||||
if(CARES_INCLUDE AND CARES_LIB)
|
||||
@@ -31,6 +32,7 @@ if(NOT USE_BUNDLED_DEPS)
|
||||
endif()
|
||||
|
||||
# protobuf
|
||||
mark_as_advanced(PROTOC PROTOBUF_INCLUDE PROTOBUF_LIB)
|
||||
find_program(PROTOC NAMES protoc)
|
||||
find_path(PROTOBUF_INCLUDE NAMES google/protobuf/message.h)
|
||||
find_library(PROTOBUF_LIB NAMES libprotobuf.so)
|
||||
@@ -43,6 +45,7 @@ if(NOT USE_BUNDLED_DEPS)
|
||||
endif()
|
||||
|
||||
# gpr
|
||||
mark_as_advanced(GPR_LIB)
|
||||
find_library(GPR_LIB NAMES gpr)
|
||||
|
||||
if(GPR_LIB)
|
||||
@@ -52,12 +55,16 @@ if(NOT USE_BUNDLED_DEPS)
|
||||
endif()
|
||||
|
||||
# gRPC todo(fntlnz, leodido): check that gRPC version is greater or equal than 1.8.0
|
||||
mark_as_advanced(GRPC_INCLUDE GRPC_SRC
|
||||
GRPC_LIB GRPC_LIBS_ABSOLUTE GRPCPP_LIB GRPC_CPP_PLUGIN)
|
||||
find_path(GRPCXX_INCLUDE NAMES grpc++/grpc++.h)
|
||||
if(GRPCXX_INCLUDE)
|
||||
set(GRPC_INCLUDE ${GRPCXX_INCLUDE})
|
||||
unset(GRPCXX_INCLUDE CACHE)
|
||||
else()
|
||||
find_path(GRPCPP_INCLUDE NAMES grpcpp/grpcpp.h)
|
||||
set(GRPC_INCLUDE ${GRPCPP_INCLUDE})
|
||||
unset(GRPCPP_INCLUDE CACHE)
|
||||
add_definitions(-DGRPC_INCLUDE_IS_GRPCPP=1)
|
||||
endif()
|
||||
find_library(GRPC_LIB NAMES grpc)
|
||||
@@ -115,7 +122,7 @@ else()
|
||||
grpc
|
||||
DEPENDS openssl
|
||||
GIT_REPOSITORY https://github.com/grpc/grpc.git
|
||||
GIT_TAG v1.31.1
|
||||
GIT_TAG v1.32.0
|
||||
GIT_SUBMODULES "third_party/protobuf third_party/zlib third_party/cares/cares third_party/abseil-cpp third_party/re2"
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${GRPC_LIB} ${GRPCPP_LIB}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# "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.
|
||||
#
|
||||
mark_as_advanced(JQ_INCLUDE JQ_LIB)
|
||||
if (NOT USE_BUNDLED_DEPS)
|
||||
find_path(JQ_INCLUDE jq.h PATH_SUFFIXES jq)
|
||||
find_library(JQ_LIB NAMES jq)
|
||||
|
||||
@@ -15,12 +15,13 @@ 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
|
||||
INSTALL_COMMAND ${CMD_MAKE} install)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
28
cmake/modules/lpeg.cmake
Normal file
28
cmake/modules/lpeg.cmake
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Copyright (C) 2020 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(LPEG_SRC "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg")
|
||||
set(LPEG_LIB "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg/build/lpeg.a")
|
||||
message(STATUS "Using bundled lpeg in '${LPEG_SRC}'")
|
||||
set(LPEG_DEPENDENCIES "")
|
||||
list(APPEND LPEG_DEPENDENCIES "luajit")
|
||||
ExternalProject_Add(
|
||||
lpeg
|
||||
DEPENDS ${LPEG_DEPENDENCIES}
|
||||
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
|
||||
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
|
||||
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${LPEG_LIB}
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
27
cmake/modules/luajit.cmake
Normal file
27
cmake/modules/luajit.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (C) 2020 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(LUAJIT_SRC "${PROJECT_BINARY_DIR}/luajit-prefix/src/luajit/src")
|
||||
message(STATUS "Using bundled LuaJIT in '${LUAJIT_SRC}'")
|
||||
set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
|
||||
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
|
||||
externalproject_add(
|
||||
luajit
|
||||
GIT_REPOSITORY "https://github.com/LuaJIT/LuaJIT"
|
||||
GIT_TAG "1d8b747c161db457e032a023ebbff511f5de5ec2"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${LUAJIT_LIB}
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
28
cmake/modules/lyaml.cmake
Normal file
28
cmake/modules/lyaml.cmake
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Copyright (C) 2020 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(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
|
||||
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
|
||||
message(STATUS "Using bundled lyaml in '${LYAML_SRC}'")
|
||||
externalproject_add(
|
||||
lyaml
|
||||
DEPENDS luajit libyaml
|
||||
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
|
||||
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${LYAML_LIB}
|
||||
CONFIGURE_COMMAND ./configure --enable-static CFLAGS=-I${LIBYAML_INSTALL_DIR}/include CPPFLAGS=-I${LIBYAML_INSTALL_DIR}/include LDFLAGS=-L${LIBYAML_INSTALL_DIR}/lib LIBS=-lyaml LUA=${LUAJIT_SRC}/luajit LUA_INCLUDE=-I${LUAJIT_INCLUDE}
|
||||
INSTALL_COMMAND sh -c
|
||||
"cp -R ${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/lib/* ${PROJECT_SOURCE_DIR}/userspace/engine/lua"
|
||||
)
|
||||
@@ -3,6 +3,7 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck)
|
||||
|
||||
# cppcheck
|
||||
mark_as_advanced(CPPCHECK CPPCHECK_HTMLREPORT)
|
||||
find_program(CPPCHECK cppcheck)
|
||||
find_program(CPPCHECK_HTMLREPORT cppcheck-htmlreport)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
# Copyright (C) 2020 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
|
||||
@@ -25,4 +25,4 @@ ExternalProject_Add(
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch)
|
||||
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch && patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/luajit.patch)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c
|
||||
index e9faea51..a1b3b501 100644
|
||||
index 6f51588e..5f9ea84e 100644
|
||||
--- a/userspace/libscap/scap.c
|
||||
+++ b/userspace/libscap/scap.c
|
||||
@@ -52,7 +52,7 @@ limitations under the License.
|
||||
@@ -55,7 +55,7 @@ limitations under the License.
|
||||
//#define NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
@@ -11,7 +11,16 @@ index e9faea51..a1b3b501 100644
|
||||
|
||||
//
|
||||
// Probe version string size
|
||||
@@ -171,7 +171,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
||||
@@ -114,7 +114,7 @@ scap_t* scap_open_udig_int(char *error, int32_t *rc,
|
||||
static uint32_t get_max_consumers()
|
||||
{
|
||||
uint32_t max;
|
||||
- FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers", "r");
|
||||
+ FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers", "r");
|
||||
if(pfile != NULL)
|
||||
{
|
||||
int w = fscanf(pfile, "%"PRIu32, &max);
|
||||
@@ -186,7 +186,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -20,7 +29,16 @@ index e9faea51..a1b3b501 100644
|
||||
bpf_probe = buf;
|
||||
}
|
||||
}
|
||||
@@ -1808,7 +1808,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
|
||||
@@ -344,7 +344,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
||||
else if(errno == EBUSY)
|
||||
{
|
||||
uint32_t curr_max_consumers = get_max_consumers();
|
||||
- snprintf(error, SCAP_LASTERR_SIZE, "Too many sysdig instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
|
||||
+ snprintf(error, SCAP_LASTERR_SIZE, "Too many Falco instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2175,7 +2175,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
|
||||
|
||||
const char* scap_get_host_root()
|
||||
{
|
||||
|
||||
57
cmake/modules/sysdig-repo/patch/luajit.patch
Normal file
57
cmake/modules/sysdig-repo/patch/luajit.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
diff --git a/userspace/libsinsp/chisel.cpp b/userspace/libsinsp/chisel.cpp
|
||||
index 0a6e3cf8..0c2e255a 100644
|
||||
--- a/userspace/libsinsp/chisel.cpp
|
||||
+++ b/userspace/libsinsp/chisel.cpp
|
||||
@@ -98,7 +98,7 @@ void lua_stackdump(lua_State *L)
|
||||
// Lua callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAS_LUA_CHISELS
|
||||
-const static struct luaL_reg ll_sysdig [] =
|
||||
+const static struct luaL_Reg ll_sysdig [] =
|
||||
{
|
||||
{"set_filter", &lua_cbacks::set_global_filter},
|
||||
{"set_snaplen", &lua_cbacks::set_snaplen},
|
||||
@@ -134,7 +134,7 @@ const static struct luaL_reg ll_sysdig [] =
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
-const static struct luaL_reg ll_chisel [] =
|
||||
+const static struct luaL_Reg ll_chisel [] =
|
||||
{
|
||||
{"request_field", &lua_cbacks::request_field},
|
||||
{"set_filter", &lua_cbacks::set_filter},
|
||||
@@ -146,7 +146,7 @@ const static struct luaL_reg ll_chisel [] =
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
-const static struct luaL_reg ll_evt [] =
|
||||
+const static struct luaL_Reg ll_evt [] =
|
||||
{
|
||||
{"field", &lua_cbacks::field},
|
||||
{"get_num", &lua_cbacks::get_num},
|
||||
diff --git a/userspace/libsinsp/lua_parser.cpp b/userspace/libsinsp/lua_parser.cpp
|
||||
index 0e26617d..78810d96 100644
|
||||
--- a/userspace/libsinsp/lua_parser.cpp
|
||||
+++ b/userspace/libsinsp/lua_parser.cpp
|
||||
@@ -32,7 +32,7 @@ extern "C" {
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
||||
-const static struct luaL_reg ll_filter [] =
|
||||
+const static struct luaL_Reg ll_filter [] =
|
||||
{
|
||||
{"rel_expr", &lua_parser_cbacks::rel_expr},
|
||||
{"bool_op", &lua_parser_cbacks::bool_op},
|
||||
diff --git a/userspace/libsinsp/lua_parser_api.cpp b/userspace/libsinsp/lua_parser_api.cpp
|
||||
index c89e9126..c3d8008a 100644
|
||||
--- a/userspace/libsinsp/lua_parser_api.cpp
|
||||
+++ b/userspace/libsinsp/lua_parser_api.cpp
|
||||
@@ -266,7 +266,7 @@ int lua_parser_cbacks::rel_expr(lua_State *ls)
|
||||
string err = "Got non-table as in-expression operand\n";
|
||||
throw sinsp_exception("parser API error");
|
||||
}
|
||||
- int n = luaL_getn(ls, 4); /* get size of table */
|
||||
+ int n = lua_objlen (ls, 4); /* get size of table */
|
||||
for (i=1; i<=n; i++)
|
||||
{
|
||||
lua_rawgeti(ls, 4, i);
|
||||
@@ -29,8 +29,8 @@ file(MAKE_DIRECTORY ${SYSDIG_CMAKE_WORKING_DIR})
|
||||
# default below In case you want to test against another sysdig version just pass the variable - ie., `cmake
|
||||
# -DSYSDIG_VERSION=dev ..`
|
||||
if(NOT SYSDIG_VERSION)
|
||||
set(SYSDIG_VERSION "2aa88dcf6243982697811df4c1b484bcbe9488a2")
|
||||
set(SYSDIG_CHECKSUM "SHA256=a737077543a6f3473ab306b424bcf7385d788149829ed1538252661b0f20d0f6")
|
||||
set(SYSDIG_VERSION "5c0b863ddade7a45568c0ac97d037422c9efb750")
|
||||
set(SYSDIG_CHECKSUM "SHA256=9de717b3a4b611ea6df56afee05171860167112f74bb7717b394bcc88ac843cd")
|
||||
endif()
|
||||
set(PROBE_VERSION "${SYSDIG_VERSION}")
|
||||
|
||||
@@ -57,6 +57,7 @@ add_subdirectory("${SYSDIG_SOURCE_DIR}/driver" "${PROJECT_BINARY_DIR}/driver")
|
||||
# Add libscap directory
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
add_definitions(-DHAS_CAPTURE)
|
||||
add_definitions(-DNOCURSESUI)
|
||||
if(MUSL_OPTIMIZED_BUILD)
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
endif()
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# "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.
|
||||
#
|
||||
mark_as_advanced(YAMLCPP_INCLUDE_DIR YAMLCPP_LIB)
|
||||
if(NOT USE_BUNDLED_DEPS)
|
||||
find_path(YAMLCPP_INCLUDE_DIR NAMES yaml-cpp/yaml.h)
|
||||
find_library(YAMLCPP_LIB NAMES yaml-cpp)
|
||||
|
||||
@@ -3,7 +3,7 @@ FROM falcosecurity/falco:${FALCO_IMAGE_TAG}
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
LABEL usage="docker run -i -t -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro --name NAME IMAGE"
|
||||
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 --name NAME IMAGE"
|
||||
|
||||
ENV HOST_ROOT /host
|
||||
ENV HOME /root
|
||||
|
||||
@@ -2,7 +2,7 @@ FROM debian:stable
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
LABEL usage="docker run -i -t -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro --name NAME IMAGE"
|
||||
LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -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 --name NAME IMAGE"
|
||||
|
||||
ARG FALCO_VERSION=latest
|
||||
ARG VERSION_BUCKET=deb
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
FROM ubuntu:18.04 as ubuntu
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
ARG FALCO_VERSION
|
||||
ARG VERSION_BUCKET=bin
|
||||
|
||||
@@ -22,6 +20,14 @@ RUN sed -e 's/time_format_iso_8601: false/time_format_iso_8601: true/' < /falco/
|
||||
|
||||
FROM scratch
|
||||
|
||||
LABEL 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 /dev:/host/dev -v /proc:/host/proc:ro --name NAME IMAGE"
|
||||
# NOTE: for the "least privileged" use case, please refer to the official documentation
|
||||
|
||||
ENV HOST_ROOT /host
|
||||
ENV HOME /root
|
||||
|
||||
COPY --from=ubuntu /falco /
|
||||
|
||||
CMD ["/usr/bin/falco", "-o", "time_format_iso_8601=true"]
|
||||
17
falco.yaml
17
falco.yaml
@@ -87,6 +87,23 @@ syscall_event_drops:
|
||||
rate: .03333
|
||||
max_burst: 10
|
||||
|
||||
# Falco continuously monitors outputs performance. When an output channel does not allow
|
||||
# to deliver an alert within a given deadline, an error is reported indicating
|
||||
# which output is blocking notifications.
|
||||
# The timeout error will be reported to the log according to the above log_* settings.
|
||||
# Note that the notification will not be discarded from the output queue; thus,
|
||||
# output channels may indefinitely remain blocked.
|
||||
# An output timeout error indeed indicate a misconfiguration issue or I/O problems
|
||||
# that cannot be recovered by Falco and should be fixed by the user.
|
||||
#
|
||||
# The "output_timeout" value specifies the duration in milliseconds to wait before
|
||||
# considering the deadline exceed.
|
||||
#
|
||||
# With a 2000ms default, the notification consumer can block the Falco output
|
||||
# for up to 2 seconds without reaching the timeout.
|
||||
|
||||
output_timeout: 2000
|
||||
|
||||
# A throttling mechanism implemented as a token bucket limits the
|
||||
# rate of falco notifications. This throttling is controlled by the following configuration
|
||||
# options:
|
||||
|
||||
240
proposals/20200828-structured-exception-handling.md
Normal file
240
proposals/20200828-structured-exception-handling.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Proposal for First Class Structured Exceptions in Falco Rules
|
||||
|
||||
## Summary
|
||||
|
||||
## Motivation
|
||||
|
||||
Almost all Falco Rules have cases where the behavior detected by the
|
||||
rule should be allowed. For example, The rule Write Below Binary Dir
|
||||
has exceptions for specific programs that are known to write below
|
||||
these directories as a part of software installation/management:
|
||||
|
||||
```yaml
|
||||
- rule: Write below binary dir
|
||||
desc: an attempt to write to any file below a set of binary directories
|
||||
condition: >
|
||||
bin_dir and evt.dir = < and open_write
|
||||
and not package_mgmt_procs
|
||||
and not exe_running_docker_save
|
||||
and not python_running_get_pip
|
||||
and not python_running_ms_oms
|
||||
and not user_known_write_below_binary_dir_activities
|
||||
...
|
||||
```
|
||||
In most cases, these exceptions are expressed as concatenations to the original rule's condition. For example, looking at the macro package_mgmt_procs:
|
||||
|
||||
```yaml
|
||||
- macro: package_mgmt_procs
|
||||
condition: proc.name in (package_mgmt_binaries)
|
||||
```
|
||||
|
||||
The result is appending `and not proc.name in (package_mgmt_binaries)` to the condition of the rule.
|
||||
|
||||
A more extreme case of this is the write_below_etc macro used by Write below etc rule. It has tens of exceptions:
|
||||
|
||||
```
|
||||
...
|
||||
and not sed_temporary_file
|
||||
and not exe_running_docker_save
|
||||
and not ansible_running_python
|
||||
and not python_running_denyhosts
|
||||
and not fluentd_writing_conf_files
|
||||
and not user_known_write_etc_conditions
|
||||
and not run_by_centrify
|
||||
and not run_by_adclient
|
||||
and not qualys_writing_conf_files
|
||||
and not git_writing_nssdb
|
||||
...
|
||||
```
|
||||
|
||||
The exceptions all generally follow the same structure--naming a program and a directory prefix below /etc where that program is allowed to write files.
|
||||
|
||||
### Using Appends/Overwrites to Customize Rules
|
||||
|
||||
An important way to customize rules and macros is to use `append: true` to add to them, or `append: false` to define a new rule/macro, overwriting the original rule/macro. Here's an example from Update Package Repository:
|
||||
|
||||
```yaml
|
||||
- list: package_mgmt_binaries
|
||||
items: [rpm_binaries, deb_binaries, update-alternat, gem, pip, pip3, sane-utils.post, alternatives, chef-client, apk, snapd]
|
||||
|
||||
- macro: package_mgmt_procs
|
||||
condition: proc.name in (package_mgmt_binaries)
|
||||
|
||||
- macro: user_known_update_package_registry
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Update Package Repository
|
||||
desc: Detect package repositories get updated
|
||||
condition: >
|
||||
((open_write and access_repositories) or (modify and modify_repositories))
|
||||
and not package_mgmt_procs
|
||||
and not exe_running_docker_save
|
||||
and not user_known_update_package_registry
|
||||
```
|
||||
|
||||
If someone wanted to add additional exceptions to this rule, they could add the following to the user_rules file:
|
||||
|
||||
```yaml
|
||||
- list: package_mgmt_binaries
|
||||
items: [puppet]
|
||||
append: true
|
||||
|
||||
- macro: package_mgmt_procs
|
||||
condition: and not proc.pname=chef
|
||||
append: true
|
||||
|
||||
- macro: user_known_update_package_registry
|
||||
condition: (proc.name in (npm))
|
||||
append: false
|
||||
```
|
||||
|
||||
This adds an 3 different exceptions:
|
||||
* an additional binary to package_mgmt_binaries (because append is true),
|
||||
* adds to package_mgmt_procs, adding an exception for programs spawned by chef (because append is true)
|
||||
* overrides the macro user_known_update_package_registry to add an exception for npm (because append is false).
|
||||
|
||||
### Problems with Appends/Overrides to Define Exceptions
|
||||
|
||||
Although the concepts of macros and lists in condition fields, combined with appending to lists/conditions in macros/rules, is very general purpose, it can be unwieldy:
|
||||
|
||||
* Appending to conditions can result in incorrect behavior, unless the original condition has its logical operators set up properly with parentheses. For example:
|
||||
|
||||
```yaml
|
||||
rule: my_rule
|
||||
condition: (evt.type=open and (fd.name=/tmp/foo or fd.name=/tmp/bar))
|
||||
|
||||
rule: my_rule
|
||||
condition: or fd.name=/tmp/baz
|
||||
append: true
|
||||
```
|
||||
|
||||
Results in unintended behavior. It will match any fd related event where the name is /tmp/baz, when the intent was probably to add /tmp/baz as an additional opened file.
|
||||
|
||||
* A good convention many rules use is to have a clause "and not user_known_xxxx" built into the condition field. However, it's not in all rules and its use is a bit haphazard.
|
||||
|
||||
* Appends and overrides can get confusing if you try to apply them multiple times. For example:
|
||||
|
||||
```yaml
|
||||
macro: allowed_files
|
||||
condition: fd.name=/tmp/foo
|
||||
|
||||
...
|
||||
|
||||
macro: allowed_files
|
||||
condition: and fd.name=/tmp/bar
|
||||
append: true
|
||||
```
|
||||
|
||||
If someone wanted to override the original behavior of allowed_files, they would have to use `append: false` in a third definition of allowed_files, but this would result in losing the append: true override.
|
||||
|
||||
## Solution: Exceptions as first class objects
|
||||
|
||||
To address some of these problems, we will add the notion of Exceptions as top level objects alongside Rules, Macros, and Lists. A rule that supports exceptions must define a new key `exceptions` in the rule. The exceptions key is a list of identifier plus list of tuples of filtercheck fields. Here's an example:
|
||||
|
||||
```yaml
|
||||
- rule: Write below binary dir
|
||||
desc: an attempt to write to any file below a set of binary directories
|
||||
condition: >
|
||||
bin_dir and evt.dir = < and open_write
|
||||
and not package_mgmt_procs
|
||||
and not exe_running_docker_save
|
||||
and not python_running_get_pip
|
||||
and not python_running_ms_oms
|
||||
and not user_known_write_below_binary_dir_activities
|
||||
exceptions:
|
||||
- name: proc_writer
|
||||
fields: [proc.name, fd.directory]
|
||||
- name: container_writer
|
||||
fields: [container.image.repository, fd.directory]
|
||||
comps: [=, startswith]
|
||||
- name: proc_filenames
|
||||
fields: [proc.name, fd.name]
|
||||
comps: [=, in]
|
||||
- name: filenames
|
||||
fields: fd.filename
|
||||
comps: in
|
||||
```
|
||||
|
||||
This rule defines four kinds of exceptions:
|
||||
* proc_writer: uses a combination of proc.name and fd.directory
|
||||
* container_writer: uses a combination of container.image.repository and fd.directory
|
||||
* proc_filenames: uses a combination of process and list of filenames.
|
||||
* filenames: uses a list of filenames
|
||||
|
||||
The specific strings "proc_writer"/"container_writer"/"proc_filenames"/"filenames" are arbitrary strings and don't have a special meaning to the rules file parser. They're only used to link together the list of field names with the list of field values that exist in the exception object.
|
||||
|
||||
proc_writer does not have any comps property, so the fields are directly compared to values using the = operator. container_writer does have a comps property, so each field will be compared to the corresponding exception items using the corresponding comparison operator.
|
||||
|
||||
proc_filenames uses the in comparison operator, so the corresponding values entry should be a list of filenames.
|
||||
|
||||
filenames differs from the others in that it names a single field and single comp operator. This changes how the exception condition snippet is constructed (see below).
|
||||
|
||||
Notice that exceptions are defined as a part of the rule. This is important because the author of the rule defines what construes a valid exception to the rule. In this case, an exception can consist of a process and file directory (actor and target), but not a process name only (too broad).
|
||||
|
||||
Exception values will most commonly be defined in rules with append: true. Here's an example:
|
||||
|
||||
```yaml
|
||||
- list: apt_files
|
||||
items: [/bin/ls, /bin/rm]
|
||||
|
||||
- rule: Write below binary dir
|
||||
exceptions:
|
||||
- name: proc_writer
|
||||
values:
|
||||
- [apk, /usr/lib/alpine]
|
||||
- [npm, /usr/node/bin]
|
||||
- name: container_writer
|
||||
values:
|
||||
- [docker.io/alpine, /usr/libexec/alpine]
|
||||
- name: proc_filenames
|
||||
values:
|
||||
- [apt, apt_files]
|
||||
- [rpm, [/bin/cp, /bin/pwd]]
|
||||
- name: filenames
|
||||
values: [python, go]
|
||||
```
|
||||
|
||||
A rule exception applies if for a given event, the fields in a rule.exception match all of the values in some exception.item. For example, if a program `apk` writes to a file below `/usr/lib/alpine`, the rule will not trigger, even if the condition is met.
|
||||
|
||||
Notice that an item in a values list can be a list. This allows building exceptions with operators like "in", "pmatch", etc. that work on a list of items. The item can also be a name of an existing list. If not present surrounding parantheses will be added.
|
||||
|
||||
Finally, note that the structure of the values property differs between the items where fields is a list of fields (proc_writer/container_writer/proc_filenames) and when it is a single field (procs_only). This changes how the condition snippet is constructed.
|
||||
|
||||
### Implementation
|
||||
|
||||
For exception items where the fields property is a list of field names, each exception can be thought of as an implicit "and not (field1 cmp1 val1 and field2 cmp2 val2 and...)" appended to the rule's condition. For exception items where the fields property is a single field name, the exception can be thought of as an implict "and not field cmp (val1, val2, ...)". In practice, that's how exceptions will be implemented.
|
||||
|
||||
When a rule is parsed, the original condition will be wrapped in an extra layer of parentheses and all exception values will be appended to the condition. For example, using the example above, the resulting condition will be:
|
||||
|
||||
```
|
||||
(<Write below binary dir condition>) and not (
|
||||
(proc.name = apk and fd.directory = /usr/lib/alpine) or (proc.name = npm and fd.directory = /usr/node/bin) or
|
||||
(container.image.repository = docker.io/alpine and fd.directory startswith /usr/libexec/alpine) or
|
||||
(proc.name=apt and fd.name in (apt_files))) or
|
||||
(fd.filename in (python, go))))
|
||||
```
|
||||
|
||||
The exceptions are effectively syntatic sugar that allows expressing sets of exceptions in a concise way.
|
||||
|
||||
### Advantages
|
||||
|
||||
Adding Exception objects as described here has several advantages:
|
||||
|
||||
* All rules will implicitly support exceptions. A rule writer doesn't need to define a user_known_xxx macro and add it to the condition.
|
||||
* The rule writer has some controls on what defines a valid exception. The rule author knows best what is a good exception, and can define the fields that make up the exception.
|
||||
* With this approach, it's much easier to add and manage multiple sets of exceptions from multiple sources. You're just combining lists of tuples of filtercheck field values.
|
||||
|
||||
## Backwards compatibility
|
||||
|
||||
To take advantage of these new features, users will need to upgrade Falco to a version that supports exception objects and exception keys in rules. For the most part, however, the rules file structure is unchanged.
|
||||
|
||||
This approach does not remove the ability to append to exceptions nor the existing use of user_xxx macros to define exceptions to rules. It only provides an additional way to express exceptions. Hopefully, we can migrate existing exceptions to use this approach, but there isn't any plan to make wholesale rules changes as a part of this.
|
||||
|
||||
This approach is for the most part backwards compatible with older Falco releases. To implement exceptions, we'll add a preprocessing element to rule parsing. The main Falco engine is unchanged.
|
||||
|
||||
However, there are a few changes we'll have to make to Falco rules file parsing:
|
||||
|
||||
* Currently, Falco will reject files containing anything other than rule/macro/list top-level objects. As a result, `exception` objects would be rejected. We'll probably want to make a one-time change to Falco to allow arbitrary top level objects.
|
||||
* Similarly, Falco will reject rule objects with exception keys. We'll also probably want to change Falco to allow unknown keys inside rule/macro/list/exception objects.
|
||||
|
||||
|
||||
@@ -1213,6 +1213,9 @@
|
||||
fd.name startswith /etc/ssh/ssh_monitor_config_ or
|
||||
fd.name startswith /etc/ssh/ssh_config_))
|
||||
|
||||
- macro: multipath_writing_conf
|
||||
condition: (proc.name = multipath and fd.name startswith /etc/multipath/)
|
||||
|
||||
# Add conditions to this macro (probably in a separate file,
|
||||
# overwriting this macro) to allow for specific combinations of
|
||||
# programs writing below specific directories below
|
||||
@@ -1333,6 +1336,7 @@
|
||||
and not automount_using_mtab
|
||||
and not mcafee_writing_cma_d
|
||||
and not avinetworks_supervisor_writing_ssh
|
||||
and not multipath_writing_conf
|
||||
|
||||
- rule: Write below etc
|
||||
desc: an attempt to write to any file below /etc
|
||||
@@ -1597,7 +1601,12 @@
|
||||
|
||||
- rule: Mkdir binary dirs
|
||||
desc: an attempt to create a directory below a set of binary directories.
|
||||
condition: mkdir and bin_dir_mkdir and not package_mgmt_procs and not user_known_mkdir_bin_dir_activities
|
||||
condition: >
|
||||
mkdir
|
||||
and bin_dir_mkdir
|
||||
and not package_mgmt_procs
|
||||
and not user_known_mkdir_bin_dir_activities
|
||||
and not exe_running_docker_save
|
||||
output: >
|
||||
Directory below known binary directory created (user=%user.name user_loginuid=%user.loginuid
|
||||
command=%proc.cmdline directory=%evt.arg.path container_id=%container.id image=%container.image.repository)
|
||||
@@ -1608,7 +1617,7 @@
|
||||
# to change thread namespace without having to copy and override the
|
||||
# entire change thread namespace rule.
|
||||
- list: user_known_change_thread_namespace_binaries
|
||||
items: []
|
||||
items: [crio, multus]
|
||||
|
||||
- macro: user_known_change_thread_namespace_activities
|
||||
condition: (never_true)
|
||||
@@ -2315,6 +2324,9 @@
|
||||
- macro: user_known_user_management_activities
|
||||
condition: (never_true)
|
||||
|
||||
- macro: chage_list
|
||||
condition: (proc.name=chage and (proc.cmdline contains "-l" or proc.cmdline contains "--list"))
|
||||
|
||||
- rule: User mgmt binaries
|
||||
desc: >
|
||||
activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded.
|
||||
@@ -2333,6 +2345,7 @@
|
||||
not run_by_yum and
|
||||
not run_by_ms_oms and
|
||||
not run_by_google_accounts_daemon and
|
||||
not chage_list and
|
||||
not user_known_user_management_activities
|
||||
output: >
|
||||
User management binary command run outside of container
|
||||
@@ -2717,6 +2730,7 @@
|
||||
(open_write and evt.arg.flags contains "O_CREAT" and fd.name contains "/." and not fd.name pmatch (exclude_hidden_directories))) and
|
||||
consider_hidden_file_creation and
|
||||
not user_known_create_hidden_file_activities
|
||||
and not exe_running_docker_save
|
||||
output: >
|
||||
Hidden file or directory created (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline
|
||||
file=%fd.name newpath=%evt.arg.newpath container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
@@ -2864,12 +2878,22 @@
|
||||
- list: k8s_client_binaries
|
||||
items: [docker, kubectl, crictl]
|
||||
|
||||
- list: user_known_k8s_ns_kube_system_images
|
||||
items: [
|
||||
k8s.gcr.io/fluentd-gcp-scaler,
|
||||
k8s.gcr.io/node-problem-detector/node-problem-detector
|
||||
]
|
||||
|
||||
- list: user_known_k8s_images
|
||||
items: [
|
||||
mcr.microsoft.com/aks/hcp/hcp-tunnel-front
|
||||
]
|
||||
|
||||
# Whitelist for known docker client binaries run inside container
|
||||
# - k8s.gcr.io/fluentd-gcp-scaler in GCP/GKE
|
||||
- macro: user_known_k8s_client_container
|
||||
condition: >
|
||||
(k8s.ns.name="kube-system" and container.image.repository=k8s.gcr.io/fluentd-gcp-scaler) or
|
||||
container.image.repository=mcr.microsoft.com/aks/hcp/hcp-tunnel-front
|
||||
(k8s.ns.name="kube-system" and container.image.repository in (user_known_k8s_ns_kube_system_images)) or container.image.repository in (user_known_k8s_images)
|
||||
|
||||
- macro: user_known_k8s_client_container_parens
|
||||
condition: (user_known_k8s_client_container)
|
||||
@@ -3042,6 +3066,32 @@
|
||||
priority: WARNING
|
||||
tags: [network]
|
||||
|
||||
- list: white_listed_modules
|
||||
items: []
|
||||
|
||||
- rule: Linux Kernel Module Injection Detected
|
||||
desc: Detect kernel module was injected (from container).
|
||||
condition: spawned_process and container and proc.name=insmod and not proc.args in (white_listed_modules)
|
||||
output: Linux Kernel Module injection using insmod detected (user=%user.name user_loginuid=%user.loginuid parent_process=%proc.pname module=%proc.args)
|
||||
priority: WARNING
|
||||
tags: [process]
|
||||
|
||||
- list: run_as_root_image_list
|
||||
items: []
|
||||
|
||||
- macro: user_known_run_as_root_container
|
||||
condition: (container.image.repository in (run_as_root_image_list))
|
||||
|
||||
# The rule is disabled by default and should be enabled when non-root container policy has been applied.
|
||||
# Note the rule will not work as expected when usernamespace is applied, e.g. userns-remap is enabled.
|
||||
- rule: Container Run as Root User
|
||||
desc: Detected container running as root user
|
||||
condition: spawned_process and container and proc.vpid=1 and user.uid=0 and not user_known_run_as_root_container
|
||||
enabled: false
|
||||
output: Container launched with root user privilege (uid=%user.uid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
priority: INFO
|
||||
tags: [container, process]
|
||||
|
||||
# Application rules have moved to application_rules.yaml. Please look
|
||||
# there if you want to enable them by adding to
|
||||
# falco_rules.local.yaml.
|
||||
|
||||
@@ -220,7 +220,7 @@ load_kernel_module() {
|
||||
rmmod "${DRIVER_NAME}" 2>/dev/null
|
||||
WAIT_TIME=0
|
||||
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
|
||||
while lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1 && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
|
||||
while lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
|
||||
if rmmod "${DRIVER_NAME}" 2>/dev/null; then
|
||||
echo "* Unloading ${DRIVER_NAME} module succeeded after ${WAIT_TIME}s"
|
||||
break
|
||||
@@ -232,7 +232,7 @@ load_kernel_module() {
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
|
||||
if lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" > /dev/null 2>&1; then
|
||||
echo "* ${DRIVER_NAME} module seems to still be loaded, hoping the best"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -26,7 +26,7 @@ bool falco_formats::s_json_output = false;
|
||||
bool falco_formats::s_json_include_output_property = true;
|
||||
std::unique_ptr<sinsp_evt_formatter_cache> falco_formats::s_formatters = NULL;
|
||||
|
||||
const static struct luaL_reg ll_falco[] =
|
||||
const static struct luaL_Reg ll_falco[] =
|
||||
{
|
||||
{"formatter", &falco_formats::lua_formatter},
|
||||
{"free_formatter", &falco_formats::lua_free_formatter},
|
||||
|
||||
@@ -26,15 +26,14 @@ extern "C" {
|
||||
#include "falco_engine.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
const static struct luaL_reg ll_falco_rules [] =
|
||||
{
|
||||
{"clear_filters", &falco_rules::clear_filters},
|
||||
{"add_filter", &falco_rules::add_filter},
|
||||
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
|
||||
{"enable_rule", &falco_rules::enable_rule},
|
||||
{"engine_version", &falco_rules::engine_version},
|
||||
{NULL,NULL}
|
||||
};
|
||||
const static struct luaL_Reg ll_falco_rules[] =
|
||||
{
|
||||
{"clear_filters", &falco_rules::clear_filters},
|
||||
{"add_filter", &falco_rules::add_filter},
|
||||
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
|
||||
{"enable_rule", &falco_rules::enable_rule},
|
||||
{"engine_version", &falco_rules::engine_version},
|
||||
{NULL, NULL}};
|
||||
|
||||
falco_rules::falco_rules(sinsp* inspector,
|
||||
falco_engine *engine,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
# Copyright (C) 2020 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
|
||||
@@ -11,39 +11,10 @@
|
||||
# specific language governing permissions and limitations under the License.
|
||||
#
|
||||
|
||||
configure_file("${SYSDIG_SOURCE_DIR}/userspace/sysdig/config_sysdig.h.in" config_sysdig.h)
|
||||
configure_file(config_falco.h.in config_falco.h)
|
||||
|
||||
if(NOT MINIMAL_BUILD)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
|
||||
COMMENT "Generate gRPC API"
|
||||
# Falco gRPC Version API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
# Falco gRPC Outputs API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
if(MINIMAL_BUILD)
|
||||
add_executable(
|
||||
falco
|
||||
set(
|
||||
FALCO_SOURCES
|
||||
configuration.cpp
|
||||
logger.cpp
|
||||
falco_outputs.cpp
|
||||
@@ -54,84 +25,74 @@ add_executable(
|
||||
event_drops.cpp
|
||||
statsfilewriter.cpp
|
||||
falco.cpp
|
||||
"${SYSDIG_SOURCE_DIR}/userspace/sysdig/fields_info.cpp")
|
||||
else()
|
||||
add_executable(
|
||||
falco
|
||||
configuration.cpp
|
||||
logger.cpp
|
||||
falco_outputs.cpp
|
||||
outputs_file.cpp
|
||||
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/fields_info.cpp"
|
||||
)
|
||||
|
||||
set(
|
||||
FALCO_INCLUDE_DIRECTORIES
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||
"${PROJECT_BINARY_DIR}/driver/src"
|
||||
"${STRING_VIEW_LITE_INCLUDE}"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include"
|
||||
)
|
||||
|
||||
set(
|
||||
FALCO_DEPENDENCIES
|
||||
string-view-lite
|
||||
libyaml
|
||||
b64
|
||||
luajit
|
||||
lpeg
|
||||
lyaml
|
||||
)
|
||||
|
||||
set(
|
||||
FALCO_LIBRARIES
|
||||
falco_engine
|
||||
sinsp
|
||||
"${LIBYAML_LIB}"
|
||||
"${YAMLCPP_LIB}"
|
||||
)
|
||||
|
||||
if(USE_BUNDLED_DEPS)
|
||||
list(APPEND FALCO_DEPENDENCIES yamlcpp)
|
||||
endif()
|
||||
|
||||
if(NOT MINIMAL_BUILD)
|
||||
list(
|
||||
APPEND FALCO_SOURCES
|
||||
outputs_grpc.cpp
|
||||
outputs_http.cpp
|
||||
outputs_program.cpp
|
||||
outputs_stdout.cpp
|
||||
outputs_syslog.cpp
|
||||
event_drops.cpp
|
||||
statsfilewriter.cpp
|
||||
falco.cpp
|
||||
"${SYSDIG_SOURCE_DIR}/userspace/sysdig/fields_info.cpp"
|
||||
webserver.cpp
|
||||
grpc_context.cpp
|
||||
grpc_server_impl.cpp
|
||||
grpc_request_context.cpp
|
||||
grpc_server.cpp
|
||||
grpc_context.cpp
|
||||
grpc_server_impl.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
)
|
||||
|
||||
add_dependencies(falco civetweb)
|
||||
endif()
|
||||
list(
|
||||
APPEND FALCO_INCLUDE_DIRECTORIES
|
||||
"${CIVETWEB_INCLUDE_DIR}"
|
||||
"${OPENSSL_INCLUDE_DIR}"
|
||||
"${GRPC_INCLUDE}"
|
||||
"${GRPCPP_INCLUDE}"
|
||||
"${PROTOBUF_INCLUDE}"
|
||||
)
|
||||
|
||||
add_dependencies(falco string-view-lite)
|
||||
list(APPEND FALCO_DEPENDENCIES civetweb)
|
||||
|
||||
if(USE_BUNDLED_DEPS)
|
||||
add_dependencies(falco yamlcpp)
|
||||
endif()
|
||||
|
||||
if(MINIMAL_BUILD)
|
||||
target_include_directories(
|
||||
falco
|
||||
PUBLIC
|
||||
"${SYSDIG_SOURCE_DIR}/userspace/sysdig"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||
"${PROJECT_BINARY_DIR}/driver/src"
|
||||
"${STRING_VIEW_LITE_INCLUDE}"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include")
|
||||
|
||||
target_link_libraries(
|
||||
falco
|
||||
falco_engine
|
||||
sinsp
|
||||
"${LIBYAML_LIB}"
|
||||
"${YAMLCPP_LIB}")
|
||||
else()
|
||||
target_include_directories(
|
||||
falco
|
||||
PUBLIC
|
||||
"${SYSDIG_SOURCE_DIR}/userspace/sysdig"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||
"${PROJECT_BINARY_DIR}/driver/src"
|
||||
"${STRING_VIEW_LITE_INCLUDE}"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${CIVETWEB_INCLUDE_DIR}"
|
||||
"${OPENSSL_INCLUDE_DIR}"
|
||||
"${GRPC_INCLUDE}"
|
||||
"${GRPCPP_INCLUDE}"
|
||||
"${PROTOBUF_INCLUDE}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include")
|
||||
|
||||
target_link_libraries(
|
||||
falco
|
||||
falco_engine
|
||||
sinsp
|
||||
list(
|
||||
APPEND FALCO_LIBRARIES
|
||||
"${GPR_LIB}"
|
||||
"${GRPC_LIB}"
|
||||
"${GRPCPP_LIB}"
|
||||
@@ -140,19 +101,66 @@ else()
|
||||
"${OPENSSL_LIBRARY_CRYPTO}"
|
||||
"${LIBYAML_LIB}"
|
||||
"${YAMLCPP_LIB}"
|
||||
"${CIVETWEB_LIB}")
|
||||
"${CIVETWEB_LIB}"
|
||||
)
|
||||
endif()
|
||||
|
||||
configure_file(config_falco.h.in config_falco.h)
|
||||
add_executable(
|
||||
falco
|
||||
${FALCO_SOURCES}
|
||||
)
|
||||
|
||||
add_dependencies(falco ${FALCO_DEPENDENCIES})
|
||||
|
||||
target_link_libraries(
|
||||
falco
|
||||
${FALCO_LIBRARIES}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
falco
|
||||
PUBLIC
|
||||
${FALCO_INCLUDE_DIRECTORIES}
|
||||
)
|
||||
|
||||
if(NOT MINIMAL_BUILD)
|
||||
add_custom_command(
|
||||
TARGET falco
|
||||
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields")
|
||||
COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields"
|
||||
)
|
||||
else()
|
||||
MESSAGE(STATUS "Skipping engine fields checksum when building the minimal Falco.")
|
||||
message(STATUS "Skipping engine fields checksum when building the minimal Falco.")
|
||||
endif()
|
||||
|
||||
if(NOT MINIMAL_BUILD)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
|
||||
COMMENT "Generate gRPC API"
|
||||
# Falco gRPC Version API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
# Falco gRPC Outputs API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# strip the Falco binary when releasing using musl
|
||||
@@ -161,7 +169,8 @@ if(MUSL_OPTIMIZED_BUILD AND CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
TARGET falco
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_STRIP} --strip-unneeded falco
|
||||
COMMENT "Strip the Falco binary when releasing the musl build")
|
||||
COMMENT "Strip the Falco binary when releasing the musl build"
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS falco DESTINATION ${FALCO_BIN_DIR})
|
||||
|
||||
@@ -47,16 +47,6 @@ falco_configuration::~falco_configuration()
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have a configuration file, we just use stdout output and all other defaults
|
||||
void falco_configuration::init(list<string> &cmdline_options)
|
||||
{
|
||||
init_cmdline_options(cmdline_options);
|
||||
|
||||
falco::outputs::config stdout_output;
|
||||
stdout_output.name = "stdout";
|
||||
m_outputs.push_back(stdout_output);
|
||||
}
|
||||
|
||||
void falco_configuration::init(string conf_filename, list<string> &cmdline_options)
|
||||
{
|
||||
string m_config_file = conf_filename;
|
||||
@@ -176,6 +166,8 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
||||
|
||||
falco_logger::set_level(m_log_level);
|
||||
|
||||
m_output_timeout = m_config->get_scalar<uint32_t>("output_timeout", 2000);
|
||||
|
||||
m_notifications_rate = m_config->get_scalar<uint32_t>("outputs", "rate", 1);
|
||||
m_notifications_max_burst = m_config->get_scalar<uint32_t>("outputs", "max_burst", 1000);
|
||||
|
||||
@@ -346,4 +338,4 @@ void falco_configuration::set_cmdline_option(const string &opt)
|
||||
{
|
||||
m_config->set_scalar(keyval.first, keyval.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +204,7 @@ public:
|
||||
|
||||
bool m_buffered_outputs;
|
||||
bool m_time_format_iso_8601;
|
||||
uint32_t m_output_timeout;
|
||||
|
||||
bool m_grpc_enabled;
|
||||
uint32_t m_grpc_threadiness;
|
||||
|
||||
@@ -36,7 +36,7 @@ limitations under the License.
|
||||
#include "logger.h"
|
||||
#include "utils.h"
|
||||
#include "chisel.h"
|
||||
#include "sysdig.h"
|
||||
#include "fields_info.h"
|
||||
|
||||
#include "event_drops.h"
|
||||
#include "configuration.h"
|
||||
@@ -762,8 +762,6 @@ int falco_init(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
outputs = new falco_outputs();
|
||||
|
||||
// Some combinations of arguments are not allowed.
|
||||
if (daemon && pidfilename == "") {
|
||||
throw std::invalid_argument("If -d is provided, a pid file must also be provided");
|
||||
@@ -794,7 +792,7 @@ int falco_init(int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
conf_filename = "";
|
||||
throw std::invalid_argument("You must create a config file at " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE " or by passing -c\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -836,12 +834,7 @@ int falco_init(int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
config.init(cmdline_options);
|
||||
falco_logger::set_time_format_iso_8601(config.m_time_format_iso_8601);
|
||||
|
||||
// log after config init because config determines where logs go
|
||||
falco_logger::log(LOG_INFO, "Falco version " + std::string(FALCO_VERSION) + " (driver version " + std::string(DRIVER_VERSION) + ")\n");
|
||||
falco_logger::log(LOG_INFO, "Falco initialized. No configuration file found, proceeding with defaults\n");
|
||||
throw std::runtime_error("Could not find configuration file at " + conf_filename);
|
||||
}
|
||||
|
||||
if (rules_filenames.size())
|
||||
@@ -970,13 +963,6 @@ int falco_init(int argc, char **argv)
|
||||
hostname = c_hostname;
|
||||
}
|
||||
|
||||
outputs->init(config.m_json_output,
|
||||
config.m_json_include_output_property,
|
||||
config.m_notifications_rate, config.m_notifications_max_burst,
|
||||
config.m_buffered_outputs,
|
||||
config.m_time_format_iso_8601,
|
||||
hostname);
|
||||
|
||||
if(!all_events)
|
||||
{
|
||||
inspector->set_drop_event_flags(EF_DROP_SIMPLE_CONS);
|
||||
@@ -996,11 +982,6 @@ int falco_init(int argc, char **argv)
|
||||
|
||||
inspector->set_hostname_and_port_resolution_mode(false);
|
||||
|
||||
for(auto output : config.m_outputs)
|
||||
{
|
||||
outputs->add_output(output);
|
||||
}
|
||||
|
||||
if(signal(SIGINT, signal_callback) == SIG_ERR)
|
||||
{
|
||||
fprintf(stderr, "An error occurred while setting SIGINT signal handler.\n");
|
||||
@@ -1086,6 +1067,21 @@ int falco_init(int argc, char **argv)
|
||||
g_daemonized = true;
|
||||
}
|
||||
|
||||
outputs = new falco_outputs();
|
||||
|
||||
outputs->init(config.m_json_output,
|
||||
config.m_json_include_output_property,
|
||||
config.m_output_timeout,
|
||||
config.m_notifications_rate, config.m_notifications_max_burst,
|
||||
config.m_buffered_outputs,
|
||||
config.m_time_format_iso_8601,
|
||||
hostname);
|
||||
|
||||
for(auto output : config.m_outputs)
|
||||
{
|
||||
outputs->add_output(output);
|
||||
}
|
||||
|
||||
if(trace_filename.size())
|
||||
{
|
||||
// Try to open the trace file as a sysdig
|
||||
|
||||
@@ -24,6 +24,7 @@ limitations under the License.
|
||||
|
||||
#include "formats.h"
|
||||
#include "logger.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
#include "outputs_file.h"
|
||||
#include "outputs_program.h"
|
||||
@@ -51,18 +52,26 @@ falco_outputs::~falco_outputs()
|
||||
{
|
||||
if(m_initialized)
|
||||
{
|
||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
||||
this->stop_worker();
|
||||
for(auto o : m_outputs)
|
||||
{
|
||||
(*it)->cleanup();
|
||||
delete o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void falco_outputs::init(bool json_output,
|
||||
bool json_include_output_property,
|
||||
uint32_t rate, uint32_t max_burst, bool buffered,
|
||||
bool time_format_iso_8601, string hostname)
|
||||
bool json_include_output_property,
|
||||
uint32_t timeout,
|
||||
uint32_t rate, uint32_t max_burst, bool buffered,
|
||||
bool time_format_iso_8601, std::string hostname)
|
||||
{
|
||||
// Cannot be initialized more than one time.
|
||||
if(m_initialized)
|
||||
{
|
||||
throw falco_exception("falco_outputs already initialized");
|
||||
}
|
||||
|
||||
m_json_output = json_output;
|
||||
|
||||
// Note that falco_formats is already initialized by the engine,
|
||||
@@ -71,17 +80,29 @@ void falco_outputs::init(bool json_output,
|
||||
falco_formats::s_json_output = json_output;
|
||||
falco_formats::s_json_include_output_property = json_include_output_property;
|
||||
|
||||
m_timeout = std::chrono::milliseconds(timeout);
|
||||
|
||||
m_notifications_tb.init(rate, max_burst);
|
||||
|
||||
m_buffered = buffered;
|
||||
m_time_format_iso_8601 = time_format_iso_8601;
|
||||
m_hostname = hostname;
|
||||
|
||||
m_worker_thread = std::thread(&falco_outputs::worker, this);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
// This function has to be called after init() since some configuration settings
|
||||
// need to be passed to the output plugins. Then, although the worker has started,
|
||||
// the worker is still on hold, waiting for a message.
|
||||
// Thus it is still safe to call add_output() before any message has been enqueued.
|
||||
void falco_outputs::add_output(falco::outputs::config oc)
|
||||
{
|
||||
if(!m_initialized)
|
||||
{
|
||||
throw falco_exception("cannot add output: falco_outputs not initialized yet");
|
||||
}
|
||||
|
||||
falco::outputs::abstract_output *oo;
|
||||
|
||||
@@ -129,6 +150,12 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
|
||||
return;
|
||||
}
|
||||
|
||||
falco_outputs::ctrl_msg cmsg = {};
|
||||
cmsg.ts = evt->get_ts();
|
||||
cmsg.priority = priority;
|
||||
cmsg.source = source;
|
||||
cmsg.rule = rule;
|
||||
|
||||
string sformat;
|
||||
if(source == "syscall")
|
||||
{
|
||||
@@ -163,35 +190,38 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
|
||||
sformat += " " + format;
|
||||
}
|
||||
|
||||
string msg;
|
||||
msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
|
||||
cmsg.msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
|
||||
cmsg.fields = falco_formats::resolve_tokens(evt, source, sformat);
|
||||
|
||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
||||
{
|
||||
(*it)->output_event(evt, rule, source, priority, sformat, msg);
|
||||
}
|
||||
cmsg.type = ctrl_msg_type::CTRL_MSG_OUTPUT;
|
||||
m_queue.push(cmsg);
|
||||
}
|
||||
|
||||
void falco_outputs::handle_msg(uint64_t now,
|
||||
void falco_outputs::handle_msg(uint64_t ts,
|
||||
falco_common::priority_type priority,
|
||||
std::string &msg,
|
||||
std::string &rule,
|
||||
std::map<std::string, std::string> &output_fields)
|
||||
{
|
||||
std::string full_msg;
|
||||
falco_outputs::ctrl_msg cmsg = {};
|
||||
cmsg.ts = ts;
|
||||
cmsg.priority = priority;
|
||||
cmsg.source = "internal";
|
||||
cmsg.rule = rule;
|
||||
cmsg.fields = output_fields;
|
||||
|
||||
if(m_json_output)
|
||||
{
|
||||
nlohmann::json jmsg;
|
||||
|
||||
// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
|
||||
time_t evttime = now / 1000000000;
|
||||
time_t evttime = ts / 1000000000;
|
||||
char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
|
||||
char time_ns[12]; // sizeof ".sssssssssZ"
|
||||
string iso8601evttime;
|
||||
|
||||
strftime(time_sec, sizeof(time_sec), "%FT%T", gmtime(&evttime));
|
||||
snprintf(time_ns, sizeof(time_ns), ".%09luZ", now % 1000000000);
|
||||
snprintf(time_ns, sizeof(time_ns), ".%09luZ", ts % 1000000000);
|
||||
iso8601evttime = time_sec;
|
||||
iso8601evttime += time_ns;
|
||||
|
||||
@@ -201,15 +231,15 @@ void falco_outputs::handle_msg(uint64_t now,
|
||||
jmsg["time"] = iso8601evttime;
|
||||
jmsg["output_fields"] = output_fields;
|
||||
|
||||
full_msg = jmsg.dump();
|
||||
cmsg.msg = jmsg.dump();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string timestr;
|
||||
bool first = true;
|
||||
|
||||
sinsp_utils::ts_to_string(now, ×tr, false, true);
|
||||
full_msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
|
||||
sinsp_utils::ts_to_string(ts, ×tr, false, true);
|
||||
cmsg.msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
|
||||
for(auto &pair : output_fields)
|
||||
{
|
||||
if(first)
|
||||
@@ -218,23 +248,95 @@ void falco_outputs::handle_msg(uint64_t now,
|
||||
}
|
||||
else
|
||||
{
|
||||
full_msg += " ";
|
||||
cmsg.msg += " ";
|
||||
}
|
||||
full_msg += pair.first + "=" + pair.second;
|
||||
cmsg.msg += pair.first + "=" + pair.second;
|
||||
}
|
||||
full_msg += ")";
|
||||
cmsg.msg += ")";
|
||||
}
|
||||
|
||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
||||
{
|
||||
(*it)->output_msg(priority, full_msg);
|
||||
}
|
||||
cmsg.type = ctrl_msg_type::CTRL_MSG_OUTPUT;
|
||||
m_queue.push(cmsg);
|
||||
}
|
||||
|
||||
void falco_outputs::cleanup_outputs()
|
||||
{
|
||||
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_CLEANUP);
|
||||
}
|
||||
|
||||
void falco_outputs::reopen_outputs()
|
||||
{
|
||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
||||
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_REOPEN);
|
||||
}
|
||||
|
||||
void falco_outputs::stop_worker()
|
||||
{
|
||||
watchdog<void *> wd;
|
||||
wd.start([&](void *) -> void {
|
||||
falco_logger::log(LOG_NOTICE, "output channels still blocked, discarding all remaining notifications\n");
|
||||
m_queue.clear();
|
||||
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_STOP);
|
||||
});
|
||||
wd.set_timeout(m_timeout, nullptr);
|
||||
|
||||
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_STOP);
|
||||
if(m_worker_thread.joinable())
|
||||
{
|
||||
(*it)->reopen();
|
||||
m_worker_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
inline void falco_outputs::push(ctrl_msg_type cmt)
|
||||
{
|
||||
falco_outputs::ctrl_msg cmsg = {};
|
||||
cmsg.type = cmt;
|
||||
m_queue.push(cmsg);
|
||||
}
|
||||
|
||||
// todo(leogr,leodido): this function is not supposed to throw exceptions, and with "noexcept",
|
||||
// the program is terminated if that occurs. Although that's the wanted behavior,
|
||||
// we still need to improve the error reporting since some inner functions can throw exceptions.
|
||||
void falco_outputs::worker() noexcept
|
||||
{
|
||||
watchdog<std::string> wd;
|
||||
wd.start([&](std::string payload) -> void {
|
||||
falco_logger::log(LOG_CRIT, "\"" + payload + "\" output timeout, all output channels are blocked\n");
|
||||
});
|
||||
|
||||
auto timeout = m_timeout;
|
||||
|
||||
falco_outputs::ctrl_msg cmsg;
|
||||
do
|
||||
{
|
||||
// Block until a message becomes available.
|
||||
m_queue.pop(cmsg);
|
||||
|
||||
for(const auto o : m_outputs)
|
||||
{
|
||||
wd.set_timeout(timeout, o->get_name());
|
||||
try
|
||||
{
|
||||
switch(cmsg.type)
|
||||
{
|
||||
case ctrl_msg_type::CTRL_MSG_OUTPUT:
|
||||
o->output(&cmsg);
|
||||
break;
|
||||
case ctrl_msg_type::CTRL_MSG_CLEANUP:
|
||||
case ctrl_msg_type::CTRL_MSG_STOP:
|
||||
o->cleanup();
|
||||
break;
|
||||
case ctrl_msg_type::CTRL_MSG_REOPEN:
|
||||
o->reopen();
|
||||
break;
|
||||
default:
|
||||
falco_logger::log(LOG_DEBUG, "Outputs worker received an unknown message type\n");
|
||||
}
|
||||
}
|
||||
catch(const exception &e)
|
||||
{
|
||||
falco_logger::log(LOG_ERR, o->get_name() + ": " + string(e.what()) + "\n");
|
||||
}
|
||||
}
|
||||
wd.cancel_timeout();
|
||||
} while(cmsg.type != ctrl_msg_type::CTRL_MSG_STOP);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ limitations under the License.
|
||||
#include "token_bucket.h"
|
||||
#include "falco_engine.h"
|
||||
#include "outputs.h"
|
||||
#include "tbb/concurrent_queue.h"
|
||||
|
||||
//
|
||||
// This class acts as the primary interface between a program and the
|
||||
@@ -39,25 +40,25 @@ public:
|
||||
|
||||
void init(bool json_output,
|
||||
bool json_include_output_property,
|
||||
uint32_t timeout,
|
||||
uint32_t rate, uint32_t max_burst, bool buffered,
|
||||
bool time_format_iso_8601, std::string hostname);
|
||||
|
||||
void add_output(falco::outputs::config oc);
|
||||
|
||||
//
|
||||
// evt is an event that has matched some rule. Pass the event
|
||||
// to all configured outputs.
|
||||
//
|
||||
// Format then send the event to all configured outputs (`evt` is an event that has matched some rule).
|
||||
void handle_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format);
|
||||
|
||||
// Send a generic message to all outputs. Not necessarily associated with any event.
|
||||
// Format then send a generic message to all outputs. Not necessarily associated with any event.
|
||||
void handle_msg(uint64_t now,
|
||||
falco_common::priority_type priority,
|
||||
std::string &msg,
|
||||
std::string &rule,
|
||||
std::map<std::string, std::string> &output_fields);
|
||||
|
||||
void cleanup_outputs();
|
||||
|
||||
void reopen_outputs();
|
||||
|
||||
private:
|
||||
@@ -71,5 +72,28 @@ private:
|
||||
bool m_buffered;
|
||||
bool m_json_output;
|
||||
bool m_time_format_iso_8601;
|
||||
std::chrono::milliseconds m_timeout;
|
||||
std::string m_hostname;
|
||||
|
||||
enum ctrl_msg_type
|
||||
{
|
||||
CTRL_MSG_STOP = 0,
|
||||
CTRL_MSG_OUTPUT = 1,
|
||||
CTRL_MSG_CLEANUP = 2,
|
||||
CTRL_MSG_REOPEN = 3,
|
||||
};
|
||||
|
||||
struct ctrl_msg : falco::outputs::message
|
||||
{
|
||||
ctrl_msg_type type;
|
||||
};
|
||||
|
||||
typedef tbb::concurrent_bounded_queue<ctrl_msg> falco_outputs_cbq;
|
||||
|
||||
falco_outputs_cbq m_queue;
|
||||
|
||||
std::thread m_worker_thread;
|
||||
inline void push(ctrl_msg_type cmt);
|
||||
void worker() noexcept;
|
||||
void stop_worker();
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
#include "config_falco.h"
|
||||
#include "falco_engine_version.h"
|
||||
#include "grpc_server_impl.h"
|
||||
#include "grpc_queue.h"
|
||||
#include "logger.h"
|
||||
@@ -75,6 +76,9 @@ void falco::grpc::server_impl::version(const context& ctx, const version::reques
|
||||
auto& version = *res.mutable_version();
|
||||
version = FALCO_VERSION;
|
||||
|
||||
res.set_engine_version(FALCO_ENGINE_VERSION);
|
||||
res.set_engine_fields_checksum(FALCO_FIELDS_CHECKSUM);
|
||||
|
||||
res.set_major(FALCO_VERSION_MAJOR);
|
||||
res.set_minor(FALCO_VERSION_MINOR);
|
||||
res.set_patch(FALCO_VERSION_PATCH);
|
||||
|
||||
@@ -37,6 +37,21 @@ struct config
|
||||
std::map<std::string, std::string> options;
|
||||
};
|
||||
|
||||
//
|
||||
// The message to be outputted. It can either refer to:
|
||||
// - an event that has matched some rule,
|
||||
// - or a generic message (e.g., a drop alert).
|
||||
//
|
||||
struct message
|
||||
{
|
||||
uint64_t ts;
|
||||
falco_common::priority_type priority;
|
||||
std::string msg;
|
||||
std::string rule;
|
||||
std::string source;
|
||||
map<std::string, std::string> fields;
|
||||
};
|
||||
|
||||
//
|
||||
// This class acts as the primary interface for implementing
|
||||
// a Falco output class.
|
||||
@@ -45,6 +60,8 @@ struct config
|
||||
class abstract_output
|
||||
{
|
||||
public:
|
||||
virtual ~abstract_output() {}
|
||||
|
||||
void init(config oc, bool buffered, std::string hostname)
|
||||
{
|
||||
m_oc = oc;
|
||||
@@ -52,15 +69,19 @@ public:
|
||||
m_hostname = hostname;
|
||||
}
|
||||
|
||||
// Output an event that has matched some rule.
|
||||
virtual void output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg) = 0;
|
||||
// Return the output's name as per its configuration.
|
||||
const std::string get_name() const
|
||||
{
|
||||
return m_oc.name;
|
||||
}
|
||||
|
||||
// Output a generic message. Not necessarily associated with any event.
|
||||
virtual void output_msg(falco_common::priority_type priority, std::string &msg) = 0;
|
||||
// Output a message.
|
||||
virtual void output(const message *msg) = 0;
|
||||
|
||||
// Possibly close the output and open it again.
|
||||
virtual void reopen() {}
|
||||
|
||||
// Possibly flush the output.
|
||||
virtual void cleanup() {}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -31,16 +31,10 @@ void falco::outputs::output_file::open_file()
|
||||
}
|
||||
}
|
||||
|
||||
void falco::outputs::output_file::output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
||||
{
|
||||
output_msg(priority, msg);
|
||||
}
|
||||
|
||||
void falco::outputs::output_file::output_msg(falco_common::priority_type priority, std::string &msg)
|
||||
void falco::outputs::output_file::output(const message *msg)
|
||||
{
|
||||
open_file();
|
||||
m_outfile << msg + "\n";
|
||||
m_outfile << msg->msg + "\n";
|
||||
|
||||
if(m_oc.options["keep_alive"] != "true")
|
||||
{
|
||||
|
||||
@@ -27,10 +27,7 @@ namespace outputs
|
||||
|
||||
class output_file : public abstract_output
|
||||
{
|
||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
||||
|
||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
||||
void output(const message *msg);
|
||||
|
||||
void cleanup();
|
||||
|
||||
|
||||
@@ -21,44 +21,41 @@ limitations under the License.
|
||||
#include "formats.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
void falco::outputs::output_grpc::output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format,
|
||||
std::string &msg)
|
||||
void falco::outputs::output_grpc::output(const message *msg)
|
||||
{
|
||||
falco::outputs::response grpc_res;
|
||||
|
||||
// time
|
||||
auto timestamp = grpc_res.mutable_time();
|
||||
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(evt->get_ts());
|
||||
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(msg->ts);
|
||||
|
||||
// rule
|
||||
auto r = grpc_res.mutable_rule();
|
||||
*r = rule;
|
||||
*r = msg->rule;
|
||||
|
||||
// source
|
||||
falco::schema::source s = falco::schema::source::SYSCALL;
|
||||
if(!falco::schema::source_Parse(source, &s))
|
||||
if(!falco::schema::source_Parse(msg->source, &s))
|
||||
{
|
||||
throw falco_exception("Unknown source passed to output_grpc::output_event()");
|
||||
throw falco_exception("Unknown source passed to output_grpc::output()");
|
||||
}
|
||||
grpc_res.set_source(s);
|
||||
|
||||
// priority
|
||||
falco::schema::priority p = falco::schema::priority::EMERGENCY;
|
||||
if(!falco::schema::priority_Parse(falco_common::priority_names[priority], &p))
|
||||
if(!falco::schema::priority_Parse(falco_common::priority_names[msg->priority], &p))
|
||||
{
|
||||
throw falco_exception("Unknown priority passed to output_grpc::output_event()");
|
||||
throw falco_exception("Unknown priority passed to output_grpc::output()");
|
||||
}
|
||||
grpc_res.set_priority(p);
|
||||
|
||||
// output
|
||||
auto output = grpc_res.mutable_output();
|
||||
*output = msg;
|
||||
*output = msg->msg;
|
||||
|
||||
// output fields
|
||||
auto &fields = *grpc_res.mutable_output_fields();
|
||||
auto resolvedTkns = falco_formats::resolve_tokens(evt, source, format);
|
||||
for(const auto &kv : resolvedTkns)
|
||||
for(const auto &kv : msg->fields)
|
||||
{
|
||||
fields[kv.first] = kv.second;
|
||||
}
|
||||
@@ -68,9 +65,4 @@ void falco::outputs::output_grpc::output_event(gen_event *evt, std::string &rule
|
||||
*host = m_hostname;
|
||||
|
||||
falco::grpc::queue::get().push(grpc_res);
|
||||
}
|
||||
|
||||
void falco::outputs::output_grpc::output_msg(falco_common::priority_type priority, std::string &msg)
|
||||
{
|
||||
// todo(fntlnz, leodido, leogr) > gRPC does not support subscribing to dropped events yet
|
||||
}
|
||||
@@ -25,10 +25,7 @@ namespace outputs
|
||||
|
||||
class output_grpc : public abstract_output
|
||||
{
|
||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
||||
|
||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
||||
void output(const message *msg);
|
||||
};
|
||||
|
||||
} // namespace outputs
|
||||
|
||||
@@ -18,13 +18,7 @@ limitations under the License.
|
||||
#include "logger.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
void falco::outputs::output_http::output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
||||
{
|
||||
output_msg(priority, msg);
|
||||
}
|
||||
|
||||
void falco::outputs::output_http::output_msg(falco_common::priority_type priority, std::string &msg)
|
||||
void falco::outputs::output_http::output(const message *msg)
|
||||
{
|
||||
CURL *curl = NULL;
|
||||
CURLcode res = CURLE_FAILED_INIT;
|
||||
@@ -37,7 +31,7 @@ void falco::outputs::output_http::output_msg(falco_common::priority_type priorit
|
||||
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, m_oc.options["url"].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg->msg.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
@@ -25,10 +25,7 @@ namespace outputs
|
||||
|
||||
class output_http : public abstract_output
|
||||
{
|
||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
||||
|
||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
||||
void output(const message *msg);
|
||||
};
|
||||
|
||||
} // namespace outputs
|
||||
|
||||
@@ -31,17 +31,11 @@ void falco::outputs::output_program::open_pfile()
|
||||
}
|
||||
}
|
||||
|
||||
void falco::outputs::output_program::output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
||||
{
|
||||
output_msg(priority, msg);
|
||||
}
|
||||
|
||||
void falco::outputs::output_program::output_msg(falco_common::priority_type priority, std::string &msg)
|
||||
void falco::outputs::output_program::output(const message *msg)
|
||||
{
|
||||
open_pfile();
|
||||
|
||||
fprintf(m_pfile, "%s\n", msg.c_str());
|
||||
fprintf(m_pfile, "%s\n", msg->msg.c_str());
|
||||
|
||||
if(m_oc.options["keep_alive"] != "true")
|
||||
{
|
||||
|
||||
@@ -25,10 +25,7 @@ namespace outputs
|
||||
|
||||
class output_program : public abstract_output
|
||||
{
|
||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
||||
|
||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
||||
void output(const message *msg);
|
||||
|
||||
void cleanup();
|
||||
|
||||
|
||||
@@ -18,16 +18,10 @@ limitations under the License.
|
||||
#include <iostream>
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
void falco::outputs::output_stdout::output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
||||
{
|
||||
output_msg(priority, msg);
|
||||
}
|
||||
|
||||
void falco::outputs::output_stdout::output_msg(falco_common::priority_type priority, std::string &msg)
|
||||
void falco::outputs::output_stdout::output(const message *msg)
|
||||
{
|
||||
//
|
||||
// By default, the stdout stream is fully buffered or line buffered
|
||||
// By default, the stdout stream is fully buffered or line buffered
|
||||
// (if the stream can be determined to refer to an interactive device, e.g. in a TTY).
|
||||
// Just enable automatic flushing when unbuffered output is desired.
|
||||
// Note that it is set every time since other writings to the stdout can disable it.
|
||||
@@ -36,7 +30,7 @@ void falco::outputs::output_stdout::output_msg(falco_common::priority_type prior
|
||||
{
|
||||
std::cout << std::unitbuf;
|
||||
}
|
||||
std::cout << msg + "\n";
|
||||
std::cout << msg->msg + "\n";
|
||||
}
|
||||
|
||||
void falco::outputs::output_stdout::cleanup()
|
||||
|
||||
@@ -25,10 +25,7 @@ namespace outputs
|
||||
|
||||
class output_stdout : public abstract_output
|
||||
{
|
||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
||||
|
||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
||||
void output(const message *msg);
|
||||
|
||||
void cleanup();
|
||||
};
|
||||
|
||||
@@ -18,14 +18,8 @@ limitations under the License.
|
||||
#include <syslog.h>
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
void falco::outputs::output_syslog::output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
||||
{
|
||||
output_msg(priority, msg);
|
||||
}
|
||||
|
||||
void falco::outputs::output_syslog::output_msg(falco_common::priority_type priority, std::string &msg)
|
||||
void falco::outputs::output_syslog::output(const message *msg)
|
||||
{
|
||||
// Syslog output should not have any trailing newline
|
||||
::syslog(priority, "%s", msg.c_str());
|
||||
::syslog(msg->priority, "%s", msg->msg.c_str());
|
||||
}
|
||||
|
||||
@@ -25,10 +25,7 @@ namespace outputs
|
||||
|
||||
class output_syslog : public abstract_output
|
||||
{
|
||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
||||
|
||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
||||
void output(const message *msg);
|
||||
};
|
||||
|
||||
} // namespace outputs
|
||||
|
||||
@@ -57,4 +57,7 @@ enum source {
|
||||
k8s_audit = 1;
|
||||
K8s_audit = 1;
|
||||
K8S_audit = 1;
|
||||
INTERNAL = 2;
|
||||
internal = 2;
|
||||
Internal = 2;
|
||||
}
|
||||
|
||||
@@ -36,10 +36,14 @@ message request
|
||||
// its parts as per semver 2.0 specification (https://semver.org).
|
||||
message response
|
||||
{
|
||||
// falco version
|
||||
string version = 1;
|
||||
uint32 major = 2;
|
||||
uint32 minor = 3;
|
||||
uint32 patch = 4;
|
||||
string prerelease = 5;
|
||||
string build = 6;
|
||||
}
|
||||
// falco engine version
|
||||
uint32 engine_version = 7;
|
||||
string engine_fields_checksum = 8;
|
||||
}
|
||||
|
||||
96
userspace/falco/watchdog.h
Normal file
96
userspace/falco/watchdog.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright (C) 2020 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 <chrono>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <atomic>
|
||||
|
||||
template<typename _T>
|
||||
class watchdog
|
||||
{
|
||||
public:
|
||||
watchdog():
|
||||
m_timeout(nullptr),
|
||||
m_is_running(false)
|
||||
{
|
||||
}
|
||||
|
||||
~watchdog()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void start(std::function<void(_T)> cb,
|
||||
std::chrono::milliseconds resolution = std::chrono::milliseconds(100))
|
||||
{
|
||||
stop();
|
||||
m_is_running.store(true, std::memory_order_release);
|
||||
m_thread = std::thread([this, cb, resolution]() {
|
||||
const auto no_deadline = time_point{};
|
||||
timeout_data curr;
|
||||
while(m_is_running.load(std::memory_order_acquire))
|
||||
{
|
||||
auto t = m_timeout.exchange(nullptr, std::memory_order_release);
|
||||
if(t)
|
||||
{
|
||||
curr = *t;
|
||||
delete t;
|
||||
}
|
||||
if(curr.deadline != no_deadline && curr.deadline < std::chrono::steady_clock::now())
|
||||
{
|
||||
cb(curr.payload);
|
||||
curr.deadline = no_deadline;
|
||||
}
|
||||
std::this_thread::sleep_for(resolution);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if(m_is_running.load(std::memory_order_acquire))
|
||||
{
|
||||
m_is_running.store(false, std::memory_order_release);
|
||||
if(m_thread.joinable())
|
||||
{
|
||||
m_thread.join();
|
||||
}
|
||||
delete m_timeout.exchange(nullptr, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
inline void set_timeout(std::chrono::milliseconds timeout, _T payload) noexcept
|
||||
{
|
||||
delete m_timeout.exchange(new timeout_data{std::chrono::steady_clock::now() + timeout, payload}, std::memory_order_release);
|
||||
}
|
||||
|
||||
inline void cancel_timeout() noexcept
|
||||
{
|
||||
delete m_timeout.exchange(new timeout_data, std::memory_order_release);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::chrono::time_point<std::chrono::steady_clock> time_point;
|
||||
struct timeout_data
|
||||
{
|
||||
time_point deadline;
|
||||
_T payload;
|
||||
};
|
||||
std::atomic<timeout_data *> m_timeout;
|
||||
std::atomic<bool> m_is_running;
|
||||
std::thread m_thread;
|
||||
};
|
||||
Reference in New Issue
Block a user