mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-29 16:12:34 +00:00
Compare commits
2 Commits
update/cli
...
fix/script
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7637ccd7a8 | ||
|
|
40635ab620 |
@@ -1,85 +1,5 @@
|
|||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
# Build a statically linked Falco release binary using musl
|
|
||||||
# This build is 100% static, there are no host dependencies
|
|
||||||
"build/musl":
|
|
||||||
docker:
|
|
||||||
- image: alpine:3.12
|
|
||||||
steps:
|
|
||||||
- checkout:
|
|
||||||
path: /source-static/falco
|
|
||||||
- run:
|
|
||||||
name: Update base image
|
|
||||||
command: apk update
|
|
||||||
- run:
|
|
||||||
name: Install build dependencies
|
|
||||||
command: apk add g++ gcc cmake cmake make ncurses-dev git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils
|
|
||||||
- run:
|
|
||||||
name: Prepare project
|
|
||||||
command: |
|
|
||||||
mkdir -p /build-static/release
|
|
||||||
cd /build-static/release
|
|
||||||
cmake -DCPACK_GENERATOR=TGZ -DBUILD_BPF=Off -DBUILD_DRIVER=Off -DCMAKE_BUILD_TYPE=Release -DUSE_BUNDLED_DEPS=On -DMUSL_OPTIMIZED_BUILD=On -DFALCO_ETC_DIR=/etc/falco /source-static/falco
|
|
||||||
- run:
|
|
||||||
name: Build
|
|
||||||
command: |
|
|
||||||
cd /build-static/release
|
|
||||||
make -j4 all
|
|
||||||
- run:
|
|
||||||
name: Package
|
|
||||||
command: |
|
|
||||||
cd /build-static/release
|
|
||||||
make -j4 package
|
|
||||||
- run:
|
|
||||||
name: Run unit tests
|
|
||||||
command: |
|
|
||||||
cd /build-static/release
|
|
||||||
make tests
|
|
||||||
- run:
|
|
||||||
name: Prepare artifacts
|
|
||||||
command: |
|
|
||||||
mkdir -p /tmp/packages
|
|
||||||
cp /build-static/release/*.tar.gz /tmp/packages
|
|
||||||
- store_artifacts:
|
|
||||||
path: /tmp/packages
|
|
||||||
destination: /packages
|
|
||||||
- persist_to_workspace:
|
|
||||||
root: /
|
|
||||||
paths:
|
|
||||||
- build-static/release
|
|
||||||
- source-static
|
|
||||||
# Build the minimal Falco
|
|
||||||
# This build only contains the Falco engine and the basic input/output.
|
|
||||||
"build/minimal":
|
|
||||||
docker:
|
|
||||||
- image: ubuntu:focal
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
- run:
|
|
||||||
name: Update base image
|
|
||||||
command: apt update -y
|
|
||||||
- run:
|
|
||||||
name: Install dependencies
|
|
||||||
command: DEBIAN_FRONTEND=noninteractive apt install libjq-dev libncurses-dev libyaml-cpp-dev libelf-dev cmake build-essential git -y
|
|
||||||
- run:
|
|
||||||
name: Prepare project
|
|
||||||
command: |
|
|
||||||
mkdir build-minimal
|
|
||||||
pushd build-minimal
|
|
||||||
cmake -DMINIMAL_BUILD=On -DBUILD_BPF=Off -DBUILD_DRIVER=Off -DCMAKE_BUILD_TYPE=Release ..
|
|
||||||
popd
|
|
||||||
- run:
|
|
||||||
name: Build
|
|
||||||
command: |
|
|
||||||
pushd build-minimal
|
|
||||||
make -j4 all
|
|
||||||
popd
|
|
||||||
- run:
|
|
||||||
name: Run unit tests
|
|
||||||
command: |
|
|
||||||
pushd build-minimal
|
|
||||||
make tests
|
|
||||||
popd
|
|
||||||
# Build using ubuntu LTS
|
# Build using ubuntu LTS
|
||||||
# This build is dynamic, most dependencies are taken from the OS
|
# This build is dynamic, most dependencies are taken from the OS
|
||||||
"build/ubuntu-focal":
|
"build/ubuntu-focal":
|
||||||
@@ -282,25 +202,6 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Execute integration tests
|
name: Execute integration tests
|
||||||
command: /usr/bin/entrypoint test
|
command: /usr/bin/entrypoint test
|
||||||
- store_test_results:
|
|
||||||
path: /build/release/integration-tests-xunit
|
|
||||||
"tests/integration-static":
|
|
||||||
docker:
|
|
||||||
- image: falcosecurity/falco-tester:latest
|
|
||||||
environment:
|
|
||||||
SOURCE_DIR: "/source-static"
|
|
||||||
BUILD_DIR: "/build-static"
|
|
||||||
BUILD_TYPE: "release"
|
|
||||||
SKIP_PACKAGES_TESTS: "true"
|
|
||||||
steps:
|
|
||||||
- setup_remote_docker
|
|
||||||
- attach_workspace:
|
|
||||||
at: /
|
|
||||||
- run:
|
|
||||||
name: Execute integration tests
|
|
||||||
command: /usr/bin/entrypoint test
|
|
||||||
- store_test_results:
|
|
||||||
path: /build-static/release/integration-tests-xunit
|
|
||||||
"tests/driver-loader/integration":
|
"tests/driver-loader/integration":
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-1604:202004-01
|
image: ubuntu-1604:202004-01
|
||||||
@@ -310,33 +211,6 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Execute driver-loader integration tests
|
name: Execute driver-loader integration tests
|
||||||
command: /tmp/ws/source/falco/test/driver-loader/run_test.sh /tmp/ws/build/release/
|
command: /tmp/ws/source/falco/test/driver-loader/run_test.sh /tmp/ws/build/release/
|
||||||
# Code quality
|
|
||||||
"quality/static-analysis":
|
|
||||||
docker:
|
|
||||||
- image: falcosecurity/falco-builder:latest
|
|
||||||
environment:
|
|
||||||
BUILD_TYPE: "release"
|
|
||||||
steps:
|
|
||||||
- run:
|
|
||||||
name: Install cppcheck
|
|
||||||
command: |
|
|
||||||
yum update -y
|
|
||||||
yum install epel-release -y
|
|
||||||
yum install cppcheck cppcheck-htmlreport -y
|
|
||||||
- checkout:
|
|
||||||
path: /source/falco
|
|
||||||
- run:
|
|
||||||
name: Prepare project
|
|
||||||
command: /usr/bin/entrypoint cmake
|
|
||||||
- run:
|
|
||||||
name: cppcheck
|
|
||||||
command: /usr/bin/entrypoint cppcheck
|
|
||||||
- run:
|
|
||||||
name: cppcheck html report
|
|
||||||
command: /usr/bin/entrypoint cppcheck_htmlreport
|
|
||||||
- store_artifacts:
|
|
||||||
path: /build/release/static-analysis-reports
|
|
||||||
destination: /static-analysis-reports
|
|
||||||
# Sign rpm packages
|
# Sign rpm packages
|
||||||
"rpm/sign":
|
"rpm/sign":
|
||||||
docker:
|
docker:
|
||||||
@@ -393,34 +267,10 @@ jobs:
|
|||||||
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||||
jfrog bt u /build/release/falco-${FALCO_VERSION}-x86_64.rpm falcosecurity/rpm-dev/falco/${FALCO_VERSION} --user poiana --key ${BINTRAY_SECRET} --publish --override
|
jfrog bt u /build/release/falco-${FALCO_VERSION}-x86_64.rpm falcosecurity/rpm-dev/falco/${FALCO_VERSION} --user poiana --key ${BINTRAY_SECRET} --publish --override
|
||||||
- run:
|
- run:
|
||||||
name: Publish bin-dev
|
name: Publish tgz-dev
|
||||||
command: |
|
command: |
|
||||||
FALCO_VERSION=$(cat /build-static/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||||
jfrog bt u /build-static/release/falco-${FALCO_VERSION}-x86_64.tar.gz falcosecurity/bin-dev/falco/${FALCO_VERSION} x86_64/ --user poiana --key ${BINTRAY_SECRET} --publish --override
|
jfrog bt u /build/release/falco-${FALCO_VERSION}-x86_64.tar.gz falcosecurity/bin-dev/falco/${FALCO_VERSION} x86_64/ --user poiana --key ${BINTRAY_SECRET} --publish --override
|
||||||
# Clenup the Falco development release packages
|
|
||||||
"cleanup/packages-dev":
|
|
||||||
docker:
|
|
||||||
- image: docker.bintray.io/jfrog/jfrog-cli-go:latest
|
|
||||||
steps:
|
|
||||||
- checkout:
|
|
||||||
path: /source/falco
|
|
||||||
- run:
|
|
||||||
name: Prepare env
|
|
||||||
command: |
|
|
||||||
apk add --no-cache --update
|
|
||||||
apk add curl jq
|
|
||||||
- run:
|
|
||||||
name: Only keep the 10 most recent Falco development release tarballs
|
|
||||||
command: |
|
|
||||||
/source/falco/scripts/cleanup -p ${BINTRAY_SECRET} -r bin-dev
|
|
||||||
- run:
|
|
||||||
name: Only keep the 50 most recent Falco development release RPMs
|
|
||||||
command: |
|
|
||||||
/source/falco/scripts/cleanup -p ${BINTRAY_SECRET} -r rpm-dev
|
|
||||||
- run:
|
|
||||||
name: Only keep the 50 most recent Falco development release DEBs
|
|
||||||
command: |
|
|
||||||
/source/falco/scripts/cleanup -p ${BINTRAY_SECRET} -r deb-dev
|
|
||||||
# Publish docker packages
|
# Publish docker packages
|
||||||
"publish/docker-dev":
|
"publish/docker-dev":
|
||||||
docker:
|
docker:
|
||||||
@@ -477,10 +327,10 @@ jobs:
|
|||||||
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||||
jfrog bt u /build/release/falco-${FALCO_VERSION}-x86_64.rpm falcosecurity/rpm/falco/${FALCO_VERSION} --user poiana --key ${BINTRAY_SECRET} --publish --override
|
jfrog bt u /build/release/falco-${FALCO_VERSION}-x86_64.rpm falcosecurity/rpm/falco/${FALCO_VERSION} --user poiana --key ${BINTRAY_SECRET} --publish --override
|
||||||
- run:
|
- run:
|
||||||
name: Publish bin
|
name: Publish tgz
|
||||||
command: |
|
command: |
|
||||||
FALCO_VERSION=$(cat /build-static/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||||
jfrog bt u /build-static/release/falco-${FALCO_VERSION}-x86_64.tar.gz falcosecurity/bin/falco/${FALCO_VERSION} x86_64/ --user poiana --key ${BINTRAY_SECRET} --publish --override
|
jfrog bt u /build/release/falco-${FALCO_VERSION}-x86_64.tar.gz falcosecurity/bin/falco/${FALCO_VERSION} x86_64/ --user poiana --key ${BINTRAY_SECRET} --publish --override
|
||||||
# Publish docker packages
|
# Publish docker packages
|
||||||
"publish/docker":
|
"publish/docker":
|
||||||
docker:
|
docker:
|
||||||
@@ -522,8 +372,6 @@ workflows:
|
|||||||
version: 2
|
version: 2
|
||||||
build_and_test:
|
build_and_test:
|
||||||
jobs:
|
jobs:
|
||||||
- "build/musl"
|
|
||||||
- "build/minimal"
|
|
||||||
- "build/ubuntu-focal"
|
- "build/ubuntu-focal"
|
||||||
- "build/ubuntu-focal-debug"
|
- "build/ubuntu-focal-debug"
|
||||||
- "build/ubuntu-bionic"
|
- "build/ubuntu-bionic"
|
||||||
@@ -533,9 +381,6 @@ workflows:
|
|||||||
- "tests/integration":
|
- "tests/integration":
|
||||||
requires:
|
requires:
|
||||||
- "build/centos7"
|
- "build/centos7"
|
||||||
- "tests/integration-static":
|
|
||||||
requires:
|
|
||||||
- "build/musl"
|
|
||||||
- "tests/driver-loader/integration":
|
- "tests/driver-loader/integration":
|
||||||
requires:
|
requires:
|
||||||
- "build/centos7"
|
- "build/centos7"
|
||||||
@@ -557,16 +402,6 @@ workflows:
|
|||||||
only: master
|
only: master
|
||||||
requires:
|
requires:
|
||||||
- "rpm/sign"
|
- "rpm/sign"
|
||||||
- "tests/integration-static"
|
|
||||||
- "cleanup/packages-dev":
|
|
||||||
context: falco
|
|
||||||
filters:
|
|
||||||
tags:
|
|
||||||
ignore: /.*/
|
|
||||||
branches:
|
|
||||||
only: master
|
|
||||||
requires:
|
|
||||||
- "publish/packages-dev"
|
|
||||||
- "publish/docker-dev":
|
- "publish/docker-dev":
|
||||||
context: falco
|
context: falco
|
||||||
filters:
|
filters:
|
||||||
@@ -577,15 +412,8 @@ workflows:
|
|||||||
requires:
|
requires:
|
||||||
- "publish/packages-dev"
|
- "publish/packages-dev"
|
||||||
- "tests/driver-loader/integration"
|
- "tests/driver-loader/integration"
|
||||||
- "quality/static-analysis"
|
|
||||||
release:
|
release:
|
||||||
jobs:
|
jobs:
|
||||||
- "build/musl":
|
|
||||||
filters:
|
|
||||||
tags:
|
|
||||||
only: /.*/
|
|
||||||
branches:
|
|
||||||
ignore: /.*/
|
|
||||||
- "build/centos7":
|
- "build/centos7":
|
||||||
filters:
|
filters:
|
||||||
tags:
|
tags:
|
||||||
@@ -604,7 +432,6 @@ workflows:
|
|||||||
- "publish/packages":
|
- "publish/packages":
|
||||||
context: falco
|
context: falco
|
||||||
requires:
|
requires:
|
||||||
- "build/musl"
|
|
||||||
- "rpm/sign"
|
- "rpm/sign"
|
||||||
filters:
|
filters:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
20
.github/stale.yml
vendored
Normal file
20
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Number of days of inactivity before an issue becomes stale
|
||||||
|
daysUntilStale: 60
|
||||||
|
# Number of days of inactivity before a stale issue is closed
|
||||||
|
daysUntilClose: 7
|
||||||
|
# Issues with these labels will never be considered stale
|
||||||
|
exemptLabels:
|
||||||
|
- cncf
|
||||||
|
- roadmap
|
||||||
|
- "help wanted"
|
||||||
|
# Label to use when marking an issue as stale
|
||||||
|
staleLabel: wontfix
|
||||||
|
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||||
|
markComment: >
|
||||||
|
This issue has been automatically marked as stale because it has not had
|
||||||
|
recent activity. It will be closed if no further activity occurs. Thank you
|
||||||
|
for your contributions.
|
||||||
|
Issues labeled "cncf", "roadmap" and "help wanted" will not be automatically closed.
|
||||||
|
Please refer to a maintainer to get such label added if you think this should be kept open.
|
||||||
|
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||||
|
closeComment: false
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,6 +11,8 @@ test/.phoronix-test-suite
|
|||||||
test/results*.json.*
|
test/results*.json.*
|
||||||
test/build
|
test/build
|
||||||
|
|
||||||
|
userspace/falco/lua/re.lua
|
||||||
|
userspace/falco/lua/lpeg.so
|
||||||
userspace/engine/lua/lyaml
|
userspace/engine/lua/lyaml
|
||||||
userspace/engine/lua/lyaml.lua
|
userspace/engine/lua/lyaml.lua
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
std = "min"
|
std = "min"
|
||||||
cache = true
|
cache = true
|
||||||
include_files = {
|
include_files = {
|
||||||
|
"userspace/falco/lua/*.lua",
|
||||||
"userspace/engine/lua/*.lua",
|
"userspace/engine/lua/*.lua",
|
||||||
"userspace/engine/lua/lyaml/*.lua",
|
"userspace/engine/lua/lyaml/*.lua",
|
||||||
"*.luacheckrc"
|
"*.luacheckrc"
|
||||||
|
|||||||
97
CHANGELOG.md
97
CHANGELOG.md
@@ -1,101 +1,6 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## v0.26.2
|
This file documents all notable changes to Falco. The release numbering uses [semantic versioning](http://semver.org).
|
||||||
|
|
||||||
Released on 2020-11-10
|
|
||||||
|
|
||||||
### Major Changes
|
|
||||||
|
|
||||||
* update: DRIVERS_REPO now defaults to https://download.falco.org/driver [[#1460](https://github.com/falcosecurity/falco/pull/1460)] - [@leodido](https://github.com/leodido)
|
|
||||||
|
|
||||||
## v0.26.1
|
|
||||||
|
|
||||||
Released on 2020-10-01
|
|
||||||
|
|
||||||
### Major Changes
|
|
||||||
|
|
||||||
* new: CLI flag `--alternate-lua-dir` to load Lua files from arbitrary paths [[#1419](https://github.com/falcosecurity/falco/pull/1419)] - [@admiral0](https://github.com/admiral0)
|
|
||||||
|
|
||||||
|
|
||||||
### Rule Changes
|
|
||||||
|
|
||||||
* rule(Delete or rename shell history): fix warnings/FPs + container teardown [[#1423](https://github.com/falcosecurity/falco/pull/1423)] - [@mstemm](https://github.com/mstemm)
|
|
||||||
* rule(Write below root): ensure proc_name_exists too [[#1423](https://github.com/falcosecurity/falco/pull/1423)] - [@mstemm](https://github.com/mstemm)
|
|
||||||
|
|
||||||
|
|
||||||
## v0.26.0
|
|
||||||
|
|
||||||
Released on 2020-24-09
|
|
||||||
|
|
||||||
### Major Changes
|
|
||||||
|
|
||||||
* new: address several sources of FPs, primarily from GKE environments. [[#1372](https://github.com/falcosecurity/falco/pull/1372)] - [@mstemm](https://github.com/mstemm)
|
|
||||||
* new: driver updated to 2aa88dcf6243982697811df4c1b484bcbe9488a2 [[#1410](https://github.com/falcosecurity/falco/pull/1410)] - [@leogr](https://github.com/leogr)
|
|
||||||
* new(scripts/falco-driver-loader): detect and try to build the Falco kernel module driver using different GCC versions available in the current environment. [[#1408](https://github.com/falcosecurity/falco/pull/1408)] - [@fntlnz](https://github.com/fntlnz)
|
|
||||||
* new: tgz (tarball) containing the statically-linked (musl) binary of Falco is now automatically built and published on bintray [[#1377](https://github.com/falcosecurity/falco/pull/1377)] - [@leogr](https://github.com/leogr)
|
|
||||||
|
|
||||||
|
|
||||||
### Minor Changes
|
|
||||||
|
|
||||||
* update: bump Falco engine version to 7 [[#1381](https://github.com/falcosecurity/falco/pull/1381)] - [@leogr](https://github.com/leogr)
|
|
||||||
* update: the required_engine_version is now on by default [[#1381](https://github.com/falcosecurity/falco/pull/1381)] - [@leogr](https://github.com/leogr)
|
|
||||||
* update: falcosecurity/falco-no-driver image now uses the statically-linked Falco [[#1377](https://github.com/falcosecurity/falco/pull/1377)] - [@leogr](https://github.com/leogr)
|
|
||||||
* docs(proposals): artifacts storage [[#1375](https://github.com/falcosecurity/falco/pull/1375)] - [@leodido](https://github.com/leodido)
|
|
||||||
* docs(proposals): artifacts cleanup [[#1375](https://github.com/falcosecurity/falco/pull/1375)] - [@leodido](https://github.com/leodido)
|
|
||||||
|
|
||||||
|
|
||||||
### Rule Changes
|
|
||||||
|
|
||||||
* rule(macro inbound_outbound): add brackets to disambiguate operator precedence [[#1373](https://github.com/falcosecurity/falco/pull/1373)] - [@ldegio](https://github.com/ldegio)
|
|
||||||
* rule(macro redis_writing_conf): add brackets to disambiguate operator precedence [[#1373](https://github.com/falcosecurity/falco/pull/1373)] - [@ldegio](https://github.com/ldegio)
|
|
||||||
* rule(macro run_by_foreman): add brackets to disambiguate operator precedence [[#1373](https://github.com/falcosecurity/falco/pull/1373)] - [@ldegio](https://github.com/ldegio)
|
|
||||||
* rule(macro consider_packet_socket_communication): enable "Packet socket created in container" rule by default. [[#1402](https://github.com/falcosecurity/falco/pull/1402)] - [@rung](https://github.com/rung)
|
|
||||||
* rule(Delete or rename shell history): skip docker overlay filesystems when considering bash history [[#1393](https://github.com/falcosecurity/falco/pull/1393)] - [@mstemm](https://github.com/mstemm)
|
|
||||||
* rule(Disallowed K8s User): quote colons in user names [[#1393](https://github.com/falcosecurity/falco/pull/1393)] - [@mstemm](https://github.com/mstemm)
|
|
||||||
* rule(macro falco_sensitive_mount_containers): Adds a trailing slash to avoid repo naming issues [[#1394](https://github.com/falcosecurity/falco/pull/1394)] - [@bgeesaman](https://github.com/bgeesaman)
|
|
||||||
* rule: adds user.loginuid to the default Falco rules that also contain user.name [[#1369](https://github.com/falcosecurity/falco/pull/1369)] - [@csschwe](https://github.com/csschwe)
|
|
||||||
|
|
||||||
## v0.25.0
|
|
||||||
|
|
||||||
Released on 2020-08-25
|
|
||||||
|
|
||||||
### Major Changes
|
|
||||||
|
|
||||||
* new(userspace/falco): print the Falco and driver versions at the very beginning of the output. [[#1303](https://github.com/falcosecurity/falco/pull/1303)] - [@leogr](https://github.com/leogr)
|
|
||||||
* new: libyaml is now bundled in the release process. Users can now avoid installing libyaml directly when getting Falco from the official release. [[#1252](https://github.com/falcosecurity/falco/pull/1252)] - [@fntlnz](https://github.com/fntlnz)
|
|
||||||
|
|
||||||
|
|
||||||
### Minor Changes
|
|
||||||
|
|
||||||
* docs(test): step-by-step instructions to run integration tests locally [[#1313](https://github.com/falcosecurity/falco/pull/1313)] - [@leodido](https://github.com/leodido)
|
|
||||||
* update: renameat2 syscall support [[#1355](https://github.com/falcosecurity/falco/pull/1355)] - [@fntlnz](https://github.com/fntlnz)
|
|
||||||
* update: support for 5.8.x kernels [[#1355](https://github.com/falcosecurity/falco/pull/1355)] - [@fntlnz](https://github.com/fntlnz)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* fix(userspace/falco): correct the fallback mechanism for loading the kernel module [[#1366](https://github.com/falcosecurity/falco/pull/1366)] - [@leogr](https://github.com/leogr)
|
|
||||||
* fix(falco-driver-loader): script crashing when using arguments [[#1330](https://github.com/falcosecurity/falco/pull/1330)] - [@antoinedeschenes](https://github.com/antoinedeschenes)
|
|
||||||
|
|
||||||
|
|
||||||
### Rule Changes
|
|
||||||
|
|
||||||
* rule(macro user_trusted_containers): add `sysdig/node-image-analyzer` and `sysdig/agent-slim` [[#1321](https://github.com/falcosecurity/falco/pull/1321)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(macro falco_privileged_images): add `docker.io/falcosecurity/falco` [[#1326](https://github.com/falcosecurity/falco/pull/1326)] - [@nvanheuverzwijn](https://github.com/nvanheuverzwijn)
|
|
||||||
* rule(EphemeralContainers Created): add new rule to detect ephemeral container created [[#1339](https://github.com/falcosecurity/falco/pull/1339)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(macro user_read_sensitive_file_containers): replace endswiths with exact image repo name [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(macro user_trusted_containers): replace endswiths with exact image repo name [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(macro user_privileged_containers): replace endswiths with exact image repo name [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(macro trusted_images_query_miner_domain_dns): replace endswiths with exact image repo name [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(macro falco_privileged_containers): append "/" to quay.io/sysdig [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(list falco_privileged_images): add images docker.io/sysdig/agent-slim and docker.io/sysdig/node-image-analyzer [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(list falco_sensitive_mount_images): add image docker.io/sysdig/agent-slim [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(list k8s_containers): prepend docker.io to images [[#1349](https://github.com/falcosecurity/falco/pull/1349)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(macro exe_running_docker_save): add better support for centos [[#1350](https://github.com/falcosecurity/falco/pull/1350)] - [@admiral0](https://github.com/admiral0)
|
|
||||||
* rule(macro rename): add `renameat2` syscall [[#1359](https://github.com/falcosecurity/falco/pull/1359)] - [@leogr](https://github.com/leogr)
|
|
||||||
* rule(Read sensitive file untrusted): add trusted images into whitelist [[#1327](https://github.com/falcosecurity/falco/pull/1327)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(Pod Created in Kube Namespace): add new list k8s_image_list as white list [[#1336](https://github.com/falcosecurity/falco/pull/1336)] - [@Kaizhe](https://github.com/Kaizhe)
|
|
||||||
* rule(list allowed_k8s_users): add "kubernetes-admin" user [[#1323](https://github.com/falcosecurity/falco/pull/1323)] - [@leogr](https://github.com/leogr)
|
|
||||||
|
|
||||||
## v0.24.0
|
## v0.24.0
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ project(falco)
|
|||||||
|
|
||||||
option(USE_BUNDLED_DEPS "Bundle hard to find dependencies into the Falco binary" OFF)
|
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)
|
option(BUILD_WARNINGS_AS_ERRORS "Enable building with -Wextra -Werror flags" OFF)
|
||||||
option(MINIMAL_BUILD "Build a minimal version of Falco, containing only the engine and basic input/output (EXPERIMENTAL)" OFF)
|
|
||||||
option(MUSL_OPTIMIZED_BUILD "Enable if you want a musl optimized build" OFF)
|
|
||||||
|
|
||||||
# Elapsed time
|
# Elapsed time
|
||||||
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add a flag to enable this
|
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add a flag to enable this
|
||||||
@@ -52,15 +50,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
if(MINIMAL_BUILD)
|
set(CMAKE_COMMON_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS}")
|
||||||
set(MINIMAL_BUILD_FLAGS "-DMINIMAL_BUILD")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(MUSL_OPTIMIZED_BUILD)
|
|
||||||
set(MUSL_FLAGS "-static -Os")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_COMMON_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
|
|
||||||
|
|
||||||
if(BUILD_WARNINGS_AS_ERRORS)
|
if(BUILD_WARNINGS_AS_ERRORS)
|
||||||
set(CMAKE_SUPPRESSED_WARNINGS
|
set(CMAKE_SUPPRESSED_WARNINGS
|
||||||
@@ -83,7 +73,7 @@ include(GetFalcoVersion)
|
|||||||
set(PACKAGE_NAME "falco")
|
set(PACKAGE_NAME "falco")
|
||||||
set(PROBE_NAME "falco")
|
set(PROBE_NAME "falco")
|
||||||
set(PROBE_DEVICE_NAME "falco")
|
set(PROBE_DEVICE_NAME "falco")
|
||||||
set(DRIVERS_REPO "https://download.falco.org/driver")
|
set(DRIVERS_REPO "https://dl.bintray.com/falcosecurity/driver")
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
set(CMAKE_INSTALL_PREFIX
|
set(CMAKE_INSTALL_PREFIX
|
||||||
/usr
|
/usr
|
||||||
@@ -115,31 +105,77 @@ set(CURSES_NEED_NCURSES TRUE)
|
|||||||
find_package(Curses REQUIRED)
|
find_package(Curses REQUIRED)
|
||||||
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
|
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
|
||||||
|
|
||||||
# b64
|
# libb64
|
||||||
include(b64)
|
|
||||||
|
set(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
|
||||||
|
message(STATUS "Using bundled b64 in '${B64_SRC}'")
|
||||||
|
set(B64_INCLUDE "${B64_SRC}/include")
|
||||||
|
set(B64_LIB "${B64_SRC}/src/libb64.a")
|
||||||
|
ExternalProject_Add(
|
||||||
|
b64
|
||||||
|
URL "https://github.com/libb64/libb64/archive/v1.2.1.zip"
|
||||||
|
URL_HASH "SHA256=665134c2b600098a7ebd3d00b6a866cb34909a6d48e0e37a0eda226a4ad2638a"
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ${CMD_MAKE}
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
INSTALL_COMMAND "")
|
||||||
|
|
||||||
# yaml-cpp
|
# yaml-cpp
|
||||||
include(yaml-cpp)
|
include(yaml-cpp)
|
||||||
|
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
# OpenSSL
|
# OpenSSL
|
||||||
include(OpenSSL)
|
include(OpenSSL)
|
||||||
|
|
||||||
# libcurl
|
# libcurl
|
||||||
include(cURL)
|
include(cURL)
|
||||||
endif()
|
|
||||||
|
|
||||||
# LuaJIT
|
# LuaJIT
|
||||||
include(luajit)
|
set(LUAJIT_SRC "${PROJECT_BINARY_DIR}/luajit-prefix/src/luajit/src")
|
||||||
|
message(STATUS "Using bundled LuaJIT in '${LUAJIT_SRC}'")
|
||||||
|
set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
|
||||||
|
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
|
||||||
|
ExternalProject_Add(
|
||||||
|
luajit
|
||||||
|
URL "https://github.com/LuaJIT/LuaJIT/archive/v2.0.3.tar.gz"
|
||||||
|
URL_HASH "SHA256=8da3d984495a11ba1bce9a833ba60e18b532ca0641e7d90d97fafe85ff014baa"
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ${CMD_MAKE}
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
INSTALL_COMMAND "")
|
||||||
|
|
||||||
# Lpeg
|
# Lpeg
|
||||||
include(lpeg)
|
set(LPEG_SRC "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg")
|
||||||
|
set(LPEG_LIB "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg/build/lpeg.a")
|
||||||
|
message(STATUS "Using bundled lpeg in '${LPEG_SRC}'")
|
||||||
|
set(LPEG_DEPENDENCIES "")
|
||||||
|
list(APPEND LPEG_DEPENDENCIES "luajit")
|
||||||
|
ExternalProject_Add(
|
||||||
|
lpeg
|
||||||
|
DEPENDS ${LPEG_DEPENDENCIES}
|
||||||
|
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
|
||||||
|
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
|
||||||
|
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
INSTALL_COMMAND "")
|
||||||
|
|
||||||
# libyaml
|
# libyaml
|
||||||
include(libyaml)
|
include(libyaml)
|
||||||
|
|
||||||
# lyaml
|
# lyaml
|
||||||
include(lyaml)
|
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
|
||||||
|
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
|
||||||
|
message(STATUS "Using bundled lyaml in '${LYAML_SRC}'")
|
||||||
|
ExternalProject_Add(
|
||||||
|
lyaml
|
||||||
|
DEPENDS luajit libyaml
|
||||||
|
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
|
||||||
|
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
|
||||||
|
BUILD_COMMAND ${CMD_MAKE}
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
CONFIGURE_COMMAND ./configure --enable-static CFLAGS=-I${LIBYAML_INSTALL_DIR}/include CPPFLAGS=-I${LIBYAML_INSTALL_DIR}/include LDFLAGS=-L${LIBYAML_INSTALL_DIR}/lib LIBS=-lyaml LUA=${LUAJIT_SRC}/luajit LUA_INCLUDE=-I${LUAJIT_INCLUDE}
|
||||||
|
INSTALL_COMMAND sh -c
|
||||||
|
"cp -R ${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/lib/* ${PROJECT_SOURCE_DIR}/userspace/engine/lua")
|
||||||
|
|
||||||
# One TBB
|
# One TBB
|
||||||
set(TBB_SRC "${PROJECT_BINARY_DIR}/tbb-prefix/src/tbb")
|
set(TBB_SRC "${PROJECT_BINARY_DIR}/tbb-prefix/src/tbb")
|
||||||
@@ -158,7 +194,6 @@ ExternalProject_Add(
|
|||||||
BUILD_BYPRODUCTS ${TBB_LIB}
|
BUILD_BYPRODUCTS ${TBB_LIB}
|
||||||
INSTALL_COMMAND "")
|
INSTALL_COMMAND "")
|
||||||
|
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
# civetweb
|
# civetweb
|
||||||
set(CIVETWEB_SRC "${PROJECT_BINARY_DIR}/civetweb-prefix/src/civetweb/")
|
set(CIVETWEB_SRC "${PROJECT_BINARY_DIR}/civetweb-prefix/src/civetweb/")
|
||||||
set(CIVETWEB_LIB "${CIVETWEB_SRC}/install/lib/libcivetweb.a")
|
set(CIVETWEB_LIB "${CIVETWEB_SRC}/install/lib/libcivetweb.a")
|
||||||
@@ -172,20 +207,13 @@ if(NOT MINIMAL_BUILD)
|
|||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/include
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/include
|
||||||
BUILD_IN_SOURCE 1
|
BUILD_IN_SOURCE 1
|
||||||
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
|
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
|
||||||
BUILD_BYPRODUCTS ${CIVETWEB_LIB}
|
|
||||||
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
|
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
|
||||||
endif()
|
|
||||||
|
|
||||||
#string-view-lite
|
#string-view-lite
|
||||||
include(DownloadStringViewLite)
|
include(DownloadStringViewLite)
|
||||||
|
|
||||||
# cxxopts
|
|
||||||
include(DownloadCxxOpts)
|
|
||||||
|
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
# gRPC
|
# gRPC
|
||||||
include(gRPC)
|
include(gRPC)
|
||||||
endif()
|
|
||||||
|
|
||||||
# sysdig
|
# sysdig
|
||||||
include(sysdig)
|
include(sysdig)
|
||||||
@@ -193,13 +221,11 @@ include(sysdig)
|
|||||||
# Installation
|
# Installation
|
||||||
install(FILES falco.yaml DESTINATION "${FALCO_ETC_DIR}")
|
install(FILES falco.yaml DESTINATION "${FALCO_ETC_DIR}")
|
||||||
|
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
# Coverage
|
# Coverage
|
||||||
include(Coverage)
|
include(Coverage)
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
|
||||||
|
|
||||||
# Rules
|
# Rules
|
||||||
add_subdirectory(rules)
|
add_subdirectory(rules)
|
||||||
@@ -210,9 +236,6 @@ add_subdirectory(docker)
|
|||||||
# Clang format
|
# Clang format
|
||||||
# add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:falco,SOURCES> COMMENT "Formatting ..." VERBATIM)
|
# add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:falco,SOURCES> COMMENT "Formatting ..." VERBATIM)
|
||||||
|
|
||||||
# Static analysis
|
|
||||||
include(static-analysis)
|
|
||||||
|
|
||||||
# Shared build variables
|
# Shared build variables
|
||||||
set(FALCO_SINSP_LIBRARY sinsp)
|
set(FALCO_SINSP_LIBRARY sinsp)
|
||||||
set(FALCO_SHARE_DIR share/falco)
|
set(FALCO_SHARE_DIR share/falco)
|
||||||
|
|||||||
16
README.md
16
README.md
@@ -5,9 +5,7 @@
|
|||||||
|
|
||||||
[](https://circleci.com/gh/falcosecurity/falco) [](https://bestpractices.coreinfrastructure.org/projects/2317) [](COPYING)
|
[](https://circleci.com/gh/falcosecurity/falco) [](https://bestpractices.coreinfrastructure.org/projects/2317) [](COPYING)
|
||||||
|
|
||||||
Want to talk? Join us on the [#falco](https://kubernetes.slack.com/archives/CMWH3EH32) channel in the [Kubernetes Slack](https://slack.k8s.io).
|
#### Latest releases
|
||||||
|
|
||||||
### Latest releases
|
|
||||||
|
|
||||||
Read the [change log](CHANGELOG.md).
|
Read the [change log](CHANGELOG.md).
|
||||||
|
|
||||||
@@ -41,7 +39,7 @@ If you would like to run Falco in **production** please adhere to the [official
|
|||||||
|
|
||||||
Falco is designed to be extensible such that it can be built into cloud-native applications and infrastructure.
|
Falco is designed to be extensible such that it can be built into cloud-native applications and infrastructure.
|
||||||
|
|
||||||
Falco has a [gRPC](https://falco.org/docs/grpc/) endpoint and an API defined in [protobuf](https://github.com/falcosecurity/falco/blob/master/userspace/falco/outputs.proto).
|
Falco has a [gRPC](https://falco.org/docs/grpc/) endpoint and an API defined in [protobuf](https://github.com/falcosecurity/falco/blob/update-readme/userspace/falco/outputs.proto).
|
||||||
The Falco Project supports various SDKs for this endpoint.
|
The Falco Project supports various SDKs for this endpoint.
|
||||||
|
|
||||||
##### SDKs
|
##### SDKs
|
||||||
@@ -65,7 +63,6 @@ For example, Falco can easily detect incidents including but not limited to:
|
|||||||
- Unexpected read of a sensitive file, such as `/etc/shadow`.
|
- Unexpected read of a sensitive file, such as `/etc/shadow`.
|
||||||
- A non-device file is written to `/dev`.
|
- A non-device file is written to `/dev`.
|
||||||
- A standard system binary, such as `ls`, is making an outbound network connection.
|
- A standard system binary, such as `ls`, is making an outbound network connection.
|
||||||
- A privileged pod is started in a Kubernetes cluster.
|
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
@@ -75,16 +72,9 @@ The [Official Documentation](https://falco.org/docs/) is the best resource to le
|
|||||||
|
|
||||||
To get involved with The Falco Project please visit [the community repository](https://github.com/falcosecurity/community) to find more.
|
To get involved with The Falco Project please visit [the community repository](https://github.com/falcosecurity/community) to find more.
|
||||||
|
|
||||||
How to reach out?
|
|
||||||
|
|
||||||
- Join the #falco channel on the [Kubernetes Slack](https://slack.k8s.io)
|
|
||||||
- [Join the Falco mailing list](https://lists.cncf.io/g/cncf-falco-dev)
|
|
||||||
- [Read the Falco documentation](https://falco.org/docs/)
|
|
||||||
|
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
|
|
||||||
See the [CONTRIBUTING.md](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md).
|
See the [CONTRIBUTING.md](./CONTRIBUTING.md).
|
||||||
|
|
||||||
### Security Audit
|
### Security Audit
|
||||||
|
|
||||||
|
|||||||
43
RELEASE.md
43
RELEASE.md
@@ -4,21 +4,19 @@ Our release process is mostly automated, but we still need some manual steps to
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
A release happens every two months ([as per community discussion](https://github.com/falcosecurity/community/blob/master/meeting-notes/2020-09-30.md#agenda)), 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.
|
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.
|
||||||
|
|
||||||
Finally, on the proposed due date the assignees for the upcoming release proceed with the processes described below.
|
Finally, on the proposed due date the assignees for the upcoming release proceed with the processes described below.
|
||||||
|
|
||||||
## Pre-Release Checklist
|
## Pre-Release Checklist
|
||||||
|
|
||||||
Before cutting a release we need to do some homework in the Falco repository. This should take 5 minutes using the GitHub UI.
|
|
||||||
|
|
||||||
### 1. Release notes
|
### 1. Release notes
|
||||||
- Find the LAST release (-1) and use `YYYY-MM-DD` as the day before of the [latest release](https://github.com/falcosecurity/falco/releases)
|
- 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:>YYYY-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
|
- 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
|
- 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:>YYYY-MM-DD](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+no%3Amilestone+closed%3A%3EYYYY-MM-DD) filter) and add them 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:>YYYY-MM-DD` [filters](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+no%3Amilestone+closed%3A%3EYYYY-MM-DD), if any, fix them
|
- 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
|
### 2. Milestones
|
||||||
|
|
||||||
@@ -30,15 +28,14 @@ Before cutting a release we need to do some homework in the Falco repository. Th
|
|||||||
- If any, manually correct it then open an issue to automate version number bumping later
|
- If any, manually correct it then open an issue to automate version number bumping later
|
||||||
- Versions table in the `README.md` update itself automatically
|
- 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)
|
||||||
- If you review timeout errors with `rn2md` try to generate an GitHub Oauth access token and use `-t`
|
- Add the lastest changes on top the previous `CHANGELOG.md`
|
||||||
- Add the latest changes on top the previous `CHANGELOG.md`
|
|
||||||
- Submit a PR with the above modifications
|
- Submit a PR with the above modifications
|
||||||
- Await PR approval
|
- Await PR approval
|
||||||
- Close the completed milestone as soon as the PR is merged
|
- Close the completed milestone as soon PR is merged
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
|
|
||||||
Now assume `x.y.z` is the new version.
|
Let `x.y.z` the new version.
|
||||||
|
|
||||||
### 1. Create a tag
|
### 1. Create a tag
|
||||||
|
|
||||||
@@ -61,26 +58,12 @@ Now assume `x.y.z` is the new version.
|
|||||||
- Use `x.y.z` both as tag version and release title
|
- Use `x.y.z` both as tag version and release title
|
||||||
- Use the following template to fill the release description:
|
- Use the following template to fill the release description:
|
||||||
```
|
```
|
||||||
<!-- Substitute x.y.z with the current release version -->
|
|
||||||
|
|
||||||
| Packages | Download |
|
|
||||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
||||||
| rpm | [](https://dl.bintray.com/falcosecurity/rpm/falco-x.y.z-x86_64.rpm) |
|
|
||||||
| deb | [](https://dl.bintray.com/falcosecurity/deb/stable/falco-x.y.z-x86_64.deb) |
|
|
||||||
| tgz | [](https://dl.bintray.com/falcosecurity/bin/x86_64/falco-x.y.z-x86_64.deb) |
|
|
||||||
|
|
||||||
| Images |
|
|
||||||
| --------------------------------------------------------------- |
|
|
||||||
| `docker pull docker.io/falcosecurity/falco:_tag_` |
|
|
||||||
| `docker pull docker.io/falcosecurity/falco-driver-loader:_tag_` |
|
|
||||||
| `docker pull docker.io/falcosecurity/falco-no-driver:_tag_` |
|
|
||||||
|
|
||||||
<!-- Copy the relevant part of the changelog here -->
|
<!-- Copy the relevant part of the changelog here -->
|
||||||
|
|
||||||
### Statistics
|
### Statistics
|
||||||
|
|
||||||
| Merged PRs | Number |
|
| Merged PRs | Number |
|
||||||
| --------------- | ------ |
|
|-------------------|---------|
|
||||||
| Not user-facing | x |
|
| Not user-facing | x |
|
||||||
| Release note | x |
|
| Release note | x |
|
||||||
| Total | x |
|
| Total | x |
|
||||||
@@ -90,16 +73,6 @@ Now assume `x.y.z` is the new version.
|
|||||||
|
|
||||||
- Finally, publish the release!
|
- Finally, publish the release!
|
||||||
|
|
||||||
### 3. Update the meeting notes
|
|
||||||
|
|
||||||
For each release we archive the meeting notes in git for historical purposes.
|
|
||||||
|
|
||||||
- The notes from the Falco meetings can be [found here](https://hackmd.io/6sEAlInlSaGnLz2FnFz21A).
|
|
||||||
- Note: There may be other notes from working groups that can optionally be added as well as needed.
|
|
||||||
- Add the entire content of the document to a new file in [github.com/falcosecurity/community/tree/master/meeting-notes](https://github.com/falcosecurity/community/tree/master/meeting-notes) as a new file labeled `release-x.y.z.md`
|
|
||||||
- Open up a pull request with the new change.
|
|
||||||
|
|
||||||
|
|
||||||
## Post-Release tasks
|
## Post-Release tasks
|
||||||
|
|
||||||
Announce the new release to the world!
|
Announce the new release to the world!
|
||||||
|
|||||||
@@ -15,21 +15,6 @@ There are 3 logos available for use in this directory. Use the primary logo unle
|
|||||||
|
|
||||||
The Falco logo is Apache 2 licensed and free to use in media and publication for the CNCF Falco project.
|
The Falco logo is Apache 2 licensed and free to use in media and publication for the CNCF Falco project.
|
||||||
|
|
||||||
### Colors
|
|
||||||
|
|
||||||
| Name | PMS | RGB |
|
|
||||||
|-----------|------|-------------|
|
|
||||||
| Teal | 3125 | 0 174 199 |
|
|
||||||
| Cool Gray | 11 | 83 86 90 |
|
|
||||||
| Black | | 0 0 0 |
|
|
||||||
| Blue-Gray | 7700 | 22 92 125 |
|
|
||||||
| Gold | 1375 | 255 158 27 |
|
|
||||||
| Orange | 171 | 255 92 57 |
|
|
||||||
| Emerald | 3278 | 0 155 119 |
|
|
||||||
| Green | 360 | 108 194 74 |
|
|
||||||
|
|
||||||
The primary colors are those in the first two rows.
|
|
||||||
|
|
||||||
### Slogan
|
### Slogan
|
||||||
|
|
||||||
> Cloud Native Runtime Security
|
> Cloud Native Runtime Security
|
||||||
|
|||||||
@@ -25,20 +25,10 @@ set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_SOURCE_DIR}/cmake/cpack/CMakeCPackOptio
|
|||||||
set(CPACK_STRIP_FILES "ON")
|
set(CPACK_STRIP_FILES "ON")
|
||||||
set(CPACK_PACKAGE_RELOCATABLE "OFF")
|
set(CPACK_PACKAGE_RELOCATABLE "OFF")
|
||||||
|
|
||||||
if(NOT CPACK_GENERATOR)
|
|
||||||
set(CPACK_GENERATOR DEB RPM TGZ)
|
set(CPACK_GENERATOR DEB RPM TGZ)
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Using package generators: ${CPACK_GENERATOR}")
|
|
||||||
message(STATUS "Package architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
|
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
||||||
endif()
|
|
||||||
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
|
||||||
endif()
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.falco.org")
|
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.falco.org")
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0)")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0)")
|
||||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
|
||||||
# the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
include(ExternalProject)
|
|
||||||
|
|
||||||
set(CXXOPTS_PREFIX ${CMAKE_BINARY_DIR}/cxxopts-prefix)
|
|
||||||
set(CXXOPTS_INCLUDE ${CXXOPTS_PREFIX}/include)
|
|
||||||
message(STATUS "Using bundled cxxopts in ${CXXOPTS_INCLUDE}")
|
|
||||||
|
|
||||||
ExternalProject_Add(
|
|
||||||
cxxopts
|
|
||||||
PREFIX ${CXXOPTS_PREFIX}
|
|
||||||
GIT_REPOSITORY "https://github.com/jarro2783/cxxopts.git"
|
|
||||||
GIT_TAG "master"
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ""
|
|
||||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CXXOPTS_PREFIX}/src/cxxopts/include/cxxopts.hpp
|
|
||||||
${CXXOPTS_INCLUDE}/cxxopts.hpp)
|
|
||||||
@@ -15,7 +15,7 @@ include(ExternalProject)
|
|||||||
|
|
||||||
set(STRING_VIEW_LITE_PREFIX ${CMAKE_BINARY_DIR}/string-view-lite-prefix)
|
set(STRING_VIEW_LITE_PREFIX ${CMAKE_BINARY_DIR}/string-view-lite-prefix)
|
||||||
set(STRING_VIEW_LITE_INCLUDE ${STRING_VIEW_LITE_PREFIX}/include)
|
set(STRING_VIEW_LITE_INCLUDE ${STRING_VIEW_LITE_PREFIX}/include)
|
||||||
message(STATUS "Using bundled string-view-lite in ${STRING_VIEW_LITE_INCLUDE}")
|
message(STATUS "Found string-view-lite: include: ${STRING_VIEW_LITE_INCLUDE}")
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
string-view-lite
|
string-view-lite
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
|
||||||
# the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
set(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
|
|
||||||
message(STATUS "Using bundled b64 in '${B64_SRC}'")
|
|
||||||
set(B64_INCLUDE "${B64_SRC}/include")
|
|
||||||
set(B64_LIB "${B64_SRC}/src/libb64.a")
|
|
||||||
externalproject_add(
|
|
||||||
b64
|
|
||||||
URL "https://github.com/libb64/libb64/archive/ce864b17ea0e24a91e77c7dd3eb2d1ac4175b3f0.tar.gz"
|
|
||||||
URL_HASH "SHA256=d07173e66f435e5c77dbf81bd9313f8d0e4a3b4edd4105a62f4f8132ba932811"
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ${CMD_MAKE}
|
|
||||||
BUILD_IN_SOURCE 1
|
|
||||||
BUILD_BYPRODUCTS ${B64_LIB}
|
|
||||||
INSTALL_COMMAND ""
|
|
||||||
)
|
|
||||||
@@ -96,17 +96,12 @@ else()
|
|||||||
# that zlib will be very outdated
|
# that zlib will be very outdated
|
||||||
set(ZLIB_INCLUDE "${GRPC_SRC}/third_party/zlib")
|
set(ZLIB_INCLUDE "${GRPC_SRC}/third_party/zlib")
|
||||||
set(ZLIB_LIB "${GRPC_LIBS_ABSOLUTE}/libz.a")
|
set(ZLIB_LIB "${GRPC_LIBS_ABSOLUTE}/libz.a")
|
||||||
# we tell gRPC to compile c-ares for us because when a gRPC package is not available, like on CentOS, it's very likely
|
|
||||||
# that c-ares will be very outdated
|
|
||||||
set(CARES_INCLUDE "${GRPC_SRC}/third_party/cares" "${GRPC_SRC}/third_party/cares/cares")
|
|
||||||
set(CARES_LIB "${GRPC_LIBS_ABSOLUTE}/libares.a")
|
|
||||||
|
|
||||||
message(STATUS "Using bundled gRPC in '${GRPC_SRC}'")
|
message(STATUS "Using bundled gRPC in '${GRPC_SRC}'")
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"Bundled gRPC comes with protobuf: compiler: ${PROTOC}, include: ${PROTOBUF_INCLUDE}, lib: ${PROTOBUF_LIB}")
|
"Bundled gRPC comes with protobuf: compiler: ${PROTOC}, include: ${PROTOBUF_INCLUDE}, lib: ${PROTOBUF_LIB}")
|
||||||
message(STATUS "Bundled gRPC comes with zlib: include: ${ZLIB_INCLUDE}, lib: ${ZLIB_LIB}}")
|
message(STATUS "Bundled gRPC comes with zlib: include: ${ZLIB_INCLUDE}, lib: ${ZLIB_LIB}}")
|
||||||
message(STATUS "Bundled gRPC comes with cares: include: ${CARES_INCLUDE}, lib: ${CARES_LIB}}")
|
|
||||||
message(STATUS "Bundled gRPC comes with gRPC C++ plugin: include: ${GRPC_CPP_PLUGIN}")
|
message(STATUS "Bundled gRPC comes with gRPC C++ plugin: include: ${GRPC_CPP_PLUGIN}")
|
||||||
|
|
||||||
get_filename_component(PROTOC_DIR ${PROTOC} PATH)
|
get_filename_component(PROTOC_DIR ${PROTOC} PATH)
|
||||||
@@ -115,7 +110,7 @@ else()
|
|||||||
grpc
|
grpc
|
||||||
DEPENDS openssl
|
DEPENDS openssl
|
||||||
GIT_REPOSITORY https://github.com/grpc/grpc.git
|
GIT_REPOSITORY https://github.com/grpc/grpc.git
|
||||||
GIT_TAG v1.32.0
|
GIT_TAG v1.31.1
|
||||||
GIT_SUBMODULES "third_party/protobuf third_party/zlib third_party/cares/cares third_party/abseil-cpp third_party/re2"
|
GIT_SUBMODULES "third_party/protobuf third_party/zlib third_party/cares/cares third_party/abseil-cpp third_party/re2"
|
||||||
BUILD_IN_SOURCE 1
|
BUILD_IN_SOURCE 1
|
||||||
BUILD_BYPRODUCTS ${GRPC_LIB} ${GRPCPP_LIB}
|
BUILD_BYPRODUCTS ${GRPC_LIB} ${GRPCPP_LIB}
|
||||||
|
|||||||
@@ -15,13 +15,12 @@ set(LIBYAML_SRC "${PROJECT_BINARY_DIR}/libyaml-prefix/src/libyaml")
|
|||||||
set(LIBYAML_INSTALL_DIR "${LIBYAML_SRC}/target")
|
set(LIBYAML_INSTALL_DIR "${LIBYAML_SRC}/target")
|
||||||
message(STATUS "Using bundled libyaml in '${LIBYAML_SRC}'")
|
message(STATUS "Using bundled libyaml in '${LIBYAML_SRC}'")
|
||||||
set(LIBYAML_LIB "${LIBYAML_SRC}/src/.libs/libyaml.a")
|
set(LIBYAML_LIB "${LIBYAML_SRC}/src/.libs/libyaml.a")
|
||||||
externalproject_add(
|
ExternalProject_Add(
|
||||||
libyaml
|
libyaml
|
||||||
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
|
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
|
||||||
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
|
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
|
||||||
CONFIGURE_COMMAND ./configure --prefix=${LIBYAML_INSTALL_DIR} CFLAGS=-fPIC CPPFLAGS=-fPIC --enable-static=true --enable-shared=false
|
CONFIGURE_COMMAND ./configure --prefix=${LIBYAML_INSTALL_DIR} CFLAGS=-fPIC CPPFLAGS=-fPIC --enable-static=true --enable-shared=false
|
||||||
BUILD_COMMAND ${CMD_MAKE}
|
BUILD_COMMAND ${CMD_MAKE}
|
||||||
BUILD_IN_SOURCE 1
|
BUILD_IN_SOURCE 1
|
||||||
BUILD_BYPRODUCTS ${LIBYAML_LIB}
|
INSTALL_COMMAND ${CMD_MAKE} install)
|
||||||
INSTALL_COMMAND ${CMD_MAKE} install
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
|
||||||
# the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
set(LPEG_SRC "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg")
|
|
||||||
set(LPEG_LIB "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg/build/lpeg.a")
|
|
||||||
message(STATUS "Using bundled lpeg in '${LPEG_SRC}'")
|
|
||||||
set(LPEG_DEPENDENCIES "")
|
|
||||||
list(APPEND LPEG_DEPENDENCIES "luajit")
|
|
||||||
ExternalProject_Add(
|
|
||||||
lpeg
|
|
||||||
DEPENDS ${LPEG_DEPENDENCIES}
|
|
||||||
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
|
|
||||||
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
|
|
||||||
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
|
|
||||||
BUILD_IN_SOURCE 1
|
|
||||||
BUILD_BYPRODUCTS ${LPEG_LIB}
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
INSTALL_COMMAND "")
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
|
||||||
# the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
set(LUAJIT_SRC "${PROJECT_BINARY_DIR}/luajit-prefix/src/luajit/src")
|
|
||||||
message(STATUS "Using bundled LuaJIT in '${LUAJIT_SRC}'")
|
|
||||||
set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
|
|
||||||
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
|
|
||||||
externalproject_add(
|
|
||||||
luajit
|
|
||||||
GIT_REPOSITORY "https://github.com/LuaJIT/LuaJIT"
|
|
||||||
GIT_TAG "1d8b747c161db457e032a023ebbff511f5de5ec2"
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ${CMD_MAKE}
|
|
||||||
BUILD_IN_SOURCE 1
|
|
||||||
BUILD_BYPRODUCTS ${LUAJIT_LIB}
|
|
||||||
INSTALL_COMMAND ""
|
|
||||||
)
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
|
||||||
# the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
|
|
||||||
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
|
|
||||||
message(STATUS "Using bundled lyaml in '${LYAML_SRC}'")
|
|
||||||
externalproject_add(
|
|
||||||
lyaml
|
|
||||||
DEPENDS luajit libyaml
|
|
||||||
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
|
|
||||||
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
|
|
||||||
BUILD_COMMAND ${CMD_MAKE}
|
|
||||||
BUILD_IN_SOURCE 1
|
|
||||||
BUILD_BYPRODUCTS ${LYAML_LIB}
|
|
||||||
CONFIGURE_COMMAND ./configure --enable-static CFLAGS=-I${LIBYAML_INSTALL_DIR}/include CPPFLAGS=-I${LIBYAML_INSTALL_DIR}/include LDFLAGS=-L${LIBYAML_INSTALL_DIR}/lib LIBS=-lyaml LUA=${LUAJIT_SRC}/luajit LUA_INCLUDE=-I${LUAJIT_INCLUDE}
|
|
||||||
INSTALL_COMMAND sh -c
|
|
||||||
"cp -R ${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/lib/* ${PROJECT_SOURCE_DIR}/userspace/engine/lua"
|
|
||||||
)
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# create the reports folder
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports)
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck)
|
|
||||||
|
|
||||||
# cppcheck
|
|
||||||
find_program(CPPCHECK cppcheck)
|
|
||||||
find_program(CPPCHECK_HTMLREPORT cppcheck-htmlreport)
|
|
||||||
|
|
||||||
if(NOT CPPCHECK)
|
|
||||||
message(STATUS "cppcheck command not found, static code analysis using cppcheck will not be available.")
|
|
||||||
else()
|
|
||||||
message(STATUS "cppcheck found at: ${CPPCHECK}")
|
|
||||||
# we are aware that cppcheck can be run
|
|
||||||
# along with the software compilation in a single step
|
|
||||||
# using the CMAKE_CXX_CPPCHECK variables.
|
|
||||||
# However, for practical needs we want to keep the
|
|
||||||
# two things separated and have a specific target for it.
|
|
||||||
# Our cppcheck target reads the compilation database produced by CMake
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS On)
|
|
||||||
add_custom_target(
|
|
||||||
cppcheck
|
|
||||||
COMMAND ${CPPCHECK}
|
|
||||||
"--enable=all"
|
|
||||||
"--force"
|
|
||||||
"--inconclusive"
|
|
||||||
"--inline-suppr" # allows to specify suppressions directly in source code
|
|
||||||
"--project=${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" # use the compilation database as source
|
|
||||||
"--quiet"
|
|
||||||
"--xml" # we want to generate a report
|
|
||||||
"--output-file=${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck/cppcheck.xml" # generate the report under the reports folder in the build folder
|
|
||||||
"-i${CMAKE_CURRENT_BINARY_DIR}"# exclude the build folder
|
|
||||||
)
|
|
||||||
endif() # CPPCHECK
|
|
||||||
|
|
||||||
if(NOT CPPCHECK_HTMLREPORT)
|
|
||||||
message(STATUS "cppcheck-htmlreport command not found, will not be able to produce html reports for cppcheck results")
|
|
||||||
else()
|
|
||||||
message(STATUS "cppcheck-htmlreport found at: ${CPPCHECK_HTMLREPORT}")
|
|
||||||
add_custom_target(
|
|
||||||
cppcheck_htmlreport
|
|
||||||
COMMAND ${CPPCHECK_HTMLREPORT} --title=${CMAKE_PROJECT_NAME} --report-dir=${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck --file=static-analysis-reports/cppcheck/cppcheck.xml)
|
|
||||||
endif() # CPPCHECK_HTMLREPORT
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
# Copyright (C) 2019 The Falco Authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
# 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
|
# the License. You may obtain a copy of the License at
|
||||||
@@ -25,4 +25,4 @@ ExternalProject_Add(
|
|||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
TEST_COMMAND ""
|
TEST_COMMAND ""
|
||||||
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch && patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/luajit.patch)
|
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c
|
diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c
|
||||||
index 6f51588e..5f9ea84e 100644
|
index e9faea51..a1b3b501 100644
|
||||||
--- a/userspace/libscap/scap.c
|
--- a/userspace/libscap/scap.c
|
||||||
+++ b/userspace/libscap/scap.c
|
+++ b/userspace/libscap/scap.c
|
||||||
@@ -55,7 +55,7 @@ limitations under the License.
|
@@ -52,7 +52,7 @@ limitations under the License.
|
||||||
//#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -11,16 +11,7 @@ index 6f51588e..5f9ea84e 100644
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Probe version string size
|
// Probe version string size
|
||||||
@@ -114,7 +114,7 @@ scap_t* scap_open_udig_int(char *error, int32_t *rc,
|
@@ -171,7 +171,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
||||||
static uint32_t get_max_consumers()
|
|
||||||
{
|
|
||||||
uint32_t max;
|
|
||||||
- FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers", "r");
|
|
||||||
+ FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers", "r");
|
|
||||||
if(pfile != NULL)
|
|
||||||
{
|
|
||||||
int w = fscanf(pfile, "%"PRIu32, &max);
|
|
||||||
@@ -186,7 +186,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,27 +20,7 @@ index 6f51588e..5f9ea84e 100644
|
|||||||
bpf_probe = buf;
|
bpf_probe = buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +344,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
@@ -1808,7 +1808,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
|
||||||
else if(errno == EBUSY)
|
|
||||||
{
|
|
||||||
uint32_t curr_max_consumers = get_max_consumers();
|
|
||||||
- snprintf(error, SCAP_LASTERR_SIZE, "Too many sysdig instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
|
|
||||||
+ snprintf(error, SCAP_LASTERR_SIZE, "Too many Falco instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@@ -579,8 +579,8 @@ scap_t* scap_open_udig_int(char *error, int32_t *rc,
|
|
||||||
//
|
|
||||||
// Map the ppm_ring_buffer_info that contains the buffer pointers
|
|
||||||
//
|
|
||||||
- if(udig_alloc_ring_descriptors(&(handle->m_devs[0].m_bufinfo_fd),
|
|
||||||
- &handle->m_devs[0].m_bufinfo,
|
|
||||||
+ if(udig_alloc_ring_descriptors(&(handle->m_devs[0].m_bufinfo_fd),
|
|
||||||
+ &handle->m_devs[0].m_bufinfo,
|
|
||||||
&handle->m_devs[0].m_bufstatus,
|
|
||||||
error) != SCAP_SUCCESS)
|
|
||||||
{
|
|
||||||
@@ -2175,7 +2175,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
|
|
||||||
|
|
||||||
const char* scap_get_host_root()
|
const char* scap_get_host_root()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
diff --git a/userspace/libsinsp/chisel.cpp b/userspace/libsinsp/chisel.cpp
|
|
||||||
index 0a6e3cf8..0c2e255a 100644
|
|
||||||
--- a/userspace/libsinsp/chisel.cpp
|
|
||||||
+++ b/userspace/libsinsp/chisel.cpp
|
|
||||||
@@ -98,7 +98,7 @@ void lua_stackdump(lua_State *L)
|
|
||||||
// Lua callbacks
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
#ifdef HAS_LUA_CHISELS
|
|
||||||
-const static struct luaL_reg ll_sysdig [] =
|
|
||||||
+const static struct luaL_Reg ll_sysdig [] =
|
|
||||||
{
|
|
||||||
{"set_filter", &lua_cbacks::set_global_filter},
|
|
||||||
{"set_snaplen", &lua_cbacks::set_snaplen},
|
|
||||||
@@ -134,7 +134,7 @@ const static struct luaL_reg ll_sysdig [] =
|
|
||||||
{NULL,NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
-const static struct luaL_reg ll_chisel [] =
|
|
||||||
+const static struct luaL_Reg ll_chisel [] =
|
|
||||||
{
|
|
||||||
{"request_field", &lua_cbacks::request_field},
|
|
||||||
{"set_filter", &lua_cbacks::set_filter},
|
|
||||||
@@ -146,7 +146,7 @@ const static struct luaL_reg ll_chisel [] =
|
|
||||||
{NULL,NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
-const static struct luaL_reg ll_evt [] =
|
|
||||||
+const static struct luaL_Reg ll_evt [] =
|
|
||||||
{
|
|
||||||
{"field", &lua_cbacks::field},
|
|
||||||
{"get_num", &lua_cbacks::get_num},
|
|
||||||
diff --git a/userspace/libsinsp/lua_parser.cpp b/userspace/libsinsp/lua_parser.cpp
|
|
||||||
index 0e26617d..78810d96 100644
|
|
||||||
--- a/userspace/libsinsp/lua_parser.cpp
|
|
||||||
+++ b/userspace/libsinsp/lua_parser.cpp
|
|
||||||
@@ -32,7 +32,7 @@ extern "C" {
|
|
||||||
#include "lauxlib.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
-const static struct luaL_reg ll_filter [] =
|
|
||||||
+const static struct luaL_Reg ll_filter [] =
|
|
||||||
{
|
|
||||||
{"rel_expr", &lua_parser_cbacks::rel_expr},
|
|
||||||
{"bool_op", &lua_parser_cbacks::bool_op},
|
|
||||||
diff --git a/userspace/libsinsp/lua_parser_api.cpp b/userspace/libsinsp/lua_parser_api.cpp
|
|
||||||
index c89e9126..c3d8008a 100644
|
|
||||||
--- a/userspace/libsinsp/lua_parser_api.cpp
|
|
||||||
+++ b/userspace/libsinsp/lua_parser_api.cpp
|
|
||||||
@@ -266,7 +266,7 @@ int lua_parser_cbacks::rel_expr(lua_State *ls)
|
|
||||||
string err = "Got non-table as in-expression operand\n";
|
|
||||||
throw sinsp_exception("parser API error");
|
|
||||||
}
|
|
||||||
- int n = luaL_getn(ls, 4); /* get size of table */
|
|
||||||
+ int n = lua_objlen (ls, 4); /* get size of table */
|
|
||||||
for (i=1; i<=n; i++)
|
|
||||||
{
|
|
||||||
lua_rawgeti(ls, 4, i);
|
|
||||||
@@ -17,9 +17,7 @@ set(SYSDIG_CMAKE_WORKING_DIR "${CMAKE_BINARY_DIR}/sysdig-repo")
|
|||||||
# this needs to be here at the top
|
# this needs to be here at the top
|
||||||
if(USE_BUNDLED_DEPS)
|
if(USE_BUNDLED_DEPS)
|
||||||
# explicitly force this dependency to use the bundled OpenSSL
|
# explicitly force this dependency to use the bundled OpenSSL
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
set(USE_BUNDLED_OPENSSL ON)
|
set(USE_BUNDLED_OPENSSL ON)
|
||||||
endif()
|
|
||||||
set(USE_BUNDLED_JQ ON)
|
set(USE_BUNDLED_JQ ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -29,8 +27,8 @@ file(MAKE_DIRECTORY ${SYSDIG_CMAKE_WORKING_DIR})
|
|||||||
# default below In case you want to test against another sysdig version just pass the variable - ie., `cmake
|
# default below In case you want to test against another sysdig version just pass the variable - ie., `cmake
|
||||||
# -DSYSDIG_VERSION=dev ..`
|
# -DSYSDIG_VERSION=dev ..`
|
||||||
if(NOT SYSDIG_VERSION)
|
if(NOT SYSDIG_VERSION)
|
||||||
set(SYSDIG_VERSION "5c0b863ddade7a45568c0ac97d037422c9efb750")
|
set(SYSDIG_VERSION "ae104eb20ff0198a5dcb0c91cc36c86e7c3f25c7")
|
||||||
set(SYSDIG_CHECKSUM "SHA256=9de717b3a4b611ea6df56afee05171860167112f74bb7717b394bcc88ac843cd")
|
set(SYSDIG_CHECKSUM "SHA256=43d274e4ce16b0d0e4dd00aab78006c902f36070d1cbb22d12a2685134a2ae51")
|
||||||
endif()
|
endif()
|
||||||
set(PROBE_VERSION "${SYSDIG_VERSION}")
|
set(PROBE_VERSION "${SYSDIG_VERSION}")
|
||||||
|
|
||||||
@@ -57,10 +55,6 @@ add_subdirectory("${SYSDIG_SOURCE_DIR}/driver" "${PROJECT_BINARY_DIR}/driver")
|
|||||||
# Add libscap directory
|
# Add libscap directory
|
||||||
add_definitions(-D_GNU_SOURCE)
|
add_definitions(-D_GNU_SOURCE)
|
||||||
add_definitions(-DHAS_CAPTURE)
|
add_definitions(-DHAS_CAPTURE)
|
||||||
add_definitions(-DNOCURSESUI)
|
|
||||||
if(MUSL_OPTIMIZED_BUILD)
|
|
||||||
add_definitions(-DMUSL_OPTIMIZED)
|
|
||||||
endif()
|
|
||||||
add_subdirectory("${SYSDIG_SOURCE_DIR}/userspace/libscap" "${PROJECT_BINARY_DIR}/userspace/libscap")
|
add_subdirectory("${SYSDIG_SOURCE_DIR}/userspace/libscap" "${PROJECT_BINARY_DIR}/userspace/libscap")
|
||||||
|
|
||||||
# Add libsinsp directory
|
# Add libsinsp directory
|
||||||
@@ -71,8 +65,5 @@ add_dependencies(sinsp tbb b64 luajit)
|
|||||||
set(CREATE_TEST_TARGETS OFF)
|
set(CREATE_TEST_TARGETS OFF)
|
||||||
|
|
||||||
if(USE_BUNDLED_DEPS)
|
if(USE_BUNDLED_DEPS)
|
||||||
add_dependencies(scap jq)
|
add_dependencies(scap grpc curl jq)
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
add_dependencies(scap curl grpc)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ case "$CMD" in
|
|||||||
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
-DBUILD_DRIVER="$BUILD_DRIVER" \
|
-DBUILD_DRIVER="$BUILD_DRIVER" \
|
||||||
-DMINIMAL_BUILD="$MINIMAL_BUILD" \
|
|
||||||
-DBUILD_BPF="$BUILD_BPF" \
|
-DBUILD_BPF="$BUILD_BPF" \
|
||||||
-DBUILD_WARNINGS_AS_ERRORS="$BUILD_WARNINGS_AS_ERRORS" \
|
-DBUILD_WARNINGS_AS_ERRORS="$BUILD_WARNINGS_AS_ERRORS" \
|
||||||
-DFALCO_VERSION="$FALCO_VERSION" \
|
-DFALCO_VERSION="$FALCO_VERSION" \
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ FROM falcosecurity/falco:${FALCO_IMAGE_TAG}
|
|||||||
|
|
||||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||||
|
|
||||||
LABEL usage="docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc:ro --name NAME IMAGE"
|
LABEL usage="docker run -i -t -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro --name NAME IMAGE"
|
||||||
|
|
||||||
ENV HOST_ROOT /host
|
ENV HOST_ROOT /host
|
||||||
ENV HOME /root
|
ENV HOME /root
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ FROM debian:stable
|
|||||||
|
|
||||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||||
|
|
||||||
LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc --name NAME IMAGE"
|
LABEL usage="docker run -i -t -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro --name NAME IMAGE"
|
||||||
|
|
||||||
ARG FALCO_VERSION=latest
|
ARG FALCO_VERSION=latest
|
||||||
ARG VERSION_BUCKET=deb
|
ARG VERSION_BUCKET=deb
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
FROM ubuntu:18.04 as ubuntu
|
FROM ubuntu:18.04 as ubuntu
|
||||||
|
|
||||||
|
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||||
|
|
||||||
ARG FALCO_VERSION
|
ARG FALCO_VERSION
|
||||||
ARG VERSION_BUCKET=bin
|
ARG VERSION_BUCKET=bin
|
||||||
|
|
||||||
@@ -10,23 +12,46 @@ WORKDIR /
|
|||||||
|
|
||||||
ADD https://bintray.com/api/ui/download/falcosecurity/${VERSION_BUCKET}/x86_64/falco-${FALCO_VERSION}-x86_64.tar.gz /
|
ADD https://bintray.com/api/ui/download/falcosecurity/${VERSION_BUCKET}/x86_64/falco-${FALCO_VERSION}-x86_64.tar.gz /
|
||||||
|
|
||||||
RUN tar -xvf 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 && \
|
rm -f falco-${FALCO_VERSION}-x86_64.tar.gz && \
|
||||||
mv falco-${FALCO_VERSION}-x86_64 falco && \
|
mv falco-${FALCO_VERSION}-x86_64 falco && \
|
||||||
rm -rf falco/usr/src/falco-* falco/usr/bin/falco-driver-loader
|
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 \
|
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
|
&& mv /falco/etc/falco/falco.yaml.new /falco/etc/falco/falco.yaml
|
||||||
|
|
||||||
FROM scratch
|
FROM scratch
|
||||||
|
|
||||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
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/
|
||||||
|
|
||||||
LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro --name NAME IMAGE"
|
COPY --from=ubuntu /usr/lib/x86_64-linux-gnu/libstdc++.so.6 \
|
||||||
# NOTE: for the "least privileged" use case, please refer to the official documentation
|
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
|
||||||
|
|
||||||
ENV HOST_ROOT /host
|
COPY --from=ubuntu /etc/ld.so.cache \
|
||||||
ENV HOME /root
|
/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 /
|
COPY --from=ubuntu /falco /
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
BUILD_DIR=${BUILD_DIR:-/build}
|
set -eu -o pipefail
|
||||||
SOURCE_DIR=${SOURCE_DIR:-/source}
|
|
||||||
SKIP_PACKAGES_TESTS=${SKIP_PACKAGES_TESTS:-false}
|
|
||||||
|
|
||||||
|
SOURCE_DIR=/source
|
||||||
|
BUILD_DIR=/build
|
||||||
CMD=${1:-test}
|
CMD=${1:-test}
|
||||||
shift
|
shift
|
||||||
|
|
||||||
# Stop the execution if a command in the pipeline has an error, from now on
|
|
||||||
set -e -u -o pipefail
|
|
||||||
|
|
||||||
# build type can be "debug" or "release", fallbacks to "release" by default
|
# build type can be "debug" or "release", fallbacks to "release" by default
|
||||||
BUILD_TYPE=$(echo "$BUILD_TYPE" | tr "[:upper:]" "[:lower:]")
|
BUILD_TYPE=$(echo "$BUILD_TYPE" | tr "[:upper:]" "[:lower:]")
|
||||||
case "$BUILD_TYPE" in
|
case "$BUILD_TYPE" in
|
||||||
@@ -50,8 +47,7 @@ case "$CMD" in
|
|||||||
"test")
|
"test")
|
||||||
if [ -z "$FALCO_VERSION" ]; then
|
if [ -z "$FALCO_VERSION" ]; then
|
||||||
echo "Automatically figuring out Falco version."
|
echo "Automatically figuring out Falco version."
|
||||||
FALCO_VERSION_FULL=$("$BUILD_DIR/$BUILD_TYPE/userspace/falco/falco" --version)
|
FALCO_VERSION=$("$BUILD_DIR/$BUILD_TYPE/userspace/falco/falco" --version | head -n 1 | cut -d' ' -f3 | tr -d '\r')
|
||||||
FALCO_VERSION=$(echo "$FALCO_VERSION_FULL" | head -n 1 | cut -d' ' -f3 | tr -d '\r')
|
|
||||||
echo "Falco version: $FALCO_VERSION"
|
echo "Falco version: $FALCO_VERSION"
|
||||||
fi
|
fi
|
||||||
if [ -z "$FALCO_VERSION" ]; then
|
if [ -z "$FALCO_VERSION" ]; then
|
||||||
@@ -60,11 +56,9 @@ case "$CMD" in
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# build docker images
|
# build docker images
|
||||||
if [ "$SKIP_PACKAGES_TESTS" = false ] ; then
|
|
||||||
build_image "$BUILD_DIR" "$BUILD_TYPE" "$FALCO_VERSION" "deb"
|
build_image "$BUILD_DIR" "$BUILD_TYPE" "$FALCO_VERSION" "deb"
|
||||||
build_image "$BUILD_DIR" "$BUILD_TYPE" "$FALCO_VERSION" "rpm"
|
build_image "$BUILD_DIR" "$BUILD_TYPE" "$FALCO_VERSION" "rpm"
|
||||||
build_image "$BUILD_DIR" "$BUILD_TYPE" "$FALCO_VERSION" "tar.gz"
|
build_image "$BUILD_DIR" "$BUILD_TYPE" "$FALCO_VERSION" "tar.gz"
|
||||||
fi
|
|
||||||
|
|
||||||
# check that source directory contains Falco
|
# check that source directory contains Falco
|
||||||
if [ ! -d "$SOURCE_DIR/falco/test" ]; then
|
if [ ! -d "$SOURCE_DIR/falco/test" ]; then
|
||||||
@@ -75,14 +69,12 @@ case "$CMD" in
|
|||||||
# run tests
|
# run tests
|
||||||
echo "Running regression tests ..."
|
echo "Running regression tests ..."
|
||||||
cd "$SOURCE_DIR/falco/test"
|
cd "$SOURCE_DIR/falco/test"
|
||||||
SKIP_PACKAGES_TESTS=$SKIP_PACKAGES_TESTS ./run_regression_tests.sh -d "$BUILD_DIR/$BUILD_TYPE"
|
./run_regression_tests.sh -d "$BUILD_DIR/$BUILD_TYPE"
|
||||||
|
|
||||||
# clean docker images
|
# clean docker images
|
||||||
if [ "$SKIP_PACKAGES_TESTS" = false ] ; then
|
|
||||||
clean_image "deb"
|
clean_image "deb"
|
||||||
clean_image "rpm"
|
clean_image "rpm"
|
||||||
clean_image "tar.gz"
|
clean_image "tar.gz"
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
"bash")
|
"bash")
|
||||||
CMD=/bin/bash
|
CMD=/bin/bash
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Inspired by many previous issues and many of the weekly community calls.
|
|||||||
|
|
||||||
**package**
|
**package**
|
||||||
|
|
||||||
*An installable artifact that is operating system specific. All packages MUST be hosted on [bintray](https://bintray.com/falcosecurity).*
|
*An installable artifact that is operating system specific. All packages MUST be hosted on bintray.*
|
||||||
|
|
||||||
**image**
|
**image**
|
||||||
|
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
# Falco Artifacts Storage
|
|
||||||
|
|
||||||
This document reflects the way we store the Falco artifacts.
|
|
||||||
|
|
||||||
## Terms & Definitions
|
|
||||||
|
|
||||||
- [Falco artifacts](./20200506-artifacts-scope-part-1.md)
|
|
||||||
- Bintray: artifacts distribution platform
|
|
||||||
|
|
||||||
## Packages
|
|
||||||
|
|
||||||
The Falco packages are **automatically** built and sent to [bintray](https://bintray.com/falcosecurity) in the following cases:
|
|
||||||
|
|
||||||
- a pull request gets merged into the master branch (**Falco development releases**)
|
|
||||||
- a new Falco release (git tag) happens on the master branch (**Falco stable releases**)
|
|
||||||
|
|
||||||
The only prerequisite is that the specific Falco source code builds successfully and that the tests pass.
|
|
||||||
|
|
||||||
As per [Falco Artifacts Scope (#1)](./20200506-artifacts-scope-part-1.md) proposal we provide three kind of Falco packages:
|
|
||||||
|
|
||||||
- DEB
|
|
||||||
- RPM
|
|
||||||
- Tarball
|
|
||||||
|
|
||||||
Thus, we have three repositories for the Falco stable releases:
|
|
||||||
|
|
||||||
- https://bintray.com/falcosecurity/deb
|
|
||||||
- https://bintray.com/falcosecurity/rpm
|
|
||||||
- https://bintray.com/falcosecurity/bin
|
|
||||||
|
|
||||||
And three repositories for the Falco development releases:
|
|
||||||
|
|
||||||
- https://bintray.com/falcosecurity/deb-dev
|
|
||||||
- https://bintray.com/falcosecurity/rpm-dev
|
|
||||||
- https://bintray.com/falcosecurity/bin-dev
|
|
||||||
|
|
||||||
## Drivers
|
|
||||||
|
|
||||||
The process of publishing a set of prebuilt Falco drivers is implemented by the **Drivers Build Grid (DBG)** in the [test-infra](https://github.com/falcosecurity/test-infra/tree/master/driverkit) repository (`driverkit` directory).
|
|
||||||
|
|
||||||
This process is driven by the configuration files (YAML) present in the `driverkit/config` directory in the [test-infra](https://github.com/falcosecurity/test-infra/tree/master/driverkit) repository.
|
|
||||||
|
|
||||||
Each of these files represents a prebuilt driver (eventually two: kernel module and eBPF probe, when possible) that will be published on [bintray](https://bintray.com/falcosecurity) if it builds correctly.
|
|
||||||
|
|
||||||
Every time the `driverkit/config` directory on the master branch has some changes from the previous commit the CI system, which you can find defined in the [.circleci/config.yml](https://github.com/falcosecurity/test-infra/blob/master/.circleci/config.yml) file, takes care of building and publishing all the drivers.
|
|
||||||
|
|
||||||
The driver versions we ship prebuilt drivers for are:
|
|
||||||
|
|
||||||
- the driver version associated with the last Falco stable version ([see here](https://github.com/falcosecurity/falco/blob/c4b7f17271d1a4ca533b2e672ecaaea5289ccdc5/cmake/modules/sysdig.cmake#L29))
|
|
||||||
- the driver version associated with the penultimate Falco stable version
|
|
||||||
|
|
||||||
The prebuilt drivers get published into [this](https://bintray.com/falcosecurity/driver) generic artifacts repository.
|
|
||||||
|
|
||||||
You can also visualize the full list of prebuilt drivers by driver version visiting this [URL](https://dl.bintray.com/falcosecurity/driver).
|
|
||||||
|
|
||||||
### Notice
|
|
||||||
|
|
||||||
The generation of new prebuilt drivers takes usually place with a frequency of 1-2 weeks, on a **best-effort** basis.
|
|
||||||
|
|
||||||
Thus, it can happen the list of available prebuilt drivers does not yet contain the driver version currently on Falco master.
|
|
||||||
|
|
||||||
Nevertheless, this process is an open, auditable, and transparent one.
|
|
||||||
|
|
||||||
So, by sending a pull-request towards [test-infra](https://github.com/falcosecurity/test-infra) repository containing the configuration YAML files you can help the Falco community stay on track.
|
|
||||||
|
|
||||||
Some pull-requests you can look at to create your own are:
|
|
||||||
|
|
||||||
- https://github.com/falcosecurity/test-infra/pull/165
|
|
||||||
- https://github.com/falcosecurity/test-infra/pull/163
|
|
||||||
- https://github.com/falcosecurity/test-infra/pull/162
|
|
||||||
|
|
||||||
While, the documentation of the YAML configuration files can be found [here](https://github.com/falcosecurity/driverkit/blob/master/README.md).
|
|
||||||
|
|
||||||
## Container images
|
|
||||||
|
|
||||||
As per Falco packages, also the Falco official container images are **automatically** published to the [dockerhub](https://hub.docker.com/r/falcosecurity/falco).
|
|
||||||
|
|
||||||
These images are built and published in two cases:
|
|
||||||
|
|
||||||
- a pull request gets merged into the master branch (**Falco development releases**)
|
|
||||||
- a new Falco release (git tag) happens (**Falco stable releases**)
|
|
||||||
|
|
||||||
For a detailed explanation of the container images we build and ship look at the following [documentation](https://github.com/falcosecurity/falco/blob/master/docker/README.md).
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
# Falco Artifacts Cleanup
|
|
||||||
|
|
||||||
This document reflects when and how we clean up the Falco artifacts from their storage location.
|
|
||||||
|
|
||||||
## Motivation
|
|
||||||
|
|
||||||
The [bintray](https://bintray.com/falcosecurity) open-source plan offers 10GB free space for storing artifacts.
|
|
||||||
|
|
||||||
They also kindly granted us an additional 5GB of free space.
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
Keep the storage space usage under 15GB by cleaning up the [Falco artifacts](./20200506-artifacts-scope-part-1.md) from the [storage](./20200818-artifacts-storage).
|
|
||||||
|
|
||||||
## Status
|
|
||||||
|
|
||||||
To be implemented.
|
|
||||||
|
|
||||||
## Packages
|
|
||||||
|
|
||||||
### Tarballs from Falco master
|
|
||||||
|
|
||||||
At the moment of writing this document, this kind of Falco package requires approx. 50MB (maximum detected size) of storage space.
|
|
||||||
|
|
||||||
Since, historically, the [bin-dev](https://bintray.com/falcosecurity/bin-dev) repository is the less used one, this document proposes to keep only the last 10 **Falco development releases** it contains.
|
|
||||||
|
|
||||||
This means that the [bin-dev](https://bintray.com/falcosecurity/bin-dev) repository will take at maximum 500MB of storage space.
|
|
||||||
|
|
||||||
### DEB from Falco master
|
|
||||||
|
|
||||||
At the moment of writing this document, this kind of Falco package requires approx. 5.1MB (maximum detected size) of storage space.
|
|
||||||
|
|
||||||
Historically, every Falco release is composed by less than 50 merges (upper limit).
|
|
||||||
|
|
||||||
So, to theoretically retain all the **Falco development releases** that led to a Falco stable release, this document proposes to keep the last 50 Falco DEB packages.
|
|
||||||
|
|
||||||
This means that the [deb-dev](https://bintray.com/falcosecurity/deb-dev) repository will take at maximum 255MB of storage space.
|
|
||||||
|
|
||||||
### RPM from Falco master
|
|
||||||
|
|
||||||
At the moment of writing this document, this kind of Falco package requires approx. 4.3MB (maximum detected size) of storage space.
|
|
||||||
|
|
||||||
For the same exact reasons explained above this document proposes to keep the last 50 Falco RPM packages.
|
|
||||||
|
|
||||||
This means that the [rpm-dev](https://bintray.com/falcosecurity/rpm-dev) repository will take at maximum 215MB of storage space.
|
|
||||||
|
|
||||||
### Stable releases
|
|
||||||
|
|
||||||
This document proposes to retain all the stable releases.
|
|
||||||
|
|
||||||
This means that all the Falco packages present in the Falco stable release repositories will be kept.
|
|
||||||
|
|
||||||
The [bin](https://bintray.com/falcosecurity/bin) repository contains a Falco tarball package for every release.
|
|
||||||
This means it grows in space of ~50MB each month.
|
|
||||||
|
|
||||||
The [deb](https://bintray.com/falcosecurity/deb) repository contains a Falco DEB package for every release.
|
|
||||||
This means it grows in space of ~5MB each month.
|
|
||||||
|
|
||||||
The [rpm](https://bintray.com/falcosecurity/rpm) repository contains a Falco RPM package for every release.
|
|
||||||
This means it grows in space of ~4.3MB each month.
|
|
||||||
|
|
||||||
### Considerations
|
|
||||||
|
|
||||||
Assuming the size of the packages does not surpass the numbers listed in the above sections, the **Falco development releases** will always take less that 1GB of artifacts storage space.
|
|
||||||
|
|
||||||
Assuming 12 stable releases at year, at the current size of packages, the **Falco stable releases** will take approx. 720MB of storage space every year.
|
|
||||||
|
|
||||||
### Implementation
|
|
||||||
|
|
||||||
The Falco CI will have a new CI job - called `cleanup/packages-dev` - responsible for removing the **Falco development releases** depending on the above plan.
|
|
||||||
|
|
||||||
This job will be triggered after the `publish/packages-dev` completed successfully.
|
|
||||||
|
|
||||||
## Drivers
|
|
||||||
|
|
||||||
As explained in the [Artifacts Storage](./20200818-artifacts-storage) proposal, we build the drivers for the **last two driver versions** associated with **latest Falco stable releases**.
|
|
||||||
Then, we store those drivers into a [generic bintray repository](https://bintray.com/falcosecurity/driver) from which the installation process automatically downloads them, if suitable.
|
|
||||||
|
|
||||||
This document proposes to implement a cleanup mechanism that deletes all the other driver versions available.
|
|
||||||
|
|
||||||
At the moment of writing, considering only the last two driver versions (**ae104eb**, **85c8895**) associated with the latest Falco stable releases, we ship ~340 eBPF drivers, each accounting for ~3.1MB of storage space, and 1512 kernel modules (~3.1MB size each, too).
|
|
||||||
|
|
||||||
Thus, we obtain an estimate of approx. 2.875GB for **each** driver version.
|
|
||||||
|
|
||||||
This document proposes to only store the last two driver versions associates with the latest Falco stable releases. And deleting the other ones.
|
|
||||||
|
|
||||||
This way, assuming the number of prebuilt drivers does not skyrocket, we can reasonably estimate the storage space used by prebuilt drivers to be around 6GB.
|
|
||||||
|
|
||||||
Notice that, in case a Falco stable release will not depend on a new driver version, this means the last two driver versions will, in this case, cover more than the two Falco stable releases.
|
|
||||||
|
|
||||||
### Archivation
|
|
||||||
|
|
||||||
Since the process of building drivers is time and resource consuming, this document also proposes to move the driver versions in other storage facilities.
|
|
||||||
|
|
||||||
The candidate is an AWS S3 bucket responsible for holding the deleted driver version files.
|
|
||||||
|
|
||||||
### Implementation
|
|
||||||
|
|
||||||
The [test-infra](https://github.com/falcosecurity/test-infra) CI, specifically its part dedicated to run the **Drivers Build Grid** that runs every time it detects changes into the `driverkit` directory of the [test-infra](https://github.com/falcosecurity/test-infra) repository,
|
|
||||||
will have a new job - called `drivers/cleanup` - responsible for removing all the Falco driver versions except the last two.
|
|
||||||
|
|
||||||
This job will be triggered after the `drivers/publish` completed successfully on the master branch.
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
# Falco Drivers Storage S3
|
|
||||||
|
|
||||||
Supersedes: [20200818-artifacts-storage.md#drivers](20200818-artifacts-storage.md#drivers)
|
|
||||||
|
|
||||||
Supersedes: [20200901-artifacts-cleanup.md#drivers](20200901-artifacts-cleanup.md#drivers)
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
In the past days, as many people probably noticed, Bintray started rate-limiting our users, effectively preventing them from downloading any kernel module, rpm/deb package or any pre-built dependency we host there.
|
|
||||||
|
|
||||||
This does not only interrupt the workflow of our users but also the workflow of the contributors, since without bintray most of our container images and CMake files can’t download the dependencies we mirror.
|
|
||||||
|
|
||||||
### What is the cause?
|
|
||||||
|
|
||||||
We had a spike in adoption apparently, either a user with many nodes or an increased number of users. We don’t know this detail specifically yet because bintray does not give us very fine-grained statistics on this.
|
|
||||||
|
|
||||||
This is the 30-days history:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
As you can see, we can only see that they downloaded the latest kernel module driver version, however we can’t see if:
|
|
||||||
|
|
||||||
* It’s a single source or many different users
|
|
||||||
|
|
||||||
* What is the kernel/OS they are using
|
|
||||||
|
|
||||||
### What do we host on Bintray?
|
|
||||||
|
|
||||||
* RPM packages: high traffic but very manageable ~90k downloads a month
|
|
||||||
|
|
||||||
* Deb packages:low traffic ~5k downloads a month
|
|
||||||
|
|
||||||
* Pre-built image Dependencies: low traffic, will eventually disappear in the future
|
|
||||||
|
|
||||||
* Kernel modules: very high traffic, 700k downloads in 10 days, this is what is causing the current problems. They are primarily used by users of our container images.
|
|
||||||
|
|
||||||
* eBPF probes: low traffic ~5k downloads a month
|
|
||||||
|
|
||||||
### Motivations to go to S3 instead of Bintray for the Drivers
|
|
||||||
|
|
||||||
Bintray does an excellent service at building the rpm/deb structures for us, however we also use them for S3-like storage for the drivers. We have ten thousand files hosted there and the combinations are infinite.
|
|
||||||
|
|
||||||
|
|
||||||
Before today, we had many issues with storage even without the spike in users we are seeing since the last ten days.
|
|
||||||
|
|
||||||
## Context on AWS
|
|
||||||
|
|
||||||
Amazon AWS, recently gave credits to the Falco project to operate some parts of the infrastructure on AWS. The CNCF is providing a sub-account we are already using for the migration of the other pieces (like Prow).
|
|
||||||
|
|
||||||
## Interactions with other teams and the CNCF
|
|
||||||
|
|
||||||
* The setup on the AWS account side already done, this is all technical work.
|
|
||||||
|
|
||||||
* We need to open a CNCF service account ticket for the download.falco.org subdomain to point to the S3 bucket we want to use
|
|
||||||
|
|
||||||
## The Plan
|
|
||||||
|
|
||||||
We want to propose to move the drivers and the container dependencies to S3.
|
|
||||||
|
|
||||||
#### Moving means:
|
|
||||||
|
|
||||||
* We create a public S3 bucket with [stats enabled](https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html)
|
|
||||||
|
|
||||||
* We attach the bucket to a cloudfront distribution behind the download.falco.org subdomain
|
|
||||||
|
|
||||||
* We move the current content keeping the same web server directory structure
|
|
||||||
|
|
||||||
* We change the Falco Dockerfiles and driver loader script accordingly
|
|
||||||
|
|
||||||
* We update test-infra to push the drivers to S3
|
|
||||||
|
|
||||||
* Once we have the drivers in S3, we can ask bintray to relax the limits for this month so that our users are able to download the other packages we keep there. Otherwise they will have to wait until November 1st. We only want to do that after the moving because otherwise we will hit the limits pretty quickly.
|
|
||||||
|
|
||||||
#### The repositories we want to move are:
|
|
||||||
|
|
||||||
* [https://bintray.com/falcosecurity/driver](https://bintray.com/falcosecurity/driver) will become https://download.falco.org/driver
|
|
||||||
|
|
||||||
* [https://bintray.com/falcosecurity/dependencies](https://bintray.com/falcosecurity/dependencies) will become https://download.falco.org/dependencies
|
|
||||||
|
|
||||||
#### Changes in Falco
|
|
||||||
|
|
||||||
* [Search for bintray ](https://github.com/falcosecurity/falco/search?p=2&q=bintray)on the Falco repo and replace the URL for the CMake and Docker files.
|
|
||||||
|
|
||||||
* It’s very important to change the DRIVERS_REPO environment variable [here](https://github.com/falcosecurity/falco/blob/0a33f555eb8e019806b46fea8b80a6302a935421/CMakeLists.txt#L86) - this is what updates the falco-driver-loader scripts that the users and container images use to fetch the module
|
|
||||||
|
|
||||||
#### Changes in Test Infra
|
|
||||||
|
|
||||||
* We need to use the S3 cli instead of jfrog cli to upload to the s3 bucket after building [here](https://github.com/falcosecurity/test-infra/blob/master/.circleci/config.yml)
|
|
||||||
|
|
||||||
* We can probably remove jfrog from that repo since it only deals with drivers and drivers are being put on S3 now
|
|
||||||
|
|
||||||
* Instructions on how to setup the S3 directory structure [here](https://falco.org/docs/installation/#install-driver)
|
|
||||||
|
|
||||||
* `/$driver_version$/falco_$target$_$kernelrelease$_$kernelversion$.[ko|o]`
|
|
||||||
|
|
||||||
#### Changes to Falco website
|
|
||||||
|
|
||||||
* Changes should not be necessary, we are not updating the way people install Falco but only the driver. The driver is managed by a script we can change.
|
|
||||||
|
|
||||||
## Mitigation and next steps for the users
|
|
||||||
|
|
||||||
* **The average users should be good to go now, Bintray raised our limits and we have some room to do this without requiring manual steps on your end**
|
|
||||||
|
|
||||||
* **Users that can’t wait for us to have the S3 setup done: **can setup an S3 as driver repo themselves, push the drivers they need to it after compiling them (they can use [Driverkit](https://github.com/falcosecurity/driverkit) for that) Instructions on how to setup the S3 directory structure [here](https://falco.org/docs/installation/#install-driver).
|
|
||||||
|
|
||||||
* **Users that can’t wait but don’t want to setup a webserver themselves**: the falco-driver-loader script can also compile the module for you. Make sure to install the kernel-headers on your nodes.
|
|
||||||
|
|
||||||
* **Users that can wait** we will approve this document and act on the plan described here by providing the DRIVERS_REPO at [https://download.falco.org/driver](https://download.falco.org/driver) that then you can use
|
|
||||||
|
|
||||||
### How to use an alternative DRIVERS_REPO ?
|
|
||||||
|
|
||||||
**On bash:**
|
|
||||||
|
|
||||||
export DRIVERS_REPO=https://your-url-here
|
|
||||||
|
|
||||||
**Docker**
|
|
||||||
|
|
||||||
Pass it as environment variable using the docker run flag -e - for example:
|
|
||||||
|
|
||||||
docker run -e DRIVERS_REPO=[https://your-url-here](https://your-url-here)
|
|
||||||
|
|
||||||
**Kubernetes**
|
|
||||||
|
|
||||||
spec:
|
|
||||||
|
|
||||||
containers:
|
|
||||||
|
|
||||||
- env:
|
|
||||||
|
|
||||||
- name: DRIVERS_REPO
|
|
||||||
|
|
||||||
value: https://your-url-here
|
|
||||||
|
|
||||||
## Release
|
|
||||||
|
|
||||||
Next release is on December 1st, we want to rollout a hotfix 0.26.2 release that only contains the updated script before that date so that users don’t get confused and we can just tell them "update Falco" to get the thing working again.
|
|
||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
@@ -37,6 +37,7 @@ if(DEFINED FALCO_COMPONENT)
|
|||||||
COMPONENT "${FALCO_COMPONENT}"
|
COMPONENT "${FALCO_COMPONENT}"
|
||||||
DESTINATION "${FALCO_ETC_DIR}"
|
DESTINATION "${FALCO_ETC_DIR}"
|
||||||
RENAME "${FALCO_LOCAL_RULES_DEST_FILENAME}")
|
RENAME "${FALCO_LOCAL_RULES_DEST_FILENAME}")
|
||||||
|
|
||||||
# Intentionally *not* installing application_rules.yaml. Not needed when falco is embedded in other projects.
|
# Intentionally *not* installing application_rules.yaml. Not needed when falco is embedded in other projects.
|
||||||
else()
|
else()
|
||||||
install(
|
install(
|
||||||
@@ -56,8 +57,8 @@ else()
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES application_rules.yaml
|
FILES application_rules.yaml
|
||||||
DESTINATION "${FALCO_ETC_DIR}/rules.available"
|
DESTINATION "/etc/falco/rules.available"
|
||||||
RENAME "${FALCO_APP_RULES_DEST_FILENAME}")
|
RENAME "${FALCO_APP_RULES_DEST_FILENAME}")
|
||||||
|
|
||||||
install(DIRECTORY DESTINATION "${FALCO_ETC_DIR}/rules.d")
|
install(DIRECTORY DESTINATION "/etc/falco/rules.d")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
# Copyright (C) 2019 The Falco Authors.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
# change to this rules file, we'll uncomment this line and set it to
|
# change to this rules file, we'll uncomment this line and set it to
|
||||||
# the falco engine version in use at the time.
|
# the falco engine version in use at the time.
|
||||||
#
|
#
|
||||||
- required_engine_version: 7
|
#- required_engine_version: 2
|
||||||
|
|
||||||
# Currently disabled as read/write are ignored syscalls. The nearly
|
# Currently disabled as read/write are ignored syscalls. The nearly
|
||||||
# similar open_write/open_read check for files being opened for
|
# similar open_write/open_read check for files being opened for
|
||||||
@@ -344,8 +344,8 @@
|
|||||||
# for efficiency.
|
# for efficiency.
|
||||||
- macro: inbound_outbound
|
- macro: inbound_outbound
|
||||||
condition: >
|
condition: >
|
||||||
((((evt.type in (accept,listen,connect) and evt.dir=<)) or
|
(((evt.type in (accept,listen,connect) and evt.dir=<)) or
|
||||||
(fd.typechar = 4 or fd.typechar = 6)) and
|
(fd.typechar = 4 or fd.typechar = 6) and
|
||||||
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and
|
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and
|
||||||
(evt.rawres >= 0 or evt.res = EINPROGRESS))
|
(evt.rawres >= 0 or evt.res = EINPROGRESS))
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@
|
|||||||
- rule: Disallowed SSH Connection
|
- rule: Disallowed SSH Connection
|
||||||
desc: Detect any new ssh connection to a host other than those in an allowed group of hosts
|
desc: Detect any new ssh connection to a host other than those in an allowed group of hosts
|
||||||
condition: (inbound_outbound) and ssh_port and not allowed_ssh_hosts
|
condition: (inbound_outbound) and ssh_port and not allowed_ssh_hosts
|
||||||
output: Disallowed SSH Connection (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository)
|
output: Disallowed SSH Connection (command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, mitre_remote_service]
|
tags: [network, mitre_remote_service]
|
||||||
|
|
||||||
@@ -399,7 +399,7 @@
|
|||||||
((fd.sip in (allowed_outbound_destination_ipaddrs)) or
|
((fd.sip in (allowed_outbound_destination_ipaddrs)) or
|
||||||
(fd.snet in (allowed_outbound_destination_networks)) or
|
(fd.snet in (allowed_outbound_destination_networks)) or
|
||||||
(fd.sip.name in (allowed_outbound_destination_domains)))
|
(fd.sip.name in (allowed_outbound_destination_domains)))
|
||||||
output: Disallowed outbound connection destination (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository)
|
output: Disallowed outbound connection destination (command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network]
|
tags: [network]
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@
|
|||||||
((fd.cip in (allowed_inbound_source_ipaddrs)) or
|
((fd.cip in (allowed_inbound_source_ipaddrs)) or
|
||||||
(fd.cnet in (allowed_inbound_source_networks)) or
|
(fd.cnet in (allowed_inbound_source_networks)) or
|
||||||
(fd.cip.name in (allowed_inbound_source_domains)))
|
(fd.cip.name in (allowed_inbound_source_domains)))
|
||||||
output: Disallowed inbound connection source (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository)
|
output: Disallowed inbound connection source (command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network]
|
tags: [network]
|
||||||
|
|
||||||
@@ -461,7 +461,7 @@
|
|||||||
and not proc.name in (shell_binaries)
|
and not proc.name in (shell_binaries)
|
||||||
and not exe_running_docker_save
|
and not exe_running_docker_save
|
||||||
output: >
|
output: >
|
||||||
a shell configuration file has been modified (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
a shell configuration file has been modified (user=%user.name command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
||||||
priority:
|
priority:
|
||||||
WARNING
|
WARNING
|
||||||
tags: [file, mitre_persistence]
|
tags: [file, mitre_persistence]
|
||||||
@@ -483,7 +483,7 @@
|
|||||||
fd.directory in (shell_config_directories)) and
|
fd.directory in (shell_config_directories)) and
|
||||||
(not proc.name in (shell_binaries))
|
(not proc.name in (shell_binaries))
|
||||||
output: >
|
output: >
|
||||||
a shell configuration file was read by a non-shell program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
a shell configuration file was read by a non-shell program (user=%user.name command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
||||||
priority:
|
priority:
|
||||||
WARNING
|
WARNING
|
||||||
tags: [file, mitre_discovery]
|
tags: [file, mitre_discovery]
|
||||||
@@ -502,7 +502,7 @@
|
|||||||
consider_all_cron_jobs and
|
consider_all_cron_jobs and
|
||||||
not user_known_cron_jobs
|
not user_known_cron_jobs
|
||||||
output: >
|
output: >
|
||||||
Cron jobs were scheduled to run (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline
|
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)
|
file=%fd.name container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||||
priority:
|
priority:
|
||||||
NOTICE
|
NOTICE
|
||||||
@@ -512,8 +512,8 @@
|
|||||||
|
|
||||||
# When displaying container information in the output field, use
|
# When displaying container information in the output field, use
|
||||||
# %container.info, without any leading term (file=%fd.name
|
# %container.info, without any leading term (file=%fd.name
|
||||||
# %container.info user=%user.name user_loginuid=%user.loginuid, and not file=%fd.name
|
# %container.info user=%user.name, and not file=%fd.name
|
||||||
# container=%container.info user=%user.name user_loginuid=%user.loginuid). The output will change
|
# container=%container.info user=%user.name). The output will change
|
||||||
# based on the context and whether or not -pk/-pm/-pc was specified on
|
# based on the context and whether or not -pk/-pm/-pc was specified on
|
||||||
# the command line.
|
# the command line.
|
||||||
- macro: container
|
- macro: container
|
||||||
@@ -522,7 +522,7 @@
|
|||||||
- macro: container_started
|
- macro: container_started
|
||||||
condition: >
|
condition: >
|
||||||
((evt.type = container or
|
((evt.type = container or
|
||||||
(spawned_process and proc.vpid=1)) and
|
(evt.type=execve and evt.dir=< and proc.vpid=1)) and
|
||||||
container.image.repository != incomplete)
|
container.image.repository != incomplete)
|
||||||
|
|
||||||
- macro: interactive
|
- macro: interactive
|
||||||
@@ -696,8 +696,8 @@
|
|||||||
- macro: run_by_foreman
|
- macro: run_by_foreman
|
||||||
condition: >
|
condition: >
|
||||||
(user.name=foreman and
|
(user.name=foreman and
|
||||||
((proc.pname in (rake, ruby, scl) and proc.aname[5] in (tfm-rake,tfm-ruby)) or
|
(proc.pname in (rake, ruby, scl) and proc.aname[5] in (tfm-rake,tfm-ruby)) or
|
||||||
(proc.pname=scl and proc.aname[2] in (tfm-rake,tfm-ruby))))
|
(proc.pname=scl and proc.aname[2] in (tfm-rake,tfm-ruby)))
|
||||||
|
|
||||||
- macro: java_running_sdjagent
|
- macro: java_running_sdjagent
|
||||||
condition: proc.name=java and proc.cmdline contains sdjagent.jar
|
condition: proc.name=java and proc.cmdline contains sdjagent.jar
|
||||||
@@ -746,13 +746,6 @@
|
|||||||
- macro: runuser_reading_pam
|
- macro: runuser_reading_pam
|
||||||
condition: (proc.name=runuser and fd.directory=/etc/pam.d)
|
condition: (proc.name=runuser and fd.directory=/etc/pam.d)
|
||||||
|
|
||||||
# CIS Linux Benchmark program
|
|
||||||
- macro: linux_bench_reading_etc_shadow
|
|
||||||
condition: ((proc.aname[2]=linux-bench and
|
|
||||||
proc.name in (awk,cut,grep)) and
|
|
||||||
(fd.name=/etc/shadow or
|
|
||||||
fd.directory=/etc/pam.d))
|
|
||||||
|
|
||||||
- macro: parent_ucf_writing_conf
|
- macro: parent_ucf_writing_conf
|
||||||
condition: (proc.pname=ucf and proc.aname[2]=frontend)
|
condition: (proc.pname=ucf and proc.aname[2]=frontend)
|
||||||
|
|
||||||
@@ -935,12 +928,10 @@
|
|||||||
items: [sources.list]
|
items: [sources.list]
|
||||||
|
|
||||||
- list: repository_directories
|
- list: repository_directories
|
||||||
items: [/etc/apt/sources.list.d, /etc/yum.repos.d, /etc/apt]
|
items: [/etc/apt/sources.list.d, /etc/yum.repos.d]
|
||||||
|
|
||||||
- macro: access_repositories
|
- macro: access_repositories
|
||||||
condition: (fd.directory in (repository_directories) or
|
condition: (fd.filename in (repository_files) or fd.directory in (repository_directories))
|
||||||
(fd.name pmatch (repository_directories) and
|
|
||||||
fd.filename in (repository_files)))
|
|
||||||
|
|
||||||
- macro: modify_repositories
|
- macro: modify_repositories
|
||||||
condition: (evt.arg.newpath pmatch (repository_directories))
|
condition: (evt.arg.newpath pmatch (repository_directories))
|
||||||
@@ -953,11 +944,10 @@
|
|||||||
condition: >
|
condition: >
|
||||||
((open_write and access_repositories) or (modify and modify_repositories))
|
((open_write and access_repositories) or (modify and modify_repositories))
|
||||||
and not package_mgmt_procs
|
and not package_mgmt_procs
|
||||||
and not package_mgmt_ancestor_procs
|
|
||||||
and not exe_running_docker_save
|
and not exe_running_docker_save
|
||||||
and not user_known_update_package_registry
|
and not user_known_update_package_registry
|
||||||
output: >
|
output: >
|
||||||
Repository files get updated (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name newpath=%evt.arg.newpath container_id=%container.id image=%container.image.repository)
|
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:
|
priority:
|
||||||
NOTICE
|
NOTICE
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
@@ -978,7 +968,7 @@
|
|||||||
and not python_running_ms_oms
|
and not python_running_ms_oms
|
||||||
and not user_known_write_below_binary_dir_activities
|
and not user_known_write_below_binary_dir_activities
|
||||||
output: >
|
output: >
|
||||||
File below a known binary directory opened for writing (user=%user.name user_loginuid=%user.loginuid
|
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)
|
command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository)
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
@@ -1036,7 +1026,7 @@
|
|||||||
and not cloud_init_writing_ssh
|
and not cloud_init_writing_ssh
|
||||||
and not user_known_write_monitored_dir_conditions
|
and not user_known_write_monitored_dir_conditions
|
||||||
output: >
|
output: >
|
||||||
File below a monitored directory opened for writing (user=%user.name user_loginuid=%user.loginuid
|
File below a monitored 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)
|
command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository)
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
@@ -1059,7 +1049,7 @@
|
|||||||
not user_known_read_ssh_information_activities and
|
not user_known_read_ssh_information_activities and
|
||||||
not proc.name in (ssh_binaries))
|
not proc.name in (ssh_binaries))
|
||||||
output: >
|
output: >
|
||||||
ssh-related file/directory read by non-ssh program (user=%user.name user_loginuid=%user.loginuid
|
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)
|
command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository)
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_discovery]
|
tags: [filesystem, mitre_discovery]
|
||||||
@@ -1155,7 +1145,7 @@
|
|||||||
|
|
||||||
- macro: redis_writing_conf
|
- macro: redis_writing_conf
|
||||||
condition: >
|
condition: >
|
||||||
(proc.name in (run-redis, redis-launcher.) and (fd.name=/etc/redis.conf or fd.name startswith /etc/redis))
|
(proc.name in (run-redis, redis-launcher.) and fd.name=/etc/redis.conf or fd.name startswith /etc/redis)
|
||||||
|
|
||||||
- macro: openvpn_writing_conf
|
- macro: openvpn_writing_conf
|
||||||
condition: (proc.name in (openvpn,openvpn-entrypo) and fd.name startswith /etc/openvpn)
|
condition: (proc.name in (openvpn,openvpn-entrypo) and fd.name startswith /etc/openvpn)
|
||||||
@@ -1183,10 +1173,7 @@
|
|||||||
|
|
||||||
- macro: calico_writing_conf
|
- macro: calico_writing_conf
|
||||||
condition: >
|
condition: >
|
||||||
(((proc.name = calico-node) or
|
(proc.name = calico-node and fd.name startswith /etc/calico)
|
||||||
(container.image.repository=gcr.io/projectcalico-org/node and proc.name in (start_runit, cp)) or
|
|
||||||
(container.image.repository=gcr.io/projectcalico-org/cni and proc.name=sed))
|
|
||||||
and fd.name startswith /etc/calico)
|
|
||||||
|
|
||||||
- macro: prometheus_conf_writing_conf
|
- macro: prometheus_conf_writing_conf
|
||||||
condition: (proc.name=prometheus-conf and fd.name startswith /etc/prometheus/config_out)
|
condition: (proc.name=prometheus-conf and fd.name startswith /etc/prometheus/config_out)
|
||||||
@@ -1213,9 +1200,6 @@
|
|||||||
fd.name startswith /etc/ssh/ssh_monitor_config_ or
|
fd.name startswith /etc/ssh/ssh_monitor_config_ or
|
||||||
fd.name startswith /etc/ssh/ssh_config_))
|
fd.name startswith /etc/ssh/ssh_config_))
|
||||||
|
|
||||||
- macro: multipath_writing_conf
|
|
||||||
condition: (proc.name = multipath and fd.name startswith /etc/multipath/)
|
|
||||||
|
|
||||||
# Add conditions to this macro (probably in a separate file,
|
# Add conditions to this macro (probably in a separate file,
|
||||||
# overwriting this macro) to allow for specific combinations of
|
# overwriting this macro) to allow for specific combinations of
|
||||||
# programs writing below specific directories below
|
# programs writing below specific directories below
|
||||||
@@ -1336,12 +1320,11 @@
|
|||||||
and not automount_using_mtab
|
and not automount_using_mtab
|
||||||
and not mcafee_writing_cma_d
|
and not mcafee_writing_cma_d
|
||||||
and not avinetworks_supervisor_writing_ssh
|
and not avinetworks_supervisor_writing_ssh
|
||||||
and not multipath_writing_conf
|
|
||||||
|
|
||||||
- rule: Write below etc
|
- rule: Write below etc
|
||||||
desc: an attempt to write to any file below /etc
|
desc: an attempt to write to any file below /etc
|
||||||
condition: write_etc_common
|
condition: write_etc_common
|
||||||
output: "File below /etc opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname pcmdline=%proc.pcmdline file=%fd.name program=%proc.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)"
|
output: "File below /etc opened for writing (user=%user.name command=%proc.cmdline parent=%proc.pname pcmdline=%proc.pcmdline file=%fd.name program=%proc.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)"
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
|
|
||||||
@@ -1410,14 +1393,10 @@
|
|||||||
- macro: runc_writing_var_lib_docker
|
- macro: runc_writing_var_lib_docker
|
||||||
condition: (proc.cmdline="runc:[1:CHILD] init" and evt.arg.filename startswith /var/lib/docker)
|
condition: (proc.cmdline="runc:[1:CHILD] init" and evt.arg.filename startswith /var/lib/docker)
|
||||||
|
|
||||||
- macro: mysqlsh_writing_state
|
|
||||||
condition: (proc.name=mysqlsh and fd.directory=/root/.mysqlsh)
|
|
||||||
|
|
||||||
- rule: Write below root
|
- rule: Write below root
|
||||||
desc: an attempt to write to any file directly below / or /root
|
desc: an attempt to write to any file directly below / or /root
|
||||||
condition: >
|
condition: >
|
||||||
root_dir and evt.dir = < and open_write
|
root_dir and evt.dir = < and open_write
|
||||||
and proc_name_exists
|
|
||||||
and not fd.name in (known_root_files)
|
and not fd.name in (known_root_files)
|
||||||
and not fd.directory pmatch (known_root_directories)
|
and not fd.directory pmatch (known_root_directories)
|
||||||
and not exe_running_docker_save
|
and not exe_running_docker_save
|
||||||
@@ -1434,11 +1413,10 @@
|
|||||||
and not calico_writing_state
|
and not calico_writing_state
|
||||||
and not rancher_writing_root
|
and not rancher_writing_root
|
||||||
and not runc_writing_exec_fifo
|
and not runc_writing_exec_fifo
|
||||||
and not mysqlsh_writing_state
|
|
||||||
and not known_root_conditions
|
and not known_root_conditions
|
||||||
and not user_known_write_root_conditions
|
and not user_known_write_root_conditions
|
||||||
and not user_known_write_below_root_activities
|
and not user_known_write_below_root_activities
|
||||||
output: "File below / or /root opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname file=%fd.name program=%proc.name container_id=%container.id image=%container.image.repository)"
|
output: "File below / or /root opened for writing (user=%user.name command=%proc.cmdline parent=%proc.pname file=%fd.name program=%proc.name container_id=%container.id image=%container.image.repository)"
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
|
|
||||||
@@ -1455,7 +1433,7 @@
|
|||||||
at startup to load initial state, but not afterwards.
|
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" and not user_known_read_sensitive_files_activities
|
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: >
|
output: >
|
||||||
Sensitive file opened for reading by trusted program after startup (user=%user.name user_loginuid=%user.loginuid
|
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)
|
command=%proc.cmdline parent=%proc.pname file=%fd.name parent=%proc.pname gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
tags: [filesystem, mitre_credential_access]
|
tags: [filesystem, mitre_credential_access]
|
||||||
@@ -1497,9 +1475,7 @@
|
|||||||
and not proc.name in (user_mgmt_binaries, userexec_binaries, package_mgmt_binaries,
|
and not proc.name in (user_mgmt_binaries, userexec_binaries, package_mgmt_binaries,
|
||||||
cron_binaries, read_sensitive_file_binaries, shell_binaries, hids_binaries,
|
cron_binaries, read_sensitive_file_binaries, shell_binaries, hids_binaries,
|
||||||
vpn_binaries, mail_config_binaries, nomachine_binaries, sshkit_script_binaries,
|
vpn_binaries, mail_config_binaries, nomachine_binaries, sshkit_script_binaries,
|
||||||
in.proftpd, mandb, salt-minion, postgres_mgmt_binaries,
|
in.proftpd, mandb, salt-minion, postgres_mgmt_binaries)
|
||||||
google_oslogin_
|
|
||||||
)
|
|
||||||
and not cmp_cp_by_passwd
|
and not cmp_cp_by_passwd
|
||||||
and not ansible_running_python
|
and not ansible_running_python
|
||||||
and not proc.cmdline contains /usr/bin/mandb
|
and not proc.cmdline contains /usr/bin/mandb
|
||||||
@@ -1512,11 +1488,10 @@
|
|||||||
and not veritas_driver_script
|
and not veritas_driver_script
|
||||||
and not perl_running_centrifydc
|
and not perl_running_centrifydc
|
||||||
and not runuser_reading_pam
|
and not runuser_reading_pam
|
||||||
and not linux_bench_reading_etc_shadow
|
|
||||||
and not user_known_read_sensitive_files_activities
|
and not user_known_read_sensitive_files_activities
|
||||||
and not user_read_sensitive_file_containers
|
and not user_read_sensitive_file_containers
|
||||||
output: >
|
output: >
|
||||||
Sensitive file opened for reading by non-trusted program (user=%user.name user_loginuid=%user.loginuid program=%proc.name
|
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)
|
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)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
tags: [filesystem, mitre_credential_access, mitre_discovery]
|
tags: [filesystem, mitre_credential_access, mitre_discovery]
|
||||||
@@ -1579,7 +1554,7 @@
|
|||||||
and not postgres_running_wal_e
|
and not postgres_running_wal_e
|
||||||
and not user_known_db_spawned_processes
|
and not user_known_db_spawned_processes
|
||||||
output: >
|
output: >
|
||||||
Database-related program spawned process other than itself (user=%user.name user_loginuid=%user.loginuid
|
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)
|
program=%proc.cmdline parent=%proc.pname container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [process, database, mitre_execution]
|
tags: [process, database, mitre_execution]
|
||||||
@@ -1591,7 +1566,7 @@
|
|||||||
desc: an attempt to modify any file below a set of binary directories.
|
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 and not user_known_modify_bin_dir_activities
|
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: >
|
output: >
|
||||||
File below known binary directory renamed/removed (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline
|
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)
|
pcmdline=%proc.pcmdline operation=%evt.type file=%fd.name %evt.args container_id=%container.id image=%container.image.repository)
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
@@ -1603,7 +1578,7 @@
|
|||||||
desc: an attempt to create a directory below a set of binary directories.
|
desc: an attempt to create a directory below a set of binary directories.
|
||||||
condition: mkdir and bin_dir_mkdir and not package_mgmt_procs and not user_known_mkdir_bin_dir_activities
|
condition: mkdir and bin_dir_mkdir and not package_mgmt_procs and not user_known_mkdir_bin_dir_activities
|
||||||
output: >
|
output: >
|
||||||
Directory below known binary directory created (user=%user.name user_loginuid=%user.loginuid
|
Directory below known binary directory created (user=%user.name
|
||||||
command=%proc.cmdline directory=%evt.arg.path container_id=%container.id image=%container.image.repository)
|
command=%proc.cmdline directory=%evt.arg.path container_id=%container.id image=%container.image.repository)
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
@@ -1632,7 +1607,6 @@
|
|||||||
as a part of creating a container) by calling setns.
|
as a part of creating a container) by calling setns.
|
||||||
condition: >
|
condition: >
|
||||||
evt.type=setns and evt.dir=<
|
evt.type=setns and evt.dir=<
|
||||||
and proc_name_exists
|
|
||||||
and not (container.id=host and proc.name in (docker_binaries, k8s_binaries, lxd_binaries, nsenter))
|
and not (container.id=host and proc.name in (docker_binaries, k8s_binaries, lxd_binaries, nsenter))
|
||||||
and not proc.name in (sysdigcloud_binaries, sysdig, calico, oci-umount, cilium-cni, network_plugin_binaries)
|
and not proc.name in (sysdigcloud_binaries, sysdig, calico, oci-umount, cilium-cni, network_plugin_binaries)
|
||||||
and not proc.name in (user_known_change_thread_namespace_binaries)
|
and not proc.name in (user_known_change_thread_namespace_binaries)
|
||||||
@@ -1648,7 +1622,7 @@
|
|||||||
and not weaveworks_scope
|
and not weaveworks_scope
|
||||||
and not user_known_change_thread_namespace_activities
|
and not user_known_change_thread_namespace_activities
|
||||||
output: >
|
output: >
|
||||||
Namespace change (setns) by unexpected program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline
|
Namespace change (setns) by unexpected program (user=%user.name command=%proc.cmdline
|
||||||
parent=%proc.pname %container.info container_id=%container.id image=%container.image.repository:%container.image.tag)
|
parent=%proc.pname %container.info container_id=%container.id image=%container.image.repository:%container.image.tag)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [process, mitre_privilege_escalation, mitre_lateral_movement]
|
tags: [process, mitre_privilege_escalation, mitre_lateral_movement]
|
||||||
@@ -1794,7 +1768,7 @@
|
|||||||
and not run_by_appdynamics
|
and not run_by_appdynamics
|
||||||
and not user_shell_container_exclusions
|
and not user_shell_container_exclusions
|
||||||
output: >
|
output: >
|
||||||
Shell spawned by untrusted binary (user=%user.name user_loginuid=%user.loginuid shell=%proc.name parent=%proc.pname
|
Shell spawned by untrusted binary (user=%user.name shell=%proc.name parent=%proc.pname
|
||||||
cmdline=%proc.cmdline pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3]
|
cmdline=%proc.cmdline pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3]
|
||||||
aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] container_id=%container.id image=%container.image.repository)
|
aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] container_id=%container.id image=%container.image.repository)
|
||||||
priority: DEBUG
|
priority: DEBUG
|
||||||
@@ -1869,30 +1843,11 @@
|
|||||||
# These container images are allowed to run with --privileged
|
# These container images are allowed to run with --privileged
|
||||||
- list: falco_privileged_images
|
- list: falco_privileged_images
|
||||||
items: [
|
items: [
|
||||||
docker.io/calico/node,
|
docker.io/sysdig/falco, docker.io/sysdig/sysdig,
|
||||||
calico/node,
|
gcr.io/google_containers/kube-proxy, docker.io/calico/node, quay.io/calico/node,
|
||||||
docker.io/cloudnativelabs/kube-router,
|
docker.io/rook/toolbox, docker.io/cloudnativelabs/kube-router, docker.io/mesosphere/mesos-slave,
|
||||||
docker.io/docker/ucp-agent,
|
docker.io/docker/ucp-agent, sematext_images, k8s.gcr.io/kube-proxy,
|
||||||
docker.io/falcosecurity/falco,
|
docker.io/falcosecurity/falco, sysdig/falco, sysdig/sysdig, falcosecurity/falco
|
||||||
docker.io/mesosphere/mesos-slave,
|
|
||||||
docker.io/rook/toolbox,
|
|
||||||
docker.io/sysdig/falco,
|
|
||||||
docker.io/sysdig/sysdig,
|
|
||||||
falcosecurity/falco,
|
|
||||||
gcr.io/google_containers/kube-proxy,
|
|
||||||
gcr.io/google-containers/startup-script,
|
|
||||||
gcr.io/projectcalico-org/node,
|
|
||||||
gke.gcr.io/kube-proxy,
|
|
||||||
gke.gcr.io/gke-metadata-server,
|
|
||||||
gke.gcr.io/netd-amd64,
|
|
||||||
gcr.io/google-containers/prometheus-to-sd,
|
|
||||||
k8s.gcr.io/ip-masq-agent-amd64,
|
|
||||||
k8s.gcr.io/kube-proxy,
|
|
||||||
k8s.gcr.io/prometheus-to-sd,
|
|
||||||
quay.io/calico/node,
|
|
||||||
sysdig/falco,
|
|
||||||
sysdig/sysdig,
|
|
||||||
sematext_images
|
|
||||||
]
|
]
|
||||||
|
|
||||||
- macro: falco_privileged_containers
|
- macro: falco_privileged_containers
|
||||||
@@ -1923,7 +1878,6 @@
|
|||||||
- list: falco_sensitive_mount_images
|
- list: falco_sensitive_mount_images
|
||||||
items: [
|
items: [
|
||||||
docker.io/sysdig/falco, docker.io/sysdig/sysdig, sysdig/falco, sysdig/sysdig,
|
docker.io/sysdig/falco, docker.io/sysdig/sysdig, sysdig/falco, sysdig/sysdig,
|
||||||
docker.io/falcosecurity/falco, falcosecurity/falco,
|
|
||||||
gcr.io/google_containers/hyperkube,
|
gcr.io/google_containers/hyperkube,
|
||||||
gcr.io/google_containers/kube-proxy, docker.io/calico/node,
|
gcr.io/google_containers/kube-proxy, docker.io/calico/node,
|
||||||
docker.io/rook/toolbox, docker.io/cloudnativelabs/kube-router, docker.io/consul,
|
docker.io/rook/toolbox, docker.io/cloudnativelabs/kube-router, docker.io/consul,
|
||||||
@@ -1936,20 +1890,11 @@
|
|||||||
condition: (user_trusted_containers or
|
condition: (user_trusted_containers or
|
||||||
container.image.repository in (trusted_images) or
|
container.image.repository in (trusted_images) or
|
||||||
container.image.repository in (falco_sensitive_mount_images) or
|
container.image.repository in (falco_sensitive_mount_images) or
|
||||||
container.image.repository startswith quay.io/sysdig/)
|
container.image.repository startswith quay.io/sysdig)
|
||||||
|
|
||||||
# These container images are allowed to run with hostnetwork=true
|
# These container images are allowed to run with hostnetwork=true
|
||||||
- list: falco_hostnetwork_images
|
- list: falco_hostnetwork_images
|
||||||
items: [
|
items: []
|
||||||
gcr.io/google-containers/prometheus-to-sd,
|
|
||||||
gcr.io/projectcalico-org/typha,
|
|
||||||
gcr.io/projectcalico-org/node,
|
|
||||||
gke.gcr.io/gke-metadata-server,
|
|
||||||
gke.gcr.io/kube-proxy,
|
|
||||||
gke.gcr.io/netd-amd64,
|
|
||||||
k8s.gcr.io/ip-masq-agent-amd64
|
|
||||||
k8s.gcr.io/prometheus-to-sd,
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add conditions to this macro (probably in a separate file,
|
# Add conditions to this macro (probably in a separate file,
|
||||||
# overwriting this macro) to specify additional containers that are
|
# overwriting this macro) to specify additional containers that are
|
||||||
@@ -1967,7 +1912,7 @@
|
|||||||
and container.privileged=true
|
and container.privileged=true
|
||||||
and not falco_privileged_containers
|
and not falco_privileged_containers
|
||||||
and not user_privileged_containers
|
and not user_privileged_containers
|
||||||
output: Privileged container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
output: Privileged container started (user=%user.name command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
||||||
priority: INFO
|
priority: INFO
|
||||||
tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement]
|
tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement]
|
||||||
|
|
||||||
@@ -2011,7 +1956,7 @@
|
|||||||
and sensitive_mount
|
and sensitive_mount
|
||||||
and not falco_sensitive_mount_containers
|
and not falco_sensitive_mount_containers
|
||||||
and not user_sensitive_mount_containers
|
and not user_sensitive_mount_containers
|
||||||
output: Container with sensitive mount started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag mounts=%container.mounts)
|
output: Container with sensitive mount started (user=%user.name command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag mounts=%container.mounts)
|
||||||
priority: INFO
|
priority: INFO
|
||||||
tags: [container, cis, mitre_lateral_movement]
|
tags: [container, cis, mitre_lateral_movement]
|
||||||
|
|
||||||
@@ -2031,7 +1976,7 @@
|
|||||||
desc: >
|
desc: >
|
||||||
Detect the initial process started by a container that is not in a list of allowed containers.
|
Detect the initial process started by a container that is not in a list of allowed containers.
|
||||||
condition: container_started and container and not allowed_containers
|
condition: container_started and container and not allowed_containers
|
||||||
output: Container started and not in allowed list (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
output: Container started and not in allowed list (user=%user.name command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
tags: [container, mitre_lateral_movement]
|
tags: [container, mitre_lateral_movement]
|
||||||
|
|
||||||
@@ -2046,7 +1991,7 @@
|
|||||||
- rule: System user interactive
|
- rule: System user interactive
|
||||||
desc: an attempt to run interactive commands by a system (i.e. non-login) user
|
desc: an attempt to run interactive commands by a system (i.e. non-login) user
|
||||||
condition: spawned_process and system_users and interactive and not user_known_system_user_login
|
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 user_loginuid=%user.loginuid command=%proc.cmdline container_id=%container.id image=%container.image.repository)"
|
output: "System user ran an interactive command (user=%user.name command=%proc.cmdline container_id=%container.id image=%container.image.repository)"
|
||||||
priority: INFO
|
priority: INFO
|
||||||
tags: [users, mitre_remote_access_tools]
|
tags: [users, mitre_remote_access_tools]
|
||||||
|
|
||||||
@@ -2063,7 +2008,7 @@
|
|||||||
and container_entrypoint
|
and container_entrypoint
|
||||||
and not user_expected_terminal_shell_in_container_conditions
|
and not user_expected_terminal_shell_in_container_conditions
|
||||||
output: >
|
output: >
|
||||||
A shell was spawned in a container with an attached terminal (user=%user.name user_loginuid=%user.loginuid %container.info
|
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)
|
shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [container, shell, mitre_execution]
|
tags: [container, shell, mitre_execution]
|
||||||
@@ -2139,7 +2084,7 @@
|
|||||||
and not user_expected_system_procs_network_activity_conditions
|
and not user_expected_system_procs_network_activity_conditions
|
||||||
output: >
|
output: >
|
||||||
Known system binary sent/received network traffic
|
Known system binary sent/received network traffic
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository)
|
(user=%user.name command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, mitre_exfiltration]
|
tags: [network, mitre_exfiltration]
|
||||||
|
|
||||||
@@ -2177,7 +2122,7 @@
|
|||||||
proc.env icontains HTTP_PROXY
|
proc.env icontains HTTP_PROXY
|
||||||
output: >
|
output: >
|
||||||
Program run with disallowed HTTP_PROXY environment variable
|
Program run with disallowed HTTP_PROXY environment variable
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline env=%proc.env parent=%proc.pname container_id=%container.id image=%container.image.repository)
|
(user=%user.name command=%proc.cmdline env=%proc.env parent=%proc.pname container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [host, users]
|
tags: [host, users]
|
||||||
|
|
||||||
@@ -2200,7 +2145,7 @@
|
|||||||
and interpreted_procs)
|
and interpreted_procs)
|
||||||
output: >
|
output: >
|
||||||
Interpreted program received/listened for network traffic
|
Interpreted program received/listened for network traffic
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository)
|
(user=%user.name command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, mitre_exfiltration]
|
tags: [network, mitre_exfiltration]
|
||||||
|
|
||||||
@@ -2211,7 +2156,7 @@
|
|||||||
and interpreted_procs)
|
and interpreted_procs)
|
||||||
output: >
|
output: >
|
||||||
Interpreted program performed outgoing network connection
|
Interpreted program performed outgoing network connection
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository)
|
(user=%user.name command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, mitre_exfiltration]
|
tags: [network, mitre_exfiltration]
|
||||||
|
|
||||||
@@ -2252,7 +2197,7 @@
|
|||||||
condition: (inbound_outbound) and do_unexpected_udp_check and fd.l4proto=udp and not expected_udp_traffic
|
condition: (inbound_outbound) and do_unexpected_udp_check and fd.l4proto=udp and not expected_udp_traffic
|
||||||
output: >
|
output: >
|
||||||
Unexpected UDP Traffic Seen
|
Unexpected UDP Traffic Seen
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name proto=%fd.l4proto evt=%evt.type %evt.args container_id=%container.id image=%container.image.repository)
|
(user=%user.name command=%proc.cmdline connection=%fd.name proto=%fd.l4proto evt=%evt.type %evt.args container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, mitre_exfiltration]
|
tags: [network, mitre_exfiltration]
|
||||||
|
|
||||||
@@ -2311,7 +2256,7 @@
|
|||||||
and not nrpe_becoming_nagios
|
and not nrpe_becoming_nagios
|
||||||
and not user_known_non_sudo_setuid_conditions
|
and not user_known_non_sudo_setuid_conditions
|
||||||
output: >
|
output: >
|
||||||
Unexpected setuid call by non-sudo, non-root program (user=%user.name user_loginuid=%user.loginuid cur_uid=%user.uid parent=%proc.pname
|
Unexpected setuid call by non-sudo, non-root program (user=%user.name cur_uid=%user.uid parent=%proc.pname
|
||||||
command=%proc.cmdline uid=%evt.arg.uid container_id=%container.id image=%container.image.repository)
|
command=%proc.cmdline uid=%evt.arg.uid container_id=%container.id image=%container.image.repository)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [users, mitre_privilege_escalation]
|
tags: [users, mitre_privilege_escalation]
|
||||||
@@ -2319,9 +2264,6 @@
|
|||||||
- macro: user_known_user_management_activities
|
- macro: user_known_user_management_activities
|
||||||
condition: (never_true)
|
condition: (never_true)
|
||||||
|
|
||||||
- macro: chage_list
|
|
||||||
condition: (proc.name=chage and (proc.cmdline contains "-l" or proc.cmdline contains "--list"))
|
|
||||||
|
|
||||||
- rule: User mgmt binaries
|
- rule: User mgmt binaries
|
||||||
desc: >
|
desc: >
|
||||||
activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded.
|
activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded.
|
||||||
@@ -2340,11 +2282,10 @@
|
|||||||
not run_by_yum and
|
not run_by_yum and
|
||||||
not run_by_ms_oms and
|
not run_by_ms_oms and
|
||||||
not run_by_google_accounts_daemon and
|
not run_by_google_accounts_daemon and
|
||||||
not chage_list and
|
|
||||||
not user_known_user_management_activities
|
not user_known_user_management_activities
|
||||||
output: >
|
output: >
|
||||||
User management binary command run outside of container
|
User management binary command run outside of container
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4])
|
(user=%user.name command=%proc.cmdline parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4])
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [host, users, mitre_persistence]
|
tags: [host, users, mitre_persistence]
|
||||||
|
|
||||||
@@ -2368,7 +2309,7 @@
|
|||||||
and not fd.name in (allowed_dev_files)
|
and not fd.name in (allowed_dev_files)
|
||||||
and not fd.name startswith /dev/tty
|
and not fd.name startswith /dev/tty
|
||||||
and not user_known_create_files_below_dev_activities
|
and not user_known_create_files_below_dev_activities
|
||||||
output: "File created below /dev by untrusted program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)"
|
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
|
priority: ERROR
|
||||||
tags: [filesystem, mitre_persistence]
|
tags: [filesystem, mitre_persistence]
|
||||||
|
|
||||||
@@ -2486,7 +2427,7 @@
|
|||||||
and not package_mgmt_ancestor_procs
|
and not package_mgmt_ancestor_procs
|
||||||
and not user_known_package_manager_in_container
|
and not user_known_package_manager_in_container
|
||||||
output: >
|
output: >
|
||||||
Package management process launched in container (user=%user.name user_loginuid=%user.loginuid
|
Package management process launched in container (user=%user.name
|
||||||
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||||
priority: ERROR
|
priority: ERROR
|
||||||
tags: [process, mitre_persistence]
|
tags: [process, mitre_persistence]
|
||||||
@@ -2500,7 +2441,7 @@
|
|||||||
or proc.args contains "-c " or proc.args contains "--lua-exec"))
|
or proc.args contains "-c " or proc.args contains "--lua-exec"))
|
||||||
)
|
)
|
||||||
output: >
|
output: >
|
||||||
Netcat runs inside container that allows remote code execution (user=%user.name user_loginuid=%user.loginuid
|
Netcat runs inside container that allows remote code execution (user=%user.name
|
||||||
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
tags: [network, process, mitre_execution]
|
tags: [network, process, mitre_execution]
|
||||||
@@ -2513,7 +2454,7 @@
|
|||||||
condition: >
|
condition: >
|
||||||
spawned_process and container and network_tool_procs and not user_known_network_tool_activities
|
spawned_process and container and network_tool_procs and not user_known_network_tool_activities
|
||||||
output: >
|
output: >
|
||||||
Network tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent_process=%proc.pname
|
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)
|
container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, process, mitre_discovery, mitre_exfiltration]
|
tags: [network, process, mitre_discovery, mitre_exfiltration]
|
||||||
@@ -2533,7 +2474,7 @@
|
|||||||
network_tool_procs and
|
network_tool_procs and
|
||||||
not user_known_network_tool_activities
|
not user_known_network_tool_activities
|
||||||
output: >
|
output: >
|
||||||
Network tool launched on host (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent_process=%proc.pname)
|
Network tool launched on host (user=%user.name command=%proc.cmdline parent_process=%proc.pname)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, process, mitre_discovery, mitre_exfiltration]
|
tags: [network, process, mitre_discovery, mitre_exfiltration]
|
||||||
|
|
||||||
@@ -2569,7 +2510,7 @@
|
|||||||
)
|
)
|
||||||
output: >
|
output: >
|
||||||
Grep private keys or passwords activities found
|
Grep private keys or passwords activities found
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline container_id=%container.id container_name=%container.name
|
(user=%user.name command=%proc.cmdline container_id=%container.id container_name=%container.name
|
||||||
image=%container.image.repository:%container.image.tag)
|
image=%container.image.repository:%container.image.tag)
|
||||||
priority:
|
priority:
|
||||||
WARNING
|
WARNING
|
||||||
@@ -2603,7 +2544,7 @@
|
|||||||
not trusted_logging_images and
|
not trusted_logging_images and
|
||||||
not allowed_clear_log_files
|
not allowed_clear_log_files
|
||||||
output: >
|
output: >
|
||||||
Log files were tampered (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
Log files were tampered (user=%user.name command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
||||||
priority:
|
priority:
|
||||||
WARNING
|
WARNING
|
||||||
tags: [file, mitre_defense_evasion]
|
tags: [file, mitre_defense_evasion]
|
||||||
@@ -2621,12 +2562,13 @@
|
|||||||
desc: Detect process running to clear bulk data from disk
|
desc: Detect process running to clear bulk data from disk
|
||||||
condition: spawned_process and clear_data_procs and not user_known_remove_data_activities
|
condition: spawned_process and clear_data_procs and not user_known_remove_data_activities
|
||||||
output: >
|
output: >
|
||||||
Bulk data has been removed from disk (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
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:
|
priority:
|
||||||
WARNING
|
WARNING
|
||||||
tags: [process, mitre_persistence]
|
tags: [process, mitre_persistence]
|
||||||
|
|
||||||
- macro: modify_shell_history
|
- rule: Delete or rename shell history
|
||||||
|
desc: Detect shell history deletion
|
||||||
condition: >
|
condition: >
|
||||||
(modify and (
|
(modify and (
|
||||||
evt.arg.name contains "bash_history" or
|
evt.arg.name contains "bash_history" or
|
||||||
@@ -2640,27 +2582,14 @@
|
|||||||
evt.arg.path contains "bash_history" or
|
evt.arg.path contains "bash_history" or
|
||||||
evt.arg.path contains "zsh_history" or
|
evt.arg.path contains "zsh_history" or
|
||||||
evt.arg.path contains "fish_read_history" or
|
evt.arg.path contains "fish_read_history" or
|
||||||
evt.arg.path endswith "fish_history"))
|
evt.arg.path endswith "fish_history")) or
|
||||||
|
|
||||||
- macro: truncate_shell_history
|
|
||||||
condition: >
|
|
||||||
(open_write and (
|
(open_write and (
|
||||||
fd.name contains "bash_history" or
|
fd.name contains "bash_history" or
|
||||||
fd.name contains "zsh_history" or
|
fd.name contains "zsh_history" or
|
||||||
fd.name contains "fish_read_history" or
|
fd.name contains "fish_read_history" or
|
||||||
fd.name endswith "fish_history") and evt.arg.flags contains "O_TRUNC")
|
fd.name endswith "fish_history") and evt.arg.flags contains "O_TRUNC")
|
||||||
|
|
||||||
- macro: var_lib_docker_filepath
|
|
||||||
condition: (evt.arg.name startswith /var/lib/docker or fd.name startswith /var/lib/docker)
|
|
||||||
|
|
||||||
- rule: Delete or rename shell history
|
|
||||||
desc: Detect shell history deletion
|
|
||||||
condition: >
|
|
||||||
(modify_shell_history or truncate_shell_history) and
|
|
||||||
not var_lib_docker_filepath and
|
|
||||||
not proc.name in (docker_binaries)
|
|
||||||
output: >
|
output: >
|
||||||
Shell history had been deleted or renamed (user=%user.name user_loginuid=%user.loginuid type=%evt.type command=%proc.cmdline fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info)
|
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)
|
||||||
priority:
|
priority:
|
||||||
WARNING
|
WARNING
|
||||||
tags: [process, mitre_defense_evasion]
|
tags: [process, mitre_defense_evasion]
|
||||||
@@ -2673,7 +2602,7 @@
|
|||||||
((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"))
|
(open_write and fd.name contains "bash_history" and evt.arg.flags contains "O_TRUNC"))
|
||||||
output: >
|
output: >
|
||||||
Shell history had been deleted or renamed (user=%user.name user_loginuid=%user.loginuid type=%evt.type command=%proc.cmdline fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info)
|
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)
|
||||||
priority:
|
priority:
|
||||||
WARNING
|
WARNING
|
||||||
tags: [process, mitre_defense_evasion]
|
tags: [process, mitre_defense_evasion]
|
||||||
@@ -2701,7 +2630,7 @@
|
|||||||
and not exe_running_docker_save
|
and not exe_running_docker_save
|
||||||
and not user_known_set_setuid_or_setgid_bit_conditions
|
and not user_known_set_setuid_or_setgid_bit_conditions
|
||||||
output: >
|
output: >
|
||||||
Setuid or setgid bit is set via chmod (fd=%evt.arg.fd filename=%evt.arg.filename mode=%evt.arg.mode user=%user.name user_loginuid=%user.loginuid process=%proc.name
|
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)
|
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||||
priority:
|
priority:
|
||||||
NOTICE
|
NOTICE
|
||||||
@@ -2726,7 +2655,7 @@
|
|||||||
consider_hidden_file_creation and
|
consider_hidden_file_creation and
|
||||||
not user_known_create_hidden_file_activities
|
not user_known_create_hidden_file_activities
|
||||||
output: >
|
output: >
|
||||||
Hidden file or directory created (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline
|
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)
|
file=%fd.name newpath=%evt.arg.newpath container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||||
priority:
|
priority:
|
||||||
NOTICE
|
NOTICE
|
||||||
@@ -2738,20 +2667,12 @@
|
|||||||
- macro: remote_file_copy_procs
|
- macro: remote_file_copy_procs
|
||||||
condition: (proc.name in (remote_file_copy_binaries))
|
condition: (proc.name in (remote_file_copy_binaries))
|
||||||
|
|
||||||
# Users should overwrite this macro to specify conditions under which a
|
|
||||||
# Custom condition for use of remote file copy tool in container
|
|
||||||
- macro: user_known_remote_file_copy_activities
|
|
||||||
condition: (never_true)
|
|
||||||
|
|
||||||
- rule: Launch Remote File Copy Tools in Container
|
- rule: Launch Remote File Copy Tools in Container
|
||||||
desc: Detect remote file copy tools launched in container
|
desc: Detect remote file copy tools launched in container
|
||||||
condition: >
|
condition: >
|
||||||
spawned_process
|
spawned_process and container and remote_file_copy_procs
|
||||||
and container
|
|
||||||
and remote_file_copy_procs
|
|
||||||
and not user_known_remote_file_copy_activities
|
|
||||||
output: >
|
output: >
|
||||||
Remote file copy tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent_process=%proc.pname
|
Remote file copy 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)
|
container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [network, process, mitre_lateral_movement, mitre_exfiltration]
|
tags: [network, process, mitre_lateral_movement, mitre_exfiltration]
|
||||||
@@ -2762,7 +2683,7 @@
|
|||||||
create_symlink and
|
create_symlink and
|
||||||
(evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names))
|
(evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names))
|
||||||
output: >
|
output: >
|
||||||
Symlinks created over senstivie files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline target=%evt.arg.target linkpath=%evt.arg.linkpath parent_process=%proc.pname)
|
Symlinks created over senstivie files (user=%user.name command=%proc.cmdline target=%evt.arg.target linkpath=%evt.arg.linkpath parent_process=%proc.pname)
|
||||||
priority: NOTICE
|
priority: NOTICE
|
||||||
tags: [file, mitre_exfiltration]
|
tags: [file, mitre_exfiltration]
|
||||||
|
|
||||||
@@ -2872,22 +2793,12 @@
|
|||||||
- list: k8s_client_binaries
|
- list: k8s_client_binaries
|
||||||
items: [docker, kubectl, crictl]
|
items: [docker, kubectl, crictl]
|
||||||
|
|
||||||
- list: user_known_k8s_ns_kube_system_images
|
|
||||||
items: [
|
|
||||||
k8s.gcr.io/fluentd-gcp-scaler,
|
|
||||||
k8s.gcr.io/node-problem-detector/node-problem-detector
|
|
||||||
]
|
|
||||||
|
|
||||||
- list: user_known_k8s_images
|
|
||||||
items: [
|
|
||||||
mcr.microsoft.com/aks/hcp/hcp-tunnel-front
|
|
||||||
]
|
|
||||||
|
|
||||||
# Whitelist for known docker client binaries run inside container
|
# Whitelist for known docker client binaries run inside container
|
||||||
# - k8s.gcr.io/fluentd-gcp-scaler in GCP/GKE
|
# - k8s.gcr.io/fluentd-gcp-scaler in GCP/GKE
|
||||||
- macro: user_known_k8s_client_container
|
- macro: user_known_k8s_client_container
|
||||||
condition: >
|
condition: >
|
||||||
(k8s.ns.name="kube-system" and container.image.repository in (user_known_k8s_ns_kube_system_images)) or container.image.repository in (user_known_k8s_images)
|
(k8s.ns.name="kube-system" and container.image.repository=k8s.gcr.io/fluentd-gcp-scaler) or
|
||||||
|
container.image.repository=mcr.microsoft.com/aks/hcp/hcp-tunnel-front
|
||||||
|
|
||||||
- macro: user_known_k8s_client_container_parens
|
- macro: user_known_k8s_client_container_parens
|
||||||
condition: (user_known_k8s_client_container)
|
condition: (user_known_k8s_client_container)
|
||||||
@@ -2895,23 +2806,24 @@
|
|||||||
- rule: The docker client is executed in a container
|
- rule: The docker client is executed in a container
|
||||||
desc: Detect a k8s client tool executed inside a container
|
desc: Detect a k8s client tool executed inside a container
|
||||||
condition: spawned_process and container and not user_known_k8s_client_container_parens 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 user_loginuid=%user.loginuid %container.info parent=%proc.pname cmdline=%proc.cmdline image=%container.image.repository:%container.image.tag)"
|
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
|
priority: WARNING
|
||||||
tags: [container, mitre_execution]
|
tags: [container, mitre_execution]
|
||||||
|
|
||||||
|
|
||||||
# This rule is enabled by default.
|
# This rule is not enabled by default, as there are legitimate use
|
||||||
# If you want to disable it, modify the following macro.
|
# cases for raw packet. If you want to enable it, modify the
|
||||||
|
# following macro.
|
||||||
- macro: consider_packet_socket_communication
|
- macro: consider_packet_socket_communication
|
||||||
condition: (always_true)
|
condition: (never_true)
|
||||||
|
|
||||||
- list: user_known_packet_socket_binaries
|
- list: user_known_packet_socket_binaries
|
||||||
items: []
|
items: []
|
||||||
|
|
||||||
- rule: Packet socket created in container
|
- rule: Packet socket created in container
|
||||||
desc: Detect new packet socket at the device driver (OSI Layer 2) level in a container. Packet socket could be used for ARP Spoofing and privilege escalation(CVE-2020-14386) by attacker.
|
desc: Detect new packet socket at the device driver (OSI Layer 2) level in a container. Packet socket could be used to do ARP Spoofing by attacker.
|
||||||
condition: evt.type=socket and evt.arg[0]=AF_PACKET and consider_packet_socket_communication and container and not proc.name in (user_known_packet_socket_binaries)
|
condition: evt.type=socket and evt.arg[0]=AF_PACKET and consider_packet_socket_communication and container and not proc.name in (user_known_packet_socket_binaries)
|
||||||
output: Packet socket was created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline socket_info=%evt.args container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
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
|
priority: NOTICE
|
||||||
tags: [network, mitre_discovery]
|
tags: [network, mitre_discovery]
|
||||||
|
|
||||||
@@ -2950,7 +2862,7 @@
|
|||||||
k8s.ns.name in (namespace_scope_network_only_subnet)
|
k8s.ns.name in (namespace_scope_network_only_subnet)
|
||||||
output: >
|
output: >
|
||||||
Network connection outside local subnet
|
Network connection outside local subnet
|
||||||
(command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id
|
(command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id
|
||||||
image=%container.image.repository namespace=%k8s.ns.name
|
image=%container.image.repository namespace=%k8s.ns.name
|
||||||
fd.rip.name=%fd.rip.name fd.lip.name=%fd.lip.name fd.cip.name=%fd.cip.name fd.sip.name=%fd.sip.name)
|
fd.rip.name=%fd.rip.name fd.lip.name=%fd.lip.name fd.cip.name=%fd.cip.name fd.sip.name=%fd.sip.name)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
@@ -2990,7 +2902,7 @@
|
|||||||
not fd.sport in (authorized_server_port)
|
not fd.sport in (authorized_server_port)
|
||||||
output: >
|
output: >
|
||||||
Network connection outside authorized port and binary
|
Network connection outside authorized port and binary
|
||||||
(command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id
|
(command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id
|
||||||
image=%container.image.repository)
|
image=%container.image.repository)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
tags: [network]
|
tags: [network]
|
||||||
@@ -3002,7 +2914,7 @@
|
|||||||
desc: Detect redirecting stdout/stdin to network connection in container (potential reverse shell).
|
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") and not user_known_stand_streams_redirect_activities
|
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: >
|
output: >
|
||||||
Redirect stdout/stdin to network connection (user=%user.name user_loginuid=%user.loginuid %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)
|
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
|
priority: WARNING
|
||||||
|
|
||||||
# The two Container Drift rules below will fire when a new executable is created in a container.
|
# The two Container Drift rules below will fire when a new executable is created in a container.
|
||||||
@@ -3031,7 +2943,7 @@
|
|||||||
((evt.arg.mode contains "S_IXUSR") or
|
((evt.arg.mode contains "S_IXUSR") or
|
||||||
(evt.arg.mode contains "S_IXGRP") or
|
(evt.arg.mode contains "S_IXGRP") or
|
||||||
(evt.arg.mode contains "S_IXOTH"))
|
(evt.arg.mode contains "S_IXOTH"))
|
||||||
output: Drift detected (chmod), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type)
|
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
|
priority: ERROR
|
||||||
|
|
||||||
# ****************************************************************************
|
# ****************************************************************************
|
||||||
@@ -3047,28 +2959,9 @@
|
|||||||
not runc_writing_var_lib_docker and
|
not runc_writing_var_lib_docker and
|
||||||
not user_known_container_drift_activities and
|
not user_known_container_drift_activities and
|
||||||
evt.rawres>=0
|
evt.rawres>=0
|
||||||
output: Drift detected (open+create), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type)
|
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
|
priority: ERROR
|
||||||
|
|
||||||
- list: c2_server_ip_list
|
|
||||||
items: []
|
|
||||||
|
|
||||||
- rule: Outbound Connection to C2 Servers
|
|
||||||
desc: Detect outbound connection to command & control servers
|
|
||||||
condition: outbound and fd.sip in (c2_server_ip_list)
|
|
||||||
output: Outbound connection to C2 server (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository)
|
|
||||||
priority: WARNING
|
|
||||||
tags: [network]
|
|
||||||
|
|
||||||
- list: white_listed_modules
|
|
||||||
items: []
|
|
||||||
|
|
||||||
- rule: Linux Kernel Module Injection Detected
|
|
||||||
desc: Detect kernel module was injected (from container).
|
|
||||||
condition: spawned_process and container and proc.name=insmod and not proc.args in (white_listed_modules)
|
|
||||||
output: Linux Kernel Module injection using insmod detected (user=%user.name user_loginuid=%user.loginuid parent_process=%proc.pname module=%proc.args)
|
|
||||||
priority: WARNING
|
|
||||||
tags: [process]
|
|
||||||
|
|
||||||
# Application rules have moved to application_rules.yaml. Please look
|
# Application rules have moved to application_rules.yaml. Please look
|
||||||
# there if you want to enable them by adding to
|
# there if you want to enable them by adding to
|
||||||
|
|||||||
@@ -48,9 +48,6 @@
|
|||||||
"minikube", "minikube-user", "kubelet", "kops", "admin", "kube", "kube-proxy", "kube-apiserver-healthcheck",
|
"minikube", "minikube-user", "kubelet", "kops", "admin", "kube", "kube-proxy", "kube-apiserver-healthcheck",
|
||||||
"kubernetes-admin",
|
"kubernetes-admin",
|
||||||
vertical_pod_autoscaler_users,
|
vertical_pod_autoscaler_users,
|
||||||
cluster-autoscaler,
|
|
||||||
"system:addon-manager",
|
|
||||||
"cloud-controller-manager"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
- rule: Disallowed K8s User
|
- rule: Disallowed K8s User
|
||||||
@@ -245,48 +242,20 @@
|
|||||||
source: k8s_audit
|
source: k8s_audit
|
||||||
tags: [k8s]
|
tags: [k8s]
|
||||||
|
|
||||||
# Only defined for backwards compatibility. Use the more specific
|
|
||||||
# user_allowed_kube_namespace_image_list instead.
|
|
||||||
- list: user_trusted_image_list
|
- list: user_trusted_image_list
|
||||||
items: []
|
items: []
|
||||||
|
|
||||||
- list: user_allowed_kube_namespace_image_list
|
|
||||||
items: [user_trusted_image_list]
|
|
||||||
|
|
||||||
# Only defined for backwards compatibility. Use the more specific
|
|
||||||
# allowed_kube_namespace_image_list instead.
|
|
||||||
- list: k8s_image_list
|
- list: k8s_image_list
|
||||||
items: []
|
items: [k8s.gcr.io/kube-apiserver, kope/kube-apiserver-healthcheck]
|
||||||
|
|
||||||
- list: allowed_kube_namespace_image_list
|
- macro: trusted_pod
|
||||||
items: [
|
condition: (ka.req.pod.containers.image.repository in (user_trusted_image_list) or
|
||||||
gcr.io/google-containers/prometheus-to-sd,
|
ka.req.pod.containers.image.repository in (k8s_image_list))
|
||||||
gcr.io/projectcalico-org/node,
|
|
||||||
gke.gcr.io/addon-resizer,
|
|
||||||
gke.gcr.io/heapster,
|
|
||||||
gke.gcr.io/gke-metadata-server,
|
|
||||||
k8s.gcr.io/ip-masq-agent-amd64,
|
|
||||||
k8s.gcr.io/kube-apiserver,
|
|
||||||
gke.gcr.io/kube-proxy,
|
|
||||||
gke.gcr.io/netd-amd64,
|
|
||||||
k8s.gcr.io/addon-resizer
|
|
||||||
k8s.gcr.io/prometheus-to-sd,
|
|
||||||
k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64,
|
|
||||||
k8s.gcr.io/k8s-dns-kube-dns-amd64,
|
|
||||||
k8s.gcr.io/k8s-dns-sidecar-amd64,
|
|
||||||
k8s.gcr.io/metrics-server-amd64,
|
|
||||||
kope/kube-apiserver-healthcheck,
|
|
||||||
k8s_image_list
|
|
||||||
]
|
|
||||||
|
|
||||||
- macro: allowed_kube_namespace_pods
|
|
||||||
condition: (ka.req.pod.containers.image.repository in (user_allowed_kube_namespace_image_list) or
|
|
||||||
ka.req.pod.containers.image.repository in (allowed_kube_namespace_image_list))
|
|
||||||
|
|
||||||
# Detect any new pod created in the kube-system namespace
|
# Detect any new pod created in the kube-system namespace
|
||||||
- rule: Pod Created in Kube Namespace
|
- rule: Pod Created in Kube Namespace
|
||||||
desc: Detect any attempt to create a pod in the kube-system or kube-public namespaces
|
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) and not allowed_kube_namespace_pods
|
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)
|
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
|
priority: WARNING
|
||||||
source: k8s_audit
|
source: k8s_audit
|
||||||
@@ -312,8 +281,7 @@
|
|||||||
# normal operation.
|
# normal operation.
|
||||||
- rule: System ClusterRole Modified/Deleted
|
- rule: System ClusterRole Modified/Deleted
|
||||||
desc: Detect any attempt to modify/delete a ClusterRole/Role starting with system
|
desc: Detect any attempt to modify/delete a ClusterRole/Role starting with system
|
||||||
condition: kevt and (role or clusterrole) and (kmodify or kdelete) and (ka.target.name startswith "system:") and
|
condition: kevt and (role or clusterrole) and (kmodify or kdelete) and (ka.target.name startswith "system:") and ka.target.name!="system:coredns"
|
||||||
not ka.target.name in (system:coredns, system:managed-certificate-controller)
|
|
||||||
output: System ClusterRole/Role modified or deleted (user=%ka.user.name role=%ka.target.name ns=%ka.target.namespace action=%ka.verb)
|
output: System ClusterRole/Role modified or deleted (user=%ka.user.name role=%ka.target.name ns=%ka.target.namespace action=%ka.verb)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
source: k8s_audit
|
source: k8s_audit
|
||||||
@@ -537,7 +505,7 @@
|
|||||||
condition: >
|
condition: >
|
||||||
kevt
|
kevt
|
||||||
and non_system_user
|
and non_system_user
|
||||||
and ka.user.name in (full_admin_k8s_users)
|
and ka.user.name in (admin_k8s_users)
|
||||||
and not allowed_full_admin_users
|
and not allowed_full_admin_users
|
||||||
output: K8s Operation performed by full admin user (user=%ka.user.name target=%ka.target.name/%ka.target.resource verb=%ka.verb uri=%ka.uri resp=%ka.response.code)
|
output: K8s Operation performed by full admin user (user=%ka.user.name target=%ka.target.name/%ka.target.resource verb=%ka.verb uri=%ka.uri resp=%ka.response.code)
|
||||||
priority: WARNING
|
priority: WARNING
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo "usage: $0 -p 0987654321 -r <deb-dev|rpm-dev|bin-dev>"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
user=poiana
|
|
||||||
|
|
||||||
# Get the versions to delete.
|
|
||||||
#
|
|
||||||
# $1: repository to lookup
|
|
||||||
# $2: number of versions to skip.
|
|
||||||
get_versions() {
|
|
||||||
# The API endpoint returns the Falco package versions sort by most recent.
|
|
||||||
IFS=$'\n' read -r -d '' -a all < <(curl -s --header "Content-Type: application/json" "https://api.bintray.com/packages/falcosecurity/$1/falco" | jq -r '.versions | .[]' | tail -n "+$2")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove all the versions (${all[@]} array).
|
|
||||||
#
|
|
||||||
# $1: repository containing the versions.
|
|
||||||
rem_versions() {
|
|
||||||
for i in "${!all[@]}";
|
|
||||||
do
|
|
||||||
JFROG_CLI_LOG_LEVEL=DEBUG jfrog bt vd --quiet --user "${user}" --key "${pass}" "falcosecurity/$1/falco/${all[$i]}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
while getopts ":p::r:" opt; do
|
|
||||||
case "${opt}" in
|
|
||||||
p )
|
|
||||||
pass=${OPTARG}
|
|
||||||
;;
|
|
||||||
r )
|
|
||||||
repo="${OPTARG}"
|
|
||||||
[[ "${repo}" == "deb-dev" || "${repo}" == "rpm-dev" || "${repo}" == "bin-dev" ]] || usage
|
|
||||||
;;
|
|
||||||
: )
|
|
||||||
echo "invalid option: ${OPTARG} requires an argument" 1>&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
\?)
|
|
||||||
echo "invalid option: ${OPTARG}" 1>&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND-1))
|
|
||||||
|
|
||||||
if [ -z "${pass}" ] || [ -z "${repo}" ]; then
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
skip=51
|
|
||||||
if [[ "${repo}" == "bin-dev" ]]; then
|
|
||||||
skip=11
|
|
||||||
fi
|
|
||||||
|
|
||||||
get_versions "${repo}" ${skip}
|
|
||||||
echo "number of versions to delete: ${#all[@]}"
|
|
||||||
rem_versions "${repo}"
|
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
# Required-Stop: $remote_fs $syslog
|
# Required-Stop: $remote_fs $syslog
|
||||||
# Default-Start: 2 3 4 5
|
# Default-Start: 2 3 4 5
|
||||||
# Default-Stop: 0 1 6
|
# Default-Stop: 0 1 6
|
||||||
# Short-Description: Falco syscall activity monitoring agent
|
# Short-Description: Falco Cloud Native runtime security
|
||||||
# Description: Falco is a system activity monitoring agent
|
# Description: Falco is a system activity monitoring agent
|
||||||
# driven by system calls with support for containers.
|
# driven by system calls with support for containers.
|
||||||
### END INIT INFO
|
### END INIT INFO
|
||||||
@@ -62,11 +62,11 @@ do_start()
|
|||||||
# 0 if daemon has been started
|
# 0 if daemon has been started
|
||||||
# 1 if daemon was already running
|
# 1 if daemon was already running
|
||||||
# 2 if daemon could not be started
|
# 2 if daemon could not be started
|
||||||
|
if [ ! -d /sys/module/falco ]; then
|
||||||
|
/sbin/modprobe falco || exit 2
|
||||||
|
fi
|
||||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||||
|| return 1
|
|| return 1
|
||||||
if [ ! -d /sys/module/falco ]; then
|
|
||||||
/sbin/modprobe falco || exit 1
|
|
||||||
fi
|
|
||||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
||||||
$DAEMON_ARGS \
|
$DAEMON_ARGS \
|
||||||
|| return 2
|
|| return 2
|
||||||
|
|||||||
@@ -143,21 +143,10 @@ load_kernel_module_compile() {
|
|||||||
# skip dkms on UEK hosts because it will always fail
|
# skip dkms on UEK hosts because it will always fail
|
||||||
if [[ $(uname -r) == *uek* ]]; then
|
if [[ $(uname -r) == *uek* ]]; then
|
||||||
echo "* Skipping dkms install for UEK host"
|
echo "* Skipping dkms install for UEK host"
|
||||||
return
|
else
|
||||||
fi
|
if hash dkms &>/dev/null; then
|
||||||
|
echo "* Trying to dkms install ${DRIVER_NAME} module"
|
||||||
if ! hash dkms &>/dev/null; then
|
if dkms install -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
|
||||||
echo "* Skipping dkms install (dkms not found)"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# try to compile using all the available gcc versions
|
|
||||||
for CURRENT_GCC in $(which gcc) $(ls "$(dirname "$(which gcc)")"/gcc-* | grep 'gcc-[0-9]\+' | sort -r); do
|
|
||||||
echo "* Trying to dkms install ${DRIVER_NAME} module with GCC ${CURRENT_GCC}"
|
|
||||||
echo "#!/usr/bin/env bash" > /tmp/falco-dkms-make
|
|
||||||
echo "make CC=${CURRENT_GCC} \$@" >> /tmp/falco-dkms-make
|
|
||||||
chmod +x /tmp/falco-dkms-make
|
|
||||||
if dkms install --directive="MAKE='/tmp/falco-dkms-make'" -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
|
|
||||||
echo "* ${DRIVER_NAME} module installed in dkms, trying to insmod"
|
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
|
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"
|
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms"
|
||||||
@@ -171,13 +160,16 @@ load_kernel_module_compile() {
|
|||||||
else
|
else
|
||||||
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
|
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
|
||||||
if [ -f "${DKMS_LOG}" ]; then
|
if [ -f "${DKMS_LOG}" ]; then
|
||||||
echo "* Running dkms build failed, dumping ${DKMS_LOG} (with GCC ${CURRENT_GCC})"
|
echo "* Running dkms build failed, dumping ${DKMS_LOG}"
|
||||||
cat "${DKMS_LOG}"
|
cat "${DKMS_LOG}"
|
||||||
else
|
else
|
||||||
echo "* Running dkms build failed, couldn't find ${DKMS_LOG} (with GCC ${CURRENT_GCC})"
|
echo "* Running dkms build failed, couldn't find ${DKMS_LOG}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "* Skipping dkms install (dkms not found)"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_kernel_module_download() {
|
load_kernel_module_download() {
|
||||||
@@ -220,7 +212,7 @@ load_kernel_module() {
|
|||||||
rmmod "${DRIVER_NAME}" 2>/dev/null
|
rmmod "${DRIVER_NAME}" 2>/dev/null
|
||||||
WAIT_TIME=0
|
WAIT_TIME=0
|
||||||
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
|
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
|
||||||
while lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
|
while lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1 && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
|
||||||
if rmmod "${DRIVER_NAME}" 2>/dev/null; then
|
if rmmod "${DRIVER_NAME}" 2>/dev/null; then
|
||||||
echo "* Unloading ${DRIVER_NAME} module succeeded after ${WAIT_TIME}s"
|
echo "* Unloading ${DRIVER_NAME} module succeeded after ${WAIT_TIME}s"
|
||||||
break
|
break
|
||||||
@@ -232,7 +224,7 @@ load_kernel_module() {
|
|||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
if lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" > /dev/null 2>&1; then
|
if lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
|
||||||
echo "* ${DRIVER_NAME} module seems to still be loaded, hoping the best"
|
echo "* ${DRIVER_NAME} module seems to still be loaded, hoping the best"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (C) 2019 The Falco Authors.
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# falco syscall monitoring agent
|
# Falco Cloud Native runtime security
|
||||||
#
|
#
|
||||||
# chkconfig: 2345 55 45
|
# chkconfig: 2345 55 45
|
||||||
# description: Falco syscall monitoring agent
|
# description: Falco Cloud Native runtime security
|
||||||
#
|
#
|
||||||
|
|
||||||
### BEGIN INIT INFO
|
### BEGIN INIT INFO
|
||||||
@@ -52,10 +52,10 @@ start() {
|
|||||||
[ -x $exec ] || exit 5
|
[ -x $exec ] || exit 5
|
||||||
# [ -f $config ] || exit 6
|
# [ -f $config ] || exit 6
|
||||||
echo -n $"Starting $prog: "
|
echo -n $"Starting $prog: "
|
||||||
daemon $exec --daemon --pidfile=$pidfile
|
|
||||||
if [ ! -d /sys/module/falco ]; then
|
if [ ! -d /sys/module/falco ]; then
|
||||||
/sbin/modprobe falco || return $?
|
/sbin/modprobe falco || return $?
|
||||||
fi
|
fi
|
||||||
|
daemon $exec --daemon --pidfile=$pidfile
|
||||||
retval=$?
|
retval=$?
|
||||||
echo
|
echo
|
||||||
[ $retval -eq 0 ] && touch $lockfile
|
[ $retval -eq 0 ] && touch $lockfile
|
||||||
|
|||||||
@@ -41,4 +41,4 @@ stdout_output:
|
|||||||
|
|
||||||
program_output:
|
program_output:
|
||||||
enabled: true
|
enabled: true
|
||||||
program: cat >> /tmp/falco_outputs/program_output.txt
|
program: cat > /tmp/falco_outputs/program_output.txt
|
||||||
|
|||||||
@@ -1,42 +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.
|
|
||||||
#
|
|
||||||
|
|
||||||
# File containing Falco rules, loaded at startup.
|
|
||||||
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.
|
|
||||||
log_stderr: false
|
|
||||||
log_syslog: false
|
|
||||||
|
|
||||||
# Where security notifications should go.
|
|
||||||
# Multiple outputs can be enabled.
|
|
||||||
|
|
||||||
syslog_output:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
file_output:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
stdout_output:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
program_output:
|
|
||||||
enabled: false
|
|
||||||
@@ -31,7 +31,6 @@ from avocado.utils import process
|
|||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
from watchdog.events import PatternMatchingEventHandler
|
from watchdog.events import PatternMatchingEventHandler
|
||||||
|
|
||||||
|
|
||||||
class FalcoTest(Test):
|
class FalcoTest(Test):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -50,20 +49,17 @@ class FalcoTest(Test):
|
|||||||
self.stdout_is = self.params.get('stdout_is', '*', default='')
|
self.stdout_is = self.params.get('stdout_is', '*', default='')
|
||||||
self.stderr_is = self.params.get('stderr_is', '*', default='')
|
self.stderr_is = self.params.get('stderr_is', '*', default='')
|
||||||
|
|
||||||
self.stdout_contains = self.params.get(
|
self.stdout_contains = self.params.get('stdout_contains', '*', default='')
|
||||||
'stdout_contains', '*', default='')
|
|
||||||
|
|
||||||
if not isinstance(self.stdout_contains, list):
|
if not isinstance(self.stdout_contains, list):
|
||||||
self.stdout_contains = [self.stdout_contains]
|
self.stdout_contains = [self.stdout_contains]
|
||||||
|
|
||||||
self.stderr_contains = self.params.get(
|
self.stderr_contains = self.params.get('stderr_contains', '*', default='')
|
||||||
'stderr_contains', '*', default='')
|
|
||||||
|
|
||||||
if not isinstance(self.stderr_contains, list):
|
if not isinstance(self.stderr_contains, list):
|
||||||
self.stderr_contains = [self.stderr_contains]
|
self.stderr_contains = [self.stderr_contains]
|
||||||
|
|
||||||
self.stdout_not_contains = self.params.get(
|
self.stdout_not_contains = self.params.get('stdout_not_contains', '*', default='')
|
||||||
'stdout_not_contains', '*', default='')
|
|
||||||
|
|
||||||
if not isinstance(self.stdout_not_contains, list):
|
if not isinstance(self.stdout_not_contains, list):
|
||||||
if self.stdout_not_contains == '':
|
if self.stdout_not_contains == '':
|
||||||
@@ -71,8 +67,7 @@ class FalcoTest(Test):
|
|||||||
else:
|
else:
|
||||||
self.stdout_not_contains = [self.stdout_not_contains]
|
self.stdout_not_contains = [self.stdout_not_contains]
|
||||||
|
|
||||||
self.stderr_not_contains = self.params.get(
|
self.stderr_not_contains = self.params.get('stderr_not_contains', '*', default='')
|
||||||
'stderr_not_contains', '*', default='')
|
|
||||||
|
|
||||||
if not isinstance(self.stderr_not_contains, list):
|
if not isinstance(self.stderr_not_contains, list):
|
||||||
if self.stderr_not_contains == '':
|
if self.stderr_not_contains == '':
|
||||||
@@ -88,18 +83,15 @@ class FalcoTest(Test):
|
|||||||
self.trace_file = os.path.join(build_dir, "test", self.trace_file)
|
self.trace_file = os.path.join(build_dir, "test", self.trace_file)
|
||||||
|
|
||||||
self.json_output = self.params.get('json_output', '*', default=False)
|
self.json_output = self.params.get('json_output', '*', default=False)
|
||||||
self.json_include_output_property = self.params.get(
|
self.json_include_output_property = self.params.get('json_include_output_property', '*', default=True)
|
||||||
'json_include_output_property', '*', default=True)
|
|
||||||
self.all_events = self.params.get('all_events', '*', default=False)
|
self.all_events = self.params.get('all_events', '*', default=False)
|
||||||
self.priority = self.params.get('priority', '*', default='debug')
|
self.priority = self.params.get('priority', '*', default='debug')
|
||||||
self.rules_file = self.params.get(
|
self.rules_file = self.params.get('rules_file', '*', default=os.path.join(self.basedir, '../rules/falco_rules.yaml'))
|
||||||
'rules_file', '*', default=os.path.join(self.basedir, '../rules/falco_rules.yaml'))
|
|
||||||
|
|
||||||
if not isinstance(self.rules_file, list):
|
if not isinstance(self.rules_file, list):
|
||||||
self.rules_file = [self.rules_file]
|
self.rules_file = [self.rules_file]
|
||||||
|
|
||||||
self.validate_rules_file = self.params.get(
|
self.validate_rules_file = self.params.get('validate_rules_file', '*', default=False)
|
||||||
'validate_rules_file', '*', default=False)
|
|
||||||
|
|
||||||
if self.validate_rules_file == False:
|
if self.validate_rules_file == False:
|
||||||
self.validate_rules_file = []
|
self.validate_rules_file = []
|
||||||
@@ -126,15 +118,13 @@ class FalcoTest(Test):
|
|||||||
file = os.path.join(self.basedir, file)
|
file = os.path.join(self.basedir, file)
|
||||||
self.rules_args = self.rules_args + "-r " + file + " "
|
self.rules_args = self.rules_args + "-r " + file + " "
|
||||||
|
|
||||||
self.conf_file = self.params.get(
|
self.conf_file = self.params.get('conf_file', '*', default=os.path.join(self.basedir, '../falco.yaml'))
|
||||||
'conf_file', '*', default=os.path.join(self.basedir, '../falco.yaml'))
|
|
||||||
if not os.path.isabs(self.conf_file):
|
if not os.path.isabs(self.conf_file):
|
||||||
self.conf_file = os.path.join(self.basedir, self.conf_file)
|
self.conf_file = os.path.join(self.basedir, self.conf_file)
|
||||||
|
|
||||||
self.run_duration = self.params.get('run_duration', '*', default='')
|
self.run_duration = self.params.get('run_duration', '*', default='')
|
||||||
|
|
||||||
self.disabled_rules = self.params.get(
|
self.disabled_rules = self.params.get('disabled_rules', '*', default='')
|
||||||
'disabled_rules', '*', default='')
|
|
||||||
|
|
||||||
if self.disabled_rules == '':
|
if self.disabled_rules == '':
|
||||||
self.disabled_rules = []
|
self.disabled_rules = []
|
||||||
@@ -147,8 +137,7 @@ class FalcoTest(Test):
|
|||||||
for rule in self.disabled_rules:
|
for rule in self.disabled_rules:
|
||||||
self.disabled_args = self.disabled_args + "-D " + rule + " "
|
self.disabled_args = self.disabled_args + "-D " + rule + " "
|
||||||
|
|
||||||
self.detect_counts = self.params.get(
|
self.detect_counts = self.params.get('detect_counts', '*', default=False)
|
||||||
'detect_counts', '*', default=False)
|
|
||||||
if self.detect_counts == False:
|
if self.detect_counts == False:
|
||||||
self.detect_counts = {}
|
self.detect_counts = {}
|
||||||
else:
|
else:
|
||||||
@@ -158,8 +147,7 @@ class FalcoTest(Test):
|
|||||||
detect_counts[key] = value
|
detect_counts[key] = value
|
||||||
self.detect_counts = detect_counts
|
self.detect_counts = detect_counts
|
||||||
|
|
||||||
self.rules_warning = self.params.get(
|
self.rules_warning = self.params.get('rules_warning', '*', default=False)
|
||||||
'rules_warning', '*', default=False)
|
|
||||||
if self.rules_warning == False:
|
if self.rules_warning == False:
|
||||||
self.rules_warning = set()
|
self.rules_warning = set()
|
||||||
else:
|
else:
|
||||||
@@ -184,11 +172,9 @@ class FalcoTest(Test):
|
|||||||
|
|
||||||
self.package = self.params.get('package', '*', default='None')
|
self.package = self.params.get('package', '*', default='None')
|
||||||
|
|
||||||
self.addl_docker_run_args = self.params.get(
|
self.addl_docker_run_args = self.params.get('addl_docker_run_args', '*', default='')
|
||||||
'addl_docker_run_args', '*', default='')
|
|
||||||
|
|
||||||
self.copy_local_driver = self.params.get(
|
self.copy_local_driver = self.params.get('copy_local_driver', '*', default=False)
|
||||||
'copy_local_driver', '*', default=False)
|
|
||||||
|
|
||||||
# Used by possibly_copy_local_driver as well as docker run
|
# Used by possibly_copy_local_driver as well as docker run
|
||||||
self.module_dir = os.path.expanduser("~/.falco")
|
self.module_dir = os.path.expanduser("~/.falco")
|
||||||
@@ -211,33 +197,9 @@ class FalcoTest(Test):
|
|||||||
os.makedirs(filedir)
|
os.makedirs(filedir)
|
||||||
self.outputs = outputs
|
self.outputs = outputs
|
||||||
|
|
||||||
self.output_strictly_contains = self.params.get(
|
|
||||||
'output_strictly_contains', '*', default='')
|
|
||||||
|
|
||||||
if self.output_strictly_contains == '':
|
|
||||||
self.output_strictly_contains = {}
|
|
||||||
else:
|
|
||||||
output_strictly_contains = []
|
|
||||||
for item in self.output_strictly_contains:
|
|
||||||
for key, value in list(item.items()):
|
|
||||||
output = {}
|
|
||||||
output['actual'] = key
|
|
||||||
output['expected'] = value
|
|
||||||
output_strictly_contains.append(output)
|
|
||||||
if not output['actual'] == 'stdout':
|
|
||||||
# Clean up file from previous tests, if any
|
|
||||||
if os.path.exists(output['actual']):
|
|
||||||
os.remove(output['actual'])
|
|
||||||
# Create the parent directory for the file if it doesn't exist.
|
|
||||||
filedir = os.path.dirname(output['actual'])
|
|
||||||
if not os.path.isdir(filedir):
|
|
||||||
os.makedirs(filedir)
|
|
||||||
self.output_strictly_contains = output_strictly_contains
|
|
||||||
|
|
||||||
self.grpcurl_res = None
|
self.grpcurl_res = None
|
||||||
self.grpc_observer = None
|
self.grpc_observer = None
|
||||||
self.grpc_address = self.params.get(
|
self.grpc_address = self.params.get('address', 'grpc/*', default='/var/run/falco.sock')
|
||||||
'address', 'grpc/*', default='/var/run/falco.sock')
|
|
||||||
if self.grpc_address.startswith("unix://"):
|
if self.grpc_address.startswith("unix://"):
|
||||||
self.is_grpc_using_unix_socket = True
|
self.is_grpc_using_unix_socket = True
|
||||||
self.grpc_address = self.grpc_address[len("unix://"):]
|
self.grpc_address = self.grpc_address[len("unix://"):]
|
||||||
@@ -263,8 +225,7 @@ class FalcoTest(Test):
|
|||||||
if self.run_tags == '':
|
if self.run_tags == '':
|
||||||
self.run_tags=[]
|
self.run_tags=[]
|
||||||
|
|
||||||
self.time_iso_8601 = self.params.get(
|
self.time_iso_8601 = self.params.get('time_iso_8601', '*', default=False)
|
||||||
'time_iso_8601', '*', default=False)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
if self.package != 'None':
|
if self.package != 'None':
|
||||||
@@ -283,8 +244,7 @@ class FalcoTest(Test):
|
|||||||
self.log.debug("Actual warning rules: {}".format(found_warning))
|
self.log.debug("Actual warning rules: {}".format(found_warning))
|
||||||
|
|
||||||
if found_warning != self.rules_warning:
|
if found_warning != self.rules_warning:
|
||||||
self.fail("Expected rules with warnings {} does not match actual rules with warnings {}".format(
|
self.fail("Expected rules with warnings {} does not match actual rules with warnings {}".format(self.rules_warning, found_warning))
|
||||||
self.rules_warning, found_warning))
|
|
||||||
|
|
||||||
def check_rules_events(self, res):
|
def check_rules_events(self, res):
|
||||||
|
|
||||||
@@ -295,60 +255,50 @@ class FalcoTest(Test):
|
|||||||
events = set(match.group(2).split(","))
|
events = set(match.group(2).split(","))
|
||||||
found_events[rule] = events
|
found_events[rule] = events
|
||||||
|
|
||||||
self.log.debug(
|
self.log.debug("Expected events for rules: {}".format(self.rules_events))
|
||||||
"Expected events for rules: {}".format(self.rules_events))
|
|
||||||
self.log.debug("Actual events for rules: {}".format(found_events))
|
self.log.debug("Actual events for rules: {}".format(found_events))
|
||||||
|
|
||||||
for rule in list(found_events.keys()):
|
for rule in list(found_events.keys()):
|
||||||
if found_events.get(rule) != self.rules_events.get(rule):
|
if found_events.get(rule) != self.rules_events.get(rule):
|
||||||
self.fail("rule {}: expected events {} differs from actual events {}".format(
|
self.fail("rule {}: expected events {} differs from actual events {}".format(rule, self.rules_events.get(rule), found_events.get(rule)))
|
||||||
rule, self.rules_events.get(rule), found_events.get(rule)))
|
|
||||||
|
|
||||||
def check_detections(self, res):
|
def check_detections(self, res):
|
||||||
# Get the number of events detected.
|
# Get the number of events detected.
|
||||||
match = re.search('Events detected: (\d+)', res.stdout.decode("utf-8"))
|
match = re.search('Events detected: (\d+)', res.stdout.decode("utf-8"))
|
||||||
if match is None:
|
if match is None:
|
||||||
self.fail(
|
self.fail("Could not find a line 'Events detected: <count>' in falco output")
|
||||||
"Could not find a line 'Events detected: <count>' in falco output")
|
|
||||||
|
|
||||||
events_detected = int(match.group(1))
|
events_detected = int(match.group(1))
|
||||||
|
|
||||||
if not self.should_detect and events_detected > 0:
|
if not self.should_detect and events_detected > 0:
|
||||||
self.fail("Detected {} events when should have detected none".format(
|
self.fail("Detected {} events when should have detected none".format(events_detected))
|
||||||
events_detected))
|
|
||||||
|
|
||||||
if self.should_detect:
|
if self.should_detect:
|
||||||
if events_detected == 0:
|
if events_detected == 0:
|
||||||
self.fail("Detected {} events when should have detected > 0".format(
|
self.fail("Detected {} events when should have detected > 0".format(events_detected))
|
||||||
events_detected))
|
|
||||||
|
|
||||||
for level in self.detect_level:
|
for level in self.detect_level:
|
||||||
level_line = '(?i){}: (\d+)'.format(level)
|
level_line = '(?i){}: (\d+)'.format(level)
|
||||||
match = re.search(level_line, res.stdout.decode("utf-8"))
|
match = re.search(level_line, res.stdout.decode("utf-8"))
|
||||||
|
|
||||||
if match is None:
|
if match is None:
|
||||||
self.fail(
|
self.fail("Could not find a line '{}: <count>' in falco output".format(level))
|
||||||
"Could not find a line '{}: <count>' in falco output".format(level))
|
|
||||||
|
|
||||||
events_detected = int(match.group(1))
|
events_detected = int(match.group(1))
|
||||||
|
|
||||||
if not events_detected > 0:
|
if not events_detected > 0:
|
||||||
self.fail("Detected {} events at level {} when should have detected > 0".format(
|
self.fail("Detected {} events at level {} when should have detected > 0".format(events_detected, level))
|
||||||
events_detected, level))
|
|
||||||
|
|
||||||
def check_detections_by_rule(self, res):
|
def check_detections_by_rule(self, res):
|
||||||
# Get the number of events detected for each rule. Must match the expected counts.
|
# Get the number of events detected for each rule. Must match the expected counts.
|
||||||
match = re.search('Triggered rules by rule name:(.*)',
|
match = re.search('Triggered rules by rule name:(.*)', res.stdout.decode("utf-8"), re.DOTALL)
|
||||||
res.stdout.decode("utf-8"), re.DOTALL)
|
|
||||||
if match is None:
|
if match is None:
|
||||||
self.fail(
|
self.fail("Could not find a block 'Triggered rules by rule name: ...' in falco output")
|
||||||
"Could not find a block 'Triggered rules by rule name: ...' in falco output")
|
|
||||||
|
|
||||||
triggered_rules = match.group(1)
|
triggered_rules = match.group(1)
|
||||||
|
|
||||||
for rule, count in list(self.detect_counts.items()):
|
for rule, count in list(self.detect_counts.items()):
|
||||||
expected = '\s{}: (\d+)'.format(
|
expected = '\s{}: (\d+)'.format(re.sub(r'([$\.*+?()[\]{}|^])', r'\\\1', rule))
|
||||||
re.sub(r'([$\.*+?()[\]{}|^])', r'\\\1', rule))
|
|
||||||
match = re.search(expected, triggered_rules)
|
match = re.search(expected, triggered_rules)
|
||||||
|
|
||||||
if match is None:
|
if match is None:
|
||||||
@@ -357,11 +307,9 @@ class FalcoTest(Test):
|
|||||||
actual_count = int(match.group(1))
|
actual_count = int(match.group(1))
|
||||||
|
|
||||||
if actual_count != count:
|
if actual_count != count:
|
||||||
self.fail("Different counts for rule {}: expected={}, actual={}".format(
|
self.fail("Different counts for rule {}: expected={}, actual={}".format(rule, count, actual_count))
|
||||||
rule, count, actual_count))
|
|
||||||
else:
|
else:
|
||||||
self.log.debug(
|
self.log.debug("Found expected count for rule {}: {}".format(rule, count))
|
||||||
"Found expected count for rule {}: {}".format(rule, count))
|
|
||||||
|
|
||||||
def check_outputs(self):
|
def check_outputs(self):
|
||||||
for output in self.outputs:
|
for output in self.outputs:
|
||||||
@@ -376,8 +324,7 @@ class FalcoTest(Test):
|
|||||||
found = True
|
found = True
|
||||||
|
|
||||||
if found == False:
|
if found == False:
|
||||||
self.fail("Could not find a line '{}' in file '{}'".format(
|
self.fail("Could not find a line '{}' in file '{}'".format(output['line'], output['file']))
|
||||||
output['line'], output['file']))
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -394,27 +341,7 @@ class FalcoTest(Test):
|
|||||||
attrs = ['time', 'rule', 'priority']
|
attrs = ['time', 'rule', 'priority']
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
if not attr in obj:
|
if not attr in obj:
|
||||||
self.fail(
|
self.fail("Falco JSON object {} does not contain property \"{}\"".format(line, attr))
|
||||||
"Falco JSON object {} does not contain property \"{}\"".format(line, attr))
|
|
||||||
|
|
||||||
def check_output_strictly_contains(self, res):
|
|
||||||
for output in self.output_strictly_contains:
|
|
||||||
# Read the expected output (from a file) and actual output (either from a file or the stdout),
|
|
||||||
# then check if the actual one strictly contains the expected one.
|
|
||||||
|
|
||||||
expected = open(output['expected']).read()
|
|
||||||
|
|
||||||
if output['actual'] == 'stdout':
|
|
||||||
actual = res.stdout.decode("utf-8")
|
|
||||||
else:
|
|
||||||
actual = open(output['actual']).read()
|
|
||||||
|
|
||||||
if expected not in actual:
|
|
||||||
self.fail("Output '{}' does not strictly contains the expected content '{}'".format(
|
|
||||||
output['actual'], output['expected']))
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def install_package(self):
|
def install_package(self):
|
||||||
|
|
||||||
@@ -433,39 +360,35 @@ class FalcoTest(Test):
|
|||||||
self.module_dir, self.addl_docker_run_args, image)
|
self.module_dir, self.addl_docker_run_args, image)
|
||||||
|
|
||||||
elif self.package.endswith(".deb"):
|
elif self.package.endswith(".deb"):
|
||||||
self.falco_binary_path = '/usr/bin/falco'
|
self.falco_binary_path = '/usr/bin/falco';
|
||||||
|
|
||||||
package_glob = "{}/{}".format(self.falcodir, self.package)
|
package_glob = "{}/{}".format(self.falcodir, self.package)
|
||||||
|
|
||||||
matches = glob.glob(package_glob)
|
matches = glob.glob(package_glob)
|
||||||
|
|
||||||
if len(matches) != 1:
|
if len(matches) != 1:
|
||||||
self.fail("Package path {} did not match exactly 1 file. Instead it matched: {}",
|
self.fail("Package path {} did not match exactly 1 file. Instead it matched: {}", package_glob, ",".join(matches))
|
||||||
package_glob, ",".join(matches))
|
|
||||||
|
|
||||||
package_path = matches[0]
|
package_path = matches[0]
|
||||||
|
|
||||||
cmdline = "dpkg -i {}".format(package_path)
|
cmdline = "dpkg -i {}".format(package_path)
|
||||||
self.log.debug(
|
self.log.debug("Installing debian package via \"{}\"".format(cmdline))
|
||||||
"Installing debian package via \"{}\"".format(cmdline))
|
|
||||||
res = process.run(cmdline, timeout=120, sudo=True)
|
res = process.run(cmdline, timeout=120, sudo=True)
|
||||||
|
|
||||||
elif self.package.endswith(".rpm"):
|
elif self.package.endswith(".rpm"):
|
||||||
self.falco_binary_path = '/usr/bin/falco'
|
self.falco_binary_path = '/usr/bin/falco';
|
||||||
|
|
||||||
package_glob = "{}/{}".format(self.falcodir, self.package)
|
package_glob = "{}/{}".format(self.falcodir, self.package)
|
||||||
|
|
||||||
matches = glob.glob(package_glob)
|
matches = glob.glob(package_glob)
|
||||||
|
|
||||||
if len(matches) != 1:
|
if len(matches) != 1:
|
||||||
self.fail("Package path {} did not match exactly 1 file. Instead it matched: {}",
|
self.fail("Package path {} did not match exactly 1 file. Instead it matched: {}", package_glob, ",".join(matches))
|
||||||
package_glob, ",".join(matches))
|
|
||||||
|
|
||||||
package_path = matches[0]
|
package_path = matches[0]
|
||||||
|
|
||||||
cmdline = "rpm -i --nodeps --noscripts {}".format(package_path)
|
cmdline = "rpm -i --nodeps --noscripts {}".format(package_path)
|
||||||
self.log.debug(
|
self.log.debug("Installing centos package via \"{}\"".format(cmdline))
|
||||||
"Installing centos package via \"{}\"".format(cmdline))
|
|
||||||
res = process.run(cmdline, timeout=120, sudo=True)
|
res = process.run(cmdline, timeout=120, sudo=True)
|
||||||
|
|
||||||
def uninstall_package(self):
|
def uninstall_package(self):
|
||||||
@@ -475,29 +398,25 @@ class FalcoTest(Test):
|
|||||||
|
|
||||||
elif self.package.endswith(".rpm"):
|
elif self.package.endswith(".rpm"):
|
||||||
cmdline = "rpm -e --noscripts --nodeps falco"
|
cmdline = "rpm -e --noscripts --nodeps falco"
|
||||||
self.log.debug(
|
self.log.debug("Uninstalling centos package via \"{}\"".format(cmdline))
|
||||||
"Uninstalling centos package via \"{}\"".format(cmdline))
|
|
||||||
res = process.run(cmdline, timeout=120, sudo=True)
|
res = process.run(cmdline, timeout=120, sudo=True)
|
||||||
|
|
||||||
elif self.package.endswith(".deb"):
|
elif self.package.endswith(".deb"):
|
||||||
cmdline = "dpkg --purge falco"
|
cmdline = "dpkg --purge falco"
|
||||||
self.log.debug(
|
self.log.debug("Uninstalling debian package via \"{}\"".format(cmdline))
|
||||||
"Uninstalling debian package via \"{}\"".format(cmdline))
|
|
||||||
res = process.run(cmdline, timeout=120, sudo=True)
|
res = process.run(cmdline, timeout=120, sudo=True)
|
||||||
|
|
||||||
def possibly_copy_driver(self):
|
def possibly_copy_driver(self):
|
||||||
# Remove the contents of ~/.falco regardless of copy_local_driver.
|
# Remove the contents of ~/.falco regardless of copy_local_driver.
|
||||||
self.log.debug("Checking for module dir {}".format(self.module_dir))
|
self.log.debug("Checking for module dir {}".format(self.module_dir))
|
||||||
if os.path.isdir(self.module_dir):
|
if os.path.isdir(self.module_dir):
|
||||||
self.log.info(
|
self.log.info("Removing files below directory {}".format(self.module_dir))
|
||||||
"Removing files below directory {}".format(self.module_dir))
|
|
||||||
for rmfile in glob.glob(self.module_dir + "/*"):
|
for rmfile in glob.glob(self.module_dir + "/*"):
|
||||||
self.log.debug("Removing file {}".format(rmfile))
|
self.log.debug("Removing file {}".format(rmfile))
|
||||||
os.remove(rmfile)
|
os.remove(rmfile)
|
||||||
|
|
||||||
if self.copy_local_driver:
|
if self.copy_local_driver:
|
||||||
verlines = [str.strip() for str in subprocess.check_output(
|
verlines = [str.strip() for str in subprocess.check_output([self.falco_binary_path, "--version"]).splitlines()]
|
||||||
[self.falco_binary_path, "--version"]).splitlines()]
|
|
||||||
verstr = verlines[0].decode("utf-8")
|
verstr = verlines[0].decode("utf-8")
|
||||||
self.log.info("verstr {}".format(verstr))
|
self.log.info("verstr {}".format(verstr))
|
||||||
falco_version = verstr.split(" ")[2]
|
falco_version = verstr.split(" ")[2]
|
||||||
@@ -509,12 +428,10 @@ class FalcoTest(Test):
|
|||||||
|
|
||||||
# falco-driver-loader has a more comprehensive set of ways to
|
# falco-driver-loader has a more comprehensive set of ways to
|
||||||
# find the config hash. We only look at /boot/config-<kernel release>
|
# find the config hash. We only look at /boot/config-<kernel release>
|
||||||
md5_output = subprocess.check_output(
|
md5_output = subprocess.check_output(["md5sum", "/boot/config-{}".format(kernel_release)]).rstrip()
|
||||||
["md5sum", "/boot/config-{}".format(kernel_release)]).rstrip()
|
|
||||||
config_hash = md5_output.split(" ")[0]
|
config_hash = md5_output.split(" ")[0]
|
||||||
|
|
||||||
probe_filename = "falco-{}-{}-{}-{}.ko".format(
|
probe_filename = "falco-{}-{}-{}-{}.ko".format(falco_version, arch, kernel_release, config_hash)
|
||||||
falco_version, arch, kernel_release, config_hash)
|
|
||||||
driver_path = os.path.join(self.falcodir, "driver", "falco.ko")
|
driver_path = os.path.join(self.falcodir, "driver", "falco.ko")
|
||||||
module_path = os.path.join(self.module_dir, probe_filename)
|
module_path = os.path.join(self.module_dir, probe_filename)
|
||||||
self.log.debug("Copying {} to {}".format(driver_path, module_path))
|
self.log.debug("Copying {} to {}".format(driver_path, module_path))
|
||||||
@@ -526,12 +443,10 @@ class FalcoTest(Test):
|
|||||||
if not self.is_grpc_using_unix_socket:
|
if not self.is_grpc_using_unix_socket:
|
||||||
self.fail("This test suite supports gRPC with unix socket only")
|
self.fail("This test suite supports gRPC with unix socket only")
|
||||||
|
|
||||||
cmdline = "grpcurl -format text -import-path ../userspace/falco " \
|
cmdline = "grpcurl -import-path ../userspace/falco " \
|
||||||
"-proto {} -plaintext -unix {} " \
|
"-proto {} -plaintext -unix {} " \
|
||||||
"{}/{}".format(self.grpc_proto, self.grpc_address,
|
"{}/{}".format(self.grpc_proto, self.grpc_address, self.grpc_service, self.grpc_method)
|
||||||
self.grpc_service, self.grpc_method)
|
|
||||||
that = self
|
that = self
|
||||||
|
|
||||||
class GRPCUnixSocketEventHandler(PatternMatchingEventHandler):
|
class GRPCUnixSocketEventHandler(PatternMatchingEventHandler):
|
||||||
def on_created(self, event):
|
def on_created(self, event):
|
||||||
# that.log.info("EVENT: {}", event)
|
# that.log.info("EVENT: {}", event)
|
||||||
@@ -555,19 +470,19 @@ class FalcoTest(Test):
|
|||||||
for exp_result in self.grpc_results:
|
for exp_result in self.grpc_results:
|
||||||
found = False
|
found = False
|
||||||
for line in self.grpcurl_res.stdout.decode("utf-8").splitlines():
|
for line in self.grpcurl_res.stdout.decode("utf-8").splitlines():
|
||||||
if exp_result in line:
|
match = re.search(exp_result, line)
|
||||||
|
|
||||||
|
if match is not None:
|
||||||
found = True
|
found = True
|
||||||
break
|
|
||||||
|
|
||||||
if found == False:
|
if found == False:
|
||||||
self.fail(
|
self.fail("Could not find a line '{}' in gRPC responses".format(exp_result))
|
||||||
"Could not find a line with '{}' in gRPC responses (protobuf text".format(exp_result))
|
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
self.log.info("Trace file %s", self.trace_file)
|
self.log.info("Trace file %s", self.trace_file)
|
||||||
|
|
||||||
self.falco_binary_path = '{}/userspace/falco/falco'.format(
|
self.falco_binary_path = '{}/userspace/falco/falco'.format(self.falcodir)
|
||||||
self.falcodir)
|
|
||||||
|
|
||||||
self.possibly_copy_driver()
|
self.possibly_copy_driver()
|
||||||
|
|
||||||
@@ -586,11 +501,9 @@ class FalcoTest(Test):
|
|||||||
if self.psp_file != "":
|
if self.psp_file != "":
|
||||||
|
|
||||||
if not os.path.isfile(self.psp_conv_path):
|
if not os.path.isfile(self.psp_conv_path):
|
||||||
self.log.info("Downloading {} to {}".format(
|
self.log.info("Downloading {} to {}".format(self.psp_conv_url, self.psp_conv_path))
|
||||||
self.psp_conv_url, self.psp_conv_path))
|
|
||||||
|
|
||||||
urllib.request.urlretrieve(
|
urllib.request.urlretrieve(self.psp_conv_url, self.psp_conv_path)
|
||||||
self.psp_conv_url, self.psp_conv_path)
|
|
||||||
os.chmod(self.psp_conv_path, stat.S_IEXEC)
|
os.chmod(self.psp_conv_path, stat.S_IEXEC)
|
||||||
|
|
||||||
conv_cmd = '{} convert psp --psp-path {} --rules-path {}'.format(
|
conv_cmd = '{} convert psp --psp-path {} --rules-path {}'.format(
|
||||||
@@ -608,6 +521,7 @@ class FalcoTest(Test):
|
|||||||
psp_rules = myfile.read()
|
psp_rules = myfile.read()
|
||||||
self.log.debug("Converted Rules: {}".format(psp_rules))
|
self.log.debug("Converted Rules: {}".format(psp_rules))
|
||||||
|
|
||||||
|
|
||||||
# Run falco
|
# Run falco
|
||||||
cmd = '{} {} {} -c {} {} -o json_output={} -o json_include_output_property={} -o priority={} -v'.format(
|
cmd = '{} {} {} -c {} {} -o json_output={} -o json_include_output_property={} -o priority={} -v'.format(
|
||||||
self.falco_binary_path, self.rules_args, self.disabled_args, self.conf_file, trace_arg, self.json_output, self.json_include_output_property, self.priority)
|
self.falco_binary_path, self.rules_args, self.disabled_args, self.conf_file, trace_arg, self.json_output, self.json_include_output_property, self.priority)
|
||||||
@@ -643,26 +557,22 @@ class FalcoTest(Test):
|
|||||||
for pattern in self.stderr_contains:
|
for pattern in self.stderr_contains:
|
||||||
match = re.search(pattern, res.stderr.decode("utf-8"))
|
match = re.search(pattern, res.stderr.decode("utf-8"))
|
||||||
if match is None:
|
if match is None:
|
||||||
self.fail(
|
self.fail("Stderr of falco process did not contain content matching {}".format(pattern))
|
||||||
"Stderr of falco process did not contain content matching {}".format(pattern))
|
|
||||||
|
|
||||||
for pattern in self.stdout_contains:
|
for pattern in self.stdout_contains:
|
||||||
match = re.search(pattern, res.stdout.decode("utf-8"))
|
match = re.search(pattern, res.stdout.decode("utf-8"))
|
||||||
if match is None:
|
if match is None:
|
||||||
self.fail("Stdout of falco process '{}' did not contain content matching {}".format(
|
self.fail("Stdout of falco process '{}' did not contain content matching {}".format(res.stdout.decode("utf-8"), pattern))
|
||||||
res.stdout.decode("utf-8"), pattern))
|
|
||||||
|
|
||||||
for pattern in self.stderr_not_contains:
|
for pattern in self.stderr_not_contains:
|
||||||
match = re.search(pattern, res.stderr.decode("utf-8"))
|
match = re.search(pattern, res.stderr.decode("utf-8"))
|
||||||
if match is not None:
|
if match is not None:
|
||||||
self.fail(
|
self.fail("Stderr of falco process contained content matching {} when it should have not".format(pattern))
|
||||||
"Stderr of falco process contained content matching {} when it should have not".format(pattern))
|
|
||||||
|
|
||||||
for pattern in self.stdout_not_contains:
|
for pattern in self.stdout_not_contains:
|
||||||
match = re.search(pattern, res.stdout.decode("utf-8"))
|
match = re.search(pattern, res.stdout.decode("utf-8"))
|
||||||
if match is not None:
|
if match is not None:
|
||||||
self.fail("Stdout of falco process '{}' did contain content matching {} when it should have not".format(
|
self.fail("Stdout of falco process '{}' did contain content matching {} when it should have not".format(res.stdout.decode("utf-8"), pattern))
|
||||||
res.stdout.decode("utf-8"), pattern))
|
|
||||||
|
|
||||||
if res.exit_status != self.exit_status:
|
if res.exit_status != self.exit_status:
|
||||||
self.error("Falco command \"{}\" exited with unexpected return value {} (!= {})".format(
|
self.error("Falco command \"{}\" exited with unexpected return value {} (!= {})".format(
|
||||||
@@ -680,7 +590,6 @@ class FalcoTest(Test):
|
|||||||
self.check_detections_by_rule(res)
|
self.check_detections_by_rule(res)
|
||||||
self.check_json_output(res)
|
self.check_json_output(res)
|
||||||
self.check_outputs()
|
self.check_outputs()
|
||||||
self.check_output_strictly_contains(res)
|
|
||||||
self.check_grpc()
|
self.check_grpc()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
# Copyright (C) 2016-2018 The Falco Authors..
|
||||||
#
|
#
|
||||||
# This file is part of falco.
|
# This file is part of falco.
|
||||||
#
|
#
|
||||||
@@ -652,50 +652,25 @@ trace_files: !mux
|
|||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
stdout_contains: "Warning An open was seen .cport=<NA> command=cat /dev/null."
|
stdout_contains: "Warning An open was seen .cport=<NA> command=cat /dev/null."
|
||||||
|
|
||||||
stdout_output_strict:
|
file_output:
|
||||||
detect: True
|
|
||||||
detect_level: WARNING
|
|
||||||
rules_file:
|
|
||||||
- rules/single_rule.yaml
|
|
||||||
conf_file: confs/stdout_output.yaml
|
|
||||||
trace_file: trace_files/cat_write.scap
|
|
||||||
time_iso_8601: true
|
|
||||||
output_strictly_contains:
|
|
||||||
- stdout: output_files/single_rule_with_cat_write.txt
|
|
||||||
|
|
||||||
stdout_output_json_strict:
|
|
||||||
json_output: True
|
|
||||||
detect: True
|
|
||||||
detect_level: WARNING
|
|
||||||
rules_file:
|
|
||||||
- rules/single_rule.yaml
|
|
||||||
conf_file: confs/stdout_output.yaml
|
|
||||||
trace_file: trace_files/cat_write.scap
|
|
||||||
time_iso_8601: true
|
|
||||||
output_strictly_contains:
|
|
||||||
- stdout: output_files/single_rule_with_cat_write.json
|
|
||||||
|
|
||||||
file_output_strict:
|
|
||||||
detect: True
|
detect: True
|
||||||
detect_level: WARNING
|
detect_level: WARNING
|
||||||
rules_file:
|
rules_file:
|
||||||
- rules/single_rule.yaml
|
- rules/single_rule.yaml
|
||||||
conf_file: confs/file_output.yaml
|
conf_file: confs/file_output.yaml
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
time_iso_8601: true
|
outputs:
|
||||||
output_strictly_contains:
|
- /tmp/falco_outputs/file_output.txt: Warning An open was seen
|
||||||
- /tmp/falco_outputs/file_output.txt: output_files/single_rule_with_cat_write.txt
|
|
||||||
|
|
||||||
program_output_strict:
|
program_output:
|
||||||
detect: True
|
detect: True
|
||||||
detect_level: WARNING
|
detect_level: WARNING
|
||||||
rules_file:
|
rules_file:
|
||||||
- rules/single_rule.yaml
|
- rules/single_rule.yaml
|
||||||
conf_file: confs/program_output.yaml
|
conf_file: confs/program_output.yaml
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
time_iso_8601: true
|
outputs:
|
||||||
output_strictly_contains:
|
- /tmp/falco_outputs/program_output.txt: Warning An open was seen
|
||||||
- /tmp/falco_outputs/program_output.txt: output_files/single_rule_with_cat_write.txt
|
|
||||||
|
|
||||||
grpc_unix_socket_outputs:
|
grpc_unix_socket_outputs:
|
||||||
detect: True
|
detect: True
|
||||||
@@ -705,26 +680,13 @@ trace_files: !mux
|
|||||||
conf_file: confs/grpc_unix_socket.yaml
|
conf_file: confs/grpc_unix_socket.yaml
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
run_duration: 5
|
run_duration: 5
|
||||||
time_iso_8601: true
|
|
||||||
grpc:
|
grpc:
|
||||||
address: unix:///tmp/falco/falco.sock
|
address: unix:///tmp/falco/falco.sock
|
||||||
proto: outputs.proto
|
proto: outputs.proto
|
||||||
service: falco.outputs.service
|
service: falco.outputs.service
|
||||||
method: get
|
method: get
|
||||||
# protobuf text format
|
|
||||||
results:
|
results:
|
||||||
- "seconds:1470327477 nanos:881781397"
|
- "Warning An open was seen"
|
||||||
- "priority: WARNING"
|
|
||||||
- "rule: \"open_from_cat\""
|
|
||||||
- "output: \"2016-08-04T16:17:57.881781397+0000: Warning An open was seen (command=cat /dev/null)\""
|
|
||||||
# output fields
|
|
||||||
- "key: \"evt.time.iso8601\""
|
|
||||||
- "value: \"2016-08-04T16:17:57.881781397+0000\""
|
|
||||||
- "key: \"proc.cmdline\""
|
|
||||||
- "value: \"cat /dev/null\""
|
|
||||||
# For the hostname, since we don't know that beforehand,
|
|
||||||
# only check the field presence
|
|
||||||
- "hostname: "
|
|
||||||
|
|
||||||
detect_counts:
|
detect_counts:
|
||||||
detect: True
|
detect: True
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
{"output":"2016-08-04T16:17:57.881781397+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881781397Z", "output_fields": {"evt.time.iso8601":1470327477881781397,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
{"output":"2016-08-04T16:17:57.881785348+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881785348Z", "output_fields": {"evt.time.iso8601":1470327477881785348,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
{"output":"2016-08-04T16:17:57.881796705+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881796705Z", "output_fields": {"evt.time.iso8601":1470327477881796705,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
{"output":"2016-08-04T16:17:57.881799840+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881799840Z", "output_fields": {"evt.time.iso8601":1470327477881799840,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
{"output":"2016-08-04T16:17:57.882003104+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882003104Z", "output_fields": {"evt.time.iso8601":1470327477882003104,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
{"output":"2016-08-04T16:17:57.882008208+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882008208Z", "output_fields": {"evt.time.iso8601":1470327477882008208,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
{"output":"2016-08-04T16:17:57.882045694+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882045694Z", "output_fields": {"evt.time.iso8601":1470327477882045694,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
{"output":"2016-08-04T16:17:57.882054739+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882054739Z", "output_fields": {"evt.time.iso8601":1470327477882054739,"proc.cmdline":"cat /dev/null"}}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
2016-08-04T16:17:57.881781397+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
2016-08-04T16:17:57.881785348+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
2016-08-04T16:17:57.881796705+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
2016-08-04T16:17:57.881799840+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
2016-08-04T16:17:57.882003104+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
2016-08-04T16:17:57.882008208+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
2016-08-04T16:17:57.882045694+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
2016-08-04T16:17:57.882054739+0000: Warning An open was seen (command=cat /dev/null)
|
|
||||||
@@ -18,5 +18,5 @@
|
|||||||
desc: Detect any connect to the localhost network, using fd.net and the in operator
|
desc: Detect any connect to the localhost network, using fd.net and the in operator
|
||||||
condition: evt.type=connect and fd.net in ("127.0.0.1/24")
|
condition: evt.type=connect and fd.net in ("127.0.0.1/24")
|
||||||
output: Program connected to localhost network
|
output: Program connected to localhost network
|
||||||
(user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name)
|
(user=%user.name command=%proc.cmdline connection=%fd.name)
|
||||||
priority: INFO
|
priority: INFO
|
||||||
|
|||||||
@@ -19,13 +19,6 @@ set -euo pipefail
|
|||||||
|
|
||||||
SCRIPT=$(readlink -f $0)
|
SCRIPT=$(readlink -f $0)
|
||||||
SCRIPTDIR=$(dirname "$SCRIPT")
|
SCRIPTDIR=$(dirname "$SCRIPT")
|
||||||
SKIP_PACKAGES_TESTS=${SKIP_PACKAGES_TESTS:-false}
|
|
||||||
|
|
||||||
# Trace file tarballs are now versioned. Any time a substantial change
|
|
||||||
# is made that affects the interaction of rules+engine and the trace
|
|
||||||
# files here, upload a new trace file zip file and change the version
|
|
||||||
# suffix here.
|
|
||||||
TRACE_FILES_VERSION=20200831
|
|
||||||
|
|
||||||
function download_trace_files() {
|
function download_trace_files() {
|
||||||
for TRACE in traces-positive traces-negative traces-info ; do
|
for TRACE in traces-positive traces-negative traces-info ; do
|
||||||
@@ -33,7 +26,7 @@ function download_trace_files() {
|
|||||||
if [ "$OPT_BRANCH" != "none" ]; 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
|
curl -fso "$TRACE_DIR/$TRACE.zip" https://s3.amazonaws.com/download.draios.com/falco-tests/$TRACE-$OPT_BRANCH.zip
|
||||||
else
|
else
|
||||||
curl -fso "$TRACE_DIR/$TRACE.zip" https://s3.amazonaws.com/download.draios.com/falco-tests/$TRACE-$TRACE_FILES_VERSION.zip
|
curl -fso "$TRACE_DIR/$TRACE.zip" https://s3.amazonaws.com/download.draios.com/falco-tests/$TRACE.zip
|
||||||
fi
|
fi
|
||||||
unzip -d "$TRACE_DIR" "$TRACE_DIR/$TRACE.zip"
|
unzip -d "$TRACE_DIR" "$TRACE_DIR/$TRACE.zip"
|
||||||
rm -rf "$TRACE_DIR/$TRACE.zip"
|
rm -rf "$TRACE_DIR/$TRACE.zip"
|
||||||
@@ -98,18 +91,8 @@ function run_tests() {
|
|||||||
# as we're watching the return status when running avocado.
|
# as we're watching the return status when running avocado.
|
||||||
set +e
|
set +e
|
||||||
TEST_RC=0
|
TEST_RC=0
|
||||||
suites=($SCRIPTDIR/falco_traces.yaml $SCRIPTDIR/falco_tests.yaml $SCRIPTDIR/falco_k8s_audit_tests.yaml $SCRIPTDIR/falco_tests_psp.yaml)
|
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"
|
||||||
if [ "$SKIP_PACKAGES_TESTS" = false ] ; then
|
|
||||||
suites+=($SCRIPTDIR/falco_tests_package.yaml)
|
|
||||||
fi
|
|
||||||
|
|
||||||
XUNIT_DIR="${OPT_BUILD_DIR}/integration-tests-xunit"
|
|
||||||
mkdir -p "${XUNIT_DIR}"
|
|
||||||
|
|
||||||
for mult in "${suites[@]}"; do
|
|
||||||
XUNIT_FILE_NAME="${XUNIT_DIR}/$(basename "${mult}").xml"
|
|
||||||
CMD="avocado run --xunit ${XUNIT_FILE_NAME} --mux-yaml $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
|
|
||||||
echo "Running $CMD"
|
echo "Running $CMD"
|
||||||
BUILD_DIR=${OPT_BUILD_DIR} $CMD
|
BUILD_DIR=${OPT_BUILD_DIR} $CMD
|
||||||
RC=$?
|
RC=$?
|
||||||
|
|||||||
@@ -14,11 +14,7 @@
|
|||||||
# License for the specific language governing permissions and limitations under
|
# License for the specific language governing permissions and limitations under
|
||||||
# the License.
|
# the License.
|
||||||
#
|
#
|
||||||
if(MINIMAL_BUILD)
|
|
||||||
set(FALCO_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp engine/test_rulesets.cpp engine/test_falco_utils.cpp)
|
|
||||||
else()
|
|
||||||
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_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp engine/test_rulesets.cpp engine/test_falco_utils.cpp falco/test_webserver.cpp)
|
||||||
endif()
|
|
||||||
|
|
||||||
set(FALCO_TESTED_LIBRARIES falco_engine)
|
set(FALCO_TESTED_LIBRARIES falco_engine)
|
||||||
|
|
||||||
@@ -39,16 +35,6 @@ if(FALCO_BUILD_TESTS)
|
|||||||
add_executable(falco_test ${FALCO_TESTS_SOURCES})
|
add_executable(falco_test ${FALCO_TESTS_SOURCES})
|
||||||
|
|
||||||
target_link_libraries(falco_test PUBLIC ${FALCO_TESTED_LIBRARIES})
|
target_link_libraries(falco_test PUBLIC ${FALCO_TESTED_LIBRARIES})
|
||||||
|
|
||||||
if(MINIMAL_BUILD)
|
|
||||||
target_include_directories(
|
|
||||||
falco_test
|
|
||||||
PUBLIC "${CATCH2_INCLUDE}"
|
|
||||||
"${FAKEIT_INCLUDE}"
|
|
||||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
|
||||||
"${YAMLCPP_INCLUDE_DIR}"
|
|
||||||
"${PROJECT_SOURCE_DIR}/userspace/falco")
|
|
||||||
else()
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
falco_test
|
falco_test
|
||||||
PUBLIC "${CATCH2_INCLUDE}"
|
PUBLIC "${CATCH2_INCLUDE}"
|
||||||
@@ -57,7 +43,6 @@ if(FALCO_BUILD_TESTS)
|
|||||||
"${YAMLCPP_INCLUDE_DIR}"
|
"${YAMLCPP_INCLUDE_DIR}"
|
||||||
"${CIVETWEB_INCLUDE_DIR}"
|
"${CIVETWEB_INCLUDE_DIR}"
|
||||||
"${PROJECT_SOURCE_DIR}/userspace/falco")
|
"${PROJECT_SOURCE_DIR}/userspace/falco")
|
||||||
endif()
|
|
||||||
add_dependencies(falco_test catch2)
|
add_dependencies(falco_test catch2)
|
||||||
|
|
||||||
include(CMakeParseArguments)
|
include(CMakeParseArguments)
|
||||||
|
|||||||
@@ -27,19 +27,6 @@ if(USE_BUNDLED_DEPS)
|
|||||||
add_dependencies(falco_engine libyaml)
|
add_dependencies(falco_engine libyaml)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MINIMAL_BUILD)
|
|
||||||
target_include_directories(
|
|
||||||
falco_engine
|
|
||||||
PUBLIC
|
|
||||||
"${LUAJIT_INCLUDE}"
|
|
||||||
"${NJSON_INCLUDE}"
|
|
||||||
"${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"
|
|
||||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
|
||||||
else()
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
falco_engine
|
falco_engine
|
||||||
PUBLIC
|
PUBLIC
|
||||||
@@ -52,7 +39,6 @@ else()
|
|||||||
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
|
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
|
||||||
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
|
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
|
||||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
"${PROJECT_BINARY_DIR}/userspace/engine")
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}")
|
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}")
|
||||||
|
|
||||||
|
|||||||
@@ -171,8 +171,9 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
|
|||||||
m_ls);
|
m_ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that falco_formats is added to the lua state used
|
// Note that falco_formats is added to both the lua state used
|
||||||
// by the falco engine only. Within the engine, only
|
// by the falco engine as well as the separate lua state used
|
||||||
|
// by falco outputs. Within the engine, only
|
||||||
// formats.formatter is used, so we can unconditionally set
|
// formats.formatter is used, so we can unconditionally set
|
||||||
// json_output to false.
|
// json_output to false.
|
||||||
bool json_output = false;
|
bool json_output = false;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
// The version of rules/filter fields/etc supported by this falco
|
// The version of rules/filter fields/etc supported by this falco
|
||||||
// engine.
|
// engine.
|
||||||
#define FALCO_ENGINE_VERSION (7)
|
#define FALCO_ENGINE_VERSION (6)
|
||||||
|
|
||||||
// This is the result of running "falco --list -N | sha256sum" and
|
// This is the result of running "falco --list -N | sha256sum" and
|
||||||
// represents the fields supported by this version of falco. It's used
|
// represents the fields supported by this version of falco. It's used
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -20,17 +20,22 @@ limitations under the License.
|
|||||||
#include "falco_engine.h"
|
#include "falco_engine.h"
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
|
|
||||||
sinsp* falco_formats::s_inspector = NULL;
|
sinsp* falco_formats::s_inspector = NULL;
|
||||||
falco_engine *falco_formats::s_engine = NULL;
|
falco_engine *falco_formats::s_engine = NULL;
|
||||||
bool falco_formats::s_json_output = false;
|
bool falco_formats::s_json_output = false;
|
||||||
bool falco_formats::s_json_include_output_property = true;
|
bool falco_formats::s_json_include_output_property = true;
|
||||||
std::unique_ptr<sinsp_evt_formatter_cache> falco_formats::s_formatters = NULL;
|
sinsp_evt_formatter_cache *falco_formats::s_formatters = NULL;
|
||||||
|
|
||||||
const static struct luaL_Reg ll_falco[] =
|
const static struct luaL_reg ll_falco [] =
|
||||||
{
|
{
|
||||||
{"formatter", &falco_formats::lua_formatter},
|
{"formatter", &falco_formats::formatter},
|
||||||
{"free_formatter", &falco_formats::lua_free_formatter},
|
{"free_formatter", &falco_formats::free_formatter},
|
||||||
{NULL, NULL}};
|
{"free_formatters", &falco_formats::free_formatters},
|
||||||
|
{"format_event", &falco_formats::format_event},
|
||||||
|
{"resolve_tokens", &falco_formats::resolve_tokens},
|
||||||
|
{NULL,NULL}
|
||||||
|
};
|
||||||
|
|
||||||
void falco_formats::init(sinsp* inspector,
|
void falco_formats::init(sinsp* inspector,
|
||||||
falco_engine *engine,
|
falco_engine *engine,
|
||||||
@@ -42,14 +47,15 @@ void falco_formats::init(sinsp *inspector,
|
|||||||
s_engine = engine;
|
s_engine = engine;
|
||||||
s_json_output = json_output;
|
s_json_output = json_output;
|
||||||
s_json_include_output_property = json_include_output_property;
|
s_json_include_output_property = json_include_output_property;
|
||||||
|
if(!s_formatters)
|
||||||
// todo(leogr): we should have used std::make_unique, but we cannot since it's not C++14
|
{
|
||||||
s_formatters = std::unique_ptr<sinsp_evt_formatter_cache>(new sinsp_evt_formatter_cache(s_inspector));
|
s_formatters = new sinsp_evt_formatter_cache(s_inspector);
|
||||||
|
}
|
||||||
|
|
||||||
luaL_openlib(ls, "formats", ll_falco, 0);
|
luaL_openlib(ls, "formats", ll_falco, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int falco_formats::lua_formatter(lua_State *ls)
|
int falco_formats::formatter(lua_State *ls)
|
||||||
{
|
{
|
||||||
string source = luaL_checkstring(ls, -2);
|
string source = luaL_checkstring(ls, -2);
|
||||||
string format = luaL_checkstring(ls, -1);
|
string format = luaL_checkstring(ls, -1);
|
||||||
@@ -81,7 +87,7 @@ int falco_formats::lua_formatter(lua_State *ls)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int falco_formats::lua_free_formatter(lua_State *ls)
|
int falco_formats::free_formatter(lua_State *ls)
|
||||||
{
|
{
|
||||||
if (!lua_islightuserdata(ls, -1) ||
|
if (!lua_islightuserdata(ls, -1) ||
|
||||||
!lua_isstring(ls, -2))
|
!lua_isstring(ls, -2))
|
||||||
@@ -106,16 +112,40 @@ int falco_formats::lua_free_formatter(lua_State *ls)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string falco_formats::format_event(const gen_event *evt, const std::string &rule, const std::string &source,
|
int falco_formats::free_formatters(lua_State *ls)
|
||||||
const std::string &level, const std::string &format)
|
|
||||||
{
|
{
|
||||||
|
if(s_formatters)
|
||||||
|
{
|
||||||
|
delete(s_formatters);
|
||||||
|
s_formatters = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int falco_formats::format_event (lua_State *ls)
|
||||||
|
{
|
||||||
string line;
|
string line;
|
||||||
string json_line;
|
string json_line;
|
||||||
|
|
||||||
|
if (!lua_isstring(ls, -1) ||
|
||||||
|
!lua_isstring(ls, -2) ||
|
||||||
|
!lua_isstring(ls, -3) ||
|
||||||
|
!lua_isstring(ls, -4) ||
|
||||||
|
!lua_islightuserdata(ls, -5)) {
|
||||||
|
lua_pushstring(ls, "Invalid arguments passed to format_event()");
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
gen_event* evt = (gen_event*)lua_topointer(ls, 1);
|
||||||
|
const char *rule = (char *) lua_tostring(ls, 2);
|
||||||
|
const char *source = (char *) lua_tostring(ls, 3);
|
||||||
|
const char *level = (char *) lua_tostring(ls, 4);
|
||||||
|
const char *format = (char *) lua_tostring(ls, 5);
|
||||||
|
|
||||||
string sformat = format;
|
string sformat = format;
|
||||||
|
|
||||||
if(strcmp(source.c_str(), "syscall") == 0)
|
if(strcmp(source, "syscall") == 0)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
// This is "output"
|
// This is "output"
|
||||||
s_formatters->tostring((sinsp_evt *) evt, sformat, &line);
|
s_formatters->tostring((sinsp_evt *) evt, sformat, &line);
|
||||||
|
|
||||||
@@ -154,8 +184,17 @@ string falco_formats::format_event(const gen_event *evt, const std::string &rule
|
|||||||
s_inspector->set_buffer_format(cur_fmt);
|
s_inspector->set_buffer_format(cur_fmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (sinsp_exception& e)
|
||||||
|
{
|
||||||
|
string err = "Invalid output format '" + sformat + "': '" + string(e.what()) + "'";
|
||||||
|
lua_pushstring(ls, err.c_str());
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
json_event_formatter formatter(s_engine->json_factory(), sformat);
|
json_event_formatter formatter(s_engine->json_factory(), sformat);
|
||||||
|
|
||||||
line = formatter.tostring((json_event *) evt);
|
line = formatter.tostring((json_event *) evt);
|
||||||
@@ -165,14 +204,20 @@ string falco_formats::format_event(const gen_event *evt, const std::string &rule
|
|||||||
json_line = formatter.tojson((json_event *) evt);
|
json_line = formatter.tojson((json_event *) evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (exception &e)
|
||||||
|
{
|
||||||
|
string err = "Invalid output format '" + sformat + "': '" + string(e.what()) + "'";
|
||||||
|
lua_pushstring(ls, err.c_str());
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For JSON output, the formatter returned a json-as-text
|
// For JSON output, the formatter returned a json-as-text
|
||||||
// object containing all the fields in the original format
|
// object containing all the fields in the original format
|
||||||
// message as well as the event time in ns. Use this to build
|
// message as well as the event time in ns. Use this to build
|
||||||
// a more detailed object containing the event time, rule,
|
// a more detailed object containing the event time, rule,
|
||||||
// severity, full output, and fields.
|
// severity, full output, and fields.
|
||||||
if(s_json_output)
|
if (s_json_output) {
|
||||||
{
|
|
||||||
Json::Value event;
|
Json::Value event;
|
||||||
Json::FastWriter writer;
|
Json::FastWriter writer;
|
||||||
string full_line;
|
string full_line;
|
||||||
@@ -216,12 +261,24 @@ string falco_formats::format_event(const gen_event *evt, const std::string &rule
|
|||||||
line = full_line;
|
line = full_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
return line.c_str();
|
lua_pushstring(ls, line.c_str());
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
map<string, string> falco_formats::resolve_tokens(const gen_event *evt, const std::string &source, const std::string &format)
|
int falco_formats::resolve_tokens(lua_State *ls)
|
||||||
{
|
{
|
||||||
|
if(!lua_isstring(ls, -1) ||
|
||||||
|
!lua_isstring(ls, -2) ||
|
||||||
|
!lua_islightuserdata(ls, -3))
|
||||||
|
{
|
||||||
|
lua_pushstring(ls, "Invalid arguments passed to resolve_tokens()");
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
gen_event *evt = (gen_event *)lua_topointer(ls, 1);
|
||||||
|
string source = luaL_checkstring(ls, 2);
|
||||||
|
const char *format = (char *)lua_tostring(ls, 3);
|
||||||
string sformat = format;
|
string sformat = format;
|
||||||
|
|
||||||
map<string, string> values;
|
map<string, string> values;
|
||||||
if(source == "syscall")
|
if(source == "syscall")
|
||||||
{
|
{
|
||||||
@@ -233,5 +290,14 @@ map<string, string> falco_formats::resolve_tokens(const gen_event *evt, const st
|
|||||||
json_event_formatter json_formatter(s_engine->json_factory(), sformat);
|
json_event_formatter json_formatter(s_engine->json_factory(), sformat);
|
||||||
values = json_formatter.tomap((json_event*) evt);
|
values = json_formatter.tomap((json_event*) evt);
|
||||||
}
|
}
|
||||||
return values;
|
|
||||||
|
lua_newtable(ls);
|
||||||
|
for(auto const& v : values)
|
||||||
|
{
|
||||||
|
lua_pushstring(ls, v.first.c_str());
|
||||||
|
lua_pushstring(ls, v.second.c_str());
|
||||||
|
lua_settable(ls, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -18,8 +18,7 @@ limitations under the License.
|
|||||||
|
|
||||||
#include "sinsp.h"
|
#include "sinsp.h"
|
||||||
|
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
@@ -40,20 +39,23 @@ public:
|
|||||||
bool json_include_output_property);
|
bool json_include_output_property);
|
||||||
|
|
||||||
// formatter = falco.formatter(format_string)
|
// formatter = falco.formatter(format_string)
|
||||||
static int lua_formatter(lua_State *ls);
|
static int formatter(lua_State *ls);
|
||||||
|
|
||||||
// falco.free_formatter(formatter)
|
// falco.free_formatter(formatter)
|
||||||
static int lua_free_formatter(lua_State *ls);
|
static int free_formatter(lua_State *ls);
|
||||||
|
|
||||||
static string format_event(const gen_event *evt, const std::string &rule, const std::string &source,
|
// falco.free_formatters()
|
||||||
const std::string &level, const std::string &format);
|
static int free_formatters(lua_State *ls);
|
||||||
|
|
||||||
static map<string, string> resolve_tokens(const gen_event *evt, const std::string &source,
|
// formatted_string = falco.format_event(evt, formatter)
|
||||||
const std::string &format);
|
static int format_event(lua_State *ls);
|
||||||
|
|
||||||
|
// resolve_tokens = falco.resolve_tokens(evt, formatter)
|
||||||
|
static int resolve_tokens(lua_State *ls);
|
||||||
|
|
||||||
static sinsp* s_inspector;
|
static sinsp* s_inspector;
|
||||||
static falco_engine *s_engine;
|
static falco_engine *s_engine;
|
||||||
static std::unique_ptr<sinsp_evt_formatter_cache> s_formatters;
|
static sinsp_evt_formatter_cache *s_formatters;
|
||||||
static bool s_json_output;
|
static bool s_json_output;
|
||||||
static bool s_json_include_output_property;
|
static bool s_json_include_output_property;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,14 +26,15 @@ extern "C" {
|
|||||||
#include "falco_engine.h"
|
#include "falco_engine.h"
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
const static struct luaL_Reg ll_falco_rules[] =
|
const static struct luaL_reg ll_falco_rules [] =
|
||||||
{
|
{
|
||||||
{"clear_filters", &falco_rules::clear_filters},
|
{"clear_filters", &falco_rules::clear_filters},
|
||||||
{"add_filter", &falco_rules::add_filter},
|
{"add_filter", &falco_rules::add_filter},
|
||||||
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
|
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
|
||||||
{"enable_rule", &falco_rules::enable_rule},
|
{"enable_rule", &falco_rules::enable_rule},
|
||||||
{"engine_version", &falco_rules::engine_version},
|
{"engine_version", &falco_rules::engine_version},
|
||||||
{NULL, NULL}};
|
{NULL,NULL}
|
||||||
|
};
|
||||||
|
|
||||||
falco_rules::falco_rules(sinsp* inspector,
|
falco_rules::falco_rules(sinsp* inspector,
|
||||||
falco_engine *engine,
|
falco_engine *engine,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2020 The Falco Authors.
|
# Copyright (C) 2019 The Falco Authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
# 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
|
# the License. You may obtain a copy of the License at
|
||||||
@@ -11,133 +11,8 @@
|
|||||||
# specific language governing permissions and limitations under the License.
|
# specific language governing permissions and limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
configure_file(config_falco.h.in config_falco.h)
|
configure_file("${SYSDIG_SOURCE_DIR}/userspace/sysdig/config_sysdig.h.in" config_sysdig.h)
|
||||||
|
|
||||||
set(
|
|
||||||
FALCO_SOURCES
|
|
||||||
cli.cpp
|
|
||||||
configuration.cpp
|
|
||||||
logger.cpp
|
|
||||||
falco_outputs.cpp
|
|
||||||
outputs_file.cpp
|
|
||||||
outputs_program.cpp
|
|
||||||
outputs_stdout.cpp
|
|
||||||
outputs_syslog.cpp
|
|
||||||
event_drops.cpp
|
|
||||||
statsfilewriter.cpp
|
|
||||||
falco.cpp
|
|
||||||
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/fields_info.cpp"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(
|
|
||||||
FALCO_INCLUDE_DIRECTORIES
|
|
||||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
|
||||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
|
||||||
"${PROJECT_BINARY_DIR}/driver/src"
|
|
||||||
"${STRING_VIEW_LITE_INCLUDE}"
|
|
||||||
"${CXXOPTS_INCLUDE}"
|
|
||||||
"${YAMLCPP_INCLUDE_DIR}"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(
|
|
||||||
FALCO_DEPENDENCIES
|
|
||||||
cxxopts
|
|
||||||
string-view-lite
|
|
||||||
libyaml
|
|
||||||
b64
|
|
||||||
luajit
|
|
||||||
lpeg
|
|
||||||
lyaml
|
|
||||||
)
|
|
||||||
|
|
||||||
set(
|
|
||||||
FALCO_LIBRARIES
|
|
||||||
falco_engine
|
|
||||||
sinsp
|
|
||||||
"${LIBYAML_LIB}"
|
|
||||||
"${YAMLCPP_LIB}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if(USE_BUNDLED_DEPS)
|
|
||||||
list(APPEND FALCO_DEPENDENCIES yamlcpp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
list(
|
|
||||||
APPEND FALCO_SOURCES
|
|
||||||
outputs_grpc.cpp
|
|
||||||
outputs_http.cpp
|
|
||||||
webserver.cpp
|
|
||||||
grpc_context.cpp
|
|
||||||
grpc_server_impl.cpp
|
|
||||||
grpc_request_context.cpp
|
|
||||||
grpc_server.cpp
|
|
||||||
grpc_context.cpp
|
|
||||||
grpc_server_impl.cpp
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
list(
|
|
||||||
APPEND FALCO_INCLUDE_DIRECTORIES
|
|
||||||
"${CIVETWEB_INCLUDE_DIR}"
|
|
||||||
"${OPENSSL_INCLUDE_DIR}"
|
|
||||||
"${GRPC_INCLUDE}"
|
|
||||||
"${GRPCPP_INCLUDE}"
|
|
||||||
"${PROTOBUF_INCLUDE}"
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND FALCO_DEPENDENCIES civetweb)
|
|
||||||
|
|
||||||
list(
|
|
||||||
APPEND FALCO_LIBRARIES
|
|
||||||
"${GPR_LIB}"
|
|
||||||
"${GRPC_LIB}"
|
|
||||||
"${GRPCPP_LIB}"
|
|
||||||
"${PROTOBUF_LIB}"
|
|
||||||
"${OPENSSL_LIBRARY_SSL}"
|
|
||||||
"${OPENSSL_LIBRARY_CRYPTO}"
|
|
||||||
"${LIBYAML_LIB}"
|
|
||||||
"${YAMLCPP_LIB}"
|
|
||||||
"${CIVETWEB_LIB}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(
|
|
||||||
falco
|
|
||||||
${FALCO_SOURCES}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_dependencies(falco ${FALCO_DEPENDENCIES})
|
|
||||||
|
|
||||||
target_link_libraries(
|
|
||||||
falco
|
|
||||||
${FALCO_LIBRARIES}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(
|
|
||||||
falco
|
|
||||||
PUBLIC
|
|
||||||
${FALCO_INCLUDE_DIRECTORIES}
|
|
||||||
)
|
|
||||||
|
|
||||||
# if(NOT MINIMAL_BUILD)
|
|
||||||
# add_custom_command(
|
|
||||||
# TARGET falco
|
|
||||||
# COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR}
|
|
||||||
# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
# COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields"
|
|
||||||
# )
|
|
||||||
# else()
|
|
||||||
# message(STATUS "Skipping engine fields checksum when building the minimal Falco.")
|
|
||||||
# endif()
|
|
||||||
|
|
||||||
if(NOT MINIMAL_BUILD)
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT
|
OUTPUT
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||||
@@ -162,18 +37,80 @@ if(NOT MINIMAL_BUILD)
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
||||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
)
|
|
||||||
|
add_executable(
|
||||||
|
falco
|
||||||
|
configuration.cpp
|
||||||
|
logger.cpp
|
||||||
|
falco_outputs.cpp
|
||||||
|
event_drops.cpp
|
||||||
|
statsfilewriter.cpp
|
||||||
|
falco.cpp
|
||||||
|
"${SYSDIG_SOURCE_DIR}/userspace/sysdig/fields_info.cpp"
|
||||||
|
webserver.cpp
|
||||||
|
grpc_context.cpp
|
||||||
|
grpc_server_impl.cpp
|
||||||
|
grpc_request_context.cpp
|
||||||
|
grpc_server.cpp
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc)
|
||||||
|
|
||||||
|
add_dependencies(falco civetweb string-view-lite)
|
||||||
|
|
||||||
|
if(USE_BUNDLED_DEPS)
|
||||||
|
add_dependencies(falco yamlcpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# strip the Falco binary when releasing using musl
|
target_include_directories(
|
||||||
if(MUSL_OPTIMIZED_BUILD AND CMAKE_BUILD_TYPE STREQUAL "release")
|
falco
|
||||||
|
PUBLIC
|
||||||
|
"${SYSDIG_SOURCE_DIR}/userspace/sysdig"
|
||||||
|
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||||
|
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||||
|
"${PROJECT_BINARY_DIR}/driver/src"
|
||||||
|
"${STRING_VIEW_LITE_INCLUDE}"
|
||||||
|
"${YAMLCPP_INCLUDE_DIR}"
|
||||||
|
"${CIVETWEB_INCLUDE_DIR}"
|
||||||
|
"${OPENSSL_INCLUDE_DIR}"
|
||||||
|
"${GRPC_INCLUDE}"
|
||||||
|
"${GRPCPP_INCLUDE}"
|
||||||
|
"${PROTOBUF_INCLUDE}"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include")
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
falco
|
||||||
|
falco_engine
|
||||||
|
sinsp
|
||||||
|
"${GPR_LIB}"
|
||||||
|
"${GRPC_LIB}"
|
||||||
|
"${GRPCPP_LIB}"
|
||||||
|
"${PROTOBUF_LIB}"
|
||||||
|
"${OPENSSL_LIBRARY_SSL}"
|
||||||
|
"${OPENSSL_LIBRARY_CRYPTO}"
|
||||||
|
"${LIBYAML_LIB}"
|
||||||
|
"${YAMLCPP_LIB}"
|
||||||
|
"${CIVETWEB_LIB}")
|
||||||
|
|
||||||
|
configure_file(config_falco.h.in config_falco.h)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET falco
|
TARGET falco
|
||||||
POST_BUILD
|
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR} ${OPENSSL_BINARY}
|
||||||
COMMAND ${CMAKE_STRIP} --strip-unneeded falco
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMENT "Strip the Falco binary when releasing the musl build"
|
COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields")
|
||||||
)
|
|
||||||
endif()
|
# add_custom_target(verify_engine_fields DEPENDS verify_engine_fields.sh falco_engine.h)
|
||||||
|
|
||||||
|
# add_dependencies(verify_engine_fields falco)
|
||||||
|
|
||||||
install(TARGETS falco DESTINATION ${FALCO_BIN_DIR})
|
install(TARGETS falco DESTINATION ${FALCO_BIN_DIR})
|
||||||
|
install(
|
||||||
|
DIRECTORY lua
|
||||||
|
DESTINATION ${FALCO_SHARE_DIR}
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN *.lua)
|
||||||
|
|||||||
@@ -1,22 +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 "cli.h"
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,188 +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 <cxxopts.hpp>
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
|
|
||||||
class option_requires_specific_argument_exception : public cxxopts::OptionParseException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit option_requires_specific_argument_exception(const std::string& option, const std::string& values):
|
|
||||||
OptionParseException("Option " + cxxopts::LQUOTE + option + cxxopts::RQUOTE + " requires an argument equal to " + values)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class option_cannot_be_specified_exception : public cxxopts::OptionParseException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit option_cannot_be_specified_exception(const std::string& option1, const std::string& option2):
|
|
||||||
OptionParseException("Options " + cxxopts::LQUOTE + option1 + cxxopts::RQUOTE + " and " + cxxopts::LQUOTE + option2 + cxxopts::RQUOTE + " can not be specified together")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class cli
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cli(int argc, const char** argv):
|
|
||||||
m_argc(argc), m_argv(argv), m_options("falco", "Cloud-Native Runtime Security")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual ~cli()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
// These options give some info about Falco (Falco exits).
|
|
||||||
m_options.add_options(
|
|
||||||
"help",
|
|
||||||
{
|
|
||||||
{"h,help", "Print help page."},
|
|
||||||
{"support", "Print support information (version, rules files, etc.)."},
|
|
||||||
{"version", "Print version info."},
|
|
||||||
});
|
|
||||||
|
|
||||||
// These are options responsible for listing Falco elements (Falco exits).
|
|
||||||
m_options.add_options(
|
|
||||||
"list",
|
|
||||||
{
|
|
||||||
{"L", "Show name and description of all rules."},
|
|
||||||
{"l", "Show name and description of a specific rule.", cxxopts::value<std::string>(), "rule name"},
|
|
||||||
{"list", "Show all fields.", cxxopts::value<std::string>()->implicit_value("all"), "sycall|k8s_audit"},
|
|
||||||
{"N", "Show field names only."},
|
|
||||||
});
|
|
||||||
|
|
||||||
// m_options.add_options(
|
|
||||||
// "output",
|
|
||||||
// {
|
|
||||||
// {},
|
|
||||||
// });
|
|
||||||
|
|
||||||
// m_options.add_options(
|
|
||||||
// "input",
|
|
||||||
// {
|
|
||||||
// {},
|
|
||||||
// });
|
|
||||||
|
|
||||||
m_options.add_options(
|
|
||||||
"filtering",
|
|
||||||
{
|
|
||||||
{"D", "Disable any rules with names having the given substring. Can be specified multiple times. Can not be specified with -t.", cxxopts::value<std::vector<std::string>>(), "substring"},
|
|
||||||
{"T", "Disable any rules with a specific tag. Can be specified several times. Can not be specified with -t.", cxxopts::value<std::vector<std::string>>(), "tag"},
|
|
||||||
{"t", "Only run those rules with a specific tag. Can be specified several times. Can not be specified with -T or -D.", cxxopts::value<std::vector<std::string>>(), "tag"},
|
|
||||||
});
|
|
||||||
|
|
||||||
m_result = m_options.parse(m_argc, m_argv);
|
|
||||||
|
|
||||||
process();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void process()
|
|
||||||
{
|
|
||||||
if(m_result.count("help") && m_result["help"].as<bool>())
|
|
||||||
{
|
|
||||||
std::cout << m_options.help() << std::endl;
|
|
||||||
// todo: print > exit
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_result.count("support") && m_result["support"].as<bool>())
|
|
||||||
{
|
|
||||||
// todo: argv + config rule filenames > cmdline > print > exit
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_result.count("version") && m_result["version"].as<bool>())
|
|
||||||
{
|
|
||||||
// todo: print > exit
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_result.count("L") && m_result["L"].as<bool>())
|
|
||||||
{
|
|
||||||
// todo: engine > print > exit
|
|
||||||
// engine->describe_rule(NULL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_result.count("l"))
|
|
||||||
{
|
|
||||||
// todo: engine > print > exit
|
|
||||||
// engine->describe_rule(m_result["l"].as<string>());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_result.count("list"))
|
|
||||||
{
|
|
||||||
auto source = m_result["list"].as<std::string>();
|
|
||||||
// todo: retrieve implicit value
|
|
||||||
if(source.empty() || (source != "syscall" && source != "k8s_audit" && source != "all"))
|
|
||||||
{
|
|
||||||
throw falco::option_requires_specific_argument_exception(
|
|
||||||
"list",
|
|
||||||
cxxopts::LQUOTE + "syscall" + cxxopts::RQUOTE + " or " + cxxopts::LQUOTE + "k8s_audit" + cxxopts::RQUOTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool names_only = false;
|
|
||||||
if(m_result.count("N"))
|
|
||||||
{
|
|
||||||
names_only = m_result["N"].as<bool>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: engine + names_only + source
|
|
||||||
// se valore == syscall ==> + [-V]
|
|
||||||
}
|
|
||||||
|
|
||||||
bool count_D = m_result.count("D");
|
|
||||||
bool count_t = m_result.count("t");
|
|
||||||
bool count_T = m_result.count("T");
|
|
||||||
if(count_D > 0)
|
|
||||||
{
|
|
||||||
if(count_t > 0)
|
|
||||||
{
|
|
||||||
throw falco::option_cannot_be_specified_exception("D", "t");
|
|
||||||
}
|
|
||||||
// todo
|
|
||||||
// engine > not exit
|
|
||||||
}
|
|
||||||
if(count_T > 0)
|
|
||||||
{
|
|
||||||
if(count_t > 0)
|
|
||||||
{
|
|
||||||
throw falco::option_cannot_be_specified_exception("T", "t");
|
|
||||||
}
|
|
||||||
// todo
|
|
||||||
// engine > not exit
|
|
||||||
}
|
|
||||||
if(count_t > 0)
|
|
||||||
{
|
|
||||||
// todo
|
|
||||||
// engine > not exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int m_argc;
|
|
||||||
const char** m_argv;
|
|
||||||
cxxopts::Options m_options;
|
|
||||||
cxxopts::ParseResult m_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace falco
|
|
||||||
|
|
||||||
// 3 tipi di azioni
|
|
||||||
// quelle che una volta date devono farlo uscire e non hanno bisogno di nessuna istanza
|
|
||||||
// quelle che hanno bisogno di inspector e/o engine e poi falco esce
|
|
||||||
// quelle che hanno bisogno di inspector e/o engine e poi falco esegue
|
|
||||||
@@ -25,9 +25,11 @@ limitations under the License.
|
|||||||
#define FALCO_VERSION_PRERELEASE "@FALCO_VERSION_PRERELEASE@"
|
#define FALCO_VERSION_PRERELEASE "@FALCO_VERSION_PRERELEASE@"
|
||||||
#define FALCO_VERSION_BUILD "@FALCO_VERSION_BUILD@"
|
#define FALCO_VERSION_BUILD "@FALCO_VERSION_BUILD@"
|
||||||
|
|
||||||
|
#define FALCO_LUA_DIR "${CMAKE_INSTALL_PREFIX}/${FALCO_SHARE_DIR}/lua/"
|
||||||
#define FALCO_SOURCE_DIR "${PROJECT_SOURCE_DIR}"
|
#define FALCO_SOURCE_DIR "${PROJECT_SOURCE_DIR}"
|
||||||
#define FALCO_SOURCE_CONF_FILE "${PROJECT_SOURCE_DIR}/falco.yaml"
|
#define FALCO_SOURCE_CONF_FILE "${PROJECT_SOURCE_DIR}/falco.yaml"
|
||||||
#define FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml"
|
#define FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml"
|
||||||
|
#define FALCO_SOURCE_LUA_DIR "${PROJECT_SOURCE_DIR}/userspace/falco/lua/"
|
||||||
|
|
||||||
#define PROBE_NAME "@PROBE_NAME@"
|
#define PROBE_NAME "@PROBE_NAME@"
|
||||||
#define DRIVER_VERSION "@PROBE_VERSION@"
|
#define DRIVER_VERSION "@PROBE_VERSION@"
|
||||||
@@ -52,7 +52,7 @@ void falco_configuration::init(list<string> &cmdline_options)
|
|||||||
{
|
{
|
||||||
init_cmdline_options(cmdline_options);
|
init_cmdline_options(cmdline_options);
|
||||||
|
|
||||||
falco::outputs::config stdout_output;
|
falco_outputs::output_config stdout_output;
|
||||||
stdout_output.name = "stdout";
|
stdout_output.name = "stdout";
|
||||||
m_outputs.push_back(stdout_output);
|
m_outputs.push_back(stdout_output);
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
|||||||
m_json_output = m_config->get_scalar<bool>("json_output", false);
|
m_json_output = m_config->get_scalar<bool>("json_output", false);
|
||||||
m_json_include_output_property = m_config->get_scalar<bool>("json_include_output_property", true);
|
m_json_include_output_property = m_config->get_scalar<bool>("json_include_output_property", true);
|
||||||
|
|
||||||
falco::outputs::config file_output;
|
falco_outputs::output_config file_output;
|
||||||
file_output.name = "file";
|
file_output.name = "file";
|
||||||
if(m_config->get_scalar<bool>("file_output", "enabled", false))
|
if(m_config->get_scalar<bool>("file_output", "enabled", false))
|
||||||
{
|
{
|
||||||
@@ -99,21 +99,21 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
|||||||
m_outputs.push_back(file_output);
|
m_outputs.push_back(file_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
falco::outputs::config stdout_output;
|
falco_outputs::output_config stdout_output;
|
||||||
stdout_output.name = "stdout";
|
stdout_output.name = "stdout";
|
||||||
if(m_config->get_scalar<bool>("stdout_output", "enabled", false))
|
if(m_config->get_scalar<bool>("stdout_output", "enabled", false))
|
||||||
{
|
{
|
||||||
m_outputs.push_back(stdout_output);
|
m_outputs.push_back(stdout_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
falco::outputs::config syslog_output;
|
falco_outputs::output_config syslog_output;
|
||||||
syslog_output.name = "syslog";
|
syslog_output.name = "syslog";
|
||||||
if(m_config->get_scalar<bool>("syslog_output", "enabled", false))
|
if(m_config->get_scalar<bool>("syslog_output", "enabled", false))
|
||||||
{
|
{
|
||||||
m_outputs.push_back(syslog_output);
|
m_outputs.push_back(syslog_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
falco::outputs::config program_output;
|
falco_outputs::output_config program_output;
|
||||||
program_output.name = "program";
|
program_output.name = "program";
|
||||||
if(m_config->get_scalar<bool>("program_output", "enabled", false))
|
if(m_config->get_scalar<bool>("program_output", "enabled", false))
|
||||||
{
|
{
|
||||||
@@ -131,7 +131,7 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
|||||||
m_outputs.push_back(program_output);
|
m_outputs.push_back(program_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
falco::outputs::config http_output;
|
falco_outputs::output_config http_output;
|
||||||
http_output.name = "http";
|
http_output.name = "http";
|
||||||
if(m_config->get_scalar<bool>("http_output", "enabled", false))
|
if(m_config->get_scalar<bool>("http_output", "enabled", false))
|
||||||
{
|
{
|
||||||
@@ -159,7 +159,7 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
|||||||
m_grpc_cert_chain = m_config->get_scalar<string>("grpc", "cert_chain", "/etc/falco/certs/server.crt");
|
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");
|
m_grpc_root_certs = m_config->get_scalar<string>("grpc", "root_certs", "/etc/falco/certs/ca.crt");
|
||||||
|
|
||||||
falco::outputs::config grpc_output;
|
falco_outputs::output_config grpc_output;
|
||||||
grpc_output.name = "grpc";
|
grpc_output.name = "grpc";
|
||||||
// gRPC output is enabled only if gRPC server is enabled too
|
// gRPC output is enabled only if gRPC server is enabled too
|
||||||
if(m_config->get_scalar<bool>("grpc_output", "enabled", true) && m_grpc_enabled)
|
if(m_config->get_scalar<bool>("grpc_output", "enabled", true) && m_grpc_enabled)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_path = path;
|
m_path = path;
|
||||||
YAML::Node config;
|
YAML::Node config;
|
||||||
std::vector<falco::outputs::config> outputs;
|
std::vector<falco_outputs::output_config> outputs;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_root = YAML::LoadFile(path);
|
m_root = YAML::LoadFile(path);
|
||||||
@@ -196,7 +196,7 @@ public:
|
|||||||
bool m_json_output;
|
bool m_json_output;
|
||||||
bool m_json_include_output_property;
|
bool m_json_include_output_property;
|
||||||
std::string m_log_level;
|
std::string m_log_level;
|
||||||
std::vector<falco::outputs::config> m_outputs;
|
std::vector<falco_outputs::output_config> m_outputs;
|
||||||
uint32_t m_notifications_rate;
|
uint32_t m_notifications_rate;
|
||||||
uint32_t m_notifications_max_burst;
|
uint32_t m_notifications_max_burst;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -15,7 +15,6 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "event_drops.h"
|
#include "event_drops.h"
|
||||||
#include "falco_common.h"
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
syscall_evt_drop_mgr::syscall_evt_drop_mgr():
|
syscall_evt_drop_mgr::syscall_evt_drop_mgr():
|
||||||
@@ -138,7 +137,7 @@ bool syscall_evt_drop_mgr::perform_actions(uint64_t now, scap_stats &delta, bool
|
|||||||
|
|
||||||
case ACT_ALERT:
|
case ACT_ALERT:
|
||||||
m_outputs->handle_msg(now,
|
m_outputs->handle_msg(now,
|
||||||
falco_common::PRIORITY_CRITICAL,
|
falco_outputs::PRIORITY_CRITICAL,
|
||||||
msg,
|
msg,
|
||||||
rule,
|
rule,
|
||||||
output_fields);
|
output_fields);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -36,18 +36,15 @@ limitations under the License.
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "chisel.h"
|
#include "chisel.h"
|
||||||
#include "fields_info.h"
|
#include "sysdig.h"
|
||||||
|
|
||||||
#include "event_drops.h"
|
#include "event_drops.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "falco_engine.h"
|
#include "falco_engine.h"
|
||||||
#include "config_falco.h"
|
#include "config_falco.h"
|
||||||
#include "statsfilewriter.h"
|
#include "statsfilewriter.h"
|
||||||
#include "cli.h"
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
#include "webserver.h"
|
#include "webserver.h"
|
||||||
#include "grpc_server.h"
|
#include "grpc_server.h"
|
||||||
#endif
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
typedef function<void(sinsp* inspector)> open_t;
|
typedef function<void(sinsp* inspector)> open_t;
|
||||||
@@ -75,102 +72,101 @@ static void restart_falco(int signal)
|
|||||||
g_restart = true;
|
g_restart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// //
|
//
|
||||||
// // Program help
|
// Program help
|
||||||
// //
|
//
|
||||||
// static void usage()
|
static void usage()
|
||||||
// {
|
{
|
||||||
// printf(
|
printf(
|
||||||
// "Falco version: " FALCO_VERSION "\n"
|
"Falco version: " FALCO_VERSION "\n"
|
||||||
// "Usage: falco [options]\n\n"
|
"Usage: falco [options]\n\n"
|
||||||
// "Options:\n"
|
"Options:\n"
|
||||||
|
" -h, --help Print this page\n"
|
||||||
// " -c Configuration file (default " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ")\n"
|
" -c Configuration file (default " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ")\n"
|
||||||
// " -A Monitor all events, including those with EF_DROP_SIMPLE_CONS flag.\n"
|
" -A Monitor all events, including those with EF_DROP_SIMPLE_CONS flag.\n"
|
||||||
// " --alternate-lua-dir <path> Specify an alternate path for loading Falco lua files\n"
|
" -b, --print-base64 Print data buffers in base64.\n"
|
||||||
// " -b, --print-base64 Print data buffers in base64.\n"
|
" This is useful for encoding binary data that needs to be used over media designed to.\n"
|
||||||
// " This is useful for encoding binary data that needs to be used over media designed to.\n"
|
" --cri <path> Path to CRI socket for container metadata.\n"
|
||||||
// " --cri <path> Path to CRI socket for container metadata.\n"
|
" Use the specified socket to fetch data from a CRI-compatible runtime.\n"
|
||||||
// " Use the specified socket to fetch data from a CRI-compatible runtime.\n"
|
" -d, --daemon Run as a daemon.\n"
|
||||||
// " -d, --daemon Run as a daemon.\n"
|
" --disable-cri-async Disable asynchronous CRI metadata fetching.\n"
|
||||||
// " --disable-cri-async Disable asynchronous CRI metadata fetching.\n"
|
" This is useful to let the input event wait for the container metadata fetch\n"
|
||||||
// " This is useful to let the input event wait for the container metadata fetch\n"
|
" to finish before moving forward. Async fetching, in some environments leads\n"
|
||||||
// " to finish before moving forward. Async fetching, in some environments leads\n"
|
" to empty fields for container metadata when the fetch is not fast enough to be\n"
|
||||||
// " to empty fields for container metadata when the fetch is not fast enough to be\n"
|
" completed asynchronously. This can have a performance penalty on your environment\n"
|
||||||
// " completed asynchronously. This can have a performance penalty on your environment\n"
|
" depending on the number of containers and the frequency at which they are created/started/stopped\n"
|
||||||
// " depending on the number of containers and the frequency at which they are created/started/stopped\n"
|
" --disable-source <event_source>\n"
|
||||||
// " --disable-source <event_source>\n"
|
" Disable a specific event source.\n"
|
||||||
// " Disable a specific event source.\n"
|
" Available event sources are: syscall, k8s_audit.\n"
|
||||||
// " Available event sources are: syscall, k8s_audit.\n"
|
" It can be passed multiple times.\n"
|
||||||
// " It can be passed multiple times.\n"
|
" Can not disable both the event sources.\n"
|
||||||
// " Can not disable both the event sources.\n"
|
" -D <substring> Disable any rules with names having the substring <substring>. Can be specified multiple times.\n"
|
||||||
|
" Can not be specified with -t.\n"
|
||||||
// " -e <events_file> Read the events from <events_file> (in .scap format for sinsp events, or jsonl for\n"
|
" -e <events_file> Read the events from <events_file> (in .scap format for sinsp events, or jsonl for\n"
|
||||||
// " k8s audit events) instead of tapping into live.\n"
|
" k8s audit events) instead of tapping into live.\n"
|
||||||
// #ifndef MINIMAL_BUILD
|
" -k <url>, --k8s-api <url>\n"
|
||||||
// " -k <url>, --k8s-api <url>\n"
|
" Enable Kubernetes support by connecting to the API server specified as argument.\n"
|
||||||
// " Enable Kubernetes support by connecting to the API server specified as argument.\n"
|
" E.g. \"http://admin:password@127.0.0.1:8080\".\n"
|
||||||
// " E.g. \"http://admin:password@127.0.0.1:8080\".\n"
|
" The API server can also be specified via the environment variable FALCO_K8S_API.\n"
|
||||||
// " The API server can also be specified via the environment variable FALCO_K8S_API.\n"
|
" -K <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>], --k8s-api-cert <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>]\n"
|
||||||
// " -K <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>], --k8s-api-cert <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>]\n"
|
" Use the provided files names to authenticate user and (optionally) verify the K8S API server identity.\n"
|
||||||
// " Use the provided files names to authenticate user and (optionally) verify the K8S API server identity.\n"
|
" Each entry must specify full (absolute, or relative to the current directory) path to the respective file.\n"
|
||||||
// " Each entry must specify full (absolute, or relative to the current directory) path to the respective file.\n"
|
" Private key password is optional (needed only if key is password protected).\n"
|
||||||
// " Private key password is optional (needed only if key is password protected).\n"
|
" CA certificate is optional. For all files, only PEM file format is supported. \n"
|
||||||
// " CA certificate is optional. For all files, only PEM file format is supported. \n"
|
" Specifying CA certificate only is obsoleted - when single entry is provided \n"
|
||||||
// " Specifying CA certificate only is obsoleted - when single entry is provided \n"
|
" for this option, it will be interpreted as the name of a file containing bearer token.\n"
|
||||||
// " for this option, it will be interpreted as the name of a file containing bearer token.\n"
|
" Note that the format of this command-line option prohibits use of files whose names contain\n"
|
||||||
// " Note that the format of this command-line option prohibits use of files whose names contain\n"
|
" ':' or '#' characters in the file name.\n"
|
||||||
// " ':' or '#' characters in the file name.\n"
|
" -L Show the name and description of all rules and exit.\n"
|
||||||
// #endif
|
" -l <rule> Show the name and description of the rule with name <rule> and exit.\n"
|
||||||
|
" --list [<source>] List all defined fields. If <source> is provided, only list those fields for\n"
|
||||||
|
" the source <source>. Current values for <source> are \"syscall\", \"k8s_audit\"\n"
|
||||||
|
" -m <url[,marathon_url]>, --mesos-api <url[,marathon_url]>\n"
|
||||||
|
" Enable Mesos support by connecting to the API server\n"
|
||||||
// #ifndef MINIMAL_BUILD
|
" specified as argument. E.g. \"http://admin:password@127.0.0.1:5050\".\n"
|
||||||
// " -m <url[,marathon_url]>, --mesos-api <url[,marathon_url]>\n"
|
" Marathon url is optional and defaults to Mesos address, port 8080.\n"
|
||||||
// " Enable Mesos support by connecting to the API server\n"
|
" The API servers can also be specified via the environment variable FALCO_MESOS_API.\n"
|
||||||
// " specified as argument. E.g. \"http://admin:password@127.0.0.1:5050\".\n"
|
" -M <num_seconds> Stop collecting after <num_seconds> reached.\n"
|
||||||
// " Marathon url is optional and defaults to Mesos address, port 8080.\n"
|
" -N When used with --list, only print field names.\n"
|
||||||
// " The API servers can also be specified via the environment variable FALCO_MESOS_API.\n"
|
" -o, --option <key>=<val> Set the value of option <key> to <val>. Overrides values in configuration file.\n"
|
||||||
// #endif
|
" <key> can be a two-part <key>.<subkey>\n"
|
||||||
// " -M <num_seconds> Stop collecting after <num_seconds> reached.\n"
|
" -p <output_format>, --print <output_format>\n"
|
||||||
|
" Add additional information to each falco notification's output.\n"
|
||||||
// " -o, --option <key>=<val> Set the value of option <key> to <val>. Overrides values in configuration file.\n"
|
" With -pc or -pcontainer will use a container-friendly format.\n"
|
||||||
// " <key> can be a two-part <key>.<subkey>\n"
|
" With -pk or -pkubernetes will use a kubernetes-friendly format.\n"
|
||||||
// " -p <output_format>, --print <output_format>\n"
|
" With -pm or -pmesos will use a mesos-friendly format.\n"
|
||||||
// " Add additional information to each falco notification's output.\n"
|
" Additionally, specifying -pc/-pk/-pm will change the interpretation\n"
|
||||||
// " With -pc or -pcontainer will use a container-friendly format.\n"
|
" of %%container.info in rule output fields.\n"
|
||||||
// " With -pk or -pkubernetes will use a kubernetes-friendly format.\n"
|
" -P, --pidfile <pid_file> When run as a daemon, write pid to specified file\n"
|
||||||
// " With -pm or -pmesos will use a mesos-friendly format.\n"
|
" -r <rules_file> Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml).\n"
|
||||||
// " Additionally, specifying -pc/-pk/-pm will change the interpretation\n"
|
" Can be specified multiple times to read from multiple files/directories.\n"
|
||||||
// " of %%container.info in rule output fields.\n"
|
" -s <stats_file> If specified, append statistics related to Falco's reading/processing of events\n"
|
||||||
// " -P, --pidfile <pid_file> When run as a daemon, write pid to specified file\n"
|
" to this file (only useful in live mode).\n"
|
||||||
// " -r <rules_file> Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml).\n"
|
" --stats-interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n"
|
||||||
// " Can be specified multiple times to read from multiple files/directories.\n"
|
" This uses signals, so don't recommend intervals below 200 ms.\n"
|
||||||
// " -s <stats_file> If specified, append statistics related to Falco's reading/processing of events\n"
|
" Defaults to 5000 (5 seconds).\n"
|
||||||
// " to this file (only useful in live mode).\n"
|
" -S <len>, --snaplen <len>\n"
|
||||||
// " --stats-interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n"
|
" Capture the first <len> bytes of each I/O buffer.\n"
|
||||||
// " This uses signals, so don't recommend intervals below 200 ms.\n"
|
" By default, the first 80 bytes are captured. Use this\n"
|
||||||
// " Defaults to 5000 (5 seconds).\n"
|
" option with caution, it can generate huge trace files.\n"
|
||||||
// " -S <len>, --snaplen <len>\n"
|
" --support Print support information including version, rules files used, etc. and exit.\n"
|
||||||
// " Capture the first <len> bytes of each I/O buffer.\n"
|
" -T <tag> Disable any rules with a tag=<tag>. Can be specified multiple times.\n"
|
||||||
// " By default, the first 80 bytes are captured. Use this\n"
|
" Can not be specified with -t.\n"
|
||||||
// " option with caution, it can generate huge trace files.\n"
|
" -t <tag> Only run those rules with a tag=<tag>. Can be specified multiple times.\n"
|
||||||
|
" Can not be specified with -T/-D.\n"
|
||||||
|
" -U,--unbuffered Turn off output buffering to configured outputs.\n"
|
||||||
// " -U,--unbuffered Turn off output buffering to configured outputs.\n"
|
" This causes every single line emitted by falco to be flushed,\n"
|
||||||
// " 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"
|
||||||
// " which generates higher CPU usage but is useful when piping those outputs\n"
|
" into another process or into a script.\n"
|
||||||
// " into another process or into a script.\n"
|
" -u, --userspace Parse events from userspace.\n"
|
||||||
// " -u, --userspace Parse events from userspace.\n"
|
" To be used in conjunction with the ptrace(2) based driver (pdig).\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"
|
||||||
// " -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"
|
||||||
// " Can be specified multiple times to validate multiple files.\n"
|
" -v Verbose output.\n"
|
||||||
// " -v Verbose output.\n"
|
" --version Print version number.\n"
|
||||||
|
"\n"
|
||||||
// "\n"
|
);
|
||||||
// );
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
static void display_fatal_err(const string &msg)
|
static void display_fatal_err(const string &msg)
|
||||||
{
|
{
|
||||||
@@ -189,7 +185,6 @@ static void display_fatal_err(const string &msg)
|
|||||||
// Splitting into key=value or key.subkey=value will be handled by configuration class.
|
// Splitting into key=value or key.subkey=value will be handled by configuration class.
|
||||||
std::list<string> cmdline_options;
|
std::list<string> cmdline_options;
|
||||||
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
// Read a jsonl file containing k8s audit events and pass each to the engine.
|
// Read a jsonl file containing k8s audit events and pass each to the engine.
|
||||||
void read_k8s_audit_trace_file(falco_engine *engine,
|
void read_k8s_audit_trace_file(falco_engine *engine,
|
||||||
falco_outputs *outputs,
|
falco_outputs *outputs,
|
||||||
@@ -218,7 +213,6 @@ void read_k8s_audit_trace_file(falco_engine *engine,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static std::string read_file(std::string filename)
|
static std::string read_file(std::string filename)
|
||||||
{
|
{
|
||||||
@@ -392,7 +386,8 @@ static void print_all_ignored_events(sinsp *inspector)
|
|||||||
|
|
||||||
static void list_source_fields(falco_engine *engine, bool verbose, bool names_only, std::string &source)
|
static void list_source_fields(falco_engine *engine, bool verbose, bool names_only, std::string &source)
|
||||||
{
|
{
|
||||||
if(!source.empty() && !(source == "syscall" || source == "k8s_audit"))
|
if(source.size() > 0 &&
|
||||||
|
!(source == "syscall" || source == "k8s_audit"))
|
||||||
{
|
{
|
||||||
throw std::invalid_argument("Value for --list must be \"syscall\" or \"k8s_audit\"");
|
throw std::invalid_argument("Value for --list must be \"syscall\" or \"k8s_audit\"");
|
||||||
}
|
}
|
||||||
@@ -409,7 +404,7 @@ static void list_source_fields(falco_engine *engine, bool verbose, bool names_on
|
|||||||
//
|
//
|
||||||
// ARGUMENT PARSING AND PROGRAM SETUP
|
// ARGUMENT PARSING AND PROGRAM SETUP
|
||||||
//
|
//
|
||||||
int falco_init()
|
int falco_init(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int result = EXIT_SUCCESS;
|
int result = EXIT_SUCCESS;
|
||||||
sinsp* inspector = NULL;
|
sinsp* inspector = NULL;
|
||||||
@@ -434,11 +429,9 @@ int falco_init()
|
|||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool names_only = false;
|
bool names_only = false;
|
||||||
bool all_events = false;
|
bool all_events = false;
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
string* k8s_api = 0;
|
string* k8s_api = 0;
|
||||||
string* k8s_api_cert = 0;
|
string* k8s_api_cert = 0;
|
||||||
string* mesos_api = 0;
|
string* mesos_api = 0;
|
||||||
#endif
|
|
||||||
string output_format = "";
|
string output_format = "";
|
||||||
uint32_t snaplen = 0;
|
uint32_t snaplen = 0;
|
||||||
bool replace_container_info = false;
|
bool replace_container_info = false;
|
||||||
@@ -468,15 +461,12 @@ int falco_init()
|
|||||||
double duration;
|
double duration;
|
||||||
scap_stats cstats;
|
scap_stats cstats;
|
||||||
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
falco_webserver webserver;
|
falco_webserver webserver;
|
||||||
falco::grpc::server grpc_server;
|
falco::grpc::server grpc_server;
|
||||||
std::thread grpc_server_thread;
|
std::thread grpc_server_thread;
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct option long_options[] =
|
static struct option long_options[] =
|
||||||
{
|
{
|
||||||
{"alternate-lua-dir", required_argument, 0},
|
|
||||||
{"cri", required_argument, 0},
|
{"cri", required_argument, 0},
|
||||||
{"daemon", no_argument, 0, 'd'},
|
{"daemon", no_argument, 0, 'd'},
|
||||||
{"disable-cri-async", no_argument, 0, 0},
|
{"disable-cri-async", no_argument, 0, 0},
|
||||||
@@ -499,208 +489,193 @@ int falco_init()
|
|||||||
{"validate", required_argument, 0, 'V'},
|
{"validate", required_argument, 0, 'V'},
|
||||||
{"version", no_argument, 0, 0},
|
{"version", no_argument, 0, 0},
|
||||||
{"writefile", required_argument, 0, 'w'},
|
{"writefile", required_argument, 0, 'w'},
|
||||||
{0, 0, 0, 0}};
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
set<string> disabled_rule_substrings;
|
set<string> disabled_rule_substrings;
|
||||||
string substring;
|
string substring;
|
||||||
string all_rules = "";
|
string all_rules = "";
|
||||||
string alternate_lua_dir = FALCO_ENGINE_SOURCE_LUA_DIR;
|
|
||||||
set<string> disabled_rule_tags;
|
set<string> disabled_rule_tags;
|
||||||
set<string> enabled_rule_tags;
|
set<string> enabled_rule_tags;
|
||||||
|
|
||||||
// //
|
//
|
||||||
// // Parse the args
|
// Parse the args
|
||||||
// //
|
//
|
||||||
// while((op = getopt_long(argc, argv,
|
while((op = getopt_long(argc, argv,
|
||||||
// "hc:AbdD:e:F:ik:K:Ll:m:M:No:P:p:r:S:s:T:t:UuvV: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)
|
long_options, &long_index)) != -1)
|
||||||
// {
|
{
|
||||||
// switch(op)
|
switch(op)
|
||||||
// {
|
{
|
||||||
// case 'h':
|
case 'h':
|
||||||
// usage();
|
usage();
|
||||||
// goto exit;
|
goto exit;
|
||||||
// case 'c':
|
case 'c':
|
||||||
// conf_filename = optarg;
|
conf_filename = optarg;
|
||||||
// break;
|
break;
|
||||||
// case 'A':
|
case 'A':
|
||||||
// all_events = true;
|
all_events = true;
|
||||||
// break;
|
break;
|
||||||
// case 'b':
|
case 'b':
|
||||||
// event_buffer_format = sinsp_evt::PF_BASE64;
|
event_buffer_format = sinsp_evt::PF_BASE64;
|
||||||
// break;
|
break;
|
||||||
// case 'd':
|
case 'd':
|
||||||
// daemon = true;
|
daemon = true;
|
||||||
// break;
|
break;
|
||||||
// case 'D':
|
case 'D':
|
||||||
// substring = optarg;
|
substring = optarg;
|
||||||
// disabled_rule_substrings.insert(substring);
|
disabled_rule_substrings.insert(substring);
|
||||||
// break;
|
break;
|
||||||
// case 'e':
|
case 'e':
|
||||||
// trace_filename = optarg;
|
trace_filename = optarg;
|
||||||
// #ifndef MINIMAL_BUILD
|
k8s_api = new string();
|
||||||
// k8s_api = new string();
|
mesos_api = new string();
|
||||||
// mesos_api = new string();
|
break;
|
||||||
// #endif
|
case 'F':
|
||||||
// break;
|
list_flds = optarg;
|
||||||
// case 'F':
|
break;
|
||||||
// list_flds = optarg;
|
case 'i':
|
||||||
// break;
|
print_ignored_events = true;
|
||||||
// case 'i':
|
break;
|
||||||
// print_ignored_events = true;
|
case 'k':
|
||||||
// break;
|
k8s_api = new string(optarg);
|
||||||
// #ifndef MINIMAL_BUILD
|
break;
|
||||||
// case 'k':
|
case 'K':
|
||||||
// k8s_api = new string(optarg);
|
k8s_api_cert = new string(optarg);
|
||||||
// break;
|
break;
|
||||||
// case 'K':
|
case 'L':
|
||||||
// k8s_api_cert = new string(optarg);
|
describe_all_rules = true;
|
||||||
// break;
|
break;
|
||||||
// #endif
|
case 'l':
|
||||||
// case 'L':
|
describe_rule = optarg;
|
||||||
// describe_all_rules = true;
|
break;
|
||||||
// break;
|
case 'm':
|
||||||
// case 'l':
|
mesos_api = new string(optarg);
|
||||||
// describe_rule = optarg;
|
break;
|
||||||
// break;
|
case 'M':
|
||||||
// #ifndef MINIMAL_BUILD
|
duration_to_tot = atoi(optarg);
|
||||||
// case 'm':
|
if(duration_to_tot <= 0)
|
||||||
// mesos_api = new string(optarg);
|
{
|
||||||
// break;
|
throw sinsp_exception(string("invalid duration") + optarg);
|
||||||
// #endif
|
}
|
||||||
// case 'M':
|
break;
|
||||||
// duration_to_tot = atoi(optarg);
|
case 'N':
|
||||||
// if(duration_to_tot <= 0)
|
names_only = true;
|
||||||
// {
|
break;
|
||||||
// throw sinsp_exception(string("invalid duration") + optarg);
|
case 'o':
|
||||||
// }
|
cmdline_options.push_back(optarg);
|
||||||
// break;
|
break;
|
||||||
// case 'N':
|
case 'P':
|
||||||
// names_only = true;
|
pidfilename = optarg;
|
||||||
// break;
|
break;
|
||||||
// case 'o':
|
case 'p':
|
||||||
// cmdline_options.push_back(optarg);
|
if(string(optarg) == "c" || string(optarg) == "container")
|
||||||
// break;
|
{
|
||||||
// case 'P':
|
output_format = "container=%container.name (id=%container.id)";
|
||||||
// pidfilename = optarg;
|
replace_container_info = true;
|
||||||
// break;
|
}
|
||||||
// case 'p':
|
else if(string(optarg) == "k" || string(optarg) == "kubernetes")
|
||||||
// if(string(optarg) == "c" || string(optarg) == "container")
|
{
|
||||||
// {
|
output_format = "k8s.ns=%k8s.ns.name k8s.pod=%k8s.pod.name container=%container.id";
|
||||||
// output_format = "container=%container.name (id=%container.id)";
|
replace_container_info = true;
|
||||||
// replace_container_info = true;
|
}
|
||||||
// }
|
else if(string(optarg) == "m" || string(optarg) == "mesos")
|
||||||
// else if(string(optarg) == "k" || string(optarg) == "kubernetes")
|
{
|
||||||
// {
|
output_format = "task=%mesos.task.name container=%container.id";
|
||||||
// output_format = "k8s.ns=%k8s.ns.name k8s.pod=%k8s.pod.name container=%container.id";
|
replace_container_info = true;
|
||||||
// replace_container_info = true;
|
}
|
||||||
// }
|
else
|
||||||
// else if(string(optarg) == "m" || string(optarg) == "mesos")
|
{
|
||||||
// {
|
output_format = optarg;
|
||||||
// output_format = "task=%mesos.task.name container=%container.id";
|
replace_container_info = false;
|
||||||
// replace_container_info = true;
|
}
|
||||||
// }
|
break;
|
||||||
// else
|
case 'r':
|
||||||
// {
|
falco_configuration::read_rules_file_directory(string(optarg), rules_filenames);
|
||||||
// output_format = optarg;
|
break;
|
||||||
// replace_container_info = false;
|
case 'S':
|
||||||
// }
|
snaplen = atoi(optarg);
|
||||||
// break;
|
break;
|
||||||
// case 'r':
|
case 's':
|
||||||
// falco_configuration::read_rules_file_directory(string(optarg), rules_filenames);
|
stats_filename = optarg;
|
||||||
// break;
|
break;
|
||||||
// case 'S':
|
case 'T':
|
||||||
// snaplen = atoi(optarg);
|
disabled_rule_tags.insert(optarg);
|
||||||
// break;
|
break;
|
||||||
// case 's':
|
case 't':
|
||||||
// stats_filename = optarg;
|
enabled_rule_tags.insert(optarg);
|
||||||
// break;
|
break;
|
||||||
// case 'T':
|
case 'U':
|
||||||
// disabled_rule_tags.insert(optarg);
|
buffered_outputs = false;
|
||||||
// break;
|
buffered_cmdline = true;
|
||||||
// case 't':
|
break;
|
||||||
// enabled_rule_tags.insert(optarg);
|
case 'u':
|
||||||
// break;
|
userspace = true;
|
||||||
// case 'U':
|
break;
|
||||||
// buffered_outputs = false;
|
case 'v':
|
||||||
// buffered_cmdline = true;
|
verbose = true;
|
||||||
// break;
|
break;
|
||||||
// case 'u':
|
case 'V':
|
||||||
// userspace = true;
|
validate_rules_filenames.push_back(optarg);
|
||||||
// break;
|
break;
|
||||||
// case 'v':
|
case 'w':
|
||||||
// verbose = true;
|
outfile = optarg;
|
||||||
// break;
|
break;
|
||||||
// case 'V':
|
case '?':
|
||||||
// validate_rules_filenames.push_back(optarg);
|
result = EXIT_FAILURE;
|
||||||
// break;
|
goto exit;
|
||||||
// case 'w':
|
|
||||||
// outfile = optarg;
|
|
||||||
// break;
|
|
||||||
// case '?':
|
|
||||||
// result = EXIT_FAILURE;
|
|
||||||
// goto exit;
|
|
||||||
|
|
||||||
// case 0:
|
case 0:
|
||||||
// if(string(long_options[long_index].name) == "version")
|
if(string(long_options[long_index].name) == "version")
|
||||||
// {
|
{
|
||||||
// printf("Falco version: %s\n", FALCO_VERSION);
|
printf("Falco version: %s\n", FALCO_VERSION);
|
||||||
// printf("Driver version: %s\n", DRIVER_VERSION);
|
printf("Driver version: %s\n", DRIVER_VERSION);
|
||||||
// return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
// }
|
}
|
||||||
// else if (string(long_options[long_index].name) == "cri")
|
else if (string(long_options[long_index].name) == "cri")
|
||||||
// {
|
{
|
||||||
// if(optarg != NULL)
|
if(optarg != NULL)
|
||||||
// {
|
{
|
||||||
// cri_socket_path = optarg;
|
cri_socket_path = optarg;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// else if (string(long_options[long_index].name) == "disable-cri-async")
|
else if (string(long_options[long_index].name) == "disable-cri-async")
|
||||||
// {
|
{
|
||||||
// cri_async = false;
|
cri_async = false;
|
||||||
// }
|
}
|
||||||
// else if (string(long_options[long_index].name) == "list")
|
else if (string(long_options[long_index].name) == "list")
|
||||||
// {
|
{
|
||||||
// list_flds = true;
|
list_flds = true;
|
||||||
// if(optarg != NULL)
|
if(optarg != NULL)
|
||||||
// {
|
{
|
||||||
// list_flds_source = optarg;
|
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);
|
stats_interval = atoi(optarg);
|
||||||
// }
|
}
|
||||||
// else if (string(long_options[long_index].name) == "support")
|
else if (string(long_options[long_index].name) == "support")
|
||||||
// {
|
{
|
||||||
// print_support = true;
|
print_support = true;
|
||||||
// }
|
}
|
||||||
// else if (string(long_options[long_index].name) == "disable-source")
|
else if (string(long_options[long_index].name) == "disable-source")
|
||||||
// {
|
{
|
||||||
// if(optarg != NULL)
|
if(optarg != NULL)
|
||||||
// {
|
{
|
||||||
// disable_sources.insert(optarg);
|
disable_sources.insert(optarg);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// else if (string(long_options[long_index].name)== "alternate-lua-dir")
|
break;
|
||||||
// {
|
|
||||||
// if(optarg != NULL)
|
|
||||||
// {
|
|
||||||
// alternate_lua_dir = optarg;
|
|
||||||
// if (alternate_lua_dir.back() != '/') {
|
|
||||||
// alternate_lua_dir += '/';
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// default:
|
default:
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// }
|
|
||||||
inspector = new sinsp();
|
inspector = new sinsp();
|
||||||
inspector->set_buffer_format(event_buffer_format);
|
inspector->set_buffer_format(event_buffer_format);
|
||||||
|
|
||||||
@@ -728,7 +703,7 @@ int falco_init()
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine = new falco_engine(true, alternate_lua_dir);
|
engine = new falco_engine();
|
||||||
engine->set_inspector(inspector);
|
engine->set_inspector(inspector);
|
||||||
engine->set_extra(output_format, replace_container_info);
|
engine->set_extra(output_format, replace_container_info);
|
||||||
|
|
||||||
@@ -757,7 +732,8 @@ int falco_init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outputs = new falco_outputs();
|
outputs = new falco_outputs(engine);
|
||||||
|
outputs->set_inspector(inspector);
|
||||||
|
|
||||||
// Some combinations of arguments are not allowed.
|
// Some combinations of arguments are not allowed.
|
||||||
if (daemon && pidfilename == "") {
|
if (daemon && pidfilename == "") {
|
||||||
@@ -916,14 +892,14 @@ int falco_init()
|
|||||||
throw std::runtime_error(string("Could not uname() to find system info: %s\n") + strerror(errno));
|
throw std::runtime_error(string("Could not uname() to find system info: %s\n") + strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
// for(char **arg = argv; *arg; arg++)
|
for(char **arg = argv; *arg; arg++)
|
||||||
// {
|
{
|
||||||
// if(cmdline.size() > 0)
|
if(cmdline.size() > 0)
|
||||||
// {
|
{
|
||||||
// cmdline += " ";
|
cmdline += " ";
|
||||||
// }
|
}
|
||||||
// cmdline += *arg;
|
cmdline += *arg;
|
||||||
// }
|
}
|
||||||
|
|
||||||
support["version"] = FALCO_VERSION;
|
support["version"] = FALCO_VERSION;
|
||||||
support["system_info"]["sysname"] = sysinfo.sysname;
|
support["system_info"]["sysname"] = sysinfo.sysname;
|
||||||
@@ -965,6 +941,7 @@ int falco_init()
|
|||||||
hostname = c_hostname;
|
hostname = c_hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
outputs->init(config.m_json_output,
|
outputs->init(config.m_json_output,
|
||||||
config.m_json_include_output_property,
|
config.m_json_include_output_property,
|
||||||
config.m_notifications_rate, config.m_notifications_max_burst,
|
config.m_notifications_rate, config.m_notifications_max_burst,
|
||||||
@@ -1097,12 +1074,6 @@ int falco_init()
|
|||||||
|
|
||||||
if(!trace_is_scap)
|
if(!trace_is_scap)
|
||||||
{
|
{
|
||||||
#ifdef MINIMAL_BUILD
|
|
||||||
// Note that the webserver is not available when MINIMAL_BUILD is defined.
|
|
||||||
fprintf(stderr, "Cannot use k8s audit events trace file with a minimal Falco build");
|
|
||||||
result = EXIT_FAILURE;
|
|
||||||
goto exit;
|
|
||||||
#else
|
|
||||||
try {
|
try {
|
||||||
string line;
|
string line;
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
@@ -1127,7 +1098,6 @@ int falco_init()
|
|||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1173,16 +1143,13 @@ int falco_init()
|
|||||||
// Try to insert the Falco kernel module
|
// Try to insert the Falco kernel module
|
||||||
if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null"))
|
if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null"))
|
||||||
{
|
{
|
||||||
falco_logger::log(LOG_ERR, "Unable to load the driver.\n");
|
falco_logger::log(LOG_ERR, "Unable to load the driver. Exiting.\n");
|
||||||
}
|
}
|
||||||
open_f(inspector);
|
open_f(inspector);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
rethrow_exception(current_exception());
|
rethrow_exception(current_exception());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// This must be done after the open
|
// This must be done after the open
|
||||||
if(!all_events)
|
if(!all_events)
|
||||||
@@ -1198,7 +1165,6 @@ int falco_init()
|
|||||||
|
|
||||||
duration = ((double)clock()) / CLOCKS_PER_SEC;
|
duration = ((double)clock()) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
//
|
//
|
||||||
// Run k8s, if required
|
// Run k8s, if required
|
||||||
//
|
//
|
||||||
@@ -1282,15 +1248,12 @@ int falco_init()
|
|||||||
grpc_server.run();
|
grpc_server.run();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!trace_filename.empty() && !trace_is_scap)
|
if(!trace_filename.empty() && !trace_is_scap)
|
||||||
{
|
{
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
read_k8s_audit_trace_file(engine,
|
read_k8s_audit_trace_file(engine,
|
||||||
outputs,
|
outputs,
|
||||||
trace_filename);
|
trace_filename);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1336,14 +1299,12 @@ int falco_init()
|
|||||||
inspector->close();
|
inspector->close();
|
||||||
engine->print_stats();
|
engine->print_stats();
|
||||||
sdropmgr.print_stats();
|
sdropmgr.print_stats();
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
webserver.stop();
|
webserver.stop();
|
||||||
if(grpc_server_thread.joinable())
|
if(grpc_server_thread.joinable())
|
||||||
{
|
{
|
||||||
grpc_server.shutdown();
|
grpc_server.shutdown();
|
||||||
grpc_server_thread.join();
|
grpc_server_thread.join();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
catch(exception &e)
|
catch(exception &e)
|
||||||
{
|
{
|
||||||
@@ -1351,14 +1312,12 @@ int falco_init()
|
|||||||
|
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
webserver.stop();
|
webserver.stop();
|
||||||
if(grpc_server_thread.joinable())
|
if(grpc_server_thread.joinable())
|
||||||
{
|
{
|
||||||
grpc_server.shutdown();
|
grpc_server.shutdown();
|
||||||
grpc_server_thread.join();
|
grpc_server_thread.join();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -1373,23 +1332,13 @@ exit:
|
|||||||
//
|
//
|
||||||
// MAIN
|
// MAIN
|
||||||
//
|
//
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
auto cli = new falco::cli(argc, argv);
|
|
||||||
cli->run();
|
|
||||||
}
|
|
||||||
catch(const cxxopts::OptionException &e)
|
|
||||||
{
|
|
||||||
display_fatal_err("Error parsing options: " + string(e.what()) + "\n");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
// g_restart will cause the falco loop to exit, but we
|
// g_restart will cause the falco loop to exit, but we
|
||||||
// should reload everything and start over.
|
// should reload everything and start over.
|
||||||
while((rc = falco_init()) == EXIT_SUCCESS && g_restart)
|
while((rc = falco_init(argc, argv)) == EXIT_SUCCESS && g_restart)
|
||||||
{
|
{
|
||||||
g_restart = false;
|
g_restart = false;
|
||||||
optind = 1;
|
optind = 1;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,9 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
#include <google/protobuf/util/time_util.h>
|
#include <google/protobuf/util/time_util.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "falco_outputs.h"
|
#include "falco_outputs.h"
|
||||||
|
|
||||||
@@ -24,21 +22,20 @@ limitations under the License.
|
|||||||
|
|
||||||
#include "formats.h"
|
#include "formats.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "falco_outputs_queue.h"
|
||||||
#include "outputs_file.h"
|
|
||||||
#include "outputs_program.h"
|
|
||||||
#include "outputs_stdout.h"
|
|
||||||
#include "outputs_syslog.h"
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
#include "outputs_http.h"
|
|
||||||
#include "outputs_grpc.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
falco_outputs::falco_outputs():
|
const static struct luaL_reg ll_falco_outputs [] =
|
||||||
|
{
|
||||||
|
{"handle_http", &falco_outputs::handle_http},
|
||||||
|
{"handle_grpc", &falco_outputs::handle_grpc},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
falco_outputs::falco_outputs(falco_engine *engine):
|
||||||
|
m_falco_engine(engine),
|
||||||
m_initialized(false),
|
m_initialized(false),
|
||||||
m_buffered(true),
|
m_buffered(true),
|
||||||
m_json_output(false),
|
m_json_output(false),
|
||||||
@@ -49,11 +46,25 @@ falco_outputs::falco_outputs():
|
|||||||
|
|
||||||
falco_outputs::~falco_outputs()
|
falco_outputs::~falco_outputs()
|
||||||
{
|
{
|
||||||
|
// Note: The assert()s in this destructor were previously places where
|
||||||
|
// exceptions were thrown. C++11 doesn't allow destructors to
|
||||||
|
// emit exceptions; if they're thrown, they'll trigger a call
|
||||||
|
// to 'terminate()'. To maintain similar behavior, the exceptions
|
||||||
|
// were replace with calls to 'assert()'
|
||||||
if(m_initialized)
|
if(m_initialized)
|
||||||
{
|
{
|
||||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
lua_getglobal(m_ls, m_lua_output_cleanup.c_str());
|
||||||
|
if(!lua_isfunction(m_ls, -1))
|
||||||
{
|
{
|
||||||
(*it)->cleanup();
|
falco_logger::log(LOG_ERR, std::string("No function ") + m_lua_output_cleanup + " found. ");
|
||||||
|
assert(nullptr == "Missing lua cleanup function in ~falco_outputs");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lua_pcall(m_ls, 0, 0, 0) != 0)
|
||||||
|
{
|
||||||
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
|
falco_logger::log(LOG_ERR, std::string("lua_pcall failed, err: ") + lerr);
|
||||||
|
assert(nullptr == "lua_pcall failed in ~falco_outputs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,13 +74,24 @@ void falco_outputs::init(bool json_output,
|
|||||||
uint32_t rate, uint32_t max_burst, bool buffered,
|
uint32_t rate, uint32_t max_burst, bool buffered,
|
||||||
bool time_format_iso_8601, string hostname)
|
bool time_format_iso_8601, string hostname)
|
||||||
{
|
{
|
||||||
|
// The engine must have been given an inspector by now.
|
||||||
|
if(!m_inspector)
|
||||||
|
{
|
||||||
|
throw falco_exception("No inspector provided");
|
||||||
|
}
|
||||||
|
|
||||||
m_json_output = json_output;
|
m_json_output = json_output;
|
||||||
|
|
||||||
// Note that falco_formats is already initialized by the engine,
|
falco_common::init(m_lua_main_filename.c_str(), FALCO_SOURCE_LUA_DIR);
|
||||||
// and the following json options are not used within the engine.
|
|
||||||
// So we can safely update them.
|
// Note that falco_formats is added to both the lua state used
|
||||||
falco_formats::s_json_output = json_output;
|
// by the falco engine as well as the separate lua state used
|
||||||
falco_formats::s_json_include_output_property = json_include_output_property;
|
// by falco outputs.
|
||||||
|
falco_formats::init(m_inspector, m_falco_engine, m_ls, json_output, json_include_output_property);
|
||||||
|
|
||||||
|
falco_logger::init(m_ls);
|
||||||
|
|
||||||
|
luaL_openlib(m_ls, "c_outputs", ll_falco_outputs, 0);
|
||||||
|
|
||||||
m_notifications_tb.init(rate, max_burst);
|
m_notifications_tb.init(rate, max_burst);
|
||||||
|
|
||||||
@@ -80,47 +102,40 @@ void falco_outputs::init(bool json_output,
|
|||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_outputs::add_output(falco::outputs::config oc)
|
void falco_outputs::add_output(output_config oc)
|
||||||
{
|
{
|
||||||
|
uint8_t nargs = 3;
|
||||||
|
lua_getglobal(m_ls, m_lua_add_output.c_str());
|
||||||
|
|
||||||
falco::outputs::abstract_output *oo;
|
if(!lua_isfunction(m_ls, -1))
|
||||||
|
{
|
||||||
|
throw falco_exception("No function " + m_lua_add_output + " found. ");
|
||||||
|
}
|
||||||
|
lua_pushstring(m_ls, oc.name.c_str());
|
||||||
|
lua_pushnumber(m_ls, (m_buffered ? 1 : 0));
|
||||||
|
lua_pushnumber(m_ls, (m_time_format_iso_8601 ? 1 : 0));
|
||||||
|
|
||||||
if(oc.name == "file")
|
// If we have options, build up a lua table containing them
|
||||||
|
if(oc.options.size())
|
||||||
{
|
{
|
||||||
oo = new falco::outputs::output_file();
|
nargs = 4;
|
||||||
|
lua_createtable(m_ls, 0, oc.options.size());
|
||||||
|
|
||||||
|
for(auto it = oc.options.cbegin(); it != oc.options.cend(); ++it)
|
||||||
|
{
|
||||||
|
lua_pushstring(m_ls, (*it).second.c_str());
|
||||||
|
lua_setfield(m_ls, -2, (*it).first.c_str());
|
||||||
}
|
}
|
||||||
else if(oc.name == "program")
|
|
||||||
{
|
|
||||||
oo = new falco::outputs::output_program();
|
|
||||||
}
|
|
||||||
else if(oc.name == "stdout")
|
|
||||||
{
|
|
||||||
oo = new falco::outputs::output_stdout();
|
|
||||||
}
|
|
||||||
else if(oc.name == "syslog")
|
|
||||||
{
|
|
||||||
oo = new falco::outputs::output_syslog();
|
|
||||||
}
|
|
||||||
#ifndef MINIMAL_BUILD
|
|
||||||
else if(oc.name == "http")
|
|
||||||
{
|
|
||||||
oo = new falco::outputs::output_http();
|
|
||||||
}
|
|
||||||
else if(oc.name == "grpc")
|
|
||||||
{
|
|
||||||
oo = new falco::outputs::output_grpc();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw falco_exception("Output not supported: " + oc.name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oo->init(oc, m_buffered, m_hostname);
|
if(lua_pcall(m_ls, nargs, 0, 0) != 0)
|
||||||
m_outputs.push_back(oo);
|
{
|
||||||
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
|
throw falco_exception(string(lerr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
|
void falco_outputs::handle_event(gen_event *ev, string &rule, string &source,
|
||||||
falco_common::priority_type priority, string &format)
|
falco_common::priority_type priority, string &format)
|
||||||
{
|
{
|
||||||
if(!m_notifications_tb.claim())
|
if(!m_notifications_tb.claim())
|
||||||
@@ -129,46 +144,29 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string sformat;
|
std::lock_guard<std::mutex> guard(m_ls_semaphore);
|
||||||
if(source == "syscall")
|
lua_getglobal(m_ls, m_lua_output_event.c_str());
|
||||||
{
|
|
||||||
if(m_time_format_iso_8601)
|
|
||||||
{
|
|
||||||
sformat = "*%evt.time.iso8601: " + falco_common::priority_names[priority];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sformat = "*%evt.time: " + falco_common::priority_names[priority];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(m_time_format_iso_8601)
|
|
||||||
{
|
|
||||||
sformat = "*%jevt.time.iso8601: " + falco_common::priority_names[priority];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sformat = "*%jevt.time: " + falco_common::priority_names[priority];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if format starts with a *, remove it, as we added our own prefix
|
if(lua_isfunction(m_ls, -1))
|
||||||
if(format[0] == '*')
|
|
||||||
{
|
{
|
||||||
sformat += " " + format.substr(1, format.length() - 1);
|
lua_pushlightuserdata(m_ls, ev);
|
||||||
|
lua_pushstring(m_ls, rule.c_str());
|
||||||
|
lua_pushstring(m_ls, source.c_str());
|
||||||
|
lua_pushstring(m_ls, falco_common::priority_names[priority].c_str());
|
||||||
|
lua_pushnumber(m_ls, priority);
|
||||||
|
lua_pushstring(m_ls, format.c_str());
|
||||||
|
lua_pushstring(m_ls, m_hostname.c_str());
|
||||||
|
|
||||||
|
if(lua_pcall(m_ls, 7, 0, 0) != 0)
|
||||||
|
{
|
||||||
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
|
string err = "Error invoking function output: " + string(lerr);
|
||||||
|
throw falco_exception(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sformat += " " + format;
|
throw falco_exception("No function " + m_lua_output_event + " found in lua compiler module");
|
||||||
}
|
|
||||||
|
|
||||||
string msg;
|
|
||||||
msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
|
|
||||||
|
|
||||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
|
||||||
{
|
|
||||||
(*it)->output_event(evt, rule, source, priority, sformat, msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +194,7 @@ void falco_outputs::handle_msg(uint64_t now,
|
|||||||
iso8601evttime += time_ns;
|
iso8601evttime += time_ns;
|
||||||
|
|
||||||
jmsg["output"] = msg;
|
jmsg["output"] = msg;
|
||||||
jmsg["priority"] = falco_common::priority_names[priority];
|
jmsg["priority"] = "Critical";
|
||||||
jmsg["rule"] = rule;
|
jmsg["rule"] = rule;
|
||||||
jmsg["time"] = iso8601evttime;
|
jmsg["time"] = iso8601evttime;
|
||||||
jmsg["output_fields"] = output_fields;
|
jmsg["output_fields"] = output_fields;
|
||||||
@@ -209,7 +207,7 @@ void falco_outputs::handle_msg(uint64_t now,
|
|||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
sinsp_utils::ts_to_string(now, ×tr, false, true);
|
sinsp_utils::ts_to_string(now, ×tr, false, true);
|
||||||
full_msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
|
full_msg = timestr + ": " + falco_common::priority_names[LOG_CRIT] + " " + msg + " (";
|
||||||
for(auto &pair : output_fields)
|
for(auto &pair : output_fields)
|
||||||
{
|
{
|
||||||
if(first)
|
if(first)
|
||||||
@@ -225,16 +223,149 @@ void falco_outputs::handle_msg(uint64_t now,
|
|||||||
full_msg += ")";
|
full_msg += ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
std::lock_guard<std::mutex> guard(m_ls_semaphore);
|
||||||
|
lua_getglobal(m_ls, m_lua_output_msg.c_str());
|
||||||
|
if(lua_isfunction(m_ls, -1))
|
||||||
{
|
{
|
||||||
(*it)->output_msg(priority, full_msg);
|
lua_pushstring(m_ls, full_msg.c_str());
|
||||||
|
lua_pushstring(m_ls, falco_common::priority_names[priority].c_str());
|
||||||
|
lua_pushnumber(m_ls, priority);
|
||||||
|
|
||||||
|
if(lua_pcall(m_ls, 3, 0, 0) != 0)
|
||||||
|
{
|
||||||
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
|
string err = "Error invoking function output: " + string(lerr);
|
||||||
|
throw falco_exception(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw falco_exception("No function " + m_lua_output_msg + " found in lua compiler module");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_outputs::reopen_outputs()
|
void falco_outputs::reopen_outputs()
|
||||||
{
|
{
|
||||||
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
|
lua_getglobal(m_ls, m_lua_output_reopen.c_str());
|
||||||
|
if(!lua_isfunction(m_ls, -1))
|
||||||
{
|
{
|
||||||
(*it)->reopen();
|
throw falco_exception("No function " + m_lua_output_reopen + " found. ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lua_pcall(m_ls, 0, 0, 0) != 0)
|
||||||
|
{
|
||||||
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
|
throw falco_exception(string(lerr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int falco_outputs::handle_http(lua_State *ls)
|
||||||
|
{
|
||||||
|
CURL *curl = NULL;
|
||||||
|
CURLcode res = CURLE_FAILED_INIT;
|
||||||
|
struct curl_slist *slist1;
|
||||||
|
slist1 = NULL;
|
||||||
|
|
||||||
|
if(!lua_isstring(ls, -1) ||
|
||||||
|
!lua_isstring(ls, -2))
|
||||||
|
{
|
||||||
|
lua_pushstring(ls, "Invalid arguments passed to handle_http()");
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
string url = (char *)lua_tostring(ls, 1);
|
||||||
|
string msg = (char *)lua_tostring(ls, 2);
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if(curl)
|
||||||
|
{
|
||||||
|
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
if(res != CURLE_OK)
|
||||||
|
{
|
||||||
|
falco_logger::log(LOG_ERR, "libcurl error: " + string(curl_easy_strerror(res)));
|
||||||
|
}
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
curl = NULL;
|
||||||
|
curl_slist_free_all(slist1);
|
||||||
|
slist1 = NULL;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int falco_outputs::handle_grpc(lua_State *ls)
|
||||||
|
{
|
||||||
|
// check parameters
|
||||||
|
if(!lua_islightuserdata(ls, -8) ||
|
||||||
|
!lua_isstring(ls, -7) ||
|
||||||
|
!lua_isstring(ls, -6) ||
|
||||||
|
!lua_isstring(ls, -5) ||
|
||||||
|
!lua_isstring(ls, -4) ||
|
||||||
|
!lua_istable(ls, -3) ||
|
||||||
|
!lua_isstring(ls, -2) ||
|
||||||
|
!lua_istable(ls, -1))
|
||||||
|
{
|
||||||
|
lua_pushstring(ls, "Invalid arguments passed to handle_grpc()");
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
falco::outputs::response grpc_res;
|
||||||
|
|
||||||
|
// time
|
||||||
|
gen_event *evt = (gen_event *)lua_topointer(ls, 1);
|
||||||
|
auto timestamp = grpc_res.mutable_time();
|
||||||
|
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(evt->get_ts());
|
||||||
|
|
||||||
|
// rule
|
||||||
|
auto rule = grpc_res.mutable_rule();
|
||||||
|
*rule = (char *)lua_tostring(ls, 2);
|
||||||
|
|
||||||
|
// source
|
||||||
|
falco::schema::source s = falco::schema::source::SYSCALL;
|
||||||
|
string sstr = (char *)lua_tostring(ls, 3);
|
||||||
|
if(!falco::schema::source_Parse(sstr, &s))
|
||||||
|
{
|
||||||
|
lua_pushstring(ls, "Unknown source passed to to handle_grpc()");
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
grpc_res.set_source(s);
|
||||||
|
|
||||||
|
// priority
|
||||||
|
falco::schema::priority p = falco::schema::priority::EMERGENCY;
|
||||||
|
string pstr = (char *)lua_tostring(ls, 4);
|
||||||
|
if(!falco::schema::priority_Parse(pstr, &p))
|
||||||
|
{
|
||||||
|
lua_pushstring(ls, "Unknown priority passed to to handle_grpc()");
|
||||||
|
lua_error(ls);
|
||||||
|
}
|
||||||
|
grpc_res.set_priority(p);
|
||||||
|
|
||||||
|
// output
|
||||||
|
auto output = grpc_res.mutable_output();
|
||||||
|
*output = (char *)lua_tostring(ls, 5);
|
||||||
|
|
||||||
|
// output fields
|
||||||
|
auto &fields = *grpc_res.mutable_output_fields();
|
||||||
|
|
||||||
|
lua_pushnil(ls); // so that lua_next removes it from stack and puts (k, v) on it
|
||||||
|
while(lua_next(ls, 6) != 0)
|
||||||
|
{
|
||||||
|
fields[lua_tostring(ls, -2)] = lua_tostring(ls, -1);
|
||||||
|
lua_pop(ls, 1); // remove value, keep key for lua_next
|
||||||
|
}
|
||||||
|
lua_pop(ls, 1); // pop table
|
||||||
|
|
||||||
|
// hostname
|
||||||
|
auto host = grpc_res.mutable_hostname();
|
||||||
|
*host = (char *)lua_tostring(ls, 7);
|
||||||
|
|
||||||
|
falco::outputs::queue::get().push(grpc_res);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -19,36 +19,50 @@ limitations under the License.
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
}
|
||||||
|
|
||||||
#include "gen_filter.h"
|
#include "gen_filter.h"
|
||||||
#include "json_evt.h"
|
#include "json_evt.h"
|
||||||
#include "falco_common.h"
|
#include "falco_common.h"
|
||||||
#include "token_bucket.h"
|
#include "token_bucket.h"
|
||||||
#include "falco_engine.h"
|
#include "falco_engine.h"
|
||||||
#include "outputs.h"
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// This class acts as the primary interface between a program and the
|
// This class acts as the primary interface between a program and the
|
||||||
// falco output engine. The falco rules engine is implemented by a
|
// falco output engine. The falco rules engine is implemented by a
|
||||||
// separate class falco_engine.
|
// separate class falco_engine.
|
||||||
//
|
//
|
||||||
class falco_outputs
|
|
||||||
|
class falco_outputs : public falco_common
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
falco_outputs();
|
falco_outputs(falco_engine *engine);
|
||||||
virtual ~falco_outputs();
|
virtual ~falco_outputs();
|
||||||
|
|
||||||
|
// The way to refer to an output (file, syslog, stdout, etc.)
|
||||||
|
// An output has a name and set of options.
|
||||||
|
struct output_config
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::map<std::string, std::string> options;
|
||||||
|
};
|
||||||
|
|
||||||
void init(bool json_output,
|
void init(bool json_output,
|
||||||
bool json_include_output_property,
|
bool json_include_output_property,
|
||||||
uint32_t rate, uint32_t max_burst, bool buffered,
|
uint32_t rate, uint32_t max_burst, bool buffered,
|
||||||
bool time_format_iso_8601, std::string hostname);
|
bool time_format_iso_8601, std::string hostname);
|
||||||
|
|
||||||
void add_output(falco::outputs::config oc);
|
void add_output(output_config oc);
|
||||||
|
|
||||||
//
|
//
|
||||||
// evt is an event that has matched some rule. Pass the event
|
// ev is an event that has matched some rule. Pass the event
|
||||||
// to all configured outputs.
|
// to all configured outputs.
|
||||||
//
|
//
|
||||||
void handle_event(gen_event *evt, std::string &rule, std::string &source,
|
void handle_event(gen_event *ev, std::string &rule, std::string &source,
|
||||||
falco_common::priority_type priority, std::string &format);
|
falco_common::priority_type priority, std::string &format);
|
||||||
|
|
||||||
// Send a generic message to all outputs. Not necessarily associated with any event.
|
// Send a generic message to all outputs. Not necessarily associated with any event.
|
||||||
@@ -60,10 +74,14 @@ public:
|
|||||||
|
|
||||||
void reopen_outputs();
|
void reopen_outputs();
|
||||||
|
|
||||||
private:
|
static int handle_http(lua_State *ls);
|
||||||
bool m_initialized;
|
static int handle_grpc(lua_State *ls);
|
||||||
|
|
||||||
std::vector<falco::outputs::abstract_output *> m_outputs;
|
private:
|
||||||
|
|
||||||
|
falco_engine *m_falco_engine;
|
||||||
|
|
||||||
|
bool m_initialized;
|
||||||
|
|
||||||
// Rate limits notifications
|
// Rate limits notifications
|
||||||
token_bucket m_notifications_tb;
|
token_bucket m_notifications_tb;
|
||||||
@@ -72,4 +90,11 @@ private:
|
|||||||
bool m_json_output;
|
bool m_json_output;
|
||||||
bool m_time_format_iso_8601;
|
bool m_time_format_iso_8601;
|
||||||
std::string m_hostname;
|
std::string m_hostname;
|
||||||
|
|
||||||
|
std::string m_lua_add_output = "add_output";
|
||||||
|
std::string m_lua_output_event = "output_event";
|
||||||
|
std::string m_lua_output_msg = "output_msg";
|
||||||
|
std::string m_lua_output_cleanup = "output_cleanup";
|
||||||
|
std::string m_lua_output_reopen = "output_reopen";
|
||||||
|
std::string m_lua_main_filename = "output.lua";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors
|
Copyright (C) 2019 The Falco Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -21,9 +21,9 @@ limitations under the License.
|
|||||||
|
|
||||||
namespace falco
|
namespace falco
|
||||||
{
|
{
|
||||||
namespace grpc
|
namespace outputs
|
||||||
{
|
{
|
||||||
typedef tbb::concurrent_queue<outputs::response> response_cq;
|
typedef tbb::concurrent_queue<response> response_cq;
|
||||||
|
|
||||||
class queue
|
class queue
|
||||||
{
|
{
|
||||||
@@ -34,12 +34,12 @@ public:
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_pop(outputs::response& res)
|
bool try_pop(response& res)
|
||||||
{
|
{
|
||||||
return m_queue.try_pop(res);
|
return m_queue.try_pop(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(outputs::response& res)
|
void push(response& res)
|
||||||
{
|
{
|
||||||
m_queue.push(res);
|
m_queue.push(res);
|
||||||
}
|
}
|
||||||
@@ -56,5 +56,5 @@ public:
|
|||||||
queue(queue const&) = delete;
|
queue(queue const&) = delete;
|
||||||
void operator=(queue const&) = delete;
|
void operator=(queue const&) = delete;
|
||||||
};
|
};
|
||||||
} // namespace grpc
|
} // namespace output
|
||||||
} // namespace falco
|
} // namespace falco
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors
|
Copyright (C) 2019 The Falco Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
#include "config_falco.h"
|
#include "config_falco.h"
|
||||||
#include "grpc_server_impl.h"
|
#include "grpc_server_impl.h"
|
||||||
#include "grpc_queue.h"
|
#include "falco_outputs_queue.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ void falco::grpc::server_impl::get(const stream_context& ctx, const outputs::req
|
|||||||
// m_status == stream_context::STREAMING?
|
// m_status == stream_context::STREAMING?
|
||||||
// todo(leodido) > set m_stream
|
// todo(leodido) > set m_stream
|
||||||
|
|
||||||
ctx.m_has_more = queue::get().try_pop(res);
|
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)
|
void falco::grpc::server_impl::sub(const bidi_context& ctx, const outputs::request& req, outputs::response& res)
|
||||||
@@ -61,7 +61,7 @@ void falco::grpc::server_impl::sub(const bidi_context& ctx, const outputs::reque
|
|||||||
// m_status == stream_context::STREAMING?
|
// m_status == stream_context::STREAMING?
|
||||||
// todo(leodido) > set m_stream
|
// todo(leodido) > set m_stream
|
||||||
|
|
||||||
ctx.m_has_more = queue::get().try_pop(res);
|
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)
|
void falco::grpc::server_impl::version(const context& ctx, const version::request&, version::response& res)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +16,25 @@ limitations under the License.
|
|||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "chisel_api.h"
|
||||||
|
|
||||||
#include "falco_common.h"
|
#include "falco_common.h"
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
|
const static struct luaL_reg ll_falco [] =
|
||||||
|
{
|
||||||
|
{"syslog", &falco_logger::syslog},
|
||||||
|
{NULL,NULL}
|
||||||
|
};
|
||||||
|
|
||||||
int falco_logger::level = LOG_INFO;
|
int falco_logger::level = LOG_INFO;
|
||||||
bool falco_logger::time_format_iso_8601 = false;
|
bool falco_logger::time_format_iso_8601 = false;
|
||||||
|
|
||||||
|
void falco_logger::init(lua_State *ls)
|
||||||
|
{
|
||||||
|
luaL_openlib(ls, "falco", ll_falco, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void falco_logger::set_time_format_iso_8601(bool val)
|
void falco_logger::set_time_format_iso_8601(bool val)
|
||||||
{
|
{
|
||||||
falco_logger::time_format_iso_8601 = val;
|
falco_logger::time_format_iso_8601 = val;
|
||||||
@@ -69,6 +81,19 @@ void falco_logger::set_level(string &level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int falco_logger::syslog(lua_State *ls) {
|
||||||
|
int priority = luaL_checknumber(ls, 1);
|
||||||
|
|
||||||
|
if (priority > LOG_DEBUG) {
|
||||||
|
return luaL_argerror(ls, 1, "falco.syslog: priority must be a number between 0 and 7");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *msg = luaL_checkstring(ls, 2);
|
||||||
|
::syslog(priority, "%s", msg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool falco_logger::log_stderr = true;
|
bool falco_logger::log_stderr = true;
|
||||||
bool falco_logger::log_syslog = true;
|
bool falco_logger::log_syslog = true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2020 The Falco Authors.
|
Copyright (C) 2019 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -19,15 +19,25 @@ limitations under the License.
|
|||||||
#include "sinsp.h"
|
#include "sinsp.h"
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
}
|
||||||
|
|
||||||
class falco_logger
|
class falco_logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static void init(lua_State *ls);
|
||||||
|
|
||||||
static void set_time_format_iso_8601(bool val);
|
static void set_time_format_iso_8601(bool val);
|
||||||
|
|
||||||
// Will throw exception if level is unknown.
|
// Will throw exception if level is unknown.
|
||||||
static void set_level(string &level);
|
static void set_level(string &level);
|
||||||
|
|
||||||
|
// value = falco.syslog(level, message)
|
||||||
|
static int syslog(lua_State *ls);
|
||||||
|
|
||||||
static void log(int priority, const string msg);
|
static void log(int priority, const string msg);
|
||||||
|
|
||||||
static int level;
|
static int level;
|
||||||
|
|||||||
1
userspace/falco/lua/.gitignore
vendored
Normal file
1
userspace/falco/lua/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lyaml*
|
||||||
271
userspace/falco/lua/output.lua
Normal file
271
userspace/falco/lua/output.lua
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
-- 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.
|
||||||
|
--
|
||||||
|
|
||||||
|
local mod = {}
|
||||||
|
|
||||||
|
local outputs = {}
|
||||||
|
|
||||||
|
function mod.stdout(event, rule, source, priority, priority_num, msg, format, hostname, options)
|
||||||
|
mod.stdout_message(priority, priority_num, msg, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.stdout_message(priority, priority_num, msg, options)
|
||||||
|
if options.buffered == 0 then
|
||||||
|
io.stdout:setvbuf "no"
|
||||||
|
end
|
||||||
|
print(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.stdout_cleanup()
|
||||||
|
io.stdout:flush()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Note: not actually closing/reopening stdout
|
||||||
|
function mod.stdout_reopen(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.file_validate(options)
|
||||||
|
if (not type(options.filename) == "string") then
|
||||||
|
error("File output needs to be configured with a valid filename")
|
||||||
|
end
|
||||||
|
|
||||||
|
local file, err = io.open(options.filename, "a+")
|
||||||
|
if file == nil then
|
||||||
|
error("Error with file output: " .. err)
|
||||||
|
end
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.file_open(options)
|
||||||
|
if ffile == nil then
|
||||||
|
ffile = io.open(options.filename, "a+")
|
||||||
|
if options.buffered == 0 then
|
||||||
|
ffile:setvbuf "no"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.file(event, rule, source, priority, priority_num, msg, format, hostname, options)
|
||||||
|
mod.file_message(priority, priority_num, msg, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.file_message(priority, priority_num, msg, options)
|
||||||
|
if options.keep_alive == "true" then
|
||||||
|
mod.file_open(options)
|
||||||
|
else
|
||||||
|
ffile = io.open(options.filename, "a+")
|
||||||
|
end
|
||||||
|
|
||||||
|
ffile:write(msg, "\n")
|
||||||
|
|
||||||
|
if options.keep_alive == nil or options.keep_alive ~= "true" then
|
||||||
|
ffile:close()
|
||||||
|
ffile = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.file_cleanup()
|
||||||
|
if ffile ~= nil then
|
||||||
|
ffile:flush()
|
||||||
|
ffile:close()
|
||||||
|
ffile = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.file_reopen(options)
|
||||||
|
if options.keep_alive == "true" then
|
||||||
|
mod.file_cleanup()
|
||||||
|
mod.file_open(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.syslog(event, rule, source, priority, priority_num, msg, format, hostname, options)
|
||||||
|
mod.syslog_message(priority, priority_num, msg, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.syslog_message(priority, priority_num, msg, options)
|
||||||
|
falco.syslog(priority_num, msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.syslog_cleanup()
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.syslog_reopen()
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.program_open(options)
|
||||||
|
if pfile == nil then
|
||||||
|
pfile = io.popen(options.program, "w")
|
||||||
|
if options.buffered == 0 then
|
||||||
|
pfile:setvbuf "no"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.program(event, rule, source, priority, priority_num, msg, format, hostname, options)
|
||||||
|
mod.program_message(priority, priority_num, msg, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.program_message(priority, priority_num, msg, options)
|
||||||
|
-- XXX Ideally we'd check that the program ran
|
||||||
|
-- successfully. However, the luajit we're using returns true even
|
||||||
|
-- when the shell can't run the program.
|
||||||
|
|
||||||
|
-- Note: options are all strings
|
||||||
|
if options.keep_alive == "true" then
|
||||||
|
mod.program_open(options)
|
||||||
|
else
|
||||||
|
pfile = io.popen(options.program, "w")
|
||||||
|
end
|
||||||
|
|
||||||
|
pfile:write(msg, "\n")
|
||||||
|
|
||||||
|
if options.keep_alive == nil or options.keep_alive ~= "true" then
|
||||||
|
pfile:close()
|
||||||
|
pfile = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.program_cleanup()
|
||||||
|
if pfile ~= nil then
|
||||||
|
pfile:flush()
|
||||||
|
pfile:close()
|
||||||
|
pfile = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.program_reopen(options)
|
||||||
|
if options.keep_alive == "true" then
|
||||||
|
mod.program_cleanup()
|
||||||
|
mod.program_open(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.http(event, rule, source, priority, priority_num, msg, format, hostname, options)
|
||||||
|
mod.http_message(priority, priority_num, msg, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.http_message(priority, priority_num, msg, options)
|
||||||
|
c_outputs.handle_http(options.url, msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.http_cleanup()
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.http_reopen()
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.grpc(event, rule, source, priority, priority_num, msg, format, hostname, options)
|
||||||
|
fields = formats.resolve_tokens(event, source, format)
|
||||||
|
c_outputs.handle_grpc(event, rule, source, priority, msg, fields, hostname, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.grpc_message(priority, priority_num, msg, options)
|
||||||
|
-- todo(fntlnz, leodido) > gRPC does not support subscribing to dropped events yet
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function mod.grpc_cleanup()
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.grpc_reopen()
|
||||||
|
end
|
||||||
|
|
||||||
|
function output_event(event, rule, source, priority, priority_num, format, hostname)
|
||||||
|
-- If format starts with a *, remove it, as we're adding our own
|
||||||
|
-- prefix here.
|
||||||
|
if format:sub(1, 1) == "*" then
|
||||||
|
format = format:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- time_format_iso_8601 will be the same for all output channels
|
||||||
|
time_format_iso_8601 = 0
|
||||||
|
|
||||||
|
for index, o in ipairs(outputs) do
|
||||||
|
time_format_iso_8601 = o.options.time_format_iso_8601
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
if source == "syscall" then
|
||||||
|
if time_format_iso_8601 == 1 then
|
||||||
|
format = "*%evt.time.iso8601: " .. priority .. " " .. format
|
||||||
|
else
|
||||||
|
format = "*%evt.time: " .. priority .. " " .. format
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if time_format_iso_8601 == 1 then
|
||||||
|
format = "*%jevt.time.iso8601: " .. priority .. " " .. format
|
||||||
|
else
|
||||||
|
format = "*%jevt.time: " .. priority .. " " .. format
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
msg = formats.format_event(event, rule, source, priority, format)
|
||||||
|
|
||||||
|
for index, o in ipairs(outputs) do
|
||||||
|
o.output(event, rule, source, priority, priority_num, msg, format, hostname, o.options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function output_msg(msg, priority, priority_num)
|
||||||
|
for index, o in ipairs(outputs) do
|
||||||
|
o.message(priority, priority_num, msg, o.options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function output_cleanup()
|
||||||
|
formats.free_formatters()
|
||||||
|
for index, o in ipairs(outputs) do
|
||||||
|
o.cleanup()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function output_reopen()
|
||||||
|
for index, o in ipairs(outputs) do
|
||||||
|
o.reopen(o.options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function add_output(output_name, buffered, time_format_iso_8601, options)
|
||||||
|
if not (type(mod[output_name]) == "function") then
|
||||||
|
error("rule_loader.add_output(): invalid output_name: " .. output_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- outputs can optionally define a validation function so that we don't
|
||||||
|
-- find out at runtime (when an event finally matches a rule!) that the options are invalid
|
||||||
|
if (type(mod[output_name .. "_validate"]) == "function") then
|
||||||
|
mod[output_name .. "_validate"](options)
|
||||||
|
end
|
||||||
|
|
||||||
|
if options == nil then
|
||||||
|
options = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
options.buffered = buffered
|
||||||
|
options.time_format_iso_8601 = time_format_iso_8601
|
||||||
|
|
||||||
|
table.insert(
|
||||||
|
outputs,
|
||||||
|
{
|
||||||
|
output = mod[output_name],
|
||||||
|
cleanup = mod[output_name .. "_cleanup"],
|
||||||
|
reopen = mod[output_name .. "_reopen"],
|
||||||
|
message = mod[output_name .. "_message"],
|
||||||
|
options = options
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
return mod
|
||||||
44
userspace/falco/lua/test.lua
Normal file
44
userspace/falco/lua/test.lua
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
-- 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.
|
||||||
|
--
|
||||||
|
|
||||||
|
local parser = require "parser"
|
||||||
|
|
||||||
|
if #arg ~= 1 then
|
||||||
|
print("Usage: test.lua <string>")
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local macros = {}
|
||||||
|
local ast
|
||||||
|
|
||||||
|
local function doit(line)
|
||||||
|
ast = parser.parse_filter(line)
|
||||||
|
|
||||||
|
if not ast then
|
||||||
|
print("error", error_msg)
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
for str in string.gmatch(arg[1], "([^;]+)") do
|
||||||
|
doit(str)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (ast and ast.type) then
|
||||||
|
parser.print_ast(ast)
|
||||||
|
end
|
||||||
|
|
||||||
|
os.exit(0)
|
||||||
|
|
||||||
@@ -1,73 +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 <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "falco_common.h"
|
|
||||||
#include "gen_filter.h"
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
namespace outputs
|
|
||||||
{
|
|
||||||
|
|
||||||
//
|
|
||||||
// The way to refer to an output (file, syslog, stdout, etc.)
|
|
||||||
// An output has a name and set of options.
|
|
||||||
//
|
|
||||||
struct config
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
std::map<std::string, std::string> options;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// This class acts as the primary interface for implementing
|
|
||||||
// a Falco output class.
|
|
||||||
//
|
|
||||||
|
|
||||||
class abstract_output
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void init(config oc, bool buffered, std::string hostname)
|
|
||||||
{
|
|
||||||
m_oc = oc;
|
|
||||||
m_buffered = buffered;
|
|
||||||
m_hostname = hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output an event that has matched some rule.
|
|
||||||
virtual void output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg) = 0;
|
|
||||||
|
|
||||||
// Output a generic message. Not necessarily associated with any event.
|
|
||||||
virtual void output_msg(falco_common::priority_type priority, std::string &msg) = 0;
|
|
||||||
|
|
||||||
virtual void reopen() {}
|
|
||||||
|
|
||||||
virtual void cleanup() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
config m_oc;
|
|
||||||
bool m_buffered;
|
|
||||||
std::string m_hostname;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace outputs
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,63 +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 "outputs_file.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
|
||||||
|
|
||||||
void falco::outputs::output_file::open_file()
|
|
||||||
{
|
|
||||||
if(!m_buffered)
|
|
||||||
{
|
|
||||||
m_outfile.rdbuf()->pubsetbuf(0, 0);
|
|
||||||
}
|
|
||||||
if(!m_outfile.is_open())
|
|
||||||
{
|
|
||||||
m_outfile.open(m_oc.options["filename"], fstream::app);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_file::output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
|
||||||
{
|
|
||||||
output_msg(priority, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_file::output_msg(falco_common::priority_type priority, std::string &msg)
|
|
||||||
{
|
|
||||||
open_file();
|
|
||||||
m_outfile << msg + "\n";
|
|
||||||
|
|
||||||
if(m_oc.options["keep_alive"] != "true")
|
|
||||||
{
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_file::cleanup()
|
|
||||||
{
|
|
||||||
if(m_outfile.is_open())
|
|
||||||
{
|
|
||||||
m_outfile.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_file::reopen()
|
|
||||||
{
|
|
||||||
cleanup();
|
|
||||||
open_file();
|
|
||||||
}
|
|
||||||
@@ -1,46 +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 "outputs.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
namespace outputs
|
|
||||||
{
|
|
||||||
|
|
||||||
class output_file : public abstract_output
|
|
||||||
{
|
|
||||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
|
||||||
|
|
||||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
void reopen();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void open_file();
|
|
||||||
|
|
||||||
std::ofstream m_outfile;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace outputs
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,76 +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 <google/protobuf/util/time_util.h>
|
|
||||||
#include "outputs_grpc.h"
|
|
||||||
#include "grpc_queue.h"
|
|
||||||
#include "falco_common.h"
|
|
||||||
#include "formats.h"
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
|
||||||
|
|
||||||
void falco::outputs::output_grpc::output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format,
|
|
||||||
std::string &msg)
|
|
||||||
{
|
|
||||||
falco::outputs::response grpc_res;
|
|
||||||
|
|
||||||
// time
|
|
||||||
auto timestamp = grpc_res.mutable_time();
|
|
||||||
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(evt->get_ts());
|
|
||||||
|
|
||||||
// rule
|
|
||||||
auto r = grpc_res.mutable_rule();
|
|
||||||
*r = rule;
|
|
||||||
|
|
||||||
// source
|
|
||||||
falco::schema::source s = falco::schema::source::SYSCALL;
|
|
||||||
if(!falco::schema::source_Parse(source, &s))
|
|
||||||
{
|
|
||||||
throw falco_exception("Unknown source passed to output_grpc::output_event()");
|
|
||||||
}
|
|
||||||
grpc_res.set_source(s);
|
|
||||||
|
|
||||||
// priority
|
|
||||||
falco::schema::priority p = falco::schema::priority::EMERGENCY;
|
|
||||||
if(!falco::schema::priority_Parse(falco_common::priority_names[priority], &p))
|
|
||||||
{
|
|
||||||
throw falco_exception("Unknown priority passed to output_grpc::output_event()");
|
|
||||||
}
|
|
||||||
grpc_res.set_priority(p);
|
|
||||||
|
|
||||||
// output
|
|
||||||
auto output = grpc_res.mutable_output();
|
|
||||||
*output = msg;
|
|
||||||
|
|
||||||
// output fields
|
|
||||||
auto &fields = *grpc_res.mutable_output_fields();
|
|
||||||
auto resolvedTkns = falco_formats::resolve_tokens(evt, source, format);
|
|
||||||
for(const auto &kv : resolvedTkns)
|
|
||||||
{
|
|
||||||
fields[kv.first] = kv.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hostname
|
|
||||||
auto host = grpc_res.mutable_hostname();
|
|
||||||
*host = m_hostname;
|
|
||||||
|
|
||||||
falco::grpc::queue::get().push(grpc_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_grpc::output_msg(falco_common::priority_type priority, std::string &msg)
|
|
||||||
{
|
|
||||||
// todo(fntlnz, leodido, leogr) > gRPC does not support subscribing to dropped events yet
|
|
||||||
}
|
|
||||||
@@ -1,35 +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 "outputs.h"
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
namespace outputs
|
|
||||||
{
|
|
||||||
|
|
||||||
class output_grpc : public abstract_output
|
|
||||||
{
|
|
||||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
|
||||||
|
|
||||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace outputs
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,54 +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 "outputs_http.h"
|
|
||||||
#include "logger.h"
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
|
||||||
|
|
||||||
void falco::outputs::output_http::output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
|
||||||
{
|
|
||||||
output_msg(priority, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_http::output_msg(falco_common::priority_type priority, std::string &msg)
|
|
||||||
{
|
|
||||||
CURL *curl = NULL;
|
|
||||||
CURLcode res = CURLE_FAILED_INIT;
|
|
||||||
struct curl_slist *slist1;
|
|
||||||
slist1 = NULL;
|
|
||||||
|
|
||||||
curl = curl_easy_init();
|
|
||||||
if(curl)
|
|
||||||
{
|
|
||||||
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, m_oc.options["url"].c_str());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
|
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
|
|
||||||
if(res != CURLE_OK)
|
|
||||||
{
|
|
||||||
falco_logger::log(LOG_ERR, "libcurl error: " + string(curl_easy_strerror(res)));
|
|
||||||
}
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
curl = NULL;
|
|
||||||
curl_slist_free_all(slist1);
|
|
||||||
slist1 = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +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 "outputs.h"
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
namespace outputs
|
|
||||||
{
|
|
||||||
|
|
||||||
class output_http : public abstract_output
|
|
||||||
{
|
|
||||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
|
||||||
|
|
||||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace outputs
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,65 +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 "outputs_program.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
|
||||||
|
|
||||||
void falco::outputs::output_program::open_pfile()
|
|
||||||
{
|
|
||||||
if(m_pfile == nullptr)
|
|
||||||
{
|
|
||||||
m_pfile = popen(m_oc.options["program"].c_str(), "w");
|
|
||||||
|
|
||||||
if(!m_buffered)
|
|
||||||
{
|
|
||||||
setvbuf(m_pfile, NULL, _IONBF, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_program::output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
|
||||||
{
|
|
||||||
output_msg(priority, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_program::output_msg(falco_common::priority_type priority, std::string &msg)
|
|
||||||
{
|
|
||||||
open_pfile();
|
|
||||||
|
|
||||||
fprintf(m_pfile, "%s\n", msg.c_str());
|
|
||||||
|
|
||||||
if(m_oc.options["keep_alive"] != "true")
|
|
||||||
{
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_program::cleanup()
|
|
||||||
{
|
|
||||||
if(m_pfile != nullptr)
|
|
||||||
{
|
|
||||||
pclose(m_pfile);
|
|
||||||
m_pfile = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_program::reopen()
|
|
||||||
{
|
|
||||||
cleanup();
|
|
||||||
open_pfile();
|
|
||||||
}
|
|
||||||
@@ -1,44 +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 "outputs.h"
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
namespace outputs
|
|
||||||
{
|
|
||||||
|
|
||||||
class output_program : public abstract_output
|
|
||||||
{
|
|
||||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
|
||||||
|
|
||||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
void reopen();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void open_pfile();
|
|
||||||
|
|
||||||
FILE *m_pfile;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace outputs
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,45 +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 "outputs_stdout.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
|
||||||
|
|
||||||
void falco::outputs::output_stdout::output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
|
||||||
{
|
|
||||||
output_msg(priority, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_stdout::output_msg(falco_common::priority_type priority, std::string &msg)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// By default, the stdout stream is fully buffered or line buffered
|
|
||||||
// (if the stream can be determined to refer to an interactive device, e.g. in a TTY).
|
|
||||||
// Just enable automatic flushing when unbuffered output is desired.
|
|
||||||
// Note that it is set every time since other writings to the stdout can disable it.
|
|
||||||
//
|
|
||||||
if(!m_buffered)
|
|
||||||
{
|
|
||||||
std::cout << std::unitbuf;
|
|
||||||
}
|
|
||||||
std::cout << msg + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_stdout::cleanup()
|
|
||||||
{
|
|
||||||
std::cout.flush();
|
|
||||||
}
|
|
||||||
@@ -1,37 +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 "outputs.h"
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
namespace outputs
|
|
||||||
{
|
|
||||||
|
|
||||||
class output_stdout : public abstract_output
|
|
||||||
{
|
|
||||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
|
||||||
|
|
||||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace outputs
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,31 +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 "outputs_syslog.h"
|
|
||||||
#include <syslog.h>
|
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
|
||||||
|
|
||||||
void falco::outputs::output_syslog::output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg)
|
|
||||||
{
|
|
||||||
output_msg(priority, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco::outputs::output_syslog::output_msg(falco_common::priority_type priority, std::string &msg)
|
|
||||||
{
|
|
||||||
// Syslog output should not have any trailing newline
|
|
||||||
::syslog(priority, "%s", msg.c_str());
|
|
||||||
}
|
|
||||||
@@ -1,35 +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 "outputs.h"
|
|
||||||
|
|
||||||
namespace falco
|
|
||||||
{
|
|
||||||
namespace outputs
|
|
||||||
{
|
|
||||||
|
|
||||||
class output_syslog : public abstract_output
|
|
||||||
{
|
|
||||||
void output_event(gen_event *evt, std::string &rule, std::string &source,
|
|
||||||
falco_common::priority_type priority, std::string &format, std::string &msg);
|
|
||||||
|
|
||||||
void output_msg(falco_common::priority_type priority, std::string &msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace outputs
|
|
||||||
} // namespace falco
|
|
||||||
@@ -1,12 +1,19 @@
|
|||||||
#!/bin/env/bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SOURCE_DIR=$1
|
SOURCE_DIR=$1
|
||||||
|
OPENSSL=$2
|
||||||
|
|
||||||
NEW_CHECKSUM=$(./falco --list -N | sha256sum | awk '{print $1}')
|
if ! command -v "${OPENSSL}" version > /dev/null 2>&1; then
|
||||||
|
echo "No openssl command at ${OPENSSL}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
NEW_CHECKSUM=$(./falco --list -N | ${OPENSSL} dgst -sha256 | awk '{print $2}')
|
||||||
CUR_CHECKSUM=$(grep FALCO_FIELDS_CHECKSUM "${SOURCE_DIR}/userspace/engine/falco_engine_version.h" | awk '{print $3}' | sed -e 's/"//g')
|
CUR_CHECKSUM=$(grep FALCO_FIELDS_CHECKSUM "${SOURCE_DIR}/userspace/engine/falco_engine_version.h" | awk '{print $3}' | sed -e 's/"//g')
|
||||||
|
|
||||||
|
|
||||||
if [ "$NEW_CHECKSUM" != "$CUR_CHECKSUM" ]; then
|
if [ "$NEW_CHECKSUM" != "$CUR_CHECKSUM" ]; then
|
||||||
echo "Set of fields supported has changed (new checksum $NEW_CHECKSUM != old checksum $CUR_CHECKSUM)."
|
echo "Set of fields supported has changed (new checksum $NEW_CHECKSUM != old checksum $CUR_CHECKSUM)."
|
||||||
echo "Update checksum and/or version in falco_engine_version.h."
|
echo "Update checksum and/or version in falco_engine_version.h."
|
||||||
|
|||||||
Reference in New Issue
Block a user