mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-20 19:52:08 +00:00
Compare commits
153 Commits
new/profil
...
perf-exper
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
511ef52717 | ||
|
|
e2bf87d207 | ||
|
|
0a600253ac | ||
|
|
571f8a28e7 | ||
|
|
6bb0bba68a | ||
|
|
f1a42cf259 | ||
|
|
427c15f257 | ||
|
|
a9b4e6c73e | ||
|
|
b32853798f | ||
|
|
b86bc4a857 | ||
|
|
23224355a5 | ||
|
|
84fbac0863 | ||
|
|
3814b2e81b | ||
|
|
a83b91fc53 | ||
|
|
e618f005b6 | ||
|
|
d8faa95702 | ||
|
|
ef5e71598a | ||
|
|
bb1282c7be | ||
|
|
8f07189ede | ||
|
|
dec2ff7d72 | ||
|
|
f3022e0abf | ||
|
|
9b42b20e1c | ||
|
|
850a49989f | ||
|
|
0dc2a6abd3 | ||
|
|
4346e98f20 | ||
|
|
38009f23b4 | ||
|
|
324a3b88e7 | ||
|
|
c03f563450 | ||
|
|
c4b7f17271 | ||
|
|
ebb0c47524 | ||
|
|
a447b6996e | ||
|
|
596e7ee303 | ||
|
|
8ae6aa51b9 | ||
|
|
1343fd7e92 | ||
|
|
1954cf3af3 | ||
|
|
bc8f9a5692 | ||
|
|
1af1226566 | ||
|
|
c743f1eb68 | ||
|
|
bca98e0419 | ||
|
|
32bae35de2 | ||
|
|
de147447ed | ||
|
|
825e249294 | ||
|
|
00689a5d97 | ||
|
|
4d31784a83 | ||
|
|
2848eceb03 | ||
|
|
c7ac1ef61b | ||
|
|
5fd3c38422 | ||
|
|
3bad1d2a56 | ||
|
|
8ad5c4f834 | ||
|
|
553856ad68 | ||
|
|
2d52be603d | ||
|
|
75e62269c3 | ||
|
|
3d1f27d082 | ||
|
|
ad960a9485 | ||
|
|
d8d218230d | ||
|
|
b7e7a10035 | ||
|
|
fecf1a9fea | ||
|
|
54a6d5c523 | ||
|
|
9fe78bf658 | ||
|
|
727755e276 | ||
|
|
352307431a | ||
|
|
6cfb0ec2b8 | ||
|
|
4af769f84c | ||
|
|
82e0b5f217 | ||
|
|
b4d005eb51 | ||
|
|
061c5f5ac9 | ||
|
|
c06ccf8378 | ||
|
|
3408ea9164 | ||
|
|
51aea00be8 | ||
|
|
a5cadbf5fa | ||
|
|
9eb0b7fb5f | ||
|
|
869d883dc7 | ||
|
|
b88767f558 | ||
|
|
bdbdf7b830 | ||
|
|
4e2f3e2c71 | ||
|
|
3d9bc8f67b | ||
|
|
c89c11c3c4 | ||
|
|
5bd9ba0529 | ||
|
|
b9e6d65e69 | ||
|
|
0d194f2b40 | ||
|
|
d9f2cda8cf | ||
|
|
2ebc55f897 | ||
|
|
01ae8701d9 | ||
|
|
be6c4b273d | ||
|
|
a72f27c028 | ||
|
|
58adc5b60c | ||
|
|
cf31712fad | ||
|
|
a568c42adb | ||
|
|
05dd170d70 | ||
|
|
e29a4c8560 | ||
|
|
c5ba95deff | ||
|
|
27037e64cc | ||
|
|
1859552834 | ||
|
|
298ba29c88 | ||
|
|
0272b94bb1 | ||
|
|
dbd86234ad | ||
|
|
b69bde6bd4 | ||
|
|
d2f0ad7c07 | ||
|
|
70b9bfe1d6 | ||
|
|
17f6da7885 | ||
|
|
dee0cc67f3 | ||
|
|
8429256e37 | ||
|
|
00884ef581 | ||
|
|
578ef7f64d | ||
|
|
a5ce61f03f | ||
|
|
74ca02d199 | ||
|
|
3bfd94fefd | ||
|
|
6eb9b1add1 | ||
|
|
81e29c55ec | ||
|
|
f186e5f41f | ||
|
|
ade64b0ce8 | ||
|
|
d808c0aeaf | ||
|
|
65e069a020 | ||
|
|
75c2275dac | ||
|
|
258f73ede2 | ||
|
|
3386671452 | ||
|
|
2680a459ec | ||
|
|
da9278f061 | ||
|
|
dc0670c718 | ||
|
|
05ce5b7f0b | ||
|
|
de8bade2bf | ||
|
|
e245fe460f | ||
|
|
d7de45acb2 | ||
|
|
86b473e224 | ||
|
|
d1c9aae881 | ||
|
|
986ea28279 | ||
|
|
5266618689 | ||
|
|
fa3d2eb473 | ||
|
|
acb3f94786 | ||
|
|
d1af7e139f | ||
|
|
434a5abc8b | ||
|
|
fd97f99b9f | ||
|
|
555bf1f10d | ||
|
|
f3f512c6dd | ||
|
|
8d79c11953 | ||
|
|
439152c8d8 | ||
|
|
3d3d537d85 | ||
|
|
88dbc78a44 | ||
|
|
59c2e6b421 | ||
|
|
33c93e6c29 | ||
|
|
46483339a3 | ||
|
|
762ef015b8 | ||
|
|
b887c92c91 | ||
|
|
efd0bf1967 | ||
|
|
5c69639a69 | ||
|
|
b8875df48f | ||
|
|
368817a95d | ||
|
|
622a6c1e44 | ||
|
|
95e7242d13 | ||
|
|
c42cb1858c | ||
|
|
935d9f5378 | ||
|
|
2345ea2770 | ||
|
|
901239c3c8 |
@@ -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":
|
||||
|
||||
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -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
|
||||
|
||||
5
.github/stale.yml
vendored
5
.github/stale.yml
vendored
@@ -6,7 +6,6 @@ daysUntilClose: 7
|
||||
exemptLabels:
|
||||
- cncf
|
||||
- roadmap
|
||||
- enhancement
|
||||
- "help wanted"
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
@@ -15,5 +14,7 @@ markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
Issues labeled "cncf", "roadmap" and "help wanted" will not be automatically closed.
|
||||
Please refer to a maintainer to get such label added if you think this should be kept open.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
closeComment: false
|
||||
|
||||
@@ -8,8 +8,13 @@ This is a list of production adopters of Falco (in alphabetical order):
|
||||
|
||||
* [Frame.io](https://frame.io/) - Frame.io is a cloud-based (SaaS) video review and collaboration platform that enables users to securely upload source media, work-in-progress edits, dailies, and more into private workspaces where they can invite their team and clients to collaborate on projects. Understanding what is running on production servers, and the context around why things are running is even more tricky now that we have further abstractions like Docker and Kubernetes. To get this needed visibility into our system, we rely on Falco. Falco's ability to collect raw system calls such as open, connect, exec, along with their arguments offer key insights on what is happening on the production system and became the foundation of our intrusion detection and alerting system.
|
||||
|
||||
* [GitLab](https://about.gitlab.com/direction/defend/container_host_security/) - GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate. GitLab Ultimate provides the single tool teams need to find, triage, and fix vulnerabilities in applications, services, and cloud-native environments enabling them to manage their risk. This provides them with repeatable, defensible processes that automate security and compliance policies. GitLab includes a tight integration with Falco, allowing users to defend their containerized applications from attacks while running in production.
|
||||
|
||||
* [League](https://league.com/ca/) - League provides health benefits management services to help employees understand and get the most from their benefits, and employers to provide effective, efficient plans. Falco is used to monitor our deployed services on Kubernetes, protecting against malicious access to containerswhich could lead to leaks of PHI or other sensitive data. The Falco alerts are logged in Stackdriver for grouping and further analysis. In the future, we're hoping for integrations with Prometheus and AlertManager as well.
|
||||
|
||||
* [Logz.io](https://logz.io/) - Logz.io is a cloud observability platform for modern engineering teams. The Logz.io platform consists of three products — Log Management, Infrastructure Monitoring, and Cloud SIEM — that work together to unify the jobs of monitoring, troubleshooting, and security. We empower engineers to deliver better software by offering the world's most popular open source observability tools — the ELK Stack, Grafana, and Jaeger — in a single, easy to use, and powerful platform purpose-built for monitoring distributed cloud environments. Cloud SIEM supports data from multiple sources, including Falco's alerts, and offers useful rules and dashboards content to visualize and manage incidents across your systems in a unified UI.
|
||||
* https://logz.io/blog/k8s-security-with-falco-and-cloud-siem/
|
||||
|
||||
* [Preferral](https://www.preferral.com) - Preferral is a HIPAA-compliant platform for Referral Management and Online Referral Forms. Preferral streamlines the referral process for patients, specialists and their referral partners. By automating the referral process, referring practices spend less time on the phone, manual efforts are eliminated, and patients get the right care from the right specialist. Preferral leverages Falco to provide a Host Intrusion Detection System to meet their HIPPA compliance requirements.
|
||||
* https://hipaa.preferral.com/01-preferral_hipaa_compliance/
|
||||
|
||||
|
||||
151
CHANGELOG.md
151
CHANGELOG.md
@@ -2,9 +2,156 @@
|
||||
|
||||
This file documents all notable changes to Falco. The release numbering uses [semantic versioning](http://semver.org).
|
||||
|
||||
## v0.24.0
|
||||
|
||||
Released on 2020-07-16
|
||||
|
||||
### Major Changes
|
||||
|
||||
* new: Falco now supports userspace instrumentation with the -u flag [[#1195](https://github.com/falcosecurity/falco/pull/1195)]
|
||||
* BREAKING CHANGE: --stats_interval is now --stats-interval [[#1308](https://github.com/falcosecurity/falco/pull/1308)]
|
||||
* new: auto threadiness for gRPC server [[#1271](https://github.com/falcosecurity/falco/pull/1271)]
|
||||
* BREAKING CHANGE: server streaming gRPC outputs method is now `falco.outputs.service/get` [[#1241](https://github.com/falcosecurity/falco/pull/1241)]
|
||||
* new: new bi-directional async streaming gRPC outputs (`falco.outputs.service/sub`) [[#1241](https://github.com/falcosecurity/falco/pull/1241)]
|
||||
* new: unix socket for the gRPC server [[#1217](https://github.com/falcosecurity/falco/pull/1217)]
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* update: driver version is 85c88952b018fdbce2464222c3303229f5bfcfad now [[#1305](https://github.com/falcosecurity/falco/pull/1305)]
|
||||
* update: `SKIP_MODULE_LOAD` renamed to `SKIP_DRIVER_LOADER` [[#1297](https://github.com/falcosecurity/falco/pull/1297)]
|
||||
* docs: add leogr to OWNERS [[#1300](https://github.com/falcosecurity/falco/pull/1300)]
|
||||
* update: default threadiness to 0 ("auto" behavior) [[#1271](https://github.com/falcosecurity/falco/pull/1271)]
|
||||
* update: k8s audit endpoint now defaults to /k8s-audit everywhere [[#1292](https://github.com/falcosecurity/falco/pull/1292)]
|
||||
* update(falco.yaml): `webserver.k8s_audit_endpoint` default value changed from `/k8s_audit` to `/k8s-audit` [[#1261](https://github.com/falcosecurity/falco/pull/1261)]
|
||||
* docs(test): instructions to run regression test suites locally [[#1234](https://github.com/falcosecurity/falco/pull/1234)]
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix: --stats-interval correctly accepts values >= 999 (ms) [[#1308](https://github.com/falcosecurity/falco/pull/1308)]
|
||||
* fix: make the eBPF driver build work on CentOS 8 [[#1301](https://github.com/falcosecurity/falco/pull/1301)]
|
||||
* fix(userspace/falco): correct options handling for `buffered_output: false` which was not honored for the `stdout` output [[#1296](https://github.com/falcosecurity/falco/pull/1296)]
|
||||
* fix(userspace/falco): honor -M also when using a trace file [[#1245](https://github.com/falcosecurity/falco/pull/1245)]
|
||||
* fix: high CPU usage when using server streaming gRPC outputs [[#1241](https://github.com/falcosecurity/falco/pull/1241)]
|
||||
* fix: missing newline from some log messages (eg., token bucket depleted) [[#1257](https://github.com/falcosecurity/falco/pull/1257)]
|
||||
|
||||
|
||||
### Rule Changes
|
||||
|
||||
* rule(Container Drift Detected (chmod)): disabled by default [[#1316](https://github.com/falcosecurity/falco/pull/1316)]
|
||||
* rule(Container Drift Detected (open+create)): disabled by default [[#1316](https://github.com/falcosecurity/falco/pull/1316)]
|
||||
* rule(Write below etc): allow snapd to write its unit files [[#1289](https://github.com/falcosecurity/falco/pull/1289)]
|
||||
* rule(macro remote_file_copy_procs): fix reference to remote_file_copy_binaries [[#1224](https://github.com/falcosecurity/falco/pull/1224)]
|
||||
* rule(list allowed_k8s_users): whitelisted kube-apiserver-healthcheck user created by kops >= 1.17.0 for the kube-apiserver-healthcheck sidecar [[#1286](https://github.com/falcosecurity/falco/pull/1286)]
|
||||
* rule(Change thread namespace): Allow `protokube`, `dockerd`, `tini` and `aws` binaries to change thread namespace. [[#1222](https://github.com/falcosecurity/falco/pull/1222)]
|
||||
* rule(macro exe_running_docker_save): to filter out cmdlines containing `/var/run/docker`. [[#1222](https://github.com/falcosecurity/falco/pull/1222)]
|
||||
* rule(macro user_known_cron_jobs): new macro to be overridden to list known cron jobs [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Schedule Cron Jobs): exclude known cron jobs [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_update_package_registry): new macro to be overridden to list known package registry update [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Update Package Registry): exclude known package registry update [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_read_ssh_information_activities): new macro to be overridden to list known activities that read SSH info [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Read ssh information): do not throw for activities known to read SSH info [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_read_sensitive_files_activities): new macro to be overridden to list activities known to read sensitive files [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Read sensitive file trusted after startup): do not throw for activities known to read sensitive files [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Read sensitive file untrusted): do not throw for activities known to read sensitive files [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_write_rpm_database_activities): new macro to be overridden to list activities known to write RPM database [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Write below rpm database): do not throw for activities known to write RPM database [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_db_spawned_processes): new macro to be overridden to list processes known to spawn DB [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(DB program spawned process): do not throw for processes known to spawn DB [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_modify_bin_dir_activities): new macro to be overridden to list activities known to modify bin directories [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Modify binary dirs): do not throw for activities known to modify bin directories [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_mkdir_bin_dir_activities): new macro to be overridden to list activities known to create directories below bin directories [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Mkdir binary dirs): do not throw for activities known to create directories below bin directories [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_system_user_login): new macro to exclude known system user logins [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(System user interactive): do not throw for known system user logins [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_user_management_activities): new macro to be overridden to list activities known to do user managements activities [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(User mgmt binaries): do not throw for activities known to do user managements activities [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_create_files_below_dev_activities): new macro to be overridden to list activities known to create files below dev [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Create files below dev): do not throw for activities known to create files below dev [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_contact_k8s_api_server_activities): new macro to be overridden to list activities known to contact Kubernetes API server [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Contact K8S API Server From Container): do not throw for activities known to contact Kubernetes API server [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_network_tool_activities): new macro to be overridden to list activities known to spawn/use network tools [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Launch Suspicious Network Tool in Container): do not throw for activities known to spawn/use network tools [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_remove_data_activities): new macro to be overridden to list activities known to perform data remove commands [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Remove Bulk Data from Disk): do not throw for activities known to perform data remove commands [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_create_hidden_file_activities): new macro to be overridden to list activities known to create hidden files [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Create Hidden Files or Directories): do not throw for activities known to create hidden files [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_stand_streams_redirect_activities): new macro to be overridden to list activities known to redirect stream to network connection (in containers) [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Redirect STDOUT/STDIN to Network Connection in Container): do not throw for activities known to redirect stream to network connection (in containers) [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_container_drift_activities): new macro to be overridden to list activities known to create executables in containers [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Container Drift Detected (chmod)): do not throw for activities known to give execution permissions to files in containers [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Container Drift Detected (open+create)): do not throw for activities known to create executables in containers [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_node_port_service): do not throw for services known to start with a NopePort service type (k8s) [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Create NodePort Service): do not throw for services known to start with a NopePort service type (k8s) [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro user_known_exec_pod_activities): do not throw for activities known to attach/exec to a pod (k8s) [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Attach/Exec Pod): do not throw for activities known to attach/exec to a pod (k8s) [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro trusted_pod): defines trusted pods by an image list [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Pod Created in Kube Namespace): do not throw for trusted pods [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(macro trusted_sa): define trusted ServiceAccount [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(Service Account Created in Kube Namespace): do not throw for trusted ServiceAccount [[#1294](https://github.com/falcosecurity/falco/pull/1294)]
|
||||
* rule(list network_tool_binaries): add zmap to the list [[#1284](https://github.com/falcosecurity/falco/pull/1284)]
|
||||
* rule(macro root_dir): correct macro to exactly match the `/root` dir and not other with just `/root` as a prefix [[#1279](https://github.com/falcosecurity/falco/pull/1279)]
|
||||
* rule(macro user_expected_terminal_shell_in_container_conditions): allow whitelisting terminals in containers under specific conditions [[#1154](https://github.com/falcosecurity/falco/pull/1154)]
|
||||
* rule(macro user_known_write_below_binary_dir_activities): allow writing to a binary dir in some conditions [[#1260](https://github.com/falcosecurity/falco/pull/1260)]
|
||||
* rule(macro trusted_logging_images): Add addl fluentd image [[#1230](https://github.com/falcosecurity/falco/pull/1230)]
|
||||
* rule(macro trusted_logging_images): Let azure-npm image write to /var/log [[#1230](https://github.com/falcosecurity/falco/pull/1230)]
|
||||
* rule(macro lvprogs_writing_conf): Add lvs as a lvm program [[#1230](https://github.com/falcosecurity/falco/pull/1230)]
|
||||
* rule(macro user_known_k8s_client_container): Allow hcp-tunnelfront to run kubectl in containers [[#1230](https://github.com/falcosecurity/falco/pull/1230)]
|
||||
* rule(list allowed_k8s_users): Add vertical pod autoscaler as known k8s users [[#1230](https://github.com/falcosecurity/falco/pull/1230)]
|
||||
* rule(Anonymous Request Allowed): update to checking auth decision equals to allow [[#1267](https://github.com/falcosecurity/falco/pull/1267)]
|
||||
* rule(Container Drift Detected (chmod)): new rule to detect if an existing file get exec permissions in a container [[#1254](https://github.com/falcosecurity/falco/pull/1254)]
|
||||
* rule(Container Drift Detected (open+create)): new rule to detect if a new file with execution permission is created in a container [[#1254](https://github.com/falcosecurity/falco/pull/1254)]
|
||||
* rule(Mkdir binary dirs): correct condition in macro `bin_dir_mkdir` to catch `mkdirat` syscall [[#1250](https://github.com/falcosecurity/falco/pull/1250)]
|
||||
* rule(Modify binary dirs): correct condition in macro `bin_dir_rename` to catch `rename`, `renameat`, and `unlinkat` syscalls [[#1250](https://github.com/falcosecurity/falco/pull/1250)]
|
||||
* rule(Create files below dev): correct condition to catch `openat` syscall [[#1250](https://github.com/falcosecurity/falco/pull/1250)]
|
||||
* rule(macro user_known_set_setuid_or_setgid_bit_conditions): create macro [[#1213](https://github.com/falcosecurity/falco/pull/1213)]
|
||||
|
||||
## v0.23.0
|
||||
|
||||
Released on 2020-05-18
|
||||
|
||||
### 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
|
||||
Released on 2020-04-17
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -24,7 +171,7 @@ Released on 2020-17-04
|
||||
|
||||
## v0.22.0
|
||||
|
||||
Released on 2020-16-04
|
||||
Released on 2020-04-16
|
||||
|
||||
### Major Changes
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -93,26 +93,28 @@ message(STATUS "Using bundled nlohmann-json in '${NJSON_SRC}'")
|
||||
set(NJSON_INCLUDE "${NJSON_SRC}/single_include")
|
||||
ExternalProject_Add(
|
||||
njson
|
||||
URL "https://s3.amazonaws.com/download.draios.com/dependencies/njson-3.3.0.tar.gz"
|
||||
URL "https://github.com/nlohmann/json/archive/v3.3.0.tar.gz"
|
||||
URL_HASH "SHA256=2fd1d207b4669a7843296c41d3b6ac5b23d00dec48dba507ba051d14564aa801"
|
||||
CONFIGURE_COMMAND ""
|
||||
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}")
|
||||
|
||||
# libb64
|
||||
|
||||
set(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
|
||||
message(STATUS "Using bundled b64 in '${B64_SRC}'")
|
||||
set(B64_INCLUDE "${B64_SRC}/include")
|
||||
set(B64_LIB "${B64_SRC}/src/libb64.a")
|
||||
ExternalProject_Add(
|
||||
b64
|
||||
URL "https://s3.amazonaws.com/download.draios.com/dependencies/libb64-1.2.src.zip"
|
||||
URL_HASH "SHA256=343d8d61c5cbe3d3407394f16a5390c06f8ff907bd8d614c16546310b689bfd3"
|
||||
URL "https://github.com/libb64/libb64/archive/v1.2.1.zip"
|
||||
URL_HASH "SHA256=665134c2b600098a7ebd3d00b6a866cb34909a6d48e0e37a0eda226a4ad2638a"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
@@ -134,8 +136,8 @@ set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
|
||||
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
|
||||
ExternalProject_Add(
|
||||
luajit
|
||||
URL "https://s3.amazonaws.com/download.draios.com/dependencies/LuaJIT-2.0.3.tar.gz"
|
||||
URL_HASH "SHA256=55be6cb2d101ed38acca32c5b1f99ae345904b365b642203194c585d27bebd79"
|
||||
URL "https://github.com/LuaJIT/LuaJIT/archive/v2.0.3.tar.gz"
|
||||
URL_HASH "SHA256=8da3d984495a11ba1bce9a833ba60e18b532ca0641e7d90d97fafe85ff014baa"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
@@ -150,20 +152,15 @@ list(APPEND LPEG_DEPENDENCIES "luajit")
|
||||
ExternalProject_Add(
|
||||
lpeg
|
||||
DEPENDS ${LPEG_DEPENDENCIES}
|
||||
URL "https://s3.amazonaws.com/download.draios.com/dependencies/lpeg-1.0.0.tar.gz"
|
||||
URL_HASH "SHA256=10190ae758a22a16415429a9eb70344cf29cbda738a6962a9f94a732340abf8e"
|
||||
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
|
||||
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
|
||||
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
# libyaml
|
||||
find_library(LIBYAML_LIB NAMES libyaml.so)
|
||||
if(LIBYAML_LIB)
|
||||
message(STATUS "Found libyaml: lib: ${LIBYAML_LIB}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system libyaml")
|
||||
endif()
|
||||
include(libyaml)
|
||||
|
||||
# lyaml
|
||||
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
|
||||
@@ -174,7 +171,7 @@ list(APPEND LYAML_DEPENDENCIES "luajit")
|
||||
ExternalProject_Add(
|
||||
lyaml
|
||||
DEPENDS ${LYAML_DEPENDENCIES}
|
||||
URL "https://s3.amazonaws.com/download.draios.com/dependencies/lyaml-release-v6.0.tar.gz"
|
||||
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
|
||||
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
@@ -214,11 +211,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 +235,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 +245,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
2
OWNERS
2
OWNERS
@@ -3,6 +3,7 @@ approvers:
|
||||
- kris-nova
|
||||
- leodido
|
||||
- mstemm
|
||||
- leogr
|
||||
reviewers:
|
||||
- fntlnz
|
||||
- kaizhe
|
||||
@@ -10,3 +11,4 @@ reviewers:
|
||||
- leodido
|
||||
- mfdii
|
||||
- mstemm
|
||||
- leogr
|
||||
|
||||
12
RELEASE.md
12
RELEASE.md
@@ -2,7 +2,7 @@
|
||||
|
||||
Our release process is mostly automated, but we still need some manual steps to initiate and complete it.
|
||||
|
||||
Changes and new features are grouped in [milestones](https://github.com/falcosecurity/falco/milestones), the milestone with the next version represents what is going to be released.
|
||||
Changes and new features are grouped in [milestones](https://github.com/falcosecurity/falco/milestones), the milestone with the next version represents what is going to be released.
|
||||
|
||||
Releases happen on a monthly cadence, towards the 16th of the on-going month, and we need to assign owners for each (usually we pair a new person with an experienced one). Assignees and the due date are proposed during the [weekly community call](https://github.com/falcosecurity/community). Note that hotfix releases can happen as soon as it is needed.
|
||||
|
||||
@@ -12,25 +12,26 @@ 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
|
||||
- Double-check that there are no more merged PRs without the target milestone assigned with the `is:pr is:merged no:milestone closed:>YYYT-MM-DD` [filters](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+no%3Amilestone+closed%3A%3EYYYT-MM-DD), if any, fix them
|
||||
|
||||
### 2. Milestones
|
||||
|
||||
- Move the [tasks not completed](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Aopen) to a new minor milestone
|
||||
- Close the completed milestone
|
||||
|
||||
|
||||
### 3. Release PR
|
||||
|
||||
- Double-check if any hard-coded version number is present in the code, it should be not present anywhere:
|
||||
- If any, manually correct it then open an issue to automate version number bumping later
|
||||
- Versions table in the `README.md` update itself automatically
|
||||
- Generate the change log https://github.com/leodido/rn2md, or https://fs.fntlnz.wtf/falco/milestones-changelog.txt for the lazy people (it updates every 5 minutes)
|
||||
- Generate the change log https://github.com/leodido/rn2md, or https://fs.fntlnz.wtf/falco/milestones-changelog.txt for the lazy people (it updates every 5 minutes)
|
||||
- Add the lastest changes on top the previous `CHANGELOG.md`
|
||||
- Submit a PR with the above modifications
|
||||
- Await PR approval
|
||||
- Close the completed milestone as soon PR is merged
|
||||
|
||||
## Release
|
||||
|
||||
@@ -52,6 +53,7 @@ Let `x.y.z` the new version.
|
||||
- Wait for the CI to complete
|
||||
|
||||
### 2. Update the GitHub release
|
||||
|
||||
- [Draft a new release](https://github.com/falcosecurity/falco/releases/new)
|
||||
- Use `x.y.z` both as tag version and release title
|
||||
- Use the following template to fill the release description:
|
||||
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -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
|
||||
@@ -17,14 +30,14 @@ set(CPACK_GENERATOR DEB RPM TGZ)
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.falco.org")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0), libyaml-0-2")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0)")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||
"${CMAKE_BINARY_DIR}/scripts/debian/postinst;${CMAKE_BINARY_DIR}/scripts/debian/prerm;${CMAKE_BINARY_DIR}/scripts/debian/postrm;${PROJECT_SOURCE_DIR}/cmake/cpack/debian/conffiles"
|
||||
)
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "Apache v2.0")
|
||||
set(CPACK_RPM_PACKAGE_URL "https://www.falco.org")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "dkms, kernel-devel, libyaml, ncurses")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "dkms, kernel-devel, ncurses")
|
||||
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_BINARY_DIR}/scripts/rpm/postinstall")
|
||||
set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${CMAKE_BINARY_DIR}/scripts/rpm/preuninstall")
|
||||
set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${CMAKE_BINARY_DIR}/scripts/rpm/postuninstall")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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}")
|
||||
@@ -20,8 +32,8 @@ else()
|
||||
ExternalProject_Add(
|
||||
openssl
|
||||
# START CHANGE for CVE-2017-3735, CVE-2017-3731, CVE-2017-3737, CVE-2017-3738, CVE-2017-3736
|
||||
URL "https://s3.amazonaws.com/download.draios.com/dependencies/openssl-1.0.2n.tar.gz"
|
||||
URL_HASH "SHA256=370babb75f278c39e0c50e8c4e7493bc0f18db6867478341a832a982fd15a8fe"
|
||||
URL "https://github.com/openssl/openssl/archive/OpenSSL_1_0_2n.tar.gz"
|
||||
URL_HASH "SHA256=4f4bc907caff1fee6ff8593729e5729891adcee412049153a3bb4db7625e8364"
|
||||
# END CHANGE for CVE-2017-3735, CVE-2017-3731, CVE-2017-3737, CVE-2017-3738, CVE-2017-3736
|
||||
CONFIGURE_COMMAND ./config shared --prefix=${OPENSSL_INSTALL_DIR}
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
|
||||
@@ -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
|
||||
@@ -31,7 +31,7 @@ else()
|
||||
curl
|
||||
DEPENDS openssl
|
||||
# START CHANGE for CVE-2017-8816, CVE-2017-8817, CVE-2017-8818, CVE-2018-1000007
|
||||
URL "https://s3.amazonaws.com/download.draios.com/dependencies/curl-7.61.0.tar.bz2"
|
||||
URL "https://github.com/curl/curl/releases/download/curl-7_61_0/curl-7.61.0.tar.bz2"
|
||||
URL_HASH "SHA256=5f6f336921cf5b84de56afbd08dfb70adeef2303751ffb3e570c936c6d656c9c"
|
||||
# END CHANGE for CVE-2017-8816, CVE-2017-8817, CVE-2017-8818, CVE-2018-1000007
|
||||
CONFIGURE_COMMAND
|
||||
|
||||
@@ -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
|
||||
|
||||
32
cmake/modules/libyaml.cmake
Normal file
32
cmake/modules/libyaml.cmake
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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_library(LIBYAML_LIB NAMES libyaml.so)
|
||||
if(LIBYAML_LIB)
|
||||
message(STATUS "Found libyaml: lib: ${LIBYAML_LIB}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system libyaml")
|
||||
endif()
|
||||
else()
|
||||
set(LIBYAML_SRC "${PROJECT_BINARY_DIR}/libyaml-prefix/src/libyaml")
|
||||
message(STATUS "Using bundled libyaml in '${LIBYAML_SRC}'")
|
||||
set(LIBYAML_LIB "${LIBYAML_SRC}/src/.libs/libyaml.a")
|
||||
ExternalProject_Add(
|
||||
libyaml
|
||||
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
|
||||
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
|
||||
CONFIGURE_COMMAND ./configure --enable-static=true --enable-shared=false
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
INSTALL_COMMAND "")
|
||||
endif()
|
||||
@@ -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()
|
||||
|
||||
@@ -26,8 +26,8 @@ file(MAKE_DIRECTORY ${SYSDIG_CMAKE_WORKING_DIR})
|
||||
# To update sysdig version for the next release, change the default below
|
||||
# In case you want to test against another sysdig version just pass the variable - ie., `cmake -DSYSDIG_VERSION=dev ..`
|
||||
if(NOT SYSDIG_VERSION)
|
||||
set(SYSDIG_VERSION "96bd9bc560f67742738eb7255aeb4d03046b8045")
|
||||
set(SYSDIG_CHECKSUM "SHA256=766e8952a36a4198fd976b9d848523e6abe4336612188e4fc911e217d8e8a00d")
|
||||
set(SYSDIG_VERSION "85c88952b018fdbce2464222c3303229f5bfcfad")
|
||||
set(SYSDIG_CHECKSUM "SHA256=6c3f5f2d699c9540e281f50cbc5cb6b580f0fc689798bc65d4a77f57f932a71c")
|
||||
endif()
|
||||
set(PROBE_VERSION "${SYSDIG_VERSION}")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -25,4 +25,4 @@ do
|
||||
ln -s "$i" "/usr/src/$base"
|
||||
done
|
||||
|
||||
/usr/bin/falco-driver-loader $1
|
||||
/usr/bin/falco-driver-loader "$@"
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
# Copyright (C) 2020 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -16,10 +16,14 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# todo(leogr): remove deprecation notice within a couple of releases
|
||||
if [[ ! -z "${SKIP_MODULE_LOAD}" ]]; then
|
||||
echo "* SKIP_MODULE_LOAD is deprecated and will be removed soon, use SKIP_DRIVER_LOADER instead"
|
||||
fi
|
||||
|
||||
# Set the SKIP_MODULE_LOAD variable to skip loading the kernel module
|
||||
# Set the SKIP_DRIVER_LOADER variable to skip loading the driver
|
||||
|
||||
if [[ -z "${SKIP_MODULE_LOAD}" ]]; then
|
||||
if [[ -z "${SKIP_DRIVER_LOADER}" ]] && [[ -z "${SKIP_MODULE_LOAD}" ]]; then
|
||||
echo "* Setting up /usr/src links from host"
|
||||
|
||||
for i in "$HOST_ROOT/usr/src"/*
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
# Copyright (C) 2020 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -17,9 +17,9 @@
|
||||
#
|
||||
|
||||
|
||||
# Set the SKIP_MODULE_LOAD variable to skip loading the kernel module
|
||||
# Set the SKIP_DRIVER_LOADER variable to skip loading the driver
|
||||
|
||||
if [[ -z "${SKIP_MODULE_LOAD}" ]]; then
|
||||
if [[ -z "${SKIP_DRIVER_LOADER}" ]]; then
|
||||
echo "* Setting up /usr/src links from host"
|
||||
|
||||
for i in "$HOST_ROOT/usr/src"/*
|
||||
|
||||
58
docker/no-driver/Dockerfile
Normal file
58
docker/no-driver/Dockerfile
Normal file
@@ -0,0 +1,58 @@
|
||||
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 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 /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"]
|
||||
@@ -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"]
|
||||
@@ -1,16 +1,20 @@
|
||||
FROM fedora:31
|
||||
|
||||
LABEL name="falcosecurity/falco-tester"
|
||||
LABEL usage="docker run -v /boot:/boot:ro -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/..:/source -v $PWD/build:/build -e FALCO_VERSION=<current_falco_version> --name <name> falcosecurity/falco-tester test"
|
||||
LABEL usage="docker run -v /boot:/boot:ro -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/..:/source -v $PWD/build:/build --name <name> falcosecurity/falco-tester test"
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
ENV FALCO_VERSION=
|
||||
ENV BUILD_TYPE=release
|
||||
|
||||
ADD https://github.com/fullstorydev/grpcurl/releases/download/v1.6.0/grpcurl_1.6.0_linux_x86_64.tar.gz /
|
||||
RUN dnf install -y python-pip python docker findutils jq unzip && dnf clean all
|
||||
ENV PATH="/root/.local/bin/:${PATH}"
|
||||
RUN pip install --user avocado-framework==69.0
|
||||
RUN pip install --user avocado-framework-plugin-varianter-yaml-to-mux==69.0
|
||||
RUN pip install --user watchdog==0.10.2
|
||||
RUN pip install --user pathtools==0.1.2
|
||||
RUN tar -C /usr/bin -xvf grpcurl_1.6.0_linux_x86_64.tar.gz
|
||||
|
||||
COPY ./root /
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ RUN test -n FALCO_VERSION
|
||||
ENV FALCO_VERSION ${FALCO_VERSION}
|
||||
|
||||
RUN apt update -y
|
||||
RUN apt install dkms libyaml-0-2 -y
|
||||
RUN apt install dkms -y
|
||||
|
||||
ADD falco-${FALCO_VERSION}-x86_64.deb /
|
||||
RUN dpkg -i /falco-${FALCO_VERSION}-x86_64.deb
|
||||
|
||||
@@ -6,7 +6,7 @@ RUN test -n FALCO_VERSION
|
||||
ENV FALCO_VERSION ${FALCO_VERSION}
|
||||
|
||||
RUN apt update -y
|
||||
RUN apt install dkms libyaml-0-2 curl -y
|
||||
RUN apt install dkms curl -y
|
||||
|
||||
ADD falco-${FALCO_VERSION}-x86_64.tar.gz /
|
||||
RUN cp -R /falco-${FALCO_VERSION}-x86_64/* /
|
||||
|
||||
@@ -69,7 +69,7 @@ case "$CMD" in
|
||||
# run tests
|
||||
echo "Running regression tests ..."
|
||||
cd "$SOURCE_DIR/falco/test"
|
||||
./run_regression_tests.sh "$BUILD_DIR/$BUILD_TYPE"
|
||||
./run_regression_tests.sh -d "$BUILD_DIR/$BUILD_TYPE"
|
||||
|
||||
# clean docker images
|
||||
clean_image "deb"
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
32
falco.yaml
32
falco.yaml
@@ -139,7 +139,7 @@ stdout_output:
|
||||
webserver:
|
||||
enabled: true
|
||||
listen_port: 8765
|
||||
k8s_audit_endpoint: /k8s_audit
|
||||
k8s_audit_endpoint: /k8s-audit
|
||||
ssl_enabled: false
|
||||
ssl_certificate: /etc/falco/falco.pem
|
||||
|
||||
@@ -167,21 +167,37 @@ 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"
|
||||
# # when threadiness is 0, Falco sets it by automatically figuring out the number of online cores
|
||||
# threadiness: 0
|
||||
# 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"
|
||||
threadiness: 8
|
||||
private_key: "/etc/falco/certs/server.key"
|
||||
cert_chain: "/etc/falco/certs/server.crt"
|
||||
root_certs: "/etc/falco/certs/ca.crt"
|
||||
bind_address: "unix:///var/run/falco.sock"
|
||||
# when threadiness is 0, Falco automatically guesses it depending on the number of online cores
|
||||
threadiness: 0
|
||||
|
||||
# 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# gRPC Falco Output
|
||||
# Falco gRPC Outputs
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
@@ -25,7 +25,7 @@ An alert is an "output" when it goes over a transport, and it is emitted by Falc
|
||||
|
||||
At the current moment, however, Falco can deliver alerts in a very basic way, for example by dumping them to standard output.
|
||||
|
||||
For this reason, many Falco users asked, with issues - eg., [falco#528](https://github.com/falcosecurity/falco/issues/528) - or in the [slack channel](https://sysdig.slack.com) if we can find a more consumable way to implement Falco outputs in an extensible way.
|
||||
For this reason, many Falco users asked, with issues - eg., [falco#528](https://github.com/falcosecurity/falco/issues/528) - or in the [slack channel](https://slack.k8s.io) if we can find a more consumable way to implement Falco outputs in an extensible way.
|
||||
|
||||
The motivation behind this proposal is to design a new output implementation that can meet our user's needs.
|
||||
|
||||
@@ -39,7 +39,10 @@ The motivation behind this proposal is to design a new output implementation tha
|
||||
- To continue supporting the old output formats by implementing their same interface
|
||||
- To be secure by default (**mutual TLS** authentication)
|
||||
- To be **asynchronous** and **non-blocking**
|
||||
- To implement a Go SDK
|
||||
- To provide a connection over unix socket (no authentication)
|
||||
- To implement a Go client
|
||||
- To implement a Rust client
|
||||
- To implement a Python client
|
||||
|
||||
### Non-Goals
|
||||
|
||||
@@ -77,26 +80,25 @@ syntax = "proto3";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "schema.proto";
|
||||
|
||||
package falco.output;
|
||||
package falco.outputs;
|
||||
|
||||
option go_package = "github.com/falcosecurity/client-go/pkg/api/output";
|
||||
option go_package = "github.com/falcosecurity/client-go/pkg/api/outputs";
|
||||
|
||||
// The `subscribe` service defines the RPC call
|
||||
// to perform an output `request` which will lead to obtain an output `response`.
|
||||
// This service defines the RPC methods
|
||||
// to `request` a stream of output `response`s.
|
||||
service service {
|
||||
rpc subscribe(request) returns (stream response);
|
||||
// Subscribe to a stream of Falco outputs by sending a stream of requests.
|
||||
rpc sub(stream request) returns (stream response);
|
||||
// Get all the Falco outputs present in the system up to this call.
|
||||
rpc get(request) returns (stream response);
|
||||
}
|
||||
|
||||
// The `request` message is the logical representation of the request model.
|
||||
// It is the input of the `subscribe` service.
|
||||
// It is used to configure the kind of subscription to the gRPC streaming server.
|
||||
// It is the input of the `output.service` service.
|
||||
message request {
|
||||
bool keepalive = 1;
|
||||
// string duration = 2; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
|
||||
// repeated string tags = 3; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
|
||||
}
|
||||
|
||||
// The `response` message is the logical representation of the output model.
|
||||
// The `response` message is the representation of the output model.
|
||||
// It contains all the elements that Falco emits in an output along with the
|
||||
// definitions for priorities and source.
|
||||
message response {
|
||||
@@ -106,7 +108,7 @@ message response {
|
||||
string rule = 4;
|
||||
string output = 5;
|
||||
map<string, string> output_fields = 6;
|
||||
// repeated string tags = 7; // TODO(leodido,fntlnz): tags not supported yet, keeping for reference
|
||||
string hostname = 7;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -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,24 +81,36 @@
|
||||
|
||||
- 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/
|
||||
|
||||
# This detects writes immediately below / or any write anywhere below /root
|
||||
- macro: root_dir
|
||||
condition: ((fd.directory=/ or fd.name startswith /root) and fd.name contains "/")
|
||||
condition: (fd.directory=/ or fd.name startswith /root/)
|
||||
|
||||
- list: shell_binaries
|
||||
items: [ash, bash, csh, ksh, sh, tcsh, zsh, dash]
|
||||
@@ -219,7 +232,7 @@
|
||||
# The truncated dpkg-preconfigu is intentional, process names are
|
||||
# truncated at the sysdig level.
|
||||
- list: package_mgmt_binaries
|
||||
items: [rpm_binaries, deb_binaries, update-alternat, gem, pip, pip3, sane-utils.post, alternatives, chef-client, apk]
|
||||
items: [rpm_binaries, deb_binaries, update-alternat, gem, pip, pip3, sane-utils.post, alternatives, chef-client, apk, snapd]
|
||||
|
||||
- macro: package_mgmt_procs
|
||||
condition: proc.name in (package_mgmt_binaries)
|
||||
@@ -477,12 +490,16 @@
|
||||
- macro: consider_all_cron_jobs
|
||||
condition: (never_true)
|
||||
|
||||
- macro: user_known_cron_jobs
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Schedule Cron Jobs
|
||||
desc: Detect cron jobs scheduled
|
||||
condition: >
|
||||
consider_all_cron_jobs and
|
||||
((open_write and fd.name startswith /etc/cron) or
|
||||
(spawned_process and proc.name = "crontab"))
|
||||
(spawned_process and proc.name = "crontab")) and
|
||||
consider_all_cron_jobs and
|
||||
not user_known_cron_jobs
|
||||
output: >
|
||||
Cron jobs were scheduled to run (user=%user.name command=%proc.cmdline
|
||||
file=%fd.name container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
@@ -707,7 +724,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))
|
||||
@@ -848,7 +865,8 @@
|
||||
- macro: exe_running_docker_save
|
||||
condition: >
|
||||
proc.name = "exe"
|
||||
and proc.cmdline contains "/var/lib/docker"
|
||||
and (proc.cmdline contains "/var/lib/docker"
|
||||
or proc.cmdline contains "/var/run/docker")
|
||||
and proc.pname in (dockerd, docker)
|
||||
|
||||
# Ideally we'd have a length check here as well but sysdig
|
||||
@@ -917,18 +935,28 @@
|
||||
- macro: modify_repositories
|
||||
condition: (evt.arg.newpath pmatch (repository_directories))
|
||||
|
||||
- macro: user_known_update_package_registry
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Update Package Repository
|
||||
desc: Detect package repositories get updated
|
||||
condition: >
|
||||
((open_write and access_repositories) or (modify and modify_repositories))
|
||||
and not package_mgmt_procs
|
||||
and not exe_running_docker_save
|
||||
and not user_known_update_package_registry
|
||||
output: >
|
||||
Repository files get updated (user=%user.name command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name newpath=%evt.arg.newpath container_id=%container.id image=%container.image.repository)
|
||||
priority:
|
||||
NOTICE
|
||||
tags: [filesystem, mitre_persistence]
|
||||
|
||||
# Users should overwrite this macro to specify conditions under which a
|
||||
# write under the binary dir is ignored. For example, it may be okay to
|
||||
# install a binary in the context of a ci/cd build.
|
||||
- macro: user_known_write_below_binary_dir_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Write below binary dir
|
||||
desc: an attempt to write to any file below a set of binary directories
|
||||
condition: >
|
||||
@@ -937,6 +965,7 @@
|
||||
and not exe_running_docker_save
|
||||
and not python_running_get_pip
|
||||
and not python_running_ms_oms
|
||||
and not user_known_write_below_binary_dir_activities
|
||||
output: >
|
||||
File below a known binary directory opened for writing (user=%user.name
|
||||
command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository)
|
||||
@@ -1007,13 +1036,17 @@
|
||||
- macro: consider_ssh_reads
|
||||
condition: (never_true)
|
||||
|
||||
- macro: user_known_read_ssh_information_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Read ssh information
|
||||
desc: Any attempt to read files below ssh directories by non-ssh programs
|
||||
condition: >
|
||||
(consider_ssh_reads and
|
||||
(open_read or open_directory) and
|
||||
((open_read or open_directory) and
|
||||
consider_ssh_reads and
|
||||
(user_ssh_directory or fd.name startswith /root/.ssh) and
|
||||
(not proc.name in (ssh_binaries)))
|
||||
not user_known_read_ssh_information_activities and
|
||||
not proc.name in (ssh_binaries))
|
||||
output: >
|
||||
ssh-related file/directory read by non-ssh program (user=%user.name
|
||||
command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository)
|
||||
@@ -1356,6 +1389,9 @@
|
||||
- macro: runc_writing_exec_fifo
|
||||
condition: (proc.cmdline="runc:[1:CHILD] init" and fd.name=/exec.fifo)
|
||||
|
||||
- macro: runc_writing_var_lib_docker
|
||||
condition: (proc.cmdline="runc:[1:CHILD] init" and evt.arg.filename startswith /var/lib/docker)
|
||||
|
||||
- rule: Write below root
|
||||
desc: an attempt to write to any file directly below / or /root
|
||||
condition: >
|
||||
@@ -1386,12 +1422,15 @@
|
||||
- macro: cmp_cp_by_passwd
|
||||
condition: proc.name in (cmp, cp) and proc.pname in (passwd, run-parts)
|
||||
|
||||
- macro: user_known_read_sensitive_files_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Read sensitive file trusted after startup
|
||||
desc: >
|
||||
an attempt to read any sensitive file (e.g. files containing user/password/authentication
|
||||
information) by a trusted program after startup. Trusted programs might read these files
|
||||
at startup to load initial state, but not afterwards.
|
||||
condition: sensitive_files and open_read and server_procs and not proc_is_new and proc.name!="sshd"
|
||||
condition: sensitive_files and open_read and server_procs and not proc_is_new and proc.name!="sshd" and not user_known_read_sensitive_files_activities
|
||||
output: >
|
||||
Sensitive file opened for reading by trusted program after startup (user=%user.name
|
||||
command=%proc.cmdline parent=%proc.pname file=%fd.name parent=%proc.pname gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository)
|
||||
@@ -1419,6 +1458,11 @@
|
||||
- macro: user_read_sensitive_file_conditions
|
||||
condition: cmp_cp_by_passwd
|
||||
|
||||
- macro: user_read_sensitive_file_containers
|
||||
condition: (container and
|
||||
(container.image.repository endswith "sysdig/agent") or
|
||||
(container.image.repository endswith "sysdig/agent-slim"))
|
||||
|
||||
- rule: Read sensitive file untrusted
|
||||
desc: >
|
||||
an attempt to read any sensitive file (e.g. files containing user/password/authentication
|
||||
@@ -1442,6 +1486,8 @@
|
||||
and not veritas_driver_script
|
||||
and not perl_running_centrifydc
|
||||
and not runuser_reading_pam
|
||||
and not user_known_read_sensitive_files_activities
|
||||
and not user_read_sensitive_file_containers
|
||||
output: >
|
||||
Sensitive file opened for reading by non-trusted program (user=%user.name program=%proc.name
|
||||
command=%proc.cmdline file=%fd.name parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)
|
||||
@@ -1454,6 +1500,9 @@
|
||||
proc.pcmdline = "python -m amazon_linux_extras system_motd" and
|
||||
proc.cmdline startswith "python -c import yum;")
|
||||
|
||||
- macro: user_known_write_rpm_database_activities
|
||||
condition: (never_true)
|
||||
|
||||
# Only let rpm-related programs write to the rpm database
|
||||
- rule: Write below rpm database
|
||||
desc: an attempt to write to the rpm database by any non-rpm related program
|
||||
@@ -1464,6 +1513,7 @@
|
||||
and not python_running_chef
|
||||
and not exe_running_docker_save
|
||||
and not amazon_linux_running_python_yum
|
||||
and not user_known_write_rpm_database_activities
|
||||
output: "Rpm database opened for writing by a non-rpm program (command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository)"
|
||||
priority: ERROR
|
||||
tags: [filesystem, software_mgmt, mitre_persistence]
|
||||
@@ -1488,6 +1538,9 @@
|
||||
- macro: run_by_appdynamics
|
||||
condition: (proc.pname=java and proc.pcmdline startswith "java -jar -Dappdynamics")
|
||||
|
||||
- macro: user_known_db_spawned_processes
|
||||
condition: (never_true)
|
||||
|
||||
- rule: DB program spawned process
|
||||
desc: >
|
||||
a database-server related program spawned a new process other than itself.
|
||||
@@ -1497,24 +1550,31 @@
|
||||
and spawned_process
|
||||
and not proc.name in (db_server_binaries)
|
||||
and not postgres_running_wal_e
|
||||
and not user_known_db_spawned_processes
|
||||
output: >
|
||||
Database-related program spawned process other than itself (user=%user.name
|
||||
program=%proc.cmdline parent=%proc.pname container_id=%container.id image=%container.image.repository)
|
||||
priority: NOTICE
|
||||
tags: [process, database, mitre_execution]
|
||||
|
||||
- macro: user_known_modify_bin_dir_activities
|
||||
condition: (never_true)
|
||||
|
||||
- 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 and not user_known_modify_bin_dir_activities
|
||||
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)
|
||||
priority: ERROR
|
||||
tags: [filesystem, mitre_persistence]
|
||||
|
||||
- macro: user_known_mkdir_bin_dir_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Mkdir binary dirs
|
||||
desc: an attempt to create a directory below a set of binary directories.
|
||||
condition: mkdir and bin_dir_mkdir and not package_mgmt_procs
|
||||
condition: mkdir and bin_dir_mkdir and not package_mgmt_procs and not user_known_mkdir_bin_dir_activities
|
||||
output: >
|
||||
Directory below known binary directory created (user=%user.name
|
||||
command=%proc.cmdline directory=%evt.arg.path container_id=%container.id image=%container.image.repository)
|
||||
@@ -1550,7 +1610,7 @@
|
||||
and not proc.name in (user_known_change_thread_namespace_binaries)
|
||||
and not proc.name startswith "runc"
|
||||
and not proc.cmdline startswith "containerd"
|
||||
and not proc.pname in (sysdigcloud_binaries, hyperkube, kubelet)
|
||||
and not proc.pname in (sysdigcloud_binaries, hyperkube, kubelet, protokube, dockerd, tini, aws)
|
||||
and not python_running_sdchecks
|
||||
and not java_running_sdjagent
|
||||
and not kubelet_running_loopback
|
||||
@@ -1770,7 +1830,9 @@
|
||||
# In this file, it just takes one of the images in trusted_containers
|
||||
# and repeats it.
|
||||
- macro: user_trusted_containers
|
||||
condition: (container.image.repository endswith sysdig/agent)
|
||||
condition: (container.image.repository endswith sysdig/agent or
|
||||
container.image.repository endswith sysdig/agent-slim or
|
||||
container.image.repository endswith sysdig/node-image-analyzer)
|
||||
|
||||
- list: sematext_images
|
||||
items: [docker.io/sematext/sematext-agent-docker, docker.io/sematext/agent, docker.io/sematext/logagent,
|
||||
@@ -1784,7 +1846,8 @@
|
||||
docker.io/sysdig/agent, docker.io/sysdig/falco, docker.io/sysdig/sysdig,
|
||||
gcr.io/google_containers/kube-proxy, docker.io/calico/node, quay.io/calico/node,
|
||||
docker.io/rook/toolbox, docker.io/cloudnativelabs/kube-router, docker.io/mesosphere/mesos-slave,
|
||||
docker.io/docker/ucp-agent, sematext_images, k8s.gcr.io/kube-proxy
|
||||
docker.io/docker/ucp-agent, sematext_images, k8s.gcr.io/kube-proxy,
|
||||
docker.io/falcosecurity/falco
|
||||
]
|
||||
|
||||
- macro: falco_privileged_containers
|
||||
@@ -1917,6 +1980,9 @@
|
||||
priority: WARNING
|
||||
tags: [container, mitre_lateral_movement]
|
||||
|
||||
- macro: user_known_system_user_login
|
||||
condition: (never_true)
|
||||
|
||||
# Anything run interactively by root
|
||||
# - condition: evt.type != switch and user.name = root and proc.name != sshd and interactive
|
||||
# output: "Interactive root (%user.name %proc.name %evt.dir %evt.type %evt.args %fd.name)"
|
||||
@@ -1924,17 +1990,23 @@
|
||||
|
||||
- rule: System user interactive
|
||||
desc: an attempt to run interactive commands by a system (i.e. non-login) user
|
||||
condition: spawned_process and system_users and interactive
|
||||
condition: spawned_process and system_users and interactive and not user_known_system_user_login
|
||||
output: "System user ran an interactive command (user=%user.name command=%proc.cmdline container_id=%container.id image=%container.image.repository)"
|
||||
priority: INFO
|
||||
tags: [users, mitre_remote_access_tools]
|
||||
|
||||
# In some cases, a shell is expected to be run in a container. For example, configuration
|
||||
# management software may do this, which is expected.
|
||||
- macro: user_expected_terminal_shell_in_container_conditions
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Terminal shell in container
|
||||
desc: A shell was used as the entrypoint/exec point into a container with an attached terminal.
|
||||
condition: >
|
||||
spawned_process and container
|
||||
and shell_procs and proc.tty != 0
|
||||
and container_entrypoint
|
||||
and not user_expected_terminal_shell_in_container_conditions
|
||||
output: >
|
||||
A shell was spawned in a container with an attached terminal (user=%user.name %container.info
|
||||
shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository)
|
||||
@@ -2189,6 +2261,9 @@
|
||||
priority: NOTICE
|
||||
tags: [users, mitre_privilege_escalation]
|
||||
|
||||
- macro: user_known_user_management_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: User mgmt binaries
|
||||
desc: >
|
||||
activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded.
|
||||
@@ -2206,7 +2281,8 @@
|
||||
not run_by_sumologic_securefiles and
|
||||
not run_by_yum and
|
||||
not run_by_ms_oms and
|
||||
not run_by_google_accounts_daemon
|
||||
not run_by_google_accounts_daemon and
|
||||
not user_known_user_management_activities
|
||||
output: >
|
||||
User management binary command run outside of container
|
||||
(user=%user.name command=%proc.cmdline parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4])
|
||||
@@ -2219,16 +2295,20 @@
|
||||
/dev/random, /dev/urandom, /dev/console, /dev/kmsg
|
||||
]
|
||||
|
||||
- macro: user_known_create_files_below_dev_activities
|
||||
condition: (never_true)
|
||||
|
||||
# (we may need to add additional checks against false positives, see:
|
||||
# https://bugs.launchpad.net/ubuntu/+source/rkhunter/+bug/86153)
|
||||
- rule: Create files below dev
|
||||
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
|
||||
and not user_known_create_files_below_dev_activities
|
||||
output: "File created below /dev by untrusted program (user=%user.name command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)"
|
||||
priority: ERROR
|
||||
tags: [filesystem, mitre_persistence]
|
||||
@@ -2288,9 +2368,18 @@
|
||||
- macro: k8s_api_server
|
||||
condition: (fd.sip.name="kubernetes.default.svc.cluster.local")
|
||||
|
||||
- macro: user_known_contact_k8s_api_server_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Contact K8S API Server From Container
|
||||
desc: Detect attempts to contact the K8S API Server from a container
|
||||
condition: evt.type=connect and evt.dir=< and (fd.typechar=4 or fd.typechar=6) and container and not k8s_containers and k8s_api_server
|
||||
condition: >
|
||||
evt.type=connect and evt.dir=< and
|
||||
(fd.typechar=4 or fd.typechar=6) and
|
||||
container and
|
||||
not k8s_containers and
|
||||
k8s_api_server and
|
||||
not user_known_contact_k8s_api_server_activities
|
||||
output: Unexpected connection to K8s API Server from container (command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag connection=%fd.name)
|
||||
priority: NOTICE
|
||||
tags: [network, k8s, container, mitre_discovery]
|
||||
@@ -2312,7 +2401,7 @@
|
||||
tags: [network, k8s, container, mitre_port_knocking]
|
||||
|
||||
- list: network_tool_binaries
|
||||
items: [nc, ncat, nmap, dig, tcpdump, tshark, ngrep, telnet, mitmproxy, socat]
|
||||
items: [nc, ncat, nmap, dig, tcpdump, tshark, ngrep, telnet, mitmproxy, socat, zmap]
|
||||
|
||||
- macro: network_tool_procs
|
||||
condition: (proc.name in (network_tool_binaries))
|
||||
@@ -2356,10 +2445,13 @@
|
||||
priority: WARNING
|
||||
tags: [network, process, mitre_execution]
|
||||
|
||||
- macro: user_known_network_tool_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Launch Suspicious Network Tool in Container
|
||||
desc: Detect network tools launched inside container
|
||||
condition: >
|
||||
spawned_process and container and network_tool_procs
|
||||
spawned_process and container and network_tool_procs and not user_known_network_tool_activities
|
||||
output: >
|
||||
Network tool launched in container (user=%user.name command=%proc.cmdline parent_process=%proc.pname
|
||||
container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
@@ -2378,7 +2470,8 @@
|
||||
spawned_process and
|
||||
not container and
|
||||
consider_network_tools_on_host and
|
||||
network_tool_procs
|
||||
network_tool_procs and
|
||||
not user_known_network_tool_activities
|
||||
output: >
|
||||
Network tool launched on host (user=%user.name command=%proc.cmdline parent_process=%proc.pname)
|
||||
priority: NOTICE
|
||||
@@ -2437,7 +2530,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
|
||||
@@ -2459,9 +2554,12 @@
|
||||
- macro: clear_data_procs
|
||||
condition: (proc.name in (data_remove_commands))
|
||||
|
||||
- macro: user_known_remove_data_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Remove Bulk Data from Disk
|
||||
desc: Detect process running to clear bulk data from disk
|
||||
condition: spawned_process and clear_data_procs
|
||||
condition: spawned_process and clear_data_procs and not user_known_remove_data_activities
|
||||
output: >
|
||||
Bulk data has been removed from disk (user=%user.name command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
||||
priority:
|
||||
@@ -2500,7 +2598,7 @@
|
||||
- rule: Delete Bash History
|
||||
desc: Detect bash history deletion
|
||||
condition: >
|
||||
((spawned_process and proc.name in (shred, rm, mv) and proc.args contains "bash_history") or
|
||||
((spawned_process and proc.name in (shred, rm, mv) and proc.args contains "bash_history") or
|
||||
(open_write and fd.name contains "bash_history" and evt.arg.flags contains "O_TRUNC"))
|
||||
output: >
|
||||
Shell history had been deleted or renamed (user=%user.name type=%evt.type command=%proc.cmdline fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info)
|
||||
@@ -2514,6 +2612,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 +2627,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)
|
||||
@@ -2537,14 +2642,17 @@
|
||||
- macro: consider_hidden_file_creation
|
||||
condition: (never_true)
|
||||
|
||||
- macro: user_known_create_hidden_file_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Create Hidden Files or Directories
|
||||
desc: Detect hidden files or directories created
|
||||
condition: >
|
||||
(consider_hidden_file_creation and (
|
||||
(modify and evt.arg.newpath contains "/.") or
|
||||
(mkdir and evt.arg.path contains "/.") or
|
||||
(open_write and evt.arg.flags contains "O_CREAT" and fd.name contains "/." and not fd.name pmatch (exclude_hidden_directories)))
|
||||
)
|
||||
((modify and evt.arg.newpath contains "/.") or
|
||||
(mkdir and evt.arg.path contains "/.") or
|
||||
(open_write and evt.arg.flags contains "O_CREAT" and fd.name contains "/." and not fd.name pmatch (exclude_hidden_directories))) and
|
||||
consider_hidden_file_creation and
|
||||
not user_known_create_hidden_file_activities
|
||||
output: >
|
||||
Hidden file or directory created (user=%user.name command=%proc.cmdline
|
||||
file=%fd.name newpath=%evt.arg.newpath container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
@@ -2556,7 +2664,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 +2795,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]
|
||||
@@ -2712,7 +2825,7 @@
|
||||
output: Packet socket was created in a container (user=%user.name command=%proc.cmdline socket_info=%evt.args container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
priority: NOTICE
|
||||
tags: [network, mitre_discovery]
|
||||
|
||||
|
||||
# Change to (always_true) to enable rule 'Network connection outside local subnet'
|
||||
- macro: enabled_rule_network_only_subnet
|
||||
condition: (never_true)
|
||||
@@ -2728,7 +2841,7 @@
|
||||
- macro: network_local_subnet
|
||||
condition: >
|
||||
fd.rnet in (rfc_1918_addresses) or
|
||||
fd.ip = "0.0.0.0" or
|
||||
fd.ip = "0.0.0.0" or
|
||||
fd.net = "127.0.0.0/8"
|
||||
|
||||
# # How to test:
|
||||
@@ -2788,18 +2901,67 @@
|
||||
not fd.sport in (authorized_server_port)
|
||||
output: >
|
||||
Network connection outside authorized port and binary
|
||||
(command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id
|
||||
(command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id
|
||||
image=%container.image.repository)
|
||||
priority: WARNING
|
||||
tags: [network]
|
||||
|
||||
- macro: user_known_stand_streams_redirect_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Redirect STDOUT/STDIN to Network Connection in Container
|
||||
desc: Detect redirecting stdout/stdin to network connection in container (potential reverse shell).
|
||||
condition: evt.type=dup and evt.dir=> and container and fd.num in (0, 1, 2) and fd.type in ("ipv4", "ipv6")
|
||||
condition: evt.type=dup and evt.dir=> and container and fd.num in (0, 1, 2) and fd.type in ("ipv4", "ipv6") and not user_known_stand_streams_redirect_activities
|
||||
output: >
|
||||
Redirect stdout/stdin to network connection (user=%user.name %container.info process=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository fd.name=%fd.name fd.num=%fd.num fd.type=%fd.type fd.sip=%fd.sip)
|
||||
priority: WARNING
|
||||
|
||||
# The two Container Drift rules below will fire when a new executable is created in a container.
|
||||
# There are two ways to create executables - file is created with execution permissions or permissions change of existing file.
|
||||
# We will use a new sysdig filter, is_open_exec, to find all files creations with execution permission, and will trace all chmods in a container.
|
||||
# The use case we are targeting here is an attempt to execute code that was not shipped as part of a container (drift) -
|
||||
# an activity that might be malicious or non-compliant.
|
||||
# Two things to pay attention to:
|
||||
# 1) In most cases, 'docker cp' will not be identified, but the assumption is that if an attacker gained access to the container runtime daemon, they are already privileged
|
||||
# 2) Drift rules will be noisy in environments in which containers are built (e.g. docker build)
|
||||
# These two rules are not enabled by default. Use `never_true` in macro condition to enable them.
|
||||
|
||||
- macro: user_known_container_drift_activities
|
||||
condition: (always_true)
|
||||
|
||||
- rule: Container Drift Detected (chmod)
|
||||
desc: New executable created in a container due to chmod
|
||||
condition: >
|
||||
chmod and
|
||||
consider_all_chmods and
|
||||
container and
|
||||
not runc_writing_exec_fifo and
|
||||
not runc_writing_var_lib_docker and
|
||||
not user_known_container_drift_activities and
|
||||
evt.rawres>=0 and
|
||||
((evt.arg.mode contains "S_IXUSR") or
|
||||
(evt.arg.mode contains "S_IXGRP") or
|
||||
(evt.arg.mode contains "S_IXOTH"))
|
||||
output: Drift detected (chmod), new executable created in a container (user=%user.name command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type)
|
||||
priority: ERROR
|
||||
|
||||
# ****************************************************************************
|
||||
# * "Container Drift Detected (open+create)" requires FALCO_ENGINE_VERSION 6 *
|
||||
# ****************************************************************************
|
||||
- rule: Container Drift Detected (open+create)
|
||||
desc: New executable created in a container due to open+create
|
||||
condition: >
|
||||
evt.type in (open,openat,creat) and
|
||||
evt.is_open_exec=true and
|
||||
container and
|
||||
not runc_writing_exec_fifo and
|
||||
not runc_writing_var_lib_docker and
|
||||
not user_known_container_drift_activities and
|
||||
evt.rawres>=0
|
||||
output: Drift detected (open+create), new executable created in a container (user=%user.name command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type)
|
||||
priority: ERROR
|
||||
|
||||
|
||||
# Application rules have moved to application_rules.yaml. Please look
|
||||
# there if you want to enable them by adding to
|
||||
# falco_rules.local.yaml.
|
||||
|
||||
@@ -40,8 +40,15 @@
|
||||
|
||||
# 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", "kube-apiserver-healthcheck",
|
||||
"kubernetes-admin",
|
||||
vertical_pod_autoscaler_users,
|
||||
]
|
||||
|
||||
- rule: Disallowed K8s User
|
||||
desc: Detect any k8s operation by users outside of an allowed set of users.
|
||||
@@ -149,10 +156,13 @@
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- macro: user_known_node_port_service
|
||||
condition: (k8s_audit_never_true)
|
||||
|
||||
- rule: Create NodePort Service
|
||||
desc: >
|
||||
Detect an attempt to start a service with a NodePort service type
|
||||
condition: kevt and service and kcreate and ka.req.service.type=NodePort
|
||||
condition: kevt and service and kcreate and ka.req.service.type=NodePort and not user_known_node_port_service
|
||||
output: NodePort Service Created (user=%ka.user.name service=%ka.target.name ns=%ka.target.namespace ports=%ka.req.service.ports)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
@@ -180,7 +190,7 @@
|
||||
- rule: Anonymous Request Allowed
|
||||
desc: >
|
||||
Detect any request made by the anonymous user that was allowed
|
||||
condition: kevt and ka.user.name=system:anonymous and ka.auth.decision!=reject and not health_endpoint
|
||||
condition: kevt and ka.user.name=system:anonymous and ka.auth.decision="allow" and not health_endpoint
|
||||
output: Request by anonymous user allowed (user=%ka.user.name verb=%ka.verb uri=%ka.uri reason=%ka.auth.reason))
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
@@ -195,15 +205,31 @@
|
||||
# attach request was created privileged or not. For now, we have a
|
||||
# less severe rule that detects attaches/execs to any pod.
|
||||
|
||||
- macro: user_known_exec_pod_activities
|
||||
condition: (k8s_audit_never_true)
|
||||
|
||||
- rule: Attach/Exec Pod
|
||||
desc: >
|
||||
Detect any attempt to attach/exec to a pod
|
||||
condition: kevt_started and pod_subresource and kcreate and ka.target.subresource in (exec,attach)
|
||||
condition: kevt_started and pod_subresource and kcreate and ka.target.subresource in (exec,attach) and not user_known_exec_pod_activities
|
||||
output: Attach/Exec to pod (user=%ka.user.name pod=%ka.target.name ns=%ka.target.namespace action=%ka.target.subresource command=%ka.uri.param[command])
|
||||
priority: NOTICE
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- macro: user_known_pod_debug_activities
|
||||
condition: (k8s_audit_never_true)
|
||||
|
||||
# Only works when feature gate EphemeralContainers is enabled
|
||||
- rule: EphemeralContainers Created
|
||||
desc: >
|
||||
Detect any ephemeral container created
|
||||
condition: kevt and pod_subresource and kmodify and ka.target.subresource in (ephemeralcontainers) and not user_known_pod_debug_activities
|
||||
output: Ephemeral container is created in pod (user=%ka.user.name pod=%ka.target.name ns=%ka.target.namespace ephemeral_container_name=%jevt.value[/requestObject/ephemeralContainers/0/name] ephemeral_container_image=%jevt.value[/requestObject/ephemeralContainers/0/image])
|
||||
priority: NOTICE
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# In a local/user rules fie, you can append to this list to add additional allowed namespaces
|
||||
- list: allowed_namespaces
|
||||
items: [kube-system, kube-public, default]
|
||||
@@ -216,19 +242,35 @@
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- list: user_trusted_image_list
|
||||
items: []
|
||||
|
||||
- list: k8s_image_list
|
||||
items: [k8s.gcr.io/kube-apiserver, kope/kube-apiserver-healthcheck]
|
||||
|
||||
- macro: trusted_pod
|
||||
condition: (ka.req.pod.containers.image.repository in (user_trusted_image_list) or
|
||||
ka.req.pod.containers.image.repository in (k8s_image_list))
|
||||
|
||||
# Detect any new pod created in the kube-system namespace
|
||||
- rule: Pod Created in Kube Namespace
|
||||
desc: Detect any attempt to create a pod in the kube-system or kube-public namespaces
|
||||
condition: kevt and pod and kcreate and ka.target.namespace in (kube-system, kube-public)
|
||||
condition: kevt and pod and kcreate and ka.target.namespace in (kube-system, kube-public) and not trusted_pod
|
||||
output: Pod created in kube namespace (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace images=%ka.req.pod.containers.image)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- list: user_known_sa_list
|
||||
items: []
|
||||
|
||||
- macro: trusted_sa
|
||||
condition: (ka.target.name in (user_known_sa_list))
|
||||
|
||||
# Detect creating a service account in the kube-system/kube-public namespace
|
||||
- rule: Service Account Created in Kube Namespace
|
||||
desc: Detect any attempt to create a serviceaccount in the kube-system or kube-public namespaces
|
||||
condition: kevt and serviceaccount and kcreate and ka.target.namespace in (kube-system, kube-public) and response_successful
|
||||
condition: kevt and serviceaccount and kcreate and ka.target.namespace in (kube-system, kube-public) and response_successful and not trusted_sa
|
||||
output: Service account created in kube namespace (user=%ka.user.name serviceaccount=%ka.target.name ns=%ka.target.namespace)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
@@ -470,8 +512,6 @@
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
|
||||
|
||||
- macro: ingress
|
||||
condition: ka.target.resource=ingresses
|
||||
|
||||
@@ -507,8 +547,6 @@
|
||||
priority: WARNING
|
||||
tags: [k8s, network]
|
||||
|
||||
|
||||
|
||||
- macro: node
|
||||
condition: ka.target.resource=nodes
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -412,26 +473,91 @@ else
|
||||
FALCO_DRIVER_CURL_OPTIONS=-fsS
|
||||
fi
|
||||
|
||||
MAX_RMMOD_WAIT=60
|
||||
if [[ $# -ge 1 ]]; then
|
||||
MAX_RMMOD_WAIT=$1
|
||||
if [[ -z "$MAX_RMMOD_WAIT" ]]; then
|
||||
MAX_RMMOD_WAIT=60
|
||||
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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
add_subdirectory(trace_files)
|
||||
|
||||
add_custom_target(test-trace-files ALL)
|
||||
add_dependencies(test-trace-files trace-files-base-scap trace-files-psp trace-files-k8s-audit)
|
||||
111
test/README.md
111
test/README.md
@@ -1,6 +1,115 @@
|
||||
# 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.in)
|
||||
- [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
|
||||
|
||||
This step assumes you already built Falco.
|
||||
|
||||
Note that the tests are intended to be run against a [release build](https://falco.org/docs/source/#specify-the-build-type) of Falco, at the moment.
|
||||
|
||||
Also, it assumes you prepared [falco_traces](#falco_traces) (see the section below) and you already run the following command from the build directory:
|
||||
|
||||
```console
|
||||
make test-trace-files
|
||||
```
|
||||
|
||||
It prepares the fixtures (`json` and `scap` files) needed by the integration tests.
|
||||
|
||||
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 for a given test suite, execute:
|
||||
|
||||
```console
|
||||
avocado variants --mux-yaml falco_tests.yaml
|
||||
```
|
||||
|
||||
### falco_traces
|
||||
|
||||
The `falco_traces.yaml` test suite gets generated through the `falco_traces.yaml.in` file and some fixtures (`scap` files) downloaded from the web at execution time.
|
||||
|
||||
1. Ensure you have `unzip` and `xargs` utilities
|
||||
2. Prepare the test suite with the following command:
|
||||
|
||||
```console
|
||||
bash run_regression_tests.sh -p -v
|
||||
```
|
||||
|
||||
### falco_tests_package
|
||||
|
||||
The `falco_tests_package.yaml` test suite requires some additional setup steps to be succesfully run on your local machine.
|
||||
|
||||
In particular, it requires some runners (ie., docker images) to be already built and present into your local machine.
|
||||
|
||||
1. Ensure you have `docker` up and running
|
||||
2. Ensure you build Falco (with bundled deps)
|
||||
|
||||
The recommended way of doing it by running the `falcosecurity/falco-builder` docker image from the project root:
|
||||
|
||||
```console
|
||||
docker run -v $PWD/..:/source -v $PWD/mybuild:/build falcosecurity/falco-builder cmake
|
||||
docker run -v $PWD/..:/source -v $PWD/mybuild:/build falcosecurity/falco-builder falco
|
||||
```
|
||||
|
||||
3. Ensure you build the Falco packages from the Falco above:
|
||||
|
||||
```console
|
||||
docker run -v $PWD/..:/source -v $PWD/mybuild:/build falcosecurity/falco-builder package
|
||||
```
|
||||
|
||||
4. Ensure you build the runners:
|
||||
|
||||
```console
|
||||
FALCO_VERSION=$(./mybuild/release/userspace/falco/falco --version | head -n 1 | cut -d' ' -f3 | tr -d '\r')
|
||||
mkdir -p /tmp/runners-rootfs
|
||||
cp -R ./test/rules /tmp/runners-rootfs
|
||||
cp -R ./test/trace_files /tmp/runners-rootfs
|
||||
cp ./mybuild/release/falco-${FALCO_VERSION}-x86_64.{deb,rpm,tar.gz} /tmp/runners-rootfs
|
||||
docker build -f docker/tester/root/runners/deb.Dockerfile --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco:test-deb /tmp/runners-rootfs
|
||||
docker build -f docker/tester/root/runners/rpm.Dockerfile --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco:test-rpm /tmp/runners-rootfs
|
||||
docker build -f docker/tester/root/runners/tar.gz.Dockerfile --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco:test-tar.gz /tmp/runners-rootfs
|
||||
```
|
||||
|
||||
5. Run the `falco_tests_package.yaml` test suite from the `test` directory
|
||||
|
||||
```console
|
||||
cd test
|
||||
BUILD_DIR="../mybuild" avocado run --mux-yaml falco_tests_package.yaml --job-results-dir /tmp/job-results -- falco_test.py
|
||||
```
|
||||
|
||||
### Execute all the test suites
|
||||
|
||||
In case you want to run all the test suites at once, you can directly use the `run_regression_tests.sh` runner script.
|
||||
|
||||
```console
|
||||
cd test
|
||||
./run_regression_tests.sh -v
|
||||
```
|
||||
|
||||
Just make sure you followed all the previous setup steps.
|
||||
|
||||
38
test/confs/grpc_unix_socket.yaml
Normal file
38
test/confs/grpc_unix_socket.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# 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.
|
||||
log_stderr: false
|
||||
log_syslog: false
|
||||
|
||||
# Where security notifications should go.
|
||||
stdout_output:
|
||||
enabled: false
|
||||
|
||||
# gRPC server using an unix socket.
|
||||
grpc:
|
||||
enabled: true
|
||||
bind_address: "unix:///tmp/falco/falco.sock"
|
||||
threadiness: 8
|
||||
|
||||
grpc_output:
|
||||
enabled: true
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ stdout_output:
|
||||
webserver:
|
||||
enabled: true
|
||||
listen_port: 8765
|
||||
k8s_audit_endpoint: /k8s_audit
|
||||
k8s_audit_endpoint: /k8s-audit
|
||||
ssl_enabled: false
|
||||
ssl_certificate: /etc/falco/falco.pem
|
||||
|
||||
|
||||
48
test/driver-loader/run_test.sh
Executable file
48
test/driver-loader/run_test.sh
Executable 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
|
||||
32
test/driver-loader/runner/Dockerfile
Normal file
32
test/driver-loader/runner/Dockerfile
Normal file
@@ -0,0 +1,32 @@
|
||||
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 \
|
||||
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
136
test/driver-loader/runner/test.sh
Executable 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"
|
||||
@@ -28,6 +28,8 @@ import urllib.request
|
||||
from avocado import Test
|
||||
from avocado import main
|
||||
from avocado.utils import process
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import PatternMatchingEventHandler
|
||||
|
||||
class FalcoTest(Test):
|
||||
|
||||
@@ -195,6 +197,24 @@ class FalcoTest(Test):
|
||||
os.makedirs(filedir)
|
||||
self.outputs = outputs
|
||||
|
||||
self.grpcurl_res = None
|
||||
self.grpc_observer = None
|
||||
self.grpc_address = self.params.get('address', 'grpc/*', default='/var/run/falco.sock')
|
||||
if self.grpc_address.startswith("unix://"):
|
||||
self.is_grpc_using_unix_socket = True
|
||||
self.grpc_address = self.grpc_address[len("unix://"):]
|
||||
else:
|
||||
self.is_grpc_using_unix_socket = False
|
||||
self.grpc_proto = self.params.get('proto', 'grpc/*', default='')
|
||||
self.grpc_service = self.params.get('service', 'grpc/*', default='')
|
||||
self.grpc_method = self.params.get('method', 'grpc/*', default='')
|
||||
self.grpc_results = self.params.get('results', 'grpc/*', default='')
|
||||
if self.grpc_results == '':
|
||||
self.grpc_results = []
|
||||
else:
|
||||
if type(self.grpc_results) == str:
|
||||
self.grpc_results = [self.grpc_results]
|
||||
|
||||
self.disable_tags = self.params.get('disable_tags', '*', default='')
|
||||
|
||||
if self.disable_tags == '':
|
||||
@@ -411,12 +431,54 @@ 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)
|
||||
|
||||
def init_grpc_handler(self):
|
||||
self.grpcurl_res = None
|
||||
if len(self.grpc_results) > 0:
|
||||
if not self.is_grpc_using_unix_socket:
|
||||
self.fail("This test suite supports gRPC with unix socket only")
|
||||
|
||||
cmdline = "grpcurl -import-path ../userspace/falco " \
|
||||
"-proto {} -plaintext -unix {} " \
|
||||
"{}/{}".format(self.grpc_proto, self.grpc_address, self.grpc_service, self.grpc_method)
|
||||
that = self
|
||||
class GRPCUnixSocketEventHandler(PatternMatchingEventHandler):
|
||||
def on_created(self, event):
|
||||
# that.log.info("EVENT: {}", event)
|
||||
that.grpcurl_res = process.run(cmdline)
|
||||
|
||||
path = os.path.dirname(self.grpc_address)
|
||||
process.run("mkdir -p {}".format(path))
|
||||
event_handler = GRPCUnixSocketEventHandler(patterns=['*'],
|
||||
ignore_directories=True)
|
||||
self.grpc_observer = Observer()
|
||||
self.grpc_observer.schedule(event_handler, path, recursive=False)
|
||||
self.grpc_observer.start()
|
||||
|
||||
def check_grpc(self):
|
||||
if self.grpc_observer is not None:
|
||||
self.grpc_observer.stop()
|
||||
self.grpc_observer = None
|
||||
if self.grpcurl_res is None:
|
||||
self.fail("gRPC responses not found")
|
||||
|
||||
for exp_result in self.grpc_results:
|
||||
found = False
|
||||
for line in self.grpcurl_res.stdout.decode("utf-8").splitlines():
|
||||
match = re.search(exp_result, line)
|
||||
|
||||
if match is not None:
|
||||
found = True
|
||||
|
||||
if found == False:
|
||||
self.fail("Could not find a line '{}' in gRPC responses".format(exp_result))
|
||||
|
||||
|
||||
def test(self):
|
||||
self.log.info("Trace file %s", self.trace_file)
|
||||
|
||||
@@ -424,6 +486,8 @@ class FalcoTest(Test):
|
||||
|
||||
self.possibly_copy_driver()
|
||||
|
||||
self.init_grpc_handler()
|
||||
|
||||
if self.package != 'None':
|
||||
# This sets falco_binary_path as a side-effect.
|
||||
self.install_package()
|
||||
@@ -526,6 +590,7 @@ class FalcoTest(Test):
|
||||
self.check_detections_by_rule(res)
|
||||
self.check_json_output(res)
|
||||
self.check_outputs()
|
||||
self.check_grpc()
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -672,6 +672,22 @@ trace_files: !mux
|
||||
outputs:
|
||||
- /tmp/falco_outputs/program_output.txt: Warning An open was seen
|
||||
|
||||
grpc_unix_socket_outputs:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/single_rule.yaml
|
||||
conf_file: confs/grpc_unix_socket.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
run_duration: 5
|
||||
grpc:
|
||||
address: unix:///tmp/falco/falco.sock
|
||||
proto: outputs.proto
|
||||
service: falco.outputs.service
|
||||
method: get
|
||||
results:
|
||||
- "Warning An open was seen"
|
||||
|
||||
detect_counts:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
|
||||
@@ -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");
|
||||
|
||||
13
test/requirements.txt
Normal file
13
test/requirements.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
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
|
||||
pathtools==0.1.2
|
||||
pbr==5.4.5
|
||||
PyYAML==5.3.1
|
||||
requests==2.23.0
|
||||
six==1.14.0
|
||||
stevedore==1.32.0
|
||||
urllib3==1.25.9
|
||||
watchdog==0.10.2
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
# Copyright (C) 2020 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -18,45 +18,46 @@
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT=$(readlink -f $0)
|
||||
SCRIPTDIR=$(dirname $SCRIPT)
|
||||
BUILD_DIR=$1
|
||||
BRANCH=${2:-none}
|
||||
|
||||
TRACE_DIR=$BUILD_DIR/test
|
||||
|
||||
mkdir -p $TRACE_DIR
|
||||
SCRIPTDIR=$(dirname "$SCRIPT")
|
||||
|
||||
function download_trace_files() {
|
||||
echo "branch=$BRANCH"
|
||||
for TRACE in traces-positive traces-negative traces-info ; do
|
||||
if [ ! -e $TRACE_DIR/$TRACE ]; then
|
||||
if [ $BRANCH != "none" ]; then
|
||||
curl -fso $TRACE_DIR/$TRACE.zip https://s3.amazonaws.com/download.draios.com/falco-tests/$TRACE-$BRANCH.zip
|
||||
else
|
||||
curl -fso $TRACE_DIR/$TRACE.zip https://s3.amazonaws.com/download.draios.com/falco-tests/$TRACE.zip
|
||||
fi
|
||||
unzip -d $TRACE_DIR $TRACE_DIR/$TRACE.zip
|
||||
rm -rf $TRACE_DIR/$TRACE.zip
|
||||
fi
|
||||
if [ ! -e "$TRACE_DIR/$TRACE" ]; then
|
||||
if [ "$OPT_BRANCH" != "none" ]; then
|
||||
curl -fso "$TRACE_DIR/$TRACE.zip" https://s3.amazonaws.com/download.draios.com/falco-tests/$TRACE-$OPT_BRANCH.zip
|
||||
else
|
||||
curl -fso "$TRACE_DIR/$TRACE.zip" https://s3.amazonaws.com/download.draios.com/falco-tests/$TRACE.zip
|
||||
fi
|
||||
unzip -d "$TRACE_DIR" "$TRACE_DIR/$TRACE.zip"
|
||||
rm -rf "$TRACE_DIR/$TRACE.zip"
|
||||
else
|
||||
if ${OPT_VERBOSE}; then
|
||||
echo "Trace directory $TRACE_DIR/$TRACE already exist: skipping"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function prepare_multiplex_fileset() {
|
||||
|
||||
dir=$1
|
||||
detect=$2
|
||||
|
||||
for trace in $TRACE_DIR/$dir/*.scap ; do
|
||||
[ -e "$trace" ] || continue
|
||||
NAME=`basename $trace .scap`
|
||||
for trace in "$TRACE_DIR/$dir"/*.scap ; do
|
||||
[ -e "$trace" ] || continue
|
||||
NAME=$(basename "$trace" .scap)
|
||||
|
||||
# falco_traces.yaml might already have an entry for this trace
|
||||
# file, with specific detection levels and counts. If so, skip
|
||||
# it. Otherwise, add a generic entry showing whether or not to
|
||||
# detect anything.
|
||||
grep -q "$NAME:" $SCRIPTDIR/falco_traces.yaml && continue
|
||||
# falco_traces.yaml might already have an entry for this trace file, with specific detection levels and counts.
|
||||
# If so, skip it.
|
||||
# Otherwise, add a generic entry showing whether or not to detect anything.
|
||||
if grep -q "$NAME:" "$SCRIPTDIR/falco_traces.yaml"; then
|
||||
if ${OPT_VERBOSE}; then
|
||||
echo "Entry $NAME already exist: skipping"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
cat << EOF >> "$SCRIPTDIR/falco_traces.yaml"
|
||||
|
||||
cat << EOF >> $SCRIPTDIR/falco_traces.yaml
|
||||
$NAME:
|
||||
detect: $detect
|
||||
detect_level: WARNING
|
||||
@@ -66,41 +67,96 @@ EOF
|
||||
}
|
||||
|
||||
function prepare_multiplex_file() {
|
||||
cp $SCRIPTDIR/falco_traces.yaml.in $SCRIPTDIR/falco_traces.yaml
|
||||
/bin/cp -f "$SCRIPTDIR/falco_traces.yaml.in" "$SCRIPTDIR/falco_traces.yaml"
|
||||
|
||||
prepare_multiplex_fileset traces-positive True
|
||||
prepare_multiplex_fileset traces-negative False
|
||||
prepare_multiplex_fileset traces-info True
|
||||
|
||||
echo "Contents of $SCRIPTDIR/falco_traces.yaml:"
|
||||
cat $SCRIPTDIR/falco_traces.yaml
|
||||
if ${OPT_VERBOSE}; then
|
||||
echo "Contents of $SCRIPTDIR/falco_traces.yaml"
|
||||
cat "$SCRIPTDIR/falco_traces.yaml"
|
||||
fi
|
||||
}
|
||||
|
||||
function print_test_failure_details() {
|
||||
echo "Showing full job logs for any tests that failed:"
|
||||
jq '.tests[] | select(.status != "PASS") | .logfile' $SCRIPTDIR/job-results/latest/results.json | xargs cat
|
||||
jq '.tests[] | select(.status != "PASS") | .logfile' "$SCRIPTDIR/job-results/latest/results.json" | xargs cat
|
||||
}
|
||||
|
||||
function run_tests() {
|
||||
rm -rf /tmp/falco_outputs
|
||||
mkdir /tmp/falco_outputs
|
||||
# If we got this far, we can undo set -e, as we're watching the
|
||||
# return status when running avocado.
|
||||
# If we got this far, we can undo set -e,
|
||||
# as we're watching the return status when running avocado.
|
||||
set +e
|
||||
TEST_RC=0
|
||||
for mult in $SCRIPTDIR/falco_traces.yaml $SCRIPTDIR/falco_tests.yaml $SCRIPTDIR/falco_tests_package.yaml $SCRIPTDIR/falco_k8s_audit_tests.yaml $SCRIPTDIR/falco_tests_psp.yaml; do
|
||||
CMD="avocado run --mux-yaml $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
|
||||
echo "Running: $CMD"
|
||||
BUILD_DIR=${BUILD_DIR} $CMD
|
||||
RC=$?
|
||||
TEST_RC=$((TEST_RC+$RC))
|
||||
if [ $RC -ne 0 ]; then
|
||||
print_test_failure_details
|
||||
fi
|
||||
CMD="avocado run --mux-yaml $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
|
||||
echo "Running $CMD"
|
||||
BUILD_DIR=${OPT_BUILD_DIR} $CMD
|
||||
RC=$?
|
||||
TEST_RC=$((TEST_RC+RC))
|
||||
if [ $RC -ne 0 ]; then
|
||||
print_test_failure_details
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
OPT_ONLY_PREPARE="false"
|
||||
OPT_VERBOSE="false"
|
||||
OPT_BUILD_DIR="$(dirname "$SCRIPTDIR")/build"
|
||||
OPT_BRANCH="none"
|
||||
while getopts ':p :h :v :b: :d:' 'OPTKEY'; do
|
||||
case ${OPTKEY} in
|
||||
'p')
|
||||
OPT_ONLY_PREPARE="true"
|
||||
;;
|
||||
'h')
|
||||
/bin/bash usage
|
||||
exit 0
|
||||
;;
|
||||
'v')
|
||||
OPT_VERBOSE="true"
|
||||
;;
|
||||
'd')
|
||||
OPT_BUILD_DIR=${OPTARG}
|
||||
;;
|
||||
'b')
|
||||
OPT_BRANCH=${OPTARG}
|
||||
;;
|
||||
'?')
|
||||
echo "Invalid option: ${OPTARG}." >&2
|
||||
/bin/bash usage
|
||||
exit 1
|
||||
;;
|
||||
':')
|
||||
echo "Missing argument for option: ${OPTARG}." >&2
|
||||
/bin/bash usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Unimplemented option: ${OPTKEY}." >&2
|
||||
/bin/bash usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
TRACE_DIR=$OPT_BUILD_DIR/test
|
||||
|
||||
if ${OPT_VERBOSE}; then
|
||||
echo "Build directory = $OPT_BUILD_DIR"
|
||||
echo "Trace directory = $TRACE_DIR"
|
||||
echo "Custom branch = $OPT_BRANCH"
|
||||
fi
|
||||
|
||||
mkdir -p "$TRACE_DIR"
|
||||
|
||||
download_trace_files
|
||||
prepare_multiplex_file
|
||||
run_tests
|
||||
exit $TEST_RC
|
||||
|
||||
if ! ${OPT_ONLY_PREPARE}; then
|
||||
run_tests
|
||||
exit $TEST_RC
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
add_subdirectory(k8s_audit)
|
||||
add_subdirectory(psp)
|
||||
|
||||
# Note: list of traces is created at cmake time, not build time
|
||||
file(GLOB test_trace_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.scap")
|
||||
@@ -11,4 +12,8 @@ foreach(trace_file_path ${test_trace_files})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${trace_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
DEPENDS ${trace_file_path})
|
||||
list(APPEND BASE_SCAP_TRACE_FILES_TARGETS test-trace-${trace_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(trace-files-base-scap ALL)
|
||||
add_dependencies(trace-files-base-scap ${BASE_SCAP_TRACE_FILES_TARGETS})
|
||||
@@ -9,4 +9,8 @@ foreach(trace_file_path ${test_trace_files})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${trace_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
DEPENDS ${trace_file_path})
|
||||
list(APPEND K8S_AUDIT_TRACE_FILES_TARGETS test-trace-${trace_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(trace-files-k8s-audit ALL)
|
||||
add_dependencies(trace-files-k8s-audit ${K8S_AUDIT_TRACE_FILES_TARGETS})
|
||||
@@ -10,4 +10,8 @@ foreach(trace_file_path ${test_trace_files})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${trace_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
DEPENDS ${trace_file_path})
|
||||
list(APPEND PSP_TRACE_FILES_TARGETS test-trace-${trace_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(trace-files-psp ALL)
|
||||
add_dependencies(trace-files-psp ${PSP_TRACE_FILES_TARGETS})
|
||||
32
test/usage
Executable file
32
test/usage
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/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.
|
||||
#
|
||||
cat <<EOF
|
||||
Hello, this is Falco integration tests runner.
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
bash run_regression_tests.sh [-h] [-v] [-p] [-d=<build directory>] [-b=<custom branch>]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-h Display usage instructions
|
||||
-v Verbose output
|
||||
-p Prepare the falco_traces integration test suite
|
||||
-b=CUSTOM_BRANCH Specify a custom branch for downloading falco_traces fixtures (defaults to "none")
|
||||
-d=BUILD_DIRECTORY Specify the build directory where Falco has been built (defaults to $SCRIPTDIR/../build)
|
||||
EOF
|
||||
@@ -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()
|
||||
|
||||
53
tests/engine/test_falco_utils.cpp
Normal file
53
tests/engine/test_falco_utils.cpp
Normal 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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -21,7 +21,11 @@ set(FALCO_ENGINE_SOURCE_FILES
|
||||
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)
|
||||
|
||||
if(USE_BUNDLED_DEPS)
|
||||
add_dependencies(falco_engine libyaml)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
falco_engine
|
||||
@@ -30,6 +34,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"
|
||||
|
||||
@@ -16,9 +16,9 @@ limitations under the License.
|
||||
|
||||
// The version of rules/filter fields/etc supported by this falco
|
||||
// engine.
|
||||
#define FALCO_ENGINE_VERSION (5)
|
||||
#define FALCO_ENGINE_VERSION (6)
|
||||
|
||||
// This is the result of running "falco --list -N | sha256sum" and
|
||||
// represents the fields supported by this version of falco. It's used
|
||||
// at build time to detect a changed set of fields.
|
||||
#define FALCO_FIELDS_CHECKSUM "ca9e75fa41fe4480cdfad8cf275cdbbc334e656569f070c066d87cbd2955c1ae"
|
||||
#define FALCO_FIELDS_CHECKSUM "2f324e2e66d4b423f53600e7e0fcf2f0ff72e4a87755c490f2ae8f310aba9386"
|
||||
|
||||
@@ -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,34 @@ std::string wrap_text(const std::string &str, uint32_t initial_pos, uint32_t ind
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
uint32_t hardware_concurrency()
|
||||
{
|
||||
auto hc = std::thread::hardware_concurrency();
|
||||
return hc ? hc : 1;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -17,7 +17,12 @@ limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <nonstd/string_view.hpp>
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -27,8 +32,16 @@ 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);
|
||||
|
||||
uint32_t hardware_concurrency();
|
||||
|
||||
namespace network
|
||||
{
|
||||
static const std::string UNIX_SCHEME("unix://");
|
||||
bool is_unix_scheme(nonstd::string_view url);
|
||||
} // namespace network
|
||||
} // namespace utils
|
||||
|
||||
} // namespace falco
|
||||
|
||||
@@ -45,7 +45,7 @@ const json &json_event::jevt()
|
||||
return m_jevt;
|
||||
}
|
||||
|
||||
uint64_t json_event::get_ts()
|
||||
uint64_t json_event::get_ts() const
|
||||
{
|
||||
return m_event_ts;
|
||||
}
|
||||
|
||||
@@ -38,14 +38,14 @@ public:
|
||||
void set_jevt(nlohmann::json &evt, uint64_t ts);
|
||||
const nlohmann::json &jevt();
|
||||
|
||||
uint64_t get_ts();
|
||||
uint64_t get_ts() const;
|
||||
|
||||
inline uint16_t get_source()
|
||||
inline uint16_t get_source() const
|
||||
{
|
||||
return ESRC_K8S_AUDIT;
|
||||
}
|
||||
|
||||
inline uint16_t get_type()
|
||||
inline uint16_t get_type() const
|
||||
{
|
||||
// All k8s audit events have the single tag "1". - see falco_engine::process_k8s_audit_event
|
||||
return 1;
|
||||
|
||||
@@ -19,23 +19,24 @@ add_custom_command(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/output.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/output.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
|
||||
COMMENT "Generate gRPC version API"
|
||||
COMMENT "Generate gRPC API"
|
||||
# Falco gRPC Version API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMENT "Generate gRPC outputs API"
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/output.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/output.proto
|
||||
# Falco gRPC Outputs API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/output.proto
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(
|
||||
@@ -52,14 +53,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}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.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 +69,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 +85,6 @@ target_link_libraries(
|
||||
falco
|
||||
falco_engine
|
||||
sinsp
|
||||
falco_profiler
|
||||
"${GPR_LIB}"
|
||||
"${GRPC_LIB}"
|
||||
"${GRPCPP_LIB}"
|
||||
|
||||
@@ -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.
|
||||
@@ -20,6 +20,7 @@ limitations under the License.
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "falco_utils.h"
|
||||
|
||||
#include "configuration.h"
|
||||
#include "logger.h"
|
||||
@@ -32,7 +33,7 @@ falco_configuration::falco_configuration():
|
||||
m_time_format_iso_8601(false),
|
||||
m_webserver_enabled(false),
|
||||
m_webserver_listen_port(8765),
|
||||
m_webserver_k8s_audit_endpoint("/k8s_audit"),
|
||||
m_webserver_k8s_audit_endpoint("/k8s-audit"),
|
||||
m_webserver_ssl_enabled(false),
|
||||
m_config(NULL)
|
||||
{
|
||||
@@ -148,11 +149,12 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
||||
|
||||
m_grpc_enabled = m_config->get_scalar<bool>("grpc", "enabled", false);
|
||||
m_grpc_bind_address = m_config->get_scalar<string>("grpc", "bind_address", "0.0.0.0:5060");
|
||||
m_grpc_threadiness = m_config->get_scalar<uint32_t>("grpc", "threadiness", 8); // todo > limit it to avoid overshubscription? std::thread::hardware_concurrency()
|
||||
m_grpc_threadiness = m_config->get_scalar<uint32_t>("grpc", "threadiness", 0);
|
||||
if(m_grpc_threadiness == 0)
|
||||
{
|
||||
throw logic_error("error reading config file (" + m_config_file +"): gRPC threadiness must be greater than 0");
|
||||
m_grpc_threadiness = falco::utils::hardware_concurrency();
|
||||
}
|
||||
// todo > else limit threadiness to avoid oversubscription?
|
||||
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");
|
||||
m_grpc_root_certs = m_config->get_scalar<string>("grpc", "root_certs", "/etc/falco/certs/ca.crt");
|
||||
@@ -170,9 +172,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);
|
||||
@@ -198,7 +200,7 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
||||
|
||||
m_webserver_enabled = m_config->get_scalar<bool>("webserver", "enabled", false);
|
||||
m_webserver_listen_port = m_config->get_scalar<uint32_t>("webserver", "listen_port", 8765);
|
||||
m_webserver_k8s_audit_endpoint = m_config->get_scalar<string>("webserver", "k8s_audit_endpoint", "/k8s_audit");
|
||||
m_webserver_k8s_audit_endpoint = m_config->get_scalar<string>("webserver", "k8s_audit_endpoint", "/k8s-audit");
|
||||
m_webserver_ssl_enabled = m_config->get_scalar<bool>("webserver", "ssl_enabled", false);
|
||||
m_webserver_ssl_certificate = m_config->get_scalar<string>("webserver", "ssl_certificate", "/etc/falco/falco.pem");
|
||||
|
||||
@@ -344,4 +346,4 @@ void falco_configuration::set_cmdline_option(const string &opt)
|
||||
{
|
||||
m_config->set_scalar(keyval.first, keyval.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -205,7 +206,7 @@ public:
|
||||
bool m_time_format_iso_8601;
|
||||
|
||||
bool m_grpc_enabled;
|
||||
int m_grpc_threadiness;
|
||||
uint32_t m_grpc_threadiness;
|
||||
std::string m_grpc_bind_address;
|
||||
std::string m_grpc_private_key;
|
||||
std::string m_grpc_cert_chain;
|
||||
|
||||
@@ -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;
|
||||
@@ -141,9 +140,9 @@ static void usage()
|
||||
" -P, --pidfile <pid_file> When run as a daemon, write pid to specified file\n"
|
||||
" -r <rules_file> Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml).\n"
|
||||
" Can be specified multiple times to read from multiple files/directories.\n"
|
||||
" -s <stats_file> If specified, write statistics related to falco's reading/processing of events\n"
|
||||
" to this file. (Only useful in live mode).\n"
|
||||
" --stats_interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n"
|
||||
" -s <stats_file> If specified, append statistics related to Falco's reading/processing of events\n"
|
||||
" to this file (only useful in live mode).\n"
|
||||
" --stats-interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n"
|
||||
" This uses signals, so don't recommend intervals below 200 ms.\n"
|
||||
" Defaults to 5000 (5 seconds).\n"
|
||||
" -S <len>, --snaplen <len>\n"
|
||||
@@ -159,6 +158,8 @@ static void usage()
|
||||
" This causes every single line emitted by falco to be flushed,\n"
|
||||
" which generates higher CPU usage but is useful when piping those outputs\n"
|
||||
" into another process or into a script.\n"
|
||||
" -u, --userspace Parse events from userspace.\n"
|
||||
" To be used in conjunction with the ptrace(2) based driver (pdig).\n"
|
||||
" -V, --validate <rules_file> Read the contents of the specified rules(s) file and exit.\n"
|
||||
" Can be specified multiple times to validate multiple files.\n"
|
||||
" -v Verbose output.\n"
|
||||
@@ -236,7 +237,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;
|
||||
@@ -445,6 +445,7 @@ int falco_init(int argc, char **argv)
|
||||
set<string> disable_sources;
|
||||
bool disable_syscall = false;
|
||||
bool disable_k8s_audit = false;
|
||||
bool userspace = false;
|
||||
|
||||
// Used for writing trace files
|
||||
int duration_seconds = 0;
|
||||
@@ -481,9 +482,10 @@ int falco_init(int argc, char **argv)
|
||||
{"print-base64", no_argument, 0, 'b'},
|
||||
{"print", required_argument, 0, 'p'},
|
||||
{"snaplen", required_argument, 0, 'S'},
|
||||
{"stats_interval", required_argument, 0},
|
||||
{"stats-interval", required_argument, 0},
|
||||
{"support", no_argument, 0},
|
||||
{"unbuffered", no_argument, 0, 'U'},
|
||||
{"userspace", no_argument, 0, 'u'},
|
||||
{"validate", required_argument, 0, 'V'},
|
||||
{"version", no_argument, 0, 0},
|
||||
{"writefile", required_argument, 0, 'w'},
|
||||
@@ -502,7 +504,7 @@ int falco_init(int argc, char **argv)
|
||||
// Parse the args
|
||||
//
|
||||
while((op = getopt_long(argc, argv,
|
||||
"hc:AbdD:e:F:ik:K:Ll:m:M:No:P:p:r:S:s:T:t:UvV:w:",
|
||||
"hc:AbdD:e:F:ik:K:Ll:m:M:No:P:p:r:S:s:T:t:UuvV:w:",
|
||||
long_options, &long_index)) != -1)
|
||||
{
|
||||
switch(op)
|
||||
@@ -609,6 +611,9 @@ int falco_init(int argc, char **argv)
|
||||
buffered_outputs = false;
|
||||
buffered_cmdline = true;
|
||||
break;
|
||||
case 'u':
|
||||
userspace = true;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
@@ -648,7 +653,7 @@ int falco_init(int argc, char **argv)
|
||||
list_flds_source = optarg;
|
||||
}
|
||||
}
|
||||
else if (string(long_options[long_index].name) == "stats_interval")
|
||||
else if (string(long_options[long_index].name) == "stats-interval")
|
||||
{
|
||||
stats_interval = atoi(optarg);
|
||||
}
|
||||
@@ -797,12 +802,16 @@ int falco_init(int argc, char **argv)
|
||||
falco_logger::set_time_format_iso_8601(config.m_time_format_iso_8601);
|
||||
|
||||
// log after config init because config determines where logs go
|
||||
falco_logger::log(LOG_INFO, "Falco version " + std::string(FALCO_VERSION) + " (driver version " + std::string(DRIVER_VERSION) + ")\n");
|
||||
falco_logger::log(LOG_INFO, "Falco initialized with configuration file " + conf_filename + "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
config.init(cmdline_options);
|
||||
falco_logger::set_time_format_iso_8601(config.m_time_format_iso_8601);
|
||||
|
||||
// log after config init because config determines where logs go
|
||||
falco_logger::log(LOG_INFO, "Falco version " + std::string(FALCO_VERSION) + " (driver version " + std::string(DRIVER_VERSION) + ")\n");
|
||||
falco_logger::log(LOG_INFO, "Falco initialized. No configuration file found, proceeding with defaults\n");
|
||||
}
|
||||
|
||||
@@ -1093,7 +1102,17 @@ int falco_init(int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
open_t open_cb = [](sinsp* inspector) {
|
||||
open_t open_cb = [&userspace](sinsp* inspector)
|
||||
{
|
||||
if(userspace)
|
||||
{
|
||||
// open_udig() is the underlying method used in the capture code to parse userspace events from the kernel.
|
||||
//
|
||||
// Falco uses a ptrace(2) based userspace implementation.
|
||||
// Regardless of the implementation, the underlying method remains the same.
|
||||
inspector->open_udig();
|
||||
return;
|
||||
}
|
||||
inspector->open();
|
||||
};
|
||||
open_t open_nodriver_cb = [](sinsp* inspector) {
|
||||
@@ -1118,11 +1137,17 @@ int falco_init(int argc, char **argv)
|
||||
}
|
||||
catch(sinsp_exception &e)
|
||||
{
|
||||
if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null"))
|
||||
// If syscall input source is enabled and not through userspace instrumentation
|
||||
if (!disable_syscall && !userspace)
|
||||
{
|
||||
falco_logger::log(LOG_ERR, "Unable to load the driver. Exiting.\n");
|
||||
// Try to insert the Falco kernel module
|
||||
if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null"))
|
||||
{
|
||||
falco_logger::log(LOG_ERR, "Unable to load the driver. Exiting.\n");
|
||||
}
|
||||
open_f(inspector);
|
||||
}
|
||||
open_f(inspector);
|
||||
rethrow_exception(current_exception());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1141,7 +1166,7 @@ int falco_init(int argc, char **argv)
|
||||
duration = ((double)clock()) / CLOCKS_PER_SEC;
|
||||
|
||||
//
|
||||
// run k8s, if required
|
||||
// Run k8s, if required
|
||||
//
|
||||
if(k8s_api)
|
||||
{
|
||||
@@ -1180,7 +1205,7 @@ int falco_init(int argc, char **argv)
|
||||
}
|
||||
|
||||
//
|
||||
// run mesos, if required
|
||||
// Run mesos, if required
|
||||
//
|
||||
if(mesos_api)
|
||||
{
|
||||
@@ -1205,12 +1230,20 @@ int falco_init(int argc, char **argv)
|
||||
webserver.start();
|
||||
}
|
||||
|
||||
// grpc server
|
||||
// gRPC server
|
||||
if(config.m_grpc_enabled)
|
||||
{
|
||||
falco_logger::log(LOG_INFO, "gRPC server threadiness equals to " + to_string(config.m_grpc_threadiness) + "\n");
|
||||
// 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();
|
||||
});
|
||||
@@ -1255,6 +1288,14 @@ int falco_init(int argc, char **argv)
|
||||
|
||||
}
|
||||
|
||||
// Honor -M also when using a trace file.
|
||||
// Since inspection stops as soon as all events have been consumed
|
||||
// just await the given duration is reached, if needed.
|
||||
if(!trace_filename.empty() && duration_to_tot>0)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(duration_to_tot));
|
||||
}
|
||||
|
||||
inspector->close();
|
||||
engine->print_stats();
|
||||
sdropmgr.print_stats();
|
||||
@@ -1293,7 +1334,6 @@ exit:
|
||||
//
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
alloc_chunk();
|
||||
int rc;
|
||||
|
||||
// g_restart will cause the falco loop to exit, but we
|
||||
|
||||
@@ -22,11 +22,10 @@ limitations under the License.
|
||||
|
||||
#include "formats.h"
|
||||
#include "logger.h"
|
||||
#include "falco_output_queue.h"
|
||||
#include "falco_outputs_queue.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
using namespace std;
|
||||
using namespace falco::output;
|
||||
|
||||
const static struct luaL_reg ll_falco_outputs [] =
|
||||
{
|
||||
@@ -316,7 +315,7 @@ int falco_outputs::handle_grpc(lua_State *ls)
|
||||
lua_error(ls);
|
||||
}
|
||||
|
||||
response grpc_res = response();
|
||||
falco::outputs::response grpc_res;
|
||||
|
||||
// time
|
||||
gen_event *evt = (gen_event *)lua_topointer(ls, 1);
|
||||
@@ -366,7 +365,7 @@ int falco_outputs::handle_grpc(lua_State *ls)
|
||||
auto host = grpc_res.mutable_hostname();
|
||||
*host = (char *)lua_tostring(ls, 7);
|
||||
|
||||
falco::output::queue::get().push(grpc_res);
|
||||
falco::outputs::queue::get().push(grpc_res);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@ limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "output.pb.h"
|
||||
#include "outputs.pb.h"
|
||||
#include "tbb/concurrent_queue.h"
|
||||
|
||||
namespace falco
|
||||
{
|
||||
namespace output
|
||||
namespace outputs
|
||||
{
|
||||
typedef tbb::concurrent_queue<response> response_cq;
|
||||
|
||||
@@ -36,7 +36,7 @@ class context
|
||||
{
|
||||
public:
|
||||
context(::grpc::ServerContext* ctx);
|
||||
~context() = default;
|
||||
virtual ~context() = default;
|
||||
|
||||
void get_metadata(std::string key, std::string& val);
|
||||
|
||||
@@ -50,7 +50,7 @@ class stream_context : public context
|
||||
public:
|
||||
stream_context(::grpc::ServerContext* ctx):
|
||||
context(ctx){};
|
||||
~stream_context() = default;
|
||||
virtual ~stream_context() = default;
|
||||
|
||||
enum : char
|
||||
{
|
||||
@@ -61,6 +61,15 @@ public:
|
||||
|
||||
mutable void* m_stream = nullptr; // todo(fntlnz, leodido) > useful in the future
|
||||
mutable bool m_has_more = false;
|
||||
mutable bool m_is_running = true;
|
||||
};
|
||||
|
||||
class bidi_context : public stream_context
|
||||
{
|
||||
public:
|
||||
bidi_context(::grpc::ServerContext* ctx):
|
||||
stream_context(ctx){};
|
||||
virtual ~bidi_context() = default;
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
@@ -24,12 +24,12 @@ namespace grpc
|
||||
{
|
||||
|
||||
template<>
|
||||
void request_stream_context<falco::output::service, falco::output::request, falco::output::response>::start(server* srv)
|
||||
void request_stream_context<outputs::service, outputs::request, outputs::response>::start(server* srv)
|
||||
{
|
||||
m_state = request_context_base::REQUEST;
|
||||
m_srv_ctx.reset(new ::grpc::ServerContext);
|
||||
auto srvctx = m_srv_ctx.get();
|
||||
m_res_writer.reset(new ::grpc::ServerAsyncWriter<output::response>(srvctx));
|
||||
m_res_writer.reset(new ::grpc::ServerAsyncWriter<outputs::response>(srvctx));
|
||||
m_stream_ctx.reset();
|
||||
m_req.Clear();
|
||||
auto cq = srv->m_completion_queue.get();
|
||||
@@ -38,7 +38,7 @@ void request_stream_context<falco::output::service, falco::output::request, falc
|
||||
}
|
||||
|
||||
template<>
|
||||
void request_stream_context<falco::output::service, falco::output::request, falco::output::response>::process(server* srv)
|
||||
void request_stream_context<outputs::service, outputs::request, outputs::response>::process(server* srv)
|
||||
{
|
||||
// When it is the 1st process call
|
||||
if(m_state == request_context_base::REQUEST)
|
||||
@@ -48,40 +48,46 @@ void request_stream_context<falco::output::service, falco::output::request, falc
|
||||
}
|
||||
|
||||
// Processing
|
||||
output::response res;
|
||||
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // subscribe()
|
||||
outputs::response res;
|
||||
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // get()
|
||||
|
||||
if(!m_stream_ctx->m_is_running)
|
||||
{
|
||||
m_state = request_context_base::FINISH;
|
||||
m_res_writer->Finish(::grpc::Status::OK, this);
|
||||
return;
|
||||
}
|
||||
|
||||
// When there are still more responses to stream
|
||||
if(m_stream_ctx->m_has_more)
|
||||
{
|
||||
// todo(leodido) > log "write: tag=this, state=m_state"
|
||||
m_res_writer->Write(res, this);
|
||||
return;
|
||||
}
|
||||
|
||||
// No more responses to stream
|
||||
else
|
||||
{
|
||||
// Communicate to the gRPC runtime that we have finished.
|
||||
// The memory address of "this" instance uniquely identifies the event.
|
||||
m_state = request_context_base::FINISH;
|
||||
// todo(leodido) > log "finish: tag=this, state=m_state"
|
||||
m_res_writer->Finish(::grpc::Status::OK, this);
|
||||
}
|
||||
// Communicate to the gRPC runtime that we have finished.
|
||||
// The memory address of "this" instance uniquely identifies the event.
|
||||
m_state = request_context_base::FINISH;
|
||||
// todo(leodido) > log "finish: tag=this, state=m_state"
|
||||
m_res_writer->Finish(::grpc::Status::OK, this);
|
||||
}
|
||||
|
||||
template<>
|
||||
void request_stream_context<falco::output::service, falco::output::request, falco::output::response>::end(server* srv, bool errored)
|
||||
void request_stream_context<outputs::service, outputs::request, outputs::response>::end(server* srv, bool error)
|
||||
{
|
||||
if(m_stream_ctx)
|
||||
{
|
||||
if(errored)
|
||||
if(error)
|
||||
{
|
||||
// todo(leodido) > log error "error streaming: tag=this, state=m_state, stream=m_stream_ctx->m_stream"
|
||||
}
|
||||
m_stream_ctx->m_status = errored ? stream_context::ERROR : stream_context::SUCCESS;
|
||||
m_stream_ctx->m_status = error ? stream_context::ERROR : stream_context::SUCCESS;
|
||||
|
||||
// Complete the processing
|
||||
output::response res;
|
||||
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // subscribe()
|
||||
outputs::response res;
|
||||
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // get()
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -98,7 +104,7 @@ void request_stream_context<falco::output::service, falco::output::request, falc
|
||||
}
|
||||
|
||||
template<>
|
||||
void falco::grpc::request_context<falco::version::service, falco::version::request, falco::version::response>::start(server* srv)
|
||||
void request_context<version::service, version::request, version::response>::start(server* srv)
|
||||
{
|
||||
m_state = request_context_base::REQUEST;
|
||||
m_srv_ctx.reset(new ::grpc::ServerContext);
|
||||
@@ -113,7 +119,7 @@ void falco::grpc::request_context<falco::version::service, falco::version::reque
|
||||
}
|
||||
|
||||
template<>
|
||||
void falco::grpc::request_context<falco::version::service, falco::version::request, falco::version::response>::process(server* srv)
|
||||
void request_context<version::service, version::request, version::response>::process(server* srv)
|
||||
{
|
||||
version::response res;
|
||||
(srv->*m_process_func)(m_srv_ctx.get(), m_req, res);
|
||||
@@ -125,13 +131,85 @@ void falco::grpc::request_context<falco::version::service, falco::version::reque
|
||||
}
|
||||
|
||||
template<>
|
||||
void falco::grpc::request_context<falco::version::service, falco::version::request, falco::version::response>::end(server* srv, bool errored)
|
||||
void request_context<version::service, version::request, version::response>::end(server* srv, bool error)
|
||||
{
|
||||
// todo(leodido) > handle processing errors here
|
||||
|
||||
|
||||
// Ask to start processing requests
|
||||
start(srv);
|
||||
}
|
||||
|
||||
template<>
|
||||
void request_bidi_context<outputs::service, outputs::request, outputs::response>::start(server* srv)
|
||||
{
|
||||
m_state = request_context_base::REQUEST;
|
||||
m_srv_ctx.reset(new ::grpc::ServerContext);
|
||||
auto srvctx = m_srv_ctx.get();
|
||||
m_reader_writer.reset(new ::grpc::ServerAsyncReaderWriter<outputs::response, outputs::request>(srvctx));
|
||||
m_req.Clear();
|
||||
auto cq = srv->m_completion_queue.get();
|
||||
// Request to start processing given requests.
|
||||
// Using "this" - ie., the memory address of this context - as the tag that uniquely identifies the request.
|
||||
// In this way, different contexts can serve different requests concurrently.
|
||||
(srv->m_output_svc.*m_request_func)(srvctx, m_reader_writer.get(), cq, cq, this);
|
||||
};
|
||||
|
||||
template<>
|
||||
void request_bidi_context<outputs::service, outputs::request, outputs::response>::process(server* srv)
|
||||
{
|
||||
switch(m_state)
|
||||
{
|
||||
case request_context_base::REQUEST:
|
||||
m_bidi_ctx.reset(new bidi_context(m_srv_ctx.get()));
|
||||
m_bidi_ctx->m_status = bidi_context::STREAMING;
|
||||
m_state = request_context_base::WRITE;
|
||||
m_reader_writer->Read(&m_req, this);
|
||||
return;
|
||||
case request_context_base::WRITE:
|
||||
// Processing
|
||||
{
|
||||
outputs::response res;
|
||||
(srv->*m_process_func)(*m_bidi_ctx, m_req, res); // sub()
|
||||
|
||||
if(!m_bidi_ctx->m_is_running)
|
||||
{
|
||||
m_state = request_context_base::FINISH;
|
||||
m_reader_writer->Finish(::grpc::Status::OK, this);
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_bidi_ctx->m_has_more)
|
||||
{
|
||||
m_state = request_context_base::WRITE;
|
||||
m_reader_writer->Write(res, this);
|
||||
return;
|
||||
}
|
||||
|
||||
m_state = request_context_base::WRITE;
|
||||
m_reader_writer->Read(&m_req, this);
|
||||
}
|
||||
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void request_bidi_context<outputs::service, outputs::request, outputs::response>::end(server* srv, bool error)
|
||||
{
|
||||
if(m_bidi_ctx)
|
||||
{
|
||||
m_bidi_ctx->m_status = error ? bidi_context::ERROR : bidi_context::SUCCESS;
|
||||
|
||||
// Complete the processing
|
||||
outputs::response res;
|
||||
(srv->*m_process_func)(*m_bidi_ctx, m_req, res); // sub()
|
||||
}
|
||||
|
||||
// Ask to start processing requests
|
||||
start(srv);
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
} // namespace falco
|
||||
} // namespace falco
|
||||
|
||||
@@ -29,7 +29,8 @@ class request_context_base
|
||||
{
|
||||
public:
|
||||
request_context_base() = default;
|
||||
~request_context_base() = default;
|
||||
// virtual to guarantee that the derived classes are destructed properly
|
||||
virtual ~request_context_base() = default;
|
||||
|
||||
std::unique_ptr<::grpc::ServerContext> m_srv_ctx;
|
||||
enum : char
|
||||
@@ -39,6 +40,7 @@ public:
|
||||
WRITE,
|
||||
FINISH
|
||||
} m_state = UNKNOWN;
|
||||
|
||||
virtual void start(server* srv) = 0;
|
||||
virtual void process(server* srv) = 0;
|
||||
virtual void end(server* srv, bool isError) = 0;
|
||||
@@ -63,7 +65,7 @@ public:
|
||||
|
||||
void start(server* srv);
|
||||
void process(server* srv);
|
||||
void end(server* srv, bool isError);
|
||||
void end(server* srv, bool error);
|
||||
|
||||
private:
|
||||
std::unique_ptr<::grpc::ServerAsyncWriter<Response>> m_res_writer;
|
||||
@@ -90,11 +92,37 @@ public:
|
||||
|
||||
void start(server* srv);
|
||||
void process(server* srv);
|
||||
void end(server* srv, bool isError);
|
||||
void end(server* srv, bool error);
|
||||
|
||||
private:
|
||||
std::unique_ptr<::grpc::ServerAsyncResponseWriter<Response>> m_res_writer;
|
||||
Request m_req;
|
||||
};
|
||||
|
||||
template<class Service, class Request, class Response>
|
||||
class request_bidi_context : public request_context_base
|
||||
{
|
||||
public:
|
||||
request_bidi_context():
|
||||
m_process_func(nullptr),
|
||||
m_request_func(nullptr){};
|
||||
~request_bidi_context() = default;
|
||||
|
||||
// Pointer to function that does actual processing
|
||||
void (server::*m_process_func)(const bidi_context&, const Request&, Response&);
|
||||
|
||||
// Pointer to function that requests the system to start processing given requests
|
||||
void (Service::AsyncService::*m_request_func)(::grpc::ServerContext*, ::grpc::ServerAsyncReaderWriter<Response, Request>*, ::grpc::CompletionQueue*, ::grpc::ServerCompletionQueue*, void*);
|
||||
|
||||
void start(server* srv);
|
||||
void process(server* srv);
|
||||
void end(server* srv, bool error);
|
||||
|
||||
private:
|
||||
std::unique_ptr<::grpc::ServerAsyncReaderWriter<Response, Request>> m_reader_writer;
|
||||
std::unique_ptr<bidi_context> m_bidi_ctx;
|
||||
Request m_req;
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
} // namespace falco
|
||||
} // namespace falco
|
||||
|
||||
@@ -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,37 @@ limitations under the License.
|
||||
c.start(this); \
|
||||
}
|
||||
|
||||
#define REGISTER_BIDI(req, res, svc, rpc, impl, num) \
|
||||
std::vector<request_bidi_context<svc, req, res>> rpc##_contexts(num); \
|
||||
for(request_bidi_context<svc, req, res> & c : rpc##_contexts) \
|
||||
{ \
|
||||
c.m_process_func = &server::impl; \
|
||||
c.m_request_func = &svc::AsyncService::Request##rpc; \
|
||||
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;
|
||||
}
|
||||
|
||||
string copy = "grpc: ";
|
||||
copy.append(args->message);
|
||||
copy.push_back('\n');
|
||||
falco_logger::log(priority, copy);
|
||||
}
|
||||
|
||||
void falco::grpc::server::thread_process(int thread_index)
|
||||
{
|
||||
void* tag = nullptr;
|
||||
@@ -96,38 +127,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
|
||||
@@ -137,7 +211,8 @@ void falco::grpc::server::run()
|
||||
// todo(leodido) > take a look at thread_stress_test.cc into grpc repository
|
||||
|
||||
REGISTER_UNARY(version::request, version::response, version::service, version, version, context_num)
|
||||
REGISTER_STREAM(output::request, output::response, output::service, subscribe, subscribe, context_num)
|
||||
REGISTER_STREAM(outputs::request, outputs::response, outputs::service, get, get, context_num)
|
||||
REGISTER_BIDI(outputs::request, outputs::response, outputs::service, sub, sub, context_num)
|
||||
|
||||
m_threads.resize(m_threadiness);
|
||||
int thread_idx = 0;
|
||||
@@ -149,7 +224,7 @@ void falco::grpc::server::run()
|
||||
|
||||
while(server_impl::is_running())
|
||||
{
|
||||
sleep(1);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
// todo(leodido) > log "stopping gRPC server"
|
||||
stop();
|
||||
|
||||
@@ -29,25 +29,22 @@ 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();
|
||||
|
||||
output::service::AsyncService m_output_svc;
|
||||
outputs::service::AsyncService m_output_svc;
|
||||
version::service::AsyncService m_version_svc;
|
||||
|
||||
std::unique_ptr<::grpc::ServerCompletionQueue> m_completion_queue;
|
||||
@@ -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
|
||||
|
||||
@@ -16,7 +16,8 @@ limitations under the License.
|
||||
|
||||
#include "config_falco.h"
|
||||
#include "grpc_server_impl.h"
|
||||
#include "falco_output_queue.h"
|
||||
#include "falco_outputs_queue.h"
|
||||
#include "logger.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
bool falco::grpc::server_impl::is_running()
|
||||
@@ -28,29 +29,39 @@ bool falco::grpc::server_impl::is_running()
|
||||
return true;
|
||||
}
|
||||
|
||||
void falco::grpc::server_impl::subscribe(const stream_context& ctx, const output::request& req, output::response& res)
|
||||
void falco::grpc::server_impl::get(const stream_context& ctx, const outputs::request& req, outputs::response& res)
|
||||
{
|
||||
if(ctx.m_status == stream_context::SUCCESS || ctx.m_status == stream_context::ERROR)
|
||||
{
|
||||
// todo(leodido) > log "status=ctx->m_status, stream=ctx->m_stream"
|
||||
ctx.m_stream = nullptr;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start or continue streaming
|
||||
// todo(leodido) > check for m_status == stream_context::STREAMING?
|
||||
// todo(leodido) > set m_stream
|
||||
if(output::queue::get().try_pop(res) && !req.keepalive())
|
||||
{
|
||||
ctx.m_has_more = true;
|
||||
return;
|
||||
}
|
||||
while(is_running() && !output::queue::get().try_pop(res) && req.keepalive())
|
||||
{
|
||||
}
|
||||
|
||||
ctx.m_has_more = !is_running() ? false : req.keepalive();
|
||||
ctx.m_is_running = is_running();
|
||||
|
||||
// Start or continue streaming
|
||||
// m_status == stream_context::STREAMING?
|
||||
// todo(leodido) > set m_stream
|
||||
|
||||
ctx.m_has_more = outputs::queue::get().try_pop(res);
|
||||
}
|
||||
|
||||
void falco::grpc::server_impl::sub(const bidi_context& ctx, const outputs::request& req, outputs::response& res)
|
||||
{
|
||||
if(ctx.m_status == stream_context::SUCCESS || ctx.m_status == stream_context::ERROR)
|
||||
{
|
||||
ctx.m_stream = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.m_is_running = is_running();
|
||||
|
||||
// Start or continue streaming
|
||||
// m_status == stream_context::STREAMING?
|
||||
// todo(leodido) > set m_stream
|
||||
|
||||
ctx.m_has_more = outputs::queue::get().try_pop(res);
|
||||
}
|
||||
|
||||
void falco::grpc::server_impl::version(const context& ctx, const version::request&, version::response& res)
|
||||
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include "output.grpc.pb.h"
|
||||
#include "outputs.grpc.pb.h"
|
||||
#include "version.grpc.pb.h"
|
||||
#include "grpc_context.h"
|
||||
|
||||
@@ -36,8 +36,11 @@ public:
|
||||
protected:
|
||||
bool is_running();
|
||||
|
||||
void subscribe(const stream_context& ctx, const output::request& req, output::response& res);
|
||||
// Outputs
|
||||
void get(const stream_context& ctx, const outputs::request& req, outputs::response& res);
|
||||
void sub(const bidi_context& ctx, const outputs::request& req, outputs::response& res);
|
||||
|
||||
// Version
|
||||
void version(const context& ctx, const version::request& req, version::response& res);
|
||||
|
||||
private:
|
||||
|
||||
@@ -134,7 +134,7 @@ void falco_logger::log(int priority, const string msg)
|
||||
if(gtm != NULL &&
|
||||
(strftime(buf, sizeof(buf), "%FT%T%z", gtm) != 0))
|
||||
{
|
||||
fprintf(stderr, "%s: %s", buf, msg.c_str());
|
||||
fprintf(stderr, "%s: %s", buf, copy.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -151,7 +151,7 @@ void falco_logger::log(int priority, const string msg)
|
||||
{
|
||||
tstr = "N/A";
|
||||
}
|
||||
fprintf(stderr, "%s: %s", tstr.c_str(), msg.c_str());
|
||||
fprintf(stderr, "%s: %s", tstr.c_str(), copy.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ local mod = {}
|
||||
local outputs = {}
|
||||
|
||||
function mod.stdout(event, rule, source, priority, priority_num, msg, format, hostname, options)
|
||||
mod.stdout_message(priority, priority_num, msg, outputs)
|
||||
mod.stdout_message(priority, priority_num, msg, options)
|
||||
end
|
||||
|
||||
function mod.stdout_message(priority, priority_num, msg, options)
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "schema.proto";
|
||||
|
||||
package falco.output;
|
||||
|
||||
option go_package = "github.com/falcosecurity/client-go/pkg/api/output";
|
||||
|
||||
// The `subscribe` service defines the RPC call
|
||||
// to perform an output `request` which will lead to obtain an output `response`.
|
||||
service service {
|
||||
rpc subscribe(request) returns (stream response);
|
||||
}
|
||||
|
||||
// The `request` message is the logical representation of the request model.
|
||||
// It is the input of the `subscribe` service.
|
||||
// It is used to configure the kind of subscription to the gRPC streaming server.
|
||||
//
|
||||
// By default the request asks to the server to only receive the accumulated events.
|
||||
// In case you want to wait indefinitely for new events to come set the keepalive option to true.
|
||||
message request {
|
||||
bool keepalive = 1;
|
||||
// string duration = 2; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
|
||||
// repeated string tags = 3; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
|
||||
}
|
||||
|
||||
// The `response` message is the logical representation of the output model.
|
||||
// It contains all the elements that Falco emits in an output along with the
|
||||
// definitions for priorities and source.
|
||||
message response {
|
||||
google.protobuf.Timestamp time = 1;
|
||||
falco.schema.priority priority = 2;
|
||||
falco.schema.source source = 3;
|
||||
string rule = 4;
|
||||
string output = 5;
|
||||
map<string, string> output_fields = 6;
|
||||
string hostname = 7;
|
||||
// repeated string tags = 8; // TODO(leodido,fntlnz): tags not supported yet, keeping for reference
|
||||
}
|
||||
55
userspace/falco/outputs.proto
Normal file
55
userspace/falco/outputs.proto
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "schema.proto";
|
||||
|
||||
package falco.outputs;
|
||||
|
||||
option go_package = "github.com/falcosecurity/client-go/pkg/api/outputs";
|
||||
|
||||
// This service defines the RPC methods
|
||||
// to `request` a stream of output `response`s.
|
||||
service service {
|
||||
// Subscribe to a stream of Falco outputs by sending a stream of requests.
|
||||
rpc sub(stream request) returns (stream response);
|
||||
// Get all the Falco outputs present in the system up to this call.
|
||||
rpc get(request) returns (stream response);
|
||||
}
|
||||
|
||||
// The `request` message is the logical representation of the request model.
|
||||
// It is the input of the `output.service` service.
|
||||
message request {
|
||||
// TODO(leodido,fntlnz): tags not supported yet, keeping it for reference.
|
||||
// repeated string tags = 1;
|
||||
}
|
||||
|
||||
// The `response` message is the representation of the output model.
|
||||
// It contains all the elements that Falco emits in an output along with the
|
||||
// definitions for priorities and source.
|
||||
message response {
|
||||
google.protobuf.Timestamp time = 1;
|
||||
falco.schema.priority priority = 2;
|
||||
falco.schema.source source = 3;
|
||||
string rule = 4;
|
||||
string output = 5;
|
||||
map<string, string> output_fields = 6;
|
||||
string hostname = 7;
|
||||
// TODO(leodido,fntlnz): tags not supported yet, keeping it for reference.
|
||||
// repeated string tags = 8;
|
||||
}
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package falco.schema;
|
||||
|
||||
@@ -58,8 +58,8 @@ bool StatsFileWriter::init(sinsp *inspector, string &filename, uint32_t interval
|
||||
return false;
|
||||
}
|
||||
|
||||
timer.it_value.tv_sec = 0;
|
||||
timer.it_value.tv_usec = interval_msec * 1000;
|
||||
timer.it_value.tv_sec = interval_msec / 1000;
|
||||
timer.it_value.tv_usec = (interval_msec % 1000) * 1000;
|
||||
timer.it_interval = timer.it_value;
|
||||
if (setitimer(ITIMER_REAL, &timer, NULL) == -1)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,30 +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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace falco
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
void read(const std::string& filename, std::string& data);
|
||||
} // namespace utils
|
||||
} // namespace falco
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package falco.version;
|
||||
|
||||
@@ -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})
|
||||
@@ -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;
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user