mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-21 04:02:14 +00:00
Compare commits
214 Commits
test_filte
...
fix_CI_4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8680182c5 | ||
|
|
d99c137b09 | ||
|
|
691bc8b04d | ||
|
|
ab0133d1dd | ||
|
|
334302e525 | ||
|
|
1ab4e9e0fc | ||
|
|
9e1e68f64b | ||
|
|
752e8bf16c | ||
|
|
cbbcb61153 | ||
|
|
3b095a5eda | ||
|
|
7805bf5ad5 | ||
|
|
0c0fb63008 | ||
|
|
ed346e90cd | ||
|
|
b190a60da7 | ||
|
|
34a896f3a5 | ||
|
|
1a338e1a39 | ||
|
|
e3f54a14a6 | ||
|
|
4bfc42eb7d | ||
|
|
47959abfed | ||
|
|
8db79da647 | ||
|
|
9c01f3518a | ||
|
|
f2ebdfaf8e | ||
|
|
e427c800f3 | ||
|
|
5e17ba6c23 | ||
|
|
e177898d2b | ||
|
|
2dfd687912 | ||
|
|
b7538429b8 | ||
|
|
1de6f10ad6 | ||
|
|
5f59fee54f | ||
|
|
4d566b2c71 | ||
|
|
96f50ddac5 | ||
|
|
ade27c2546 | ||
|
|
2244cc6f71 | ||
|
|
1dd47668dd | ||
|
|
5eb2ae8d76 | ||
|
|
33451cf0bc | ||
|
|
27161bb508 | ||
|
|
0c9538241d | ||
|
|
7452c5dc98 | ||
|
|
be100f7ad5 | ||
|
|
8cf9b35b0e | ||
|
|
6e4ccb0007 | ||
|
|
44b7352180 | ||
|
|
13991f1ea7 | ||
|
|
10226a6c87 | ||
|
|
e558c4f5a5 | ||
|
|
0ba0dd8671 | ||
|
|
305ed75268 | ||
|
|
390a13bd40 | ||
|
|
67542ec88e | ||
|
|
e3943ccac3 | ||
|
|
95968defa5 | ||
|
|
6411eed4a7 | ||
|
|
c5364be191 | ||
|
|
ce4d28ef90 | ||
|
|
3b068919d0 | ||
|
|
3e4566e5af | ||
|
|
9cb4c09500 | ||
|
|
8196ee3b83 | ||
|
|
af7192bdc3 | ||
|
|
00b7c56d54 | ||
|
|
2ce8fe9011 | ||
|
|
4443e9d64f | ||
|
|
249ccf2f4b | ||
|
|
715db9ddb4 | ||
|
|
0368de5229 | ||
|
|
b92e0d6134 | ||
|
|
898ba68b3b | ||
|
|
96f474a29c | ||
|
|
12122729a4 | ||
|
|
335022076f | ||
|
|
1b14fed380 | ||
|
|
11253cc0eb | ||
|
|
be16af7fe0 | ||
|
|
588a94578a | ||
|
|
5e8e0a4722 | ||
|
|
bfef0e95be | ||
|
|
bc8f61ca68 | ||
|
|
2778b12344 | ||
|
|
7056cb9035 | ||
|
|
1f27f3b7f0 | ||
|
|
1ee6569a5d | ||
|
|
f3f56db5ca | ||
|
|
4127764129 | ||
|
|
4f1b950e0d | ||
|
|
626e609e4b | ||
|
|
ea2d62d56b | ||
|
|
fb4ac046b0 | ||
|
|
d53fa930c2 | ||
|
|
5dc9987877 | ||
|
|
a1d5bb7009 | ||
|
|
66a122d4ce | ||
|
|
b3775ce91c | ||
|
|
1e3f17150d | ||
|
|
04e2f19915 | ||
|
|
ef816e8b06 | ||
|
|
2bcd12755f | ||
|
|
359bd6e593 | ||
|
|
f073a6ee88 | ||
|
|
8bf40cdf88 | ||
|
|
22cc2e5add | ||
|
|
92b42c9474 | ||
|
|
fde8da0e5c | ||
|
|
be90768b0a | ||
|
|
b9d7eb7ab3 | ||
|
|
115729a86a | ||
|
|
1b8525bf80 | ||
|
|
6d4006a1ec | ||
|
|
f0d2f17c8d | ||
|
|
907ced9f50 | ||
|
|
df4e91476f | ||
|
|
29d3173ae3 | ||
|
|
5db29f4692 | ||
|
|
0ca5251128 | ||
|
|
89e45ced87 | ||
|
|
5ee9ff8c8f | ||
|
|
f7575292c6 | ||
|
|
af70b4e770 | ||
|
|
00a87234ce | ||
|
|
325701ce4f | ||
|
|
5b3cb654ff | ||
|
|
e5e5416ade | ||
|
|
fb0d757bfe | ||
|
|
7cf23fb7c6 | ||
|
|
345136c6c8 | ||
|
|
916d571cd0 | ||
|
|
e0f7c597be | ||
|
|
8cfa79fbc8 | ||
|
|
7319b93d9b | ||
|
|
3e95faac44 | ||
|
|
d074728994 | ||
|
|
fac48cd145 | ||
|
|
91a9717779 | ||
|
|
f5985720f1 | ||
|
|
2e7cacb4e0 | ||
|
|
214e41d093 | ||
|
|
1609ee8559 | ||
|
|
3ff2bb5c2b | ||
|
|
39aa8fe05f | ||
|
|
1e38967b18 | ||
|
|
b7cef5bab2 | ||
|
|
fec8a825cd | ||
|
|
fc35c02015 | ||
|
|
e68bb3be7d | ||
|
|
099332f958 | ||
|
|
e4054fc5ea | ||
|
|
dd807b19c8 | ||
|
|
56401340c3 | ||
|
|
4b9a8d9388 | ||
|
|
32b7ccd8dc | ||
|
|
d28f43cd98 | ||
|
|
943446ba97 | ||
|
|
d4a4de9055 | ||
|
|
e6d71d2e8e | ||
|
|
a77e2dec10 | ||
|
|
f1dec8f444 | ||
|
|
27ad4c3aec | ||
|
|
28edf94feb | ||
|
|
3c93249efb | ||
|
|
29d2406414 | ||
|
|
09b1f92267 | ||
|
|
26e421155b | ||
|
|
155b2009f3 | ||
|
|
1326ca356e | ||
|
|
9bbf9716b6 | ||
|
|
f8cbeaaa9b | ||
|
|
cd6cb14c08 | ||
|
|
d3e1a1f746 | ||
|
|
aae114c331 | ||
|
|
b67ad907a7 | ||
|
|
dc264a0577 | ||
|
|
8f411f3d3b | ||
|
|
cba80a404f | ||
|
|
26bdefae8e | ||
|
|
dce5cac820 | ||
|
|
ab77a5d687 | ||
|
|
7c7ec800a6 | ||
|
|
e0ac9c4142 | ||
|
|
4de74f3963 | ||
|
|
cca1d705c2 | ||
|
|
bbb8b014c5 | ||
|
|
2571225571 | ||
|
|
b02898dc4c | ||
|
|
66ece1a9ac | ||
|
|
ab6d76e6d2 | ||
|
|
260f189028 | ||
|
|
1b29389ed4 | ||
|
|
bb92dcfd2f | ||
|
|
0884ca4c6f | ||
|
|
e836157771 | ||
|
|
086deb9c6d | ||
|
|
49adbf6d08 | ||
|
|
16a37e5c2e | ||
|
|
c5996bd0cf | ||
|
|
83db0bb4e2 | ||
|
|
d61eaeb5fc | ||
|
|
111a76879b | ||
|
|
fe50ac22ee | ||
|
|
e3e854f016 | ||
|
|
5ed9dc0c3a | ||
|
|
2c95fae9eb | ||
|
|
e3e9efa661 | ||
|
|
9f5e458f92 | ||
|
|
071910e6dc | ||
|
|
cf10d9022e | ||
|
|
60a64ac647 | ||
|
|
e5e7a4761d | ||
|
|
6bd40f3ea2 | ||
|
|
c9a424d75e | ||
|
|
e2b21402ae | ||
|
|
7b4264918b | ||
|
|
5595212ff9 | ||
|
|
fdd520f163 | ||
|
|
b5e3ef95fe |
4
.github/release_template.md
vendored
4
.github/release_template.md
vendored
@@ -1,5 +1,5 @@
|
||||

|
||||

|
||||
[](https://github.com/falcosecurity/libs/releases/tag/LIBSVER)
|
||||
[](https://github.com/falcosecurity/libs/releases/tag/DRIVERVER)
|
||||
|
||||
| Packages | Download |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
|
||||
36
.github/workflows/ci.yml
vendored
36
.github/workflows/ci.yml
vendored
@@ -23,6 +23,13 @@ jobs:
|
||||
arch: x86_64
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
build-dev-packages-arm64:
|
||||
needs: [fetch-version]
|
||||
uses: ./.github/workflows/reusable_build_packages.yaml
|
||||
with:
|
||||
arch: aarch64
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
test-dev-packages:
|
||||
needs: [fetch-version, build-dev-packages]
|
||||
uses: ./.github/workflows/reusable_test_packages.yaml
|
||||
@@ -35,6 +42,16 @@ jobs:
|
||||
static: ${{ matrix.static != '' && true || false }}
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
test-dev-packages-arm64:
|
||||
needs: [fetch-version, build-dev-packages]
|
||||
uses: ./.github/workflows/reusable_test_packages.yaml
|
||||
strategy:
|
||||
fail-fast: false
|
||||
with:
|
||||
arch: aarch64
|
||||
static: ${{ matrix.static != '' && true || false }}
|
||||
version: ${{ needs.fetch-version.outputs.version }}
|
||||
|
||||
build-dev-minimal:
|
||||
uses: ./.github/workflows/reusable_build_dev.yaml
|
||||
with:
|
||||
@@ -42,7 +59,15 @@ jobs:
|
||||
git_ref: ${{ github.event.pull_request.head.sha }}
|
||||
minimal: true
|
||||
build_type: Debug
|
||||
|
||||
|
||||
build-dev-minimal-arm64:
|
||||
uses: ./.github/workflows/reusable_build_dev.yaml
|
||||
with:
|
||||
arch: aarch64
|
||||
git_ref: ${{ github.event.pull_request.head.sha }}
|
||||
minimal: true
|
||||
build_type: Debug
|
||||
|
||||
# builds using system deps, checking out the PR's code
|
||||
# note: this also runs a command that generates an output of form: "<engine_version> <some_hash>",
|
||||
# of which <some_hash> is computed by hashing in order the following:
|
||||
@@ -64,7 +89,7 @@ jobs:
|
||||
needs: [build-dev]
|
||||
steps:
|
||||
- name: Checkout PR head ref
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -89,7 +114,7 @@ jobs:
|
||||
needs: [build-dev]
|
||||
steps:
|
||||
- name: Checkout base ref
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.base_ref }}
|
||||
@@ -97,7 +122,10 @@ jobs:
|
||||
- name: Check Engine version
|
||||
run: |
|
||||
base_hash=$(grep CHECKSUM "./userspace/engine/falco_engine_version.h" | awk '{print $3}' | sed -e 's/"//g')
|
||||
base_engine_ver=$(grep ENGINE_VERSION "./userspace/engine/falco_engine_version.h" | awk '{print $3}' | sed -e 's/(//g' -e 's/)//g')
|
||||
base_engine_ver_major=$(grep ENGINE_VERSION_MAJOR "./userspace/engine/falco_engine_version.h" | head -n 1 | awk '{print $3}' | sed -e 's/(//g' -e 's/)//g')
|
||||
base_engine_ver_minor=$(grep ENGINE_VERSION_MINOR "./userspace/engine/falco_engine_version.h" | head -n 1 | awk '{print $3}' | sed -e 's/(//g' -e 's/)//g')
|
||||
base_engine_ver_patch=$(grep ENGINE_VERSION_PATCH "./userspace/engine/falco_engine_version.h" | head -n 1 | awk '{print $3}' | sed -e 's/(//g' -e 's/)//g')
|
||||
base_engine_ver="${base_engine_ver_major}.${base_engine_ver_minor}.${base_engine_ver_patch}"
|
||||
|
||||
cur_hash=$(echo "${{ needs.build-dev.outputs.cmdout }}" | cut -d ' ' -f 2)
|
||||
cur_engine_ver=$(echo "${{ needs.build-dev.outputs.cmdout }}" | cut -d ' ' -f 1)
|
||||
|
||||
10
.github/workflows/codeql.yaml
vendored
10
.github/workflows/codeql.yaml
vendored
@@ -36,19 +36,19 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
run: sudo apt update -y
|
||||
|
||||
- name: Install build dependencies
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm git -y
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev libprotobuf-dev protobuf-compiler libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm git -y
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
@@ -72,4 +72,4 @@ jobs:
|
||||
popd
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
|
||||
|
||||
4
.github/workflows/codespell.yml
vendored
4
.github/workflows/codespell.yml
vendored
@@ -5,8 +5,8 @@ jobs:
|
||||
codespell:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: codespell-project/actions-codespell@master
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- uses: codespell-project/actions-codespell@94259cd8be02ad2903ba34a22d9c13de21a74461 # v2.0
|
||||
with:
|
||||
skip: .git
|
||||
ignore_words_file: .codespellignore
|
||||
|
||||
@@ -15,8 +15,8 @@ jobs:
|
||||
outputs:
|
||||
engine_version_changed: ${{ steps.filter.outputs.engine_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: dorny/paths-filter@v2
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
if: needs.paths-filter.outputs.engine_version_changed == 'false'
|
||||
steps:
|
||||
- name: Check driver Falco engine version
|
||||
uses: mshick/add-pr-comment@v2
|
||||
uses: mshick/add-pr-comment@7c0890544fb33b0bdd2e59467fbacb62e028a096 # v2.8.1
|
||||
with:
|
||||
message: |
|
||||
This PR may bring feature or behavior changes in the Falco engine and may require the engine version to be bumped.
|
||||
|
||||
26
.github/workflows/insecure-api.yaml
vendored
Normal file
26
.github/workflows/insecure-api.yaml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Insecure API check
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 'release/**'
|
||||
- 'maintainers/**'
|
||||
|
||||
jobs:
|
||||
insecure-api:
|
||||
name: check-insecure-api
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: returntocorp/semgrep:1.41.0@sha256:85956fbe795a0e8a3825d5252f175887c0e0c6ce7a766a07062c0fb68415cd67
|
||||
steps:
|
||||
- name: Checkout Falco ⤵️
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Scan PR for insecure API usage 🕵️
|
||||
run: |
|
||||
semgrep scan \
|
||||
--error \
|
||||
--metrics=off \
|
||||
--baseline-commit ${{ github.event.pull_request.base.sha }} \
|
||||
--config=./semgrep
|
||||
6
.github/workflows/release.yaml
vendored
6
.github/workflows/release.yaml
vendored
@@ -131,7 +131,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
|
||||
- name: Extract LIBS and DRIVER versions
|
||||
run: |
|
||||
@@ -147,7 +147,7 @@ jobs:
|
||||
sed -i s/FALCOVER/${{ github.event.release.tag_name }}/g release-body.md
|
||||
|
||||
- name: Generate release notes
|
||||
uses: leodido/rn2md@1a17f0e75758c15128a5146e8af5ca3a47209b3f
|
||||
uses: leodido/rn2md@0669e5f3b21492c11c2db43cd6e267566f5880f3
|
||||
with:
|
||||
milestone: ${{ github.event.release.tag_name }}
|
||||
output: ./notes.md
|
||||
@@ -161,7 +161,7 @@ jobs:
|
||||
echo "#### Release Manager @${{ github.event.release.author.login }}" >> release-body.md
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15
|
||||
with:
|
||||
body_path: ./release-body.md
|
||||
tag_name: ${{ github.event.release.tag_name }}
|
||||
|
||||
19
.github/workflows/reusable_build_dev.yaml
vendored
19
.github/workflows/reusable_build_dev.yaml
vendored
@@ -27,31 +27,30 @@ on:
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-22.04' }}
|
||||
container: ${{ (inputs.arch == 'aarch64' && 'ubuntu:22.04') || '' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-22.04' }}
|
||||
outputs:
|
||||
cmdout: ${{ steps.run_cmd.outputs.out }}
|
||||
cmdout: ${{ steps.run_cmd.outputs.out }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ inputs.git_ref }}
|
||||
|
||||
- name: Update base image
|
||||
run: sudo apt update -y
|
||||
|
||||
|
||||
- name: Install build dependencies
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libjq-dev libelf-dev libyaml-cpp-dev cmake build-essential git -y
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libelf-dev libyaml-cpp-dev cmake build-essential git -y
|
||||
|
||||
- name: Install build dependencies (non-minimal)
|
||||
if: inputs.minimal != true
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libc-ares-dev libprotobuf-dev protobuf-compiler libgrpc++-dev protobuf-compiler-grpc rpm libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm -y
|
||||
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev libprotobuf-dev protobuf-compiler libgrpc++-dev protobuf-compiler-grpc rpm libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm -y
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
mkdir build
|
||||
@@ -74,7 +73,7 @@ jobs:
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
pushd build
|
||||
sudo ./unit_tests/falco_unit_tests
|
||||
sudo ./unit_tests/falco_unit_tests
|
||||
popd
|
||||
|
||||
- name: Run command
|
||||
|
||||
8
.github/workflows/reusable_build_docker.yaml
vendored
8
.github/workflows/reusable_build_docker.yaml
vendored
@@ -27,15 +27,15 @@ on:
|
||||
jobs:
|
||||
build-docker:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
env:
|
||||
TARGETARCH: ${{ (inputs.arch == 'aarch64' && 'arm64') || 'amd64' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
|
||||
- name: Build no-driver image
|
||||
run: |
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
docker save docker.io/falcosecurity/falco-driver-loader-legacy:${{ inputs.arch }}-${{ inputs.tag }} --output /tmp/falco-driver-loader-legacy-${{ inputs.arch }}.tar
|
||||
|
||||
- name: Upload images tarballs
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-images
|
||||
path: /tmp/falco-*.tar
|
||||
|
||||
95
.github/workflows/reusable_build_packages.yaml
vendored
95
.github/workflows/reusable_build_packages.yaml
vendored
@@ -14,7 +14,7 @@ on:
|
||||
jobs:
|
||||
build-modern-bpf-skeleton:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
container: fedora:latest
|
||||
steps:
|
||||
# Always install deps before invoking checkout action, to properly perform a full clone.
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
dnf install -y bpftool ca-certificates cmake make automake gcc gcc-c++ kernel-devel clang git pkg-config autoconf automake libbpf-devel
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
|
||||
- name: Build modern BPF skeleton
|
||||
run: |
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
make ProbeSkeleton -j6
|
||||
|
||||
- name: Upload skeleton
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: bpf_probe_${{ inputs.arch }}.skel.h
|
||||
path: skeleton-build/skel_dir/bpf_probe.skel.h
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
build-packages:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
needs: [build-modern-bpf-skeleton]
|
||||
container: centos:7
|
||||
steps:
|
||||
@@ -53,10 +53,11 @@ jobs:
|
||||
yum install -y wget git make m4 rpm-build perl-IPC-Cmd
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
# It is not possible to upgrade the checkout action to versions >= v4.0.0 because of incompatibilities with centos 7's libc.
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
|
||||
- name: Download skeleton
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: bpf_probe_${{ inputs.arch }}.skel.h
|
||||
path: /tmp
|
||||
@@ -97,21 +98,21 @@ jobs:
|
||||
make package
|
||||
|
||||
- name: Upload Falco tar.gz package
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-${{ inputs.arch }}.tar.gz
|
||||
path: |
|
||||
${{ github.workspace }}/build/falco-*.tar.gz
|
||||
|
||||
- name: Upload Falco deb package
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-${{ inputs.arch }}.deb
|
||||
path: |
|
||||
${{ github.workspace }}/build/falco-*.deb
|
||||
|
||||
- name: Upload Falco rpm package
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-${{ inputs.arch }}.rpm
|
||||
path: |
|
||||
@@ -129,7 +130,7 @@ jobs:
|
||||
apk add g++ gcc cmake make git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils bpftool clang
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -154,7 +155,7 @@ jobs:
|
||||
mv falco-${{ inputs.version }}-x86_64.tar.gz falco-${{ inputs.version }}-static-x86_64.tar.gz
|
||||
|
||||
- name: Upload Falco static package
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-static-x86_64.tar.gz
|
||||
path: |
|
||||
@@ -171,12 +172,12 @@ jobs:
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt install cmake build-essential git emscripten -y
|
||||
|
||||
- name: Select node version
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -210,8 +211,74 @@ jobs:
|
||||
emmake make -j6 package
|
||||
|
||||
- name: Upload Falco WASM package
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-wasm.tar.gz
|
||||
path: |
|
||||
${{ github.workspace }}/build/falco-${{ inputs.version }}-wasm.tar.gz
|
||||
|
||||
build-win32-package:
|
||||
if: ${{ inputs.arch == 'x86_64' }}
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DMINIMAL_BUILD=On -DUSE_BUNDLED_DEPS=On -DBUILD_FALCO_UNIT_TESTS=On -DFALCO_VERSION=${{ inputs.version }} ..
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
cmake --build build --target package --config Release
|
||||
|
||||
- name: Run unit Tests
|
||||
run: |
|
||||
build/unit_tests/Release/falco_unit_tests.exe
|
||||
|
||||
- name: Upload Falco win32 installer
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-installer-${{ inputs.version }}-win32.exe
|
||||
path: build/falco-*.exe
|
||||
|
||||
- name: Upload Falco win32 package
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-win32.exe
|
||||
path: |
|
||||
${{ github.workspace }}/build/userspace/falco/Release/falco.exe
|
||||
|
||||
build-macos-package:
|
||||
if: ${{ inputs.arch == 'x86_64' }}
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DMINIMAL_BUILD=On -DUSE_BUNDLED_DEPS=On -DBUILD_FALCO_UNIT_TESTS=On -DFALCO_VERSION=${{ inputs.version }} ..
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
cmake --build build --target package
|
||||
|
||||
- name: Run unit Tests
|
||||
run: |
|
||||
sudo build/unit_tests/falco_unit_tests
|
||||
|
||||
- name: Upload Falco macos package
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-macos
|
||||
path: |
|
||||
${{ github.workspace }}/build/userspace/falco/falco
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
version: ${{ steps.store_version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
23
.github/workflows/reusable_publish_docker.yaml
vendored
23
.github/workflows/reusable_publish_docker.yaml
vendored
@@ -26,10 +26,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
|
||||
- name: Download images tarballs
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-images
|
||||
path: /tmp/falco-images
|
||||
@@ -39,13 +39,13 @@ jobs:
|
||||
for img in /tmp/falco-images/falco-*.tar; do docker load --input $img; done
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USER }}
|
||||
password: ${{ secrets.DOCKERHUB_SECRET }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
with:
|
||||
role-to-assume: "arn:aws:iam::292999226676:role/github_actions-falco-ecr"
|
||||
aws-region: us-east-1 # The region must be set to us-east-1 in order to access ECR Public.
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
registry-type: public
|
||||
|
||||
- name: Setup Crane
|
||||
uses: imjasonh/setup-crane@v0.3
|
||||
uses: imjasonh/setup-crane@00c9e93efa4e1138c9a7a5c594acd6c75a2fbf0c # v0.3
|
||||
with:
|
||||
version: v0.15.1
|
||||
|
||||
@@ -76,14 +76,14 @@ jobs:
|
||||
docker push docker.io/falcosecurity/falco-driver-loader-legacy:x86_64-${{ inputs.tag }}
|
||||
|
||||
- name: Create no-driver manifest on Docker Hub
|
||||
uses: Noelware/docker-manifest-action@0.3.1
|
||||
uses: Noelware/docker-manifest-action@8e337e3cb9656abfcf20146b99706fd88716e942 # v0.4.0
|
||||
with:
|
||||
inputs: docker.io/falcosecurity/falco-no-driver:${{ inputs.tag }}
|
||||
images: docker.io/falcosecurity/falco-no-driver:aarch64-${{ inputs.tag }},docker.io/falcosecurity/falco-no-driver:x86_64-${{ inputs.tag }}
|
||||
push: true
|
||||
|
||||
- name: Create distroless manifest on Docker Hub
|
||||
uses: Noelware/docker-manifest-action@0.3.1
|
||||
uses: Noelware/docker-manifest-action@8e337e3cb9656abfcf20146b99706fd88716e942 # v0.4.0
|
||||
with:
|
||||
inputs: docker.io/falcosecurity/falco-distroless:${{ inputs.tag }}
|
||||
images: docker.io/falcosecurity/falco-distroless:aarch64-${{ inputs.tag }},docker.io/falcosecurity/falco-distroless:x86_64-${{ inputs.tag }}
|
||||
@@ -94,21 +94,21 @@ jobs:
|
||||
crane copy docker.io/falcosecurity/falco-no-driver:${{ inputs.tag }} docker.io/falcosecurity/falco:${{ inputs.tag }}-slim
|
||||
|
||||
- name: Create falco manifest on Docker Hub
|
||||
uses: Noelware/docker-manifest-action@0.3.1
|
||||
uses: Noelware/docker-manifest-action@8e337e3cb9656abfcf20146b99706fd88716e942 # v0.4.0
|
||||
with:
|
||||
inputs: docker.io/falcosecurity/falco:${{ inputs.tag }}
|
||||
images: docker.io/falcosecurity/falco:aarch64-${{ inputs.tag }},docker.io/falcosecurity/falco:x86_64-${{ inputs.tag }}
|
||||
push: true
|
||||
|
||||
- name: Create falco-driver-loader manifest on Docker Hub
|
||||
uses: Noelware/docker-manifest-action@0.3.1
|
||||
uses: Noelware/docker-manifest-action@8e337e3cb9656abfcf20146b99706fd88716e942 # v0.4.0
|
||||
with:
|
||||
inputs: docker.io/falcosecurity/falco-driver-loader:${{ inputs.tag }}
|
||||
images: docker.io/falcosecurity/falco-driver-loader:aarch64-${{ inputs.tag }},docker.io/falcosecurity/falco-driver-loader:x86_64-${{ inputs.tag }}
|
||||
push: true
|
||||
|
||||
- name: Create falco-driver-loader-legacy manifest on Docker Hub
|
||||
uses: Noelware/docker-manifest-action@0.3.1
|
||||
uses: Noelware/docker-manifest-action@8e337e3cb9656abfcf20146b99706fd88716e942 # v0.4.0
|
||||
with:
|
||||
inputs: docker.io/falcosecurity/falco-driver-loader-legacy:${{ inputs.tag }}
|
||||
images: docker.io/falcosecurity/falco-driver-loader-legacy:aarch64-${{ inputs.tag }},docker.io/falcosecurity/falco-driver-loader-legacy:x86_64-${{ inputs.tag }}
|
||||
@@ -116,6 +116,7 @@ jobs:
|
||||
|
||||
- name: Get Digests for images
|
||||
id: digests
|
||||
# We could probably use the docker-manifest-action output instead of recomputing those with crane
|
||||
run: |
|
||||
echo "falco-no-driver=$(crane digest docker.io/falcosecurity/falco-no-driver:${{ inputs.tag }})" >> $GITHUB_OUTPUT
|
||||
echo "falco-distroless=$(crane digest docker.io/falcosecurity/falco-distroless:${{ inputs.tag }})" >> $GITHUB_OUTPUT
|
||||
@@ -151,7 +152,7 @@ jobs:
|
||||
|
||||
- name: Setup Cosign
|
||||
if: inputs.sign
|
||||
uses: sigstore/cosign-installer@main
|
||||
uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
|
||||
with:
|
||||
cosign-release: v2.0.2
|
||||
|
||||
|
||||
51
.github/workflows/reusable_publish_packages.yaml
vendored
51
.github/workflows/reusable_publish_packages.yaml
vendored
@@ -23,77 +23,64 @@ env:
|
||||
jobs:
|
||||
publish-packages:
|
||||
runs-on: ubuntu-latest
|
||||
container: docker.io/centos:7
|
||||
container: docker.io/library/fedora:38
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yum install epel-release -y
|
||||
yum update -y
|
||||
yum install rpm-sign expect which createrepo gpg python python-pip -y
|
||||
pip install awscli==1.19.47
|
||||
dnf install rpm-sign expect which createrepo gpg python python-pip -y
|
||||
pip install awscli==1.29.60
|
||||
|
||||
# Configure AWS role; see https://github.com/falcosecurity/test-infra/pull/1102
|
||||
# Note: master CI can only push dev packages as we have 2 different roles for master and release.
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
with:
|
||||
role-to-assume: "arn:aws:iam::292999226676:role/github_actions-falco${{ inputs.bucket_suffix }}-s3"
|
||||
aws-region: ${{ env.AWS_S3_REGION }}
|
||||
|
||||
- name: Download RPM x86_64
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-x86_64.rpm
|
||||
path: /tmp/falco-build-rpm
|
||||
|
||||
- name: Download RPM aarch64
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-aarch64.rpm
|
||||
path: /tmp/falco-build-rpm
|
||||
|
||||
- name: Download binary x86_64
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-x86_64.tar.gz
|
||||
path: /tmp/falco-build-bin
|
||||
|
||||
- name: Download binary aarch64
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-aarch64.tar.gz
|
||||
path: /tmp/falco-build-bin
|
||||
|
||||
- name: Download static binary x86_64
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-static-x86_64.tar.gz
|
||||
path: /tmp/falco-build-bin-static
|
||||
|
||||
- name: Import gpg key
|
||||
|
||||
- name: Import gpg key
|
||||
env:
|
||||
GPG_KEY: ${{ secrets.GPG_KEY }}
|
||||
run: printenv GPG_KEY | gpg --import -
|
||||
|
||||
|
||||
- name: Sign rpms
|
||||
run: |
|
||||
echo "%_signature gpg" > ~/.rpmmacros
|
||||
echo "%_gpg_name Falcosecurity Package Signing" >> ~/.rpmmacros
|
||||
echo "%__gpg_sign_cmd %{__gpg} --force-v3-sigs --batch --no-armor --passphrase-fd 3 --no-secmem-warning -u \"%{_gpg_name}\" -sb --digest-algo sha256 %{__plaintext_filename}'" >> ~/.rpmmacros
|
||||
cat > ~/sign <<EOF
|
||||
#!/usr/bin/expect -f
|
||||
spawn rpmsign --addsign {*}\$argv
|
||||
expect -exact "Enter pass phrase: "
|
||||
send -- "\n"
|
||||
expect eof
|
||||
EOF
|
||||
chmod +x ~/sign
|
||||
~/sign /tmp/falco-build-rpm/falco-*.rpm
|
||||
rpmsign --define '_gpg_name Falcosecurity Package Signing' --addsign /tmp/falco-build-rpm/falco-*.rpm
|
||||
rpm --qf %{SIGPGP:pgpsig} -qp /tmp/falco-build-rpm/falco-*.rpm | grep SHA256
|
||||
|
||||
|
||||
- name: Publish rpm
|
||||
run: |
|
||||
./scripts/publish-rpm -f /tmp/falco-build-rpm/falco-${{ inputs.version }}-x86_64.rpm -f /tmp/falco-build-rpm/falco-${{ inputs.version }}-aarch64.rpm -r rpm${{ inputs.bucket_suffix }}
|
||||
@@ -112,7 +99,7 @@ jobs:
|
||||
container: docker.io/debian:stable
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -122,19 +109,19 @@ jobs:
|
||||
# Configure AWS role; see https://github.com/falcosecurity/test-infra/pull/1102
|
||||
# Note: master CI can only push dev packages as we have 2 different roles for master and release.
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
with:
|
||||
role-to-assume: "arn:aws:iam::292999226676:role/github_actions-falco${{ inputs.bucket_suffix }}-s3"
|
||||
aws-region: ${{ env.AWS_S3_REGION }}
|
||||
|
||||
- name: Download deb x86_64
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-x86_64.deb
|
||||
path: /tmp/falco-build-deb
|
||||
|
||||
- name: Download deb aarch64
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}-aarch64.deb
|
||||
path: /tmp/falco-build-deb
|
||||
|
||||
68
.github/workflows/reusable_test_packages.yaml
vendored
68
.github/workflows/reusable_test_packages.yaml
vendored
@@ -19,21 +19,21 @@ on:
|
||||
jobs:
|
||||
test-packages:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && fromJSON('[ "self-hosted", "linux", "ARM64" ]')) || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: 'true'
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: '>=1.17.0'
|
||||
|
||||
- name: Download binary
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: falco-${{ inputs.version }}${{ inputs.static && '-static' || '' }}-${{ inputs.arch }}.tar.gz
|
||||
|
||||
@@ -44,12 +44,25 @@ jobs:
|
||||
cd falco-${{ inputs.version }}-${{ inputs.arch }}
|
||||
sudo cp -r * /
|
||||
|
||||
# x86_64 job run on ubuntu-22.04 and here we can install kernel-headers
|
||||
- name: Install dependencies for falco-driver-loader tests on x86
|
||||
if: ${{ inputs.arch == 'x86_64' }}
|
||||
- name: Install dependencies for falco-driver-loader tests
|
||||
run: |
|
||||
sudo apt update -y
|
||||
sudo apt install -y --no-install-recommends build-essential clang make llvm gcc dkms linux-headers-$(uname -r)
|
||||
sudo apt install -y --no-install-recommends build-essential clang make llvm gcc dkms
|
||||
|
||||
- name: Install kernel headers (workaround)
|
||||
if: inputs.arch == 'aarch64'
|
||||
run: |
|
||||
sudo mkdir -p /usr/src
|
||||
sudo git clone --depth 1 --branch v$(uname -r) git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git /usr/src/linux
|
||||
sudo rm /lib/modules/$(uname -r)/build
|
||||
sudo ln -s /usr/src/linux-headers-$(uname -r)/ /lib/modules/$(uname -r)/build
|
||||
sudo rm /lib/modules/$(uname -r)/source
|
||||
sudo ln -s /usr/src/linux-headers-$(uname -r)/ /lib/modules/$(uname -r)/source
|
||||
|
||||
- name: Install kernel headers
|
||||
if: inputs.arch == 'x86_64'
|
||||
run: |
|
||||
sudo apt install -y --no-install-recommends linux-headers-$(uname -r)
|
||||
|
||||
- name: Install go-junit-report
|
||||
run: |
|
||||
@@ -63,28 +76,41 @@ jobs:
|
||||
go generate ./...
|
||||
popd
|
||||
|
||||
# Right now we are not able to install kernel-headers on our ARM64 self-hosted runner.
|
||||
# For this reason, we disable the falco-driver-loader tests, which require kernel headers on the host.
|
||||
- name: Run regression tests
|
||||
- name: Run Falco regression tests
|
||||
env:
|
||||
# fixme(leogr): this is a workaround for https://github.com/falcosecurity/falco/issues/2784
|
||||
HOST_ROOT: ""
|
||||
run: |
|
||||
pushd submodules/falcosecurity-testing
|
||||
./build/falco.test -falco-static=${{ inputs.static && 'true' || 'false' }} -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
if ${{ inputs.static && 'false' || 'true' }}; then
|
||||
./build/falcoctl.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
./build/k8saudit.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
if ${{ inputs.arch == 'x86_64' && 'true' || 'false' }}; then
|
||||
sudo ./build/falco-driver-loader.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
cat ./report.txt | go-junit-report -set-exit-code > report.xml
|
||||
popd
|
||||
|
||||
- name: Run Falcoctl regression tests
|
||||
env:
|
||||
HOST_ROOT: ""
|
||||
run: |
|
||||
pushd submodules/falcosecurity-testing
|
||||
./build/falcoctl.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
popd
|
||||
|
||||
- name: Run K8saudit regression tests
|
||||
env:
|
||||
HOST_ROOT: ""
|
||||
run: |
|
||||
pushd submodules/falcosecurity-testing
|
||||
./build/k8saudit.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
popd
|
||||
|
||||
- name: Run Falco driver loader regression tests
|
||||
env:
|
||||
HOST_ROOT: ""
|
||||
run: |
|
||||
pushd submodules/falcosecurity-testing
|
||||
sudo ./build/falco-driver-loader.test -test.timeout=90s -test.v
|
||||
popd
|
||||
|
||||
- name: Test Summary
|
||||
if: always() # run this even if previous step fails
|
||||
uses: test-summary/action@v2
|
||||
uses: test-summary/action@62bc5c68de2a6a0d02039763b8c754569df99e3f # v2.1
|
||||
with:
|
||||
paths: "submodules/falcosecurity-testing/report.xml"
|
||||
show: "fail"
|
||||
|
||||
79
.github/workflows/scorecard.yaml
vendored
Normal file
79
.github/workflows/scorecard.yaml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# This workflow uses actions that are not certified by GitHub. They are provided
|
||||
# by a third-party and are governed by separate terms of service, privacy
|
||||
# policy, and support documentation.
|
||||
|
||||
name: Scorecard supply-chain security
|
||||
on:
|
||||
# To guarantee Maintained check is occasionally updated. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
||||
schedule:
|
||||
# Weekly on Mondays at 00:00.
|
||||
- cron: '0 0 * * 1'
|
||||
|
||||
# The OSSF recommendation encourages to enable branch protection rules trigger
|
||||
# to update the scorecard
|
||||
# (https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection)
|
||||
# but due to our GitHub org management this check is triggered too often and is
|
||||
# therefore disabled.
|
||||
# branch_protection_rule:
|
||||
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecard analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Needed to publish results and get a badge (see publish_results below).
|
||||
id-token: write
|
||||
# Uncomment the permissions below if installing in a private repository.
|
||||
# contents: read
|
||||
# actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecard on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
|
||||
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
||||
|
||||
# Public repositories:
|
||||
# - Publish results to OpenSSF REST API for easy access by consumers
|
||||
# - Allows the repository to include the Scorecard badge.
|
||||
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories:
|
||||
# - `publish_results` will always be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
4
.github/workflows/staticanalysis.yaml
vendored
4
.github/workflows/staticanalysis.yaml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout ⤵️
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
make -j4 cppcheck_htmlreport
|
||||
|
||||
- name: Upload reports ⬆️
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: static-analysis-reports
|
||||
path: ./build/static-analysis-reports
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@
|
||||
.vscode/*
|
||||
|
||||
*.idea*
|
||||
CMakeUserPresets.json
|
||||
|
||||
@@ -72,6 +72,8 @@ This is a list of production adopters of Falco (in alphabetical order):
|
||||
|
||||
* [Thales Group](https://www.thalesgroup.com) Thales is a global technology leader with more than 81,000 employees on five continents. The Thales Group is investing in digital and “deep tech” innovations – Big Data, artificial intelligence, connectivity, cybersecurity and quantum technology – to build a future we can all trust. In the past few years, the Cloud-Native paradigms and its frameworks and tools have challenged the way applications and services are developed, delivered, and instantiated. All sorts of services are container-based workloads managed by higher level layers of orchestration such as the Kubernetes environment. Thales is committed to develop Cloud-Native services and to provide its customers with security features that ensure their applications and services are protected against cyber threats. Falco is a framework that can help Thales' products and services reach the level of trust, security and safety our clients need.
|
||||
|
||||
* [Thought Machine](https://www.thoughtmachine.net) Thought Machine builds Vault Core and Vault Payments: cloud-native core and payments technology enabling banks and fintechs to remain competitive and flourish into the future. Vault Core and Vault Payments are the foundation layer of a bank's technology stack. They can run any bank, any product, and any payment set. Thought Machine uses Falco to perform cloud agnostic real time detections of suspicious container behaviour.
|
||||
|
||||
* [Vinted](https://vinted.com/) Vinted uses Falco to continuously monitor container activities, identifying security threats, and ensuring compliance. The container-native approach, rule-based real-time threat detection, community support, extensibility, and compliance capabilities are the main factors why we chose it to enhance Vinted Kubernetes security. Falco Sidekick is used to send critical and warning severity alerts to our incident management solution (RTIR).
|
||||
|
||||
* [Xenit AB](https://xenit.se/contact/) Xenit is a growth company with services within cloud and digital transformation. We provide an open-source Kubernetes framework that we leverage to help our customers get their applications to production as quickly and as securely as possible. We use Falco's detection capabilities to identify anomalous behaviour within our clusters in both Azure and AWS.
|
||||
@@ -86,6 +88,8 @@ This is a list of production adopters of Falco (in alphabetical order):
|
||||
|
||||
* [StackRox](https://stackrox.io) is the industry’s first Kubernetes-native security platform enabling organizations to build, deploy, and run cloud-native applications securely. The platform works with Kubernetes environments and integrates with DevOps and security tools, enabling teams to operationalize and secure their supply chain, infrastructure, and workloads. StackRox aims to harness containerized applications’ development speed while giving operations and security teams greater context and risk profiling. StackRox leverages cloud-native principles and declarative artifacts to automate DevSecOps best practices.
|
||||
|
||||
* [Wireshark](https://www.wireshark.org) is the world's most powerful and popular network protocol analyzer. The Wireshark team is combining Wireshark's features and Falco libs to create Logray, a cloud and system log analyzer with advanced filtering, capture, and scripting capabilities.
|
||||
|
||||
## Adding a name
|
||||
|
||||
If you would like to add your name to this file, submit a pull request with your change.
|
||||
|
||||
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,9 +1,30 @@
|
||||
# Change Log
|
||||
|
||||
## v0.36.2
|
||||
|
||||
Released on 2023-10-27
|
||||
|
||||
NO CHANGES IN FALCO, ALL CHANGES IN LIBS.
|
||||
|
||||
|
||||
## v0.36.1
|
||||
|
||||
Released on 2023-10-16
|
||||
|
||||
### Major Changes
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* feat(userspace): remove experimental outputs queue recovery strategies [[#2863](https://github.com/falcosecurity/falco/pull/2863)] - [@incertum](https://github.com/incertum)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(userspace/falco): timer_delete() workaround due to bug in older GLIBC [[#2851](https://github.com/falcosecurity/falco/pull/2851)] - [@incertum](https://github.com/incertum)
|
||||
|
||||
|
||||
## v0.36.0
|
||||
|
||||
Released on 2023-09-25
|
||||
Released on 2023-09-26
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
|
||||
@@ -21,7 +21,11 @@ option(MINIMAL_BUILD "Build a minimal version of Falco, containing only the engi
|
||||
option(MUSL_OPTIMIZED_BUILD "Enable if you want a musl optimized build" OFF)
|
||||
option(BUILD_FALCO_UNIT_TESTS "Build falco unit tests" OFF)
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
if(WIN32)
|
||||
set(CPACK_GENERATOR "NSIS") # this needs NSIS installed, and available
|
||||
elseif (APPLE)
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
elseif(EMSCRIPTEN)
|
||||
set(USE_BUNDLED_DEPS ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_DRIVER OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_DKMS OFF CACHE BOOL "" FORCE)
|
||||
@@ -53,9 +57,6 @@ if (${EP_UPDATE_DISCONNECTED})
|
||||
PROPERTY EP_UPDATE_DISCONNECTED TRUE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
# Elapsed time
|
||||
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add a flag to enable this
|
||||
|
||||
@@ -83,56 +84,7 @@ else()
|
||||
set(FALCO_TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
if(NOT FALCO_EXTRA_DEBUG_FLAGS)
|
||||
set(FALCO_EXTRA_DEBUG_FLAGS "-D_DEBUG")
|
||||
endif()
|
||||
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "debug")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_DEBUG_FLAGS} ${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_BUILD_TYPE "release")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
add_definitions(-DBUILD_TYPE_RELEASE)
|
||||
endif()
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if(MINIMAL_BUILD)
|
||||
set(MINIMAL_BUILD_FLAGS "-DMINIMAL_BUILD")
|
||||
endif()
|
||||
|
||||
if(MUSL_OPTIMIZED_BUILD)
|
||||
set(MUSL_FLAGS "-static -Os -fPIE -pie")
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
endif()
|
||||
|
||||
# explicitly set hardening flags
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(FALCO_SECURITY_FLAGS "")
|
||||
if(NOT EMSCRIPTEN)
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -Wl,-z,relro,-z,now -fstack-protector-strong")
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||
endif()
|
||||
|
||||
set(CMAKE_COMMON_FLAGS "${FALCO_SECURITY_FLAGS} -Wall -ggdb ${FALCO_EXTRA_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
|
||||
|
||||
if(BUILD_WARNINGS_AS_ERRORS)
|
||||
set(CMAKE_SUPPRESSED_WARNINGS
|
||||
"-Wno-unused-parameter -Wno-unused-variable -Wno-unused-but-set-variable -Wno-missing-field-initializers -Wno-sign-compare -Wno-type-limits -Wno-implicit-fallthrough -Wno-format-truncation -Wno-stringop-truncation -Wno-stringop-overflow -Wno-restrict"
|
||||
)
|
||||
set(CMAKE_COMMON_FLAGS "${CMAKE_COMMON_FLAGS} -Wextra -Werror ${CMAKE_SUPPRESSED_WARNINGS}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_COMMON_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-std=c++17 ${CMAKE_COMMON_FLAGS} -Wno-class-memaccess")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${FALCO_EXTRA_DEBUG_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${FALCO_EXTRA_DEBUG_FLAGS}")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG")
|
||||
include(CompilerFlags)
|
||||
|
||||
set(PACKAGE_NAME "falco")
|
||||
set(DRIVER_NAME "falco")
|
||||
@@ -164,9 +116,6 @@ include(falcosecurity-libs)
|
||||
# compute FALCO_VERSION (depends on libs)
|
||||
include(falco-version)
|
||||
|
||||
# jq
|
||||
include(jq)
|
||||
|
||||
# nlohmann-json
|
||||
include(njson)
|
||||
|
||||
@@ -192,8 +141,8 @@ if (NOT EMSCRIPTEN)
|
||||
include(tbb)
|
||||
endif()
|
||||
|
||||
include(zlib)
|
||||
if (NOT MINIMAL_BUILD)
|
||||
include(zlib)
|
||||
if (NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN)
|
||||
include(cares)
|
||||
include(protobuf)
|
||||
@@ -203,7 +152,16 @@ if (NOT MINIMAL_BUILD)
|
||||
endif()
|
||||
|
||||
# Installation
|
||||
install(FILES falco.yaml DESTINATION "${FALCO_ETC_DIR}" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
if(WIN32)
|
||||
set(FALCO_INSTALL_CONF_FILE "%PROGRAMFILES%/${PACKAGE_NAME}-${FALCO_VERSION}/etc/falco/falco.yaml")
|
||||
install(FILES falco.yaml DESTINATION etc/falco/ COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
elseif(APPLE)
|
||||
set(FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml")
|
||||
install(FILES falco.yaml DESTINATION etc/falco/ COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
else()
|
||||
set(FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml")
|
||||
install(FILES falco.yaml DESTINATION "${FALCO_ETC_DIR}" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
endif()
|
||||
|
||||
if(NOT MINIMAL_BUILD)
|
||||
# Coverage
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://github.com/falcosecurity/falco/releases/latest) [](https://github.com/falcosecurity/falco/releases/latest) [](COPYING) [](https://falco.org/docs)
|
||||
|
||||
[](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#core-scope) [](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable) [](https://bestpractices.coreinfrastructure.org/projects/2317)
|
||||
[](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#core-scope) [](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable) [](https://bestpractices.coreinfrastructure.org/projects/2317) <a href="https://actuated.dev/"><img alt="Arm CI sponsored by Actuated" src="https://docs.actuated.dev/images/actuated-badge.png" width="120px"></img></a>
|
||||
|
||||
[](https://falco.org)
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ else()
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
endif()
|
||||
|
||||
# Built packages will include only the following components
|
||||
set(CPACK_INSTALL_CMAKE_PROJECTS
|
||||
"${CMAKE_CURRENT_BINARY_DIR};${FALCO_COMPONENT_NAME};${FALCO_COMPONENT_NAME};/"
|
||||
|
||||
101
cmake/modules/CompilerFlags.cmake
Normal file
101
cmake/modules/CompilerFlags.cmake
Normal file
@@ -0,0 +1,101 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 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(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(NOT FALCO_EXTRA_DEBUG_FLAGS)
|
||||
set(FALCO_EXTRA_DEBUG_FLAGS "-D_DEBUG")
|
||||
endif()
|
||||
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "debug")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_DEBUG_FLAGS} ${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_BUILD_TYPE "release")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
add_definitions(-DBUILD_TYPE_RELEASE)
|
||||
endif()
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if(MINIMAL_BUILD)
|
||||
set(MINIMAL_BUILD_FLAGS "-DMINIMAL_BUILD")
|
||||
endif()
|
||||
|
||||
if(MUSL_OPTIMIZED_BUILD)
|
||||
set(MUSL_FLAGS "-static -Os -fPIE -pie")
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
endif()
|
||||
|
||||
# explicitly set hardening flags
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(FALCO_SECURITY_FLAGS "")
|
||||
if(LINUX)
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -Wl,-z,relro,-z,now -fstack-protector-strong")
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT MSVC)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||
endif()
|
||||
|
||||
set(CMAKE_COMMON_FLAGS "${FALCO_SECURITY_FLAGS} -Wall -ggdb ${FALCO_EXTRA_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
|
||||
|
||||
if(BUILD_WARNINGS_AS_ERRORS)
|
||||
set(CMAKE_SUPPRESSED_WARNINGS
|
||||
"-Wno-unused-parameter -Wno-unused-variable -Wno-unused-but-set-variable -Wno-missing-field-initializers -Wno-sign-compare -Wno-type-limits -Wno-implicit-fallthrough -Wno-format-truncation -Wno-stringop-truncation -Wno-stringop-overflow -Wno-restrict"
|
||||
)
|
||||
set(CMAKE_COMMON_FLAGS "${CMAKE_COMMON_FLAGS} -Wextra -Werror ${CMAKE_SUPPRESSED_WARNINGS}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_COMMON_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-std=c++17 ${CMAKE_COMMON_FLAGS} -Wno-class-memaccess")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${FALCO_EXTRA_DEBUG_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${FALCO_EXTRA_DEBUG_FLAGS}")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG")
|
||||
|
||||
else() # MSVC
|
||||
set(MINIMAL_BUILD ON)
|
||||
|
||||
# The WIN32_LEAN_AND_MEAN define avoids possible macro pollution
|
||||
# when a libsinsp consumer includes the windows.h header.
|
||||
# See: https://stackoverflow.com/a/28380820
|
||||
|
||||
add_compile_definitions(
|
||||
_HAS_STD_BYTE=0
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
WIN32
|
||||
MINIMAL_BUILD
|
||||
WIN32_LEAN_AND_MEAN
|
||||
)
|
||||
|
||||
set(FALCOSECURITY_LIBS_COMMON_FLAGS "/EHsc /W3 /Zi /std:c++17")
|
||||
set(FALCOSECURITY_LIBS_DEBUG_FLAGS "/MTd /Od")
|
||||
set(FALCOSECURITY_LIBS_RELEASE_FLAGS "/MT")
|
||||
|
||||
set(CMAKE_C_FLAGS "${FALCOSECURITY_LIBS_COMMON_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${FALCOSECURITY_LIBS_COMMON_FLAGS}")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${FALCOSECURITY_LIBS_DEBUG_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${FALCOSECURITY_LIBS_DEBUG_FLAGS}")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "${FALCOSECURITY_LIBS_RELEASE_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${FALCOSECURITY_LIBS_RELEASE_FLAGS}")
|
||||
|
||||
endif()
|
||||
@@ -34,8 +34,8 @@ else()
|
||||
# In case you want to test against another driver version (or branch, or commit) just pass the variable -
|
||||
# ie., `cmake -DDRIVER_VERSION=dev ..`
|
||||
if(NOT DRIVER_VERSION)
|
||||
set(DRIVER_VERSION "6.0.1+driver")
|
||||
set(DRIVER_CHECKSUM "SHA256=2b4412b5053c8ed5bd1a9de745faa16ec0210dc65dc858af65951d4c8d22207c")
|
||||
set(DRIVER_VERSION "ea23169c13df2ce5d8ba7d6faecdaa65f36140cb")
|
||||
set(DRIVER_CHECKSUM "SHA256=c84c80a9a2241667e1c0be7a611f071c9b0264ac81b98103d2272b939337d02f")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
|
||||
@@ -16,14 +16,14 @@ include(ExternalProject)
|
||||
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} FALCOCTL_SYSTEM_NAME)
|
||||
|
||||
set(FALCOCTL_VERSION "0.6.2")
|
||||
set(FALCOCTL_VERSION "0.7.0-beta5")
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "amd64")
|
||||
set(FALCOCTL_HASH "2d06d7577dbae91fb085f71477ff6e22076a815978bddd036984fa077236a515")
|
||||
set(FALCOCTL_HASH "e08cdd3bed96bda2e45f54d86aec0f1ad986963ff30624578283b218829df225")
|
||||
else() # aarch64
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "arm64")
|
||||
set(FALCOCTL_HASH "0b711a1b3499f479d999f4f4d2c94fc4f0bc23a2506711b613e6eedb0593631b")
|
||||
set(FALCOCTL_HASH "582b6b73f77cfdf66dbcddadaa1073fa1802f24bd1670c1cf578e524fd3e8486")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
|
||||
@@ -26,17 +26,17 @@ if(FALCOSECURITY_LIBS_SOURCE_DIR)
|
||||
else()
|
||||
# FALCOSECURITY_LIBS_REPO accepts a repository name (<org name>/<repo name>) alternative to the falcosecurity/libs repository.
|
||||
# In case you want to test against a fork of falcosecurity/libs just pass the variable -
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_REPO=<your-gh-handle>/libs ..`
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_REPO=<your-gh-handle>/libs ..`
|
||||
if (NOT FALCOSECURITY_LIBS_REPO)
|
||||
set(FALCOSECURITY_LIBS_REPO "Andreagit97/libs")
|
||||
set(FALCOSECURITY_LIBS_REPO "falcosecurity/libs")
|
||||
endif()
|
||||
|
||||
# FALCOSECURITY_LIBS_VERSION accepts a git reference (branch name, commit hash, or tag) to the falcosecurity/libs repository.
|
||||
# In case you want to test against another falcosecurity/libs version (or branch, or commit) just pass the variable -
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "8b3375596fec7b02ac403dc4158c5bcdf037cf65")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=587ac097e1ef35ba70ddd3403e569d377a0c4a5935cb17c9ee8f9521dac4140c")
|
||||
set(FALCOSECURITY_LIBS_VERSION "ea23169c13df2ce5d8ba7d6faecdaa65f36140cb")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=c84c80a9a2241667e1c0be7a611f071c9b0264ac81b98103d2272b939337d02f")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
@@ -84,10 +84,11 @@ set(CREATE_TEST_TARGETS OFF CACHE BOOL "")
|
||||
set(BUILD_LIBSCAP_EXAMPLES OFF CACHE BOOL "")
|
||||
|
||||
set(USE_BUNDLED_TBB ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_B64 ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_JSONCPP ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_NLOHMANN_JSON ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_VALIJSON ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_RE2 ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_UTHASH ON CACHE BOOL "")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${FALCOSECURITY_LIBS_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
@@ -95,12 +96,15 @@ include(CheckSymbolExists)
|
||||
check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY)
|
||||
|
||||
if(HAVE_STRLCPY)
|
||||
message(STATUS "Existing strlcpy found, will *not* use local definition by setting -DHAVE_STRLCPY.")
|
||||
message(STATUS "Existing strlcpy and strlcat found, will *not* use local definition by setting -DHAVE_STRLCPY and -DHAVE_STRLCAT.")
|
||||
add_definitions(-DHAVE_STRLCPY)
|
||||
add_definitions(-DHAVE_STRLCAT)
|
||||
else()
|
||||
message(STATUS "No strlcpy found, will use local definition")
|
||||
message(STATUS "No strlcpy and strlcat found, will use local definition")
|
||||
endif()
|
||||
|
||||
include(driver)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
include(driver)
|
||||
endif()
|
||||
include(libscap)
|
||||
include(libsinsp)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 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(LIBYAML_SRC "${PROJECT_BINARY_DIR}/libyaml-prefix/src/libyaml")
|
||||
set(LIBYAML_INSTALL_DIR "${LIBYAML_SRC}/target")
|
||||
message(STATUS "Using bundled libyaml in '${LIBYAML_SRC}'")
|
||||
set(LIBYAML_LIB "${LIBYAML_SRC}/src/.libs/libyaml.a")
|
||||
externalproject_add(
|
||||
libyaml
|
||||
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
|
||||
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
|
||||
CONFIGURE_COMMAND ./configure --prefix=${LIBYAML_INSTALL_DIR} CFLAGS=-fPIC CPPFLAGS=-fPIC --enable-static=true --enable-shared=false
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${LIBYAML_LIB}
|
||||
INSTALL_COMMAND ${CMD_MAKE} install
|
||||
)
|
||||
@@ -12,24 +12,15 @@
|
||||
# specific language governing permissions and limitations under the License.
|
||||
#
|
||||
|
||||
#
|
||||
# nlohmann-json
|
||||
#
|
||||
if(NJSON_INCLUDE)
|
||||
# Adding the custom target we can use it with `add_dependencies()`
|
||||
if(NOT TARGET njson)
|
||||
add_custom_target(njson)
|
||||
endif()
|
||||
else()
|
||||
# We always use the bundled version
|
||||
set(NJSON_SRC "${PROJECT_BINARY_DIR}/njson-prefix/src/njson")
|
||||
set(NJSON_INCLUDE "${NJSON_SRC}/single_include")
|
||||
ExternalProject_Add(
|
||||
njson
|
||||
if(USE_BUNDLED_NLOHMANN_JSON)
|
||||
ExternalProject_Add(njson
|
||||
URL "https://github.com/nlohmann/json/archive/v3.3.0.tar.gz"
|
||||
URL_HASH "SHA256=2fd1d207b4669a7843296c41d3b6ac5b23d00dec48dba507ba051d14564aa801"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
message(STATUS "Using bundled nlohmann-json in '${NJSON_SRC}'")
|
||||
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/njson-prefix -DJSON_BuildTests=OFF -DBUILD_TESTING=OFF
|
||||
)
|
||||
|
||||
set(nlohmann_json_DIR ${PROJECT_BINARY_DIR}/njson-prefix/include)
|
||||
else()
|
||||
find_package(nlohmann_json CONFIG REQUIRED)
|
||||
add_custom_target(njson)
|
||||
endif()
|
||||
|
||||
@@ -34,7 +34,11 @@ set(FALCOSECURITY_RULES_LOCAL_PATH "${PROJECT_BINARY_DIR}/falcosecurity-rules-lo
|
||||
file(WRITE "${FALCOSECURITY_RULES_LOCAL_PATH}" "# Your custom rules!\n")
|
||||
|
||||
if(NOT DEFINED FALCO_ETC_DIR)
|
||||
set(FALCO_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/falco")
|
||||
set(FALCO_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/falco")
|
||||
endif()
|
||||
|
||||
if(WIN32 OR APPLE)
|
||||
set(FALCO_ETC_DIR "etc/falco")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED FALCO_RULES_DEST_FILENAME)
|
||||
|
||||
@@ -24,13 +24,18 @@ if(NOT USE_BUNDLED_DEPS)
|
||||
else()
|
||||
set(YAMLCPP_SRC "${PROJECT_BINARY_DIR}/yamlcpp-prefix/src/yamlcpp")
|
||||
message(STATUS "Using bundled yaml-cpp in '${YAMLCPP_SRC}'")
|
||||
set(YAMLCPP_LIB "${YAMLCPP_SRC}/libyaml-cpp.a")
|
||||
if(NOT WIN32)
|
||||
set(YAMLCPP_LIB "${YAMLCPP_SRC}/libyaml-cpp.a")
|
||||
else()
|
||||
set(YAMLCPP_LIB "${YAMLCPP_SRC}/${CMAKE_BUILD_TYPE}/yaml-cpp.lib")
|
||||
endif()
|
||||
set(YAMLCPP_INCLUDE_DIR "${YAMLCPP_SRC}/include")
|
||||
ExternalProject_Add(
|
||||
yamlcpp
|
||||
URL "https://github.com/jbeder/yaml-cpp/archive/yaml-cpp-0.6.2.tar.gz"
|
||||
URL_HASH "SHA256=e4d8560e163c3d875fd5d9e5542b5fd5bec810febdcba61481fe5fc4e6b1fd05"
|
||||
URL "https://github.com/jbeder/yaml-cpp/archive/yaml-cpp-0.7.0.tar.gz"
|
||||
URL_HASH "SHA256=43e6a9fcb146ad871515f0d0873947e5d497a1c9c60c58cb102a97b47208b7c3"
|
||||
BUILD_BYPRODUCTS ${YAMLCPP_LIB}
|
||||
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DYAML_MSVC_SHARED_RT=Off -DYAML_BUILD_SHARED_LIBS=Off -DYAML_CPP_BUILD_TESTS=Off -DYAML_CPP_BUILD_TOOLS=OFF -DYAML_CPP_BUILD_CONTRIB=OFF -DCMAKE_DEBUG_POSTFIX=''
|
||||
BUILD_IN_SOURCE 1
|
||||
INSTALL_COMMAND "")
|
||||
endif()
|
||||
|
||||
@@ -18,6 +18,28 @@
|
||||
#
|
||||
|
||||
|
||||
print_usage() {
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " 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 falcosecurity/falco-driver-loader-legacy:latest [driver] [options]"
|
||||
echo ""
|
||||
echo "Available drivers:"
|
||||
echo " kmod kernel module (default)"
|
||||
echo " ebpf eBPF probe"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help show this help message"
|
||||
echo " --clean try to remove an already present driver installation"
|
||||
echo " --compile try to compile the driver locally (default true)"
|
||||
echo " --download try to download a prebuilt driver (default true)"
|
||||
echo " --print-env skip execution and print env variables for other tools to consume"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " FALCOCTL_DRIVER_REPOS specify different URL(s) where to look for prebuilt Falco drivers (comma separated)"
|
||||
echo " FALCOCTL_DRIVER_NAME specify a different name for the driver"
|
||||
echo ""
|
||||
}
|
||||
|
||||
echo "* Setting up /usr/src links from host"
|
||||
|
||||
for i in "$HOST_ROOT/usr/src"/*
|
||||
@@ -26,4 +48,64 @@ do
|
||||
ln -s "$i" "/usr/src/$base"
|
||||
done
|
||||
|
||||
/usr/bin/falco-driver-loader "$@"
|
||||
ENABLE_COMPILE="false"
|
||||
ENABLE_DOWNLOAD="false"
|
||||
has_driver=
|
||||
has_opts=
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
kmod|ebpf)
|
||||
if [ -n "$has_driver" ]; then
|
||||
>&2 echo "Only one driver per invocation"
|
||||
print_usage
|
||||
exit 1
|
||||
else
|
||||
/usr/bin/falcoctl driver config --type $1
|
||||
has_driver="true"
|
||||
fi
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--clean)
|
||||
/usr/bin/falcoctl driver cleanup
|
||||
exit 0
|
||||
;;
|
||||
--compile)
|
||||
ENABLE_COMPILE="true"
|
||||
has_opts="true"
|
||||
;;
|
||||
--download)
|
||||
ENABLE_DOWNLOAD="true"
|
||||
has_opts="true"
|
||||
;;
|
||||
--source-only)
|
||||
>&2 echo "Support dropped in Falco 0.37.0."
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
--print-env)
|
||||
/usr/bin/falcoctl driver printenv
|
||||
exit 0
|
||||
;;
|
||||
--*)
|
||||
>&2 echo "Unknown option: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
>&2 echo "Unknown driver: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "$has_opts" ]; then
|
||||
ENABLE_COMPILE="true"
|
||||
ENABLE_DOWNLOAD="true"
|
||||
fi
|
||||
|
||||
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD
|
||||
|
||||
@@ -18,6 +18,28 @@
|
||||
#
|
||||
|
||||
|
||||
print_usage() {
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " 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 falcosecurity/falco-driver-loader:latest [driver] [options]"
|
||||
echo ""
|
||||
echo "Available drivers:"
|
||||
echo " kmod kernel module (default)"
|
||||
echo " ebpf eBPF probe"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help show this help message"
|
||||
echo " --clean try to remove an already present driver installation"
|
||||
echo " --compile try to compile the driver locally (default true)"
|
||||
echo " --download try to download a prebuilt driver (default true)"
|
||||
echo " --print-env skip execution and print env variables for other tools to consume"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " FALCOCTL_DRIVER_REPOS specify different URL(s) where to look for prebuilt Falco drivers (comma separated)"
|
||||
echo " FALCOCTL_DRIVER_NAME specify a different name for the driver"
|
||||
echo ""
|
||||
}
|
||||
|
||||
echo "* Setting up /usr/src links from host"
|
||||
|
||||
for i in "$HOST_ROOT/usr/src"/*
|
||||
@@ -26,4 +48,64 @@ do
|
||||
ln -s "$i" "/usr/src/$base"
|
||||
done
|
||||
|
||||
/usr/bin/falco-driver-loader "$@"
|
||||
ENABLE_COMPILE="false"
|
||||
ENABLE_DOWNLOAD="false"
|
||||
has_driver=
|
||||
has_opts=
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
kmod|ebpf)
|
||||
if [ -n "$has_driver" ]; then
|
||||
>&2 echo "Only one driver per invocation"
|
||||
print_usage
|
||||
exit 1
|
||||
else
|
||||
/usr/bin/falcoctl driver config --type $1
|
||||
has_driver="true"
|
||||
fi
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--clean)
|
||||
/usr/bin/falcoctl driver cleanup
|
||||
exit 0
|
||||
;;
|
||||
--compile)
|
||||
ENABLE_COMPILE="true"
|
||||
has_opts="true"
|
||||
;;
|
||||
--download)
|
||||
ENABLE_DOWNLOAD="true"
|
||||
has_opts="true"
|
||||
;;
|
||||
--source-only)
|
||||
>&2 echo "Support dropped in Falco 0.37.0."
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
--print-env)
|
||||
/usr/bin/falcoctl driver printenv
|
||||
exit 0
|
||||
;;
|
||||
--*)
|
||||
>&2 echo "Unknown option: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
>&2 echo "Unknown driver: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "$has_opts" ]; then
|
||||
ENABLE_COMPILE="true"
|
||||
ENABLE_DOWNLOAD="true"
|
||||
fi
|
||||
|
||||
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD
|
||||
|
||||
@@ -19,17 +19,26 @@ RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
bc \
|
||||
bison \
|
||||
ca-certificates \
|
||||
clang \
|
||||
curl \
|
||||
dkms \
|
||||
dwarves \
|
||||
flex \
|
||||
gcc \
|
||||
gcc-11 \
|
||||
gnupg2 \
|
||||
jq \
|
||||
libelf1 \
|
||||
libc6-dev \
|
||||
libelf-dev \
|
||||
libssl-dev \
|
||||
llvm \
|
||||
make \
|
||||
netcat-openbsd \
|
||||
patchelf \
|
||||
xz-utils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -s https://falco.org/repo/falcosecurity-packages.asc | apt-key add - \
|
||||
|
||||
@@ -17,6 +17,29 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
|
||||
print_usage() {
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " 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 -e 'FALCO_DRIVER_LOADER_OPTIONS=[driver] [options]' falcosecurity/falco:latest"
|
||||
echo ""
|
||||
echo "Available FALCO_DRIVER_LOADER_OPTIONS drivers:"
|
||||
echo " kmod kernel module (default)"
|
||||
echo " ebpf eBPF probe"
|
||||
echo ""
|
||||
echo "FALCO_DRIVER_LOADER_OPTIONS options:"
|
||||
echo " --help show this help message"
|
||||
echo " --clean try to remove an already present driver installation"
|
||||
echo " --compile try to compile the driver locally (default true)"
|
||||
echo " --download try to download a prebuilt driver (default true)"
|
||||
echo " --print-env skip execution and print env variables for other tools to consume"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " FALCOCTL_DRIVER_REPOS specify different URL(s) where to look for prebuilt Falco drivers (comma separated)"
|
||||
echo " FALCOCTL_DRIVER_NAME specify a different name for the driver"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Set the SKIP_DRIVER_LOADER variable to skip loading the driver
|
||||
|
||||
if [[ -z "${SKIP_DRIVER_LOADER}" ]]; then
|
||||
@@ -29,9 +52,69 @@ if [[ -z "${SKIP_DRIVER_LOADER}" ]]; then
|
||||
done
|
||||
|
||||
# convert the optional space-separated env variable FALCO_DRIVER_LOADER_OPTIONS to array, prevent
|
||||
# shell expansion and use it as argument list for falco-driver-loader
|
||||
# shell expansion and use it as argument list for falcoctl
|
||||
read -a falco_driver_loader_option_arr <<< $FALCO_DRIVER_LOADER_OPTIONS
|
||||
/usr/bin/falco-driver-loader "${falco_driver_loader_option_arr[@]}"
|
||||
|
||||
ENABLE_COMPILE="false"
|
||||
ENABLE_DOWNLOAD="false"
|
||||
has_driver=
|
||||
has_opts=
|
||||
for opt in "${falco_driver_loader_option_arr[@]}"
|
||||
do
|
||||
case "$opt" in
|
||||
kmod|ebpf)
|
||||
if [ -n "$has_driver" ]; then
|
||||
>&2 echo "Only one driver per invocation"
|
||||
print_usage
|
||||
exit 1
|
||||
else
|
||||
/usr/bin/falcoctl driver config --type $opt
|
||||
has_driver="true"
|
||||
fi
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--clean)
|
||||
/usr/bin/falcoctl driver cleanup
|
||||
exit 0
|
||||
;;
|
||||
--compile)
|
||||
ENABLE_COMPILE="true"
|
||||
has_opts="true"
|
||||
;;
|
||||
--download)
|
||||
ENABLE_DOWNLOAD="true"
|
||||
has_opts="true"
|
||||
;;
|
||||
--source-only)
|
||||
>&2 echo "Support dropped in Falco 0.37.0."
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
--print-env)
|
||||
/usr/bin/falcoctl driver printenv
|
||||
exit 0
|
||||
;;
|
||||
--*)
|
||||
>&2 echo "Unknown option: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
>&2 echo "Unknown driver: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ -z "$has_opts" ]; then
|
||||
ENABLE_COMPILE="true"
|
||||
ENABLE_DOWNLOAD="true"
|
||||
fi
|
||||
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD
|
||||
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -15,7 +15,7 @@ RUN curl -L -o falco.tar.gz \
|
||||
tar -xvf falco.tar.gz && \
|
||||
rm -f falco.tar.gz && \
|
||||
mv falco-${FALCO_VERSION}-$(uname -m) falco && \
|
||||
rm -rf /falco/usr/src/falco-* /falco/usr/bin/falco-driver-loader
|
||||
rm -rf /falco/usr/src/falco-*
|
||||
|
||||
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
|
||||
|
||||
@@ -16,7 +16,7 @@ RUN FALCO_VERSION_URLENCODED=$(echo -n ${FALCO_VERSION}|jq -sRr @uri) && \
|
||||
tar -xvf falco.tar.gz && \
|
||||
rm -f falco.tar.gz && \
|
||||
mv falco-${FALCO_VERSION}-$(uname -m) falco && \
|
||||
rm -rf /falco/usr/src/falco-* /falco/usr/bin/falco-driver-loader
|
||||
rm -rf /falco/usr/src/falco-*
|
||||
|
||||
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
|
||||
|
||||
318
falco.yaml
318
falco.yaml
@@ -27,6 +27,8 @@
|
||||
# (Falco environment variables)
|
||||
# Falco rules files
|
||||
# rules_file
|
||||
# Falco engine
|
||||
# engine
|
||||
# Falco plugins
|
||||
# load_plugins
|
||||
# plugins
|
||||
@@ -63,13 +65,10 @@
|
||||
# syscall_event_drops
|
||||
# metrics
|
||||
# Falco performance tuning (advanced)
|
||||
# syscall_buf_size_preset
|
||||
# syscall_drop_failed_exit
|
||||
# syscall_buf_size_preset [DEPRECATED]
|
||||
# syscall_drop_failed_exit [DEPRECATED]
|
||||
# base_syscalls
|
||||
# modern_bpf.cpus_for_each_syscall_buffer
|
||||
# Falco cloud orchestration systems integration
|
||||
# metadata_download
|
||||
# (Guidance for Kubernetes container engine command-line args settings)
|
||||
# modern_bpf.cpus_for_each_syscall_buffer [DEPRECATED]
|
||||
|
||||
|
||||
################################
|
||||
@@ -97,7 +96,7 @@
|
||||
# - "HOST_ROOT": Specifies the prefix to the underlying host `/proc` filesystem
|
||||
# when deploying Falco over a container with read-only host mounts instead of
|
||||
# directly on the host. Defaults to "/host".
|
||||
# - "FALCO_BPF_PROBE": Specify a custom path to the BPF object code file (`bpf`
|
||||
# - "FALCO_BPF_PROBE": DEPRECATED. Specify a custom path to the BPF object code file (`bpf`
|
||||
# driver). This is not needed for the modern_bpf driver.
|
||||
# - "FALCO_HOSTNAME": Customize the hostname output field logged by Falco by
|
||||
# setting the "FALCO_HOSTNAME" environment variable.
|
||||
@@ -148,6 +147,196 @@ rules_file:
|
||||
- /etc/falco/falco_rules.local.yaml
|
||||
- /etc/falco/rules.d
|
||||
|
||||
################
|
||||
# Falco engine #
|
||||
################
|
||||
|
||||
# [Stable] `engine`
|
||||
#
|
||||
# --- [Description]
|
||||
#
|
||||
# Falco supports different engines to generate events.
|
||||
# Choose the appropriate engine kind based on your system's configuration and requirements.
|
||||
#
|
||||
# Available engines:
|
||||
# - `kmod`: Kernel Module (Kernel Module)
|
||||
# - `ebpf`: eBPF (eBPF probe)
|
||||
# - `modern_ebpf`: Modern eBPF (CO-RE eBPF probe)
|
||||
# - `gvisor`: gVisor (gVisor sandbox)
|
||||
# - `replay`: Replay a scap trace file
|
||||
# - `none`: No event producer loaded, useful to run with plugins.
|
||||
#
|
||||
# Only one engine can be specified in the `kind` key.
|
||||
# Moreover, for each engine multiple options might be available,
|
||||
# grouped under engine-specific configuration keys.
|
||||
# Some of them deserve an in-depth description:
|
||||
#
|
||||
################### `buf_size_preset`
|
||||
#
|
||||
# --- [Description]
|
||||
#
|
||||
# The syscall buffer index determines the size of the shared space between Falco
|
||||
# and its drivers. This shared space serves as a temporary storage for syscall
|
||||
# events, allowing them to be transferred from the kernel to the userspace
|
||||
# efficiently. The buffer size for each online CPU is determined by the buffer
|
||||
# index, and each CPU has its own dedicated buffer. Adjusting this index allows
|
||||
# you to control the overall size of the syscall buffers.
|
||||
#
|
||||
# --- [Usage]
|
||||
#
|
||||
# The index 0 is reserved, and each subsequent index corresponds to an
|
||||
# increasing size in bytes. For example, index 1 corresponds to a size of 1 MB,
|
||||
# index 2 corresponds to 2 MB, and so on:
|
||||
#
|
||||
# [(*), 1 MB, 2 MB, 4 MB, 8 MB, 16 MB, 32 MB, 64 MB, 128 MB, 256 MB, 512 MB]
|
||||
# ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
||||
# | | | | | | | | | | |
|
||||
# 0 1 2 3 4 5 6 7 8 9 10
|
||||
#
|
||||
#
|
||||
# The buffer dimensions in bytes are determined by the following requirements:
|
||||
# (1) a power of 2.
|
||||
# (2) a multiple of your system_page_dimension.
|
||||
# (3) greater than `2 * (system_page_dimension).
|
||||
#
|
||||
# The buffer size constraints may limit the usability of certain indexes. Let's
|
||||
# consider an example to illustrate this:
|
||||
#
|
||||
# If your system has a page size of 1 MB, the first available buffer size would
|
||||
# be 4 MB because 2 MB is exactly equal to 2 * (system_page_size), which is not
|
||||
# sufficient as we require more than 2 * (system_page_size). In this example, it
|
||||
# is evident that if the page size is 1 MB, the first index that can be used is 3.
|
||||
#
|
||||
# However, in most cases, these constraints do not pose a limitation, and all
|
||||
# indexes from 1 to 10 can be used. You can check your system's page size using
|
||||
# the Falco `--page-size` command-line option.
|
||||
#
|
||||
# --- [Suggestions]
|
||||
#
|
||||
# The buffer size was previously fixed at 8 MB (index 4). You now have the
|
||||
# option to adjust the size based on your needs. Increasing the size, such as to
|
||||
# 16 MB (index 5), can reduce syscall drops in heavy production systems, but may
|
||||
# impact performance. Decreasing the size can speed up the system but may
|
||||
# increase syscall drops. It's important to note that the buffer size is mapped
|
||||
# twice in the process' virtual memory, so a buffer of 8 MB will result in a 16
|
||||
# MB area in virtual memory. Use this parameter with caution and only modify it
|
||||
# if the default size is not suitable for your use case.
|
||||
#
|
||||
################### `drop_failed_exit`
|
||||
#
|
||||
# --- [Description]
|
||||
#
|
||||
# Enabling this option in Falco allows it to drop failed system call exit events
|
||||
# in the kernel drivers before pushing them onto the ring buffer. This
|
||||
# optimization can result in lower CPU usage and more efficient utilization of
|
||||
# the ring buffer, potentially reducing the number of event losses. However, it
|
||||
# is important to note that enabling this option also means sacrificing some
|
||||
# visibility into the system.
|
||||
#
|
||||
################### `cpus_for_each_buffer` (modern_ebpf only)
|
||||
#
|
||||
# --- [Description]
|
||||
#
|
||||
# The modern_bpf driver in Falco utilizes the new BPF ring buffer, which has a
|
||||
# different memory footprint compared to the current BPF driver that uses the
|
||||
# perf buffer. The Falco core maintainers have discussed the differences and
|
||||
# their implications, particularly in Kubernetes environments where limits need
|
||||
# to be carefully set to avoid interference with the Falco daemonset deployment
|
||||
# from the OOM killer. Based on guidance received from the kernel mailing list,
|
||||
# it is recommended to assign multiple CPUs to one buffer instead of allocating
|
||||
# a buffer for each CPU individually. This helps optimize resource allocation
|
||||
# and prevent potential issues related to memory usage.
|
||||
#
|
||||
# This is an index that controls how many CPUs you want to assign to a single
|
||||
# syscall buffer (ring buffer). By default, for modern_bpf every syscall buffer
|
||||
# is associated to 2 CPUs, so the mapping is 1:2. The modern BPF probe allows
|
||||
# you to choose different mappings, for example, changing the value to `1`
|
||||
# results in a 1:1 mapping and would mean one syscall buffer for each CPU (this
|
||||
# is the default for the `bpf` driver).
|
||||
#
|
||||
# --- [Usage]
|
||||
#
|
||||
# You can choose an index from 0 to MAX_NUMBER_ONLINE_CPUs to set the dimension
|
||||
# of the syscall buffers. The value 0 represents a single buffer shared among
|
||||
# all online CPUs. It serves as a flexible option when the exact number of
|
||||
# online CPUs is unknown. Here's an example to illustrate this:
|
||||
#
|
||||
# Consider a system with 7 online CPUs:
|
||||
#
|
||||
# CPUs 0 X 2 3 X X 6 7 8 9 (X means offline CPU)
|
||||
#
|
||||
# - `1` means a syscall buffer for each CPU so 7 buffers
|
||||
#
|
||||
# CPUs 0 X 2 3 X X 6 7 8 9 (X means offline CPU)
|
||||
# | | | | | | |
|
||||
# BUFFERs 0 1 2 3 4 5 6
|
||||
#
|
||||
# - `2` (Default value) means a syscall buffer for each CPU pair, so 4 buffers
|
||||
#
|
||||
# CPUs 0 X 2 3 X X 6 7 8 9 (X means offline CPU)
|
||||
# | | | | | | |
|
||||
# BUFFERs 0 0 1 1 2 2 3
|
||||
#
|
||||
# Please note that in this example, there are 4 buffers in total. Three of the
|
||||
# buffers are associated with pairs of CPUs, while the last buffer is mapped to
|
||||
# a single CPU. This arrangement is necessary because we have an odd number of
|
||||
# CPUs.
|
||||
#
|
||||
# - `0` or `MAX_NUMBER_ONLINE_CPUs` mean a syscall buffer shared between all
|
||||
# CPUs, so 1 buffer
|
||||
#
|
||||
# CPUs 0 X 2 3 X X 6 7 8 9 (X means offline CPU)
|
||||
# | | | | | | |
|
||||
# BUFFERs 0 0 0 0 0 0 0
|
||||
#
|
||||
# Moreover, you have the option to combine this parameter with
|
||||
# `buf_size_preset` index. For instance, you can create a large shared
|
||||
# syscall buffer of 512 MB (using buf_size_preset=10) that is
|
||||
# allocated among all the online CPUs.
|
||||
#
|
||||
# --- [Suggestions]
|
||||
#
|
||||
# The default choice of index 2 (one syscall buffer for each CPU pair) was made
|
||||
# because the modern bpf probe utilizes a different memory allocation strategy
|
||||
# compared to the other two drivers (bpf and kernel module). However, you have
|
||||
# the flexibility to experiment and find the optimal configuration for your
|
||||
# system.
|
||||
#
|
||||
# When considering a fixed buf_size_preset and a fixed buffer dimension:
|
||||
# - Increasing this configs value results in lower number of buffers and you can
|
||||
# speed up your system and reduce memory usage
|
||||
# - However, using too few buffers may increase contention in the kernel,
|
||||
# leading to a slowdown.
|
||||
#
|
||||
# If you have low event throughputs and minimal drops, reducing the number of
|
||||
# buffers (higher `cpus_for_each_buffer`) can lower the memory footprint.
|
||||
#
|
||||
engine:
|
||||
kind: kmod
|
||||
kmod:
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
ebpf:
|
||||
# path to the elf file to load.
|
||||
probe: ${HOME}/.falco/falco-bpf.o
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
modern_ebpf:
|
||||
cpus_for_each_buffer: 2
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
replay:
|
||||
# path to the capture file to replay (eg: /path/to/file.scap)
|
||||
capture_file: ""
|
||||
gvisor:
|
||||
# A Falco-compatible configuration file can be generated with
|
||||
# '--gvisor-generate-config' and utilized for both runsc and Falco.
|
||||
config: ""
|
||||
# Set gVisor root directory for storage of container state when used
|
||||
# in conjunction with 'gvisor.config'. The 'gvisor.root' to be passed
|
||||
# is the one usually passed to 'runsc --root' flag.
|
||||
root: ""
|
||||
|
||||
#################
|
||||
# Falco plugins #
|
||||
#################
|
||||
@@ -170,11 +359,10 @@ rules_file:
|
||||
#
|
||||
# Please note that if your intention is to enrich Falco syscall logs with fields
|
||||
# such as `k8s.ns.name`, `k8s.pod.name`, and `k8s.pod.*`, you do not need to use
|
||||
# the `k8saudit` plugin nor the `-k`/`-K` Kubernetes metadata enrichment. This
|
||||
# information is automatically extracted from the container runtime socket. The
|
||||
# `k8saudit` plugin is specifically designed to integrate with Kubernetes audit
|
||||
# logs and is not required for basic enrichment of syscall logs with
|
||||
# Kubernetes-related fields.
|
||||
# the `k8saudit` plugin. This information is automatically extracted from
|
||||
# the container runtime socket. The `k8saudit` plugin is specifically designed
|
||||
# to integrate with Kubernetes audit logs and is not required for basic enrichment
|
||||
# of syscall logs with Kubernetes-related fields.
|
||||
#
|
||||
# --- [Usage]
|
||||
#
|
||||
@@ -273,34 +461,6 @@ json_include_tags_property: true
|
||||
# output mechanism. By default, buffering is disabled (false).
|
||||
buffered_outputs: false
|
||||
|
||||
# [Stable] `outputs`
|
||||
#
|
||||
# [DEPRECATED]
|
||||
# This config is deprecated and it will be removed in Falco 0.37
|
||||
#
|
||||
# A throttling mechanism, implemented as a token bucket, can be used to control
|
||||
# the rate of Falco outputs. Each event source has its own rate limiter,
|
||||
# ensuring that alerts from one source do not affect the throttling of others.
|
||||
# The following options control the mechanism:
|
||||
# - rate: the number of tokens (i.e. right to send a notification) gained per
|
||||
# second. When 0, the throttling mechanism is disabled. Defaults to 0.
|
||||
# - max_burst: the maximum number of tokens outstanding. Defaults to 1000.
|
||||
#
|
||||
# For example, setting the rate to 1 allows Falco to send up to 1000
|
||||
# notifications initially, followed by 1 notification per second. The burst
|
||||
# capacity is fully restored after 1000 seconds of no activity.
|
||||
#
|
||||
# Throttling can be useful in various scenarios, such as preventing notification
|
||||
# floods, managing system load, controlling event processing, or complying with
|
||||
# rate limits imposed by external systems or APIs. It allows for better resource
|
||||
# utilization, avoids overwhelming downstream systems, and helps maintain a
|
||||
# balanced and controlled flow of notifications.
|
||||
#
|
||||
# With the default settings, the throttling mechanism is disabled.
|
||||
outputs:
|
||||
rate: 0
|
||||
max_burst: 1000
|
||||
|
||||
# [Experimental] `rule_matching`
|
||||
#
|
||||
# The `rule_matching` configuration key's values are:
|
||||
@@ -406,6 +566,8 @@ http_output:
|
||||
client_key: "/etc/ssl/certs/client.key"
|
||||
# Whether to echo server answers to stdout
|
||||
echo: false
|
||||
compress_uploads: false
|
||||
keep_alive: false
|
||||
|
||||
# [Stable] `program_output`
|
||||
#
|
||||
@@ -520,6 +682,8 @@ webserver:
|
||||
# the appropriate number of threads based on the number of online cores in the system.
|
||||
threadiness: 0
|
||||
listen_port: 8765
|
||||
# Can be an IPV4 or IPV6 address, defaults to IPV4
|
||||
listen_address: 0.0.0.0
|
||||
k8s_healthz_endpoint: /healthz
|
||||
ssl_enabled: false
|
||||
ssl_certificate: /etc/falco/falco.pem
|
||||
@@ -755,13 +919,22 @@ syscall_event_drops:
|
||||
# number of CPUs to determine overall usage. Memory metrics are provided in raw
|
||||
# units (`kb` for `RSS`, `PSS` and `VSZ` or `bytes` for `container_memory_used`)
|
||||
# and can be uniformly converted to megabytes (MB) using the
|
||||
# `convert_memory_to_mb` functionality. In environments such as Kubernetes, it
|
||||
# is crucial to track Falco's container memory usage. To customize the path of
|
||||
# the memory metric file, you can create an environment variable named
|
||||
# `FALCO_CGROUP_MEM_PATH` and set it to the desired file path. By default, Falco
|
||||
# uses the file `/sys/fs/cgroup/memory/memory.usage_in_bytes` to monitor
|
||||
# container memory usage, which aligns with Kubernetes'
|
||||
# `container_memory_working_set_bytes` metric.
|
||||
# `convert_memory_to_mb` functionality. In environments such as Kubernetes when
|
||||
# deployed as daemonset, it is crucial to track Falco's container memory usage.
|
||||
# To customize the path of the memory metric file, you can create an environment
|
||||
# variable named `FALCO_CGROUP_MEM_PATH` and set it to the desired file path. By
|
||||
# default, Falco uses the file `/sys/fs/cgroup/memory/memory.usage_in_bytes` to
|
||||
# monitor container memory usage, which aligns with Kubernetes'
|
||||
# `container_memory_working_set_bytes` metric. Finally, we emit the overall host
|
||||
# CPU and memory usages, along with the total number of processes and open file
|
||||
# descriptors (fds) on the host, obtained from the proc file system unrelated to
|
||||
# Falco's monitoring. These metrics help assess Falco's usage in relation to the
|
||||
# server's workload intensity.
|
||||
#
|
||||
# `state_counters_enabled`: Emit counters related to Falco's state engine, including
|
||||
# added, removed threads or file descriptors (fds), and failed lookup, store, or
|
||||
# retrieve actions in relation to Falco's underlying process cache table (threadtable).
|
||||
# We also log the number of currently cached containers if applicable.
|
||||
#
|
||||
# `kernel_event_counters_enabled`: Emit kernel side event and drop counters, as
|
||||
# an alternative to `syscall_event_drops`, but with some differences. These
|
||||
@@ -794,17 +967,21 @@ metrics:
|
||||
output_rule: true
|
||||
# output_file: /tmp/falco_stats.jsonl
|
||||
resource_utilization_enabled: true
|
||||
state_counters_enabled: true
|
||||
kernel_event_counters_enabled: true
|
||||
libbpf_stats_enabled: true
|
||||
convert_memory_to_mb: true
|
||||
include_empty_values: false
|
||||
|
||||
|
||||
#######################################
|
||||
# Falco performance tuning (advanced) #
|
||||
#######################################
|
||||
|
||||
# [Stable] `syscall_buf_size_preset`
|
||||
# [DEPRECATED] `syscall_buf_size_preset`
|
||||
#
|
||||
# Deprecated in favor of engine.{kmod,ebpf,modern_ebpf}.buf_size_preset.
|
||||
# This config is evaluated only if the default `engine` config block is not changed,
|
||||
# otherwise it is ignored.
|
||||
#
|
||||
# --- [Description]
|
||||
#
|
||||
@@ -856,10 +1033,14 @@ metrics:
|
||||
# if the default size is not suitable for your use case.
|
||||
syscall_buf_size_preset: 4
|
||||
|
||||
# [Experimental] `syscall_drop_failed_exit`
|
||||
# [DEPRECATED] `syscall_drop_failed_exit`
|
||||
#
|
||||
# Deprecated in favor of engine.{kmod,ebpf,modern_ebpf}.drop_failed_exit.
|
||||
# This config is evaluated only if the default `engine` config block is not changed,
|
||||
# otherwise it is ignored.
|
||||
#
|
||||
# Enabling this option in Falco allows it to drop failed system call exit events
|
||||
# in the kernel driver before pushing them onto the ring buffer. This
|
||||
# in the kernel drivers before pushing them onto the ring buffer. This
|
||||
# optimization can result in lower CPU usage and more efficient utilization of
|
||||
# the ring buffer, potentially reducing the number of event losses. However, it
|
||||
# is important to note that enabling this option also means sacrificing some
|
||||
@@ -981,7 +1162,11 @@ base_syscalls:
|
||||
custom_set: []
|
||||
repair: false
|
||||
|
||||
# [Stable] `modern_bpf.cpus_for_each_syscall_buffer`, modern_bpf only
|
||||
# [DEPRECATED] `modern_bpf.cpus_for_each_syscall_buffer`, modern_bpf only
|
||||
#
|
||||
# Deprecated in favor of engine.modern_ebpf.cpus_for_each_buffer.
|
||||
# This config is evaluated only if the default `engine` config block is not changed,
|
||||
# otherwise it is ignored.
|
||||
#
|
||||
# --- [Description]
|
||||
#
|
||||
@@ -1061,35 +1246,6 @@ base_syscalls:
|
||||
modern_bpf:
|
||||
cpus_for_each_syscall_buffer: 2
|
||||
|
||||
|
||||
#################################################
|
||||
# Falco cloud orchestration systems integration #
|
||||
#################################################
|
||||
|
||||
# [Stable] `metadata_download`
|
||||
#
|
||||
# When connected to an orchestrator like Kubernetes, Falco has the capability to
|
||||
# collect metadata and enrich system call events with contextual data. The
|
||||
# parameters mentioned here control the downloading process of this metadata.
|
||||
#
|
||||
# Please note that support for Mesos is deprecated, so these parameters
|
||||
# currently apply only to Kubernetes. When using Falco with Kubernetes, you can
|
||||
# enable this functionality by using the `-k` or `-K` command-line flag.
|
||||
#
|
||||
# However, it's worth mentioning that for important Kubernetes metadata fields
|
||||
# such as namespace or pod name, these fields are automatically extracted from
|
||||
# the container runtime, providing the necessary enrichment for common use cases
|
||||
# of syscall-based threat detection.
|
||||
#
|
||||
# In summary, the `-k` flag is typically not required for most scenarios involving
|
||||
# Kubernetes workload owner enrichment. The `-k` flag is primarily used when
|
||||
# additional metadata is required beyond the standard fields, catering to more
|
||||
# specific use cases, see https://falco.org/docs/reference/rules/supported-fields/#field-class-k8s.
|
||||
metadata_download:
|
||||
max_mb: 100
|
||||
chunk_wait_us: 1000
|
||||
watch_freq_sec: 1
|
||||
|
||||
# [Stable] Guidance for Kubernetes container engine command-line args settings
|
||||
#
|
||||
# Modern cloud environments, particularly Kubernetes, heavily rely on
|
||||
|
||||
@@ -41,11 +41,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
configure_file(rpm/postinstall.in rpm/postinstall COPYONLY)
|
||||
configure_file(rpm/postuninstall.in rpm/postuninstall COPYONLY)
|
||||
configure_file(rpm/preuninstall.in rpm/preuninstall COPYONLY)
|
||||
|
||||
# driver loader
|
||||
configure_file(falco-driver-loader falco-driver-loader @ONLY)
|
||||
install(PROGRAMS ${PROJECT_BINARY_DIR}/scripts/falco-driver-loader
|
||||
DESTINATION ${FALCO_BIN_DIR} COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
endif()
|
||||
|
||||
# Install Falcoctl config file
|
||||
@@ -53,5 +48,6 @@ if (NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN AND NOT MUSL_OPTIMIZED_BUILD)
|
||||
if(NOT DEFINED FALCOCTL_ETC_DIR)
|
||||
set(FALCOCTL_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/falcoctl")
|
||||
endif()
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/falcoctl/falcoctl.yaml DESTINATION "${FALCOCTL_ETC_DIR}" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/falcoctl/falcoctl.yaml.in ${PROJECT_BINARY_DIR}/scripts/falcoctl/falcoctl.yaml)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/scripts/falcoctl/falcoctl.yaml DESTINATION "${FALCOCTL_ETC_DIR}" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
endif()
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#
|
||||
|
||||
chosen_driver=
|
||||
chosen_unit=
|
||||
CHOICE=
|
||||
|
||||
# Every time we call this script we want to stat from a clean state.
|
||||
echo "[POST-INSTALL] Disable all possible 'falco' services:"
|
||||
@@ -36,39 +38,63 @@ systemctl --system disable 'falcoctl-artifact-follow.service' || true
|
||||
systemctl --system unmask falcoctl-artifact-follow.service || true
|
||||
|
||||
if [ "$1" = "configure" ]; then
|
||||
if [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
# If dialog is installed, create a dialog to let users choose the correct driver for them
|
||||
CHOICE=$(dialog --clear --title "Falco drivers" --menu "Choose your preferred driver:" 12 55 4 \
|
||||
1 "Manual configuration (no unit is started)" \
|
||||
2 "Kmod" \
|
||||
3 "eBPF" \
|
||||
4 "Modern eBPF" \
|
||||
2>&1 >/dev/tty)
|
||||
case $CHOICE in
|
||||
2)
|
||||
chosen_driver="kmod"
|
||||
;;
|
||||
3)
|
||||
chosen_driver="bpf"
|
||||
;;
|
||||
4)
|
||||
chosen_driver="modern-bpf"
|
||||
;;
|
||||
esac
|
||||
if [ -n "$chosen_driver" ]; then
|
||||
CHOICE=$(dialog --clear --title "Falcoctl" --menu "Do you want to follow automatic ruleset updates?" 10 40 2 \
|
||||
1 "Yes" \
|
||||
2 "No" \
|
||||
case $FALCO_DRIVER_CHOICE in
|
||||
kmod)
|
||||
CHOICE=2
|
||||
;;
|
||||
ebpf)
|
||||
CHOICE=3
|
||||
;;
|
||||
modern_ebpf)
|
||||
CHOICE=4
|
||||
;;
|
||||
esac
|
||||
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
# If dialog is installed, create a dialog to let users choose the correct driver for them
|
||||
CHOICE=$(dialog --clear --title "Falco drivers" --menu "Choose your preferred driver:" 12 55 4 \
|
||||
1 "Manual configuration (no unit is started)" \
|
||||
2 "Kmod" \
|
||||
3 "eBPF" \
|
||||
4 "Modern eBPF" \
|
||||
2>&1 >/dev/tty)
|
||||
fi
|
||||
case $CHOICE in
|
||||
2)
|
||||
chosen_driver="kmod"
|
||||
chosen_unit="kmod"
|
||||
;;
|
||||
3)
|
||||
chosen_driver="ebpf"
|
||||
chosen_unit="bpf"
|
||||
;;
|
||||
4)
|
||||
chosen_driver="modern_ebpf"
|
||||
chosen_unit="modern-bpf"
|
||||
;;
|
||||
esac
|
||||
if [ -n "$CHOICE" ]; then
|
||||
echo "[POST-INSTALL] Configure falcoctl driver type:"
|
||||
falcoctl driver config --type $chosen_driver
|
||||
CHOICE=
|
||||
case $FALCOCTL_ENABLED in
|
||||
no)
|
||||
CHOICE=2
|
||||
;;
|
||||
esac
|
||||
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
CHOICE=$(dialog --clear --title "Falcoctl" --menu "Do you want to follow automatic ruleset updates?" 10 40 2 \
|
||||
1 "Yes" \
|
||||
2 "No" \
|
||||
2>&1 >/dev/tty)
|
||||
fi
|
||||
case $CHOICE in
|
||||
2)
|
||||
# we don't want falcoctl enabled, we mask it
|
||||
systemctl --system mask falcoctl-artifact-follow.service || true
|
||||
# we don't want falcoctl enabled, we mask it
|
||||
systemctl --system mask falcoctl-artifact-follow.service || true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
clear
|
||||
fi
|
||||
fi
|
||||
clear
|
||||
fi
|
||||
|
||||
set -e
|
||||
@@ -76,25 +102,25 @@ set -e
|
||||
echo "[POST-INSTALL] Trigger deamon-reload:"
|
||||
systemctl --system daemon-reload || true
|
||||
|
||||
# If needed, try to load/compile the driver through falco-driver-loader
|
||||
# If needed, try to load/compile the driver through falcoctl
|
||||
case "$chosen_driver" in
|
||||
"kmod")
|
||||
# Only compile for kmod, in this way we use dkms
|
||||
echo "[POST-INSTALL] Call 'falco-driver-loader --compile module':"
|
||||
falco-driver-loader --compile module
|
||||
echo "[POST-INSTALL] Call 'falcoctl driver install for kmod:"
|
||||
falcoctl driver install --download=false
|
||||
;;
|
||||
"bpf")
|
||||
echo "[POST-INSTALL] Call 'falco-driver-loader bpf':"
|
||||
falco-driver-loader bpf
|
||||
"ebpf")
|
||||
echo "[POST-INSTALL] Call 'falcoctl driver install for ebpf':"
|
||||
falcoctl driver install
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
|
||||
if [ -n "$chosen_driver" ]; then
|
||||
if [ -n "$chosen_unit" ]; then
|
||||
# we do this in 2 steps because `enable --now` is not always supported
|
||||
echo "[POST-INSTALL] Enable 'falco-$chosen_driver.service':"
|
||||
systemctl --system enable "falco-$chosen_driver.service" || true
|
||||
echo "[POST-INSTALL] Start 'falco-$chosen_driver.service':"
|
||||
systemctl --system start "falco-$chosen_driver.service" || true
|
||||
echo "[POST-INSTALL] Enable 'falco-$chosen_unit.service':"
|
||||
systemctl --system enable "falco-$chosen_unit.service" || true
|
||||
echo "[POST-INSTALL] Start 'falco-$chosen_unit.service':"
|
||||
systemctl --system start "falco-$chosen_unit.service" || true
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -31,7 +31,7 @@ case "$1" in
|
||||
systemctl --system stop 'falco-custom.service' || true
|
||||
systemctl --system stop 'falcoctl-artifact-follow.service' || true
|
||||
|
||||
echo "[PRE-REMOVE] Call 'falco-driver-loader --clean:'"
|
||||
falco-driver-loader --clean
|
||||
echo "[PRE-REMOVE] Call 'falcoctl driver cleanup:'"
|
||||
falcoctl driver cleanup
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,866 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 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.
|
||||
#
|
||||
# Simple script that desperately tries to load the kernel instrumentation by
|
||||
# looking for it in a bunch of ways. Convenient when running Falco inside
|
||||
# a container or in other weird environments.
|
||||
#
|
||||
|
||||
#
|
||||
# Returns 1 if $cos_ver > $base_ver, 0 otherwise
|
||||
#
|
||||
cos_version_greater() {
|
||||
if [[ $cos_ver == "${base_ver}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
#
|
||||
# COS build numbers are in the format x.y.z
|
||||
#
|
||||
a=$(echo "${cos_ver}" | cut -d. -f1)
|
||||
b=$(echo "${cos_ver}" | cut -d. -f2)
|
||||
c=$(echo "${cos_ver}" | cut -d. -f3)
|
||||
|
||||
d=$(echo "${base_ver}" | cut -d. -f1)
|
||||
e=$(echo "${base_ver}" | cut -d. -f2)
|
||||
f=$(echo "${base_ver}" | cut -d. -f3)
|
||||
|
||||
# Test the first component
|
||||
if [[ $a -gt $d ]]; then
|
||||
return 1
|
||||
elif [[ $d -gt $a ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Test the second component
|
||||
if [[ $b -gt $e ]]; then
|
||||
return 1
|
||||
elif [[ $e -gt $b ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Test the third component
|
||||
if [[ $c -gt $f ]]; then
|
||||
return 1
|
||||
elif [[ $f -gt $c ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If we get here, probably malformatted version string?
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
get_kernel_config() {
|
||||
if [ -f /proc/config.gz ]; then
|
||||
echo "* Found kernel config at /proc/config.gz"
|
||||
KERNEL_CONFIG_PATH=/proc/config.gz
|
||||
elif [ -f "/boot/config-${KERNEL_RELEASE}" ]; then
|
||||
echo "* Found kernel config at /boot/config-${KERNEL_RELEASE}"
|
||||
KERNEL_CONFIG_PATH=/boot/config-${KERNEL_RELEASE}
|
||||
elif [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/boot/config-${KERNEL_RELEASE}" ]; then
|
||||
echo "* Found kernel config at ${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
|
||||
KERNEL_CONFIG_PATH="${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
|
||||
elif [ -f "/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
|
||||
echo "* Found kernel config at /usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
|
||||
KERNEL_CONFIG_PATH="/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
|
||||
elif [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
|
||||
echo "* Found kernel config at ${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
|
||||
KERNEL_CONFIG_PATH="${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
|
||||
elif [ -f "/lib/modules/${KERNEL_RELEASE}/config" ]; then
|
||||
# This code works both for native host and containers assuming that
|
||||
# Dockerfile sets up the desired symlink /lib/modules -> $HOST_ROOT/lib/modules
|
||||
echo "* Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
|
||||
KERNEL_CONFIG_PATH="/lib/modules/${KERNEL_RELEASE}/config"
|
||||
fi
|
||||
|
||||
if [ -z "${KERNEL_CONFIG_PATH}" ]; then
|
||||
>&2 echo "Cannot find kernel config"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
|
||||
HASH=$(zcat "${KERNEL_CONFIG_PATH}" | md5sum - | cut -d' ' -f1)
|
||||
else
|
||||
HASH=$(md5sum "${KERNEL_CONFIG_PATH}" | cut -d' ' -f1)
|
||||
fi
|
||||
}
|
||||
|
||||
get_target_id() {
|
||||
if [ -f "${HOST_ROOT}/etc/os-release" ]; then
|
||||
# freedesktop.org and systemd
|
||||
# shellcheck source=/dev/null
|
||||
source "${HOST_ROOT}/etc/os-release"
|
||||
OS_ID=$ID
|
||||
elif [ -f "${HOST_ROOT}/etc/debian_version" ]; then
|
||||
# Older debian distros
|
||||
# fixme > Can this happen on older Ubuntu?
|
||||
OS_ID=debian
|
||||
elif [ -f "${HOST_ROOT}/etc/centos-release" ]; then
|
||||
# Older CentOS distros
|
||||
OS_ID=centos
|
||||
elif [ -f "${HOST_ROOT}/etc/redhat-release" ]; then
|
||||
# Older RHEL distros
|
||||
OS_ID=rhel
|
||||
else
|
||||
# No target id can be determinand
|
||||
TARGET_ID="undetermined"
|
||||
return
|
||||
fi
|
||||
|
||||
# Overwrite the OS_ID if /etc/VERSION file is present.
|
||||
# Not sure if there is a better way to detect minikube.
|
||||
if [ -f "${HOST_ROOT}/etc/VERSION" ]; then
|
||||
OS_ID=minikube
|
||||
fi
|
||||
|
||||
case "${OS_ID}" in
|
||||
("amzn")
|
||||
case "${VERSION_ID}" in
|
||||
("2")
|
||||
TARGET_ID="amazonlinux2"
|
||||
;;
|
||||
("2022")
|
||||
TARGET_ID="amazonlinux2022"
|
||||
;;
|
||||
("2023")
|
||||
TARGET_ID="amazonlinux2023"
|
||||
;;
|
||||
(*)
|
||||
TARGET_ID="amazonlinux"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
("debian")
|
||||
# Workaround: debian kernelreleases might now be actual kernel running;
|
||||
# instead, they might be the Debian kernel package
|
||||
# providing the compatible kernel ABI
|
||||
# See https://lists.debian.org/debian-user/2017/03/msg00485.html
|
||||
# Real kernel release is embedded inside the kernel version.
|
||||
# Moreover, kernel arch, when present, is attached to the former,
|
||||
# therefore make sure to properly take it and attach it to the latter.
|
||||
# Moreover, we support 3 flavors for debian kernels: cloud, rt and normal.
|
||||
# KERNEL-RELEASE will have a `-rt`, or `-cloud` if we are in one of these flavors.
|
||||
# Manage it to download the correct driver.
|
||||
#
|
||||
# Example: KERNEL_RELEASE="5.10.0-0.deb10.22-rt-amd64" and `uname -v`="5.10.178-3"
|
||||
# should lead to: KERNEL_RELEASE="5.10.178-3-rt-amd64"
|
||||
TARGET_ID=$(echo "${OS_ID}" | tr '[:upper:]' '[:lower:]')
|
||||
local ARCH_extra=""
|
||||
if [[ $KERNEL_RELEASE =~ -?(rt-|cloud-|)(amd64|arm64) ]];
|
||||
then
|
||||
ARCH_extra="-${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
|
||||
fi
|
||||
if [[ ${DRIVER_KERNEL_VERSION} =~ ([0-9]+\.[0-9]+\.[0-9]+\-[0-9]+) ]];
|
||||
then
|
||||
KERNEL_RELEASE="${BASH_REMATCH[1]}${ARCH_extra}"
|
||||
fi
|
||||
;;
|
||||
("ubuntu")
|
||||
# Extract the flavor from the kernelrelease
|
||||
# Examples:
|
||||
# 5.0.0-1028-aws-5.0 -> ubuntu-aws
|
||||
# 5.15.0-1009-aws -> ubuntu-aws
|
||||
if [[ $KERNEL_RELEASE =~ -([a-zA-Z]+)(-.*)?$ ]];
|
||||
then
|
||||
TARGET_ID="ubuntu-${BASH_REMATCH[1]}"
|
||||
else
|
||||
TARGET_ID="ubuntu-generic"
|
||||
fi
|
||||
|
||||
|
||||
# In the case that the kernelversion isn't just a number
|
||||
# we keep also the remaining part excluding `-Ubuntu`.
|
||||
# E.g.:
|
||||
# from the following `uname -v` result
|
||||
# `#26~22.04.1-Ubuntu SMP Mon Apr 24 01:58:15 UTC 2023`
|
||||
# we obtain the kernelversion`26~22.04.1`
|
||||
if [[ ${DRIVER_KERNEL_VERSION} =~ (^\#[0-9]+\~[^-]*-Ubuntu .*$) ]];
|
||||
then
|
||||
KERNEL_VERSION=$(echo "${DRIVER_KERNEL_VERSION}" | sed 's/#\([^-\\ ]*\).*/\1/g')
|
||||
fi
|
||||
;;
|
||||
("flatcar")
|
||||
KERNEL_RELEASE="${VERSION_ID}"
|
||||
TARGET_ID=$(echo "${OS_ID}" | tr '[:upper:]' '[:lower:]')
|
||||
;;
|
||||
("minikube")
|
||||
TARGET_ID=$(echo "${OS_ID}" | tr '[:upper:]' '[:lower:]')
|
||||
# Extract the minikube version. Ex. With minikube version equal to "v1.26.0-1655407986-14197" the extracted version
|
||||
# will be "1.26.0"
|
||||
if [[ $(cat ${HOST_ROOT}/etc/VERSION) =~ ([0-9]+(\.[0-9]+){2}) ]]; then
|
||||
# kernel version for minikube is always in "1_minikubeversion" format. Ex "1_1.26.0".
|
||||
KERNEL_VERSION="1_${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "* Unable to extract minikube version from ${HOST_ROOT}/etc/VERSION"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
("bottlerocket")
|
||||
TARGET_ID=$(echo "${OS_ID}" | tr '[:upper:]' '[:lower:]')
|
||||
# variant_id has been sourced from os-release. Get only the first variant part
|
||||
if [[ -n ${VARIANT_ID} ]]; then
|
||||
# take just first part (eg: VARIANT_ID=aws-k8s-1.15 -> aws)
|
||||
VARIANT_ID_CUT=${VARIANT_ID%%-*}
|
||||
fi
|
||||
# version_id has been sourced from os-release. Build a kernel version like: 1_1.11.0-aws
|
||||
KERNEL_VERSION="1_${VERSION_ID}-${VARIANT_ID_CUT}"
|
||||
;;
|
||||
("talos")
|
||||
TARGET_ID=$(echo "${OS_ID}" | tr '[:upper:]' '[:lower:]')
|
||||
# version_id has been sourced from os-release. Build a kernel version like: 1_1.4.1
|
||||
KERNEL_VERSION="1_${VERSION_ID}"
|
||||
;;
|
||||
(*)
|
||||
TARGET_ID=$(echo "${OS_ID}" | tr '[:upper:]' '[:lower:]')
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
flatcar_relocate_tools() {
|
||||
local -a tools=(
|
||||
scripts/basic/fixdep
|
||||
scripts/mod/modpost
|
||||
tools/objtool/objtool
|
||||
)
|
||||
local -r hostld=$(ls /host/usr/lib64/ld-linux-*.so.*)
|
||||
local -r kdir=/lib/modules/$(ls /lib/modules/)/build
|
||||
echo "** Found host dl interpreter: ${hostld}"
|
||||
for host_tool in ${tools[@]}; do
|
||||
t=${host_tool}
|
||||
tool=$(basename $t)
|
||||
tool_dir=$(dirname $t)
|
||||
host_tool=${kdir}/${host_tool}
|
||||
if [ ! -f ${host_tool} ]; then
|
||||
continue
|
||||
fi
|
||||
umount ${host_tool} 2>/dev/null || true
|
||||
mkdir -p /tmp/${tool_dir}/
|
||||
cp -a ${host_tool} /tmp/${tool_dir}/
|
||||
echo "** Setting host dl interpreter for $host_tool"
|
||||
patchelf --set-interpreter ${hostld} --set-rpath /host/usr/lib64 /tmp/${tool_dir}/${tool}
|
||||
mount -o bind /tmp/${tool_dir}/${tool} ${host_tool}
|
||||
done
|
||||
}
|
||||
|
||||
load_kernel_module_compile() {
|
||||
# Skip dkms on UEK hosts because it will always fail
|
||||
if [[ ${DRIVER_KERNEL_RELEASE} == *uek* ]]; then
|
||||
>&2 echo "Skipping because the dkms install always fail (on UEK hosts)"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! hash dkms >/dev/null 2>&1; then
|
||||
>&2 echo "This program requires dkms"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "${TARGET_ID}" == "flatcar" ]; then
|
||||
KERNEL_RELEASE=${DRIVER_KERNEL_RELEASE}
|
||||
echo "* Flatcar detected (version ${VERSION_ID}); relocating kernel tools"
|
||||
flatcar_relocate_tools
|
||||
fi
|
||||
|
||||
# Try to compile using all the available gcc versions
|
||||
for CURRENT_GCC in $(ls "$(dirname "$(which gcc)")"/gcc*); do
|
||||
# Filter away gcc-{ar,nm,...}
|
||||
# Only gcc compiler has `-print-search-dirs` option.
|
||||
${CURRENT_GCC} -print-search-dirs 2>&1 | grep "install:"
|
||||
if [ "$?" -ne "0" ]; then
|
||||
continue
|
||||
fi
|
||||
echo "* Trying to dkms install ${DRIVER_NAME} module with GCC ${CURRENT_GCC}"
|
||||
echo "#!/usr/bin/env bash" > "${TMPDIR}/falco-dkms-make"
|
||||
echo "make CC=${CURRENT_GCC} \$@" >> "${TMPDIR}/falco-dkms-make"
|
||||
chmod +x "${TMPDIR}/falco-dkms-make"
|
||||
if dkms install --directive="MAKE='${TMPDIR}/falco-dkms-make'" -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
|
||||
echo "* ${DRIVER_NAME} module installed in dkms"
|
||||
KO_FILE="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}"
|
||||
if [ -f "$KO_FILE.ko" ]; then
|
||||
KO_FILE="$KO_FILE.ko"
|
||||
elif [ -f "$KO_FILE.ko.gz" ]; then
|
||||
KO_FILE="$KO_FILE.ko.gz"
|
||||
elif [ -f "$KO_FILE.ko.xz" ]; then
|
||||
KO_FILE="$KO_FILE.ko.xz"
|
||||
elif [ -f "$KO_FILE.ko.zst" ]; then
|
||||
KO_FILE="$KO_FILE.ko.zst"
|
||||
else
|
||||
>&2 echo "${DRIVER_NAME} module file not found"
|
||||
return
|
||||
fi
|
||||
echo "* ${DRIVER_NAME} module found: ${KO_FILE}"
|
||||
echo "* Trying to insmod"
|
||||
chcon -t modules_object_t "$KO_FILE" > /dev/null 2>&1 || true
|
||||
if insmod "$KO_FILE" > /dev/null 2>&1; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms"
|
||||
exit 0
|
||||
fi
|
||||
echo "* Unable to insmod ${DRIVER_NAME} module"
|
||||
else
|
||||
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
|
||||
if [ -f "${DKMS_LOG}" ]; then
|
||||
echo "* Running dkms build failed, dumping ${DKMS_LOG} (with GCC ${CURRENT_GCC})"
|
||||
cat "${DKMS_LOG}"
|
||||
else
|
||||
echo "* Running dkms build failed, couldn't find ${DKMS_LOG} (with GCC ${CURRENT_GCC})"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
load_kernel_module_download() {
|
||||
local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"
|
||||
local URL=$(echo "${1}/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}" | sed s/+/%2B/g)
|
||||
|
||||
echo "* Trying to download a prebuilt ${DRIVER_NAME} module from ${URL}"
|
||||
if curl -L --create-dirs ${FALCO_DRIVER_CURL_OPTIONS} -o "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then
|
||||
echo "* Download succeeded"
|
||||
chcon -t modules_object_t "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}" > /dev/null 2>&1 || true
|
||||
if insmod "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}"; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and inserted"
|
||||
exit 0
|
||||
fi
|
||||
>&2 echo "Unable to insmod the prebuilt ${DRIVER_NAME} module"
|
||||
else
|
||||
>&2 echo "Unable to find a prebuilt ${DRIVER_NAME} module"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
print_clean_termination() {
|
||||
echo
|
||||
echo "[SUCCESS] Cleaning phase correctly terminated."
|
||||
echo
|
||||
echo "================ Cleaning phase ================"
|
||||
echo
|
||||
}
|
||||
|
||||
print_filename_components() {
|
||||
echo " - driver name: ${DRIVER_NAME}"
|
||||
echo " - target identifier: ${TARGET_ID}"
|
||||
echo " - kernel release: ${KERNEL_RELEASE}"
|
||||
echo " - kernel version: ${KERNEL_VERSION}"
|
||||
}
|
||||
|
||||
print_as_env_vars() {
|
||||
echo "ARCH=\"${ARCH}\""
|
||||
echo "KERNEL_RELEASE=\"${KERNEL_RELEASE}\""
|
||||
echo "KERNEL_VERSION=\"${KERNEL_VERSION}\""
|
||||
echo "ENABLE_COMPILE=\"${ENABLE_COMPILE}\""
|
||||
echo "ENABLE_DOWNLOAD=\"${ENABLE_DOWNLOAD}\""
|
||||
echo "TARGET_ID=\"${TARGET_ID}\""
|
||||
echo "DRIVER=\"${DRIVER}\""
|
||||
echo "DRIVERS_REPO=\"${DRIVERS_REPO}\""
|
||||
echo "DRIVER_VERSION=\"${DRIVER_VERSION}\""
|
||||
echo "DRIVER_NAME=\"${DRIVER_NAME}\""
|
||||
echo "FALCO_VERSION=\"${FALCO_VERSION}\""
|
||||
}
|
||||
|
||||
clean_kernel_module() {
|
||||
echo
|
||||
echo "================ Cleaning phase ================"
|
||||
echo
|
||||
|
||||
if ! hash lsmod > /dev/null 2>&1; then
|
||||
>&2 echo "This program requires lsmod."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! hash rmmod > /dev/null 2>&1; then
|
||||
>&2 echo "This program requires rmmod."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
|
||||
echo "* 1. Check if kernel module '${KMOD_NAME}' is still loaded:"
|
||||
|
||||
if ! lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}"; then
|
||||
echo "- OK! There is no '${KMOD_NAME}' module loaded."
|
||||
echo
|
||||
fi
|
||||
|
||||
# Wait 50s = MAX_RMMOD_WAIT * 5s
|
||||
MAX_RMMOD_WAIT=10
|
||||
# Remove kernel module if is still loaded.
|
||||
while lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" && [ $MAX_RMMOD_WAIT -gt 0 ]; do
|
||||
echo "- Kernel module '${KMOD_NAME}' is still loaded."
|
||||
echo "- Trying to unload it with 'rmmod ${KMOD_NAME}'..."
|
||||
if rmmod ${KMOD_NAME}; then
|
||||
echo "- OK! Unloading '${KMOD_NAME}' module succeeded."
|
||||
echo
|
||||
else
|
||||
echo "- Nothing to do...'falco-driver-loader' will wait until you remove the kernel module to have a clean termination."
|
||||
echo "- Check that no process is using the kernel module with 'lsmod | grep ${KMOD_NAME}'."
|
||||
echo "- Sleep 5 seconds..."
|
||||
echo
|
||||
((--MAX_RMMOD_WAIT))
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${MAX_RMMOD_WAIT} -eq 0 ]; then
|
||||
echo "[WARNING] '${KMOD_NAME}' module is still loaded, you could have incompatibility issues."
|
||||
echo
|
||||
fi
|
||||
|
||||
if ! hash dkms >/dev/null 2>&1; then
|
||||
echo "- Skipping dkms remove (dkms not found)."
|
||||
print_clean_termination
|
||||
return
|
||||
fi
|
||||
|
||||
# Remove all versions of this module from dkms.
|
||||
echo "* 2. Check all versions of kernel module '${KMOD_NAME}' in dkms:"
|
||||
DRIVER_VERSIONS=$(dkms status -m "${KMOD_NAME}" | tr -d "," | tr -d ":" | tr "/" " " | cut -d' ' -f2)
|
||||
if [ -z "${DRIVER_VERSIONS}" ]; then
|
||||
echo "- OK! There are no '${KMOD_NAME}' module versions in dkms."
|
||||
else
|
||||
echo "- There are some versions of '${KMOD_NAME}' module in dkms."
|
||||
echo
|
||||
echo "* 3. Removing all the following versions from dkms:"
|
||||
echo "${DRIVER_VERSIONS}"
|
||||
echo
|
||||
fi
|
||||
|
||||
for CURRENT_VER in ${DRIVER_VERSIONS}; do
|
||||
echo "- Removing ${CURRENT_VER}..."
|
||||
if dkms remove -m ${KMOD_NAME} -v "${CURRENT_VER}" --all; then
|
||||
echo
|
||||
echo "- OK! Removing '${CURRENT_VER}' succeeded."
|
||||
echo
|
||||
else
|
||||
echo "[WARNING] Removing '${KMOD_NAME}' version '${CURRENT_VER}' failed."
|
||||
fi
|
||||
done
|
||||
|
||||
print_clean_termination
|
||||
}
|
||||
|
||||
load_kernel_module() {
|
||||
clean_kernel_module
|
||||
|
||||
echo "* Looking for a ${DRIVER_NAME} module locally (kernel ${KERNEL_RELEASE})"
|
||||
|
||||
local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"
|
||||
echo "* Filename '${FALCO_KERNEL_MODULE_FILENAME}' is composed of:"
|
||||
print_filename_components
|
||||
|
||||
if [ -f "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}" ]; then
|
||||
echo "* Found a prebuilt ${DRIVER_NAME} module at ${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}, loading it"
|
||||
chcon -t modules_object_t "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}" > /dev/null 2>&1 || true
|
||||
insmod "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module found and inserted"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$ENABLE_DOWNLOAD" ]; then
|
||||
IFS=", " read -r -a urls <<< "${DRIVERS_REPO}"
|
||||
for url in "${urls[@]}"; do
|
||||
load_kernel_module_download $url
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "$ENABLE_COMPILE" ]; then
|
||||
load_kernel_module_compile
|
||||
fi
|
||||
|
||||
# Last try (might load a previous driver version)
|
||||
echo "* Trying to load a system ${DRIVER_NAME} module, if present"
|
||||
if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and loaded with modprobe"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Not able to download a prebuilt module nor to compile one on-the-fly
|
||||
>&2 echo "Consider compiling your own ${DRIVER_NAME} driver and loading it or getting in touch with the Falco community"
|
||||
exit 1
|
||||
}
|
||||
|
||||
load_bpf_probe_compile() {
|
||||
local BPF_KERNEL_SOURCES_URL=""
|
||||
local STRIP_COMPONENTS=1
|
||||
|
||||
customize_kernel_build() {
|
||||
if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
|
||||
sed -i "s/LOCALVERSION=\"\"/LOCALVERSION=\"${KERNEL_EXTRA_VERSION}\"/" .config
|
||||
fi
|
||||
make olddefconfig > /dev/null
|
||||
make modules_prepare > /dev/null
|
||||
}
|
||||
|
||||
if [ "${TARGET_ID}" == "flatcar" ]; then
|
||||
KERNEL_RELEASE=${DRIVER_KERNEL_RELEASE}
|
||||
echo "* Flatcar detected (version ${VERSION_ID}); relocating kernel tools"
|
||||
flatcar_relocate_tools
|
||||
fi
|
||||
|
||||
if [ "${TARGET_ID}" == "cos" ]; then
|
||||
echo "* COS detected (build ${BUILD_ID}), using COS kernel headers"
|
||||
|
||||
BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
|
||||
KERNEL_EXTRA_VERSION="+"
|
||||
STRIP_COMPONENTS=0
|
||||
|
||||
customize_kernel_build() {
|
||||
pushd usr/src/* > /dev/null || exit
|
||||
|
||||
# Note: this overrides the KERNELDIR set while untarring the tarball
|
||||
KERNELDIR=$(pwd)
|
||||
export KERNELDIR
|
||||
|
||||
sed -i '/^#define randomized_struct_fields_start struct {$/d' include/linux/compiler-clang.h
|
||||
sed -i '/^#define randomized_struct_fields_end };$/d' include/linux/compiler-clang.h
|
||||
|
||||
popd > /dev/null || exit
|
||||
|
||||
# Might need to configure our own sources depending on COS version
|
||||
cos_ver=${BUILD_ID}
|
||||
base_ver=11553.0.0
|
||||
|
||||
cos_version_greater
|
||||
greater_ret=$?
|
||||
|
||||
if [[ greater_ret -eq 1 ]]; then
|
||||
export KBUILD_EXTRA_CPPFLAGS=-DCOS_73_WORKAROUND
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
if [ "${TARGET_ID}" == "minikube" ]; then
|
||||
MINIKUBE_VERSION="$(cat "${HOST_ROOT}/etc/VERSION")"
|
||||
echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
|
||||
local kernel_version
|
||||
kernel_version=${DRIVER_KERNEL_RELEASE}
|
||||
local -r kernel_version_major=$(echo "${kernel_version}" | cut -d. -f1)
|
||||
local -r kernel_version_minor=$(echo "${kernel_version}" | cut -d. -f2)
|
||||
local -r kernel_version_patch=$(echo "${kernel_version}" | cut -d. -f3)
|
||||
|
||||
if [ "${kernel_version_patch}" == "0" ]; then
|
||||
kernel_version="${kernel_version_major}.${kernel_version_minor}"
|
||||
fi
|
||||
|
||||
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
|
||||
fi
|
||||
|
||||
if [ -n "${BPF_USE_LOCAL_KERNEL_SOURCES}" ]; then
|
||||
local -r kernel_version_major=$(echo "${DRIVER_KERNEL_RELEASE}" | cut -d. -f1)
|
||||
local -r kernel_version=$(echo "${DRIVER_KERNEL_RELEASE}" | cut -d- -f1)
|
||||
KERNEL_EXTRA_VERSION="-$(echo "${DRIVER_KERNEL_RELEASE}" | cut -d- -f2)"
|
||||
|
||||
echo "* Using downloaded kernel sources for kernel version ${kernel_version}..."
|
||||
|
||||
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
|
||||
fi
|
||||
|
||||
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
|
||||
get_kernel_config
|
||||
|
||||
echo "* Downloading ${BPF_KERNEL_SOURCES_URL}"
|
||||
|
||||
mkdir -p /tmp/kernel
|
||||
cd /tmp/kernel || exit
|
||||
cd "$(mktemp -d -p /tmp/kernel)" || exit
|
||||
if ! curl -L -o kernel-sources.tgz --create-dirs ${FALCO_DRIVER_CURL_OPTIONS} "${BPF_KERNEL_SOURCES_URL}"; then
|
||||
>&2 echo "Unable to download the kernel sources"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "* Extracting kernel sources"
|
||||
|
||||
mkdir kernel-sources && tar xf kernel-sources.tgz -C kernel-sources --strip-components "${STRIP_COMPONENTS}"
|
||||
|
||||
cd kernel-sources || exit
|
||||
KERNELDIR=$(pwd)
|
||||
export KERNELDIR
|
||||
|
||||
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
|
||||
zcat "${KERNEL_CONFIG_PATH}" > .config
|
||||
else
|
||||
cat "${KERNEL_CONFIG_PATH}" > .config
|
||||
fi
|
||||
|
||||
echo "* Configuring kernel"
|
||||
customize_kernel_build
|
||||
fi
|
||||
|
||||
echo "* Trying to compile the eBPF probe (${BPF_PROBE_FILENAME})"
|
||||
|
||||
make -C "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf" > /dev/null
|
||||
|
||||
mkdir -p "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}"
|
||||
mv "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf/probe.o" "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}"
|
||||
|
||||
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
|
||||
rm -r /tmp/kernel
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
load_bpf_probe_download() {
|
||||
local URL
|
||||
URL=$(echo "${1}/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
|
||||
|
||||
echo "* Trying to download a prebuilt eBPF probe from ${URL}"
|
||||
|
||||
if ! curl -L --create-dirs ${FALCO_DRIVER_CURL_OPTIONS} -o "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}" "${URL}"; then
|
||||
>&2 echo "Unable to find a prebuilt ${DRIVER_NAME} eBPF probe"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
load_bpf_probe() {
|
||||
|
||||
if [ ! -d /sys/kernel/debug/tracing ]; then
|
||||
echo "* Mounting debugfs"
|
||||
mount -t debugfs nodev /sys/kernel/debug
|
||||
fi
|
||||
|
||||
BPF_PROBE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o"
|
||||
echo "* Filename '${BPF_PROBE_FILENAME}' is composed of:"
|
||||
print_filename_components
|
||||
|
||||
if [ -n "$ENABLE_DOWNLOAD" ]; then
|
||||
if [ -f "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}" ]; then
|
||||
echo "* Skipping download, eBPF probe is already present in ${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}"
|
||||
else
|
||||
IFS=", " read -r -a urls <<< "${DRIVERS_REPO}"
|
||||
for url in "${urls[@]}"; do
|
||||
load_bpf_probe_download $url
|
||||
if [ $? -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$ENABLE_COMPILE" ]; then
|
||||
if [ -f "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}" ]; then
|
||||
echo "* Skipping compilation, eBPF probe is already present in ${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}"
|
||||
else
|
||||
load_bpf_probe_compile
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}" ]; then
|
||||
echo "* eBPF probe located in ${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}"
|
||||
|
||||
ln -sf "${HOME}/.falco/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}" "${HOME}/.falco/${DRIVER_NAME}-bpf.o" \
|
||||
&& echo "* Success: eBPF probe symlinked to ${HOME}/.falco/${DRIVER_NAME}-bpf.o"
|
||||
exit $?
|
||||
else
|
||||
>&2 echo "Unable to load the ${DRIVER_NAME} eBPF probe"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
print_usage() {
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " falco-driver-loader [driver] [options]"
|
||||
echo ""
|
||||
echo "Available drivers:"
|
||||
echo " module kernel module (default)"
|
||||
echo " bpf eBPF probe"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help show brief help"
|
||||
echo " --clean try to remove an already present driver installation"
|
||||
echo " --compile try to compile the driver locally (default true)"
|
||||
echo " --download try to download a prebuilt driver (default true)"
|
||||
echo " --source-only skip execution and allow sourcing in another script using `. falco-driver-loader`"
|
||||
echo " --print-env skip execution and print env variables for other tools to consume"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " DRIVERS_REPO specify different URL(s) where to look for prebuilt Falco drivers (comma separated)"
|
||||
echo " DRIVER_NAME specify a different name for the driver"
|
||||
echo " DRIVER_INSECURE_DOWNLOAD whether you want to allow insecure downloads or not"
|
||||
echo " DRIVER_CURL_OPTIONS specify additional options to be passed to curl command used to download Falco drivers"
|
||||
echo " DRIVER_KERNEL_RELEASE specify the kernel release for which to download/build the driver in the same format used by 'uname -r' (e.g. '6.1.0-10-cloud-amd64')"
|
||||
echo " DRIVER_KERNEL_VERSION specify the kernel version for which to download/build the driver in the same format used by 'uname -v' (e.g. '#1 SMP PREEMPT_DYNAMIC Debian 6.1.38-2 (2023-07-27)')"
|
||||
echo ""
|
||||
echo "Versions:"
|
||||
echo " Falco version ${FALCO_VERSION}"
|
||||
echo " Driver version ${DRIVER_VERSION}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
ARCH=$(uname -m)
|
||||
|
||||
DRIVER_KERNEL_RELEASE=${DRIVER_KERNEL_RELEASE:-$(uname -r)}
|
||||
KERNEL_RELEASE=${DRIVER_KERNEL_RELEASE}
|
||||
|
||||
if ! hash sed > /dev/null 2>&1; then
|
||||
>&2 echo "This program requires sed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DRIVER_KERNEL_VERSION=${DRIVER_KERNEL_VERSION:-$(uname -v)}
|
||||
KERNEL_VERSION=$(echo "${DRIVER_KERNEL_VERSION}" | sed 's/#\([[:digit:]]\+\).*/\1/')
|
||||
|
||||
DRIVERS_REPO=${DRIVERS_REPO:-"@DRIVERS_REPO@"}
|
||||
|
||||
FALCO_DRIVER_CURL_OPTIONS="-fsS --connect-timeout 5 --max-time 60 --retry 3 --retry-max-time 120"
|
||||
|
||||
if [ -n "$DRIVER_INSECURE_DOWNLOAD" ]
|
||||
then
|
||||
FALCO_DRIVER_CURL_OPTIONS+=" -k"
|
||||
fi
|
||||
|
||||
FALCO_DRIVER_CURL_OPTIONS+=" "${DRIVER_CURL_OPTIONS}
|
||||
|
||||
if [[ -z "$MAX_RMMOD_WAIT" ]]; then
|
||||
MAX_RMMOD_WAIT=60
|
||||
fi
|
||||
|
||||
DRIVER_VERSION=${DRIVER_VERSION:-"@DRIVER_VERSION@"}
|
||||
DRIVER_NAME=${DRIVER_NAME:-"@DRIVER_NAME@"}
|
||||
FALCO_VERSION="@FALCO_VERSION@"
|
||||
|
||||
TARGET_ID=
|
||||
get_target_id
|
||||
|
||||
DRIVER="module"
|
||||
if [ -v FALCO_BPF_PROBE ]; then
|
||||
DRIVER="bpf"
|
||||
fi
|
||||
|
||||
TMPDIR=${TMPDIR:-"/tmp"}
|
||||
|
||||
ENABLE_COMPILE=
|
||||
ENABLE_DOWNLOAD=
|
||||
|
||||
clean=
|
||||
has_args=
|
||||
has_opts=
|
||||
print_env=
|
||||
source_only=
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
module|bpf)
|
||||
if [ -n "$has_args" ]; then
|
||||
>&2 echo "Only one driver per invocation"
|
||||
print_usage
|
||||
exit 1
|
||||
else
|
||||
DRIVER="$1"
|
||||
has_args="true"
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--clean)
|
||||
clean="true"
|
||||
shift
|
||||
;;
|
||||
--compile)
|
||||
ENABLE_COMPILE="yes"
|
||||
has_opts="true"
|
||||
shift
|
||||
;;
|
||||
--download)
|
||||
ENABLE_DOWNLOAD="yes"
|
||||
has_opts="true"
|
||||
shift
|
||||
;;
|
||||
--source-only)
|
||||
source_only="true"
|
||||
shift
|
||||
;;
|
||||
--print-env)
|
||||
print_env="true"
|
||||
shift
|
||||
;;
|
||||
--*)
|
||||
>&2 echo "Unknown option: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
>&2 echo "Unknown driver: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$has_opts" ]; then
|
||||
ENABLE_COMPILE="yes"
|
||||
ENABLE_DOWNLOAD="yes"
|
||||
fi
|
||||
|
||||
if [ -n "$source_only" ]; then
|
||||
# Return or exit, depending if we've been sourced.
|
||||
(return 0 2>/dev/null) && return || exit 0
|
||||
fi
|
||||
|
||||
if [ -n "$print_env" ]; then
|
||||
print_as_env_vars
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "* Running falco-driver-loader for: falco version=${FALCO_VERSION}, driver version=${DRIVER_VERSION}, arch=${ARCH}, kernel release=${KERNEL_RELEASE}, kernel version=${KERNEL_VERSION}"
|
||||
|
||||
if [ "$(id -u)" != 0 ]; then
|
||||
>&2 echo "This program must be run as root (or with sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$TARGET_ID" = "undetermined" ]; then
|
||||
if [ -n "$ENABLE_COMPILE" ]; then
|
||||
ENABLE_DOWNLOAD=
|
||||
>&2 echo "Detected an unsupported target system, please get in touch with the Falco community. Trying to compile anyway."
|
||||
else
|
||||
>&2 echo "Detected an unsupported target system, please get in touch with the Falco community."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$clean" ]; then
|
||||
if [ -n "$has_opts" ]; then
|
||||
>&2 echo "Cannot use --clean with other options"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "* Running falco-driver-loader with: driver=$DRIVER, clean=yes"
|
||||
case $DRIVER in
|
||||
module)
|
||||
clean_kernel_module
|
||||
;;
|
||||
bpf)
|
||||
>&2 echo "--clean not supported for driver=bpf"
|
||||
exit 1
|
||||
esac
|
||||
else
|
||||
if ! hash curl > /dev/null 2>&1; then
|
||||
>&2 echo "This program requires curl"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "* Running falco-driver-loader with: driver=$DRIVER, compile=${ENABLE_COMPILE:-"no"}, download=${ENABLE_DOWNLOAD:-"no"}"
|
||||
case $DRIVER in
|
||||
module)
|
||||
load_kernel_module
|
||||
;;
|
||||
bpf)
|
||||
load_bpf_probe
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
@@ -1,3 +1,10 @@
|
||||
driver:
|
||||
type: "kmod"
|
||||
name: "@DRIVER_NAME@"
|
||||
repos:
|
||||
- "@DRIVERS_REPO@"
|
||||
version: "@DRIVER_VERSION@"
|
||||
hostroot: "/"
|
||||
artifact:
|
||||
follow:
|
||||
every: 6h0m0s
|
||||
@@ -17,6 +17,8 @@
|
||||
#
|
||||
|
||||
chosen_driver=
|
||||
chosen_unit=
|
||||
CHOICE=
|
||||
|
||||
# Every time we call this script we want to stat from a clean state.
|
||||
echo "[POST-INSTALL] Disable all possible enabled 'falco' service:"
|
||||
@@ -35,7 +37,18 @@ systemctl --system disable 'falcoctl-artifact-follow.service' || true
|
||||
systemctl --system unmask falcoctl-artifact-follow.service || true
|
||||
|
||||
if [ $1 -ge 1 ]; then
|
||||
if [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
case $FALCO_DRIVER_CHOICE in
|
||||
kmod)
|
||||
CHOICE=2
|
||||
;;
|
||||
ebpf)
|
||||
CHOICE=3
|
||||
;;
|
||||
modern_ebpf)
|
||||
CHOICE=4
|
||||
;;
|
||||
esac
|
||||
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
# If dialog is installed, create a dialog to let users choose the correct driver for them
|
||||
CHOICE=$(dialog --clear --title "Falco drivers" --menu "Choose your preferred driver:" 12 55 4 \
|
||||
1 "Manual configuration (no unit is started)" \
|
||||
@@ -43,31 +56,44 @@ if [ $1 -ge 1 ]; then
|
||||
3 "eBPF" \
|
||||
4 "Modern eBPF" \
|
||||
2>&1 >/dev/tty)
|
||||
case $CHOICE in
|
||||
2)
|
||||
chosen_driver="kmod"
|
||||
;;
|
||||
3)
|
||||
chosen_driver="bpf"
|
||||
;;
|
||||
4)
|
||||
chosen_driver="modern-bpf"
|
||||
fi
|
||||
case $CHOICE in
|
||||
2)
|
||||
chosen_driver="kmod"
|
||||
chosen_unit="kmod"
|
||||
;;
|
||||
3)
|
||||
chosen_driver="ebpf"
|
||||
chosen_unit="bpf"
|
||||
;;
|
||||
4)
|
||||
chosen_driver="modern_ebpf"
|
||||
chosen_unit="modern-bpf"
|
||||
;;
|
||||
esac
|
||||
if [ -n "$CHOICE" ]; then
|
||||
echo "[POST-INSTALL] Configure falcoctl driver type:"
|
||||
falcoctl driver config --type $chosen_driver
|
||||
CHOICE=
|
||||
case $FALCOCTL_ENABLED in
|
||||
no)
|
||||
CHOICE=2
|
||||
;;
|
||||
esac
|
||||
if [ -n "$chosen_driver" ]; then
|
||||
CHOICE=$(dialog --clear --title "Falcoctl" --menu "Do you want to follow automatic ruleset updates?" 10 40 2 \
|
||||
1 "Yes" \
|
||||
2 "No" \
|
||||
2>&1 >/dev/tty)
|
||||
case $CHOICE in
|
||||
2)
|
||||
# we don't want falcoctl enabled, we mask it
|
||||
systemctl --system mask falcoctl-artifact-follow.service || true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
clear
|
||||
fi
|
||||
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
CHOICE=$(dialog --clear --title "Falcoctl" --menu "Do you want to follow automatic ruleset updates?" 10 40 2 \
|
||||
1 "Yes" \
|
||||
2 "No" \
|
||||
2>&1 >/dev/tty)
|
||||
fi
|
||||
case $CHOICE in
|
||||
2)
|
||||
# we don't want falcoctl enabled, we mask it
|
||||
systemctl --system mask falcoctl-artifact-follow.service || true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
clear
|
||||
fi
|
||||
|
||||
set -e
|
||||
@@ -75,16 +101,16 @@ set -e
|
||||
echo "[POST-INSTALL] Trigger deamon-reload:"
|
||||
systemctl --system daemon-reload || true
|
||||
|
||||
# If needed, try to load/compile the driver through falco-driver-loader
|
||||
# If needed, try to load/compile the driver through falcoctl
|
||||
case "$chosen_driver" in
|
||||
"kmod")
|
||||
# Only compile for kmod, in this way we use dkms
|
||||
echo "[POST-INSTALL] Call 'falco-driver-loader --compile module':"
|
||||
falco-driver-loader --compile module
|
||||
echo "[POST-INSTALL] Call 'falcoctl driver install for kmod:"
|
||||
falcoctl driver install --download=false
|
||||
;;
|
||||
"bpf")
|
||||
echo "[POST-INSTALL] Call 'falco-driver-loader bpf':"
|
||||
falco-driver-loader bpf
|
||||
"ebpf")
|
||||
echo "[POST-INSTALL] Call 'falcoctl driver install for ebpf':"
|
||||
falcoctl driver install
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -95,14 +121,14 @@ esac
|
||||
# systemd_post macro expands to
|
||||
# if postinst:
|
||||
# `systemd-update-helper install-system-units <service>`
|
||||
%systemd_post "falco-$chosen_driver.service"
|
||||
%systemd_post "falco-$chosen_unit.service"
|
||||
|
||||
# post install/upgrade mirrored from .deb
|
||||
if [ $1 -ge 1 ]; then
|
||||
if [ -n "$chosen_driver" ]; then
|
||||
echo "[POST-INSTALL] Enable 'falco-$chosen_driver.service':"
|
||||
systemctl --system enable "falco-$chosen_driver.service" || true
|
||||
echo "[POST-INSTALL] Start 'falco-$chosen_driver.service':"
|
||||
systemctl --system start "falco-$chosen_driver.service" || true
|
||||
if [ -n "$chosen_unit" ]; then
|
||||
echo "[POST-INSTALL] Enable 'falco-$chosen_unit.service':"
|
||||
systemctl --system enable "falco-$chosen_unit.service" || true
|
||||
echo "[POST-INSTALL] Start 'falco-$chosen_unit.service':"
|
||||
systemctl --system start "falco-$chosen_unit.service" || true
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -25,8 +25,8 @@ systemctl --system stop 'falco-modern-bpf.service' || true
|
||||
systemctl --system stop 'falco-custom.service' || true
|
||||
systemctl --system stop 'falcoctl-artifact-follow.service' || true
|
||||
|
||||
echo "[PRE-REMOVE] Call 'falco-driver-loader --clean:'"
|
||||
falco-driver-loader --clean
|
||||
echo "[PRE-REMOVE] Call 'falcoctl driver cleanup:'"
|
||||
falcoctl driver cleanup
|
||||
|
||||
# validate rpm macros by `rpm -qp --scripts <rpm>`
|
||||
# RPM scriptlets: https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/#_systemd
|
||||
|
||||
@@ -7,8 +7,7 @@ Wants=falcoctl-artifact-follow.service
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
Environment=FALCO_BPF_PROBE=
|
||||
ExecStart=/usr/bin/falco
|
||||
ExecStart=/usr/bin/falco -o engine.kind=ebpf
|
||||
ExecReload=kill -1 $MAINPID
|
||||
UMask=0077
|
||||
TimeoutSec=30
|
||||
|
||||
@@ -9,7 +9,7 @@ Wants=falcoctl-artifact-follow.service
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/bin/falco
|
||||
ExecStart=/usr/bin/falco -o engine.kind=kmod
|
||||
ExecReload=kill -1 $MAINPID
|
||||
UMask=0077
|
||||
TimeoutSec=30
|
||||
|
||||
@@ -7,7 +7,7 @@ Wants=falcoctl-artifact-follow.service
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/bin/falco --modern-bpf
|
||||
ExecStart=/usr/bin/falco -o engine.kind=modern_ebpf
|
||||
ExecReload=kill -1 $MAINPID
|
||||
UMask=0077
|
||||
TimeoutSec=30
|
||||
|
||||
44
semgrep/insecure-api-gets.yaml
Normal file
44
semgrep/insecure-api-gets.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2022 raptor
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
rules:
|
||||
- id: raptor-insecure-api-gets
|
||||
metadata:
|
||||
author: Marco Ivaldi <raptor@0xdeadbeef.info>
|
||||
references:
|
||||
- https://cwe.mitre.org/data/definitions/242
|
||||
- https://cwe.mitre.org/data/definitions/120
|
||||
confidence: HIGH
|
||||
message: >-
|
||||
The program calls a function that can never be guaranteed to work
|
||||
safely.
|
||||
Certain functions behave in dangerous ways regardless of how they are
|
||||
used. Functions in this category were often implemented without
|
||||
taking security concerns into account. The gets() function is unsafe
|
||||
because it does not perform bounds checking on the size of its input.
|
||||
An attacker can easily send arbitrarily-sized input to gets() and
|
||||
overflow the destination buffer.
|
||||
severity: ERROR
|
||||
languages:
|
||||
- c
|
||||
- cpp
|
||||
pattern: gets(...)
|
||||
57
semgrep/insecure-api-sprintf-vsprintf.yaml
Normal file
57
semgrep/insecure-api-sprintf-vsprintf.yaml
Normal file
@@ -0,0 +1,57 @@
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2022 raptor
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
rules:
|
||||
- id: raptor-insecure-api-sprintf-vsprintf
|
||||
metadata:
|
||||
author: Marco Ivaldi <raptor@0xdeadbeef.info>
|
||||
references:
|
||||
- https://cwe.mitre.org/data/definitions/676
|
||||
- https://cwe.mitre.org/data/definitions/120
|
||||
- https://cwe.mitre.org/data/definitions/787
|
||||
- https://g.co/kgs/PCHQjJ
|
||||
confidence: HIGH
|
||||
message: >-
|
||||
The program invokes a potentially dangerous function that could
|
||||
introduce a vulnerability if it is used incorrectly, but the function
|
||||
can also be used safely.
|
||||
A buffer overflow condition exists when a program attempts to put
|
||||
more data in a buffer than it can hold, or when a program attempts to
|
||||
put data in a memory area outside of the boundaries of a buffer. The
|
||||
simplest type of error, and the most common cause of buffer
|
||||
overflows, is the classic case in which the program copies the buffer
|
||||
without restricting how much is copied. Other variants exist, but the
|
||||
existence of a classic overflow strongly suggests that the programmer
|
||||
is not considering even the most basic of security protections.
|
||||
severity: ERROR
|
||||
languages:
|
||||
- c
|
||||
- cpp
|
||||
patterns:
|
||||
- pattern-either:
|
||||
- pattern: sprintf($BUF, $FMT, ...)
|
||||
- pattern: vsprintf($BUF, $FMT, ...)
|
||||
# swprintf() and vswprintf() should have a size parameter
|
||||
- metavariable-regex:
|
||||
metavariable: $FMT
|
||||
# NOTE: some format string modifiers are not handled
|
||||
regex: '(".*%l?s.*"|".*%S.*"|[a-zA-Z_][a-zA-Z0-9_]*)'
|
||||
59
semgrep/insecure-api-strcpy-stpcpy-strcat.yaml
Normal file
59
semgrep/insecure-api-strcpy-stpcpy-strcat.yaml
Normal file
@@ -0,0 +1,59 @@
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2022 raptor
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
rules:
|
||||
- id: raptor-insecure-api-strcpy-stpcpy-strcat
|
||||
metadata:
|
||||
author: Marco Ivaldi <raptor@0xdeadbeef.info>
|
||||
references:
|
||||
- https://cwe.mitre.org/data/definitions/676
|
||||
- https://cwe.mitre.org/data/definitions/120
|
||||
- https://cwe.mitre.org/data/definitions/787
|
||||
- https://g.co/kgs/PCHQjJ
|
||||
confidence: HIGH
|
||||
message: >-
|
||||
The program invokes a potentially dangerous function that could
|
||||
introduce a vulnerability if it is used incorrectly, but the function
|
||||
can also be used safely.
|
||||
A buffer overflow condition exists when a program attempts to put
|
||||
more data in a buffer than it can hold, or when a program attempts to
|
||||
put data in a memory area outside of the boundaries of a buffer. The
|
||||
simplest type of error, and the most common cause of buffer
|
||||
overflows, is the classic case in which the program copies the buffer
|
||||
without restricting how much is copied. Other variants exist, but the
|
||||
existence of a classic overflow strongly suggests that the programmer
|
||||
is not considering even the most basic of security protections.
|
||||
|
||||
In the Falco codebase you can use the safer alternative strlcpy().
|
||||
severity: ERROR
|
||||
languages:
|
||||
- c
|
||||
- cpp
|
||||
patterns:
|
||||
- pattern-either:
|
||||
- pattern: strcpy(...)
|
||||
- pattern: stpcpy(...)
|
||||
- pattern: strcat(...)
|
||||
- pattern: wcscpy(...)
|
||||
- pattern: wcpcpy(...)
|
||||
- pattern: wcscat(...)
|
||||
- pattern-not: $FUN($BUF, "...", ...)
|
||||
18
semgrep/insecure-api-strn.yaml
Normal file
18
semgrep/insecure-api-strn.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
rules:
|
||||
- id: falco-insecure-api-strn
|
||||
metadata:
|
||||
references:
|
||||
- https://cwe.mitre.org/data/definitions/120
|
||||
confidence: HIGH
|
||||
message: >-
|
||||
The libc function strncpy and strncat are not used in the Falco codebase as they are error prone.
|
||||
Read more: https://www.cisa.gov/uscert/bsi/articles/knowledge/coding-practices/strncpy-and-strncat .
|
||||
In the Falco codebase you can use the safer alternatives strlcpy() and strlcat().
|
||||
severity: ERROR
|
||||
languages:
|
||||
- c
|
||||
- cpp
|
||||
patterns:
|
||||
- pattern-either:
|
||||
- pattern: strncpy(...)
|
||||
- pattern: strncat(...)
|
||||
Submodule submodules/falcosecurity-rules updated: 77ba57ab2c...262f56986e
Submodule submodules/falcosecurity-testing updated: 62edc65a03...930170bb0b
@@ -27,10 +27,18 @@ FetchContent_MakeAvailable(googletest)
|
||||
file(GLOB_RECURSE ENGINE_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/engine/*.cpp)
|
||||
file(GLOB_RECURSE FALCO_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/falco/*.cpp)
|
||||
|
||||
# Create a libscap_test_var.h file with some variables used by our tests
|
||||
# for example the kmod path or the bpf path.
|
||||
configure_file (
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/falco_test_var.h.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/falco_test_var.h"
|
||||
)
|
||||
|
||||
set(FALCO_UNIT_TESTS_SOURCES
|
||||
"${ENGINE_TESTS}"
|
||||
falco/test_configuration.cpp
|
||||
falco/app/actions/test_select_event_sources.cpp
|
||||
falco/app/actions/test_load_config.cpp
|
||||
)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
@@ -45,6 +53,7 @@ set(FALCO_UNIT_TESTS_INCLUDES
|
||||
${CMAKE_SOURCE_DIR}/userspace
|
||||
${CMAKE_BINARY_DIR}/userspace/falco # we need it to include indirectly `config_falco.h` file
|
||||
${CMAKE_SOURCE_DIR}/userspace/engine # we need it to include indirectly `falco_common.h` file
|
||||
"${CMAKE_CURRENT_BINARY_DIR}" # we need it to include `falco_test_var.h`
|
||||
)
|
||||
|
||||
set(FALCO_UNIT_TESTS_DEPENDENCIES
|
||||
|
||||
251
unit_tests/engine/test_enable_rule.cpp
Normal file
251
unit_tests/engine/test_enable_rule.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <sinsp.h>
|
||||
#include <filter_check_list.h>
|
||||
#include <filter.h>
|
||||
|
||||
#include <falco_engine.h>
|
||||
|
||||
static std::string single_rule = R"END(
|
||||
- rule: test rule
|
||||
desc: A test rule
|
||||
condition: evt.type=execve
|
||||
output: A test rule matched (evt.type=%evt.type)
|
||||
priority: INFO
|
||||
source: syscall
|
||||
tags: [process]
|
||||
|
||||
- rule: disabled rule
|
||||
desc: A disabled rule
|
||||
condition: evt.type=execve
|
||||
output: A disabled rule matched (evt.type=%evt.type)
|
||||
priority: INFO
|
||||
source: syscall
|
||||
enabled: false
|
||||
tags: [exec process]
|
||||
)END";
|
||||
|
||||
// This must be kept in line with the (private) falco_engine::s_default_ruleset
|
||||
static const std::string default_ruleset = "falco-default-ruleset";
|
||||
|
||||
static const std::string ruleset_1 = "ruleset-1";
|
||||
static const std::string ruleset_2 = "ruleset-2";
|
||||
static const std::string ruleset_3 = "ruleset-3";
|
||||
static const std::string ruleset_4 = "ruleset-4";
|
||||
|
||||
static void load_rules(falco_engine& engine, sinsp& inspector, sinsp_filter_check_list& filterchecks)
|
||||
{
|
||||
std::unique_ptr<falco::load_result> res;
|
||||
|
||||
auto filter_factory = std::shared_ptr<gen_event_filter_factory>(
|
||||
new sinsp_filter_factory(&inspector, filterchecks));
|
||||
auto formatter_factory = std::shared_ptr<gen_event_formatter_factory>(
|
||||
new sinsp_evt_formatter_factory(&inspector, filterchecks));
|
||||
|
||||
engine.add_source("syscall", filter_factory, formatter_factory);
|
||||
|
||||
res = engine.load_rules(single_rule, "single_rule.yaml");
|
||||
|
||||
EXPECT_TRUE(res->successful());
|
||||
}
|
||||
|
||||
TEST(EnableRule, enable_rule_name)
|
||||
{
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
|
||||
load_rules(engine, inspector, filterchecks);
|
||||
|
||||
// No rules should be enabled yet for any custom rulesets
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(default_ruleset));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
// Enable for first ruleset, only that ruleset should have an
|
||||
// enabled rule afterward
|
||||
engine.enable_rule("test", true, ruleset_1);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
// Enable for second ruleset
|
||||
engine.enable_rule("test", true, ruleset_2);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
// When the substring is blank, all rules are enabled
|
||||
// (including the disabled rule)
|
||||
engine.enable_rule("", true, ruleset_3);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(2, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
// Now disable for second ruleset
|
||||
engine.enable_rule("test", false, ruleset_2);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(2, engine.num_rules_for_ruleset(ruleset_3));
|
||||
}
|
||||
|
||||
TEST(EnableRule, enable_rule_tags)
|
||||
{
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
std::set<std::string> process_tags = {"process"};
|
||||
|
||||
load_rules(engine, inspector, filterchecks);
|
||||
|
||||
// No rules should be enabled yet for any custom rulesets
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(default_ruleset));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
|
||||
// Enable for first ruleset, only that ruleset should have an
|
||||
// enabled rule afterward
|
||||
engine.enable_rule_by_tag(process_tags, true, ruleset_1);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
|
||||
// Enable for second ruleset
|
||||
engine.enable_rule_by_tag(process_tags, true, ruleset_2);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
|
||||
// Now disable for second ruleset
|
||||
engine.enable_rule_by_tag(process_tags, false, ruleset_2);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
}
|
||||
|
||||
TEST(EnableRule, enable_disabled_rule_by_tag)
|
||||
{
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
std::set<std::string> exec_process_tags = {"exec process"};
|
||||
|
||||
load_rules(engine, inspector, filterchecks);
|
||||
|
||||
// Only the first rule should be enabled
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(default_ruleset));
|
||||
|
||||
// Enable the disabled rule by tag
|
||||
engine.enable_rule_by_tag(exec_process_tags, true);
|
||||
|
||||
// Both rules should be enabled now
|
||||
EXPECT_EQ(2, engine.num_rules_for_ruleset(default_ruleset));
|
||||
}
|
||||
|
||||
TEST(EnableRule, enable_rule_id)
|
||||
{
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
uint16_t ruleset_1_id;
|
||||
uint16_t ruleset_2_id;
|
||||
uint16_t ruleset_3_id;
|
||||
|
||||
load_rules(engine, inspector, filterchecks);
|
||||
|
||||
// The cases are identical to above, just using ruleset ids
|
||||
// instead of names.
|
||||
|
||||
ruleset_1_id = engine.find_ruleset_id(ruleset_1);
|
||||
ruleset_2_id = engine.find_ruleset_id(ruleset_2);
|
||||
ruleset_3_id = engine.find_ruleset_id(ruleset_3);
|
||||
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(default_ruleset));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
engine.enable_rule("test rule", true, ruleset_1_id);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
engine.enable_rule("test rule", true, ruleset_2_id);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
engine.enable_rule("", true, ruleset_3_id);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(2, engine.num_rules_for_ruleset(ruleset_3));
|
||||
|
||||
engine.enable_rule("test", false, ruleset_2_id);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(2, engine.num_rules_for_ruleset(ruleset_3));
|
||||
}
|
||||
|
||||
TEST(EnableRule, enable_rule_name_exact)
|
||||
{
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
|
||||
load_rules(engine, inspector, filterchecks);
|
||||
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(default_ruleset));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_4));
|
||||
|
||||
engine.enable_rule_exact("test rule", true, ruleset_1);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_4));
|
||||
|
||||
engine.enable_rule_exact("test rule", true, ruleset_2);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_4));
|
||||
|
||||
// This should **not** enable as this is a substring and not
|
||||
// an exact match.
|
||||
engine.enable_rule_exact("test", true, ruleset_3);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_4));
|
||||
|
||||
engine.enable_rule_exact("", true, ruleset_4);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
EXPECT_EQ(2, engine.num_rules_for_ruleset(ruleset_4));
|
||||
|
||||
engine.enable_rule("test rule", false, ruleset_2);
|
||||
EXPECT_EQ(1, engine.num_rules_for_ruleset(ruleset_1));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_2));
|
||||
EXPECT_EQ(0, engine.num_rules_for_ruleset(ruleset_3));
|
||||
EXPECT_EQ(2, engine.num_rules_for_ruleset(ruleset_4));
|
||||
}
|
||||
@@ -37,17 +37,17 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST)
|
||||
{
|
||||
libsinsp::filter::ast::pos_info macro_pos(12, 85, 27);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> filter_and;
|
||||
filter_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
|
||||
filter_and.push_back(libsinsp::filter::ast::not_expr::create(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos)));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::and_expr::create(filter_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::and_expr::create(filter_and);
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_and;
|
||||
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
|
||||
expected_and.push_back(libsinsp::filter::ast::not_expr::create(clone(macro.get())));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected = std::move(libsinsp::filter::ast::and_expr::create(expected_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected = libsinsp::filter::ast::and_expr::create(expected_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -71,9 +71,9 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_single_node)
|
||||
{
|
||||
libsinsp::filter::ast::pos_info macro_pos(12, 85, 27);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -102,18 +102,18 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_multiple_macros)
|
||||
libsinsp::filter::ast::pos_info a_macro_pos(11, 75, 43);
|
||||
libsinsp::filter::ast::pos_info b_macro_pos(91, 21, 9);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = std::move(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro = std::move(libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists");
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro = libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists");
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> filter_or;
|
||||
filter_or.push_back(libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos));
|
||||
filter_or.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::or_expr::create(filter_or));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::or_expr::create(filter_or);
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_or;
|
||||
expected_or.push_back(clone(a_macro.get()));
|
||||
expected_or.push_back(clone(b_macro.get()));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = std::move(libsinsp::filter::ast::or_expr::create(expected_or));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = libsinsp::filter::ast::or_expr::create(expected_or);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_A_NAME, a_macro);
|
||||
@@ -149,17 +149,17 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_nested_macros)
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> a_macro_and;
|
||||
a_macro_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
a_macro_and.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = std::move(libsinsp::filter::ast::and_expr::create(a_macro_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::and_expr::create(a_macro_and);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro = std::move(
|
||||
libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_macro =
|
||||
libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists");
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_and;
|
||||
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = std::move(libsinsp::filter::ast::and_expr::create(expected_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = libsinsp::filter::ast::and_expr::create(expected_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_A_NAME, a_macro);
|
||||
@@ -196,7 +196,7 @@ TEST(MacroResolver, should_find_unknown_macros)
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> filter_and;
|
||||
filter_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
|
||||
filter_and.push_back(libsinsp::filter::ast::not_expr::create(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos)));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::and_expr::create(filter_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::and_expr::create(filter_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
ASSERT_FALSE(resolver.run(filter));
|
||||
@@ -214,9 +214,9 @@ TEST(MacroResolver, should_find_unknown_nested_macros)
|
||||
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> a_macro_and;
|
||||
a_macro_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
|
||||
a_macro_and.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = std::move(libsinsp::filter::ast::and_expr::create(a_macro_and));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::and_expr::create(a_macro_and);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
auto expected_filter = clone(a_macro.get());
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
@@ -237,9 +237,9 @@ TEST(MacroResolver, should_undefine_macro)
|
||||
libsinsp::filter::ast::pos_info macro_pos_1(12, 9, 3);
|
||||
libsinsp::filter::ast::pos_info macro_pos_2(9, 6, 3);
|
||||
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_1));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_2));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> a_filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_1);
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> b_filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_2);
|
||||
filter_macro_resolver resolver;
|
||||
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -262,8 +262,8 @@ TEST(MacroResolver, should_undefine_macro)
|
||||
TEST(MacroResolver, should_clone_macro_AST)
|
||||
{
|
||||
libsinsp::filter::ast::pos_info macro_pos(5, 2, 8888);
|
||||
std::shared_ptr<libsinsp::filter::ast::unary_check_expr> macro = std::move(libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists"));
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = std::move(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos));
|
||||
std::shared_ptr<libsinsp::filter::ast::unary_check_expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos);
|
||||
filter_macro_resolver resolver;
|
||||
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
|
||||
@@ -23,9 +23,9 @@ limitations under the License.
|
||||
#define RULESET_2 2
|
||||
|
||||
/* Helpers methods */
|
||||
static std::shared_ptr<gen_event_filter_factory> create_factory()
|
||||
static std::shared_ptr<gen_event_filter_factory> create_factory(filter_check_list& list)
|
||||
{
|
||||
std::shared_ptr<gen_event_filter_factory> ret(new sinsp_filter_factory(NULL));
|
||||
std::shared_ptr<gen_event_filter_factory> ret(new sinsp_filter_factory(NULL, list));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,8 @@ static std::shared_ptr<gen_event_filter> create_filter(
|
||||
|
||||
TEST(Ruleset, enable_disable_rules_using_names)
|
||||
{
|
||||
auto f = create_factory();
|
||||
sinsp_filter_check_list filterlist;
|
||||
auto f = create_factory(filterlist);
|
||||
auto r = create_ruleset(f);
|
||||
auto ast = create_ast(f);
|
||||
auto filter = create_filter(f, ast);
|
||||
@@ -119,7 +120,8 @@ TEST(Ruleset, enable_disable_rules_using_names)
|
||||
|
||||
TEST(Ruleset, enable_disable_rules_using_tags)
|
||||
{
|
||||
auto f = create_factory();
|
||||
sinsp_filter_check_list filterlist;
|
||||
auto f = create_factory(filterlist);
|
||||
auto r = create_ruleset(f);
|
||||
auto ast = create_ast(f);
|
||||
auto filter = create_filter(f, ast);
|
||||
|
||||
@@ -19,5 +19,5 @@ limitations under the License.
|
||||
#include <falco/app/state.h>
|
||||
#include <falco/app/actions/actions.h>
|
||||
|
||||
#define EXPECT_ACTION_OK(r) { EXPECT_TRUE(r.success); EXPECT_TRUE(r.proceed); EXPECT_EQ(r.errstr, ""); }
|
||||
#define EXPECT_ACTION_FAIL(r) { EXPECT_FALSE(r.success); EXPECT_FALSE(r.proceed); EXPECT_NE(r.errstr, ""); }
|
||||
#define EXPECT_ACTION_OK(r) { auto result = r; EXPECT_TRUE(result.success); EXPECT_TRUE(result.proceed); EXPECT_EQ(result.errstr, ""); }
|
||||
#define EXPECT_ACTION_FAIL(r) { auto result = r; EXPECT_FALSE(result.success); EXPECT_FALSE(result.proceed); EXPECT_NE(result.errstr, ""); }
|
||||
|
||||
@@ -77,11 +77,12 @@ static std::shared_ptr<falco_engine> mock_engine_from_filters(const strset_t& fi
|
||||
}
|
||||
|
||||
// create a falco engine and load the ruleset
|
||||
sinsp_filter_check_list filterlist;
|
||||
std::shared_ptr<falco_engine> res(new falco_engine());
|
||||
auto filter_factory = std::shared_ptr<gen_event_filter_factory>(
|
||||
new sinsp_filter_factory(nullptr));
|
||||
new sinsp_filter_factory(nullptr, filterlist));
|
||||
auto formatter_factory = std::shared_ptr<gen_event_formatter_factory>(
|
||||
new sinsp_evt_formatter_factory(nullptr));
|
||||
new sinsp_evt_formatter_factory(nullptr, filterlist));
|
||||
res->add_source(s_sample_source, filter_factory, formatter_factory);
|
||||
res->load_rules(dummy_rules, "dummy_rules.yaml");
|
||||
res->enable_rule("", true, s_sample_ruleset);
|
||||
|
||||
@@ -27,30 +27,30 @@ TEST(ActionConfigureSyscallBufferNum, variable_number_of_CPUs)
|
||||
FAIL() << "cannot get the number of online CPUs from the system\n";
|
||||
}
|
||||
|
||||
// not modern bpf engine, we do nothing
|
||||
// not modern ebpf engine, we do nothing
|
||||
{
|
||||
falco::app::state s;
|
||||
s.options.modern_bpf = false;
|
||||
s.config->m_engine_mode = engine_kind_t::MODERN_EBPF;
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
}
|
||||
|
||||
// modern bpf engine, with an invalid number of CPUs
|
||||
// modern ebpf engine, with an invalid number of CPUs
|
||||
// default `m_cpus_for_each_syscall_buffer` to online CPU number
|
||||
{
|
||||
falco::app::state s;
|
||||
s.options.modern_bpf = true;
|
||||
s.config->m_cpus_for_each_syscall_buffer = online_cpus + 1;
|
||||
s.config->m_engine_mode = engine_kind_t::MODERN_EBPF;
|
||||
s.config->m_modern_ebpf.m_cpus_for_each_buffer = online_cpus + 1;
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.config->m_cpus_for_each_syscall_buffer, online_cpus);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, online_cpus);
|
||||
}
|
||||
|
||||
// modern bpf engine, with an valid number of CPUs
|
||||
// modern ebpf engine, with a valid number of CPUs
|
||||
// we don't modify `m_cpus_for_each_syscall_buffer`
|
||||
{
|
||||
falco::app::state s;
|
||||
s.options.modern_bpf = true;
|
||||
s.config->m_cpus_for_each_syscall_buffer = online_cpus - 1;
|
||||
s.config->m_engine_mode = engine_kind_t::MODERN_EBPF;
|
||||
s.config->m_modern_ebpf.m_cpus_for_each_buffer = online_cpus - 1;
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.config->m_cpus_for_each_syscall_buffer, online_cpus - 1);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, online_cpus - 1);
|
||||
}
|
||||
}
|
||||
|
||||
196
unit_tests/falco/app/actions/test_load_config.cpp
Normal file
196
unit_tests/falco/app/actions/test_load_config.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 ASSERTd 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 "app_action_helpers.h"
|
||||
#include "falco_test_var.h"
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
TEST(ActionLoadConfig, check_engine_config_is_correctly_parsed)
|
||||
{
|
||||
falco::app::state s = {};
|
||||
s.options.conf_filename = NEW_ENGINE_CONFIG_CHANGED;
|
||||
EXPECT_ACTION_OK(falco::app::actions::load_config(s));
|
||||
|
||||
// Check that the engine is the kmod
|
||||
EXPECT_TRUE(s.config->m_engine_mode == engine_kind_t::KMOD);
|
||||
|
||||
// Check that kmod params are the ones specified in the config
|
||||
EXPECT_EQ(s.config->m_kmod.m_buf_size_preset, 2);
|
||||
EXPECT_FALSE(s.config->m_kmod.m_drop_failed_exit);
|
||||
|
||||
// Check that all other engine params are empty
|
||||
EXPECT_TRUE(s.config->m_ebpf.m_probe_path.empty());
|
||||
EXPECT_EQ(s.config->m_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, 0);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_modern_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_replay.m_capture_file.empty());
|
||||
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_config.empty());
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
|
||||
// Check that deprecated configs are always set since
|
||||
EXPECT_EQ(s.config->m_syscall_buf_size_preset, 6);
|
||||
EXPECT_EQ(s.config->m_cpus_for_each_syscall_buffer, 7);
|
||||
EXPECT_TRUE(s.config->m_syscall_drop_failed_exit);
|
||||
}
|
||||
|
||||
// Equal to the one above but checks that the command line options are not parsed
|
||||
TEST(ActionLoadConfig, check_command_line_options_are_not_used)
|
||||
{
|
||||
falco::app::state s;
|
||||
s.options.modern_bpf = true;
|
||||
s.options.conf_filename = NEW_ENGINE_CONFIG_CHANGED;
|
||||
EXPECT_ACTION_OK(falco::app::actions::load_config(s));
|
||||
|
||||
// Check that the engine is the kmod
|
||||
EXPECT_TRUE(s.config->m_engine_mode == engine_kind_t::KMOD);
|
||||
|
||||
// Check that kmod params are the ones specified in the config
|
||||
EXPECT_EQ(s.config->m_kmod.m_buf_size_preset, 2);
|
||||
EXPECT_FALSE(s.config->m_kmod.m_drop_failed_exit);
|
||||
|
||||
// Check that all other engine params are empty
|
||||
EXPECT_TRUE(s.config->m_ebpf.m_probe_path.empty());
|
||||
EXPECT_EQ(s.config->m_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, 0);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_modern_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_replay.m_capture_file.empty());
|
||||
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_config.empty());
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
|
||||
// Check that deprecated configs are always set since
|
||||
EXPECT_EQ(s.config->m_syscall_buf_size_preset, 6);
|
||||
EXPECT_EQ(s.config->m_cpus_for_each_syscall_buffer, 7);
|
||||
EXPECT_TRUE(s.config->m_syscall_drop_failed_exit);
|
||||
}
|
||||
|
||||
TEST(ActionLoadConfig, check_kmod_with_syscall_configs)
|
||||
{
|
||||
falco::app::state s;
|
||||
s.options.conf_filename = NEW_ENGINE_CONFIG_UNCHANGED;
|
||||
EXPECT_ACTION_OK(falco::app::actions::load_config(s));
|
||||
|
||||
// Check that the engine is the kmod
|
||||
EXPECT_TRUE(s.config->m_engine_mode == engine_kind_t::KMOD);
|
||||
|
||||
// Kmod params should be populated with the syscall configs
|
||||
// since the `engine` block is untouched.
|
||||
EXPECT_EQ(s.config->m_kmod.m_buf_size_preset, 6);
|
||||
EXPECT_TRUE(s.config->m_kmod.m_drop_failed_exit);
|
||||
|
||||
// Check that all other engine params are empty
|
||||
EXPECT_TRUE(s.config->m_ebpf.m_probe_path.empty());
|
||||
EXPECT_EQ(s.config->m_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, 0);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_modern_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_replay.m_capture_file.empty());
|
||||
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_config.empty());
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
|
||||
// Check that deprecated configs are populated
|
||||
EXPECT_EQ(s.config->m_syscall_buf_size_preset, 6);
|
||||
EXPECT_EQ(s.config->m_cpus_for_each_syscall_buffer, 3);
|
||||
EXPECT_TRUE(s.config->m_syscall_drop_failed_exit);
|
||||
}
|
||||
|
||||
TEST(ActionLoadConfig, check_override_command_line_modern)
|
||||
{
|
||||
falco::app::state s;
|
||||
// The command line options should be correctly applied since the
|
||||
// config is unchanged
|
||||
s.options.modern_bpf = true;
|
||||
s.options.conf_filename = NEW_ENGINE_CONFIG_UNCHANGED;
|
||||
EXPECT_ACTION_OK(falco::app::actions::load_config(s));
|
||||
|
||||
// Check that the engine is the kmod
|
||||
EXPECT_TRUE(s.is_modern_ebpf());
|
||||
|
||||
// Check that the modern ebpf engine uses the default syscall configs
|
||||
// and not the ones in the `engine` block
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, 3);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_buf_size_preset, 6);
|
||||
EXPECT_TRUE(s.config->m_modern_ebpf.m_drop_failed_exit);
|
||||
|
||||
// Kmod params should be always populated since the kmod is the default
|
||||
EXPECT_EQ(s.config->m_kmod.m_buf_size_preset, 6);
|
||||
EXPECT_TRUE(s.config->m_kmod.m_drop_failed_exit);
|
||||
|
||||
// Check that all other engine params are empty
|
||||
EXPECT_TRUE(s.config->m_ebpf.m_probe_path.empty());
|
||||
EXPECT_EQ(s.config->m_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_replay.m_capture_file.empty());
|
||||
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_config.empty());
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
|
||||
// Check that deprecated configs are populated
|
||||
EXPECT_EQ(s.config->m_syscall_buf_size_preset, 6);
|
||||
EXPECT_EQ(s.config->m_cpus_for_each_syscall_buffer, 3);
|
||||
EXPECT_TRUE(s.config->m_syscall_drop_failed_exit);
|
||||
}
|
||||
|
||||
TEST(ActionLoadConfig, check_override_command_line_gvisor)
|
||||
{
|
||||
falco::app::state s;
|
||||
// The command line options should be correctly applied since the
|
||||
// config is unchanged
|
||||
s.options.gvisor_config = "config";
|
||||
s.options.conf_filename = NEW_ENGINE_CONFIG_UNCHANGED;
|
||||
EXPECT_ACTION_OK(falco::app::actions::load_config(s));
|
||||
|
||||
// Check that the engine is the kmod
|
||||
EXPECT_TRUE(s.is_gvisor());
|
||||
EXPECT_EQ(s.config->m_gvisor.m_config, "config");
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
|
||||
// Kmod params should be always populated since the kmod is the default
|
||||
EXPECT_EQ(s.config->m_kmod.m_buf_size_preset, 6);
|
||||
EXPECT_TRUE(s.config->m_kmod.m_drop_failed_exit);
|
||||
|
||||
// Check that all other engine params are empty
|
||||
EXPECT_TRUE(s.config->m_ebpf.m_probe_path.empty());
|
||||
EXPECT_EQ(s.config->m_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, 0);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_modern_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_replay.m_capture_file.empty());
|
||||
|
||||
// Check that deprecated configs are populated
|
||||
EXPECT_EQ(s.config->m_syscall_buf_size_preset, 6);
|
||||
EXPECT_EQ(s.config->m_cpus_for_each_syscall_buffer, 3);
|
||||
EXPECT_TRUE(s.config->m_syscall_drop_failed_exit);
|
||||
}
|
||||
#endif
|
||||
@@ -30,7 +30,7 @@ TEST(ActionSelectEventSources, pre_post_conditions)
|
||||
// ignore source selection in capture mode
|
||||
{
|
||||
falco::app::state s;
|
||||
s.options.trace_filename = "some_capture_file.scap";
|
||||
s.config->m_engine_mode = engine_kind_t::REPLAY;
|
||||
EXPECT_TRUE(s.is_capture_mode());
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
}
|
||||
|
||||
52
unit_tests/falco/test_configs/new_engine_config_changed.yaml
Normal file
52
unit_tests/falco/test_configs/new_engine_config_changed.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 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.
|
||||
#
|
||||
|
||||
################
|
||||
# Falco engine #
|
||||
################
|
||||
|
||||
engine:
|
||||
kind: kmod
|
||||
kmod:
|
||||
buf_size_preset: 2 # changed default value
|
||||
drop_failed_exit: false
|
||||
ebpf:
|
||||
probe: /path/to/probe.o
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
modern_ebpf:
|
||||
cpus_for_each_buffer: 2
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
replay:
|
||||
capture_file: /path/to/file.scap
|
||||
gvisor:
|
||||
config: /path/to/gvisor_config.yaml
|
||||
root: ""
|
||||
|
||||
#######################################
|
||||
# Falco performance tuning (advanced) #
|
||||
#######################################
|
||||
|
||||
# These configs should be ignored since we have changed the `engine` config
|
||||
syscall_buf_size_preset: 6
|
||||
|
||||
syscall_drop_failed_exit: true
|
||||
|
||||
modern_bpf:
|
||||
cpus_for_each_syscall_buffer: 7
|
||||
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 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.
|
||||
#
|
||||
|
||||
################
|
||||
# Falco engine #
|
||||
################
|
||||
|
||||
# Unchanged
|
||||
engine:
|
||||
kind: kmod
|
||||
kmod:
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
ebpf:
|
||||
probe: /path/to/probe.o
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
modern_ebpf:
|
||||
cpus_for_each_buffer: 2
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
replay:
|
||||
capture_file: /path/to/file.scap
|
||||
gvisor:
|
||||
config: /path/to/gvisor_config.yaml
|
||||
root: ""
|
||||
|
||||
#######################################
|
||||
# Falco performance tuning (advanced) #
|
||||
#######################################
|
||||
|
||||
# The `engine` config is unchanged so these configs are used
|
||||
syscall_buf_size_preset: 6
|
||||
|
||||
syscall_drop_failed_exit: true
|
||||
|
||||
modern_bpf:
|
||||
cpus_for_each_syscall_buffer: 3
|
||||
@@ -18,6 +18,12 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <falco/configuration.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SET_ENV_VAR(env_var_name, env_var_value) _putenv_s(env_var_name, env_var_value)
|
||||
#else
|
||||
#define SET_ENV_VAR(env_var_name, env_var_value) setenv(env_var_name, env_var_value, 1)
|
||||
#endif
|
||||
|
||||
static std::string sample_yaml =
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
@@ -108,17 +114,35 @@ TEST(Configuration, configuration_environment_variables)
|
||||
// Set an environment variable for testing purposes
|
||||
std::string env_var_value = "envVarValue";
|
||||
std::string env_var_name = "ENV_VAR";
|
||||
std::string default_value = "default";
|
||||
setenv(env_var_name.c_str(), env_var_value.c_str(), 1);
|
||||
yaml_helper conf;
|
||||
SET_ENV_VAR(env_var_name.c_str(), env_var_value.c_str());
|
||||
|
||||
std::string sample_yaml =
|
||||
std::string embedded_env_var_value = "${ENV_VAR}";
|
||||
std::string embedded_env_var_name = "ENV_VAR_EMBEDDED";
|
||||
SET_ENV_VAR(embedded_env_var_name.c_str(), embedded_env_var_value.c_str());
|
||||
|
||||
std::string bool_env_var_value = "true";
|
||||
std::string bool_env_var_name = "ENV_VAR_BOOL";
|
||||
SET_ENV_VAR(bool_env_var_name.c_str(), bool_env_var_value.c_str());
|
||||
|
||||
std::string int_env_var_value = "12";
|
||||
std::string int_env_var_name = "ENV_VAR_INT";
|
||||
SET_ENV_VAR(int_env_var_name.c_str(), int_env_var_value.c_str());
|
||||
|
||||
std::string empty_env_var_value = "";
|
||||
std::string empty_env_var_name = "ENV_VAR_EMPTY";
|
||||
SET_ENV_VAR(empty_env_var_name.c_str(), empty_env_var_value.c_str());
|
||||
|
||||
std::string default_value = "default";
|
||||
std::string env_var_sample_yaml =
|
||||
"base_value:\n"
|
||||
" id: $ENV_VAR\n"
|
||||
" name: '${ENV_VAR}'\n"
|
||||
" string: my_string\n"
|
||||
" invalid: $${ENV_VAR}\n"
|
||||
" invalid_env: $$ENV_VAR\n"
|
||||
" invalid_env: $$ENV_VAR\n"
|
||||
" invalid_double_env: $${ENV_VAR}$${ENV_VAR}\n"
|
||||
" invalid_embedded_env: $${${ENV_VAR}}\n"
|
||||
" invalid_valid_env: $${ENV_VAR}${ENV_VAR}\n"
|
||||
" escaped: \"${ENV_VAR}\"\n"
|
||||
" subvalue:\n"
|
||||
" subvalue2:\n"
|
||||
@@ -127,50 +151,213 @@ TEST(Configuration, configuration_environment_variables)
|
||||
" sample_list:\n"
|
||||
" - ${ENV_VAR}\n"
|
||||
" - ' ${ENV_VAR}'\n"
|
||||
" - $UNSED_XX_X_X_VAR\n";
|
||||
conf.load_from_string(sample_yaml);
|
||||
" - '${ENV_VAR} '\n"
|
||||
" - $UNSED_XX_X_X_VAR\n"
|
||||
"paths:\n"
|
||||
" - ${ENV_VAR}/foo\n"
|
||||
" - $ENV_VAR/foo\n"
|
||||
" - /foo/${ENV_VAR}/\n"
|
||||
" - /${ENV_VAR}/${ENV_VAR}${ENV_VAR}/foo\n"
|
||||
" - ${ENV_VAR_EMBEDDED}/foo\n"
|
||||
"is_test: ${ENV_VAR_BOOL}\n"
|
||||
"num_test: ${ENV_VAR_INT}\n"
|
||||
"empty_test: ${ENV_VAR_EMPTY}\n"
|
||||
"plugins:\n"
|
||||
" - name: k8saudit\n"
|
||||
" library_path: /foo/${ENV_VAR}/libk8saudit.so\n"
|
||||
" open_params: ${ENV_VAR_INT}\n";
|
||||
|
||||
yaml_helper conf;
|
||||
conf.load_from_string(env_var_sample_yaml);
|
||||
|
||||
/* Check if the base values are defined */
|
||||
ASSERT_TRUE(conf.is_defined("base_value"));
|
||||
ASSERT_TRUE(conf.is_defined("base_value_2"));
|
||||
ASSERT_TRUE(conf.is_defined("paths"));
|
||||
ASSERT_FALSE(conf.is_defined("unknown_base_value"));
|
||||
|
||||
/* Test fetching of a regular string without any environment variable */
|
||||
std::string base_value_string = conf.get_scalar<std::string>("base_value.string", default_value);
|
||||
auto base_value_string = conf.get_scalar<std::string>("base_value.string", default_value);
|
||||
ASSERT_EQ(base_value_string, "my_string");
|
||||
|
||||
/* Test fetching of escaped environment variable format. Should return the string as-is after stripping the leading `$` */
|
||||
std::string base_value_invalid = conf.get_scalar<std::string>("base_value.invalid", default_value);
|
||||
auto base_value_invalid = conf.get_scalar<std::string>("base_value.invalid", default_value);
|
||||
ASSERT_EQ(base_value_invalid, "${ENV_VAR}");
|
||||
|
||||
/* Test fetching of invalid escaped environment variable format. Should return the string as-is */
|
||||
std::string base_value_invalid_env = conf.get_scalar<std::string>("base_value.invalid_env", default_value);
|
||||
/* Test fetching of invalid escaped environment variable format. Should return the string as-is */
|
||||
auto base_value_invalid_env = conf.get_scalar<std::string>("base_value.invalid_env", default_value);
|
||||
ASSERT_EQ(base_value_invalid_env, "$$ENV_VAR");
|
||||
|
||||
/* Test fetching of 2 escaped environment variables side by side. Should return the string as-is after stripping the leading `$` */
|
||||
auto base_value_double_invalid = conf.get_scalar<std::string>("base_value.invalid_double_env", default_value);
|
||||
ASSERT_EQ(base_value_double_invalid, "${ENV_VAR}${ENV_VAR}");
|
||||
|
||||
/*
|
||||
* Test fetching of escaped environment variable format with inside an env variable.
|
||||
* Should return the string as-is after stripping the leading `$` with the resolved env variable within
|
||||
*/
|
||||
auto base_value_embedded_invalid = conf.get_scalar<std::string>("base_value.invalid_embedded_env", default_value);
|
||||
ASSERT_EQ(base_value_embedded_invalid, "${" + env_var_value + "}");
|
||||
|
||||
/*
|
||||
* Test fetching of an escaped env variable plus an env variable side by side.
|
||||
* Should return the escaped one trimming the leading `$` plus the second one resolved.
|
||||
*/
|
||||
auto base_value_valid_invalid = conf.get_scalar<std::string>("base_value.invalid_valid_env", default_value);
|
||||
ASSERT_EQ(base_value_valid_invalid, "${ENV_VAR}" + env_var_value);
|
||||
|
||||
/* Test fetching of strings that contain environment variables */
|
||||
std::string base_value_id = conf.get_scalar<std::string>("base_value.id", default_value);
|
||||
auto base_value_id = conf.get_scalar<std::string>("base_value.id", default_value);
|
||||
ASSERT_EQ(base_value_id, "$ENV_VAR"); // Does not follow the `${VAR}` format, so it should be treated as a regular string
|
||||
|
||||
std::string base_value_name = conf.get_scalar<std::string>("base_value.name", default_value);
|
||||
auto base_value_name = conf.get_scalar<std::string>("base_value.name", default_value);
|
||||
ASSERT_EQ(base_value_name, env_var_value); // Proper environment variable format
|
||||
|
||||
std::string base_value_escaped = conf.get_scalar<std::string>("base_value.escaped", default_value);
|
||||
auto base_value_escaped = conf.get_scalar<std::string>("base_value.escaped", default_value);
|
||||
ASSERT_EQ(base_value_escaped, env_var_value); // Environment variable within quotes
|
||||
|
||||
/* Test fetching of an undefined environment variable. Expected to return the default value.*/
|
||||
std::string unknown_boolean = conf.get_scalar<std::string>("base_value.subvalue.subvalue2.boolean", default_value);
|
||||
ASSERT_EQ(unknown_boolean, default_value);
|
||||
/* Test fetching of an undefined environment variable. Resolves to empty string. */
|
||||
auto unknown_boolean = conf.get_scalar<std::string>("base_value.subvalue.subvalue2.boolean", default_value);
|
||||
ASSERT_EQ(unknown_boolean, "");
|
||||
|
||||
/* Test fetching of environment variables from a list */
|
||||
std::string base_value_2_list_0 = conf.get_scalar<std::string>("base_value_2.sample_list[0]", default_value);
|
||||
auto base_value_2_list_0 = conf.get_scalar<std::string>("base_value_2.sample_list[0]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_0, env_var_value); // Proper environment variable format
|
||||
|
||||
std::string base_value_2_list_1 = conf.get_scalar<std::string>("base_value_2.sample_list[1]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_1, " ${ENV_VAR}"); // Environment variable preceded by a space, hence treated as a regular string
|
||||
auto base_value_2_list_1 = conf.get_scalar<std::string>("base_value_2.sample_list[1]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_1, " " + env_var_value); // Environment variable preceded by a space, still extracted env var with leading space
|
||||
|
||||
std::string base_value_2_list_2 = conf.get_scalar<std::string>("base_value_2.sample_list[2]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_2, "$UNSED_XX_X_X_VAR"); // Does not follow the `${VAR}` format, so should be treated as a regular string
|
||||
auto base_value_2_list_2 = conf.get_scalar<std::string>("base_value_2.sample_list[2]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_2, env_var_value + " "); // Environment variable followed by a space, still extracted env var with trailing space
|
||||
|
||||
/* Clear the set environment variable after testing */
|
||||
unsetenv(env_var_name.c_str());
|
||||
auto base_value_2_list_3 = conf.get_scalar<std::string>("base_value_2.sample_list[3]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_3, "$UNSED_XX_X_X_VAR"); // Does not follow the `${VAR}` format, so should be treated as a regular string
|
||||
|
||||
/* Test expansion of environment variables within strings */
|
||||
auto path_list_0 = conf.get_scalar<std::string>("paths[0]", default_value);
|
||||
ASSERT_EQ(path_list_0, env_var_value + "/foo"); // Even if env var is part of bigger string, it gets expanded
|
||||
|
||||
auto path_list_1 = conf.get_scalar<std::string>("paths[1]", default_value);
|
||||
ASSERT_EQ(path_list_1, "$ENV_VAR/foo"); // Does not follow the `${VAR}` format, so should be treated as a regular string
|
||||
|
||||
auto path_list_2 = conf.get_scalar<std::string>("paths[2]", default_value);
|
||||
ASSERT_EQ(path_list_2, "/foo/" + env_var_value + "/"); // Even when env var is in the middle of a string. it gets expanded
|
||||
|
||||
auto path_list_3 = conf.get_scalar<std::string>("paths[3]", default_value);
|
||||
ASSERT_EQ(path_list_3, "/" + env_var_value + "/" + env_var_value + env_var_value + "/foo"); // Even when the string contains multiple env vars they are correctly expanded
|
||||
|
||||
auto path_list_4 = conf.get_scalar<std::string>("paths[4]", default_value);
|
||||
ASSERT_EQ(path_list_4, env_var_value + "/foo"); // Even when the env var contains another env var, it gets correctly double-expanded
|
||||
|
||||
/* Check that variable expansion is type-aware */
|
||||
auto boolean = conf.get_scalar<bool>("is_test", false);
|
||||
ASSERT_EQ(boolean, true); // `true` can be parsed to bool.
|
||||
|
||||
auto boolean_as_str = conf.get_scalar<std::string>("is_test", "false");
|
||||
ASSERT_EQ(boolean_as_str, "true"); // `true` can be parsed to string.
|
||||
|
||||
auto boolean_as_int = conf.get_scalar<int32_t>("is_test", 0);
|
||||
ASSERT_EQ(boolean_as_int, 0); // `true` cannot be parsed to integer.
|
||||
|
||||
auto integer = conf.get_scalar<int32_t>("num_test", -1);
|
||||
ASSERT_EQ(integer, 12);
|
||||
|
||||
// An env var that resolves to an empty string returns ""
|
||||
auto empty_default_str = conf.get_scalar<std::string>("empty_test", default_value);
|
||||
ASSERT_EQ(empty_default_str, "");
|
||||
|
||||
std::list<falco_configuration::plugin_config> plugins;
|
||||
conf.get_sequence<std::list<falco_configuration::plugin_config>>(plugins, std::string("plugins"));
|
||||
std::vector<falco_configuration::plugin_config> m_plugins{ std::make_move_iterator(std::begin(plugins)),
|
||||
std::make_move_iterator(std::end(plugins)) };
|
||||
ASSERT_EQ(m_plugins[0].m_name, "k8saudit");
|
||||
ASSERT_EQ(m_plugins[0].m_library_path, "/foo/" + env_var_value + "/libk8saudit.so");
|
||||
ASSERT_EQ(m_plugins[0].m_open_params, "12");
|
||||
|
||||
/* Clear the set environment variables after testing */
|
||||
SET_ENV_VAR(env_var_name.c_str(), "");
|
||||
SET_ENV_VAR(embedded_env_var_name.c_str(), "");
|
||||
SET_ENV_VAR(bool_env_var_name.c_str(), "");
|
||||
SET_ENV_VAR(int_env_var_name.c_str(), "");
|
||||
SET_ENV_VAR(empty_env_var_name.c_str(), "");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_webserver_ip)
|
||||
{
|
||||
falco_configuration falco_config;
|
||||
|
||||
std::vector<std::string> valid_addresses = {"127.0.0.1",
|
||||
"1.127.0.1",
|
||||
"1.1.127.1",
|
||||
"1.1.1.127",
|
||||
"::",
|
||||
"::1",
|
||||
"1200:0000:AB00:1234:0000:2552:7777:1313",
|
||||
"1200::AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234::2552:7777:1313",
|
||||
"21DA:D3:0:2F3B:2AA:FF:FE28:9C5A",
|
||||
"FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
|
||||
"0.0.0.0",
|
||||
"9.255.255.255",
|
||||
"11.0.0.0",
|
||||
"126.255.255.255",
|
||||
"129.0.0.0",
|
||||
"169.253.255.255",
|
||||
"169.255.0.0",
|
||||
"172.15.255.255",
|
||||
"172.32.0.0",
|
||||
"191.0.1.255",
|
||||
"192.88.98.255",
|
||||
"192.88.100.0",
|
||||
"192.167.255.255",
|
||||
"192.169.0.0",
|
||||
"198.17.255.255",
|
||||
"223.255.255.255"};
|
||||
|
||||
for (const std::string &address: valid_addresses) {
|
||||
std::string option = "webserver.listen_address=";
|
||||
option.append(address);
|
||||
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back(option);
|
||||
|
||||
EXPECT_NO_THROW(falco_config.init(cmdline_config_options));
|
||||
|
||||
ASSERT_EQ(falco_config.m_webserver_listen_address, address);
|
||||
}
|
||||
|
||||
std::vector<std::string> invalid_addresses = {"327.0.0.1",
|
||||
"1.327.0.1",
|
||||
"1.1.327.1",
|
||||
"1.1.1.327",
|
||||
"12 7.0.0.1",
|
||||
"127. 0.0.1",
|
||||
"127.0. 0.1",
|
||||
"127.0.0. 1",
|
||||
"!27.0.0.1",
|
||||
"1200: 0000:AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000: AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00: 1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234: 0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234:0000: 2552:7777:1313",
|
||||
"1200:0000:AB00:1234:0000:2552: 7777:1313",
|
||||
"1200:0000:AB00:1234:0000:2552:7777: 1313",
|
||||
"1200:0000:AB00:1234:0000:2552:7777:131G",
|
||||
"1200:0000:AB00:1234:0000:2552:77Z7:1313",
|
||||
"1200:0000:AB00:1234:0000:2G52:7777:1313",
|
||||
"1200:0000:AB00:1234:0O00:2552:7777:1313",
|
||||
"1200:0000:AB00:H234:0000:2552:7777:1313",
|
||||
"1200:0000:IB00:1234:0000:2552:7777:1313",
|
||||
"1200:0O00:AB00:1234:0000:2552:7777:1313",
|
||||
"12O0:0000:AB00:1234:0000:2552:7777:1313",};
|
||||
|
||||
for (const std::string &address: invalid_addresses) {
|
||||
std::string option = "webserver.listen_address=";
|
||||
option.append(address);
|
||||
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back(option);
|
||||
|
||||
EXPECT_ANY_THROW(falco_config.init(cmdline_config_options));
|
||||
}
|
||||
}
|
||||
|
||||
4
unit_tests/falco_test_var.h.in
Normal file
4
unit_tests/falco_test_var.h.in
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#define NEW_ENGINE_CONFIG_CHANGED "${CMAKE_SOURCE_DIR}/unit_tests/falco/test_configs/new_engine_config_changed.yaml"
|
||||
#define NEW_ENGINE_CONFIG_UNCHANGED "${CMAKE_SOURCE_DIR}/unit_tests/falco/test_configs/new_engine_config_unchanged.yaml"
|
||||
@@ -11,12 +11,11 @@
|
||||
# "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(FALCO_ENGINE_SOURCE_FILES
|
||||
add_library(falco_engine STATIC
|
||||
falco_common.cpp
|
||||
falco_engine.cpp
|
||||
falco_load_result.cpp
|
||||
falco_utils.cpp
|
||||
json_evt.cpp
|
||||
evttype_index_ruleset.cpp
|
||||
formats.cpp
|
||||
filter_details_resolver.cpp
|
||||
@@ -26,9 +25,8 @@ set(FALCO_ENGINE_SOURCE_FILES
|
||||
rule_loader.cpp
|
||||
rule_loader_reader.cpp
|
||||
rule_loader_collector.cpp
|
||||
rule_loader_compiler.cpp)
|
||||
|
||||
add_library(falco_engine STATIC ${FALCO_ENGINE_SOURCE_FILES})
|
||||
rule_loader_compiler.cpp
|
||||
)
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
target_compile_options(falco_engine PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
@@ -36,26 +34,17 @@ endif()
|
||||
|
||||
add_dependencies(falco_engine yamlcpp njson)
|
||||
|
||||
if(MINIMAL_BUILD)
|
||||
target_include_directories(
|
||||
falco_engine
|
||||
PUBLIC
|
||||
"${NJSON_INCLUDE}"
|
||||
"${TBB_INCLUDE_DIR}"
|
||||
"${LIBSCAP_INCLUDE_DIRS}"
|
||||
"${LIBSINSP_INCLUDE_DIRS}"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
||||
else()
|
||||
target_include_directories(
|
||||
falco_engine
|
||||
PUBLIC
|
||||
"${NJSON_INCLUDE}"
|
||||
"${TBB_INCLUDE_DIR}"
|
||||
"${LIBSCAP_INCLUDE_DIRS}"
|
||||
"${LIBSINSP_INCLUDE_DIRS}"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
||||
endif()
|
||||
target_include_directories(falco_engine
|
||||
PUBLIC
|
||||
${LIBSCAP_INCLUDE_DIRS}
|
||||
${LIBSINSP_INCLUDE_DIRS}
|
||||
${PROJECT_BINARY_DIR}/userspace/engine
|
||||
${nlohmann_json_DIR}
|
||||
${TBB_INCLUDE_DIR}
|
||||
${YAMLCPP_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${YAMLCPP_LIB}")
|
||||
target_link_libraries(falco_engine
|
||||
${FALCO_SINSP_LIBRARY}
|
||||
${YAMLCPP_LIB}
|
||||
)
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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
|
||||
|
||||
// BAN macro defines `function` as an invalid token that says using
|
||||
// the function is banned. This throws a compile time error when the
|
||||
// function is used.
|
||||
#define BAN(function) using_##function##_is_banned
|
||||
|
||||
// BAN_ALTERNATIVE is same as BAN but the message also provides an alternative
|
||||
// function that the user could use instead of the banned function.
|
||||
#define BAN_ALTERNATIVE(function, alternative) using_##function##_is_banned__use_##alternative##_instead
|
||||
|
||||
#undef strcpy
|
||||
#define strcpy(a, b) BAN(strcpy)
|
||||
|
||||
#undef vsprintf
|
||||
#define vsprintf(a, b, c) BAN_ALTERNATIVE(vsprintf, vsnprintf)
|
||||
|
||||
#undef sprintf
|
||||
#define sprintf(a, b, ...) BAN_ALTERNATIVE(sprintf, snprintf)
|
||||
|
||||
#undef strcat
|
||||
#define strcat(a, b) BAN(strcat)
|
||||
|
||||
#undef strncpy
|
||||
#define strncpy(a, b, c) BAN(strncpy)
|
||||
|
||||
#undef swprintf
|
||||
#define swprintf(a, b, c, ...) BAN_ALTERNATIVE(swprintf, snprintf)
|
||||
|
||||
#undef vswprintf
|
||||
#define vswprintf(a, b, c, d) BAN_ALTERNATIVE(vswprintf, vsnprintf)
|
||||
@@ -16,7 +16,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
#include "evttype_index_ruleset.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
@@ -44,9 +44,7 @@ limitations under the License.
|
||||
#include "formats.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
#include "evttype_index_ruleset.h"
|
||||
#include "filter_details_resolver.h"
|
||||
|
||||
const std::string falco_engine::s_default_ruleset = "falco-default-ruleset";
|
||||
|
||||
@@ -76,9 +74,9 @@ falco_engine::~falco_engine()
|
||||
m_sources.clear();
|
||||
}
|
||||
|
||||
uint32_t falco_engine::engine_version()
|
||||
sinsp_version falco_engine::engine_version()
|
||||
{
|
||||
return (uint32_t) FALCO_ENGINE_VERSION;
|
||||
return sinsp_version(FALCO_ENGINE_VERSION);
|
||||
}
|
||||
|
||||
const falco_source* falco_engine::find_source(const std::string& name) const
|
||||
@@ -191,22 +189,60 @@ void falco_engine::load_rules(const std::string &rules_content, bool verbose, bo
|
||||
std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_content, const std::string &name)
|
||||
{
|
||||
rule_loader::configuration cfg(rules_content, m_sources, name);
|
||||
cfg.min_priority = m_min_priority;
|
||||
cfg.output_extra = m_extra;
|
||||
cfg.replace_output_container_info = m_replace_container_info;
|
||||
cfg.default_ruleset_id = m_default_ruleset_id;
|
||||
|
||||
// read rules YAML file and collect its definitions
|
||||
rule_loader::reader reader;
|
||||
if (reader.read(cfg, m_rule_collector))
|
||||
{
|
||||
// compile the definitions (resolve macro/list refs, exceptions, ...)
|
||||
m_last_compile_output = std::make_unique<rule_loader::compiler::compile_output>();
|
||||
rule_loader::compiler().compile(cfg, m_rule_collector, *m_last_compile_output.get());
|
||||
|
||||
// clear the rules known by the engine and each ruleset
|
||||
m_rules.clear();
|
||||
for (auto &src : m_sources)
|
||||
{
|
||||
src.ruleset = src.ruleset_factory->new_ruleset();
|
||||
}
|
||||
|
||||
rule_loader::compiler compiler;
|
||||
m_rules.clear();
|
||||
compiler.compile(cfg, m_rule_collector, m_rules);
|
||||
// add rules to the engine and the rulesets
|
||||
for (const auto& rule : m_last_compile_output->rules)
|
||||
{
|
||||
// skip the rule if below the minimum priority
|
||||
if (rule.priority > m_min_priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto info = m_rule_collector.rules().at(rule.name);
|
||||
if (!info)
|
||||
{
|
||||
// this is just defensive, it should never happen
|
||||
throw falco_exception("can't find internal rule info at name: " + name);
|
||||
}
|
||||
|
||||
// the rule is ok, we can add it to the engine and the rulesets
|
||||
// note: the compiler should guarantee that the rule's condition
|
||||
// is a valid sinsp filter
|
||||
auto source = find_source(rule.source);
|
||||
std::shared_ptr<gen_event_filter> filter(
|
||||
sinsp_filter_compiler(source->filter_factory, rule.condition.get()).compile());
|
||||
auto rule_id = m_rules.insert(rule, rule.name);
|
||||
m_rules.at(rule_id)->id = rule_id;
|
||||
source->ruleset->add(rule, filter, rule.condition);
|
||||
|
||||
// By default rules are enabled/disabled for the default ruleset
|
||||
if(info->enabled)
|
||||
{
|
||||
source->ruleset->enable(rule.name, true, m_default_ruleset_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
source->ruleset->disable(rule.name, true, m_default_ruleset_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg.res->successful())
|
||||
@@ -262,6 +298,12 @@ std::unique_ptr<load_result> falco_engine::load_rules_file(const std::string &ru
|
||||
void falco_engine::enable_rule(const std::string &substring, bool enabled, const std::string &ruleset)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
|
||||
enable_rule(substring, enabled, ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule(const std::string &substring, bool enabled, const uint16_t ruleset_id)
|
||||
{
|
||||
bool match_exact = false;
|
||||
|
||||
for(const auto &it : m_sources)
|
||||
@@ -280,6 +322,12 @@ void falco_engine::enable_rule(const std::string &substring, bool enabled, const
|
||||
void falco_engine::enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
|
||||
enable_rule_exact(rule_name, enabled, ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_exact(const std::string &rule_name, bool enabled, const uint16_t ruleset_id)
|
||||
{
|
||||
bool match_exact = true;
|
||||
|
||||
for(const auto &it : m_sources)
|
||||
@@ -299,6 +347,11 @@ void falco_engine::enable_rule_by_tag(const std::set<std::string> &tags, bool en
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
|
||||
enable_rule_by_tag(tags, enabled, ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_by_tag(const std::set<std::string> &tags, bool enabled, const uint16_t ruleset_id)
|
||||
{
|
||||
for(const auto &it : m_sources)
|
||||
{
|
||||
if(enabled)
|
||||
@@ -348,7 +401,7 @@ libsinsp::events::set<ppm_sc_code> falco_engine::sc_codes_for_ruleset(const std:
|
||||
{
|
||||
return find_source(source)->ruleset->enabled_sc_codes(find_ruleset_id(ruleset));
|
||||
}
|
||||
|
||||
|
||||
libsinsp::events::set<ppm_event_code> falco_engine::event_codes_for_ruleset(const std::string &source, const std::string &ruleset)
|
||||
{
|
||||
return find_source(source)->ruleset->enabled_event_codes(find_ruleset_id(ruleset));
|
||||
@@ -469,106 +522,88 @@ std::size_t falco_engine::add_source(const std::string &source,
|
||||
return m_sources.insert(src, source);
|
||||
}
|
||||
|
||||
void falco_engine::describe_rule(std::string *rule, bool json) const
|
||||
template <typename T> inline nlohmann::json sequence_to_json_array(const T& seq)
|
||||
{
|
||||
if(!json)
|
||||
nlohmann::json ret = nlohmann::json::array();
|
||||
for (const auto& v : seq)
|
||||
{
|
||||
static const char *rule_fmt = "%-50s %s\n";
|
||||
fprintf(stdout, rule_fmt, "Rule", "Description");
|
||||
fprintf(stdout, rule_fmt, "----", "-----------");
|
||||
if(!rule)
|
||||
{
|
||||
for(auto &r : m_rules)
|
||||
{
|
||||
auto str = falco::utils::wrap_text(r.description, 51, 110) + "\n";
|
||||
fprintf(stdout, rule_fmt, r.name.c_str(), str.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto r = m_rules.at(*rule);
|
||||
if(r == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto str = falco::utils::wrap_text(r->description, 51, 110) + "\n";
|
||||
fprintf(stdout, rule_fmt, r->name.c_str(), str.c_str());
|
||||
}
|
||||
ret.push_back(v);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return;
|
||||
nlohmann::json falco_engine::describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
// use previously-loaded collector definitions and the compiled
|
||||
// output of rules, macros, and lists.
|
||||
if (m_last_compile_output == nullptr)
|
||||
{
|
||||
throw falco_exception("rules most be loaded before describing them");
|
||||
}
|
||||
|
||||
std::unique_ptr<sinsp> insp(new sinsp());
|
||||
Json::FastWriter writer;
|
||||
std::string json_str;
|
||||
|
||||
// use collected and compiled info to print a json output
|
||||
nlohmann::json output;
|
||||
if(!rule)
|
||||
{
|
||||
// In this case we build json information about
|
||||
// all rules, macros and lists
|
||||
Json::Value output;
|
||||
|
||||
// Store required engine version
|
||||
auto required_engine_version = m_rule_collector.required_engine_version();
|
||||
output["required_engine_version"] = std::to_string(required_engine_version.version);
|
||||
output["required_engine_version"] = required_engine_version.version.as_string();
|
||||
|
||||
// Store required plugin versions
|
||||
Json::Value plugin_versions = Json::arrayValue;
|
||||
nlohmann::json plugin_versions = nlohmann::json::array();
|
||||
auto required_plugin_versions = m_rule_collector.required_plugin_versions();
|
||||
for(const auto& req : required_plugin_versions)
|
||||
{
|
||||
Json::Value r;
|
||||
nlohmann::json r;
|
||||
r["name"] = req.at(0).name;
|
||||
r["version"] = req.at(0).version;
|
||||
|
||||
Json::Value alternatives = Json::arrayValue;
|
||||
nlohmann::json alternatives = nlohmann::json::array();
|
||||
for(size_t i = 1; i < req.size(); i++)
|
||||
{
|
||||
Json::Value alternative;
|
||||
nlohmann::json alternative;
|
||||
alternative["name"] = req[i].name;
|
||||
alternative["version"] = req[i].version;
|
||||
alternatives.append(alternative);
|
||||
alternatives.push_back(std::move(alternative));
|
||||
}
|
||||
r["alternatives"] = alternatives;
|
||||
|
||||
plugin_versions.append(r);
|
||||
r["alternatives"] = std::move(alternatives);
|
||||
|
||||
plugin_versions.push_back(std::move(r));
|
||||
}
|
||||
output["required_plugin_versions"] = plugin_versions;
|
||||
output["required_plugin_versions"] = std::move(plugin_versions);
|
||||
|
||||
// Store information about rules
|
||||
Json::Value rules_array = Json::arrayValue;
|
||||
for(const auto& r : m_rules)
|
||||
nlohmann::json rules_array = nlohmann::json::array();
|
||||
for(const auto& r : m_last_compile_output->rules)
|
||||
{
|
||||
auto ri = m_rule_collector.rules().at(r.name);
|
||||
Json::Value rule;
|
||||
get_json_details(r, *ri, insp.get(), rule);
|
||||
|
||||
// Append to rule array
|
||||
rules_array.append(rule);
|
||||
auto info = m_rule_collector.rules().at(r.name);
|
||||
nlohmann::json rule;
|
||||
get_json_details(rule, r, *info, plugins);
|
||||
rules_array.push_back(std::move(rule));
|
||||
}
|
||||
output["rules"] = rules_array;
|
||||
|
||||
output["rules"] = std::move(rules_array);
|
||||
|
||||
// Store information about macros
|
||||
Json::Value macros_array;
|
||||
for(const auto &m : m_rule_collector.macros())
|
||||
nlohmann::json macros_array = nlohmann::json::array();
|
||||
for(const auto &m : m_last_compile_output->macros)
|
||||
{
|
||||
Json::Value macro;
|
||||
get_json_details(m, macro);
|
||||
macros_array.append(macro);
|
||||
auto info = m_rule_collector.macros().at(m.name);
|
||||
nlohmann::json macro;
|
||||
get_json_details(macro, m, *info, plugins);
|
||||
macros_array.push_back(std::move(macro));
|
||||
}
|
||||
output["macros"] = macros_array;
|
||||
output["macros"] = std::move(macros_array);
|
||||
|
||||
// Store information about lists
|
||||
Json::Value lists_array = Json::arrayValue;
|
||||
for(const auto &l : m_rule_collector.lists())
|
||||
// Store information about lists
|
||||
nlohmann::json lists_array = nlohmann::json::array();
|
||||
for(const auto &l : m_last_compile_output->lists)
|
||||
{
|
||||
Json::Value list;
|
||||
get_json_details(l, list);
|
||||
lists_array.append(list);
|
||||
auto info = m_rule_collector.lists().at(l.name);
|
||||
nlohmann::json list;
|
||||
get_json_details(list, l, *info, plugins);
|
||||
lists_array.push_back(std::move(list));
|
||||
}
|
||||
output["lists"] = lists_array;
|
||||
|
||||
json_str = writer.write(output);
|
||||
output["lists"] = std::move(lists_array);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -579,69 +614,77 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
|
||||
throw falco_exception("Rule \"" + *rule + "\" is not loaded");
|
||||
}
|
||||
auto r = m_rules.at(ri->name);
|
||||
Json::Value rule;
|
||||
get_json_details(*r, *ri, insp.get(), rule);
|
||||
json_str = writer.write(rule);
|
||||
|
||||
nlohmann::json rule;
|
||||
get_json_details(rule, *r, *ri, plugins);
|
||||
nlohmann::json rules_array = nlohmann::json::array();
|
||||
rules_array.push_back(std::move(rule));
|
||||
output["rules"] = std::move(rules_array);
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s", json_str.c_str());
|
||||
return output;
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(const falco_rule &r,
|
||||
const rule_loader::rule_info &ri,
|
||||
sinsp *insp,
|
||||
Json::Value &rule) const
|
||||
void falco_engine::get_json_details(
|
||||
nlohmann::json &out,
|
||||
const falco_rule &r,
|
||||
const rule_loader::rule_info &info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value rule_info;
|
||||
nlohmann::json rule_info;
|
||||
|
||||
// Fill general rule information
|
||||
rule_info["name"] = r.name;
|
||||
rule_info["condition"] = ri.cond;
|
||||
rule_info["condition"] = info.cond;
|
||||
rule_info["priority"] = format_priority(r.priority, false);
|
||||
rule_info["output"] = r.output;
|
||||
rule_info["output"] = info.output;
|
||||
rule_info["description"] = r.description;
|
||||
rule_info["enabled"] = ri.enabled;
|
||||
rule_info["enabled"] = info.enabled;
|
||||
rule_info["source"] = r.source;
|
||||
Json::Value tags = Json::arrayValue;
|
||||
for(const auto &t : ri.tags)
|
||||
{
|
||||
tags.append(t);
|
||||
}
|
||||
rule_info["tags"] = tags;
|
||||
rule["info"] = rule_info;
|
||||
rule_info["tags"] = sequence_to_json_array(info.tags);
|
||||
out["info"] = std::move(rule_info);
|
||||
|
||||
// Parse rule condition and build the AST
|
||||
// Assumption: no exception because rules have already been loaded.
|
||||
auto ast = libsinsp::filter::parser(ri.cond).parse();
|
||||
Json::Value json_details;
|
||||
get_json_details(ast.get(), json_details);
|
||||
rule["details"] = json_details;
|
||||
// Parse rule condition and build the non-compiled AST
|
||||
// Assumption: no error because rules have already been loaded.
|
||||
auto ast = libsinsp::filter::parser(info.cond).parse();
|
||||
|
||||
// get details related to the condition's filter
|
||||
filter_details details;
|
||||
filter_details compiled_details;
|
||||
nlohmann::json json_details;
|
||||
for(const auto &m : m_rule_collector.macros())
|
||||
{
|
||||
details.known_macros.insert(m.name);
|
||||
compiled_details.known_macros.insert(m.name);
|
||||
}
|
||||
for(const auto &l : m_rule_collector.lists())
|
||||
{
|
||||
details.known_lists.insert(l.name);
|
||||
compiled_details.known_lists.insert(l.name);
|
||||
}
|
||||
filter_details_resolver().run(ast.get(), details);
|
||||
filter_details_resolver().run(r.condition.get(), compiled_details);
|
||||
|
||||
out["details"]["macros"] = sequence_to_json_array(details.macros);
|
||||
out["details"]["lists"] = sequence_to_json_array(details.lists);
|
||||
out["details"]["condition_operators"] = sequence_to_json_array(compiled_details.operators);
|
||||
out["details"]["condition_fields"] = sequence_to_json_array(compiled_details.fields);
|
||||
|
||||
// Get fields from output string
|
||||
auto fmt = create_formatter(r.source, r.output);
|
||||
std::vector<std::string> out_fields;
|
||||
fmt->get_field_names(out_fields);
|
||||
Json::Value outputFields = Json::arrayValue;
|
||||
for(const auto &of : out_fields)
|
||||
{
|
||||
outputFields.append(of);
|
||||
}
|
||||
rule["details"]["output_fields"] = outputFields;
|
||||
out["details"]["output_fields"] = sequence_to_json_array(out_fields);
|
||||
|
||||
// Get fields from exceptions
|
||||
Json::Value exception_fields = Json::arrayValue;
|
||||
for(const auto &f : r.exception_fields)
|
||||
{
|
||||
exception_fields.append(f);
|
||||
}
|
||||
rule["details"]["exception_fields"] = exception_fields;
|
||||
out["details"]["exception_fields"] = sequence_to_json_array(r.exception_fields);
|
||||
|
||||
// Get names and operators from exceptions
|
||||
Json::Value exception_names = Json::arrayValue;
|
||||
Json::Value exception_operators = Json::arrayValue;
|
||||
for(const auto &e : ri.exceptions)
|
||||
std::unordered_set<std::string> exception_names;
|
||||
std::unordered_set<std::string> exception_operators;
|
||||
for(const auto &e : info.exceptions)
|
||||
{
|
||||
exception_names.append(e.name);
|
||||
exception_names.insert(e.name);
|
||||
if(e.comps.is_list)
|
||||
{
|
||||
for(const auto& c : e.comps.items)
|
||||
@@ -651,140 +694,239 @@ void falco_engine::get_json_details(const falco_rule &r,
|
||||
// considering max two levels of lists
|
||||
for(const auto& i : c.items)
|
||||
{
|
||||
exception_operators.append(i.item);
|
||||
exception_operators.insert(i.item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exception_operators.append(c.item);
|
||||
exception_operators.insert(c.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exception_operators.append(e.comps.item);
|
||||
}
|
||||
exception_operators.insert(e.comps.item);
|
||||
}
|
||||
}
|
||||
rule["details"]["exceptions"] = exception_names;
|
||||
rule["details"]["exception_operators"] = exception_operators;
|
||||
|
||||
if(ri.source == falco_common::syscall_source)
|
||||
{
|
||||
// Store event types
|
||||
Json::Value events;
|
||||
get_json_evt_types(ast.get(), events);
|
||||
rule["details"]["events"] = events;
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(const rule_loader::macro_info& m,
|
||||
Json::Value& macro) const
|
||||
{
|
||||
Json::Value macro_info;
|
||||
|
||||
macro_info["name"] = m.name;
|
||||
macro_info["condition"] = m.cond;
|
||||
macro["info"] = macro_info;
|
||||
|
||||
// Assumption: no exception because rules have already been loaded.
|
||||
auto ast = libsinsp::filter::parser(m.cond).parse();
|
||||
|
||||
Json::Value json_details;
|
||||
get_json_details(ast.get(), json_details);
|
||||
macro["details"] = json_details;
|
||||
out["details"]["exception_names"] = sequence_to_json_array(exception_names);
|
||||
out["details"]["exception_operators"] = sequence_to_json_array(exception_operators);
|
||||
|
||||
// Store event types
|
||||
Json::Value events;
|
||||
get_json_evt_types(ast.get(), events);
|
||||
macro["details"]["events"] = events;
|
||||
nlohmann::json events;
|
||||
get_json_evt_types(events, info.source, r.condition.get());
|
||||
out["details"]["events"] = std::move(events);
|
||||
|
||||
// Store compiled condition and output
|
||||
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(r.condition.get());
|
||||
out["details"]["output_compiled"] = r.output;
|
||||
|
||||
// Compute the plugins that are actually used by this rule. This is involves:
|
||||
// - The rule's event source, that can be implemented by a plugin
|
||||
// - The fields used in the rule's condition, output, and exceptions
|
||||
// - The evt types used in the rule's condition checks, that can potentially
|
||||
// match plugin-provided async events
|
||||
nlohmann::json used_plugins;
|
||||
// note: making a union of conditions's and output's fields
|
||||
// note: the condition's AST accounts for all the resolved refs and exceptions
|
||||
compiled_details.fields.insert(out_fields.begin(), out_fields.end());
|
||||
get_json_used_plugins(used_plugins, info.source, compiled_details.evtnames, compiled_details.fields, plugins);
|
||||
out["details"]["plugins"] = std::move(used_plugins);
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(const rule_loader::list_info& l,
|
||||
Json::Value& list) const
|
||||
void falco_engine::get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_macro& m,
|
||||
const rule_loader::macro_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value list_info;
|
||||
list_info["name"] = l.name;
|
||||
nlohmann::json macro_info;
|
||||
|
||||
Json::Value items = Json::arrayValue;
|
||||
Json::Value lists = Json::arrayValue;
|
||||
for(const auto &i : l.items)
|
||||
{
|
||||
if(m_rule_collector.lists().at(i) != nullptr)
|
||||
{
|
||||
lists.append(i);
|
||||
continue;
|
||||
}
|
||||
items.append(i);
|
||||
}
|
||||
macro_info["name"] = m.name;
|
||||
macro_info["condition"] = info.cond;
|
||||
out["info"] = std::move(macro_info);
|
||||
|
||||
list_info["items"] = items;
|
||||
list["info"] = list_info;
|
||||
list["details"]["lists"] = lists;
|
||||
}
|
||||
// Parse the macro condition and build the non-compiled AST
|
||||
// Assumption: no exception because rules have already been loaded.
|
||||
auto ast = libsinsp::filter::parser(info.cond).parse();
|
||||
|
||||
void falco_engine::get_json_details(libsinsp::filter::ast::expr* ast,
|
||||
Json::Value& output) const
|
||||
{
|
||||
// get details related to the condition's filter
|
||||
filter_details details;
|
||||
filter_details compiled_details;
|
||||
nlohmann::json json_details;
|
||||
for(const auto &m : m_rule_collector.macros())
|
||||
{
|
||||
details.known_macros.insert(m.name);
|
||||
compiled_details.known_macros.insert(m.name);
|
||||
}
|
||||
|
||||
for(const auto &l : m_rule_collector.lists())
|
||||
{
|
||||
details.known_lists.insert(l.name);
|
||||
compiled_details.known_lists.insert(l.name);
|
||||
}
|
||||
filter_details_resolver().run(ast.get(), details);
|
||||
filter_details_resolver().run(m.condition.get(), compiled_details);
|
||||
|
||||
// Resolve the AST details
|
||||
filter_details_resolver resolver;
|
||||
resolver.run(ast, details);
|
||||
out["details"]["used"] = m.used;
|
||||
out["details"]["macros"] = sequence_to_json_array(details.macros);
|
||||
out["details"]["lists"] = sequence_to_json_array(details.lists);
|
||||
out["details"]["condition_operators"] = sequence_to_json_array(compiled_details.operators);
|
||||
out["details"]["condition_fields"] = sequence_to_json_array(compiled_details.fields);
|
||||
|
||||
Json::Value macros = Json::arrayValue;
|
||||
for(const auto &m : details.macros)
|
||||
{
|
||||
macros.append(m);
|
||||
}
|
||||
output["macros"] = macros;
|
||||
// Store event types
|
||||
nlohmann::json events;
|
||||
get_json_evt_types(events, "", m.condition.get());
|
||||
out["details"]["events"] = std::move(events);
|
||||
|
||||
Json::Value operators = Json::arrayValue;
|
||||
for(const auto &o : details.operators)
|
||||
{
|
||||
operators.append(o);
|
||||
}
|
||||
output["operators"] = operators;
|
||||
// Store compiled condition
|
||||
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(m.condition.get());
|
||||
|
||||
Json::Value condition_fields = Json::arrayValue;
|
||||
for(const auto &f : details.fields)
|
||||
{
|
||||
condition_fields.append(f);
|
||||
}
|
||||
output["condition_fields"] = condition_fields;
|
||||
|
||||
Json::Value lists = Json::arrayValue;
|
||||
for(const auto &l : details.lists)
|
||||
{
|
||||
lists.append(l);
|
||||
}
|
||||
output["lists"] = lists;
|
||||
|
||||
details.reset();
|
||||
// Compute the plugins that are actually used by this macro.
|
||||
// Note: macros have no specific source, we need to set an empty list of used
|
||||
// plugins because we can't be certain about their actual usage. For example,
|
||||
// if a macro uses a plugin's field, we can't be sure which plugin actually
|
||||
// is used until we resolve the macro ref in a rule providing a source for
|
||||
// disambiguation.
|
||||
out["details"]["plugins"] = nlohmann::json::array();
|
||||
}
|
||||
|
||||
void falco_engine::get_json_evt_types(libsinsp::filter::ast::expr* ast,
|
||||
Json::Value& output) const
|
||||
void falco_engine::get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_list& l,
|
||||
const rule_loader::list_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
output = Json::arrayValue;
|
||||
auto evtcodes = libsinsp::filter::ast::ppm_event_codes(ast);
|
||||
auto syscodes = libsinsp::filter::ast::ppm_sc_codes(ast);
|
||||
auto syscodes_to_evt_names = libsinsp::events::sc_set_to_event_names(syscodes);
|
||||
auto evtcodes_to_evt_names = libsinsp::events::event_set_to_names(evtcodes, false);
|
||||
for (const auto& n : unordered_set_union(syscodes_to_evt_names, evtcodes_to_evt_names))
|
||||
nlohmann::json list_info;
|
||||
list_info["name"] = l.name;
|
||||
|
||||
// note: the syntactic definitions still has the list refs unresolved
|
||||
nlohmann::json items = nlohmann::json::array();
|
||||
std::unordered_set<std::string> lists;
|
||||
for(const auto &i : info.items)
|
||||
{
|
||||
output.append(n);
|
||||
// if an item is present in the syntactic def of a list, but not
|
||||
// on the compiled_items of the same list, then we can assume it
|
||||
// being a resolved list ref
|
||||
if(std::find(l.items.begin(), l.items.end(), i) == l.items.end())
|
||||
{
|
||||
lists.insert(i);
|
||||
continue;
|
||||
}
|
||||
items.push_back(std::move(i));
|
||||
}
|
||||
|
||||
list_info["items"] = std::move(items);
|
||||
out["info"] = std::move(list_info);
|
||||
out["details"]["used"] = l.used;
|
||||
out["details"]["lists"] = sequence_to_json_array(lists);
|
||||
out["details"]["items_compiled"] = sequence_to_json_array(l.items);
|
||||
out["details"]["plugins"] = nlohmann::json::array(); // always empty
|
||||
}
|
||||
|
||||
void falco_engine::get_json_evt_types(
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
libsinsp::filter::ast::expr* ast) const
|
||||
{
|
||||
// note: this duplicates part of the logic of evttype_index_ruleset,
|
||||
// not good but it's our best option for now
|
||||
if (source.empty() || source == falco_common::syscall_source)
|
||||
{
|
||||
auto evtcodes = libsinsp::filter::ast::ppm_event_codes(ast);
|
||||
evtcodes.insert(ppm_event_code::PPME_ASYNCEVENT_E);
|
||||
auto syscodes = libsinsp::filter::ast::ppm_sc_codes(ast);
|
||||
auto syscodes_to_evt_names = libsinsp::events::sc_set_to_event_names(syscodes);
|
||||
auto evtcodes_to_evt_names = libsinsp::events::event_set_to_names(evtcodes, false);
|
||||
out = sequence_to_json_array(unordered_set_union(syscodes_to_evt_names, evtcodes_to_evt_names));
|
||||
}
|
||||
else
|
||||
{
|
||||
out = sequence_to_json_array(libsinsp::events::event_set_to_names(
|
||||
{ppm_event_code::PPME_PLUGINEVENT_E, ppm_event_code::PPME_ASYNCEVENT_E}));
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::get_json_used_plugins(
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
const std::unordered_set<std::string>& evtnames,
|
||||
const std::unordered_set<std::string>& fields,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
// note: condition and output fields may have an argument, so
|
||||
// we need to isolate the field names
|
||||
std::unordered_set<std::string> fieldnames;
|
||||
for (const auto &f: fields)
|
||||
{
|
||||
auto argpos = f.find('[');
|
||||
if (argpos != std::string::npos)
|
||||
{
|
||||
fieldnames.insert(f.substr(0, argpos));
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldnames.insert(f);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> used_plugins;
|
||||
for (const auto& p : plugins)
|
||||
{
|
||||
bool used = false;
|
||||
if (p->caps() & CAP_SOURCING)
|
||||
{
|
||||
// The rule's source is implemented by a plugin with event
|
||||
// sourcing capability.
|
||||
// Note: if Falco loads two plugins implementing the same source,
|
||||
// they will both be included in the list.
|
||||
if (!used && p->event_source() == source)
|
||||
{
|
||||
used_plugins.insert(p->name());
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
if (!used && p->caps() & CAP_EXTRACTION)
|
||||
{
|
||||
// The rule uses a field implemented by a plugin with field
|
||||
// extraction capability that is compatible with the rule's source.
|
||||
// Note: here we're assuming that Falco will prevent loading
|
||||
// plugins implementing fields with the same name for the same
|
||||
// event source (implemented in init_inspectors app action).
|
||||
if (sinsp_plugin::is_source_compatible(p->extract_event_sources(), source))
|
||||
{
|
||||
for (const auto &f : p->fields())
|
||||
{
|
||||
if (!used && fieldnames.find(f.m_name) != fieldnames.end())
|
||||
{
|
||||
used_plugins.insert(p->name());
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!used && p->caps() & CAP_ASYNC)
|
||||
{
|
||||
// The rule matches an event type implemented by a plugin with
|
||||
// async events capability that is compatible with the rule's source.
|
||||
// Note: if Falco loads two plugins implementing async events with
|
||||
// the same name, they will both be included in the list.
|
||||
if (sinsp_plugin::is_source_compatible(p->async_event_sources(), source))
|
||||
{
|
||||
for (const auto &n : p->async_event_names())
|
||||
{
|
||||
if (!used && evtnames.find(n) != evtnames.end())
|
||||
{
|
||||
used_plugins.insert(p->name());
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out = sequence_to_json_array(used_plugins);
|
||||
}
|
||||
|
||||
void falco_engine::print_stats() const
|
||||
{
|
||||
@@ -849,14 +991,14 @@ static bool check_plugin_requirement_alternatives(
|
||||
{
|
||||
sinsp_version req_version(req.version);
|
||||
sinsp_version plugin_version(plugin.version);
|
||||
if(!plugin_version.m_valid)
|
||||
if(!plugin_version.is_valid())
|
||||
{
|
||||
err = "Plugin '" + plugin.name
|
||||
+ "' has invalid version string '"
|
||||
+ plugin.version + "'";
|
||||
return false;
|
||||
}
|
||||
if (!plugin_version.check(req_version))
|
||||
if (!plugin_version.compatible_with(req_version))
|
||||
{
|
||||
err = "Plugin '" + plugin.name
|
||||
+ "' version '" + plugin.version
|
||||
|
||||
@@ -39,6 +39,8 @@ limitations under the License.
|
||||
#include "falco_source.h"
|
||||
#include "falco_load_result.h"
|
||||
#include "filter_details_resolver.h"
|
||||
#include "rule_loader_reader.h"
|
||||
#include "rule_loader_compiler.h"
|
||||
|
||||
//
|
||||
// This class acts as the primary interface between a program and the
|
||||
@@ -56,7 +58,16 @@ public:
|
||||
// and rules file format it supports. This version will change
|
||||
// any time the code that handles rules files, expression
|
||||
// fields, etc, changes.
|
||||
static uint32_t engine_version();
|
||||
static sinsp_version engine_version();
|
||||
|
||||
// Engine version used to be represented as a simple progressive
|
||||
// number. With the new semver schema, the number now represents
|
||||
// the semver minor number. This function converts the legacy version
|
||||
// number to the new semver schema.
|
||||
static inline sinsp_version get_implicit_version(uint32_t minor)
|
||||
{
|
||||
return rule_loader::reader::get_implicit_engine_version(minor);
|
||||
}
|
||||
|
||||
// Print to stdout (using printf) a description of each field supported by this engine.
|
||||
// If source is non-empty, only fields for the provided source are printed.
|
||||
@@ -85,15 +96,23 @@ public:
|
||||
//
|
||||
void enable_rule(const std::string &substring, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Same as above but providing a ruleset id instead
|
||||
void enable_rule(const std::string &substring, bool enabled, const uint16_t ruleset_id);
|
||||
|
||||
// Like enable_rule, but the rule name must be an exact match.
|
||||
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Same as above but providing a ruleset id instead
|
||||
void enable_rule_exact(const std::string &rule_name, bool enabled, const uint16_t ruleset_id);
|
||||
|
||||
//
|
||||
// Enable/Disable any rules with any of the provided tags (set, exact matches only)
|
||||
//
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Same as above but providing a ruleset id instead
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled, const uint16_t ruleset_id);
|
||||
|
||||
//
|
||||
// Must be called after the engine has been configured and all rulesets
|
||||
// have been loaded and enabled/disabled.
|
||||
@@ -125,7 +144,7 @@ public:
|
||||
// Print details on the given rule. If rule is NULL, print
|
||||
// details on all rules.
|
||||
//
|
||||
void describe_rule(std::string *rule, bool json) const;
|
||||
nlohmann::json describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
|
||||
//
|
||||
// Print statistics on how many events matched each rule.
|
||||
@@ -303,18 +322,31 @@ private:
|
||||
inline bool should_drop_evt() const;
|
||||
|
||||
// Retrieve json details from rules, macros, lists
|
||||
void get_json_details(const falco_rule& r,
|
||||
const rule_loader::rule_info& ri,
|
||||
sinsp* insp,
|
||||
Json::Value& rule) const;
|
||||
void get_json_details(const rule_loader::macro_info& m,
|
||||
Json::Value& macro) const;
|
||||
void get_json_details(const rule_loader::list_info& l,
|
||||
Json::Value& list) const;
|
||||
void get_json_details(libsinsp::filter::ast::expr* ast,
|
||||
Json::Value& output) const;
|
||||
void get_json_evt_types(libsinsp::filter::ast::expr* ast,
|
||||
Json::Value& output) const;
|
||||
void get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_rule& r,
|
||||
const rule_loader::rule_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_macro& m,
|
||||
const rule_loader::macro_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_list& l,
|
||||
const rule_loader::list_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_evt_types(
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
libsinsp::filter::ast::expr* ast) const;
|
||||
void get_json_used_plugins(
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
const std::unordered_set<std::string>& evttypes,
|
||||
const std::unordered_set<std::string>& fields,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
|
||||
rule_loader::collector m_rule_collector;
|
||||
indexed_vector<falco_rule> m_rules;
|
||||
@@ -324,6 +356,8 @@ private:
|
||||
std::map<std::string, uint16_t> m_known_rulesets;
|
||||
falco_common::priority_type m_min_priority;
|
||||
|
||||
std::unique_ptr<rule_loader::compiler::compile_output> m_last_compile_output;
|
||||
|
||||
//
|
||||
// Here's how the sampling ratio and multiplier influence
|
||||
// whether or not an event is dropped in
|
||||
|
||||
@@ -15,8 +15,18 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// The version of this Falco engine.
|
||||
#define FALCO_ENGINE_VERSION (26)
|
||||
#define __FALCO_ENGINE_STRINGIFY1(str) #str
|
||||
#define __FALCO_ENGINE_STRINGIFY(str) __FALCO_ENGINE_STRINGIFY1(str)
|
||||
|
||||
// The version of this Falco engine
|
||||
#define FALCO_ENGINE_VERSION_MAJOR 0
|
||||
#define FALCO_ENGINE_VERSION_MINOR 29
|
||||
#define FALCO_ENGINE_VERSION_PATCH 0
|
||||
|
||||
#define FALCO_ENGINE_VERSION \
|
||||
__FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_MAJOR) "." \
|
||||
__FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_MINOR) "." \
|
||||
__FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_PATCH)
|
||||
|
||||
// This is the result of running the following command:
|
||||
// FALCO="falco -c ./falco.yaml"
|
||||
@@ -24,4 +34,4 @@ limitations under the License.
|
||||
// It represents the fields supported by this version of Falco,
|
||||
// the event types, and the underlying driverevent schema. It's used to
|
||||
// detetect changes in engine version in our CI jobs.
|
||||
#define FALCO_ENGINE_CHECKSUM "98c6e665031b95c666a9ab02d5470e7008e8636bf02f4cc410912005b90dff5c"
|
||||
#define FALCO_ENGINE_CHECKSUM "30bd8b1c09eab71e14416f04b617d4d20bc7c7358bce91748ce9bd8007786c4d"
|
||||
|
||||
@@ -21,6 +21,46 @@ limitations under the License.
|
||||
#include <string>
|
||||
#include "falco_common.h"
|
||||
|
||||
#include <filter/ast.h>
|
||||
|
||||
/*!
|
||||
\brief Represents a list in the Falco Engine.
|
||||
The rule ID must be unique across all the lists loaded in the engine.
|
||||
*/
|
||||
struct falco_list
|
||||
{
|
||||
falco_list(): used(false), id(0) { }
|
||||
falco_list(falco_list&&) = default;
|
||||
falco_list& operator = (falco_list&&) = default;
|
||||
falco_list(const falco_list&) = default;
|
||||
falco_list& operator = (const falco_list&) = default;
|
||||
~falco_list() = default;
|
||||
|
||||
bool used;
|
||||
std::size_t id;
|
||||
std::string name;
|
||||
std::vector<std::string> items;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents a macro in the Falco Engine.
|
||||
The rule ID must be unique across all the macros loaded in the engine.
|
||||
*/
|
||||
struct falco_macro
|
||||
{
|
||||
falco_macro(): used(false), id(0) { }
|
||||
falco_macro(falco_macro&&) = default;
|
||||
falco_macro& operator = (falco_macro&&) = default;
|
||||
falco_macro(const falco_macro&) = default;
|
||||
falco_macro& operator = (const falco_macro&) = default;
|
||||
~falco_macro() = default;
|
||||
|
||||
bool used;
|
||||
std::size_t id;
|
||||
std::string name;
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents a rule in the Falco Engine.
|
||||
The rule ID must be unique across all the rules loaded in the engine.
|
||||
@@ -32,6 +72,7 @@ struct falco_rule
|
||||
falco_rule& operator = (falco_rule&&) = default;
|
||||
falco_rule(const falco_rule&) = default;
|
||||
falco_rule& operator = (const falco_rule&) = default;
|
||||
~falco_rule() = default;
|
||||
|
||||
std::size_t id;
|
||||
std::string source;
|
||||
@@ -41,4 +82,5 @@ struct falco_rule
|
||||
std::set<std::string> tags;
|
||||
std::set<std::string> exception_fields;
|
||||
falco_common::priority_type priority;
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,6 @@ limitations under the License.
|
||||
|
||||
#include "falco_utils.h"
|
||||
#include "utils.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
#include <re2/re2.h>
|
||||
|
||||
@@ -160,6 +159,7 @@ void readfile(const std::string& filename, std::string& data)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
namespace network
|
||||
{
|
||||
bool is_unix_scheme(const std::string& url)
|
||||
|
||||
@@ -19,22 +19,36 @@ limitations under the License.
|
||||
|
||||
using namespace libsinsp::filter;
|
||||
|
||||
std::string get_field_name(const std::string& name, const std::string& arg)
|
||||
{
|
||||
std::string fld = name;
|
||||
if (!arg.empty())
|
||||
{
|
||||
fld += "[" + arg + "]";
|
||||
}
|
||||
return fld;
|
||||
}
|
||||
|
||||
void filter_details::reset()
|
||||
{
|
||||
fields.clear();
|
||||
macros.clear();
|
||||
operators.clear();
|
||||
lists.clear();
|
||||
evtnames.clear();
|
||||
}
|
||||
|
||||
void filter_details_resolver::run(ast::expr* filter, filter_details& details)
|
||||
{
|
||||
visitor v(details);
|
||||
// note: we may have ASTs composed on only one macro ref
|
||||
v.m_expect_macro = true;
|
||||
filter->accept(&v);
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::and_expr* e)
|
||||
{
|
||||
m_expect_macro = false;
|
||||
for(size_t i = 0; i < e->children.size(); i++)
|
||||
{
|
||||
m_expect_macro = true;
|
||||
@@ -45,6 +59,7 @@ void filter_details_resolver::visitor::visit(ast::and_expr* e)
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::or_expr* e)
|
||||
{
|
||||
m_expect_macro = false;
|
||||
for(size_t i = 0; i < e->children.size(); i++)
|
||||
{
|
||||
m_expect_macro = true;
|
||||
@@ -70,35 +85,50 @@ void filter_details_resolver::visitor::visit(ast::list_expr* e)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_expect_evtname)
|
||||
{
|
||||
for(const auto& item : e->values)
|
||||
{
|
||||
if(m_details.known_lists.find(item) == m_details.known_lists.end())
|
||||
{
|
||||
m_details.evtnames.insert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::binary_check_expr* e)
|
||||
{
|
||||
m_expect_macro = false;
|
||||
m_details.fields.insert(e->field);
|
||||
m_details.fields.insert(get_field_name(e->field, e->arg));
|
||||
m_details.operators.insert(e->op);
|
||||
m_expect_list = true;
|
||||
m_expect_evtname = e->field == "evt.type" || e->field == "evt.asynctype";
|
||||
e->value->accept(this);
|
||||
m_expect_evtname = false;
|
||||
m_expect_list = false;
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::unary_check_expr* e)
|
||||
{
|
||||
m_expect_macro = false;
|
||||
m_details.fields.insert(e->field);
|
||||
m_details.fields.insert(get_field_name(e->field, e->arg));
|
||||
m_details.operators.insert(e->op);
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::value_expr* e)
|
||||
{
|
||||
if(m_expect_macro)
|
||||
if (m_expect_macro)
|
||||
{
|
||||
auto it = m_details.known_macros.find(e->value);
|
||||
if(it == m_details.known_macros.end())
|
||||
if(m_details.known_macros.find(e->value) != m_details.known_macros.end())
|
||||
{
|
||||
return;
|
||||
m_details.macros.insert(e->value);
|
||||
}
|
||||
|
||||
m_details.macros.insert(e->value);
|
||||
// todo(jasondellaluce): should we throw an error if we
|
||||
// encounter an unknown macro?
|
||||
}
|
||||
else if (m_expect_evtname)
|
||||
{
|
||||
m_details.evtnames.insert(e->value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,17 +22,18 @@ limitations under the License.
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
struct filter_details
|
||||
struct filter_details
|
||||
{
|
||||
// input macros and lists
|
||||
std::unordered_set<std::string> known_macros;
|
||||
std::unordered_set<std::string> known_lists;
|
||||
|
||||
|
||||
// output details
|
||||
std::unordered_set<std::string> fields;
|
||||
std::unordered_set<std::string> macros;
|
||||
std::unordered_set<std::string> operators;
|
||||
std::unordered_set<std::string> lists;
|
||||
std::unordered_set<std::string> evtnames;
|
||||
|
||||
void reset();
|
||||
};
|
||||
@@ -46,24 +47,23 @@ public:
|
||||
/*!
|
||||
\brief Visits a filter AST and stores details about macros, lists,
|
||||
fields and operators used.
|
||||
\param filter The filter AST to be processed.
|
||||
\param details Helper structure used to state known macros and
|
||||
\param filter The filter AST to be processed.
|
||||
\param details Helper structure used to state known macros and
|
||||
lists on input, and to store all the retrieved details as output.
|
||||
*/
|
||||
void run(libsinsp::filter::ast::expr* filter,
|
||||
filter_details& details);
|
||||
|
||||
|
||||
private:
|
||||
struct visitor : public libsinsp::filter::ast::expr_visitor
|
||||
{
|
||||
visitor(filter_details& details) :
|
||||
visitor(filter_details& details) :
|
||||
m_details(details),
|
||||
m_expect_list(false),
|
||||
m_expect_macro(false) {}
|
||||
m_expect_macro(false),
|
||||
m_expect_evtname(false) {}
|
||||
visitor(visitor&&) = default;
|
||||
visitor& operator = (visitor&&) = default;
|
||||
visitor(const visitor&) = delete;
|
||||
visitor& operator = (const visitor&) = delete;
|
||||
|
||||
void visit(libsinsp::filter::ast::and_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::or_expr* e) override;
|
||||
@@ -76,5 +76,6 @@ private:
|
||||
filter_details& m_details;
|
||||
bool m_expect_list;
|
||||
bool m_expect_macro;
|
||||
bool m_expect_evtname;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ class filter_macro_resolver
|
||||
|
||||
/*!
|
||||
\brief used in get_{resolved,unknown}_macros and get_errors
|
||||
to represent an identifier/string value along with an AST position.
|
||||
to represent an identifier/string value along with an AST position.
|
||||
*/
|
||||
typedef std::pair<std::string,libsinsp::filter::ast::pos_info> value_info;
|
||||
|
||||
@@ -103,10 +103,6 @@ class filter_macro_resolver
|
||||
m_unknown_macros(unknown_macros),
|
||||
m_resolved_macros(resolved_macros),
|
||||
m_macros(macros) {}
|
||||
visitor(visitor&&) = default;
|
||||
visitor& operator = (visitor&&) = default;
|
||||
visitor(const visitor&) = delete;
|
||||
visitor& operator = (const visitor&) = delete;
|
||||
|
||||
std::vector<std::string> m_macros_path;
|
||||
std::unique_ptr<libsinsp::filter::ast::expr> m_node_substitute;
|
||||
|
||||
@@ -19,7 +19,6 @@ limitations under the License.
|
||||
|
||||
#include "formats.h"
|
||||
#include "falco_engine.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
falco_formats::falco_formats(std::shared_ptr<const falco_engine> engine,
|
||||
bool json_include_output_property,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,512 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 <memory>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "falco_common.h"
|
||||
#include "prefix_search.h"
|
||||
#include <sinsp.h>
|
||||
|
||||
class json_event : public gen_event
|
||||
{
|
||||
public:
|
||||
json_event();
|
||||
virtual ~json_event();
|
||||
|
||||
void set_jevt(nlohmann::json &evt, uint64_t ts);
|
||||
const nlohmann::json &jevt();
|
||||
|
||||
uint64_t get_ts() const;
|
||||
|
||||
inline uint16_t get_source() const
|
||||
{
|
||||
return ESRC_K8S_AUDIT;
|
||||
}
|
||||
|
||||
inline uint16_t get_type() const
|
||||
{
|
||||
// All k8s audit events have the single tag "1". - see falco_engine::process_k8s_audit_event
|
||||
return ppm_event_code::PPME_PLUGINEVENT_E;
|
||||
}
|
||||
|
||||
protected:
|
||||
nlohmann::json m_jevt;
|
||||
|
||||
uint64_t m_event_ts;
|
||||
};
|
||||
|
||||
namespace falco_k8s_audit {
|
||||
|
||||
//
|
||||
// Given a raw json object, return a list of k8s audit event
|
||||
// objects that represent the object. This method handles
|
||||
// things such as EventList splitting.
|
||||
//
|
||||
// Returns true if the json object was recognized as a k8s
|
||||
// audit event(s), false otherwise.
|
||||
//
|
||||
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top=true);
|
||||
};
|
||||
|
||||
// A class representing an extracted value or a value on the rhs of a
|
||||
// filter_check. This intentionally doesn't use the same types as
|
||||
// ppm_events_public.h to take advantage of actual classes instead of
|
||||
// lower-level pointers pointing to syscall events and to allow for
|
||||
// efficient set comparisons.
|
||||
|
||||
class json_event_value
|
||||
{
|
||||
public:
|
||||
enum param_type {
|
||||
JT_STRING,
|
||||
JT_INT64,
|
||||
JT_INT64_PAIR
|
||||
};
|
||||
|
||||
json_event_value();
|
||||
json_event_value(const std::string &val);
|
||||
json_event_value(int64_t val);
|
||||
virtual ~json_event_value();
|
||||
|
||||
param_type ptype() const;
|
||||
|
||||
std::string as_string() const;
|
||||
|
||||
bool operator==(const json_event_value &val) const;
|
||||
bool operator!=(const json_event_value &val) const;
|
||||
bool operator<(const json_event_value &val) const;
|
||||
bool operator>(const json_event_value &val) const;
|
||||
|
||||
// Only meaningful for string types
|
||||
bool startswith(const json_event_value &val) const;
|
||||
bool contains(const json_event_value &val) const;
|
||||
|
||||
private:
|
||||
param_type m_type;
|
||||
|
||||
static bool parse_as_pair_int64(std::pair<int64_t,int64_t> &pairval, const std::string &val);
|
||||
static bool parse_as_int64(int64_t &intval, const std::string &val);
|
||||
|
||||
// The number of possible types is small so far, so sticking
|
||||
// with separate vars
|
||||
|
||||
std::string m_stringval;
|
||||
int64_t m_intval;
|
||||
std::pair<int64_t,int64_t> m_pairval;
|
||||
};
|
||||
|
||||
class json_event_filter_check : public gen_event_filter_check
|
||||
{
|
||||
public:
|
||||
|
||||
static std::string no_value;
|
||||
|
||||
enum index_mode
|
||||
{
|
||||
IDX_REQUIRED,
|
||||
IDX_ALLOWED,
|
||||
IDX_NONE
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_index_mode_strs;
|
||||
|
||||
enum index_type
|
||||
{
|
||||
IDX_KEY,
|
||||
IDX_NUMERIC
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_index_type_strs;
|
||||
|
||||
// A struct describing a single filtercheck field ("ka.user")
|
||||
struct field_info
|
||||
{
|
||||
std::string m_name;
|
||||
std::string m_desc;
|
||||
|
||||
index_mode m_idx_mode;
|
||||
index_type m_idx_type;
|
||||
|
||||
bool m_uses_paths;
|
||||
|
||||
// The variants allow for brace-initialization either
|
||||
// with just the name/desc or additionally with index
|
||||
// information
|
||||
field_info();
|
||||
field_info(std::string name, std::string desc);
|
||||
field_info(std::string name, std::string desc, index_mode mode);
|
||||
field_info(std::string name, std::string desc, index_mode mode, index_type itype);
|
||||
field_info(std::string name, std::string desc, index_mode mode, index_type itype, bool uses_paths);
|
||||
virtual ~field_info();
|
||||
};
|
||||
|
||||
// A struct describing a group of filtercheck fields ("ka")
|
||||
struct check_info
|
||||
{
|
||||
std::string m_name;
|
||||
std::string m_shortdesc;
|
||||
std::string m_desc;
|
||||
|
||||
std::list<field_info> m_fields;
|
||||
};
|
||||
|
||||
json_event_filter_check();
|
||||
virtual ~json_event_filter_check() = 0;
|
||||
|
||||
virtual int32_t parse_field_name(const char *str, bool alloc_state, bool needed_for_filtering);
|
||||
void add_filter_value(const char *str, uint32_t len, uint32_t i = 0);
|
||||
bool compare(gen_event *evt);
|
||||
|
||||
// This is adapted to support the new extract() method signature that
|
||||
// supports extracting list of values, however json_evt was implemented
|
||||
// to support this feature in the first place through the
|
||||
// extracted_values_t structure. As such, for now this is only used for
|
||||
// signature compliance, and always pushes a single value. The value pushed
|
||||
// in the vector is a a const extracted_values_t* that points to the
|
||||
// internal m_evalues. This is a temporary workaround to sync with the
|
||||
// latest falcosecurity/libs development without re-designing the whole K8S
|
||||
// support, which will eventually be refactored as a plugin in the future anyway.
|
||||
bool extract(gen_event *evt, std::vector<extract_value_t>& values, bool sanitize_strings = true) final;
|
||||
|
||||
const std::string &field();
|
||||
const std::string &idx();
|
||||
|
||||
// The combined size of the field, index, and surrounding
|
||||
// brackets (e.g. ka.image[foo])
|
||||
size_t parsed_size();
|
||||
|
||||
virtual const check_info &get_info() const = 0;
|
||||
|
||||
//
|
||||
// Allocate a new check of the same type. Must be overridden.
|
||||
//
|
||||
virtual json_event_filter_check *allocate_new() = 0;
|
||||
|
||||
// Subclasses or extraction functions can call this method to add each extracted value.
|
||||
void add_extracted_value(const std::string &val);
|
||||
void add_extracted_value_num(int64_t val);
|
||||
|
||||
// After calling extract, you can call extracted_values to get
|
||||
// the values extracted from an event.
|
||||
typedef std::vector<json_event_value> values_t;
|
||||
const values_t &extracted_values();
|
||||
|
||||
protected:
|
||||
// Subclasses can override this method, calling
|
||||
// add_extracted_value to add extracted values.
|
||||
virtual bool extract_values(json_event *jevt);
|
||||
|
||||
static std::string json_as_string(const nlohmann::json &j);
|
||||
|
||||
// Subclasses can define field names that act as aliases for
|
||||
// specific json pointer expressions e.g. ka.user ==
|
||||
// jevt.value[/user/username]. This struct represents one of
|
||||
// those aliases.
|
||||
|
||||
// An alias might define an alternative function to extract
|
||||
// values instead of using a json pointer. An example is
|
||||
// ka.uri.param, which parses the query string to extract
|
||||
// key=value parameters.
|
||||
typedef std::function<bool (const nlohmann::json &, json_event_filter_check &jchk)> extract_t;
|
||||
|
||||
struct alias
|
||||
{
|
||||
// The variants allow for brace-initialization either
|
||||
// with just the pointer list or with a custom
|
||||
// extraction function.
|
||||
alias();
|
||||
alias(std::list<nlohmann::json::json_pointer> ptrs);
|
||||
alias(extract_t extract);
|
||||
|
||||
virtual ~alias();
|
||||
|
||||
// A json pointer used to extract a referenced value
|
||||
// from a json object. The pointers are applied in
|
||||
// order. After applying a pointer, if the resulting
|
||||
// object is an array, each array member is considered
|
||||
// for subsequent json pointers.
|
||||
//
|
||||
// This allows for "plucking" items out of an array
|
||||
// selected by an earlier json pointer.
|
||||
std::list<nlohmann::json::json_pointer> m_jptrs;
|
||||
|
||||
extract_t m_extract;
|
||||
};
|
||||
|
||||
// This map defines the aliases defined by this filter check
|
||||
// class.
|
||||
//
|
||||
// The version of parse_field_name in this base class will
|
||||
// check a field specification against all the aliases.
|
||||
virtual const std::unordered_map<std::string, alias> &get_aliases() const = 0;
|
||||
|
||||
//check_info m_info;
|
||||
|
||||
// The actual field name parsed in parse_field_name.
|
||||
std::string m_field;
|
||||
|
||||
// The field name itself might include an index component
|
||||
// e.g. ka.value[idx]. This holds the index.
|
||||
std::string m_idx;
|
||||
|
||||
private:
|
||||
typedef std::set<json_event_value> values_set_t;
|
||||
typedef std::pair<values_t, values_set_t> extracted_values_t;
|
||||
|
||||
// The default extraction function uses the list of pointers
|
||||
// in m_jptrs. Iterates over array elements between pointers if
|
||||
// found.
|
||||
bool def_extract(const nlohmann::json &j,
|
||||
const std::list<nlohmann::json::json_pointer> &ptrs,
|
||||
std::list<nlohmann::json::json_pointer>::iterator it);
|
||||
|
||||
// The actual json pointer value to use to extract from
|
||||
// events. See alias struct for usage.
|
||||
std::list<nlohmann::json::json_pointer> m_jptrs;
|
||||
|
||||
// The extraction function to use. May not be defined, in which
|
||||
// case the default function is used.
|
||||
extract_t m_extract;
|
||||
|
||||
// All values specified on the right hand side of the operator
|
||||
// e.g. "ka.ns in ("one","two","three"), m_values has ("one",
|
||||
// "two", "three")
|
||||
values_set_t m_values;
|
||||
|
||||
// All values extracted from the object by the field e.g. for
|
||||
// a field ka.req.container.image returns all container images
|
||||
// for all pods within a request.
|
||||
extracted_values_t m_evalues;
|
||||
|
||||
// If true, this filtercheck works on paths, which enables
|
||||
// some extra bookkeeping to allow for path prefix searches.
|
||||
bool m_uses_paths = false;
|
||||
|
||||
path_prefix_search m_prefix_search;
|
||||
};
|
||||
|
||||
class jevt_filter_check : public json_event_filter_check
|
||||
{
|
||||
public:
|
||||
jevt_filter_check();
|
||||
virtual ~jevt_filter_check();
|
||||
|
||||
int32_t parse_field_name(const char* str, bool alloc_state, bool needed_for_filtering) final;
|
||||
|
||||
json_event_filter_check *allocate_new() override;
|
||||
const check_info &get_info() const override;
|
||||
|
||||
protected:
|
||||
|
||||
bool extract_values(json_event *jevt) final;
|
||||
const std::unordered_map<std::string, alias> &get_aliases() const override
|
||||
{
|
||||
static std::unordered_map<std::string, alias> a;
|
||||
return a;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// When the field is jevt_value, a json pointer representing
|
||||
// the index in m_idx
|
||||
nlohmann::json::json_pointer m_idx_ptr;
|
||||
|
||||
static std::string s_jevt_time_field;
|
||||
static std::string s_jevt_time_iso_8601_field;
|
||||
static std::string s_jevt_rawtime_field;
|
||||
static std::string s_jevt_obj_field;
|
||||
static std::string s_jevt_value_field;
|
||||
};
|
||||
|
||||
class k8s_audit_filter_check : public json_event_filter_check
|
||||
{
|
||||
public:
|
||||
k8s_audit_filter_check();
|
||||
virtual ~k8s_audit_filter_check();
|
||||
|
||||
json_event_filter_check *allocate_new() override;
|
||||
|
||||
const check_info &get_info() const override;
|
||||
const std::unordered_map<std::string, alias> &get_aliases() const override;
|
||||
|
||||
// Extract all images/image repositories from the provided containers
|
||||
static bool extract_images(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
// Extract all query parameters
|
||||
static bool extract_query_param(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
// Extract some property from the set of rules in the request object
|
||||
static bool extract_rule_attrs(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
// Determine if the provided path matches any volumes host path.
|
||||
static bool check_volumes_hostpath(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
// Extract the volume types from volumes in the request object
|
||||
static bool extract_volume_types(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
// Extract all hostPort values from containers in the request object
|
||||
static bool extract_host_port(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
// Using both the pod and container security contexts, extract
|
||||
// the uid/gid that will be used for each container.
|
||||
static bool extract_effective_run_as(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
// These are only used for compatibility with older rules files
|
||||
|
||||
// Always return the string "N/A"
|
||||
static bool always_return_na(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
|
||||
|
||||
// Return true if any container has privileged=true
|
||||
static bool extract_any_privileged(const nlohmann::json &j,
|
||||
json_event_filter_check &jchk);
|
||||
};
|
||||
|
||||
|
||||
class json_event_filter : public sinsp_filter
|
||||
{
|
||||
public:
|
||||
json_event_filter();
|
||||
virtual ~json_event_filter();
|
||||
|
||||
std::string m_rule;
|
||||
uint32_t m_rule_idx;
|
||||
std::set<std::string> m_tags;
|
||||
};
|
||||
|
||||
class json_event_filter_factory : public gen_event_filter_factory
|
||||
{
|
||||
public:
|
||||
json_event_filter_factory();
|
||||
virtual ~json_event_filter_factory();
|
||||
|
||||
// Create a new filter
|
||||
gen_event_filter *new_filter();
|
||||
|
||||
// Create a new filter_check
|
||||
gen_event_filter_check *new_filtercheck(const char *fldname);
|
||||
|
||||
// All defined field names
|
||||
std::list<gen_event_filter_factory::filter_fieldclass_info> get_fields();
|
||||
|
||||
private:
|
||||
std::list<std::shared_ptr<json_event_filter_check>> m_defined_checks;
|
||||
std::list<json_event_filter_check::check_info> m_info;
|
||||
};
|
||||
|
||||
class json_event_formatter : public gen_event_formatter
|
||||
{
|
||||
public:
|
||||
json_event_formatter(std::shared_ptr<gen_event_filter_factory> factory);
|
||||
virtual ~json_event_formatter();
|
||||
|
||||
void set_format(output_format of, const std::string &format) override;
|
||||
bool tostring(gen_event *evt, std::string &output) override;
|
||||
bool tostring_withformat(gen_event *evt, std::string &output, gen_event_formatter::output_format of) override;
|
||||
bool get_field_values(gen_event *evt, std::map<std::string, std::string> &fields) override;
|
||||
void get_field_names(std::vector<std::string> &fields) override
|
||||
{
|
||||
throw falco_exception("json_event_formatter::get_field_names operation not supported");
|
||||
}
|
||||
output_format get_output_format() override;
|
||||
|
||||
std::string tojson(json_event *ev);
|
||||
|
||||
// Split the format string into a list of tuples, broken at
|
||||
// output fields, where each tuple is either a block of text
|
||||
// from the original format string, or a field value/pair from
|
||||
// the original format string.
|
||||
//
|
||||
// For example, given a format string "some output
|
||||
// (%proc.name)", this will fill in resolved with 3 tuples:
|
||||
// - ["", "some output ("]
|
||||
// - ["proc.name", "nginx"]
|
||||
// - ["", ")"]
|
||||
//
|
||||
// This can be used either to return a resolved output string
|
||||
// or a map of field name/value pairs.
|
||||
void resolve_format(json_event *ev, std::list<std::pair<std::string, std::string>> &resolved);
|
||||
|
||||
private:
|
||||
void parse_format();
|
||||
|
||||
// A format token is either a combination of a filtercheck
|
||||
// name (ka.value) and filtercheck object as key, or an empty
|
||||
// key and a NULL filtercheck object, combined with a value (
|
||||
//
|
||||
// For example, given a format string:
|
||||
// "The value is %ka.value today"
|
||||
// The tokens would be:
|
||||
// [("The value is ", NULL), ("ka.value", <an object>), " today", NULL)]
|
||||
|
||||
struct fmt_token
|
||||
{
|
||||
std::string text;
|
||||
std::shared_ptr<json_event_filter_check> check;
|
||||
};
|
||||
|
||||
gen_event_formatter::output_format m_output_format;
|
||||
|
||||
// The original format string
|
||||
std::string m_format;
|
||||
|
||||
// The chunks that make up the format string, in order, broken
|
||||
// up between text chunks and filterchecks.
|
||||
std::list<fmt_token> m_tokens;
|
||||
|
||||
// All the filterchecks required to resolve tokens in the format string
|
||||
std::shared_ptr<gen_event_filter_factory> m_json_factory;
|
||||
};
|
||||
|
||||
class json_event_formatter_factory : public gen_event_formatter_factory
|
||||
{
|
||||
public:
|
||||
json_event_formatter_factory(std::shared_ptr<gen_event_filter_factory> factory);
|
||||
virtual ~json_event_formatter_factory();
|
||||
|
||||
void set_output_format(gen_event_formatter::output_format of) override;
|
||||
|
||||
std::shared_ptr<gen_event_formatter> create_formatter(const std::string &format) override;
|
||||
|
||||
protected:
|
||||
// Maps from output string to formatter
|
||||
std::map<std::string, std::shared_ptr<gen_event_formatter>> m_formatters;
|
||||
|
||||
gen_event_formatter::output_format m_output_format;
|
||||
|
||||
// All the filterchecks required to resolve tokens in the format string
|
||||
std::shared_ptr<gen_event_filter_factory> m_json_factory;
|
||||
};
|
||||
@@ -517,7 +517,7 @@ const nlohmann::json& rule_loader::result::as_json(const rules_contents_t& conte
|
||||
}
|
||||
|
||||
rule_loader::engine_version_info::engine_version_info(context &ctx)
|
||||
: ctx(ctx), version(0)
|
||||
: ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -532,12 +532,12 @@ rule_loader::plugin_version_info::plugin_version_info(context &ctx)
|
||||
}
|
||||
|
||||
rule_loader::list_info::list_info(context &ctx)
|
||||
: ctx(ctx), used(false), index(0), visibility(0)
|
||||
: ctx(ctx), index(0), visibility(0)
|
||||
{
|
||||
}
|
||||
|
||||
rule_loader::macro_info::macro_info(context &ctx)
|
||||
: ctx(ctx), cond_ctx(ctx), used(false), index(0), visibility(0)
|
||||
: ctx(ctx), cond_ctx(ctx), index(0), visibility(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -562,10 +562,8 @@ rule_loader::rule_load_exception::~rule_load_exception()
|
||||
{
|
||||
}
|
||||
|
||||
const char* rule_loader::rule_load_exception::what()
|
||||
const char* rule_loader::rule_load_exception::what() const noexcept
|
||||
{
|
||||
errstr = falco::load_result::error_code_str(ec) + ": "
|
||||
+ msg.c_str();
|
||||
|
||||
return errstr.c_str();
|
||||
// const + noexcept: can't use functions that change the object or throw
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ limitations under the License.
|
||||
#include "falco_source.h"
|
||||
#include "falco_load_result.h"
|
||||
#include "indexed_vector.h"
|
||||
#include "version.h"
|
||||
|
||||
namespace rule_loader
|
||||
{
|
||||
@@ -208,18 +209,12 @@ namespace rule_loader
|
||||
public:
|
||||
rule_load_exception(falco::load_result::error_code ec, const std::string& msg, const context& ctx);
|
||||
virtual ~rule_load_exception();
|
||||
rule_load_exception(rule_load_exception&&) = default;
|
||||
rule_load_exception& operator = (rule_load_exception&&) = default;
|
||||
rule_load_exception(const rule_load_exception&) = default;
|
||||
rule_load_exception& operator = (const rule_load_exception&) = default;
|
||||
|
||||
const char* what();
|
||||
const char* what() const noexcept override;
|
||||
|
||||
falco::load_result::error_code ec;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
|
||||
std::string errstr;
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -273,24 +268,20 @@ namespace rule_loader
|
||||
const indexed_vector<falco_source>& srcs,
|
||||
const std::string& name)
|
||||
: content(cont), sources(srcs), name(name),
|
||||
default_ruleset_id(0), replace_output_container_info(false),
|
||||
min_priority(falco_common::PRIORITY_DEBUG)
|
||||
output_extra(), replace_output_container_info(false)
|
||||
{
|
||||
res.reset(new result(name));
|
||||
}
|
||||
configuration(configuration&&) = default;
|
||||
configuration& operator = (configuration&&) = default;
|
||||
configuration(const configuration&) = delete;
|
||||
configuration& operator = (const configuration&) = delete;
|
||||
|
||||
// inputs
|
||||
const std::string& content;
|
||||
const indexed_vector<falco_source>& sources;
|
||||
std::string name;
|
||||
std::unique_ptr<result> res;
|
||||
std::string output_extra;
|
||||
uint16_t default_ruleset_id;
|
||||
bool replace_output_container_info;
|
||||
falco_common::priority_type min_priority;
|
||||
|
||||
// outputs
|
||||
std::unique_ptr<result> res;
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -298,7 +289,7 @@ namespace rule_loader
|
||||
*/
|
||||
struct engine_version_info
|
||||
{
|
||||
engine_version_info() : ctx("no-filename-given"), version(0) { };
|
||||
engine_version_info() : ctx("no-filename-given"), version("0.0.0") { };
|
||||
engine_version_info(context &ctx);
|
||||
~engine_version_info() = default;
|
||||
engine_version_info(engine_version_info&&) = default;
|
||||
@@ -307,7 +298,7 @@ namespace rule_loader
|
||||
engine_version_info& operator = (const engine_version_info&) = default;
|
||||
|
||||
context ctx;
|
||||
uint32_t version;
|
||||
sinsp_version version;
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -359,7 +350,6 @@ namespace rule_loader
|
||||
list_info& operator = (const list_info&) = default;
|
||||
|
||||
context ctx;
|
||||
bool used;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
std::string name;
|
||||
@@ -380,12 +370,10 @@ namespace rule_loader
|
||||
|
||||
context ctx;
|
||||
context cond_ctx;
|
||||
bool used;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
std::string name;
|
||||
std::string cond;
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> cond_ast;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -146,9 +146,11 @@ const indexed_vector<rule_loader::rule_info>& rule_loader::collector::rules() co
|
||||
void rule_loader::collector::define(configuration& cfg, engine_version_info& info)
|
||||
{
|
||||
auto v = falco_engine::engine_version();
|
||||
THROW(v < info.version, "Rules require engine version "
|
||||
+ std::to_string(info.version) + ", but engine version is " + std::to_string(v),
|
||||
THROW(!v.compatible_with(info.version), "Rules require engine version "
|
||||
+ info.version.as_string() + ", but engine version is " + v.as_string(),
|
||||
info.ctx);
|
||||
|
||||
// Store max required_engine_version
|
||||
if(m_required_engine_version.version < info.version)
|
||||
{
|
||||
m_required_engine_version = info;
|
||||
@@ -161,7 +163,7 @@ void rule_loader::collector::define(configuration& cfg, plugin_version_info& inf
|
||||
for (const auto& req : info.alternatives)
|
||||
{
|
||||
sinsp_version plugin_version(req.version);
|
||||
THROW(!plugin_version.m_valid,
|
||||
THROW(!plugin_version.is_valid(),
|
||||
"Invalid required version '" + req.version
|
||||
+ "' for plugin '" + req.name + "'",
|
||||
info.ctx);
|
||||
|
||||
@@ -50,12 +50,6 @@ static void paren_item(std::string& e)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_operator_defined(const std::string& op)
|
||||
{
|
||||
auto ops = libsinsp::filter::parser::supported_operators();
|
||||
return find(ops.begin(), ops.end(), op) != ops.end();
|
||||
}
|
||||
|
||||
static inline bool is_operator_for_list(const std::string& op)
|
||||
{
|
||||
auto ops = libsinsp::filter::parser::supported_operators(true);
|
||||
@@ -83,12 +77,12 @@ static void build_rule_exception_infos(
|
||||
std::string& condition)
|
||||
{
|
||||
std::string tmp;
|
||||
for (auto &ex : exceptions)
|
||||
for (const auto &ex : exceptions)
|
||||
{
|
||||
std::string icond;
|
||||
if(!ex.fields.is_list)
|
||||
{
|
||||
for (auto &val : ex.values)
|
||||
for (const auto &val : ex.values)
|
||||
{
|
||||
THROW(val.is_list,
|
||||
"Expected values array to contain a list of strings",
|
||||
@@ -107,7 +101,7 @@ static void build_rule_exception_infos(
|
||||
else
|
||||
{
|
||||
icond = "(";
|
||||
for (auto &values : ex.values)
|
||||
for (const auto &values : ex.values)
|
||||
{
|
||||
THROW(ex.fields.items.size() != values.items.size(),
|
||||
"Fields and values lists must have equal length",
|
||||
@@ -116,13 +110,13 @@ static void build_rule_exception_infos(
|
||||
icond += "(";
|
||||
uint32_t k = 0;
|
||||
std::string istr;
|
||||
for (auto &field : ex.fields.items)
|
||||
for (const auto &field : ex.fields.items)
|
||||
{
|
||||
icond += k == 0 ? "" : " and ";
|
||||
if (values.items[k].is_list)
|
||||
{
|
||||
istr = "(";
|
||||
for (auto &v : values.items[k].items)
|
||||
for (const auto &v : values.items[k].items)
|
||||
{
|
||||
tmp = v.item;
|
||||
quote_item(tmp);
|
||||
@@ -160,8 +154,30 @@ static void build_rule_exception_infos(
|
||||
}
|
||||
}
|
||||
|
||||
static inline rule_loader::list_info* list_info_from_name(
|
||||
const rule_loader::collector& c, const std::string& name)
|
||||
{
|
||||
auto ret = c.lists().at(name);
|
||||
if (!ret)
|
||||
{
|
||||
throw falco_exception("can't find internal list info at name: " + name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline rule_loader::macro_info* macro_info_from_name(
|
||||
const rule_loader::collector& c, const std::string& name)
|
||||
{
|
||||
auto ret = c.macros().at(name);
|
||||
if (!ret)
|
||||
{
|
||||
throw falco_exception("can't find internal macro info at name: " + name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// todo(jasondellaluce): this breaks string escaping in lists
|
||||
static bool resolve_list(std::string& cnd, const rule_loader::list_info& list)
|
||||
static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
{
|
||||
static std::string blanks = " \t\n\r";
|
||||
static std::string delims = blanks + "(),=";
|
||||
@@ -190,7 +206,7 @@ static bool resolve_list(std::string& cnd, const rule_loader::list_info& list)
|
||||
}
|
||||
// create substitution string by concatenating all values
|
||||
std::string sub = "";
|
||||
for (auto &v : list.items)
|
||||
for (const auto &v : list.items)
|
||||
{
|
||||
if (!sub.empty())
|
||||
{
|
||||
@@ -232,18 +248,20 @@ static bool resolve_list(std::string& cnd, const rule_loader::list_info& list)
|
||||
}
|
||||
|
||||
static void resolve_macros(
|
||||
indexed_vector<rule_loader::macro_info>& macros,
|
||||
const indexed_vector<rule_loader::macro_info>& infos,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
std::shared_ptr<ast::expr>& ast,
|
||||
const std::string& condition,
|
||||
uint32_t visibility,
|
||||
const rule_loader::context &ctx)
|
||||
{
|
||||
filter_macro_resolver macro_resolver;
|
||||
for (auto &m : macros)
|
||||
for (const auto &m : infos)
|
||||
{
|
||||
if (m.index < visibility)
|
||||
{
|
||||
macro_resolver.set_macro(m.name, m.cond_ast);
|
||||
auto macro = macros.at(m.name);
|
||||
macro_resolver.set_macro(m.name, macro->condition);
|
||||
}
|
||||
}
|
||||
macro_resolver.run(ast);
|
||||
@@ -263,7 +281,7 @@ static void resolve_macros(
|
||||
THROW(true, errmsg, cond_ctx);
|
||||
}
|
||||
|
||||
for (auto &it : macro_resolver.get_resolved_macros())
|
||||
for (const auto &it : macro_resolver.get_resolved_macros())
|
||||
{
|
||||
macros.at(it.first)->used = true;
|
||||
}
|
||||
@@ -272,7 +290,7 @@ static void resolve_macros(
|
||||
// note: there is no visibility order between filter conditions and lists
|
||||
static std::shared_ptr<ast::expr> parse_condition(
|
||||
std::string condition,
|
||||
indexed_vector<rule_loader::list_info>& lists,
|
||||
indexed_vector<falco_list>& lists,
|
||||
const rule_loader::context &ctx)
|
||||
{
|
||||
for (auto &l : lists)
|
||||
@@ -319,15 +337,16 @@ static void apply_output_substitutions(
|
||||
void rule_loader::compiler::compile_list_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<list_info>& out) const
|
||||
indexed_vector<falco_list>& out) const
|
||||
{
|
||||
std::string tmp;
|
||||
std::vector<std::string> used;
|
||||
for (auto &list : col.lists())
|
||||
std::list<std::string> used;
|
||||
falco_list v;
|
||||
for (const auto &list : col.lists())
|
||||
{
|
||||
list_info v = list;
|
||||
v.name = list.name;
|
||||
v.items.clear();
|
||||
for (auto &item : list.items)
|
||||
for (const auto &item : list.items)
|
||||
{
|
||||
const auto ref = col.lists().at(item);
|
||||
if (ref && ref->index < list.visibility)
|
||||
@@ -347,9 +366,10 @@ void rule_loader::compiler::compile_list_infos(
|
||||
}
|
||||
}
|
||||
v.used = false;
|
||||
out.insert(v, v.name);
|
||||
auto list_id = out.insert(v, v.name);
|
||||
out.at(list_id)->id = list_id;
|
||||
}
|
||||
for (auto &v : used)
|
||||
for (const auto &v : used)
|
||||
{
|
||||
out.at(v)->used = true;
|
||||
}
|
||||
@@ -359,20 +379,23 @@ void rule_loader::compiler::compile_list_infos(
|
||||
void rule_loader::compiler::compile_macros_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& out) const
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& out) const
|
||||
{
|
||||
for (auto &m : col.macros())
|
||||
for (const auto &m : col.macros())
|
||||
{
|
||||
macro_info entry = m;
|
||||
entry.cond_ast = parse_condition(m.cond, lists, m.cond_ctx);
|
||||
falco_macro entry;
|
||||
entry.name = m.name;
|
||||
entry.condition = parse_condition(m.cond, lists, m.cond_ctx);
|
||||
entry.used = false;
|
||||
out.insert(entry, m.name);
|
||||
auto macro_id = out.insert(entry, m.name);
|
||||
out.at(macro_id)->id = macro_id;
|
||||
}
|
||||
|
||||
for (auto &m : out)
|
||||
{
|
||||
resolve_macros(out, m.cond_ast, m.cond, m.visibility, m.ctx);
|
||||
auto info = macro_info_from_name(col, m.name);
|
||||
resolve_macros(col.macros(), out, m.condition, info->cond, info->visibility, info->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,14 +409,14 @@ static bool err_is_unknown_type_or_field(const std::string& err)
|
||||
void rule_loader::compiler::compile_rule_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& macros,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
indexed_vector<falco_rule>& out) const
|
||||
{
|
||||
std::string err, condition;
|
||||
std::set<falco::load_result::load_result::warning_code> warn_codes;
|
||||
filter_warning_resolver warn_resolver;
|
||||
for (auto &r : col.rules())
|
||||
for (const auto &r : col.rules())
|
||||
{
|
||||
// skip the rule if it has an unknown source
|
||||
if (r.unknown_source)
|
||||
@@ -401,12 +424,6 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip the rule if below the minimum priority
|
||||
if (r.priority > cfg.min_priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// note: this should not be nullptr if the source is not unknown
|
||||
auto source = cfg.sources.at(r.source);
|
||||
THROW(!source,
|
||||
@@ -423,14 +440,14 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
build_rule_exception_infos(
|
||||
r.exceptions, rule.exception_fields, condition);
|
||||
}
|
||||
auto ast = parse_condition(condition, lists, r.cond_ctx);
|
||||
resolve_macros(macros, ast, condition, MAX_VISIBILITY, r.ctx);
|
||||
rule.condition = parse_condition(condition, lists, r.cond_ctx);
|
||||
resolve_macros(col.macros(), macros, rule.condition, condition, MAX_VISIBILITY, r.ctx);
|
||||
|
||||
// check for warnings in the filtering condition
|
||||
warn_codes.clear();
|
||||
if (warn_resolver.run(ast.get(), warn_codes))
|
||||
if (warn_resolver.run(rule.condition.get(), warn_codes))
|
||||
{
|
||||
for (auto &w : warn_codes)
|
||||
for (const auto &w : warn_codes)
|
||||
{
|
||||
cfg.res->add_warning(w, "", r.ctx);
|
||||
}
|
||||
@@ -443,8 +460,11 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
apply_output_substitutions(cfg, rule.output);
|
||||
}
|
||||
|
||||
// validate the rule's output
|
||||
if(!is_format_valid(*cfg.sources.at(r.source), rule.output, err))
|
||||
{
|
||||
// skip the rule silently if skip_if_unknown_filter is true and
|
||||
// we encountered some specific kind of errors
|
||||
if (err_is_unknown_type_or_field(err) && r.skip_if_unknown_filter)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
@@ -459,30 +479,18 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
r.output_ctx);
|
||||
}
|
||||
|
||||
// construct rule definition and compile it to a filter
|
||||
rule.name = r.name;
|
||||
rule.source = r.source;
|
||||
rule.description = r.desc;
|
||||
rule.priority = r.priority;
|
||||
rule.tags = r.tags;
|
||||
|
||||
auto rule_id = out.insert(rule, rule.name);
|
||||
out.at(rule_id)->id = rule_id;
|
||||
|
||||
// This also compiles the filter, and might throw a
|
||||
// falco_exception with details on the compilation
|
||||
// failure.
|
||||
sinsp_filter_compiler compiler(cfg.sources.at(r.source)->filter_factory, ast.get());
|
||||
try {
|
||||
std::shared_ptr<gen_event_filter> filter(compiler.compile());
|
||||
source->ruleset->add(*out.at(rule_id), filter, ast);
|
||||
// validate the rule's condition: we compile it into a sinsp filter
|
||||
// on-the-fly and we throw an exception with details on failure
|
||||
sinsp_filter_compiler compiler(cfg.sources.at(r.source)->filter_factory, rule.condition.get());
|
||||
try
|
||||
{
|
||||
std::shared_ptr<sinsp_filter> sfPtr(compiler.compile());
|
||||
}
|
||||
catch (const sinsp_exception& e)
|
||||
{
|
||||
// Allow errors containing "nonexistent field" if
|
||||
// skip_if_unknown_filter is true
|
||||
// skip the rule silently if skip_if_unknown_filter is true and
|
||||
// we encountered some specific kind of errors
|
||||
std::string err = e.what();
|
||||
|
||||
if (err_is_unknown_type_or_field(err) && r.skip_if_unknown_filter)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
@@ -491,7 +499,6 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
r.cond_ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
rule_loader::context ctx(compiler.get_pos(), condition, r.cond_ctx);
|
||||
throw rule_loader::rule_load_exception(
|
||||
falco::load_result::load_result::LOAD_ERR_COMPILE_CONDITION,
|
||||
@@ -499,20 +506,10 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
ctx);
|
||||
}
|
||||
|
||||
// By default rules are enabled/disabled for the default ruleset
|
||||
if(r.enabled)
|
||||
{
|
||||
source->ruleset->enable(rule.name, true, cfg.default_ruleset_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
source->ruleset->disable(rule.name, true, cfg.default_ruleset_id);
|
||||
}
|
||||
|
||||
// populate set of event types and emit an special warning
|
||||
if(rule.source == falco_common::syscall_source)
|
||||
if(r.source == falco_common::syscall_source)
|
||||
{
|
||||
auto evttypes = libsinsp::filter::ast::ppm_event_codes(ast.get());
|
||||
auto evttypes = libsinsp::filter::ast::ppm_event_codes(rule.condition.get());
|
||||
if ((evttypes.empty() || evttypes.size() > 100) && r.warn_evttypes)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
@@ -521,23 +518,29 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
r.ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// finalize the rule definition and add it to output
|
||||
rule.name = r.name;
|
||||
rule.source = r.source;
|
||||
rule.description = r.desc;
|
||||
rule.priority = r.priority;
|
||||
rule.tags = r.tags;
|
||||
auto rule_id = out.insert(rule, rule.name);
|
||||
out.at(rule_id)->id = rule_id;
|
||||
}
|
||||
}
|
||||
|
||||
void rule_loader::compiler::compile(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_rule>& out) const
|
||||
compile_output& out) const
|
||||
{
|
||||
indexed_vector<list_info> lists;
|
||||
indexed_vector<macro_info> macros;
|
||||
|
||||
// expand all lists, macros, and rules
|
||||
try
|
||||
{
|
||||
compile_list_infos(cfg, col, lists);
|
||||
compile_macros_infos(cfg, col, lists, macros);
|
||||
compile_rule_infos(cfg, col, lists, macros, out);
|
||||
compile_list_infos(cfg, col, out.lists);
|
||||
compile_macros_infos(cfg, col, out.lists, out.macros);
|
||||
compile_rule_infos(cfg, col, out.lists, out.macros, out.rules);
|
||||
}
|
||||
catch(rule_load_exception &e)
|
||||
{
|
||||
@@ -546,24 +549,24 @@ void rule_loader::compiler::compile(
|
||||
}
|
||||
|
||||
// print info on any dangling lists or macros that were not used anywhere
|
||||
for (auto &m : macros)
|
||||
for (const auto &m : out.macros)
|
||||
{
|
||||
if (!m.used)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::load_result::LOAD_UNUSED_MACRO,
|
||||
"Macro not referred to by any other rule/macro",
|
||||
m.ctx);
|
||||
macro_info_from_name(col, m.name)->ctx);
|
||||
}
|
||||
}
|
||||
for (auto &l : lists)
|
||||
for (const auto &l : out.lists)
|
||||
{
|
||||
if (!l.used)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::LOAD_UNUSED_LIST,
|
||||
"List not referred to by any other rule/macro",
|
||||
l.ctx);
|
||||
list_info_from_name(col, l.name)->ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,23 @@ namespace rule_loader
|
||||
class compiler
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief The output of a compilation.
|
||||
*/
|
||||
struct compile_output
|
||||
{
|
||||
compile_output() = default;
|
||||
virtual ~compile_output() = default;
|
||||
compile_output(compile_output&&) = default;
|
||||
compile_output& operator = (compile_output&&) = default;
|
||||
compile_output(const compile_output&) = default;
|
||||
compile_output& operator = (const compile_output&) = default;
|
||||
|
||||
indexed_vector<falco_list> lists;
|
||||
indexed_vector<falco_macro> macros;
|
||||
indexed_vector<falco_rule> rules;
|
||||
};
|
||||
|
||||
compiler() = default;
|
||||
virtual ~compiler() = default;
|
||||
compiler(compiler&&) = default;
|
||||
@@ -44,25 +61,25 @@ public:
|
||||
virtual void compile(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_rule>& out) const;
|
||||
compile_output& out) const;
|
||||
|
||||
private:
|
||||
void compile_list_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<list_info>& out) const;
|
||||
indexed_vector<falco_list>& out) const;
|
||||
|
||||
void compile_macros_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& out) const;
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& out) const;
|
||||
|
||||
void compile_rule_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& macros,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
indexed_vector<falco_rule>& out) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ limitations under the License.
|
||||
#include <vector>
|
||||
|
||||
#include "rule_loader_reader.h"
|
||||
#include "falco_engine_version.h"
|
||||
#include "logger.h"
|
||||
|
||||
#define THROW(cond, err, ctx) { if ((cond)) { throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_YAML_VALIDATE, (err), (ctx)); } }
|
||||
|
||||
@@ -255,8 +257,27 @@ static void read_item(
|
||||
{
|
||||
rule_loader::context ctx(item, rule_loader::context::REQUIRED_ENGINE_VERSION, "", parent);
|
||||
rule_loader::engine_version_info v(ctx);
|
||||
|
||||
try
|
||||
{
|
||||
// Convert convert to an uint (more restrictive than converting to a string)
|
||||
uint32_t ver;
|
||||
decode_val(item, "required_engine_version", ver, ctx);
|
||||
|
||||
// Build proper semver representation
|
||||
v.version = rule_loader::reader::get_implicit_engine_version(ver);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
// Convert to string
|
||||
std::string ver;
|
||||
decode_val(item, "required_engine_version", ver, ctx);
|
||||
|
||||
v.version = sinsp_version(ver);
|
||||
|
||||
THROW(!v.version.is_valid(), "Unable to parse engine version '" + ver + "' as a semver string. Expected \"x.y.z\" semver format.", ctx);
|
||||
}
|
||||
|
||||
decode_val(item, "required_engine_version", v.version, ctx);
|
||||
collector.define(cfg, v);
|
||||
}
|
||||
else if(item["required_plugin_versions"].IsDefined())
|
||||
|
||||
@@ -19,6 +19,9 @@ limitations under the License.
|
||||
|
||||
#include "rule_loader.h"
|
||||
#include "rule_loader_collector.h"
|
||||
#include "logger.h"
|
||||
#include "version.h"
|
||||
#include "falco_engine_version.h"
|
||||
|
||||
namespace rule_loader
|
||||
{
|
||||
@@ -41,6 +44,19 @@ public:
|
||||
thew new definitions
|
||||
*/
|
||||
virtual bool read(configuration& cfg, collector& loader);
|
||||
|
||||
/*!
|
||||
\brief Engine version used to be represented as a simple progressive
|
||||
number. With the new semver schema, the number now represents
|
||||
the semver minor number. This function converts the legacy version
|
||||
number to the new semver schema.
|
||||
*/
|
||||
static inline sinsp_version get_implicit_engine_version(uint32_t minor)
|
||||
{
|
||||
return sinsp_version(std::to_string(FALCO_ENGINE_VERSION_MAJOR) + "."
|
||||
+ std::to_string(minor) + "."
|
||||
+ std::to_string(FALCO_ENGINE_VERSION_PATCH));
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace rule_loader
|
||||
|
||||
@@ -35,10 +35,6 @@ class stats_manager
|
||||
public:
|
||||
stats_manager();
|
||||
virtual ~stats_manager();
|
||||
stats_manager(stats_manager&&) = default;
|
||||
stats_manager& operator = (stats_manager&&) = default;
|
||||
stats_manager(const stats_manager&) = default;
|
||||
stats_manager& operator = (const stats_manager&) = default;
|
||||
|
||||
/*!
|
||||
\brief Erases the internal state and statistics data
|
||||
|
||||
@@ -26,7 +26,6 @@ set(
|
||||
app/actions/pidfile.cpp
|
||||
app/actions/init_falco_engine.cpp
|
||||
app/actions/init_inspectors.cpp
|
||||
app/actions/init_clients.cpp
|
||||
app/actions/init_outputs.cpp
|
||||
app/actions/list_fields.cpp
|
||||
app/actions/list_plugins.cpp
|
||||
@@ -37,6 +36,7 @@ set(
|
||||
app/actions/print_generated_gvisor_config.cpp
|
||||
app/actions/print_help.cpp
|
||||
app/actions/print_ignored_events.cpp
|
||||
app/actions/print_kernel_version.cpp
|
||||
app/actions/print_plugin_info.cpp
|
||||
app/actions/print_support.cpp
|
||||
app/actions/print_syscall_events.cpp
|
||||
@@ -53,9 +53,7 @@ set(
|
||||
logger.cpp
|
||||
falco_outputs.cpp
|
||||
outputs_file.cpp
|
||||
outputs_program.cpp
|
||||
outputs_stdout.cpp
|
||||
outputs_syslog.cpp
|
||||
event_drops.cpp
|
||||
stats_writer.cpp
|
||||
versions_info.cpp
|
||||
@@ -90,6 +88,14 @@ if(USE_BUNDLED_DEPS)
|
||||
list(APPEND FALCO_DEPENDENCIES yamlcpp)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
list(
|
||||
APPEND FALCO_SOURCES
|
||||
outputs_program.cpp
|
||||
outputs_syslog.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
list(
|
||||
APPEND FALCO_SOURCES
|
||||
@@ -214,12 +220,16 @@ if(MUSL_OPTIMIZED_BUILD AND CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT EMSCRIPTEN)
|
||||
install(TARGETS falco RUNTIME DESTINATION ${FALCO_BIN_DIR} COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
if (EMSCRIPTEN)
|
||||
install(FILES
|
||||
"$<TARGET_FILE_DIR:falco>/falco.js"
|
||||
"$<TARGET_FILE_DIR:falco>/falco.wasm"
|
||||
DESTINATION ${FALCO_BIN_DIR}
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
elseif (WIN32)
|
||||
install(TARGETS falco
|
||||
DESTINATION bin
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
else()
|
||||
install(FILES
|
||||
"$<TARGET_FILE_DIR:falco>/falco.js"
|
||||
"$<TARGET_FILE_DIR:falco>/falco.wasm"
|
||||
DESTINATION ${FALCO_BIN_DIR}
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(TARGETS falco RUNTIME DESTINATION ${FALCO_BIN_DIR} COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
endif()
|
||||
|
||||
@@ -30,7 +30,6 @@ falco::app::run_result configure_syscall_buffer_num(falco::app::state& s);
|
||||
falco::app::run_result create_requested_paths(falco::app::state& s);
|
||||
falco::app::run_result create_signal_handlers(falco::app::state& s);
|
||||
falco::app::run_result pidfile(falco::app::state& s);
|
||||
falco::app::run_result init_clients(falco::app::state& s);
|
||||
falco::app::run_result init_falco_engine(falco::app::state& s);
|
||||
falco::app::run_result init_inspectors(falco::app::state& s);
|
||||
falco::app::run_result init_outputs(falco::app::state& s);
|
||||
@@ -42,6 +41,7 @@ falco::app::run_result load_rules_files(falco::app::state& s);
|
||||
falco::app::run_result print_generated_gvisor_config(falco::app::state& s);
|
||||
falco::app::run_result print_help(falco::app::state& s);
|
||||
falco::app::run_result print_ignored_events(falco::app::state& s);
|
||||
falco::app::run_result print_kernel_version(falco::app::state& s);
|
||||
falco::app::run_result print_page_size(falco::app::state& s);
|
||||
falco::app::run_result print_plugin_info(falco::app::state& s);
|
||||
falco::app::run_result print_support(falco::app::state& s);
|
||||
|
||||
@@ -69,7 +69,7 @@ static void select_event_set(falco::app::state& s, const libsinsp::events::set<p
|
||||
auto rules_names = libsinsp::events::sc_set_to_event_names(rules_sc_set);
|
||||
if (!rules_sc_set.empty())
|
||||
{
|
||||
falco_logger::log(LOG_DEBUG, "(" + std::to_string(rules_names.size())
|
||||
falco_logger::log(falco_logger::level::DEBUG, "(" + std::to_string(rules_names.size())
|
||||
+ ") syscalls in rules: " + concat_set_in_order(rules_names) + "\n");
|
||||
}
|
||||
|
||||
@@ -100,14 +100,14 @@ static void select_event_set(falco::app::state& s, const libsinsp::events::set<p
|
||||
|
||||
// we re-transform from sc_set to names to make
|
||||
// sure that bad user inputs are ignored
|
||||
falco_logger::log(LOG_DEBUG, "+(" + std::to_string(user_positive_sc_set_names.size())
|
||||
falco_logger::log(falco_logger::level::DEBUG, "+(" + std::to_string(user_positive_sc_set_names.size())
|
||||
+ ") syscalls added (base_syscalls override): "
|
||||
+ concat_set_in_order(user_positive_sc_set_names) + "\n");
|
||||
}
|
||||
auto invalid_positive_sc_set_names = unordered_set_difference(user_positive_names, user_positive_sc_set_names);
|
||||
if (!invalid_positive_sc_set_names.empty())
|
||||
{
|
||||
falco_logger::log(LOG_WARNING, "Invalid (positive) syscall names: warning (base_syscalls override): "
|
||||
falco_logger::log(falco_logger::level::WARNING, "Invalid (positive) syscall names: warning (base_syscalls override): "
|
||||
+ concat_set_in_order(invalid_positive_sc_set_names));
|
||||
}
|
||||
|
||||
@@ -136,14 +136,14 @@ static void select_event_set(falco::app::state& s, const libsinsp::events::set<p
|
||||
|
||||
// we re-transform from sc_set to names to make
|
||||
// sure that bad user inputs are ignored
|
||||
falco_logger::log(LOG_DEBUG, "-(" + std::to_string(user_negative_sc_set_names.size())
|
||||
falco_logger::log(falco_logger::level::DEBUG, "-(" + std::to_string(user_negative_sc_set_names.size())
|
||||
+ ") syscalls removed (base_syscalls override): "
|
||||
+ concat_set_in_order(user_negative_sc_set_names) + "\n");
|
||||
}
|
||||
auto invalid_negative_sc_set_names = unordered_set_difference(user_negative_names, user_negative_sc_set_names);
|
||||
if (!invalid_negative_sc_set_names.empty())
|
||||
{
|
||||
falco_logger::log(LOG_WARNING, "Invalid (negative) syscall names: warning (base_syscalls override): "
|
||||
falco_logger::log(falco_logger::level::WARNING, "Invalid (negative) syscall names: warning (base_syscalls override): "
|
||||
+ concat_set_in_order(invalid_negative_sc_set_names));
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ static void select_event_set(falco::app::state& s, const libsinsp::events::set<p
|
||||
if (!non_rules_sc_set.empty() && user_positive_sc_set.empty())
|
||||
{
|
||||
auto non_rules_sc_set_names = libsinsp::events::sc_set_to_event_names(non_rules_sc_set);
|
||||
falco_logger::log(LOG_DEBUG, "+(" + std::to_string(non_rules_sc_set_names.size())
|
||||
falco_logger::log(falco_logger::level::DEBUG, "+(" + std::to_string(non_rules_sc_set_names.size())
|
||||
+ ") syscalls (Falco's state engine set of syscalls): "
|
||||
+ concat_set_in_order(non_rules_sc_set_names) + "\n");
|
||||
}
|
||||
@@ -172,7 +172,7 @@ static void select_event_set(falco::app::state& s, const libsinsp::events::set<p
|
||||
if (!erased_sc_set.empty())
|
||||
{
|
||||
auto erased_sc_set_names = libsinsp::events::sc_set_to_event_names(erased_sc_set);
|
||||
falco_logger::log(LOG_DEBUG, "-(" + std::to_string(erased_sc_set_names.size())
|
||||
falco_logger::log(falco_logger::level::DEBUG, "-(" + std::to_string(erased_sc_set_names.size())
|
||||
+ ") ignored syscalls (-> activate via `-A` flag): "
|
||||
+ concat_set_in_order(erased_sc_set_names) + "\n");
|
||||
}
|
||||
@@ -192,7 +192,7 @@ static void select_event_set(falco::app::state& s, const libsinsp::events::set<p
|
||||
if (!repaired_sc_set.empty())
|
||||
{
|
||||
auto repaired_sc_set_names = libsinsp::events::sc_set_to_event_names(repaired_sc_set);
|
||||
falco_logger::log(LOG_INFO, "+(" + std::to_string(repaired_sc_set_names.size())
|
||||
falco_logger::log(falco_logger::level::INFO, "+(" + std::to_string(repaired_sc_set_names.size())
|
||||
+ ") repaired syscalls: " + concat_set_in_order(repaired_sc_set_names) + "\n");
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ static void select_event_set(falco::app::state& s, const libsinsp::events::set<p
|
||||
if (!s.selected_sc_set.empty())
|
||||
{
|
||||
auto selected_sc_set_names = libsinsp::events::sc_set_to_event_names(s.selected_sc_set);
|
||||
falco_logger::log(LOG_DEBUG, "(" + std::to_string(selected_sc_set_names.size())
|
||||
falco_logger::log(falco_logger::level::DEBUG, "(" + std::to_string(selected_sc_set_names.size())
|
||||
+ ") syscalls selected in total (final set): "
|
||||
+ concat_set_in_order(selected_sc_set_names) + "\n");
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ using namespace falco::app::actions;
|
||||
falco::app::run_result falco::app::actions::configure_syscall_buffer_num(falco::app::state& s)
|
||||
{
|
||||
#ifdef __linux__
|
||||
if(!s.options.modern_bpf)
|
||||
if(!s.is_modern_ebpf())
|
||||
{
|
||||
return run_result::ok();
|
||||
}
|
||||
@@ -34,10 +34,10 @@ falco::app::run_result falco::app::actions::configure_syscall_buffer_num(falco::
|
||||
return run_result::fatal("cannot get the number of online CPUs from the system\n");
|
||||
}
|
||||
|
||||
if(s.config->m_cpus_for_each_syscall_buffer > online_cpus)
|
||||
if(s.config->m_modern_ebpf.m_cpus_for_each_buffer > online_cpus)
|
||||
{
|
||||
falco_logger::log(LOG_WARNING, "you required a buffer every '" + std::to_string(s.config->m_cpus_for_each_syscall_buffer) + "' CPUs but there are only '" + std::to_string(online_cpus) + "' online CPUs. Falco changed the config to: one buffer every '" + std::to_string(online_cpus) + "' CPUs\n");
|
||||
s.config->m_cpus_for_each_syscall_buffer = online_cpus;
|
||||
falco_logger::log(falco_logger::level::WARNING, "you required a buffer every '" + std::to_string(s.config->m_modern_ebpf.m_cpus_for_each_buffer) + "' CPUs but there are only '" + std::to_string(online_cpus) + "' online CPUs. Falco changed the config to: one buffer every '" + std::to_string(online_cpus) + "' CPUs\n");
|
||||
s.config->m_modern_ebpf.m_cpus_for_each_buffer = online_cpus;
|
||||
}
|
||||
#endif
|
||||
return run_result::ok();
|
||||
|
||||
@@ -28,21 +28,15 @@ using namespace falco::app::actions;
|
||||
falco::app::run_result falco::app::actions::configure_syscall_buffer_size(falco::app::state& s)
|
||||
{
|
||||
#ifdef __linux__
|
||||
/* We don't need to compute the syscall buffer dimension if we are in capture mode or if the
|
||||
* the syscall source is not enabled.
|
||||
*/
|
||||
if(s.is_capture_mode()
|
||||
|| !s.is_source_enabled(falco_common::syscall_source)
|
||||
|| s.is_gvisor_enabled()
|
||||
|| s.options.nodriver)
|
||||
auto index = s.driver_buf_size_preset();
|
||||
if (index == -1)
|
||||
{
|
||||
// Chosen driver kind does not support this option.
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
uint16_t index = s.config->m_syscall_buf_size_preset;
|
||||
if(index < MIN_INDEX || index > MAX_INDEX)
|
||||
{
|
||||
return run_result::fatal("The 'syscall_buf_size_preset' value must be between '" + std::to_string(MIN_INDEX) + "' and '" + std::to_string(MAX_INDEX) + "'\n");
|
||||
return run_result::fatal("The 'buf_size_preset' value must be between '" + std::to_string(MIN_INDEX) + "' and '" + std::to_string(MAX_INDEX) + "'\n");
|
||||
}
|
||||
|
||||
/* Sizes from `1 MB` to `512 MB`. The index `0` is reserved, users cannot use it! */
|
||||
@@ -55,24 +49,24 @@ falco::app::run_result falco::app::actions::configure_syscall_buffer_size(falco:
|
||||
if(page_size <= 0)
|
||||
{
|
||||
s.syscall_buffer_bytes_size = DEFAULT_BYTE_SIZE;
|
||||
falco_logger::log(LOG_WARNING, "Unable to get the system page size through 'getpagesize()'. Try to use the default syscall buffer dimension: " + std::to_string(DEFAULT_BYTE_SIZE) + " bytes\n");
|
||||
falco_logger::log(falco_logger::level::WARNING, "Unable to get the system page size through 'getpagesize()'. Try to use the default syscall buffer dimension: " + std::to_string(DEFAULT_BYTE_SIZE) + " bytes\n");
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
/* Check if the chosen size is a multiple of the page size. */
|
||||
if(chosen_size % page_size != 0)
|
||||
{
|
||||
return run_result::fatal("The chosen syscall buffer size '" + std::to_string(chosen_size) + "' is not a multiple of your system page size '" + std::to_string(page_size) + "'. Please configure a greater 'syscall_buf_size_preset' value in the Falco configuration file\n");
|
||||
return run_result::fatal("The chosen syscall buffer size '" + std::to_string(chosen_size) + "' is not a multiple of your system page size '" + std::to_string(page_size) + "'. Please configure a greater 'buf_size_preset' value in the Falco configuration file\n");
|
||||
}
|
||||
|
||||
/* Check if the chosen size is greater than `2 * page_size`. */
|
||||
if((chosen_size / page_size) <= 2)
|
||||
{
|
||||
return run_result::fatal("The chosen syscall buffer size '" + std::to_string(chosen_size) + "' is not greater than '2 * " + std::to_string(page_size) + "' where '" + std::to_string(page_size) + "' is your system page size. Please configure a greater 'syscall_buf_size_preset' value in the Falco configuration file\n");
|
||||
return run_result::fatal("The chosen syscall buffer size '" + std::to_string(chosen_size) + "' is not greater than '2 * " + std::to_string(page_size) + "' where '" + std::to_string(page_size) + "' is your system page size. Please configure a greater 'buf_size_preset' value in the Falco configuration file\n");
|
||||
}
|
||||
|
||||
s.syscall_buffer_bytes_size = chosen_size;
|
||||
falco_logger::log(LOG_INFO, "The chosen syscall buffer dimension is: " + std::to_string(chosen_size) + " bytes (" + std::to_string(chosen_size / (uint64_t)(1024 * 1024)) + " MBs)\n");
|
||||
falco_logger::log(falco_logger::level::INFO, "The chosen syscall buffer dimension is: " + std::to_string(chosen_size) + " bytes (" + std::to_string(chosen_size / (uint64_t)(1024 * 1024)) + " MBs)\n");
|
||||
|
||||
#endif // __linux__
|
||||
return run_result::ok();
|
||||
|
||||
@@ -18,14 +18,7 @@ limitations under the License.
|
||||
#include "actions.h"
|
||||
#include "falco_utils.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef CPPPATH_SEP
|
||||
#ifdef _MSC_VER
|
||||
#define CPPPATH_SEP "\\"
|
||||
#else
|
||||
#define CPPPATH_SEP "/"
|
||||
#endif
|
||||
#endif
|
||||
#include <filesystem>
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
@@ -34,14 +27,14 @@ static int create_dir(const std::string &path);
|
||||
|
||||
falco::app::run_result falco::app::actions::create_requested_paths(falco::app::state& s)
|
||||
{
|
||||
if(s.is_gvisor_enabled())
|
||||
if(s.is_gvisor())
|
||||
{
|
||||
// This is bad: parsing gvisor config to get endpoint
|
||||
// to be able to auto-create the path to the file for the user.
|
||||
std::ifstream reader(s.options.gvisor_config);
|
||||
std::ifstream reader(s.config->m_gvisor.m_config);
|
||||
if (reader.fail())
|
||||
{
|
||||
return run_result::fatal(s.options.gvisor_config + ": cannot open file");
|
||||
return run_result::fatal(s.config->m_gvisor.m_config + ": cannot open file");
|
||||
}
|
||||
|
||||
nlohmann::json parsed_json;
|
||||
@@ -52,7 +45,7 @@ falco::app::run_result falco::app::actions::create_requested_paths(falco::app::s
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
return run_result::fatal(s.options.gvisor_config + ": cannot parse JSON: " + e.what());
|
||||
return run_result::fatal(s.config->m_gvisor.m_config + ": cannot parse JSON: " + e.what());
|
||||
}
|
||||
|
||||
try
|
||||
@@ -61,7 +54,7 @@ falco::app::run_result falco::app::actions::create_requested_paths(falco::app::s
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
return run_result::fatal(s.options.gvisor_config + ": failed to fetch config.endpoint: " + e.what());
|
||||
return run_result::fatal(s.config->m_gvisor.m_config + ": failed to fetch config.endpoint: " + e.what());
|
||||
}
|
||||
|
||||
int ret = create_dir(gvisor_socket);
|
||||
@@ -91,25 +84,19 @@ falco::app::run_result falco::app::actions::create_requested_paths(falco::app::s
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
// This function operates like `mkdir -p` excluding the last part of
|
||||
// the path which we assume to be the filename.
|
||||
static int create_dir(const std::string &path)
|
||||
{
|
||||
// Properly reset errno
|
||||
errno = 0;
|
||||
|
||||
std::istringstream f(path);
|
||||
std::string path_until_token;
|
||||
std::string s;
|
||||
// Create all the subfolder stopping at last token (f.eof());
|
||||
// Examples:
|
||||
// "/tmp/foo/bar" -> "", "tmp", "foo" -> mkdir("/") + mkdir("/tmp/") + midir("/tmp/foo/")
|
||||
// "tmp/foo/bar" -> "tmp", "foo" -> mkdir("tmp/") + midir("tmp/foo/")
|
||||
while (getline(f, s, *CPPPATH_SEP) && !f.eof()) {
|
||||
path_until_token += s + CPPPATH_SEP;
|
||||
int ret = mkdir(path_until_token.c_str(), 0600);
|
||||
if (ret != 0 && errno != EEXIST)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
std::filesystem::path dirPath(path);
|
||||
|
||||
try {
|
||||
std::filesystem::create_directories(dirPath.parent_path());
|
||||
} catch (const std::exception& ex) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ falco::app::run_result falco::app::actions::create_signal_handlers(falco::app::s
|
||||
#ifdef __linux__
|
||||
if (s.options.dry_run)
|
||||
{
|
||||
falco_logger::log(LOG_DEBUG, "Skipping signal handlers creation in dry-run\n");
|
||||
falco_logger::log(falco_logger::level::DEBUG, "Skipping signal handlers creation in dry-run\n");
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ falco::app::run_result falco::app::actions::create_signal_handlers(falco::app::s
|
||||
|| !g_restart_signal.is_lock_free()
|
||||
|| !g_reopen_outputs_signal.is_lock_free())
|
||||
{
|
||||
falco_logger::log(LOG_WARNING, "Bundled atomics implementation is not lock-free, signal handlers may be unstable\n");
|
||||
falco_logger::log(falco_logger::level::WARNING, "Bundled atomics implementation is not lock-free, signal handlers may be unstable\n");
|
||||
}
|
||||
|
||||
if(! create_handler(SIGINT, ::terminate_signal_handler, ret) ||
|
||||
@@ -162,7 +162,7 @@ falco::app::run_result falco::app::actions::unregister_signal_handlers(falco::ap
|
||||
#ifdef __linux__
|
||||
if (s.options.dry_run)
|
||||
{
|
||||
falco_logger::log(LOG_DEBUG, "Skipping unregistering signal handlers in dry-run\n");
|
||||
falco_logger::log(falco_logger::level::DEBUG, "Skipping unregistering signal handlers in dry-run\n");
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ limitations under the License.
|
||||
#include "../state.h"
|
||||
#include "../run_result.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace falco {
|
||||
namespace app {
|
||||
namespace actions {
|
||||
@@ -29,6 +31,8 @@ void print_enabled_event_sources(falco::app::state& s);
|
||||
void activate_interesting_kernel_tracepoints(falco::app::state& s, std::unique_ptr<sinsp>& inspector);
|
||||
void check_for_ignored_events(falco::app::state& s);
|
||||
void format_plugin_info(std::shared_ptr<sinsp_plugin> p, std::ostream& os);
|
||||
void format_described_rules_as_text(const nlohmann::json& v, std::ostream& os);
|
||||
|
||||
falco::app::run_result open_offline_inspector(falco::app::state& s);
|
||||
falco::app::run_result open_live_inspector(
|
||||
falco::app::state& s,
|
||||
|
||||
@@ -16,6 +16,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
#include "helpers.h"
|
||||
#include "falco_utils.h"
|
||||
#include <plugin_manager.h>
|
||||
|
||||
#include <unordered_set>
|
||||
@@ -47,7 +48,7 @@ void falco::app::actions::print_enabled_event_sources(falco::app::state& s)
|
||||
str += str.empty() ? "" : ", ";
|
||||
str += src;
|
||||
}
|
||||
falco_logger::log(LOG_INFO, "Loaded event sources: " + str);
|
||||
falco_logger::log(falco_logger::level::INFO, "Loaded event sources: " + str);
|
||||
|
||||
/* Print all enabled sources. */
|
||||
str.clear();
|
||||
@@ -56,7 +57,7 @@ void falco::app::actions::print_enabled_event_sources(falco::app::state& s)
|
||||
str += str.empty() ? "" : ", ";
|
||||
str += src;
|
||||
}
|
||||
falco_logger::log(LOG_INFO, "Enabled event sources: " + str);
|
||||
falco_logger::log(falco_logger::level::INFO, "Enabled event sources: " + str);
|
||||
|
||||
// print some warnings to the user
|
||||
for (const auto& src : s.enabled_sources)
|
||||
@@ -75,18 +76,18 @@ void falco::app::actions::print_enabled_event_sources(falco::app::state& s)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src != falco_common::syscall_source || s.options.nodriver)
|
||||
if (src != falco_common::syscall_source || s.is_nodriver())
|
||||
{
|
||||
falco_logger::log(LOG_WARNING, "Enabled event source '"
|
||||
falco_logger::log(falco_logger::level::WARNING, "Enabled event source '"
|
||||
+ src + "' can be opened with multiple loaded plugins, will use only '"
|
||||
+ first_plugin->name() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!first_plugin && s.options.nodriver)
|
||||
if (!first_plugin && s.is_nodriver())
|
||||
{
|
||||
falco_logger::log(LOG_WARNING, "Enabled event source '"
|
||||
falco_logger::log(falco_logger::level::WARNING, "Enabled event source '"
|
||||
+ src + "' will be opened with no driver, no event will be produced");
|
||||
}
|
||||
}
|
||||
@@ -127,3 +128,21 @@ void falco::app::actions::format_plugin_info(std::shared_ptr<sinsp_plugin> p, st
|
||||
}
|
||||
}
|
||||
|
||||
static void format_two_columns(std::ostream& os, const std::string& l, const std::string& r)
|
||||
{
|
||||
static constexpr const int s_max_line_len = 4096;
|
||||
char buf[s_max_line_len];
|
||||
snprintf(buf, sizeof(buf) - 1, "%-50s %s", l.c_str(), r.c_str());
|
||||
os << buf << std::endl;
|
||||
}
|
||||
|
||||
void falco::app::actions::format_described_rules_as_text(const nlohmann::json& v, std::ostream& os)
|
||||
{
|
||||
format_two_columns(os, "Rule", "Description");
|
||||
format_two_columns(os, "----", "-----------");
|
||||
for(const auto &r : v["rules"])
|
||||
{
|
||||
auto str = falco::utils::wrap_text(r["info"]["description"], 51, 110) + "\n";
|
||||
format_two_columns(os, r["info"]["name"], str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@ limitations under the License.
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <plugin_manager.h>
|
||||
#include <configuration.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
/* DEPRECATED: we will remove it in Falco 0.34. */
|
||||
#define FALCO_BPF_ENV_VARIABLE "FALCO_BPF_PROBE"
|
||||
#ifdef _WIN32
|
||||
#define PATH_MAX 260
|
||||
#endif
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
@@ -33,13 +35,13 @@ falco::app::run_result falco::app::actions::open_offline_inspector(falco::app::s
|
||||
{
|
||||
try
|
||||
{
|
||||
s.offline_inspector->open_savefile(s.options.trace_filename);
|
||||
falco_logger::log(LOG_INFO, "Reading system call events from file: " + s.options.trace_filename + "\n");
|
||||
s.offline_inspector->open_savefile(s.config->m_replay.m_capture_file);
|
||||
falco_logger::log(falco_logger::level::INFO, "Replaying events from the capture file: " + s.config->m_replay.m_capture_file + "\n");
|
||||
return run_result::ok();
|
||||
}
|
||||
catch (sinsp_exception &e)
|
||||
{
|
||||
return run_result::fatal("Could not open trace filename " + s.options.trace_filename + " for reading: " + e.what());
|
||||
return run_result::fatal("Could not open trace filename " + s.config->m_replay.m_capture_file + " for reading: " + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +52,11 @@ falco::app::run_result falco::app::actions::open_live_inspector(
|
||||
{
|
||||
try
|
||||
{
|
||||
if((s.config->m_metrics_flags & PPM_SCAP_STATS_STATE_COUNTERS))
|
||||
{
|
||||
inspector->set_sinsp_stats_v2_enabled();
|
||||
}
|
||||
|
||||
if (source != falco_common::syscall_source) /* Plugin engine */
|
||||
{
|
||||
for (const auto& p: inspector->get_plugin_manager()->plugins())
|
||||
@@ -60,14 +67,14 @@ falco::app::run_result falco::app::actions::open_live_inspector(
|
||||
if (p->caps() & CAP_SOURCING && p->id() != 0 && p->event_source() == source)
|
||||
{
|
||||
auto cfg = s.plugin_configs.at(p->name());
|
||||
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with plugin '" + cfg->m_name + "'");
|
||||
falco_logger::log(falco_logger::level::INFO, "Opening '" + source + "' source with plugin '" + cfg->m_name + "'");
|
||||
inspector->open_plugin(cfg->m_name, cfg->m_open_params);
|
||||
return run_result::ok();
|
||||
}
|
||||
}
|
||||
return run_result::fatal("Can't find plugin for event source: " + source);
|
||||
}
|
||||
else if (s.options.nodriver) /* nodriver engine. */
|
||||
else if (s.is_nodriver()) /* nodriver engine. */
|
||||
{
|
||||
// when opening a capture with no driver, Falco will first check
|
||||
// if a plugin is capable of generating raw events from the libscap
|
||||
@@ -78,37 +85,28 @@ falco::app::run_result falco::app::actions::open_live_inspector(
|
||||
if (p->caps() & CAP_SOURCING && p->id() == 0)
|
||||
{
|
||||
auto cfg = s.plugin_configs.at(p->name());
|
||||
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with plugin '" + cfg->m_name + "'");
|
||||
falco_logger::log(falco_logger::level::INFO, "Opening '" + source + "' source with plugin '" + cfg->m_name + "'");
|
||||
inspector->open_plugin(cfg->m_name, cfg->m_open_params);
|
||||
return run_result::ok();
|
||||
}
|
||||
}
|
||||
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with no driver\n");
|
||||
falco_logger::log(falco_logger::level::INFO, "Opening '" + source + "' source with no driver\n");
|
||||
inspector->open_nodriver();
|
||||
}
|
||||
else if (s.options.userspace) /* udig engine. */
|
||||
else if(s.is_gvisor()) /* gvisor engine. */
|
||||
{
|
||||
// open_udig() is the underlying method used in the capture code to parse userspace events from the kernel.
|
||||
//
|
||||
// Falco uses a ptrace(2) based userspace implementation.
|
||||
// Regardless of the implementation, the underlying method remains the same.
|
||||
falco_logger::log(LOG_WARNING, "The udig engine is deprecated and will be removed in Falco 0.37. Opening '" + source + "' source with udig\n");
|
||||
inspector->open_udig();
|
||||
falco_logger::log(falco_logger::level::INFO, "Opening '" + source + "' source with gVisor. Configuration path: " + s.config->m_gvisor.m_config);
|
||||
inspector->open_gvisor(s.config->m_gvisor.m_config, s.config->m_gvisor.m_root);
|
||||
}
|
||||
else if(s.is_gvisor_enabled()) /* gvisor engine. */
|
||||
else if(s.is_modern_ebpf()) /* modern BPF engine. */
|
||||
{
|
||||
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with gVisor. Configuration path: " + s.options.gvisor_config);
|
||||
inspector->open_gvisor(s.options.gvisor_config, s.options.gvisor_root);
|
||||
falco_logger::log(falco_logger::level::INFO, "Opening '" + source + "' source with modern BPF probe.");
|
||||
falco_logger::log(falco_logger::level::INFO, "One ring buffer every '" + std::to_string(s.config->m_modern_ebpf.m_cpus_for_each_buffer) + "' CPUs.");
|
||||
inspector->open_modern_bpf(s.syscall_buffer_bytes_size, s.config->m_modern_ebpf.m_cpus_for_each_buffer, true, s.selected_sc_set);
|
||||
}
|
||||
else if(s.options.modern_bpf) /* modern BPF engine. */
|
||||
else if(s.is_ebpf()) /* BPF engine. */
|
||||
{
|
||||
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with modern BPF probe.");
|
||||
falco_logger::log(LOG_INFO, "One ring buffer every '" + std::to_string(s.config->m_cpus_for_each_syscall_buffer) + "' CPUs.");
|
||||
inspector->open_modern_bpf(s.syscall_buffer_bytes_size, s.config->m_cpus_for_each_syscall_buffer, true, s.selected_sc_set);
|
||||
}
|
||||
else if(getenv(FALCO_BPF_ENV_VARIABLE) != NULL) /* BPF engine. */
|
||||
{
|
||||
const char *bpf_probe_path = std::getenv(FALCO_BPF_ENV_VARIABLE);
|
||||
const char *bpf_probe_path = s.config->m_ebpf.m_probe_path.c_str();
|
||||
char full_path[PATH_MAX];
|
||||
/* If the path is empty try to load the probe from the default path. */
|
||||
if(strncmp(bpf_probe_path, "", 1) == 0)
|
||||
@@ -121,23 +119,23 @@ falco::app::run_result falco::app::actions::open_live_inspector(
|
||||
snprintf(full_path, PATH_MAX, "%s/%s", home, FALCO_PROBE_BPF_FILEPATH);
|
||||
bpf_probe_path = full_path;
|
||||
}
|
||||
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with BPF probe. BPF probe path: " + std::string(bpf_probe_path));
|
||||
falco_logger::log(falco_logger::level::INFO, "Opening '" + source + "' source with BPF probe. BPF probe path: " + std::string(bpf_probe_path));
|
||||
inspector->open_bpf(bpf_probe_path, s.syscall_buffer_bytes_size, s.selected_sc_set);
|
||||
}
|
||||
else /* Kernel module (default). */
|
||||
{
|
||||
try
|
||||
{
|
||||
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with Kernel module");
|
||||
falco_logger::log(falco_logger::level::INFO, "Opening '" + source + "' source with Kernel module");
|
||||
inspector->open_kmod(s.syscall_buffer_bytes_size, s.selected_sc_set);
|
||||
}
|
||||
catch(sinsp_exception &e)
|
||||
{
|
||||
// Try to insert the Falco kernel module
|
||||
falco_logger::log(LOG_INFO, "Trying to inject the Kernel module and opening the capture again...");
|
||||
falco_logger::log(falco_logger::level::INFO, "Trying to inject the Kernel module and opening the capture again...");
|
||||
if(system("modprobe " DRIVER_NAME " > /dev/null 2> /dev/null"))
|
||||
{
|
||||
falco_logger::log(LOG_ERR, "Unable to load the driver\n");
|
||||
falco_logger::log(falco_logger::level::ERR, "Unable to load the driver\n");
|
||||
}
|
||||
inspector->open_kmod(s.syscall_buffer_bytes_size, s.selected_sc_set);
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 "actions.h"
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::init_clients(falco::app::state& s)
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
// k8s is useful only if the syscall source is enabled
|
||||
if (s.is_capture_mode() || !s.is_source_enabled(falco_common::syscall_source))
|
||||
{
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
auto inspector = s.source_infos.at(falco_common::syscall_source)->inspector;
|
||||
|
||||
falco_logger::log(LOG_DEBUG, "Setting metadata download max size to " + std::to_string(s.config->m_metadata_download_max_mb) + " MB\n");
|
||||
falco_logger::log(LOG_DEBUG, "Setting metadata download chunk wait time to " + std::to_string(s.config->m_metadata_download_chunk_wait_us) + " μs\n");
|
||||
falco_logger::log(LOG_DEBUG, "Setting metadata download watch frequency to " + std::to_string(s.config->m_metadata_download_watch_freq_sec) + " seconds\n");
|
||||
inspector->set_metadata_download_params(s.config->m_metadata_download_max_mb * 1024 * 1024, s.config->m_metadata_download_chunk_wait_us, s.config->m_metadata_download_watch_freq_sec);
|
||||
|
||||
if (s.options.dry_run)
|
||||
{
|
||||
falco_logger::log(LOG_DEBUG, "Skipping clients initialization in dry-run\n");
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
//
|
||||
// Run k8s, if required
|
||||
//
|
||||
char *k8s_api_env = NULL;
|
||||
if(!s.options.k8s_api.empty() ||
|
||||
(k8s_api_env = getenv("FALCO_K8S_API")))
|
||||
{
|
||||
// Create string pointers for some config vars
|
||||
// and pass to inspector. The inspector then
|
||||
// owns the pointers.
|
||||
std::string *k8s_api_ptr = new std::string((!s.options.k8s_api.empty() ? s.options.k8s_api : k8s_api_env));
|
||||
std::string *k8s_api_cert_ptr = new std::string(s.options.k8s_api_cert);
|
||||
std::string *k8s_node_name_ptr = new std::string(s.options.k8s_node_name);
|
||||
|
||||
if(k8s_api_cert_ptr->empty())
|
||||
{
|
||||
if(char* k8s_cert_env = getenv("FALCO_K8S_API_CERT"))
|
||||
{
|
||||
*k8s_api_cert_ptr = k8s_cert_env;
|
||||
}
|
||||
}
|
||||
inspector->init_k8s_client(k8s_api_ptr, k8s_api_cert_ptr, k8s_node_name_ptr, s.options.verbose);
|
||||
}
|
||||
#endif
|
||||
|
||||
return run_result::ok();
|
||||
}
|
||||
@@ -49,9 +49,9 @@ static void init_syscall_inspector(falco::app::state& s, std::shared_ptr<sinsp>
|
||||
inspector->set_snaplen(s.options.snaplen);
|
||||
}
|
||||
|
||||
if (s.config->m_syscall_drop_failed_exit)
|
||||
if (s.is_driver_drop_failed_exit_enabled())
|
||||
{
|
||||
falco_logger::log(LOG_INFO, "Failed syscall exit events are dropped in the kernel driver\n");
|
||||
falco_logger::log(falco_logger::level::INFO, "Failed syscall exit events are dropped in the kernel driver\n");
|
||||
inspector->set_dropfailed(true);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user