Compare commits

..

53 Commits

Author SHA1 Message Date
Kris Nova
258103be08 adding changes for laptop 2020-06-16 11:17:16 -07:00
Kris Nova
f35cc98126 feat(debug): More debug for testing in GKE
Signed-off-by: Kris Nova <kris@nivenly.com>
2020-06-10 21:26:06 -07:00
Kris Nova
94149e4b00 feat(debug): Just pushing my work up so I can go work from the couch
I will squash this and most of this is throw away code anyway.

Signed-off-by: Kris Nova <kris@nivenly.com>
2020-06-10 19:06:24 -07:00
Leonardo Grasso
578ef7f64d rule(Create files below dev): correct condition to catch openat
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-10 12:21:36 +02:00
Leonardo Grasso
a5ce61f03f rule(macro bin_dir_rename): correct condition to catch all variants
Since `evt.arg[1]` does not work for all syscalls, switch to:
 - `evt.arg.path` for `rmdir` and `unlink` (used by `remove` macro)
 - `evt.arg.name` for `unlinkat` (used by `remove` macro)
 - `evt.arg.oldpath/newpath` for `rename` and `renameat` (used by `rename` macro)

That ensures `Modify binary dirs` works properly.

Note that we cannot yet use `renameat2` (not supported by sinsp, see https://github.com/draios/sysdig/issues/1603 )

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-10 12:21:36 +02:00
Leonardo Grasso
74ca02d199 rule(macro bin_dir_mkdir): correct condition to catch mkdirat case
Since the dir's path is found:
-  in `evt.arg[1]` for `mkdir`
-  but in `evt.arg[2]` for `mkdirat`
switch to `evt.arg.path` to catch both.
That ensures `Mkdir binary dirs` works properly.

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-10 12:21:36 +02:00
Leonardo Di Donato
3bfd94fefd docs(test): run locally handling python deps with venv
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-26 15:01:48 +02:00
Leonardo Di Donato
6eb9b1add1 build(test): requirements.txt
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-26 15:01:48 +02:00
Nicolas Marier
81e29c55ec rule(macro user_known_set_setuid_or_setgid_bit_conditions): create macro
This macro will be useful because it will make it possible to filter out
events with a higher degree of granularity than is currently possible
for the `Set Setuid or Setgid bit` rule.

For example, if some application is expected to set the setuid or the
setgid bit under a specific condition, like if it's started with a
specific command, then the `user_known_chmod_applications` list is not
enough because we don't want to filter out _all_ events by this
application, only specific ones. This macro allows that.

Signed-off-by: Nicolas Marier <nmarier@coveo.com>
2020-05-26 10:23:31 +02:00
Leonardo Di Donato
f186e5f41f fix(userspace/falco): set gpr log verbosity accordingly to the Falco one
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-21 18:15:46 +02:00
Leonardo Di Donato
ade64b0ce8 update(userspace/falco): make log level a configuration member
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-21 18:15:46 +02:00
Leonardo Di Donato
d808c0aeaf update(tests/engine): test is_unix_scheme
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-21 18:15:46 +02:00
Leonardo Di Donato
65e069a020 update(userspace/engine): url_is_unix_scheme() util is now is_unix_scheme(string_view)
Also no more custom `starts_with` utility function.

Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-21 18:15:46 +02:00
Leonardo Di Donato
75c2275dac build(userspace): falco and falco_engine depend on string-view-lite header
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-21 18:15:46 +02:00
Leonardo Di Donato
258f73ede2 build: download string-view-lite
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-21 18:15:46 +02:00
Leonardo Di Donato
3386671452 build(cmake/modules): cmake module for string-view-lite
The CMake module downloads `string-view-lite` from
https://github.com/martinmoene/string-view-lite

It is a single-file header-only version of C++17-like `string_view` for
C++98, C++03, C++11, and later.

Notices it also provides C++20 extensions like:

- empty()
- starts_with()
- ends_with()
- etc.

Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
2680a459ec new(tests/engine): update socket path
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
da9278f061 docs: add grpc notice in falco.yaml
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
dc0670c718 update(userspace/falco): wrap gpr logs into falco logs
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
05ce5b7f0b new(tests): cases for falco::utils::starts_with
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
de8bade2bf update(userspace/engine): move utils inside engine
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
e245fe460f docs: update falco.yaml to explain how to use the unix socket feature
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
d7de45acb2 new(userspace/falco): gRPC server unix socket support
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Lorenzo Fontana
86b473e224 update(userspace/falco): utilities to detect unix socket prefix in string
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-21 18:15:46 +02:00
Mark Stemm
d1c9aae881 rule(list allowed_k8s_users): Add vertical pod autoscaler as known k8s users
https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler

Example alert:
---
K8s Operation performed by user not in allowed list of
users (user=vpa-recommender target=vpa-recommender/endpoints verb=update
uri=core/v1/namespaces/kube-system/endpoints/vpa-recommender resp=200)

K8s Operation performed by user not in allowed list of
users (user=vpa-updater target=vpa-updater/endpoints verb=update
uri=core/v1/namespaces/kube-system/endpoints/vpa-updater resp=200)
---

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
2020-05-21 10:57:42 +02:00
Mark Stemm
986ea28279 rule(macro user_known_k8s_client_container): Allow hcp-tunnelfront torun kubectl in containers
https://stackoverflow.com/questions/50349586/what-is-hcp-tunnelfront

Example alert:

---
Docker or kubernetes client executed in container (user=root
parent=run-tunnel-fron cmdline=kubectl
--kubeconfig=/etc/kubernetes/kubeconfig/kubeconfig get secret
tunnelfront --namespace=kube-system --output json --ignore-not-found
image=mcr.microsoft.com/aks/hcp/hcp-tunnel-front)
---

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
2020-05-21 10:57:42 +02:00
Mark Stemm
5266618689 rule(macro lvprogs_writing_conf): Add lvs as a lvm program
Example event. I'm pretty sure the full file in this case is /etc/lvm/cache:

---
File below /etc opened for writing (user=root command=lvs --noheadings
--readonly --separator=";" -a -o
lv_tags,lv_path,lv_name,vg_name,lv_uuid,lv_size parent=ceph-volume
pcmdline=ceph-volume /usr/sbin/ceph-volume inventory --format json file=/etc/lvm/c...
---

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
2020-05-21 10:57:42 +02:00
Mark Stemm
fa3d2eb473 rule(macro trusted_logging_images): Let azure-npm image write to /var/log
"The Azure's NPM is a a daemonset that supports network policies as
defined by the Kubernetes policy specification."

Example event:

---
Log files were tampered (user=root command=azure-npm
file=/var/log/iptables.conf CID1 image=mcr.microsoft.com/containernetworking/azure-npm)
---

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
2020-05-21 10:57:42 +02:00
Mark Stemm
acb3f94786 rule(macro trusted_logging_images): Add addl fluentd image
Openshift specific variant, example alert:

---
Log files were tampered (user=root command=fluentd /usr/bin/fluentd
--no-supervisor file=/var/log/journal.pos CID1 image=registry.redhat.io/openshift3/ose-logging-fluentd)
---

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
2020-05-21 10:57:42 +02:00
kaizhe
d1af7e139f rule update: fix macro reference
Signed-off-by: kaizhe <derek0405@gmail.com>
2020-05-21 10:55:53 +02:00
Leonardo Grasso
434a5abc8b docs(CONTRIBUTING.md): update slack channel URL
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-20 18:07:51 +02:00
Lorenzo Fontana
fd97f99b9f build: focal builder generic kernel headers
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-19 16:34:58 +02:00
Lorenzo Fontana
555bf1f10d build: use ubuntu focal instead of bionic during the ubuntu CI step
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-05-19 16:34:58 +02:00
Leonardo Grasso
f3f512c6dd fix(.circleci): correct publishing command
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 18:16:53 +02:00
Leonardo Grasso
8d79c11953 fix(CHANGELOG.md): correct typo
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>

Co-authored-by: Leo Di Donato <leodidonato@gmail.com>
2020-05-18 16:56:21 +02:00
Leonardo Grasso
439152c8d8 docs: changelog for 0.23.0
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 16:56:21 +02:00
Leonardo Grasso
3d3d537d85 update(docker/falco-driver-loader): propagate all args
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
88dbc78a44 fix(scripts/falco-driver-loader): exit when bpf download fails
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
59c2e6b421 update(scripts/falco-driver-loader): break apart logic
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
33c93e6c29 chore(scripts/falco-driver-loader): improve messages
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
46483339a3 fix(test): correct kernel module name
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 14:08:25 +02:00
Leonardo Grasso
762ef015b8 fix(scripts): correct kernel module name
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 14:08:25 +02:00
Leonardo Grasso
b887c92c91 docs(RELEASE.md): correct typo
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 11:41:05 +02:00
Reshad Patuck
efd0bf1967 fix(falco-driver-loader): target for ubuntu is ubuntu-generic
The upstream files for the generic Ubuntu kernel are all called ubuntu-generic
see: https://dl.bintray.com/falcosecurity/driver/96bd9bc560f67742738eb7255aeb4d03046b8045/

Signed-off-by: Reshad Patuck <reshad@patuck.net>
2020-05-15 19:20:29 +02:00
Leo Di Donato
5c69639a69 update(.github): remove examples and integrations from PR template
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-15 11:27:18 +02:00
Leonardo Grasso
b8875df48f fix(.circleci): correct no-driver image aliasing
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:20:56 +02:00
Leonardo Grasso
368817a95d fix(docker/no-driver): correct config value substitution
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:20:56 +02:00
Leonardo Grasso
622a6c1e44 fix(test/driver-loader): source script to get env vars populated
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:19:31 +02:00
Leonardo Grasso
95e7242d13 test: add driver-loader integration tests
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:19:31 +02:00
Leonardo Grasso
c42cb1858c update(docker/falco): rename folder for naminig consistency
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
Leonardo Grasso
935d9f5378 fix(docker/no-driver): enable time_format_iso_8601 by default
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
Leonardo Grasso
2345ea2770 new(docker): add falco-no-driver image
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
Leonardo Grasso
901239c3c8 docs(docker): add falcosecurity/falco-no-driver image
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
61 changed files with 1251 additions and 1066 deletions

View File

@@ -2,9 +2,9 @@ version: 2
jobs:
# Build using ubuntu LTS
# This build is dynamic, most dependencies are taken from the OS
"build/ubuntu-bionic":
"build/ubuntu-focal":
docker:
- image: ubuntu:bionic
- image: ubuntu:focal
steps:
- checkout
- run:
@@ -12,19 +12,19 @@ jobs:
command: apt update -y
- run:
name: Install dependencies
command: apt install libssl-dev libyaml-dev libncurses-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm linux-headers-$(uname -r) libelf-dev cmake build-essential libcurl4-openssl-dev -y
command: DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libncurses-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-generic clang llvm git -y
- run:
name: Prepare project
command: |
mkdir build
pushd build
cmake ..
cmake -DBUILD_BPF=On ..
popd
- run:
name: Build
command: |
pushd build
make -j4 all
KERNELDIR=/lib/modules/$(ls /lib/modules)/build make -j4 all
popd
- run:
name: Run unit tests
@@ -34,9 +34,9 @@ jobs:
popd
# Debug build using ubuntu LTS
# This build is dynamic, most dependencies are taken from the OS
"build/ubuntu-bionic-debug":
"build/ubuntu-focal-debug":
docker:
- image: ubuntu:bionic
- image: ubuntu:focal
steps:
- checkout
- run:
@@ -44,19 +44,19 @@ jobs:
command: apt update -y
- run:
name: Install dependencies
command: apt install libssl-dev libyaml-dev libncurses-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm linux-headers-$(uname -r) libelf-dev cmake build-essential libcurl4-openssl-dev -y
command: DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libncurses-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-generic clang llvm git -y
- run:
name: Prepare project
command: |
mkdir build
pushd build
cmake -DCMAKE_BUILD_TYPE=debug ..
cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_BPF=On ..
popd
- run:
name: Build
command: |
pushd build
make -j4 all
KERNELDIR=/lib/modules/$(ls /lib/modules)/build make -j4 all
popd
- run:
name: Run unit tests
@@ -138,6 +138,15 @@ jobs:
- run:
name: Execute integration tests
command: /usr/bin/entrypoint test
"tests/driver-loader/integration":
machine:
image: ubuntu-1604:202004-01
steps:
- attach_workspace:
at: /tmp/ws
- run:
name: Execute driver-loader integration tests
command: /tmp/ws/source/falco/test/driver-loader/run_test.sh /tmp/ws/build/release/
# Sign rpm packages
"rpm/sign":
docker:
@@ -208,17 +217,19 @@ jobs:
- checkout
- setup_remote_docker
- run:
name: Build and publish slim-dev
name: Build and publish no-driver-dev
command: |
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 falcosecurity/falco:master-slim docker/slim
docker build --build-arg VERSION_BUCKET=bin-dev --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco-no-driver:master docker/no-driver
docker tag falcosecurity/falco-no-driver:master falcosecurity/falco:master-slim
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push falcosecurity/falco-no-driver:master
docker push falcosecurity/falco:master-slim
- run:
name: Build and publish dev
command: |
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 falcosecurity/falco:master docker/stable
docker build --build-arg VERSION_BUCKET=deb-dev --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco:master docker/falco
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push falcosecurity/falco:master
- run:
@@ -266,17 +277,21 @@ jobs:
- checkout
- setup_remote_docker
- run:
name: Build and publish slim
name: Build and publish no-driver
command: |
docker build --build-arg VERSION_BUCKET=deb --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco:${CIRCLE_TAG}-slim" docker/slim
docker tag "falcosecurity/falco:${CIRCLE_TAG}-slim" falcosecurity/falco:latest-slim
docker build --build-arg VERSION_BUCKET=bin --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco-no-driver:${CIRCLE_TAG}" docker/no-driver
docker tag "falcosecurity/falco-no-driver:${CIRCLE_TAG}" falcosecurity/falco-no-driver:latest
docker tag "falcosecurity/falco-no-driver:${CIRCLE_TAG}" "falcosecurity/falco:${CIRCLE_TAG}-slim"
docker tag "falcosecurity/falco-no-driver:${CIRCLE_TAG}" "falcosecurity/falco:latest-slim"
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push "falcosecurity/falco-no-driver:${CIRCLE_TAG}"
docker push "falcosecurity/falco-no-driver:latest"
docker push "falcosecurity/falco:${CIRCLE_TAG}-slim"
docker push "falcosecurity/falco:latest-slim"
- run:
name: Build and publish stable
name: Build and publish falco
command: |
docker build --build-arg VERSION_BUCKET=deb --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco:${CIRCLE_TAG}" docker/stable
docker build --build-arg VERSION_BUCKET=deb --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco:${CIRCLE_TAG}" docker/falco
docker tag "falcosecurity/falco:${CIRCLE_TAG}" falcosecurity/falco:latest
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push "falcosecurity/falco:${CIRCLE_TAG}"
@@ -293,13 +308,16 @@ workflows:
version: 2
build_and_test:
jobs:
- "build/ubuntu-bionic"
- "build/ubuntu-bionic-debug"
- "build/ubuntu-focal"
- "build/ubuntu-focal-debug"
- "build/centos7"
- "build/centos7-debug"
- "tests/integration":
requires:
- "build/centos7"
- "tests/driver-loader/integration":
requires:
- "build/centos7"
- "rpm/sign":
context: falco
filters:
@@ -327,6 +345,7 @@ workflows:
only: master
requires:
- "publish/packages-dev"
- "tests/driver-loader/integration"
release:
jobs:
- "build/centos7":

View File

@@ -40,12 +40,8 @@ Please remove the leading whitespace before the `/kind <>` you uncommented.
> /area engine
> /area examples
> /area rules
> /area integrations
> /area tests
> /area proposals

View File

@@ -2,6 +2,48 @@
This file documents all notable changes to Falco. The release numbering uses [semantic versioning](http://semver.org).
## v0.23.0
Released on 2020-18-05
### Major Changes
* BREAKING CHANGE: the falco-driver-loader script now references `falco-probe.o` and `falco-probe.ko` as `falco.o` and `falco.ko` [[#1158](https://github.com/falcosecurity/falco/pull/1158)]
* BREAKING CHANGE: the `falco-driver-loader` script environment variable to use a custom repository to download drivers now uses the `DRIVERS_REPO` environment variable instead of `DRIVER_LOOKUP_URL`. This variable must contain the parent URI containing the following directory structure `/$driver_version$/falco_$target$_$kernelrelease$_$kernelversion$.[ko|o]`. e.g: [[#1160](https://github.com/falcosecurity/falco/pull/1160)]
* new(scripts): options and command-line usage for `falco-driver-loader` [[#1200](https://github.com/falcosecurity/falco/pull/1200)]
* new: ability to specify exact matches when adding rules to Falco engine (only API) [[#1185](https://github.com/falcosecurity/falco/pull/1185)]
* new(docker): add an image that wraps the `falco-driver-loader` with the toolchain [[#1192](https://github.com/falcosecurity/falco/pull/1192)]
* new(docker): add `falcosecurity/falco-no-driver` image [[#1205](https://github.com/falcosecurity/falco/pull/1205)]
### Minor Changes
* update(scripts): improve `falco-driver-loader` output messages [[#1200](https://github.com/falcosecurity/falco/pull/1200)]
* update: containers look for prebuilt drivers on the Drivers Build Grid [[#1158](https://github.com/falcosecurity/falco/pull/1158)]
* update: driver version bump to 96bd9bc560f67742738eb7255aeb4d03046b8045 [[#1190](https://github.com/falcosecurity/falco/pull/1190)]
* update(docker): now `falcosecurity/falco:slim-*` alias to `falcosecurity/falco-no-driver:*` [[#1205](https://github.com/falcosecurity/falco/pull/1205)]
* docs: instructions to run unit tests [[#1199](https://github.com/falcosecurity/falco/pull/1199)]
* docs(examples): move `/examples` to `contrib` repo [[#1191](https://github.com/falcosecurity/falco/pull/1191)]
* update(docker): remove `minimal` image [[#1196](https://github.com/falcosecurity/falco/pull/1196)]
* update(integration): move `/integrations` to `contrib` repo [[#1157](https://github.com/falcosecurity/falco/pull/1157)]
* https://dl.bintray.com/driver/$driver_version$/falco_$target$_$kernelrelease$_$kernelversion$.[ko|o]` [[#1160](https://github.com/falcosecurity/falco/pull/1160)]
* update(docker/event-generator): remove the event-generator from Falco repository [[#1156](https://github.com/falcosecurity/falco/pull/1156)]
* docs(examples): set audit level to metadata for object secrets [[#1153](https://github.com/falcosecurity/falco/pull/1153)]
### Bug Fixes
* fix(scripts): upstream files (prebuilt drivers) for the generic Ubuntu kernel contains "ubuntu-generic" [[#1212](https://github.com/falcosecurity/falco/pull/1212)]
* fix: support Falco driver on Linux kernels 5.6.y [[#1174](https://github.com/falcosecurity/falco/pull/1174)]
### Rule Changes
* rule(Redirect STDOUT/STDIN to Network Connection in Container): correct rule name as per rules naming convention [[#1164](https://github.com/falcosecurity/falco/pull/1164)]
* rule(Redirect STDOUT/STDIN to Network Connection in Container): new rule to detect Redirect stdout/stdin to network connection in container [[#1152](https://github.com/falcosecurity/falco/pull/1152)]
* rule(K8s Secret Created): new rule to track the creation of Kubernetes secrets (excluding kube-system and service account secrets) [[#1151](https://github.com/falcosecurity/falco/pull/1151)]
* rule(K8s Secret Deleted): new rule to track the deletion of Kubernetes secrets (excluding kube-system and service account secrets) [[#1151](https://github.com/falcosecurity/falco/pull/1151)]
## v0.22.1
Released on 2020-17-04

View File

@@ -17,8 +17,8 @@ project(falco)
option(USE_BUNDLED_DEPS "Bundle hard to find dependencies into the Falco binary" OFF)
option(BUILD_WARNINGS_AS_ERRORS "Enable building with -Wextra -Werror flags" OFF)
# Elapsed time set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add
# a flag to enable this
# Elapsed time
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add a flag to enable this
# Make flag for parallel processing
include(ProcessorCount)
@@ -99,7 +99,8 @@ ExternalProject_Add(
BUILD_COMMAND ""
INSTALL_COMMAND "")
# curses We pull this in because libsinsp won't build without it
# curses
# We pull this in because libsinsp won't build without it
set(CURSES_NEED_NCURSES TRUE)
find_package(Curses REQUIRED)
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
@@ -214,11 +215,8 @@ ExternalProject_Add(
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
# Hedley
include(DownloadHedley)
# FlatBuffers
include(FlatBuffers)
#string-view-lite
include(DownloadStringViewLite)
# gRPC
include(gRPC)
@@ -241,8 +239,8 @@ add_subdirectory(rules)
# Dockerfiles
add_subdirectory(docker)
# Clang format add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:falco,SOURCES> COMMENT
# "Formatting ..." VERBATIM)
# Clang format
# add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:falco,SOURCES> COMMENT "Formatting ..." VERBATIM)
# Shared build variables
set(FALCO_SINSP_LIBRARY sinsp)
@@ -251,7 +249,6 @@ set(FALCO_ABSOLUTE_SHARE_DIR "${CMAKE_INSTALL_PREFIX}/${FALCO_SHARE_DIR}")
set(FALCO_BIN_DIR bin)
add_subdirectory(scripts)
add_subdirectory(userspace/profiler)
add_subdirectory(userspace/engine)
add_subdirectory(userspace/falco)
add_subdirectory(tests)

View File

@@ -81,7 +81,7 @@ Some examples:
### Slack
Other discussion, and **support requests** should go through the `#falco` channel in the open source slack, please join [here](https://slack.sysdig.com).
Other discussion, and **support requests** should go through the `#falco` channel in the Kubernetes slack, please join [here](https://slack.k8s.io/).
## Pull Requests

View File

@@ -12,7 +12,7 @@ Finally, on the proposed due date the assignees for the upcoming release proceed
### 1. Release notes
- Let `YYYY-MM-DD` the day before of the [latest release](https://github.com/falcosecurity/falco/releases)
- Check the release note block of every PR matching the `is:pr is:merged closed:>YYY-MM-DD` [filter](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+closed%3A%3EYYYY-MM-DD)
- Check the release note block of every PR matching the `is:pr is:merged closed:>YYYY-MM-DD` [filter](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+closed%3A%3EYYYY-MM-DD)
- Ensure the release note block follows the [commit convention](https://github.com/falcosecurity/falco/blob/master/CONTRIBUTING.md#commit-convention), otherwise fix its content
- If the PR has no milestone, assign it to the milestone currently undergoing release
- Check issues without a milestone (using [is:pr is:merged no:milestone closed:>YYYT-MM-DD](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+no%3Amilestone+closed%3A%3EYYYT-MM-DD) filter) and add them to the milestone currently undergoing release

View File

@@ -1,3 +1,16 @@
#
# 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(CPACK_PACKAGE_NAME "${PACKAGE_NAME}")
set(CPACK_PACKAGE_VENDOR "Cloud Native Computing Foundation (CNCF) cncf.io.")
set(CPACK_PACKAGE_CONTACT "cncf-falco-dev@lists.cncf.io") # todo: change this once we've got @falco.org addresses

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
@@ -12,17 +12,16 @@
#
include(ExternalProject)
set(CATCH2_PREFIX ${CMAKE_BINARY_DIR}/catch2-prefix)
set(CATCH2_INCLUDE ${CATCH2_PREFIX}/include)
set(CATCH2_INCLUDE ${CMAKE_BINARY_DIR}/catch2-prefix/include)
set(CATCH_EXTERNAL_URL URL https://github.com/catchorg/catch2/archive/v2.12.1.tar.gz URL_HASH
SHA256=e5635c082282ea518a8dd7ee89796c8026af8ea9068cd7402fb1615deacd91c3)
ExternalProject_Add(
catch2
PREFIX ${CATCH2_PREFIX}
PREFIX ${CMAKE_BINARY_DIR}/catch2-prefix
${CATCH_EXTERNAL_URL}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CATCH2_PREFIX}/src/catch2/single_include/catch2/catch.hpp
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/catch2-prefix/src/catch2/single_include/catch2/catch.hpp
${CATCH2_INCLUDE}/catch.hpp)

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
@@ -10,17 +10,20 @@
# "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(ExternalProject)
set(HEDLEY_PREFIX ${CMAKE_BINARY_DIR}/hedley-prefix)
set(HEDLEY_INCLUDE ${HEDLEY_PREFIX}/include)
message(STATUS "Found hedley: include: ${HEDLEY_INCLUDE}")
set(STRING_VIEW_LITE_PREFIX ${CMAKE_BINARY_DIR}/string-view-lite-prefix)
set(STRING_VIEW_LITE_INCLUDE ${STRING_VIEW_LITE_PREFIX}/include)
message(STATUS "Found string-view-lite: include: ${STRING_VIEW_LITE_INCLUDE}")
ExternalProject_Add(
hedley
PREFIX ${HEDLEY_PREFIX}
GIT_REPOSITORY "https://github.com/nemequ/hedley.git"
GIT_TAG "v13"
string-view-lite
PREFIX ${STRING_VIEW_LITE_PREFIX}
GIT_REPOSITORY "https://github.com/martinmoene/string-view-lite.git"
GIT_TAG "v1.4.0"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${HEDLEY_PREFIX}/src/hedley/hedley.h ${HEDLEY_INCLUDE}/hedley.h)
INSTALL_COMMAND
${CMAKE_COMMAND} -E copy ${STRING_VIEW_LITE_PREFIX}/src/string-view-lite/include/nonstd/string_view.hpp
${STRING_VIEW_LITE_INCLUDE}/nonstd/string_view.hpp)

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at

View File

@@ -1,82 +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.
#
if(NOT USE_BUNDLED_DEPS)
find_program(FLATBUFFERS_FLATC_EXECUTABLE NAMES flatc)
find_path(FLATBUFFERS_INCLUDE_DIR NAMES flatbuffers/flatbuffers.h)
if(FLATBUFFERS_FLATC_EXECUTABLE AND FLATBUFFERS_INCLUDE_DIR)
message(STATUS "Found flatbuffers: include: ${FLATBUFFERS_INCLUDE_DIR}, flatc: ${FLATBUFFERS_FLATC_EXECUTABLE}")
else()
message(FATAL_ERROR "Couldn't find system flatbuffers")
endif()
else()
include(ExternalProject)
set(FLATBUFFERS_PREFIX ${CMAKE_BINARY_DIR}/flatbuffers-prefix)
set(FLATBUFFERS_FLATC_EXECUTABLE
${FLATBUFFERS_PREFIX}/bin/flatc
CACHE INTERNAL "FlatBuffer compiler")
set(FLATBUFFERS_INCLUDE_DIR
${FLATBUFFERS_PREFIX}/include
CACHE INTERNAL "FlatBuffer include directory")
ExternalProject_Add(
flatbuffers
PREFIX ${FLATBUFFERS_PREFIX}
GIT_REPOSITORY "https://github.com/google/flatbuffers.git"
GIT_TAG "v1.12.0"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${FLATBUFFERS_PREFIX}
-DCMAKE_BUILD_TYPE=Release
-DFLATBUFFERS_CODE_COVERAGE=OFF
-DFLATBUFFERS_BUILD_TESTS=OFF
-DFLATBUFFERS_INSTALL=ON
-DFLATBUFFERS_BUILD_FLATLIB=OFF
-DFLATBUFFERS_BUILD_FLATC=ON
-DFLATBUFFERS_BUILD_FLATHASH=OFF
-DFLATBUFFERS_BUILD_GRPCTEST=OFF
-DFLATBUFFERS_BUILD_SHAREDLIB=OFF
BUILD_BYPRODUCTS ${FLATBUFFERS_FLATC_EXECUTABLE})
endif()
# From FindFlatBuffer.cmake
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FlatBuffers DEFAULT_MSG FLATBUFFERS_FLATC_EXECUTABLE FLATBUFFERS_INCLUDE_DIR)
if(FLATBUFFERS_FOUND)
function(FLATBUFFERS_GENERATE_C_HEADERS Name)
set(FLATC_OUTPUTS)
foreach(FILE ${ARGN})
get_filename_component(FLATC_OUTPUT ${FILE} NAME_WE)
set(FLATC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FLATC_OUTPUT}_generated.h")
list(APPEND FLATC_OUTPUTS ${FLATC_OUTPUT})
add_custom_command(
OUTPUT ${FLATC_OUTPUT}
COMMAND ${FLATBUFFERS_FLATC_EXECUTABLE} ARGS -c -o "${CMAKE_CURRENT_BINARY_DIR}/" ${FILE}
DEPENDS ${FILE}
COMMENT "Building C++ header for ${FILE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endforeach()
set(${Name}_OUTPUTS
${FLATC_OUTPUTS}
PARENT_SCOPE)
endfunction()
set(FLATBUFFERS_INCLUDE_DIRS ${FLATBUFFERS_INCLUDE_DIR})
include_directories(${CMAKE_BINARY_DIR})
else()
set(FLATBUFFERS_INCLUDE_DIR)
endif()

View File

@@ -1,3 +1,16 @@
#
# 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.
#
# Retrieve git ref and commit hash
include(GetGitRevisionDescription)

View File

@@ -1,3 +1,15 @@
#
# 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.
#
if(NOT USE_BUNDLED_DEPS)
find_package(OpenSSL REQUIRED)
message(STATUS "Found openssl: include: ${OPENSSL_INCLUDE_DIR}, lib: ${OPENSSL_LIBRARIES}")

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
@@ -16,7 +16,7 @@ set(SYSDIG_CMAKE_WORKING_DIR "${CMAKE_BINARY_DIR}/sysdig-repo")
# this needs to be here at the top
if(USE_BUNDLED_DEPS)
# explicitly force this dependency to use the system OpenSSL
# explicitly force this dependency to use the bundled OpenSSL
set(USE_BUNDLED_OPENSSL ON)
endif()

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at

View File

@@ -6,9 +6,9 @@ This directory contains various ways to package Falco as a container and related
| Name | Directory | Description |
|---|---|---|
| [falcosecurity/falco:latest](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:master](https://hub.docker.com/repository/docker/falcosecurity/falco) | docker/stable | Falco (DEB built from git tag or from the master) with all the building toolchain. |
| [falcosecurity/falco:latest-slim](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:_tag_-slim](https://hub.docker.com/repository/docker/falcosecurity/falco),[falcosecurity/falco:master-slim](https://hub.docker.com/repository/docker/falcosecurity/falco) | docker/slim | Falco (DEB build from git tag or from the master) without the building toolchain. |
| [falcosecurity/falco:latest](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:master](https://hub.docker.com/repository/docker/falcosecurity/falco) | docker/falco | Falco (DEB built from git tag or from the master) with all the building toolchain. |
| [falcosecurity/falco-driver-loader:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-driver-loader), [falcosecurity/falco-driver-loader:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco-driver-loader), [falcosecurity/falco-driver-loader:master](https://hub.docker.com/repository/docker/falcosecurity/falco-driver-loader) | docker/driver-loader | `falco-driver-loader` as entrypoint with the building toolchain. |
| [falcosecurity/falco-no-driver:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-no-driver), [falcosecurity/falco-no-driver:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco-no-driver),[falcosecurity/falco-no-driver:master](https://hub.docker.com/repository/docker/falcosecurity/falco-no-driver) | docker/no-driver | Falco (TGZ built from git tag or from the master) without the building toolchain. |
| [falcosecurity/falco-builder:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-builder) | docker/builder | The complete build tool chain for compiling Falco from source. See [the documentation](https://falco.org/docs/source/) for more details on building from source. Used to build Falco (CI). |
| [falcosecurity/falco-tester:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-tester) | docker/tester | Container image for running the Falco test suite. Used to run Falco integration tests (CI). |
| _to not be published_ | docker/local | Built on-the-fly and used by falco-tester. |

View File

@@ -0,0 +1,45 @@
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: falco
namespace: falco
labels:
app: falco
spec:
selector:
matchLabels:
app: falco
template:
metadata:
labels:
app: falco
spec:
tolerations:
- operator: Exists
hostPID: true
hostNetwork: true
containers:
- name: falco-init
image: alpine
imagePullPolicy: Always
securityContext:
privileged: true
lifecycle:
preStop:
exec:
command:
- "nsenter"
- "-t"
- "1"
- "-m"
- "--"
- "/bin/sh"
- "-c"
- |
#!/bin/bash
curl -s https://falco.org/repo/falcosecurity-3672BA8F.asc | apt-key add -
echo "deb https://dl.bintray.com/falcosecurity/deb stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list
apt-get update -y
apt-get -y install linux-headers-$(uname -r)
apt-get install -y falco
exit 0

View File

@@ -25,4 +25,4 @@ do
ln -s "$i" "/usr/src/$base"
done
/usr/bin/falco-driver-loader $1
/usr/bin/falco-driver-loader "$@"

View File

@@ -0,0 +1,61 @@
FROM ubuntu:18.04 as ubuntu
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG FALCO_VERSION
ARG VERSION_BUCKET=bin
ENV FALCO_VERSION=${FALCO_VERSION}
ENV VERSION_BUCKET=${VERSION_BUCKET}
WORKDIR /
ADD https://bintray.com/api/ui/download/falcosecurity/${VERSION_BUCKET}/x86_64/falco-${FALCO_VERSION}-x86_64.tar.gz /
RUN apt-get update -y && \
apt-get install -y libyaml-0-2 binutils && \
tar -xvf falco-${FALCO_VERSION}-x86_64.tar.gz && \
rm -f falco-${FALCO_VERSION}-x86_64.tar.gz && \
mv falco-${FALCO_VERSION}-x86_64 falco && \
strip falco/usr/bin/falco && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN sed -e 's/time_format_iso_8601: false/time_format_iso_8601: true/' < /falco/etc/falco/falco.yaml > /falco/etc/falco/falco.yaml.new \
&& mv /falco/etc/falco/falco.yaml.new /falco/etc/falco/falco.yaml
FROM scratch
COPY --from=ubuntu /lib/x86_64-linux-gnu/libanl.so.1 \
/lib/x86_64-linux-gnu/libc.so.6 \
/lib/x86_64-linux-gnu/libdl.so.2 \
/lib/x86_64-linux-gnu/libgcc_s.so.1 \
/lib/x86_64-linux-gnu/libm.so.6 \
/lib/x86_64-linux-gnu/libnsl.so.1 \
/lib/x86_64-linux-gnu/libnss_compat.so.2 \
/lib/x86_64-linux-gnu/libnss_files.so.2 \
/lib/x86_64-linux-gnu/libnss_nis.so.2 \
/lib/x86_64-linux-gnu/libpthread.so.0 \
/lib/x86_64-linux-gnu/librt.so.1 \
/lib/x86_64-linux-gnu/libz.so.1 \
/lib/x86_64-linux-gnu/
COPY --from=ubuntu /usr/lib/x86_64-linux-gnu/libstdc++.so.6 \
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
COPY --from=ubuntu /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.5 \
/usr/lib/x86_64-linux-gnu/libyaml-0.so.2
COPY --from=ubuntu /etc/ld.so.cache \
/etc/nsswitch.conf \
/etc/ld.so.cache \
/etc/passwd \
/etc/group \
/etc/
COPY --from=ubuntu /etc/default/nss /etc/default/nss
COPY --from=ubuntu /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=ubuntu /falco /
CMD ["/usr/bin/falco", "-o", "time_format_iso_8601=true"]

View File

@@ -1,48 +0,0 @@
FROM ubuntu:18.04
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
LABEL RUN="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
ENV FALCO_VERSION=${FALCO_VERSION}
ENV VERSION_BUCKET=${VERSION_BUCKET}
ENV HOST_ROOT /host
ENV HOME /root
RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# bash-completion \
# bc \
ca-certificates \
curl \
gnupg2 \
jq \
# netcat \
# xz-utils \
&& rm -rf /var/lib/apt/lists/*
RUN curl -s https://falco.org/repo/falcosecurity-3672BA8F.asc | apt-key add - \
&& echo "deb https://dl.bintray.com/falcosecurity/${VERSION_BUCKET} stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list \
&& apt-get update -y \
&& if [ "$FALCO_VERSION" = "latest" ]; then apt-get install -y --no-install-recommends falco; else apt-get install -y --no-install-recommends falco=${FALCO_VERSION}; fi \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Change the falco config within the container to enable ISO 8601
# output.
RUN sed -e 's/time_format_iso_8601: false/time_format_iso_8601: true/' < /etc/falco/falco.yaml > /etc/falco/falco.yaml.new \
&& mv /etc/falco/falco.yaml.new /etc/falco/falco.yaml
# Some base images have an empty /lib/modules by default
# If it's not empty, docker build will fail instead of
# silently overwriting the existing directory
RUN rm -df /lib/modules \
&& ln -s $HOST_ROOT/lib/modules /lib/modules
CMD ["/usr/bin/falco", "-o", "time_format_iso_8601=true"]

View File

@@ -30,7 +30,7 @@ How to use.
How to build.
* cd docker/builder && DOCKER_BUILDKIT=1 docker build -t falcosecurity/falco-tester .
* cd docker/tester && DOCKER_BUILDKIT=1 docker build -t falcosecurity/falco-tester .
Environment.

View File

@@ -167,21 +167,35 @@ http_output:
enabled: false
url: http://some.url
# gRPC server configuration.
# The gRPC server is secure by default (mutual TLS) so you need to generate certificates and update their paths here.
# Falco supports running a gRPC server with two main binding types
# 1. Over the network with mandatory mutual TLS authentication (mTLS)
# 2. Over a local unix socket with no authentication
# By default, the gRPC server is disabled, with no enabled services (see grpc_output)
# please comment/uncomment and change accordingly the options below to configure it.
# Important note: if Falco has any troubles creating the gRPC server
# this information will be logged, however the main Falco daemon will not be stopped.
# gRPC server over network with (mandatory) mutual TLS configuration.
# This gRPC server is secure by default so you need to generate certificates and update their paths here.
# By default the gRPC server is off.
# You can configure the address to bind and expose it.
# By modifying the threadiness configuration you can fine-tune the number of threads (and context) it will use.
# grpc:
# enabled: true
# bind_address: "0.0.0.0:5060"
# threadiness: 8
# private_key: "/etc/falco/certs/server.key"
# cert_chain: "/etc/falco/certs/server.crt"
# root_certs: "/etc/falco/certs/ca.crt"
# gRPC server using an unix socket
grpc:
enabled: false
bind_address: "0.0.0.0:5060"
bind_address: "unix:///var/run/falco.sock"
threadiness: 8
private_key: "/etc/falco/certs/server.key"
cert_chain: "/etc/falco/certs/server.crt"
root_certs: "/etc/falco/certs/ca.crt"
# gRPC output service.
# By default it is off.
# By enabling this all the output events will be kept in memory until you read them with a gRPC client.
# Make sure to have a consumer for them or leave this disabled.
grpc_output:
enabled: false

View File

@@ -55,6 +55,7 @@
- macro: proc_name_exists
condition: (proc.name!="<NA>")
# todo(leogr): we miss "renameat2", but it's not yet supported by sinsp
- macro: rename
condition: evt.type in (rename, renameat)
- macro: mkdir
@@ -80,17 +81,29 @@
- macro: bin_dir_mkdir
condition: >
(evt.arg[1] startswith /bin/ or
evt.arg[1] startswith /sbin/ or
evt.arg[1] startswith /usr/bin/ or
evt.arg[1] startswith /usr/sbin/)
(evt.arg.path startswith /bin/ or
evt.arg.path startswith /sbin/ or
evt.arg.path startswith /usr/bin/ or
evt.arg.path startswith /usr/sbin/)
- macro: bin_dir_rename
condition: >
evt.arg[1] startswith /bin/ or
evt.arg[1] startswith /sbin/ or
evt.arg[1] startswith /usr/bin/ or
evt.arg[1] startswith /usr/sbin/
(evt.arg.path startswith /bin/ or
evt.arg.path startswith /sbin/ or
evt.arg.path startswith /usr/bin/ or
evt.arg.path startswith /usr/sbin/ or
evt.arg.name startswith /bin/ or
evt.arg.name startswith /sbin/ or
evt.arg.name startswith /usr/bin/ or
evt.arg.name startswith /usr/sbin/ or
evt.arg.oldpath startswith /bin/ or
evt.arg.oldpath startswith /sbin/ or
evt.arg.oldpath startswith /usr/bin/ or
evt.arg.oldpath startswith /usr/sbin/ or
evt.arg.newpath startswith /bin/ or
evt.arg.newpath startswith /sbin/ or
evt.arg.newpath startswith /usr/bin/ or
evt.arg.newpath startswith /usr/sbin/)
- macro: etc_dir
condition: fd.name startswith /etc/
@@ -707,7 +720,7 @@
- macro: lvprogs_writing_conf
condition: >
(proc.name in (dmeventd,lvcreate,pvscan) and
(proc.name in (dmeventd,lvcreate,pvscan,lvs) and
(fd.name startswith /etc/lvm/archive or
fd.name startswith /etc/lvm/backup or
fd.name startswith /etc/lvm/cache))
@@ -1505,7 +1518,7 @@
- rule: Modify binary dirs
desc: an attempt to modify any file below a set of binary directories.
condition: (bin_dir_rename) and modify and not package_mgmt_procs and not exe_running_docker_save
condition: bin_dir_rename and modify and not package_mgmt_procs and not exe_running_docker_save
output: >
File below known binary directory renamed/removed (user=%user.name command=%proc.cmdline
pcmdline=%proc.pcmdline operation=%evt.type file=%fd.name %evt.args container_id=%container.id image=%container.image.repository)
@@ -2225,7 +2238,7 @@
desc: creating any files below /dev other than known programs that manage devices. Some rootkits hide files in /dev.
condition: >
fd.directory = /dev and
(evt.type = creat or (evt.type = open and evt.arg.flags contains O_CREAT))
(evt.type = creat or ((evt.type = open or evt.type = openat) and evt.arg.flags contains O_CREAT))
and not proc.name in (dev_creation_binaries)
and not fd.name in (allowed_dev_files)
and not fd.name startswith /dev/tty
@@ -2437,7 +2450,9 @@
- macro: trusted_logging_images
condition: (container.image.repository endswith "splunk/fluentd-hec" or
container.image.repository endswith "fluent/fluentd-kubernetes-daemonset")
container.image.repository endswith "fluent/fluentd-kubernetes-daemonset" or
container.image.repository endswith "openshift3/ose-logging-fluentd" or
container.image.repository endswith "containernetworking/azure-npm")
- rule: Clear Log Activities
desc: Detect clearing of critical log files
@@ -2514,6 +2529,12 @@
- list: user_known_chmod_applications
items: [hyperkube, kubelet]
# This macro should be overridden in user rules as needed. This is useful if a given application
# should not be ignored alltogether with the user_known_chmod_applications list, but only in
# specific conditions.
- macro: user_known_set_setuid_or_setgid_bit_conditions
condition: (never_true)
- rule: Set Setuid or Setgid bit
desc: >
When the setuid or setgid bits are set for an application,
@@ -2523,6 +2544,7 @@
consider_all_chmods and chmod and (evt.arg.mode contains "S_ISUID" or evt.arg.mode contains "S_ISGID")
and not proc.name in (user_known_chmod_applications)
and not exe_running_docker_save
and not user_known_set_setuid_or_setgid_bit_conditions
output: >
Setuid or setgid bit is set via chmod (fd=%evt.arg.fd filename=%evt.arg.filename mode=%evt.arg.mode user=%user.name process=%proc.name
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
@@ -2556,7 +2578,7 @@
items: [rsync, scp, sftp, dcp]
- macro: remote_file_copy_procs
condition: (proc.name in (remote_File_copy_binaries))
condition: (proc.name in (remote_file_copy_binaries))
- rule: Launch Remote File Copy Tools in Container
desc: Detect remote file copy tools launched in container
@@ -2687,11 +2709,16 @@
# Whitelist for known docker client binaries run inside container
# - k8s.gcr.io/fluentd-gcp-scaler in GCP/GKE
- macro: user_known_k8s_client_container
condition: (k8s.ns.name="kube-system" and container.image.repository=k8s.gcr.io/fluentd-gcp-scaler)
condition: >
(k8s.ns.name="kube-system" and container.image.repository=k8s.gcr.io/fluentd-gcp-scaler) or
container.image.repository=mcr.microsoft.com/aks/hcp/hcp-tunnel-front
- macro: user_known_k8s_client_container_parens
condition: (user_known_k8s_client_container)
- rule: The docker client is executed in a container
desc: Detect a k8s client tool executed inside a container
condition: spawned_process and container and not user_known_k8s_client_container and proc.name in (k8s_client_binaries)
condition: spawned_process and container and not user_known_k8s_client_container_parens and proc.name in (k8s_client_binaries)
output: "Docker or kubernetes client executed in container (user=%user.name %container.info parent=%proc.pname cmdline=%proc.cmdline image=%container.image.repository:%container.image.tag)"
priority: WARNING
tags: [container, mitre_execution]

View File

@@ -40,8 +40,14 @@
# If you wish to restrict activity to a specific set of users, override/append to this list.
# users created by kops are included
- list: vertical_pod_autoscaler_users
items: ["vpa-recommender", "vpa-updater"]
- list: allowed_k8s_users
items: ["minikube", "minikube-user", "kubelet", "kops", "admin", "kube", "kube-proxy"]
items: [
"minikube", "minikube-user", "kubelet", "kops", "admin", "kube", "kube-proxy",
vertical_pod_autoscaler_users,
]
- rule: Disallowed K8s User
desc: Detect any k8s operation by users outside of an allowed set of users.

View File

@@ -64,8 +64,8 @@ do_start()
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
if [ ! -d /sys/module/falco_probe ]; then
/sbin/modprobe falco-probe || exit 1
if [ ! -d /sys/module/falco ]; then
/sbin/modprobe falco || exit 1
fi
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
@@ -96,7 +96,7 @@ do_stop()
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
/sbin/rmmod falco-probe
/sbin/rmmod falco
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"

View File

@@ -23,8 +23,7 @@
#
# Returns 1 if $cos_ver > $base_ver, 0 otherwise
#
cos_version_greater()
{
cos_version_greater() {
if [[ $cos_ver == "${base_ver}" ]]; then
return 0
fi
@@ -68,29 +67,29 @@ cos_version_greater()
get_kernel_config() {
if [ -f /proc/config.gz ]; then
echo "Found kernel config at /proc/config.gz"
echo "* Found kernel config at /proc/config.gz"
KERNEL_CONFIG_PATH=/proc/config.gz
elif [ -f "/boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at /boot/config-${KERNEL_RELEASE}"
echo "* Found kernel config at /boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH=/boot/config-${KERNEL_RELEASE}
elif [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at ${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
echo "* Found kernel config at ${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
elif [ -f "/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at /usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
echo "* Found kernel config at /usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
elif [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at ${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
echo "* Found kernel config at ${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
elif [ -f "/lib/modules/${KERNEL_RELEASE}/config" ]; then
# this code works both for native host and agent container assuming that
# Dockerfile sets up the desired symlink /lib/modules -> $HOST_ROOT/lib/modules
echo "Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
echo "* Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
KERNEL_CONFIG_PATH="/lib/modules/${KERNEL_RELEASE}/config"
fi
if [ -z "${KERNEL_CONFIG_PATH}" ]; then
echo "Cannot find kernel config"
>&2 echo "Cannot find kernel config"
exit 1
fi
@@ -131,7 +130,7 @@ get_target_id() {
if [[ $KERNEL_RELEASE == *"aws"* ]]; then
TARGET_ID="ubuntu-aws"
else
TARGET_ID="ubuntu"
TARGET_ID="ubuntu-generic"
fi
;;
(*)
@@ -140,6 +139,59 @@ get_target_id() {
esac
}
load_kernel_module_compile() {
# skip dkms on UEK hosts because it will always fail
if [[ $(uname -r) == *uek* ]]; then
echo "* Skipping dkms install for UEK host"
else
if hash dkms &>/dev/null; then
echo "* Trying to dkms install ${DRIVER_NAME} module"
if dkms install -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
echo "* ${DRIVER_NAME} module installed in dkms, trying to insmod"
if insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko" > /dev/null 2>&1; then
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms"
exit 0
elif insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko.xz" > /dev/null 2>&1; then
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms (xz)"
exit 0
else
echo "* Unable to insmod ${DRIVER_NAME} module"
fi
else
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
if [ -f "${DKMS_LOG}" ]; then
echo "* Running dkms build failed, dumping ${DKMS_LOG}"
cat "${DKMS_LOG}"
else
echo "* Running dkms build failed, couldn't find ${DKMS_LOG}"
fi
fi
else
echo "* Skipping dkms install (dkms not found)"
fi
fi
}
load_kernel_module_download() {
get_target_id
local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${FALCO_KERNEL_MODULE_FILENAME}" | sed s/+/%2B/g)
echo "* Trying to download prebuilt module from ${URL}"
if curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then
echo "* Download succeeded"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module loaded"
exit $?
else
>&2 echo "Download failed, consider compiling your own ${DRIVER_NAME} module and loading it or getting in touch with the Falco community"
exit 1
fi
}
load_kernel_module() {
if ! hash lsmod > /dev/null 2>&1; then
>&2 echo "This program requires lsmod"
@@ -177,67 +229,160 @@ load_kernel_module() {
exit 0
fi
# skip dkms on UEK hosts because it will always fail`
if [[ $(uname -r) == *uek* ]]; then
echo "* Skipping dkms install for UEK host"
else
if hash dkms &>/dev/null && dkms install -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
echo "* Trying to load a dkms ${DRIVER_NAME} module, if present"
if insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko" > /dev/null 2>&1; then
echo "${DRIVER_NAME} module found and loaded in dkms"
exit 0
elif insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko.xz" > /dev/null 2>&1; then
echo "${DRIVER_NAME} module found and loaded in dkms (xz)"
exit 0
else
echo "* Unable to insmod"
fi
else
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
if [ -f "${DKMS_LOG}" ]; then
echo "* Running dkms build failed, dumping ${DKMS_LOG}"
cat "${DKMS_LOG}"
else
echo "* Running dkms build failed, couldn't find ${DKMS_LOG}"
fi
fi
if [ -n "$ENABLE_COMPILE" ]; then
load_kernel_module_compile
fi
echo "* Trying to load a system ${DRIVER_NAME} driver, if present"
if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then
echo "${DRIVER_NAME} module found and loaded with modprobe"
echo "* Success: ${DRIVER_NAME} module found and loaded with modprobe"
exit 0
fi
fi
echo "* Trying to find a prebuilt ${DRIVER_NAME} module for kernel ${KERNEL_RELEASE}"
echo "* Trying to find locally a prebuilt ${DRIVER_NAME} module for kernel ${KERNEL_RELEASE}, if present"
get_target_id
local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"
if [ -f "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" ]; then
echo "Found a prebuilt module at ${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}, loading it"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}"
echo "* Found a prebuilt module at ${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}, loading it"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module loaded"
exit $?
fi
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${FALCO_KERNEL_MODULE_FILENAME}" | sed s/+/%2B/g)
if [ -n "$ENABLE_DOWNLOAD" ]; then
load_kernel_module_download
fi
}
echo "* Trying to download prebuilt module from ${URL}"
if curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then
echo "Download succeeded, loading module"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}"
exit $?
else
>&2 echo "Download failed, consider compiling your own ${DRIVER_NAME} module and loading it or getting in touch with the Falco community"
exit 1
load_bpf_probe_compile() {
local BPF_KERNEL_SOURCES_URL=""
local STRIP_COMPONENTS=1
customize_kernel_build() {
if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
sed -i "s/LOCALVERSION=\"\"/LOCALVERSION=\"${KERNEL_EXTRA_VERSION}\"/" .config
fi
make olddefconfig > /dev/null
make modules_prepare > /dev/null
}
if [ -n "${COS}" ]; then
echo "* COS detected (build ${BUILD_ID}), using cos kernel headers"
BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
KERNEL_EXTRA_VERSION="+"
STRIP_COMPONENTS=0
customize_kernel_build() {
pushd usr/src/* > /dev/null || exit
# Note: this overrides the KERNELDIR set while untarring the tarball
KERNELDIR=$(pwd)
export KERNELDIR
sed -i '/^#define randomized_struct_fields_start struct {$/d' include/linux/compiler-clang.h
sed -i '/^#define randomized_struct_fields_end };$/d' include/linux/compiler-clang.h
popd > /dev/null || exit
# Might need to configure our own sources depending on COS version
cos_ver=${BUILD_ID}
base_ver=11553.0.0
cos_version_greater
greater_ret=$?
if [[ greater_ret -eq 1 ]]; then
export KBUILD_EXTRA_CPPFLAGS=-DCOS_73_WORKAROUND
fi
}
fi
if [ -n "${MINIKUBE}" ]; then
echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
local kernel_version
kernel_version=$(uname -r)
local -r kernel_version_major=$(echo "${kernel_version}" | cut -d. -f1)
local -r kernel_version_minor=$(echo "${kernel_version}" | cut -d. -f2)
local -r kernel_version_patch=$(echo "${kernel_version}" | cut -d. -f3)
if [ "${kernel_version_patch}" == "0" ]; then
kernel_version="${kernel_version_major}.${kernel_version_minor}"
fi
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_USE_LOCAL_KERNEL_SOURCES}" ]; then
local -r kernel_version_major=$(uname -r | cut -d. -f1)
local -r kernel_version=$(uname -r | cut -d- -f1)
KERNEL_EXTRA_VERSION="-$(uname -r | cut -d- -f2)"
echo "* Using downloaded kernel sources for kernel version ${kernel_version}..."
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
echo "* Downloading ${BPF_KERNEL_SOURCES_URL}"
mkdir -p /tmp/kernel
cd /tmp/kernel || exit
cd "$(mktemp -d -p /tmp/kernel)" || exit
if ! curl -L -o kernel-sources.tgz --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" "${BPF_KERNEL_SOURCES_URL}"; then
>&2 echo "Download failed"
exit 1;
fi
echo "* Extracting kernel sources"
mkdir kernel-sources && tar xf kernel-sources.tgz -C kernel-sources --strip-components "${STRIP_COMPONENTS}"
cd kernel-sources || exit
KERNELDIR=$(pwd)
export KERNELDIR
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
zcat "${KERNEL_CONFIG_PATH}" > .config
else
cat "${KERNEL_CONFIG_PATH}" > .config
fi
echo "* Configuring kernel"
customize_kernel_build
fi
echo "* Trying to compile the eBPF probe (${BPF_PROBE_FILENAME})"
make -C "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf" > /dev/null
mkdir -p "${HOME}/.falco"
mv "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf/probe.o" "${HOME}/.falco/${BPF_PROBE_FILENAME}"
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
rm -r /tmp/kernel
fi
}
load_bpf_probe_download() {
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
echo "* Trying to download a prebuilt eBPF probe from ${URL}"
if ! curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${URL}"; then
>&2 echo "Download failed"
exit 1;
fi
}
load_bpf_probe() {
echo "* Mounting debugfs"
if [ ! -d /sys/kernel/debug/tracing ]; then
@@ -262,128 +407,27 @@ load_bpf_probe() {
get_target_id
local BPF_PROBE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o"
BPF_PROBE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o"
if [ ! -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
local BPF_KERNEL_SOURCES_URL=""
local STRIP_COMPONENTS=1
customize_kernel_build() {
if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
sed -i "s/LOCALVERSION=\"\"/LOCALVERSION=\"${KERNEL_EXTRA_VERSION}\"/" .config
fi
make olddefconfig > /dev/null
make modules_prepare > /dev/null
}
if [ -n "${COS}" ]; then
echo "* COS detected (build ${BUILD_ID}), using cos kernel headers..."
BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
KERNEL_EXTRA_VERSION="+"
STRIP_COMPONENTS=0
customize_kernel_build() {
pushd usr/src/* > /dev/null || exit
# Note: this overrides the KERNELDIR set while untarring the tarball
KERNELDIR=$(pwd)
export KERNELDIR
sed -i '/^#define randomized_struct_fields_start struct {$/d' include/linux/compiler-clang.h
sed -i '/^#define randomized_struct_fields_end };$/d' include/linux/compiler-clang.h
popd > /dev/null || exit
# Might need to configure our own sources depending on COS version
cos_ver=${BUILD_ID}
base_ver=11553.0.0
cos_version_greater
greater_ret=$?
if [[ greater_ret -eq 1 ]]; then
export KBUILD_EXTRA_CPPFLAGS=-DCOS_73_WORKAROUND
fi
}
fi
if [ -n "${MINIKUBE}" ]; then
echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
local kernel_version
kernel_version=$(uname -r)
local -r kernel_version_major=$(echo "${kernel_version}" | cut -d. -f1)
local -r kernel_version_minor=$(echo "${kernel_version}" | cut -d. -f2)
local -r kernel_version_patch=$(echo "${kernel_version}" | cut -d. -f3)
if [ "${kernel_version_patch}" == "0" ]; then
kernel_version="${kernel_version_major}.${kernel_version_minor}"
fi
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_USE_LOCAL_KERNEL_SOURCES}" ]; then
local -r kernel_version_major=$(uname -r | cut -d. -f1)
local -r kernel_version=$(uname -r | cut -d- -f1)
KERNEL_EXTRA_VERSION="-$(uname -r | cut -d- -f2)"
echo "* Using downloaded kernel sources for kernel version ${kernel_version}..."
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
echo "* Downloading ${BPF_KERNEL_SOURCES_URL}"
mkdir -p /tmp/kernel
cd /tmp/kernel || exit
cd "$(mktemp -d -p /tmp/kernel)" || exit
if ! curl -L -o kernel-sources.tgz --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" "${BPF_KERNEL_SOURCES_URL}"; then
exit 1;
fi
echo "* Extracting kernel sources"
mkdir kernel-sources && tar xf kernel-sources.tgz -C kernel-sources --strip-components "${STRIP_COMPONENTS}"
cd kernel-sources || exit
KERNELDIR=$(pwd)
export KERNELDIR
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
zcat "${KERNEL_CONFIG_PATH}" > .config
else
cat "${KERNEL_CONFIG_PATH}" > .config
fi
echo "* Configuring kernel"
customize_kernel_build
fi
echo "* Trying to compile the eBPF probe (${BPF_PROBE_FILENAME})"
make -C "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf" > /dev/null
mkdir -p "${HOME}/.falco"
mv "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf/probe.o" "${HOME}/.falco/${BPF_PROBE_FILENAME}"
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
rm -r /tmp/kernel
if [ -n "$ENABLE_COMPILE" ]; then
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* Skipping compile, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
else
load_bpf_probe_compile
fi
fi
if [ ! -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
echo "* Trying to download a prebuilt eBPF probe from ${URL}"
curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${URL}"
if [ -n "$ENABLE_DOWNLOAD" ]; then
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* Skipping download, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
else
load_bpf_probe_download
fi
fi
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* eBPF probe located in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
if [ ! -f /proc/sys/net/core/bpf_jit_enable ]; then
echo "******************************************************************"
echo "** BPF doesn't have JIT enabled, performance might be degraded. **"
@@ -391,20 +435,37 @@ load_bpf_probe() {
echo "******************************************************************"
fi
echo "* eBPF probe located, it's now possible to start Falco"
ln -sf "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${HOME}/.falco/${DRIVER_NAME}-bpf.o"
ln -sf "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${HOME}/.falco/${DRIVER_NAME}-bpf.o" \
&& echo "* Success: eBPF probe symlinked to ${HOME}/.falco/${DRIVER_NAME}-bpf.o"
exit $?
else
echo "* Failure to find an eBPF probe"
>&2 echo "Failure to find an eBPF probe"
exit 1
fi
}
print_usage() {
echo ""
echo "Usage:"
echo " falco-driver-loader [driver] [options]"
echo ""
echo "Available drivers:"
echo " module kernel module (default)"
echo " bpf eBPF probe"
echo ""
echo "Options:"
echo " --help show brief help"
echo " --compile try to compile the driver locally"
echo " --download try to download a prebuilt driver"
echo " --source-only skip execution and allow sourcing in another script"
echo ""
}
ARCH=$(uname -m)
KERNEL_RELEASE=$(uname -r)
KERNEL_VERSION=$(uname -v | sed 's/#\([[:digit:]]\+\).*/\1/')
DRIVERS_REPO=${DRIVERS_REPO:-"@DRIVERS_REPO@"}
if [ -n "$DRIVER_INSECURE_DOWNLOAD" ]
then
FALCO_DRIVER_CURL_OPTIONS=-fsSk
@@ -420,18 +481,84 @@ fi
DRIVER_VERSION="@PROBE_VERSION@"
DRIVER_NAME="@PROBE_NAME@"
if [ "$(id -u)" != 0 ]; then
echo "Installer must be run as root (or with sudo)."
exit 1
DRIVER="module"
if [ -v FALCO_BPF_PROBE ]; then
DRIVER="bpf"
fi
if ! hash curl > /dev/null 2>&1; then
echo "This program requires curl"
exit 1
ENABLE_COMPILE=
ENABLE_DOWNLOAD=
has_args=
has_opts=
source_only=
while test $# -gt 0; do
case "$1" in
module|bpf)
if [ -n "$has_args" ]; then
>&2 echo "Only one driver can be passed"
print_usage
exit 1
else
DRIVER="$1"
has_args="true"
shift
fi
;;
-h|--help)
print_usage
exit 0
;;
--compile)
ENABLE_COMPILE="yes"
has_opts="true"
shift
;;
--download)
ENABLE_DOWNLOAD="yes"
has_opts="true"
shift
;;
--source-only)
source_only="true"
shift
;;
--*)
>&2 echo "Unknown option: $1"
print_usage
exit 1
;;
*)
>&2 echo "Unknown driver: $1"
print_usage
exit 1
;;
esac
done
if [ -z "$has_opts" ]; then
ENABLE_COMPILE="yes"
ENABLE_DOWNLOAD="yes"
fi
if [ -v FALCO_BPF_PROBE ] || [ "${1}" = "bpf" ]; then
load_bpf_probe
else
load_kernel_module
fi
if [ -z "$source_only" ]; then
if [ "$(id -u)" != 0 ]; then
>&2 echo "This program must be run as root (or with sudo)"
exit 1
fi
if ! hash curl > /dev/null 2>&1; then
>&2 echo "This program requires curl"
exit 1
fi
echo "* Running falco-driver-loader with: driver=$DRIVER, compile=${ENABLE_COMPILE:-"no"}, download=${ENABLE_DOWNLOAD:-"no"}"
case $DRIVER in
module)
load_kernel_module
;;
bpf)
load_bpf_probe
;;
esac
fi

View File

@@ -53,8 +53,8 @@ start() {
# [ -f $config ] || exit 6
echo -n $"Starting $prog: "
daemon $exec --daemon --pidfile=$pidfile
if [ ! -d /sys/module/falco_probe ]; then
/sbin/modprobe falco-probe || return $?
if [ ! -d /sys/module/falco ]; then
/sbin/modprobe falco || return $?
fi
retval=$?
echo
@@ -67,7 +67,7 @@ stop() {
killproc -p $pidfile
retval=$?
echo
/sbin/rmmod falco-probe
/sbin/rmmod falco
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}

View File

@@ -1,6 +1,39 @@
# Falco Regression tests
# Falco regression tests
This folder contains the Regression tests suite for Falco.
You can find instructions on how to run this test suite on the Falco website [here](https://falco.org/docs/source/#run-regression-tests).
## Test suites
- [falco_tests](./falco_tests.yaml)
- [falco_traces](./falco_traces.yaml)
- [falco_tests_package](./falco_tests_package.yaml)
- [falco_k8s_audit_tests](./falco_k8s_audit_tests.yaml)
- [falco_tests_psp](./falco_tests_psp.yaml)
## Running locally
Using `virtualenv` the steps to locally run a specific test suite are the following ones (from this directory):
```console
virtualenv venv
source venv/bin/activate
pip install -r requirements.txt
BUILD_DIR="../build" avocado run --mux-yaml falco_tests.yaml --job-results-dir /tmp/job-results -- falco_test.py
deactivate
```
The name of the specific test suite to run is `falco_tests.yaml` in this case. Change it to run others test suites.
In case you want to only execute a specific test case, use the `--mux-filter-only` parameter as follows:
```console
BUILD_DIR="../build" avocado run --mux-yaml falco_tests.yaml --job-results-dir /tmp/job-results --mux-filter-only /run/trace_files/program_output -- falco_test.py
```
To obtain the path of all the available variants, execute:
```console
avocado variants --mux-yaml falco_test.yaml
```

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,14 +21,14 @@ rules_file: /etc/falco_rules.yaml
# Whether to output events in json or text
json_output: false
# Send information logs to stderr and/or syslog Note these are *not* security
# notification logs! These are just Falco lifecycle (and possibly error) logs.
# Send information logs to stderr and/or syslog
# Note these are *not* security notification logs!
# These are just Falco lifecycle (and possibly error) logs.
log_stderr: false
log_syslog: false
# Where security notifications should go.
# Multiple outputs can be enabled.
syslog_output:
enabled: false

48
test/driver-loader/run_test.sh Executable file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
#
# 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 -euo pipefail
BUILD_DIR=$1
SCRIPT=$(readlink -f $0)
SCRIPTDIR=$(dirname $SCRIPT)
RUNNERDIR="${SCRIPTDIR}/runner"
FALCO_VERSION=$(cat ${BUILD_DIR}/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
DRIVER_VERSION=$(cat ${BUILD_DIR}/userspace/falco/config_falco.h | grep 'DRIVER_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
FALCO_PACKAGE="falco-${FALCO_VERSION}-x86_64.tar.gz"
cp "${BUILD_DIR}/${FALCO_PACKAGE}" "${RUNNERDIR}"
pushd ${RUNNERDIR}
docker build --build-arg FALCO_VERSION="$FALCO_VERSION" \
-t falcosecurity/falco:test-driver-loader \
-f "${RUNNERDIR}/Dockerfile" ${RUNNERDIR}
popd
rm -f "${RUNNERDIR}/${FALCO_PACKAGE}"
docker run --rm --privileged \
-e FALCO_VERSION="$FALCO_VERSION" \
-e DRIVER_VERSION="$DRIVER_VERSION" \
-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:ro \
falcosecurity/falco:test-driver-loader
docker rmi -f falcosecurity/falco:test-driver-loader

View File

@@ -0,0 +1,33 @@
FROM ubuntu:18.04
ARG FALCO_VERSION=
RUN test -n FALCO_VERSION
ENV FALCO_VERSION ${FALCO_VERSION}
ENV DRIVER_VERSION=
ENV HOST_ROOT=/host
# Minimal set of deps required to run falco-driver-loader and falco
RUN apt-get update -y
RUN apt-get install -y --no-install-recommends \
ca-certificates \
libyaml-0-2 \
dkms \
curl \
gcc \
clang-7 \
llvm-7 \
libelf-dev
RUN rm -rf /usr/bin/clang \
&& rm -rf /usr/bin/llc \
&& ln -s /usr/bin/clang-7 /usr/bin/clang \
&& ln -s /usr/bin/llc-7 /usr/bin/llc
RUN rm -rf /lib/modules \
&& ln -s $HOST_ROOT/lib/modules /lib/modules
ADD falco-${FALCO_VERSION}-x86_64.tar.gz /
RUN cp -R /falco-${FALCO_VERSION}-x86_64/* /
COPY test.sh /
CMD /test.sh

136
test/driver-loader/runner/test.sh Executable file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env bash
#
# 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 -euo pipefail
FALCO="falco -M 1"
FALCO_DRIVER_LOADER=falco-driver-loader
function init() {
# We need this here since is not part of the falco-driver-loader script
#
# todo(leogr): maybe this can be moved into falco-driver-loader directly
# since it depends on HOST_ROOT
if [ -n "${HOST_ROOT}" ]; then
echo "INIT: Setting up /usr/src links from host"
for i in "$HOST_ROOT/usr/src"/*
do
base=$(basename "$i")
ln -s "$i" "/usr/src/$base"
done
fi
local EXPECTED_DRIVER_VERSION=${DRIVER_VERSION}
# We need some env vars to be populated
# Just source falco-driver-loader, and call get_target_id
# Loaded driver will be cleaned up later, if any.
echo "INIT: Sourcing ${FALCO_DRIVER_LOADER} to get env vars populated"
set +eu
source $FALCO_DRIVER_LOADER --source-only
get_target_id
set -eu
if [ ! "${EXPECTED_DRIVER_VERSION}" = "${DRIVER_VERSION}" ]; then
echo "INIT: Unexpected DRIVER_VERSION in falco-driver-loader"
echo "Expected: ${EXPECTED_DRIVER_VERSION}"
echo "Found: ${DRIVER_VERSION}"
exit 1
fi
FALCO_KERNEL_MODULE_PATH="${HOME}/.falco/${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"
FALCO_BPF_PROBE_PATH="${HOME}/.falco/${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o"
cleanup_drivers
}
function cleanup_drivers() {
echo "CLEANUP: remove drivers, if any"
# kernel module
rmmod "$DRIVER_NAME" > /dev/null 2>&1 || true
dkms uninstall "$DRIVER_NAME/$DRIVER_VERSION" > /dev/null 2>&1 || true
rm -f "$FALCO_KERNEL_MODULE_PATH"
# bpf probe
local PROBE_INSTALL_PATH="${HOME}/.falco/${DRIVER_NAME}-bpf.o"
rm -f "$FALCO_BPF_PROBE_PATH"
rm -f "$PROBE_INSTALL_PATH"
}
function run_test() {
echo ""
echo "TEST: $1"
echo ""
$1
echo ""
echo "PASS: $1"
echo ""
cleanup_drivers
}
function assert_kernel_module() {
echo "ASSERT: module loaded"
local KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
if ! lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
echo "FAIL: module not loaded"
exit 1
fi
echo "ASSERT: falco works with module"
if ! $FALCO; then
echo "FAIL: falco does not work with module"
exit 1
fi
}
function assert_bpf_probe() {
local PROBE_INSTALL_PATH="${HOME}/.falco/${DRIVER_NAME}-bpf.o"
echo "ASSERT: eBPF probe at $PROBE_INSTALL_PATH"
if ! test -f "$PROBE_INSTALL_PATH"; then
echo "FAIL: eBPF probe not found"
exit 1
fi
echo "ASSERT: falco works with bpf"
if ! FALCO_BPF_PROBE="" $FALCO; then
echo "FAIL: falco does not work with bpf"
exit 1
fi
}
function test_kernel_module() {
$FALCO_DRIVER_LOADER
assert_kernel_module
}
function test_bpf_probe() {
$FALCO_DRIVER_LOADER bpf
assert_bpf_probe
}
echo "falco-driver-loader tester"
echo ""
echo "Falco version: $FALCO_VERSION"
echo "Driver version: $DRIVER_VERSION"
echo "HOST_ROOT: ${HOST_ROOT}"
echo ""
init
run_test "test_kernel_module"
run_test "test_bpf_probe"

View File

@@ -411,8 +411,8 @@ class FalcoTest(Test):
md5_output = subprocess.check_output(["md5sum", "/boot/config-{}".format(kernel_release)]).rstrip()
config_hash = md5_output.split(" ")[0]
probe_filename = "falco-probe-{}-{}-{}-{}.ko".format(falco_version, arch, kernel_release, config_hash)
driver_path = os.path.join(self.falcodir, "driver", "falco-probe.ko")
probe_filename = "falco-{}-{}-{}-{}.ko".format(falco_version, arch, kernel_release, config_hash)
driver_path = os.path.join(self.falcodir, "driver", "falco.ko")
module_path = os.path.join(self.module_dir, probe_filename)
self.log.debug("Copying {} to {}".format(driver_path, module_path))
shutil.copyfile(driver_path, module_path)

11
test/requirements.txt Normal file
View File

@@ -0,0 +1,11 @@
avocado-framework==69.0
avocado-framework-plugin-varianter-yaml-to-mux==69.0
certifi==2020.4.5.1
chardet==3.0.4
idna==2.9
pbr==5.4.5
PyYAML==5.3.1
requests==2.23.0
six==1.14.0
stevedore==1.32.0
urllib3==1.25.9

View File

@@ -14,9 +14,9 @@
# License for the specific language governing permissions and limitations under
# the License.
#
set(FALCO_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp falco/test_webserver.cpp engine/test_rulesets.cpp profiler/test_profiler.cpp)
set(FALCO_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp engine/test_rulesets.cpp engine/test_falco_utils.cpp falco/test_webserver.cpp)
set(FALCO_TESTED_LIBRARIES falco_engine falco_profiler)
set(FALCO_TESTED_LIBRARIES falco_engine)
SET(FALCO_TESTS_ARGUMENTS "" CACHE STRING "Test arguments to pass to the Falco test suite")
@@ -43,12 +43,12 @@ if(FALCO_BUILD_TESTS)
"${YAMLCPP_INCLUDE_DIR}"
"${CIVETWEB_INCLUDE_DIR}"
"${PROJECT_SOURCE_DIR}/userspace/falco")
add_dependencies(falco_test catch2 hedley)
add_dependencies(falco_test catch2)
include(CMakeParseArguments)
include(CTest)
include(Catch)
catch_discover_tests(falco_test)
separate_arguments(FALCO_TESTS_ARGUMENTS)
add_custom_target(tests COMMAND ${CMAKE_CTEST_COMMAND} ${FALCO_TESTS_ARGUMENTS} DEPENDS falco_test flatbuffer_profiler)
add_custom_target(tests COMMAND ${CMAKE_CTEST_COMMAND} ${FALCO_TESTS_ARGUMENTS} DEPENDS falco_test)
endif()

View File

@@ -0,0 +1,53 @@
/*
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 "falco_utils.h"
#include <nonstd/string_view.hpp>
#include <catch.hpp>
TEST_CASE("is_unix_scheme matches", "[utils]")
{
SECTION("rvalue")
{
bool res = falco::utils::network::is_unix_scheme("unix:///var/run/falco.sock");
REQUIRE(res);
}
SECTION("std::string")
{
std::string url("unix:///var/run/falco.sock");
bool res = falco::utils::network::is_unix_scheme(url);
REQUIRE(res);
}
SECTION("char[]")
{
char url[] = "unix:///var/run/falco.sock";
bool res = falco::utils::network::is_unix_scheme(url);
REQUIRE(res);
}
}
TEST_CASE("is_unix_scheme does not match", "[utils]")
{
bool res = falco::utils::network::is_unix_scheme("something:///var/run/falco.sock");
REQUIRE_FALSE(res);
}
TEST_CASE("is_unix_scheme only matches scheme at the start of the string", "[utils]")
{
bool res = falco::utils::network::is_unix_scheme("/var/run/unix:///falco.sock");
REQUIRE_FALSE(res);
}

View File

@@ -1,353 +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 "profiler.h"
#include <catch.hpp>
#include <thread>
#include <chrono>
#include <algorithm>
#include <hedley.h>
#include <cstdlib>
#include <iostream>
#include <thread>
#include <flatbuffers/flatbuffers.h>
#include "profile_generated.h"
// void profile_recurse(int times)
// {
// PROFILEME();
// for(int i = 1; i < times; i++)
// {
// profile_recurse(1);
// }
// }
void profiler_sleep_1sec()
{
PROFILEME();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void profiler_sleep_2sec()
{
PROFILEME();
profiler_sleep_1sec();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
TEST_CASE("profiler stores labels and chunks", "[profiler]")
{
SECTION("profiler needs to be allocated before usage")
{
profiler::alloc_chunk();
REQUIRE(profiler::chunks.size() == 1);
REQUIRE(profiler::labels.empty());
}
SECTION("calling a profiled function results in labels and chunks increase")
{
profiler_sleep_1sec();
REQUIRE(profiler::labels.size() == 1);
REQUIRE(profiler::chunks.size() == 1);
}
SECTION("calling just another profiled function that calls the one previously called should only increase labels by one")
{
profiler_sleep_2sec();
REQUIRE(profiler::labels.size() == 2);
REQUIRE(profiler::chunks.size() == 1);
}
SECTION("clean")
{
profiler::labels.clear();
profiler::chunks.clear();
REQUIRE(profiler::labels.empty());
REQUIRE(profiler::chunks.empty());
}
}
void bb()
{
PROFILEME();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void aa()
{
PROFILEME();
bb();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void aa_threaded()
{
profiler::alloc_chunk();
PROFILEME();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void cc()
{
PROFILEME();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void profiler_fake_root_func()
{
PROFILEME();
aa();
std::this_thread::sleep_for(std::chrono::microseconds(1));
bb();
std::this_thread::sleep_for(std::chrono::microseconds(1));
cc();
std::this_thread::sleep_for(std::chrono::microseconds(1));
aa();
}
TEST_CASE("profiler computes parents (single chunk)", "[profiler]")
{
profiler::alloc_chunk();
profiler_fake_root_func();
REQUIRE(profiler::labels.size() == 4);
REQUIRE(profiler::chunks.size() == 1);
REQUIRE(profiler::chunks[0].begin[5] == 0); // profiler_fake_root_func is root (parent = 0)
auto predicate = [](int x) {
return [=](const profiler::label &l) {
return l.label == profiler::chunks[0].begin[x];
};
};
// Ctor ordering:
// profile_fake_root
// AA1
// BB1
// BB2
// CC1
// AA2
// BB3
// Dtor ordering:
// BB1
// AA1
// BB2
// CC1
// BB3
// AA2
// profile_fake_root
auto root = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(0));
REQUIRE(root->func == "profiler_fake_root_func"); // function name is "profiler_fake_root_func"
REQUIRE(profiler::chunks[0].begin[5 + CHUNK_ELEMENTS] == root->label); // aa (call aa1) has parent "profiler_fake_root_func"
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(CHUNK_ELEMENTS));
REQUIRE(it->func == "aa"); // function name is "aa" (call aa1)
REQUIRE(profiler::chunks[0].begin[5 + (2 * CHUNK_ELEMENTS)] == it->label); // bb (call bb1) has parent "aa" (call aa1)
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(2 * CHUNK_ELEMENTS));
REQUIRE(it->func == "bb"); // function name is "bb" (call bb1)
REQUIRE(profiler::chunks[0].begin[5 + (3 * CHUNK_ELEMENTS)] == root->label); // bb (call bb2) has parent "profiler_fake_root_func"
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(3 * CHUNK_ELEMENTS));
REQUIRE(it->func == "bb"); // function name is "bb" (call bb2)
REQUIRE(profiler::chunks[0].begin[5 + (4 * CHUNK_ELEMENTS)] == root->label); // cc (call cc1) has parent "profiler_fake_root_func"
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(4 * CHUNK_ELEMENTS));
REQUIRE(it->func == "cc"); // function name is "cc" (call cc1)
REQUIRE(profiler::chunks[0].begin[5 + (5 * CHUNK_ELEMENTS)] == root->label); // aa (call aa2) has parent "profiler_fake_root_func"
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(5 * CHUNK_ELEMENTS));
REQUIRE(it->func == "aa"); // function name is "aa" (call aa2)
REQUIRE(profiler::chunks[0].begin[5 + (6 * CHUNK_ELEMENTS)] == it->label); // bb (call bb3) has parent "aa" (call aa2)
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(6 * CHUNK_ELEMENTS));
REQUIRE(it->func == "bb"); // function name is "bb" (call bb3)
}
for(std::vector<int>::size_type j = 0; j != profiler::chunks.size(); j++)
{
auto *c = profiler::chunks[j].begin;
for(int i = 0; i < CHUNK_SIZE; i += CHUNK_ELEMENTS)
{
if(c[i] == 0)
{
break;
}
auto parent = c[i + 5];
auto e = ((unsigned long long)c[i + 4]) | (((unsigned long long)c[i + 3]) << 32);
auto s = ((unsigned long long)c[i + 2]) | (((unsigned long long)c[i + 1]) << 32);
char b[1024];
if(i == 0)
{
sprintf(b, "#;idx;parent ;function ;clocks");
std::cout << std::string(b) << std::endl;
}
sprintf(b, "%ld;%03d;%010u;%u;%lld", j, i, parent, c[i], e - s);
std::cout << std::string(b) << std::endl;
}
}
profiler::labels.clear();
profiler::chunks.clear();
REQUIRE(profiler::labels.empty());
REQUIRE(profiler::chunks.empty());
}
// TEST_CASE("profile computes recursive parents (more chunks)", "[profiler]")
// {
// alloc_chunk();
// REQUIRE(chunks.size() == 1);
// size_t expected_chunks = 2;
// int how_many_times = (CHUNK_SIZE / CHUNK_ELEMENTS) * HEDLEY_STATIC_CAST(int, expected_chunks);
// profile_recurse(how_many_times);
// REQUIRE(labels.size() == 1);
// REQUIRE(chunks.size() == expected_chunks + 1);
// for(std::vector<int>::size_type j = 0; j != chunks.size(); j++)
// {
// auto *c = chunks[j].begin;
// for(int i = 0; i < CHUNK_SIZE; i++)
// {
// char b[1024];
// sprintf(b, "%ld - %03d: %u", j, i, c[i]);
// std::cout << std::string(b) << std::endl;
// }
// }
// labels.clear();
// chunks.clear();
// REQUIRE(labels.empty());
// REQUIRE(chunks.empty());
// }
TEST_CASE("profiler flatbuffer serialization deserialization", "[profiler]")
{
flatbuffers::FlatBufferBuilder builder;
auto node_one = profiler::CreateNodeDirect(
builder,
"do_init",
"falco_engine.cpp",
345,
500);
auto node_two_one = profiler::CreateNodeDirect(
builder,
"do_match2",
"ruleset.cpp",
690,
100);
std::vector<flatbuffers::Offset<profiler::Node>> third_level;
third_level.push_back(node_two_one);
auto node_two = profiler::CreateNodeDirect(
builder,
"do_match",
"ruleset.cpp",
678,
250,
&third_level);
std::vector<flatbuffers::Offset<profiler::Node>> second_level;
second_level.push_back(node_one);
second_level.push_back(node_two);
auto root = profiler::CreateNodeDirect(
builder,
"main",
"falco.cpp",
123,
750,
&second_level);
profiler::FinishNodeBuffer(builder, root);
SECTION("binary output has identifier")
{
REQUIRE(profiler::NodeBufferHasIdentifier(builder.GetBufferPointer()) == true);
}
SECTION("deserialization")
{
auto node = profiler::GetNode(builder.GetBufferPointer());
REQUIRE(node->cycles() == 750);
REQUIRE(node->line() == 123);
REQUIRE(node->func()->str() == "main");
REQUIRE(node->file()->str() == "falco.cpp");
REQUIRE(node->childs() != nullptr);
REQUIRE(node->childs()->size() == 2);
REQUIRE(node->childs()->Get(0) == flatbuffers::GetTemporaryPointer(builder, node_one));
REQUIRE(node->childs()->Get(1) == flatbuffers::GetTemporaryPointer(builder, node_two));
auto expect_one = node->childs()->Get(0);
REQUIRE(expect_one->cycles() == 500);
REQUIRE(expect_one->line() == 345);
REQUIRE(expect_one->func()->str() == "do_init");
REQUIRE(expect_one->file()->str() == "falco_engine.cpp");
REQUIRE(expect_one->childs() == nullptr);
auto expect_two = node->childs()->Get(1);
REQUIRE(expect_two->cycles() == 250);
REQUIRE(expect_two->line() == 678);
REQUIRE(expect_two->func()->str() == "do_match");
REQUIRE(expect_two->file()->str() == "ruleset.cpp");
REQUIRE(expect_two->childs() != nullptr);
REQUIRE(expect_two->childs()->size() == 1);
REQUIRE(expect_two->childs()->Get(0) == flatbuffers::GetTemporaryPointer(builder, node_two_one));
auto expect_two_one = expect_two->childs()->Get(0);
REQUIRE(expect_two_one->cycles() == 100);
REQUIRE(expect_two_one->line() == 690);
REQUIRE(expect_two_one->func()->str() == "do_match2");
REQUIRE(expect_two_one->file()->str() == "ruleset.cpp");
REQUIRE(expect_two_one->childs() == nullptr);
}
}
void profile_fake_root_launching_threads()
{
PROFILEME();
std::thread ta(aa_threaded);
std::this_thread::sleep_for(std::chrono::microseconds(1));
bb();
ta.join();
}
TEST_CASE("profiler multi threading", "[profiler]")
{
profiler::alloc_chunk();
REQUIRE(profiler::chunks.size() == 1);
profile_fake_root_launching_threads();
}

22
userspace/README.md Normal file
View File

@@ -0,0 +1,22 @@
# Userspace
Here is where the main Falco engine lives.
There are two libraries here that are roughly seperated in the following way.are
### falco
This is the beloved `main()` function of the Falco program, as well as the logic for various falco outputs.
An output is just a way of delivering a Falco alert, the most simple output is the Falco stdout log.
### engine
This is the processing engine that connect the inbound stream of systemcalls to the rules engine.
This is the main powerhouse behind Falco, and does the assertion at runtime that compares system call events to rules.are
### CMake
If you are adding new files to either library you must define the `.cpp` file in the associated CMakeLists.txt file such that the linker will know where to find your new file.

View File

@@ -16,12 +16,13 @@ set(FALCO_ENGINE_SOURCE_FILES
falco_engine.cpp
falco_utils.cpp
json_evt.cpp
prettyprint.cpp
ruleset.cpp
token_bucket.cpp
formats.cpp)
add_library(falco_engine STATIC ${FALCO_ENGINE_SOURCE_FILES})
add_dependencies(falco_engine njson lyaml lpeg)
add_dependencies(falco_engine njson lyaml lpeg string-view-lite)
target_include_directories(
falco_engine
@@ -30,6 +31,7 @@ target_include_directories(
"${NJSON_INCLUDE}"
"${CURL_INCLUDE_DIR}"
"${TBB_INCLUDE_DIR}"
"${STRING_VIEW_LITE_INCLUDE}"
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"

View File

@@ -22,6 +22,7 @@ limitations under the License.
#include "falco_engine.h"
#include "falco_utils.h"
#include "falco_engine_version.h"
#include "prettyprint.h"
#include "config_falco_engine.h"
#include "formats.h"
@@ -316,6 +317,9 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
string err = "Error invoking function output: " + string(lerr);
throw falco_exception(err);
}
prettyprint::sinsp_event(ev, "Raw event just before popping to Lua");
res->evt = ev;
const char *p = lua_tostring(m_ls, -3);
res->rule = p;

View File

@@ -16,6 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstring>
#include "falco_utils.h"
#include "banned.h" // This raises a compilation error when certain functions are used
@@ -26,7 +27,7 @@ namespace falco
namespace utils
{
std::string wrap_text(const std::string &str, uint32_t initial_pos, uint32_t indent, uint32_t line_len)
std::string wrap_text(const std::string& str, uint32_t initial_pos, uint32_t indent, uint32_t line_len)
{
std::string ret;
@@ -51,6 +52,28 @@ std::string wrap_text(const std::string &str, uint32_t initial_pos, uint32_t ind
return ret;
}
} // namespace utils
void readfile(const std::string& filename, std::string& data)
{
std::ifstream file(filename.c_str(), std::ios::in);
if(file.is_open())
{
std::stringstream ss;
ss << file.rdbuf();
file.close();
data = ss.str();
}
return;
}
namespace network
{
bool is_unix_scheme(nonstd::string_view url)
{
return url.starts_with(UNIX_SCHEME);
}
} // namespace network
} // namespace utils
} // namespace falco

View File

@@ -17,7 +17,11 @@ limitations under the License.
*/
#include <sstream>
#include <fstream>
#include <iostream>
#include <string>
#include <nonstd/string_view.hpp>
#pragma once
@@ -27,8 +31,13 @@ namespace falco
namespace utils
{
std::string wrap_text(const std::string &str, uint32_t initial_pos, uint32_t indent, uint32_t line_len);
std::string wrap_text(const std::string& str, uint32_t initial_pos, uint32_t indent, uint32_t line_len);
void readfile(const std::string& filename, std::string& data);
namespace network
{
static const std::string UNIX_SCHEME("unix://");
bool is_unix_scheme(nonstd::string_view url);
} // namespace network
} // namespace utils
} // namespace falco

View File

@@ -0,0 +1,82 @@
/*
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
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 "prettyprint.h"
/**
* sinsp_event will pretty print a pointer to a sinsp_evt.
*
* This can be used for debugging an event at various times during development.
* This should never be turned on in production. Feel free to add fields below
* as we need them, and we can just dump an event in here whenever we need while
* debugging.
*
* sinsp_events are blue because they are happy.
*/
void prettyprint::sinsp_event(sinsp_evt *ev, const char* note)
{
ev->get_type()
prettyprint::warning();
printf("\033[0;34m"); // Start Blue
printf("\n*************************************************************\n");
printf("[Sinsp Event: %s]\n\n", note);
printf("name: %s\n", ev->get_name());
for(uint32_t i = 0; i <= ev->get_num_params(); i++){
}
for(int64_t j = 0; j <= ev->get_fd_num(); j++) {
printf("%s: %s\n", ev->get_param_name(j), ev->get_param_value_str(j, true).c_str());
};
// One off fields
//printf("fdinfo: %s\n", ev->get_fd_info()->tostring_clean().c_str());
//printf("type: %d\n", ev->get_type());
/*
printf("k8s.ns.name: %s\n", ev->get_param_value_str("k8s.ns.name", true).c_str());
printf("k8s %s\n", ev->get_param_value_str("k8s", true).c_str());
printf("container: %s\n", ev->get_param_value_str("container", true).c_str());
printf("proc.pid: %s\n", ev->get_param_value_str("%proc.pid", true).c_str());
printf("proc: %s\n", ev->get_param_value_str("%proc", true).c_str());
printf("data: %s\n", ev->get_param_value_str("data", true).c_str());
printf("cpu: %s\n", ev->get_param_value_str("cpu", true).c_str());
printf("fd: %s\n", ev->get_param_value_str("fd", true).c_str());
printf("fd: %s\n", ev->get_param_value_str("evt.arg.fd", true).c_str());
printf("user: %s\n", ev->get_param_value_str("user", true).c_str());
*/
printf("*************************************************************\n");
printf("\033[0m");
}
/**
* has_alerted controls our one time preliminary alert for using pretty print which is debug only
*/
bool prettyprint::has_alerted = false;
/**
* Warnings are red
*/
void prettyprint::warning() {
if (!prettyprint::has_alerted) {
printf("\033[0;31m"); // Start Red
printf("\n\n");
printf("*************************************************************\n");
printf(" [Pretty Printing Debugging is Enabled] \n");
printf(" This should never be used in production, by anyone, ever. \n");
printf("*************************************************************\n");
printf("\033[0m");
prettyprint::has_alerted = true;
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2019 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.
@@ -14,17 +14,29 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <sstream>
#include <fstream>
#include <iostream>
#include <string>
#include <set>
#include <vector>
#include <list>
#include <map>
namespace falco
{
namespace utils
{
void read(const std::string& filename, std::string& data);
} // namespace utils
} // namespace falco
#include "sinsp.h"
#include "filter.h"
#include "event.h"
#include "gen_filter.h"
#ifndef FALCO_FALCO_USERSPACE_PRETTYPRINT_H_
#define FALCO_FALCO_USERSPACE_PRETTYPRINT_H_
class prettyprint {
public:
static void sinsp_event(sinsp_evt *ev, const char* note = "");
private:
static bool has_alerted;
static void warning();
};
#endif //FALCO_FALCO_USERSPACE_PRETTYPRINT_H_

View File

@@ -52,14 +52,13 @@ add_executable(
grpc_server_impl.cpp
grpc_request_context.cpp
grpc_server.cpp
utils.cpp
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/output.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc)
add_dependencies(falco civetweb)
add_dependencies(falco civetweb string-view-lite)
if(USE_BUNDLED_DEPS)
add_dependencies(falco yamlcpp)
@@ -69,11 +68,10 @@ target_include_directories(
falco
PUBLIC
"${SYSDIG_SOURCE_DIR}/userspace/sysdig"
"${HEDLEY_INCLUDE}"
"${PROJECT_SOURCE_DIR}/userspace/profiler"
"${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}"
"${GRPC_INCLUDE}"
@@ -86,7 +84,6 @@ target_link_libraries(
falco
falco_engine
sinsp
falco_profiler
"${GPR_LIB}"
"${GRPC_LIB}"
"${GRPCPP_LIB}"

View File

@@ -151,7 +151,7 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
m_grpc_threadiness = m_config->get_scalar<uint32_t>("grpc", "threadiness", 8); // todo > limit it to avoid overshubscription? std::thread::hardware_concurrency()
if(m_grpc_threadiness == 0)
{
throw logic_error("error reading config file (" + m_config_file +"): gRPC threadiness must be greater than 0");
throw logic_error("error reading config file (" + m_config_file + "): gRPC threadiness must be greater than 0");
}
m_grpc_private_key = m_config->get_scalar<string>("grpc", "private_key", "/etc/falco/certs/server.key");
m_grpc_cert_chain = m_config->get_scalar<string>("grpc", "cert_chain", "/etc/falco/certs/server.crt");
@@ -170,9 +170,9 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
throw logic_error("Error reading config file (" + m_config_file + "): No outputs configured. Please configure at least one output file output enabled but no filename in configuration block");
}
string log_level = m_config->get_scalar<string>("log_level", "info");
m_log_level = m_config->get_scalar<string>("log_level", "info");
falco_logger::set_level(log_level);
falco_logger::set_level(m_log_level);
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);

View File

@@ -195,6 +195,7 @@ public:
std::list<std::string> m_rules_filenames;
bool m_json_output;
bool m_json_include_output_property;
std::string m_log_level;
std::vector<falco_outputs::output_config> m_outputs;
uint32_t m_notifications_rate;
uint32_t m_notifications_max_burst;

View File

@@ -45,7 +45,6 @@ limitations under the License.
#include "statsfilewriter.h"
#include "webserver.h"
#include "grpc_server.h"
#include "profiler.h"
#include "banned.h" // This raises a compilation error when certain functions are used
typedef function<void(sinsp* inspector)> open_t;
@@ -236,7 +235,6 @@ uint64_t do_inspect(falco_engine *engine,
bool all_events,
int &result)
{
PROFILEME();
uint64_t num_evts = 0;
int32_t rc;
sinsp_evt* ev;
@@ -1205,12 +1203,19 @@ int falco_init(int argc, char **argv)
webserver.start();
}
// grpc server
// gRPC server
if(config.m_grpc_enabled)
{
// TODO(fntlnz,leodido): when we want to spawn multiple threads we need to have a queue per thread, or implement
// different queuing mechanisms, round robin, fanout? What we want to achieve?
grpc_server.init(config.m_grpc_bind_address, config.m_grpc_threadiness, config.m_grpc_private_key, config.m_grpc_cert_chain, config.m_grpc_root_certs);
grpc_server.init(
config.m_grpc_bind_address,
config.m_grpc_threadiness,
config.m_grpc_private_key,
config.m_grpc_cert_chain,
config.m_grpc_root_certs,
config.m_log_level
);
grpc_server_thread = std::thread([&grpc_server] {
grpc_server.run();
});
@@ -1293,7 +1298,6 @@ exit:
//
int main(int argc, char **argv)
{
alloc_chunk();
int rc;
// g_restart will cause the falco loop to exit, but we

View File

@@ -145,6 +145,8 @@ void falco_outputs::handle_event(gen_event *ev, string &rule, string &source,
return;
}
std::lock_guard<std::mutex> guard(m_ls_semaphore);
lua_getglobal(m_ls, m_lua_output_event.c_str());

View File

@@ -23,7 +23,7 @@ limitations under the License.
#include "logger.h"
#include "grpc_server.h"
#include "grpc_request_context.h"
#include "utils.h"
#include "falco_utils.h"
#include "banned.h" // This raises a compilation error when certain functions are used
#define REGISTER_STREAM(req, res, svc, rpc, impl, num) \
@@ -44,6 +44,25 @@ limitations under the License.
c.start(this); \
}
static void gpr_log_dispatcher_func(gpr_log_func_args* args)
{
int priority;
switch(args->severity)
{
case GPR_LOG_SEVERITY_ERROR:
priority = LOG_ERR;
break;
case GPR_LOG_SEVERITY_DEBUG:
priority = LOG_DEBUG;
break;
default:
priority = LOG_INFO;
break;
}
falco_logger::log(priority, args->message);
}
void falco::grpc::server::thread_process(int thread_index)
{
void* tag = nullptr;
@@ -96,38 +115,81 @@ void falco::grpc::server::thread_process(int thread_index)
}
}
void falco::grpc::server::init(std::string server_addr, int threadiness, std::string private_key, std::string cert_chain, std::string root_certs)
void falco::grpc::server::init(
std::string server_addr,
int threadiness,
std::string private_key,
std::string cert_chain,
std::string root_certs,
std::string log_level)
{
m_server_addr = server_addr;
m_threadiness = threadiness;
m_private_key = private_key;
m_cert_chain = cert_chain;
m_root_certs = root_certs;
// Set the verbosity level of gpr logger
falco::schema::priority logging_level = falco::schema::INFORMATIONAL;
falco::schema::priority_Parse(log_level, &logging_level);
switch(logging_level)
{
case falco::schema::ERROR:
gpr_set_log_verbosity(GPR_LOG_SEVERITY_ERROR);
break;
case falco::schema::DEBUG:
gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG);
break;
case falco::schema::INFORMATIONAL:
default:
// note > info will always enter here since it is != from "informational"
gpr_set_log_verbosity(GPR_LOG_SEVERITY_INFO);
break;
}
gpr_log_verbosity_init();
gpr_set_log_function(gpr_log_dispatcher_func);
if(falco::utils::network::is_unix_scheme(m_server_addr))
{
init_unix_server_builder();
return;
}
init_mtls_server_builder();
}
void falco::grpc::server::run()
void falco::grpc::server::init_mtls_server_builder()
{
string private_key;
string cert_chain;
string root_certs;
falco::utils::read(m_cert_chain, cert_chain);
falco::utils::read(m_private_key, private_key);
falco::utils::read(m_root_certs, root_certs);
falco::utils::readfile(m_cert_chain, cert_chain);
falco::utils::readfile(m_private_key, private_key);
falco::utils::readfile(m_root_certs, root_certs);
::grpc::SslServerCredentialsOptions::PemKeyCertPair cert_pair{private_key, cert_chain};
::grpc::SslServerCredentialsOptions ssl_opts(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
ssl_opts.pem_root_certs = root_certs;
ssl_opts.pem_key_cert_pairs.push_back(cert_pair);
::grpc::ServerBuilder builder;
builder.AddListeningPort(m_server_addr, ::grpc::SslServerCredentials(ssl_opts));
builder.RegisterService(&m_output_svc);
builder.RegisterService(&m_version_svc);
m_server_builder.AddListeningPort(m_server_addr, ::grpc::SslServerCredentials(ssl_opts));
}
m_completion_queue = builder.AddCompletionQueue();
m_server = builder.BuildAndStart();
void falco::grpc::server::init_unix_server_builder()
{
m_server_builder.AddListeningPort(m_server_addr, ::grpc::InsecureServerCredentials());
}
void falco::grpc::server::run()
{
m_server_builder.RegisterService(&m_output_svc);
m_server_builder.RegisterService(&m_version_svc);
m_completion_queue = m_server_builder.AddCompletionQueue();
m_server = m_server_builder.BuildAndStart();
if(m_server == nullptr)
{
falco_logger::log(LOG_EMERG, "Error starting gRPC server\n");
return;
}
falco_logger::log(LOG_INFO, "Starting gRPC server at " + m_server_addr + "\n");
// The number of contexts is multiple of the number of threads

View File

@@ -29,20 +29,17 @@ namespace grpc
class server : public server_impl
{
public:
server()
{
}
server(std::string server_addr, int threadiness, std::string private_key, std::string cert_chain, std::string root_certs):
m_server_addr(server_addr),
m_threadiness(threadiness),
m_private_key(private_key),
m_cert_chain(cert_chain),
m_root_certs(root_certs)
{
}
server() = default;
virtual ~server() = default;
void init(std::string server_addr, int threadiness, std::string private_key, std::string cert_chain, std::string root_certs);
void init(
std::string server_addr,
int threadiness,
std::string private_key,
std::string cert_chain,
std::string root_certs,
std::string log_level
);
void thread_process(int thread_index);
void run();
void stop();
@@ -61,7 +58,10 @@ private:
std::unique_ptr<::grpc::Server> m_server;
std::vector<std::thread> m_threads;
::grpc::ServerBuilder m_server_builder;
void init_mtls_server_builder();
void init_unix_server_builder();
};
} // namespace grpc
} // namespace falco
} // namespace falco

View File

@@ -1,35 +0,0 @@
/*
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
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 "utils.h"
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::utils::read(const std::string& filename, std::string& data)
{
std::ifstream file(filename.c_str(), std::ios::in);
if(file.is_open())
{
std::stringstream ss;
ss << file.rdbuf();
file.close();
data = ss.str();
}
return;
}

View File

@@ -1,19 +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.
add_library(falco_profiler INTERFACE)
target_include_directories(falco_profiler INTERFACE "${HEDLEY_INCLUDE}" "${FLATBUFFER_INCLUDE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}")
flatbuffers_generate_c_headers(PROFILE "profile.fbs")
add_custom_target(flatbuffer_profiler DEPENDS ${PROFILE_OUTPUTS})

View File

@@ -1,14 +0,0 @@
namespace profiler;
file_identifier "FPRO";
file_extension "fpro";
table Node {
func:string;
file:string;
line:int;
cycles:uint64;
childs:[Node];
}
root_type Node;

View File

@@ -1,172 +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.
*/
#pragma once
#include <cstdint>
#include <thread>
#include <vector>
#include <mutex>
#include <memory>
#include <hedley.h>
namespace profiler
{
#define CHUNK_ELEMENTS 7
#define CHUNK_SIZE ((1 << 20) * CHUNK_ELEMENTS) // 20 MiB = 5242880 * sizeof(uint32_t)
#define LABEL_MASK 0x80000000 // Largest positive int32 + 1
struct cursor
{
uint32_t* current;
uint32_t* end;
};
struct chunk
{
uint32_t* begin;
uint32_t* end;
std::thread::id thread;
};
struct label
{
uint32_t label;
std::string file;
std::string func;
int line;
};
thread_local cursor c;
std::vector<label> labels;
std::vector<chunk> chunks;
size_t nchunks;
std::mutex mu;
HEDLEY_NEVER_INLINE void alloc_chunk()
{
auto d = new uint32_t[CHUNK_SIZE];
c.current = d;
c.end = d + CHUNK_SIZE;
mu.lock();
chunks.push_back({d, d + CHUNK_SIZE, std::this_thread::get_id()});
nchunks += 1;
mu.unlock();
}
HEDLEY_NEVER_INLINE uint32_t create_label(char const* file, int line, char const* func)
{
label l;
l.label = labels.size() | LABEL_MASK;
l.file = file;
l.func = func;
l.line = line;
mu.lock();
labels.push_back(l);
mu.unlock();
return l.label;
}
struct profile
{
uint32_t* data;
int n;
int epochs; // (max) depth at the moment of execution
explicit profile(uint32_t label)
{
data = c.current;
auto next = data + CHUNK_ELEMENTS;
n = nchunks;
epochs = (next - chunks[n - 1].begin) / CHUNK_ELEMENTS; // (next - start) / data size
if(HEDLEY_LIKELY(next != c.end))
c.current = next; // adds 28 bytes
else
alloc_chunk(); // note: changes `c` values (current and end)
data[0] = label;
data[5] = 0; // unknown parent
data[6] = 0; // mark current instance as init
unsigned int lo, hi;
__asm__ __volatile__("rdtsc"
: "=a"(lo), "=d"(hi));
data[1] = hi;
data[2] = lo;
}
~profile()
{
unsigned int lo, hi;
__asm__ __volatile__("rdtsc"
: "=a"(lo), "=d"(hi));
data[3] = hi;
data[4] = lo;
if(HEDLEY_LIKELY(epochs > 1))
{
for(int i = 0; i < epochs - 1; i++)
{
// Check whether the i-th destructor before this has been called (>0) or not (0)
if(data[-1 - (i * CHUNK_ELEMENTS)] == 0)
{
// The head of the first destructor which has not been called yet is the parent of the current one
data[5] = data[-((i + 1) * CHUNK_ELEMENTS)];
break;
}
}
}
else if(n > 1)
{
// TODO: make it span across more chunks (until n - 2 == 0)
uint32_t* cdata = chunks[n - 2].end;
for(int i = 0; i < (CHUNK_SIZE / CHUNK_ELEMENTS); i++)
{
if(cdata[-1 - (i * CHUNK_ELEMENTS)] == 0)
{
data[5] = cdata[-((i + 1) * CHUNK_ELEMENTS)];
break;
}
}
}
if(n > 1 && data[5] == 0)
{
// TODO: same as above
// TODO: make it span across more chunks (until n - 2 == 0)
uint32_t* cdata = chunks[n - 2].end;
for(int i = 0; i < (CHUNK_SIZE / CHUNK_ELEMENTS); i++)
{
if(cdata[-1 - (i * CHUNK_ELEMENTS)] == 0)
{
data[5] = cdata[-((i + 1) * CHUNK_ELEMENTS)];
break;
}
}
}
data[6] = n; // mark current instance as done storing the chunk index (+ 1)
}
};
#define PROFILE_VARIABLE_IMPL(arg1, arg2) arg1##arg2
#define PROFILE_VARIABLE(arg1, arg2) PROFILE_VARIABLE_IMPL(arg1, arg2)
#define PROFILEME() \
static uint32_t PROFILE_VARIABLE(_label, __LINE__) = profiler::create_label(__FILE__, __LINE__, __FUNCTION__); \
profiler::profile PROFILE_VARIABLE(_profile_, __LINE__)(PROFILE_VARIABLE(_label, __LINE__));
}; // namespace profiler