Compare commits

..

5 Commits

Author SHA1 Message Date
Lorenzo Fontana
1d9188a316 wip: pointer to pointer in hawk_engine rules_cb
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-11-04 19:06:41 +01:00
Leonardo Di Donato
5cc102545f wip
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-11-04 12:05:07 +00:00
Leonardo Di Donato
2801c62666 new(userspace/falco): destroy rules watcher when needed
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-10-29 11:33:12 +00:00
Leonardo Di Donato
c6cffc1f48 new(userspace): make hawk_watch_rules aware of the engine
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-10-29 10:58:28 +00:00
Lorenzo Fontana
4894c93d5e new(userspace): initial draft for libhawk
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <fontanalorenz@gmail.com>
2020-10-28 15:43:27 +01:00
61 changed files with 846 additions and 1657 deletions

View File

@@ -1,4 +0,0 @@
approvers:
- jonahjon
reviewers:
- jonahjon

View File

@@ -282,8 +282,6 @@ jobs:
- run:
name: Execute integration tests
command: /usr/bin/entrypoint test
- store_test_results:
path: /build/release/integration-tests-xunit
"tests/integration-static":
docker:
- image: falcosecurity/falco-tester:latest
@@ -299,8 +297,6 @@ jobs:
- run:
name: Execute integration tests
command: /usr/bin/entrypoint test
- store_test_results:
path: /build-static/release/integration-tests-xunit
"tests/driver-loader/integration":
machine:
image: ubuntu-1604:202004-01
@@ -452,25 +448,6 @@ 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:
@@ -537,26 +514,6 @@ 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:
@@ -616,16 +573,7 @@ workflows:
requires:
- "publish/packages-dev"
- "tests/driver-loader/integration"
- "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
- "quality/static-analysis"
release:
jobs:
- "build/musl":
@@ -668,12 +616,3 @@ 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 Normal file
View File

@@ -0,0 +1,20 @@
# 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

View File

@@ -1,79 +1,5 @@
# 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

View File

@@ -19,15 +19,6 @@ 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
@@ -69,7 +60,7 @@ if(MUSL_OPTIMIZED_BUILD)
set(MUSL_FLAGS "-static -Os")
endif()
set(CMAKE_COMMON_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
set(CMAKE_COMMON_FLAGS "-Wall -pg -ggdb ${DRAIOS_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
if(BUILD_WARNINGS_AS_ERRORS)
set(CMAKE_SUPPRESSED_WARNINGS
@@ -92,7 +83,7 @@ include(GetFalcoVersion)
set(PACKAGE_NAME "falco")
set(PROBE_NAME "falco")
set(PROBE_DEVICE_NAME "falco")
set(DRIVERS_REPO "https://download.falco.org/driver")
set(DRIVERS_REPO "https://dl.bintray.com/falcosecurity/driver")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX
/usr
@@ -124,8 +115,20 @@ set(CURSES_NEED_NCURSES TRUE)
find_package(Curses REQUIRED)
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
# b64
include(b64)
# 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 "")
# yaml-cpp
include(yaml-cpp)
@@ -139,16 +142,52 @@ if(NOT MINIMAL_BUILD)
endif()
# LuaJIT
include(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 "")
# Lpeg
include(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 "")
# libyaml
include(libyaml)
# lyaml
include(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")
# One TBB
set(TBB_SRC "${PROJECT_BINARY_DIR}/tbb-prefix/src/tbb")
@@ -181,7 +220,6 @@ 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()

View File

@@ -5,9 +5,7 @@
[![Build Status](https://img.shields.io/circleci/build/github/falcosecurity/falco/master?style=for-the-badge)](https://circleci.com/gh/falcosecurity/falco) [![CII Best Practices Summary](https://img.shields.io/cii/summary/2317?label=CCI%20Best%20Practices&style=for-the-badge)](https://bestpractices.coreinfrastructure.org/projects/2317) [![GitHub](https://img.shields.io/github/license/falcosecurity/falco?style=for-the-badge)](COPYING)
Want to talk? Join us on the [#falco](https://kubernetes.slack.com/archives/CMWH3EH32) channel in the [Kubernetes Slack](https://slack.k8s.io).
### Latest releases
#### Latest releases
Read the [change log](CHANGELOG.md).
@@ -26,22 +24,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/getting-started/installation/).
If you would like to run Falco in **production** please adhere to the [official installation guide](https://falco.org/docs/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/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. |
| 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. |
### 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/master/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/update-readme/userspace/falco/outputs.proto).
The Falco Project supports various SDKs for this endpoint.
##### SDKs
@@ -65,7 +63,6 @@ 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
@@ -75,13 +72,6 @@ The [Official Documentation](https://falco.org/docs/) is the best resource to le
To get involved with The Falco Project please visit [the community repository](https://github.com/falcosecurity/community) to find more.
How to reach out?
- Join the #falco channel on the [Kubernetes Slack](https://slack.k8s.io)
- [Join the Falco mailing list](https://lists.cncf.io/g/cncf-falco-dev)
- [Read the Falco documentation](https://falco.org/docs/)
### Contributing
See the [CONTRIBUTING.md](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md).
@@ -104,4 +94,4 @@ Falco is licensed to you under the [Apache 2.0](./COPYING) open source license.
[3]: https://dl.bintray.com/falcosecurity/deb-dev/stable
[4]: https://dl.bintray.com/falcosecurity/deb/stable
[5]: https://dl.bintray.com/falcosecurity/bin-dev/x86_64
[6]: https://dl.bintray.com/falcosecurity/bin/x86_64
[6]: https://dl.bintray.com/falcosecurity/bin/x86_64

View File

@@ -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:
- 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)
- 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,12 +69,13 @@ Now assume `x.y.z` is the new version.
| deb | [![deb](https://img.shields.io/badge/Falco-x.y.z-%2300aec7?style=flat-square)](https://dl.bintray.com/falcosecurity/deb/stable/falco-x.y.z-x86_64.deb) |
| tgz | [![tgz](https://img.shields.io/badge/Falco-x.y.z-%2300aec7?style=flat-square)](https://dl.bintray.com/falcosecurity/bin/x86_64/falco-x.y.z-x86_64.deb) |
| 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` |
| 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 -->
### Statistics

View File

@@ -30,15 +30,9 @@ 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")
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_SECTION "utils")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
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

View File

@@ -10,7 +10,6 @@
# "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}")
@@ -21,8 +20,6 @@ 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")

View File

@@ -1,27 +0,0 @@
#
# 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 ""
)

View File

@@ -22,7 +22,6 @@ 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)
@@ -32,7 +31,6 @@ 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)
@@ -45,7 +43,6 @@ if(NOT USE_BUNDLED_DEPS)
endif()
# gpr
mark_as_advanced(GPR_LIB)
find_library(GPR_LIB NAMES gpr)
if(GPR_LIB)
@@ -55,16 +52,12 @@ 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)
@@ -122,7 +115,7 @@ else()
grpc
DEPENDS openssl
GIT_REPOSITORY https://github.com/grpc/grpc.git
GIT_TAG v1.32.0
GIT_TAG v1.31.1
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}

View File

@@ -10,7 +10,6 @@
# "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)

View File

@@ -15,13 +15,12 @@ set(LIBYAML_SRC "${PROJECT_BINARY_DIR}/libyaml-prefix/src/libyaml")
set(LIBYAML_INSTALL_DIR "${LIBYAML_SRC}/target")
message(STATUS "Using bundled libyaml in '${LIBYAML_SRC}'")
set(LIBYAML_LIB "${LIBYAML_SRC}/src/.libs/libyaml.a")
externalproject_add(
libyaml
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
CONFIGURE_COMMAND ./configure --prefix=${LIBYAML_INSTALL_DIR} CFLAGS=-fPIC CPPFLAGS=-fPIC --enable-static=true --enable-shared=false
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS ${LIBYAML_LIB}
INSTALL_COMMAND ${CMD_MAKE} install
)
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)

View File

@@ -1,28 +0,0 @@
#
# 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 "")

View File

@@ -1,27 +0,0 @@
#
# 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 ""
)

View File

@@ -1,28 +0,0 @@
#
# 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"
)

View File

@@ -3,7 +3,6 @@ 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)

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2020 The Falco Authors.
# Copyright (C) 2019 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 -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/luajit.patch)
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch)

View File

@@ -1,8 +1,8 @@
diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c
index 6f51588e..5f9ea84e 100644
index e9faea51..a1b3b501 100644
--- a/userspace/libscap/scap.c
+++ b/userspace/libscap/scap.c
@@ -55,7 +55,7 @@ limitations under the License.
@@ -52,7 +52,7 @@ limitations under the License.
//#define NDEBUG
#include <assert.h>
@@ -11,16 +11,7 @@ index 6f51588e..5f9ea84e 100644
//
// Probe version string size
@@ -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,
@@ -171,7 +171,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
return NULL;
}
@@ -29,16 +20,7 @@ index 6f51588e..5f9ea84e 100644
bpf_probe = buf;
}
}
@@ -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)
@@ -1808,7 +1808,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
const char* scap_get_host_root()
{

View File

@@ -1,57 +0,0 @@
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);

View File

@@ -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 "5c0b863ddade7a45568c0ac97d037422c9efb750")
set(SYSDIG_CHECKSUM "SHA256=9de717b3a4b611ea6df56afee05171860167112f74bb7717b394bcc88ac843cd")
set(SYSDIG_VERSION "2aa88dcf6243982697811df4c1b484bcbe9488a2")
set(SYSDIG_CHECKSUM "SHA256=a737077543a6f3473ab306b424bcf7385d788149829ed1538252661b0f20d0f6")
endif()
set(PROBE_VERSION "${SYSDIG_VERSION}")
@@ -57,7 +57,6 @@ 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()

View File

@@ -10,7 +10,6 @@
# "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)

View File

@@ -3,7 +3,7 @@ FROM falcosecurity/falco:${FALCO_IMAGE_TAG}
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
LABEL usage="docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc:ro --name NAME IMAGE"
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"
ENV HOST_ROOT /host
ENV HOME /root

View File

@@ -2,7 +2,7 @@ FROM debian:stable
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 -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc --name NAME IMAGE"
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"
ARG FALCO_VERSION=latest
ARG VERSION_BUCKET=deb

View File

@@ -1,5 +1,7 @@
FROM ubuntu:18.04 as ubuntu
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG FALCO_VERSION
ARG VERSION_BUCKET=bin
@@ -20,14 +22,6 @@ 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"]

View File

@@ -28,10 +28,7 @@
# The files will be read in the order presented here, so make sure if
# you have overrides they appear in later files.
rules_file:
- /etc/falco/falco_rules.yaml
- /etc/falco/falco_rules.local.yaml
- /etc/falco/k8s_audit_rules.yaml
- /etc/falco/rules.d
- /tmp/falco
# If true, the times displayed in log messages and output messages
# will be in ISO 8601. By default, times are displayed in the local
@@ -87,23 +84,6 @@ 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:

View File

@@ -1,240 +0,0 @@
# 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.

View File

@@ -1,9 +1,5 @@
# Falco Drivers Storage S3
Supersedes: [20200818-artifacts-storage.md#drivers](20200818-artifacts-storage.md#drivers)
Supersedes: [20200901-artifacts-cleanup.md#drivers](20200901-artifacts-cleanup.md#drivers)
## Introduction
In the past days, as many people probably noticed, Bintray started rate-limiting our users, effectively preventing them from downloading any kernel module, rpm/deb package or any pre-built dependency we host there.
@@ -45,7 +41,7 @@ Before today, we had many issues with storage even without the spike in users we
## Context on AWS
Amazon AWS, recently gave credits to the Falco project to operate some parts of the infrastructure on AWS. The CNCF is providing a sub-account we are already using for the migration of the other pieces (like Prow).
Amazon AWS, recently gave credits to the Falco project to operate some parts of the infrastructure on AWS. The CNCF is providing a sub-account we are already using for the migration of the other pieces (like Prow).
## Interactions with other teams and the CNCF
@@ -59,7 +55,7 @@ We want to propose to move the drivers and the container dependencies to S3.
#### Moving means:
* We create a public S3 bucket with [stats enabled](https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html)
* We create a public S3 bucket with[ stats enabled](https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html)
* We attach the bucket to a cloudfront distribution behind the download.falco.org subdomain
@@ -117,7 +113,7 @@ export DRIVERS_REPO=https://your-url-here
Pass it as environment variable using the docker run flag -e - for example:
docker run -e DRIVERS_REPO=[https://your-url-here](https://your-url-here)
docker run -e DRIVERS_REPO=[https://your-url-here](https://your-url-here)
**Kubernetes**

View File

@@ -1213,9 +1213,6 @@
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
@@ -1336,7 +1333,6 @@
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
@@ -1601,12 +1597,7 @@
- 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
and not exe_running_docker_save
condition: mkdir and bin_dir_mkdir and not package_mgmt_procs and not user_known_mkdir_bin_dir_activities
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)
@@ -1617,7 +1608,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: [crio, multus]
items: []
- macro: user_known_change_thread_namespace_activities
condition: (never_true)
@@ -1875,7 +1866,6 @@
- list: falco_privileged_images
items: [
docker.io/calico/node,
calico/node,
docker.io/cloudnativelabs/kube-router,
docker.io/docker/ucp-agent,
docker.io/falcosecurity/falco,
@@ -2324,9 +2314,6 @@
- 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.
@@ -2345,7 +2332,6 @@
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
@@ -2439,9 +2425,9 @@
- rule: Contact K8S API Server From Container
desc: Detect attempts to contact the K8S API Server from a container
condition: >
evt.type=connect and evt.dir=< and
evt.type=connect and evt.dir=< and
(fd.typechar=4 or fd.typechar=6) and
container and
container and
not k8s_containers and
k8s_api_server and
not user_known_contact_k8s_api_server_activities
@@ -2661,7 +2647,7 @@
- rule: Delete or rename shell history
desc: Detect shell history deletion
condition: >
(modify_shell_history or truncate_shell_history) and
(modify_shell_history or truncate_shell_history) and
not var_lib_docker_filepath and
not proc.name in (docker_binaries)
output: >
@@ -2730,7 +2716,6 @@
(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)
@@ -2878,22 +2863,12 @@
- 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 in (user_known_k8s_ns_kube_system_images)) or container.image.repository in (user_known_k8s_images)
(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
- macro: user_known_k8s_client_container_parens
condition: (user_known_k8s_client_container)
@@ -2906,7 +2881,7 @@
tags: [container, mitre_execution]
# This rule is enabled by default.
# This rule is enabled by default.
# If you want to disable it, modify the following macro.
- macro: consider_packet_socket_communication
condition: (always_true)
@@ -3066,32 +3041,6 @@
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.

View File

@@ -537,7 +537,7 @@
condition: >
kevt
and non_system_user
and ka.user.name in (full_admin_k8s_users)
and ka.user.name in (admin_k8s_users)
and not allowed_full_admin_users
output: K8s Operation performed by full admin user (user=%ka.user.name target=%ka.target.name/%ka.target.resource verb=%ka.verb uri=%ka.uri resp=%ka.response.code)
priority: WARNING

View File

@@ -220,7 +220,7 @@ load_kernel_module() {
rmmod "${DRIVER_NAME}" 2>/dev/null
WAIT_TIME=0
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
while lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
while lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1 && [ $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 | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" > /dev/null 2>&1; then
if lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
echo "* ${DRIVER_NAME} module seems to still be loaded, hoping the best"
exit 0
fi

View File

@@ -104,12 +104,8 @@ function run_tests() {
suites+=($SCRIPTDIR/falco_tests_package.yaml)
fi
XUNIT_DIR="${OPT_BUILD_DIR}/integration-tests-xunit"
mkdir -p "${XUNIT_DIR}"
for mult in "${suites[@]}"; do
XUNIT_FILE_NAME="${XUNIT_DIR}/$(basename "${mult}").xml"
CMD="avocado run --xunit ${XUNIT_FILE_NAME} --mux-yaml $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
CMD="avocado run --mux-yaml $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
echo "Running $CMD"
BUILD_DIR=${OPT_BUILD_DIR} $CMD
RC=$?

View File

@@ -38,7 +38,8 @@ if(MINIMAL_BUILD)
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
"${PROJECT_BINARY_DIR}/userspace/engine")
"${PROJECT_BINARY_DIR}/userspace/engine"
"${PROJECT_SOURCE_DIR}/userspace/libhawk")
else()
target_include_directories(
falco_engine
@@ -51,11 +52,17 @@ else()
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
"${PROJECT_BINARY_DIR}/userspace/engine")
"${PROJECT_BINARY_DIR}/userspace/engine"
"${PROJECT_SOURCE_DIR}/userspace/libhawk")
endif()
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}")
if(DEFINED LIBHAWK_LIBRARIES)
message(STATUS "Using externally provided libhawk implementations: ${LIBHAWK_LIBRARIES}")
target_link_libraries(falco_engine ${LIBHAWK_LIBRARIES})
endif()
configure_file(config_falco_engine.h.in config_falco_engine.h)
if(DEFINED FALCO_COMPONENT)

View File

@@ -26,7 +26,8 @@ limitations under the License.
#include "formats.h"
extern "C" {
extern "C"
{
#include "lpeg.h"
#include "lyaml.h"
}
@@ -34,7 +35,6 @@ extern "C" {
#include "utils.h"
#include "banned.h" // This raises a compilation error when certain functions are used
string lua_on_event = "on_event";
string lua_print_stats = "print_stats";
@@ -42,24 +42,24 @@ using namespace std;
nlohmann::json::json_pointer falco_engine::k8s_audit_time = "/stageTimestamp"_json_pointer;
falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
: m_rules(NULL), m_next_ruleset_id(0),
m_min_priority(falco_common::PRIORITY_DEBUG),
m_sampling_ratio(1), m_sampling_multiplier(0),
m_replace_container_info(false)
falco_engine::falco_engine(bool seed_rng, const std::string &alternate_lua_dir):
m_rules(NULL), m_next_ruleset_id(0),
m_min_priority(falco_common::PRIORITY_DEBUG),
m_sampling_ratio(1), m_sampling_multiplier(0),
m_replace_container_info(false)
{
luaopen_lpeg(m_ls);
luaopen_yaml(m_ls);
m_alternate_lua_dir = alternate_lua_dir;
falco_common::init(m_lua_main_filename.c_str(), alternate_lua_dir.c_str());
falco_rules::init(m_ls);
m_sinsp_rules.reset(new falco_sinsp_ruleset());
m_k8s_audit_rules.reset(new falco_ruleset());
clear_filters();
if(seed_rng)
{
srandom((unsigned) getpid());
srandom((unsigned)getpid());
}
m_default_ruleset_id = find_ruleset_id(m_default_ruleset);
@@ -70,15 +70,24 @@ falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
falco_engine::~falco_engine()
{
if (m_rules)
if(m_rules)
{
delete m_rules;
}
}
falco_engine *falco_engine::clone()
{
auto engine = new falco_engine(true, m_alternate_lua_dir);
engine->set_inspector(m_inspector);
engine->set_extra(m_extra, m_replace_container_info);
engine->set_min_priority(m_min_priority);
return engine;
}
uint32_t falco_engine::engine_version()
{
return (uint32_t) FALCO_ENGINE_VERSION;
return (uint32_t)FALCO_ENGINE_VERSION;
}
#define DESCRIPTION_TEXT_START 16
@@ -144,17 +153,28 @@ void falco_engine::list_fields(bool names_only)
}
}
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
{
uint64_t dummy;
ifstream is;
return load_rules(rules_content, verbose, all_events, dummy);
is.open(rules_filename);
if(!is.is_open())
{
throw falco_exception("Could not open rules filename " +
rules_filename + " " +
"for reading");
}
string rules_content((istreambuf_iterator<char>(is)),
istreambuf_iterator<char>());
load_rules(rules_content, verbose, all_events);
}
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version)
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
{
// The engine must have been given an inspector by now.
if(! m_inspector)
if(!m_inspector)
{
throw falco_exception("No inspector provided");
}
@@ -166,45 +186,52 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
if(!m_rules)
{
m_rules = new falco_rules(m_inspector,
this,
m_ls);
// Note that falco_formats is added to the lua state used by the falco engine only.
// Within the engine, only formats.
// Formatter is used, so we can unconditionally set json_output to false.
bool json_output = false;
bool json_include_output_property = false;
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property);
m_rules = new falco_rules(m_inspector, this, m_ls);
}
// Note that falco_formats is added to the lua state used
// by the falco engine only. Within the engine, only
// formats.formatter is used, so we can unconditionally set
// json_output to false.
bool json_output = false;
bool json_include_output_property = false;
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property);
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, required_engine_version);
}
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
{
uint64_t dummy;
// m_sinsp_rules.reset(new falco_sinsp_ruleset());
// m_k8s_audit_rules.reset(new falco_ruleset());
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, dummy);
return load_rules_file(rules_filename, verbose, all_events, dummy);
m_is_ready = true;
return;
//
// auto local_rules = new falco_rules(m_inspector, this, m_ls);
// try
// {
// uint64_t dummy;
// local_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, dummy);
// // m_rules = local_rules
// // std::atomic<falco_rules *> lore(m_rules);
// // std::atomic_exchange(&lore, local_rules);
// // SCHEDULE LOCAL_RULES AS NEXT RULESET
// }
// catch(const falco_exception &e)
// {
// // todo
// printf("IGNORE BECAUSE OF ERROR LOADING RULESET!\n");
// }
}
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events, uint64_t &required_engine_version)
// // todo(fntlnz): not sure we want this in falco_engine
// void falco_engine::watch_rules(bool verbose, bool all_events)
// {
// hawk_watch_rules((hawk_watch_rules_cb)rules_cb, reinterpret_cast<hawk_engine *>(this));
// }
bool falco_engine::is_ready()
{
ifstream is;
is.open(rules_filename);
if (!is.is_open())
{
throw falco_exception("Could not open rules filename " +
rules_filename + " " +
"for reading");
}
string rules_content((istreambuf_iterator<char>(is)),
istreambuf_iterator<char>());
load_rules(rules_content, verbose, all_events, required_engine_version);
return m_is_ready;
}
void falco_engine::enable_rule(const string &substring, bool enabled, const string &ruleset)
@@ -272,7 +299,7 @@ uint64_t falco_engine::num_rules_for_ruleset(const std::string &ruleset)
uint16_t ruleset_id = find_ruleset_id(ruleset);
return m_sinsp_rules->num_rules_for_ruleset(ruleset_id) +
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
}
void falco_engine::evttypes_for_ruleset(std::vector<bool> &evttypes, const std::string &ruleset)
@@ -311,15 +338,15 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
if(lua_pcall(m_ls, 1, 3, 0) != 0)
{
const char* lerr = lua_tostring(m_ls, -1);
const char *lerr = lua_tostring(m_ls, -1);
string err = "Error invoking function output: " + string(lerr);
throw falco_exception(err);
}
res->evt = ev;
const char *p = lua_tostring(m_ls, -3);
const char *p = lua_tostring(m_ls, -3);
res->rule = p;
res->source = "syscall";
res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2);
res->priority_num = (falco_common::priority_type)lua_tonumber(m_ls, -2);
res->format = lua_tostring(m_ls, -1);
lua_pop(m_ls, 3);
}
@@ -333,6 +360,7 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_evt *ev)
{
// todo(leodido, fntlnz) > pass the last ruleset id
return process_sinsp_event(ev, m_default_ruleset_id);
}
@@ -344,7 +372,7 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json
}
// All k8s audit events have the single tag "1".
if(!m_k8s_audit_rules->run((gen_event *) ev, 1, ruleset_id))
if(!m_k8s_audit_rules->run((gen_event *)ev, 1, ruleset_id))
{
return unique_ptr<struct rule_result>();
}
@@ -359,15 +387,15 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json
if(lua_pcall(m_ls, 1, 3, 0) != 0)
{
const char* lerr = lua_tostring(m_ls, -1);
const char *lerr = lua_tostring(m_ls, -1);
string err = "Error invoking function output: " + string(lerr);
throw falco_exception(err);
}
res->evt = ev;
const char *p = lua_tostring(m_ls, -3);
const char *p = lua_tostring(m_ls, -3);
res->rule = p;
res->source = "k8s_audit";
res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2);
res->priority_num = (falco_common::priority_type)lua_tonumber(m_ls, -2);
res->format = lua_tostring(m_ls, -1);
lua_pop(m_ls, 3);
}
@@ -393,7 +421,7 @@ bool falco_engine::parse_k8s_audit_json(nlohmann::json &j, std::list<json_event>
{
// Note we only handle a single top level array, to
// avoid excessive recursion.
if(! parse_k8s_audit_json(item, evts, false))
if(!parse_k8s_audit_json(item, evts, false))
{
return false;
}
@@ -471,7 +499,7 @@ void falco_engine::print_stats()
{
if(lua_pcall(m_ls, 0, 0, 0) != 0)
{
const char* lerr = lua_tostring(m_ls, -1);
const char *lerr = lua_tostring(m_ls, -1);
string err = "Error invoking function print_stats: " + string(lerr);
throw falco_exception(err);
}
@@ -480,21 +508,20 @@ void falco_engine::print_stats()
{
throw falco_exception("No function " + lua_print_stats + " found in lua rule loader module");
}
}
void falco_engine::add_sinsp_filter(string &rule,
set<uint32_t> &evttypes,
set<uint32_t> &syscalls,
set<string> &tags,
sinsp_filter* filter)
sinsp_filter *filter)
{
m_sinsp_rules->add(rule, evttypes, syscalls, tags, filter);
}
void falco_engine::add_k8s_audit_filter(string &rule,
set<string> &tags,
json_event_filter* filter)
json_event_filter *filter)
{
// All k8s audit events have a single tag "1".
std::set<uint32_t> event_tags = {1};
@@ -536,8 +563,8 @@ inline bool falco_engine::should_drop_evt()
return false;
}
double coin = (random() * (1.0/RAND_MAX));
return (coin >= (1.0/(m_sampling_multiplier * m_sampling_ratio)));
double coin = (random() * (1.0 / RAND_MAX));
return (coin >= (1.0 / (m_sampling_multiplier * m_sampling_ratio)));
}
sinsp_filter_factory &falco_engine::sinsp_factory()

View File

@@ -38,6 +38,11 @@ limitations under the License.
#include "config_falco_engine.h"
#include "falco_common.h"
extern "C"
{
#include "hawk.h"
}
//
// This class acts as the primary interface between a program and the
// falco rules engine. Falco outputs (writing to files/syslog/etc) are
@@ -47,9 +52,12 @@ limitations under the License.
class falco_engine : public falco_common
{
public:
falco_engine(bool seed_rng=true, const std::string& alternate_lua_dir=FALCO_ENGINE_SOURCE_LUA_DIR);
falco_engine(bool seed_rng = true, const std::string &alternate_lua_dir = FALCO_ENGINE_SOURCE_LUA_DIR);
virtual ~falco_engine();
falco_engine(const falco_engine &rhs);
falco_engine *clone();
// A given engine has a version which identifies the fields
// and rules file format it supports. This version will change
// any time the code that handles rules files, expression
@@ -57,7 +65,7 @@ public:
static uint32_t engine_version();
// Print to stdout (using printf) a description of each field supported by this engine.
void list_fields(bool names_only=false);
void list_fields(bool names_only = false);
//
// Load rules either directly or from a filename.
@@ -65,12 +73,8 @@ public:
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events);
void load_rules(const std::string &rules_content, bool verbose, bool all_events);
//
// Identical to above, but also returns the required engine version for the file/content.
// (If no required engine version is specified, returns 0).
//
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events, uint64_t &required_engine_version);
void load_rules(const std::string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version);
// Watch and live-reload rules using an external ABI interface provided by libhawk
void watch_rules(bool verbose, bool all_events);
//
// Enable/Disable any rules matching the provided substring.
@@ -85,7 +89,6 @@ public:
// Wrapper that assumes the default ruleset
void enable_rule(const std::string &substring, bool enabled);
// Like enable_rule, but the rule name must be an exact match.
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset);
@@ -154,7 +157,8 @@ public:
// **Methods Related to k8s audit log events, which are
// **represented as json objects.
struct rule_result {
struct rule_result
{
gen_event *evt;
std::string rule;
std::string source;
@@ -170,7 +174,7 @@ public:
// Returns true if the json object was recognized as a k8s
// audit event(s), false otherwise.
//
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top=true);
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top = true);
//
// Given an event, check it against the set of rules in the
@@ -195,7 +199,7 @@ public:
//
void add_k8s_audit_filter(std::string &rule,
std::set<std::string> &tags,
json_event_filter* filter);
json_event_filter *filter);
// **Methods Related to Sinsp Events e.g system calls
//
@@ -236,13 +240,14 @@ public:
std::set<uint32_t> &evttypes,
std::set<uint32_t> &syscalls,
std::set<std::string> &tags,
sinsp_filter* filter);
sinsp_filter *filter);
sinsp_filter_factory &sinsp_factory();
json_event_filter_factory &json_factory();
private:
bool is_ready();
private:
static nlohmann::json::json_pointer k8s_audit_time;
//
@@ -262,6 +267,8 @@ private:
std::unique_ptr<falco_sinsp_ruleset> m_sinsp_rules;
std::unique_ptr<falco_ruleset> m_k8s_audit_rules;
std::string m_alternate_lua_dir;
//
// Here's how the sampling ratio and multiplier influence
// whether or not an event is dropped in
@@ -291,5 +298,6 @@ private:
std::string m_extra;
bool m_replace_container_info;
};
bool m_is_ready = false;
};

View File

@@ -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},

View File

@@ -26,14 +26,15 @@ 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,

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2020 The Falco Authors.
# Copyright (C) 2019 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,10 +11,39 @@
# specific language governing permissions and limitations under the License.
#
configure_file(config_falco.h.in config_falco.h)
configure_file("${SYSDIG_SOURCE_DIR}/userspace/sysdig/config_sysdig.h.in" config_sysdig.h)
set(
FALCO_SOURCES
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
configuration.cpp
logger.cpp
falco_outputs.cpp
@@ -25,74 +54,84 @@ set(
event_drops.cpp
statsfilewriter.cpp
falco.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
"${SYSDIG_SOURCE_DIR}/userspace/sysdig/fields_info.cpp")
else()
add_executable(
falco
configuration.cpp
logger.cpp
falco_outputs.cpp
outputs_file.cpp
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)
list(
APPEND FALCO_INCLUDE_DIRECTORIES
"${CIVETWEB_INCLUDE_DIR}"
"${OPENSSL_INCLUDE_DIR}"
"${GRPC_INCLUDE}"
"${GRPCPP_INCLUDE}"
"${PROTOBUF_INCLUDE}"
)
add_dependencies(falco civetweb)
endif()
list(APPEND FALCO_DEPENDENCIES civetweb)
add_dependencies(falco string-view-lite)
list(
APPEND FALCO_LIBRARIES
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
"${GPR_LIB}"
"${GRPC_LIB}"
"${GRPCPP_LIB}"
@@ -101,66 +140,19 @@ if(NOT MINIMAL_BUILD)
"${OPENSSL_LIBRARY_CRYPTO}"
"${LIBYAML_LIB}"
"${YAMLCPP_LIB}"
"${CIVETWEB_LIB}"
)
"${CIVETWEB_LIB}")
endif()
add_executable(
falco
${FALCO_SOURCES}
)
add_dependencies(falco ${FALCO_DEPENDENCIES})
target_link_libraries(
falco
${FALCO_LIBRARIES}
)
target_include_directories(
falco
PUBLIC
${FALCO_INCLUDE_DIRECTORIES}
)
configure_file(config_falco.h.in config_falco.h)
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"
)
# 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")
else()
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}
)
MESSAGE(STATUS "Skipping engine fields checksum when building the minimal Falco.")
endif()
# strip the Falco binary when releasing using musl
@@ -169,8 +161,7 @@ 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})

View File

@@ -47,6 +47,16 @@ 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;
@@ -58,16 +68,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
m_config->get_sequence<list<string>>(rules_files, string("rules_file"));
for(auto &file : rules_files)
{
// Here, we only include files that exist
struct stat buffer;
if(stat(file.c_str(), &buffer) == 0)
{
read_rules_file_directory(file, m_rules_filenames);
}
}
m_json_output = m_config->get_scalar<bool>("json_output", false);
m_json_include_output_property = m_config->get_scalar<bool>("json_include_output_property", true);
@@ -166,8 +166,6 @@ 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);
@@ -234,69 +232,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
m_syscall_evt_simulate_drops = m_config->get_scalar<bool>("syscall_event_drops", "simulate_drops", false);
}
void falco_configuration::read_rules_file_directory(const string &path, list<string> &rules_filenames)
{
struct stat st;
int rc = stat(path.c_str(), &st);
if(rc != 0)
{
std::cerr << "Could not get info on rules file " << path << ": " << strerror(errno) << std::endl;
exit(-1);
}
if(st.st_mode & S_IFDIR)
{
// It's a directory. Read the contents, sort
// alphabetically, and add every path to
// rules_filenames
vector<string> dir_filenames;
DIR *dir = opendir(path.c_str());
if(!dir)
{
std::cerr << "Could not get read contents of directory " << path << ": " << strerror(errno) << std::endl;
exit(-1);
}
for(struct dirent *ent = readdir(dir); ent; ent = readdir(dir))
{
string efile = path + "/" + ent->d_name;
rc = stat(efile.c_str(), &st);
if(rc != 0)
{
std::cerr << "Could not get info on rules file " << efile << ": " << strerror(errno) << std::endl;
exit(-1);
}
if(st.st_mode & S_IFREG)
{
dir_filenames.push_back(efile);
}
}
closedir(dir);
std::sort(dir_filenames.begin(),
dir_filenames.end());
for(string &ent : dir_filenames)
{
rules_filenames.push_back(ent);
}
}
else
{
// Assume it's a file and just add to
// rules_filenames. If it can't be opened/etc that
// will be reported later..
rules_filenames.push_back(path);
}
}
static bool split(const string &str, char delim, pair<string, string> &parts)
{

View File

@@ -190,9 +190,6 @@ public:
void init(std::string conf_filename, std::list<std::string>& cmdline_options);
void init(std::list<std::string>& cmdline_options);
static void read_rules_file_directory(const string& path, list<string>& rules_filenames);
std::list<std::string> m_rules_filenames;
bool m_json_output;
bool m_json_include_output_property;
std::string m_log_level;
@@ -204,7 +201,6 @@ 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;

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,6 @@ limitations under the License.
#include "formats.h"
#include "logger.h"
#include "watchdog.h"
#include "outputs_file.h"
#include "outputs_program.h"
@@ -52,26 +51,18 @@ falco_outputs::~falco_outputs()
{
if(m_initialized)
{
this->stop_worker();
for(auto o : m_outputs)
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
delete o;
(*it)->cleanup();
}
}
}
void falco_outputs::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)
bool json_include_output_property,
uint32_t rate, uint32_t max_burst, bool buffered,
bool time_format_iso_8601, 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,
@@ -80,29 +71,17 @@ 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;
@@ -150,12 +129,6 @@ 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")
{
@@ -190,38 +163,35 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
sformat += " " + format;
}
cmsg.msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
cmsg.fields = falco_formats::resolve_tokens(evt, source, sformat);
string msg;
msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
cmsg.type = ctrl_msg_type::CTRL_MSG_OUTPUT;
m_queue.push(cmsg);
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
(*it)->output_event(evt, rule, source, priority, sformat, msg);
}
}
void falco_outputs::handle_msg(uint64_t ts,
void falco_outputs::handle_msg(uint64_t now,
falco_common::priority_type priority,
std::string &msg,
std::string &rule,
std::map<std::string, std::string> &output_fields)
{
falco_outputs::ctrl_msg cmsg = {};
cmsg.ts = ts;
cmsg.priority = priority;
cmsg.source = "internal";
cmsg.rule = rule;
cmsg.fields = output_fields;
std::string full_msg;
if(m_json_output)
{
nlohmann::json jmsg;
// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
time_t evttime = ts / 1000000000;
time_t evttime = now / 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", ts % 1000000000);
snprintf(time_ns, sizeof(time_ns), ".%09luZ", now % 1000000000);
iso8601evttime = time_sec;
iso8601evttime += time_ns;
@@ -231,15 +201,15 @@ void falco_outputs::handle_msg(uint64_t ts,
jmsg["time"] = iso8601evttime;
jmsg["output_fields"] = output_fields;
cmsg.msg = jmsg.dump();
full_msg = jmsg.dump();
}
else
{
std::string timestr;
bool first = true;
sinsp_utils::ts_to_string(ts, &timestr, false, true);
cmsg.msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
sinsp_utils::ts_to_string(now, &timestr, false, true);
full_msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
for(auto &pair : output_fields)
{
if(first)
@@ -248,95 +218,23 @@ void falco_outputs::handle_msg(uint64_t ts,
}
else
{
cmsg.msg += " ";
full_msg += " ";
}
cmsg.msg += pair.first + "=" + pair.second;
full_msg += pair.first + "=" + pair.second;
}
cmsg.msg += ")";
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);
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
(*it)->output_msg(priority, full_msg);
}
}
void falco_outputs::reopen_outputs()
{
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())
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
m_worker_thread.join();
(*it)->reopen();
}
}
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);
}

View File

@@ -25,7 +25,6 @@ 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
@@ -40,25 +39,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);
// Format then send the event to all configured outputs (`evt` is an event that has matched some rule).
//
// evt is an event that has matched some rule. Pass the event
// to all configured outputs.
//
void handle_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format);
// Format then send a generic message to all outputs. Not necessarily associated with any event.
// 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:
@@ -72,28 +71,5 @@ 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();
};

View File

@@ -15,7 +15,6 @@ 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"
@@ -76,9 +75,6 @@ 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);

View File

@@ -37,21 +37,6 @@ 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.
@@ -60,8 +45,6 @@ struct message
class abstract_output
{
public:
virtual ~abstract_output() {}
void init(config oc, bool buffered, std::string hostname)
{
m_oc = oc;
@@ -69,19 +52,15 @@ public:
m_hostname = hostname;
}
// Return the output's name as per its configuration.
const std::string get_name() const
{
return m_oc.name;
}
// 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;
// Output a message.
virtual void output(const message *msg) = 0;
// Output a generic message. Not necessarily associated with any event.
virtual void output_msg(falco_common::priority_type priority, std::string &msg) = 0;
// Possibly close the output and open it again.
virtual void reopen() {}
// Possibly flush the output.
virtual void cleanup() {}
protected:

View File

@@ -31,10 +31,16 @@ void falco::outputs::output_file::open_file()
}
}
void falco::outputs::output_file::output(const message *msg)
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)
{
open_file();
m_outfile << msg->msg + "\n";
m_outfile << msg + "\n";
if(m_oc.options["keep_alive"] != "true")
{

View File

@@ -27,7 +27,10 @@ namespace outputs
class output_file : public abstract_output
{
void output(const message *msg);
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 cleanup();

View File

@@ -21,41 +21,44 @@ 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(const message *msg)
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)
{
falco::outputs::response grpc_res;
// time
auto timestamp = grpc_res.mutable_time();
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(msg->ts);
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(evt->get_ts());
// rule
auto r = grpc_res.mutable_rule();
*r = msg->rule;
*r = rule;
// source
falco::schema::source s = falco::schema::source::SYSCALL;
if(!falco::schema::source_Parse(msg->source, &s))
if(!falco::schema::source_Parse(source, &s))
{
throw falco_exception("Unknown source passed to output_grpc::output()");
throw falco_exception("Unknown source passed to output_grpc::output_event()");
}
grpc_res.set_source(s);
// priority
falco::schema::priority p = falco::schema::priority::EMERGENCY;
if(!falco::schema::priority_Parse(falco_common::priority_names[msg->priority], &p))
if(!falco::schema::priority_Parse(falco_common::priority_names[priority], &p))
{
throw falco_exception("Unknown priority passed to output_grpc::output()");
throw falco_exception("Unknown priority passed to output_grpc::output_event()");
}
grpc_res.set_priority(p);
// output
auto output = grpc_res.mutable_output();
*output = msg->msg;
*output = msg;
// output fields
auto &fields = *grpc_res.mutable_output_fields();
for(const auto &kv : msg->fields)
auto resolvedTkns = falco_formats::resolve_tokens(evt, source, format);
for(const auto &kv : resolvedTkns)
{
fields[kv.first] = kv.second;
}
@@ -65,4 +68,9 @@ void falco::outputs::output_grpc::output(const message *msg)
*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
}

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_grpc : public abstract_output
{
void output(const message *msg);
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);
};
} // namespace outputs

View File

@@ -18,7 +18,13 @@ 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(const message *msg)
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)
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
@@ -31,7 +37,7 @@ void falco::outputs::output_http::output(const message *msg)
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->msg.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
res = curl_easy_perform(curl);

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_http : public abstract_output
{
void output(const message *msg);
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);
};
} // namespace outputs

View File

@@ -31,11 +31,17 @@ void falco::outputs::output_program::open_pfile()
}
}
void falco::outputs::output_program::output(const message *msg)
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)
{
open_pfile();
fprintf(m_pfile, "%s\n", msg->msg.c_str());
fprintf(m_pfile, "%s\n", msg.c_str());
if(m_oc.options["keep_alive"] != "true")
{

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_program : public abstract_output
{
void output(const message *msg);
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 cleanup();

View File

@@ -18,10 +18,16 @@ 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(const message *msg)
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)
{
//
// 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.
@@ -30,7 +36,7 @@ void falco::outputs::output_stdout::output(const message *msg)
{
std::cout << std::unitbuf;
}
std::cout << msg->msg + "\n";
std::cout << msg + "\n";
}
void falco::outputs::output_stdout::cleanup()

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_stdout : public abstract_output
{
void output(const message *msg);
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 cleanup();
};

View File

@@ -18,8 +18,14 @@ 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(const message *msg)
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)
{
// Syslog output should not have any trailing newline
::syslog(msg->priority, "%s", msg->msg.c_str());
::syslog(priority, "%s", msg.c_str());
}

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_syslog : public abstract_output
{
void output(const message *msg);
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);
};
} // namespace outputs

View File

@@ -57,7 +57,4 @@ enum source {
k8s_audit = 1;
K8s_audit = 1;
K8S_audit = 1;
INTERNAL = 2;
internal = 2;
Internal = 2;
}

View File

@@ -36,14 +36,10 @@ 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;
}
}

View File

@@ -1,96 +0,0 @@
/*
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;
};

10
userspace/libhawk/hawk.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef HAWK_H
#define HAWK_H
extern void hawk_init();
extern void hawk_destroy();
typedef void* hawk_engine;
typedef void (*hawk_watch_rules_cb)(char* rules_content, hawk_engine* engine);
extern void hawk_watch_rules(hawk_watch_rules_cb cb, hawk_engine* engine);
#endif //HAWK_H