mirror of
https://github.com/falcosecurity/falco.git
synced 2026-04-02 01:52:06 +00:00
Compare commits
41 Commits
new/plugin
...
embeddable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c3fe8a4e7 | ||
|
|
5787dfa098 | ||
|
|
2434942bdc | ||
|
|
2f7b72d670 | ||
|
|
50e8da1049 | ||
|
|
5c398bd396 | ||
|
|
efbe887d6e | ||
|
|
7dcbeb1f44 | ||
|
|
93667f2d3e | ||
|
|
b5b1763d09 | ||
|
|
d6690313a0 | ||
|
|
98ce88f7ef | ||
|
|
9ff8099501 | ||
|
|
7db4778f55 | ||
|
|
7f761ade4b | ||
|
|
84257912e0 | ||
|
|
9bc942c654 | ||
|
|
8216b435cb | ||
|
|
78f710c706 | ||
|
|
1dd97c1b6f | ||
|
|
3ef5716fa2 | ||
|
|
64102078c7 | ||
|
|
9703853da8 | ||
|
|
96403fa275 | ||
|
|
acd5422b55 | ||
|
|
099c79ddde | ||
|
|
0f24448d18 | ||
|
|
1b63ad1aed | ||
|
|
b268d4d6c3 | ||
|
|
684a5d85ff | ||
|
|
58cea0c5e7 | ||
|
|
38ebc61808 | ||
|
|
535db19991 | ||
|
|
abe46a19a0 | ||
|
|
96fc8d1a27 | ||
|
|
ad82f66be3 | ||
|
|
c60fac9e34 | ||
|
|
35dc315390 | ||
|
|
62c995f309 | ||
|
|
3432551295 | ||
|
|
09e1604fe0 |
@@ -13,7 +13,7 @@ jobs:
|
||||
command: apk update
|
||||
- run:
|
||||
name: Install build dependencies
|
||||
command: apk add g++ gcc cmake cmake make ncurses-dev git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils
|
||||
command: apk add g++ gcc cmake cmake make git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
command: apt update -y
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: DEBIAN_FRONTEND=noninteractive apt install libjq-dev libncurses-dev libyaml-cpp-dev libelf-dev cmake build-essential git -y
|
||||
command: DEBIAN_FRONTEND=noninteractive apt install libjq-dev libyaml-cpp-dev libelf-dev cmake build-essential git -y
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
command: apt update -y
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libncurses-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-generic clang llvm git -y
|
||||
command: 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-generic clang llvm git -y
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
command: apt update -y
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: DEBIAN_FRONTEND=noninteractive apt install libssl-dev libyaml-dev libncurses-dev libc-ares-dev libprotobuf-dev protobuf-compiler libjq-dev libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-generic clang llvm git -y
|
||||
command: 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-generic clang llvm git -y
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
command: apt update -y
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: DEBIAN_FRONTEND=noninteractive apt install cmake build-essential clang llvm git linux-headers-generic libncurses-dev pkg-config autoconf libtool libelf-dev -y
|
||||
command: DEBIAN_FRONTEND=noninteractive apt install cmake build-essential clang llvm git linux-headers-generic pkg-config autoconf libtool libelf-dev -y
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
@@ -188,7 +188,7 @@ jobs:
|
||||
command: dnf update -y
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: dnf install gcc gcc-c++ git make cmake autoconf automake pkg-config patch ncurses-devel libtool elfutils-libelf-devel diffutils kernel-devel kernel-headers kernel-core clang llvm which -y
|
||||
command: dnf install gcc gcc-c++ git make cmake autoconf automake pkg-config patch libtool elfutils-libelf-devel diffutils kernel-devel kernel-headers kernel-core clang llvm which -y
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,6 +1,6 @@
|
||||
<!-- Thanks for sending a pull request! Here are some tips for you:
|
||||
|
||||
1. If this is your first time, please read our contributor guidelines in the [CONTRIBUTING.md](CONTRIBUTING.md) file and learn how to compile Falco from source [here](https://falco.org/docs/source).
|
||||
1. If this is your first time, please read our contributor guidelines in the [CONTRIBUTING.md](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md) file and learn how to compile Falco from source [here](https://falco.org/docs/source).
|
||||
2. Please label this pull request according to what type of issue you are addressing.
|
||||
3. . Please add a release note!
|
||||
4. If the PR is unfinished while opening it specify a wip in the title before the actual title, for example, "wip: my awesome feature"
|
||||
|
||||
49
CHANGELOG.md
49
CHANGELOG.md
@@ -1,5 +1,54 @@
|
||||
# Change Log
|
||||
|
||||
## v0.29.1
|
||||
|
||||
Released on 2021-06-29
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* update: bump the Falco engine version to version 9 [[#1675](https://github.com/falcosecurity/falco/pull/1675)] - [@leodido](https://github.com/leodido)
|
||||
|
||||
### Rule Changes
|
||||
|
||||
* rule(list user_known_userfaultfd_processes): list to exclude processes known to use userfaultfd syscall [[#1675](https://github.com/falcosecurity/falco/pull/1675)] - [@leodido](https://github.com/leodido)
|
||||
* rule(macro consider_userfaultfd_activities): macro to gate the "Unprivileged Delegation of Page Faults Handling to a Userspace Process" rule [[#1675](https://github.com/falcosecurity/falco/pull/1675)] - [@leodido](https://github.com/leodido)
|
||||
* rule(Unprivileged Delegation of Page Faults Handling to a Userspace Process): new rule to detect successful unprivileged userfaultfd syscalls [[#1675](https://github.com/falcosecurity/falco/pull/1675)] - [@leodido](https://github.com/leodido)
|
||||
* rule(Linux Kernel Module Injection Detected): adding container info to the output of the rule [[#1675](https://github.com/falcosecurity/falco/pull/1675)] - [@leodido](https://github.com/leodido)
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* docs(release.md): update steps [[#1684](https://github.com/falcosecurity/falco/pull/1684)] - [@maxgio92](https://github.com/maxgio92)
|
||||
|
||||
|
||||
## v0.29.0
|
||||
|
||||
Released on 2021-06-21
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* update: driver version is 17f5df52a7d9ed6bb12d3b1768460def8439936d now [[#1669](https://github.com/falcosecurity/falco/pull/1669)] - [@leogr](https://github.com/leogr)
|
||||
|
||||
### Rule Changes
|
||||
|
||||
* rule(list miner_domains): add rx.unmineable.com for anti-miner detection [[#1676](https://github.com/falcosecurity/falco/pull/1676)] - [@fntlnz](https://github.com/fntlnz)
|
||||
* rule(Change thread namespace and Set Setuid or Setgid bit): disable by default [[#1632](https://github.com/falcosecurity/falco/pull/1632)] - [@Kaizhe](https://github.com/Kaizhe)
|
||||
* rule(list known_sa_list): add namespace-controller, statefulset-controller, disruption-controller, job-controller, horizontal-pod-autoscaler and persistent-volume-binder as allowed service accounts in the kube-system namespace [[#1659](https://github.com/falcosecurity/falco/pull/1659)] - [@sboschman](https://github.com/sboschman)
|
||||
* rule(Non sudo setuid): check user id as well in case user name info is not available [[#1665](https://github.com/falcosecurity/falco/pull/1665)] - [@Kaizhe](https://github.com/Kaizhe)
|
||||
* rule(Debugfs Launched in Privileged Container): fix typo in description [[#1657](https://github.com/falcosecurity/falco/pull/1657)] - [@Kaizhe](https://github.com/Kaizhe)
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* Fix link to CONTRIBUTING.md in the Pull Request Template [[#1679](https://github.com/falcosecurity/falco/pull/1679)] - [@tspearconquest](https://github.com/tspearconquest)
|
||||
* fetch libs and drivers from the new repo [[#1552](https://github.com/falcosecurity/falco/pull/1552)] - [@leogr](https://github.com/leogr)
|
||||
* build(test): upgrade urllib3 to 1.26.5 [[#1666](https://github.com/falcosecurity/falco/pull/1666)] - [@leogr](https://github.com/leogr)
|
||||
* revert: add notes for 0.28.2 release [[#1663](https://github.com/falcosecurity/falco/pull/1663)] - [@maxgio92](https://github.com/maxgio92)
|
||||
* changelog: add notes for 0.28.2 release [[#1661](https://github.com/falcosecurity/falco/pull/1661)] - [@maxgio92](https://github.com/maxgio92)
|
||||
* docs(release.md): add blog announcement to post-release tasks [[#1652](https://github.com/falcosecurity/falco/pull/1652)] - [@maxgio92](https://github.com/maxgio92)
|
||||
* add Yahoo!Japan as an adopter [[#1651](https://github.com/falcosecurity/falco/pull/1651)] - [@ukitazume](https://github.com/ukitazume)
|
||||
* Add Replicated to adopters [[#1649](https://github.com/falcosecurity/falco/pull/1649)] - [@diamonwiggins](https://github.com/diamonwiggins)
|
||||
* docs(proposals): fix libs contribution name [[#1641](https://github.com/falcosecurity/falco/pull/1641)] - [@leodido](https://github.com/leodido)
|
||||
|
||||
|
||||
## v0.28.1
|
||||
|
||||
Released on 2021-05-07
|
||||
|
||||
@@ -212,7 +212,6 @@ include(static-analysis)
|
||||
# Shared build variables
|
||||
set(FALCO_SINSP_LIBRARY sinsp)
|
||||
set(FALCO_SHARE_DIR share/falco)
|
||||
set(FALCO_PLUGINS_DIR ${FALCO_SHARE_DIR}/plugins)
|
||||
set(FALCO_ABSOLUTE_SHARE_DIR "${CMAKE_INSTALL_PREFIX}/${FALCO_SHARE_DIR}")
|
||||
set(FALCO_BIN_DIR bin)
|
||||
|
||||
@@ -221,8 +220,5 @@ add_subdirectory(userspace/engine)
|
||||
add_subdirectory(userspace/falco)
|
||||
add_subdirectory(tests)
|
||||
|
||||
# Reenable once test-infra is publishing plugins artifacts
|
||||
#include(plugins)
|
||||
|
||||
# Packages configuration
|
||||
include(CPackConfig)
|
||||
|
||||
@@ -77,6 +77,10 @@ Now assume `x.y.z` is the new version.
|
||||
| `docker pull docker.io/falcosecurity/falco-driver-loader:x.y.z` |
|
||||
| `docker pull docker.io/falcosecurity/falco-no-driver:x.y.z` |
|
||||
|
||||
<changelog>
|
||||
|
||||
<!-- Substitute <changelog> with the one generated by [rn2md](https://github.com/leodido/rn2md) -->
|
||||
|
||||
### Statistics
|
||||
|
||||
| Merged PRs | Number |
|
||||
@@ -111,3 +115,4 @@ Announce the new release to the world!
|
||||
- Publish a blog on [Falco website](https://github.com/falcosecurity/falco-website) ([example](https://github.com/falcosecurity/falco-website/blob/master/content/en/blog/falco-0-28-1.md))
|
||||
- Send an announcement to cncf-falco-dev@lists.cncf.io (plain text, please)
|
||||
- Let folks in the slack #falco channel know about a new release came out
|
||||
- IFF the on going release introduces a **new minor version**, [archive a snapshot of the Falco website](https://github.com/falcosecurity/falco-website/blob/master/release.md#documentation-versioning)
|
||||
|
||||
@@ -21,7 +21,7 @@ file(MAKE_DIRECTORY ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR})
|
||||
# -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "new/plugin-system-api-additions")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=d880d7437e7f943fb89dc31878eea2b56abbdf56db33e026b095af86a3900c22")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=ba0ea2e22121b8543cb1ebe616090097c4dc3f093db8f0bb5cf2ce5a7e0425a0")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations under the License.
|
||||
#
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
set(PLUGINS_PREFIX ${CMAKE_BINARY_DIR}/plugins-prefix)
|
||||
set(PLUGINS_VERSION "0.1.0-rc1")
|
||||
string(TOLOWER ${CMAKE_SYSTEM_NAME} PLUGIN_SYSTEM_NAME)
|
||||
set(PLUGINS_FULL_VERSION "falcosecurity-plugins-${PLUGINS_VERSION}-${PLUGIN_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
message(STATUS "Using bundled plugins in ${PLUGINS_PREFIX}")
|
||||
|
||||
ExternalProject_Add(
|
||||
plugins
|
||||
PREFIX ${PLUGINS_PREFIX}
|
||||
URL "https://download.falco.org/plugins/${PLUGINS_FULL_VERSION}.tar.gz"
|
||||
URL_HASH "SHA256=3750b3e5120aba9c6d388f6bfdc3c150564edd21779876c3bcf7ec9d3afb66ad"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PLUGINS_PREFIX}/src/plugins/cloudtrail/libcloudtrail.so" "${PLUGINS_PREFIX}/src/plugins/json/libjson.so" DESTINATION "${FALCO_PLUGINS_DIR}")
|
||||
@@ -20,7 +20,7 @@ ENV FALCO_VERSION=${FALCO_VERSION}
|
||||
|
||||
# build toolchain
|
||||
RUN yum -y install centos-release-scl && \
|
||||
INSTALL_PKGS="devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-toolchain devtoolset-7-libstdc++-devel devtoolset-7-elfutils-libelf-devel llvm-toolset-7 glibc-static autoconf automake libtool createrepo expect git which libcurl-devel zlib-devel ncurses-devel rpm-build libyaml-devel" && \
|
||||
INSTALL_PKGS="devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-toolchain devtoolset-7-libstdc++-devel devtoolset-7-elfutils-libelf-devel llvm-toolset-7 glibc-static autoconf automake libtool createrepo expect git which libcurl-devel zlib-devel rpm-build libyaml-devel" && \
|
||||
yum -y install --setopt=tsflags=nodocs $INSTALL_PKGS && \
|
||||
rpm -V $INSTALL_PKGS
|
||||
|
||||
|
||||
27
falco.yaml
27
falco.yaml
@@ -33,33 +33,6 @@ rules_file:
|
||||
- /etc/falco/k8s_audit_rules.yaml
|
||||
- /etc/falco/rules.d
|
||||
|
||||
|
||||
#
|
||||
# Plugins that are available for use. These plugins are not loaded by
|
||||
# default, as they require explicit configuration to point to
|
||||
# cloudtrail log files.
|
||||
#
|
||||
|
||||
# To learn more about the supported formats for
|
||||
# init_config/open_params for the cloudtrail plugin, see the README at
|
||||
# https://github.com/falcosecurity/plugins/blob/master/plugins/cloudtrail/README.md.
|
||||
plugins:
|
||||
- name: cloudtrail
|
||||
library_path: libcloudtrail.so
|
||||
init_config: ""
|
||||
open_params: ""
|
||||
- name: json
|
||||
library_path: libjson.so
|
||||
init_config: ""
|
||||
open_params: ""
|
||||
|
||||
# Setting this list to empty ensures that the above plugins are *not*
|
||||
# loaded and enabled by default. If you want to use the above plugins,
|
||||
# set a meaningful init_config/open_params for the cloudtrail plugin
|
||||
# and then change this to:
|
||||
# load_plugins: [cloudtrail, json]
|
||||
load_plugins: []
|
||||
|
||||
# If true, the times displayed in log messages and output messages
|
||||
# will be in ISO 8601. By default, times are displayed in the local
|
||||
# time zone, as governed by /etc/localtime.
|
||||
|
||||
@@ -1,440 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# All rules files related to plugins should require engine version 10
|
||||
- required_engine_version: 10
|
||||
|
||||
# These rules can be read by cloudtrail plugin version 0.1.0, or
|
||||
# anything semver-compatible.
|
||||
- required_plugin_versions:
|
||||
- name: cloudtrail
|
||||
version: 0.1.0
|
||||
|
||||
# Note that this rule is disabled by default. It's useful only to
|
||||
# verify that the cloudtrail plugin is sending events properly. The
|
||||
# very broad condition evt.num > 0 only works because the rule source
|
||||
# is limited to aws_cloudtrail. This ensures that the only events that
|
||||
# are matched against the rule are from the cloudtrail plugin (or
|
||||
# a different plugin with the same source).
|
||||
- rule: All Cloudtrail Events
|
||||
desc: Match all cloudtrail events.
|
||||
condition:
|
||||
evt.num > 0
|
||||
output: Some Cloudtrail Event (evtnum=%evt.num info=%evt.plugininfo ts=%evt.time.iso8601 id=%ct.id error=%ct.error)
|
||||
priority: DEBUG
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
source: aws_cloudtrail
|
||||
enabled: false
|
||||
|
||||
- rule: Console Login Through Assume Role
|
||||
desc: Detect a console login through Assume Role.
|
||||
condition:
|
||||
ct.name="ConsoleLogin" and not ct.error exists
|
||||
and ct.user.identitytype="AssumedRole"
|
||||
and json.value[/responseElements/ConsoleLogin]="Success"
|
||||
output:
|
||||
Detected a console login through Assume Role
|
||||
(principal=%ct.user.principalid,
|
||||
assumedRole=%ct.user.arn,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_console
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Console Login Without MFA
|
||||
desc: Detect a console login without MFA.
|
||||
condition:
|
||||
ct.name="ConsoleLogin" and not ct.error exists
|
||||
and ct.user.identitytype!="AssumedRole"
|
||||
and json.value[/responseElements/ConsoleLogin]="Success"
|
||||
and json.value[/additionalEventData/MFAUsed]="No"
|
||||
output:
|
||||
Detected a console login without MFA
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_console
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Console Root Login Without MFA
|
||||
desc: Detect root console login without MFA.
|
||||
condition:
|
||||
ct.name="ConsoleLogin" and not ct.error exists
|
||||
and json.value[/additionalEventData/MFAUsed]="No"
|
||||
and ct.user.identitytype!="AssumedRole"
|
||||
and json.value[/responseElements/ConsoleLogin]="Success"
|
||||
and ct.user.identitytype="Root"
|
||||
output:
|
||||
Detected a root console login without MFA.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_console
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Deactivate MFA for Root User
|
||||
desc: Detect deactivating MFA configuration for root.
|
||||
condition:
|
||||
ct.name="DeactivateMFADevice" and not ct.error exists
|
||||
and ct.user.identitytype="Root"
|
||||
and ct.request.username="AWS ROOT USER"
|
||||
output:
|
||||
Multi Factor Authentication configuration has been disabled for root
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
MFA serial number=%ct.request.serialnumber)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Create AWS user
|
||||
desc: Detect creation of a new AWS user.
|
||||
condition:
|
||||
ct.name="CreateUser" and not ct.error exists
|
||||
output:
|
||||
A new AWS user has been created
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
new user created=%ct.request.username)
|
||||
priority: INFO
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Create Group
|
||||
desc: Detect creation of a new user group.
|
||||
condition:
|
||||
ct.name="CreateGroup" and not ct.error exists
|
||||
output:
|
||||
A new user group has been created.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
group name=%ct.request.groupname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Delete Group
|
||||
desc: Detect deletion of a user group.
|
||||
condition:
|
||||
ct.name="DeleteGroup" and not ct.error exists
|
||||
output:
|
||||
A user group has been deleted.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
group name=%ct.request.groupname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: ECS Service Created
|
||||
desc: Detect a new service is created in ECS.
|
||||
condition:
|
||||
ct.src="ecs.amazonaws.com" and
|
||||
ct.name="CreateService" and
|
||||
not ct.error exists
|
||||
output:
|
||||
A new service has been created in ECS
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
cluster=%ct.request.cluster,
|
||||
service name=%ct.request.servicename,
|
||||
task definition=%ct.request.taskdefinition)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ecs
|
||||
- aws_fargate
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: ECS Task Run or Started
|
||||
desc: Detect a new task is started in ECS.
|
||||
condition:
|
||||
ct.src="ecs.amazonaws.com" and
|
||||
(ct.name="RunTask" or ct.name="StartTask") and
|
||||
not ct.error exists
|
||||
output:
|
||||
A new task has been started in ECS
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
cluster=%ct.request.cluster,
|
||||
task definition=%ct.request.taskdefinition)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ecs
|
||||
- aws_fargate
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Create Lambda Function
|
||||
desc: Detect creation of a Lambda function.
|
||||
condition:
|
||||
ct.name="CreateFunction20150331" and not ct.error exists
|
||||
output:
|
||||
Lambda function has been created.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
lambda function=%ct.request.functionname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_lambda
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Update Lambda Function Code
|
||||
desc: Detect updates to a Lambda function code.
|
||||
condition:
|
||||
ct.name="UpdateFunctionCode20150331v2" and not ct.error exists
|
||||
output:
|
||||
The code of a Lambda function has been updated.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
lambda function=%ct.request.functionname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_lambda
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Update Lambda Function Configuration
|
||||
desc: Detect updates to a Lambda function configuration.
|
||||
condition:
|
||||
ct.name="UpdateFunctionConfiguration20150331v2" and not ct.error exists
|
||||
output:
|
||||
The configuration of a Lambda function has been updated.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
lambda function=%ct.request.functionname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_lambda
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Run Instances
|
||||
desc: Detect launching of a specified number of instances.
|
||||
condition:
|
||||
ct.name="RunInstances" and not ct.error exists
|
||||
output:
|
||||
A number of instances have been launched.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
availability zone=%ct.request.availabilityzone,
|
||||
subnet id=%ct.response.subnetid,
|
||||
reservation id=%ct.response.reservationid)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ec2
|
||||
source: aws_cloudtrail
|
||||
|
||||
# Only instances launched on regions in this list are approved.
|
||||
- list: approved_regions
|
||||
items:
|
||||
- us-east-0
|
||||
|
||||
- rule: Run Instances in Non-approved Region
|
||||
desc: Detect launching of a specified number of instances in a non-approved region.
|
||||
condition:
|
||||
ct.name="RunInstances" and not ct.error exists and
|
||||
not ct.region in (approved_regions)
|
||||
output:
|
||||
A number of instances have been launched in a non-approved region.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
availability zone=%ct.request.availabilityzone,
|
||||
subnet id=%ct.response.subnetid,
|
||||
reservation id=%ct.response.reservationid,
|
||||
image id=%json.value[/responseElements/instancesSet/items/0/instanceId])
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ec2
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Delete Bucket Encryption
|
||||
desc: Detect deleting configuration to use encryption for bucket storage.
|
||||
condition:
|
||||
ct.name="DeleteBucketEncryption" and not ct.error exists
|
||||
output:
|
||||
A encryption configuration for a bucket has been deleted
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket=%s3.bucket)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Delete Bucket Public Access Block
|
||||
desc: Detect deleting blocking public access to bucket.
|
||||
condition:
|
||||
ct.name="PutBucketPublicAccessBlock" and not ct.error exists and
|
||||
json.value[/requestParameters/publicAccessBlock]="" and
|
||||
(json.value[/requestParameters/PublicAccessBlockConfiguration/RestrictPublicBuckets]=false or
|
||||
json.value[/requestParameters/PublicAccessBlockConfiguration/BlockPublicPolicy]=false or
|
||||
json.value[/requestParameters/PublicAccessBlockConfiguration/BlockPublicAcls]=false or
|
||||
json.value[/requestParameters/PublicAccessBlockConfiguration/IgnorePublicAcls]=false)
|
||||
output:
|
||||
A pulic access block for a bucket has been deleted
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket=%s3.bucket)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: List Buckets
|
||||
desc: Detect listing of all S3 buckets.
|
||||
condition:
|
||||
ct.name="ListBuckets" and not ct.error exists
|
||||
output:
|
||||
A list of all S3 buckets has been requested.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
host=%ct.request.host)
|
||||
priority: WARNING
|
||||
enabled: false
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Put Bucket ACL
|
||||
desc: Detect setting the permissions on an existing bucket using access control lists.
|
||||
condition:
|
||||
ct.name="PutBucketAcl" and not ct.error exists
|
||||
output:
|
||||
The permissions on an existing bucket have been set using access control lists.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket name=%s3.bucket)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Put Bucket Policy
|
||||
desc: Detect applying an Amazon S3 bucket policy to an Amazon S3 bucket.
|
||||
condition:
|
||||
ct.name="PutBucketPolicy" and not ct.error exists
|
||||
output:
|
||||
An Amazon S3 bucket policy has been applied to an Amazon S3 bucket.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket name=%s3.bucket,
|
||||
policy=%ct.request.policy)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: CloudTrail Trail Created
|
||||
desc: Detect creation of a new trail.
|
||||
condition:
|
||||
ct.name="CreateTrail" and not ct.error exists
|
||||
output:
|
||||
A new trail has been created.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
trail name=%ct.request.name)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_cloudtrail
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: CloudTrail Logging Disabled
|
||||
desc: The CloudTrail logging has been disabled, this could be potentially malicious.
|
||||
condition:
|
||||
ct.name="StopLogging" and not ct.error exists
|
||||
output:
|
||||
The CloudTrail logging has been disabled.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
resource name=%ct.request.name)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_cloudtrail
|
||||
source: aws_cloudtrail
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# The latest Falco Engine version is 8 if you want to
|
||||
# use exceptions. However the default rules file does not
|
||||
# use them so we stick with 7 for compatibility.
|
||||
- required_engine_version: 7
|
||||
# The latest Falco Engine version is 9.
|
||||
# Starting with version 8, the Falco engine supports exceptions.
|
||||
# However the Falco rules file does not use them by default.
|
||||
- required_engine_version: 9
|
||||
|
||||
# Currently disabled as read/write are ignored syscalls. The nearly
|
||||
# similar open_write/open_read check for files being opened for
|
||||
@@ -1565,6 +1565,7 @@
|
||||
and not calico_node
|
||||
and not weaveworks_scope
|
||||
and not user_known_change_thread_namespace_activities
|
||||
enabled: false
|
||||
output: >
|
||||
Namespace change (setns) by unexpected program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline
|
||||
parent=%proc.pname %container.info container_id=%container.id image=%container.image.repository:%container.image.tag)
|
||||
@@ -1752,13 +1753,13 @@
|
||||
- macro: allowed_aws_ecr_registry_root_for_eks
|
||||
condition: >
|
||||
(container.image.repository startswith "602401143452.dkr.ecr" or
|
||||
container.image.repository startswith "877085696533.dkr.ecr" or
|
||||
container.image.repository startswith "800184023465.dkr.ecr" or
|
||||
container.image.repository startswith "602401143452.dkr.ecr" or
|
||||
container.image.repository startswith "877085696533.dkr.ecr" or
|
||||
container.image.repository startswith "800184023465.dkr.ecr" or
|
||||
container.image.repository startswith "602401143452.dkr.ecr" or
|
||||
container.image.repository startswith "918309763551.dkr.ecr" or
|
||||
container.image.repository startswith "961992271922.dkr.ecr" or
|
||||
container.image.repository startswith "961992271922.dkr.ecr" or
|
||||
container.image.repository startswith "590381155156.dkr.ecr" or
|
||||
container.image.repository startswith "558608220178.dkr.ecr" or
|
||||
container.image.repository startswith "558608220178.dkr.ecr" or
|
||||
container.image.repository startswith "151742754352.dkr.ecr" or
|
||||
container.image.repository startswith "013241004608.dkr.ecr")
|
||||
|
||||
@@ -2234,7 +2235,7 @@
|
||||
condition: >
|
||||
evt.type=setuid and evt.dir=>
|
||||
and (known_user_in_container or not container)
|
||||
and not user.name=root
|
||||
and not (user.name=root or user.uid=0)
|
||||
and not somebody_becoming_themself
|
||||
and not proc.name in (known_setuid_binaries, userexec_binaries, mail_binaries, docker_binaries,
|
||||
nomachine_binaries)
|
||||
@@ -2641,6 +2642,7 @@
|
||||
and not proc.name in (user_known_chmod_applications)
|
||||
and not exe_running_docker_save
|
||||
and not user_known_set_setuid_or_setgid_bit_conditions
|
||||
enabled: false
|
||||
output: >
|
||||
Setuid or setgid bit is set via chmod (fd=%evt.arg.fd filename=%evt.arg.filename mode=%evt.arg.mode user=%user.name user_loginuid=%user.loginuid process=%proc.name
|
||||
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
@@ -2745,7 +2747,7 @@
|
||||
"xmr-eu1.nanopool.org","xmr-eu2.nanopool.org",
|
||||
"xmr-jp1.nanopool.org","xmr-us-east1.nanopool.org",
|
||||
"xmr-us-west1.nanopool.org","xmr.crypto-pool.fr",
|
||||
"xmr.pool.minergate.com"
|
||||
"xmr.pool.minergate.com", "rx.unmineable.com"
|
||||
]
|
||||
|
||||
- list: https_miner_domains
|
||||
@@ -3001,7 +3003,7 @@
|
||||
- rule: Linux Kernel Module Injection Detected
|
||||
desc: Detect kernel module was injected (from container).
|
||||
condition: spawned_process and container and proc.name=insmod and not proc.args in (white_listed_modules)
|
||||
output: Linux Kernel Module injection using insmod detected (user=%user.name user_loginuid=%user.loginuid parent_process=%proc.pname module=%proc.args)
|
||||
output: Linux Kernel Module injection using insmod detected (user=%user.name user_loginuid=%user.loginuid parent_process=%proc.pname module=%proc.args %container.info image=%container.image.repository:%container.image.tag)
|
||||
priority: WARNING
|
||||
tags: [process]
|
||||
|
||||
@@ -3025,13 +3027,13 @@
|
||||
# A privilege escalation to root through heap-based buffer overflow
|
||||
- rule: Sudo Potential Privilege Escalation
|
||||
desc: Privilege escalation vulnerability affecting sudo (<= 1.9.5p2). Executing sudo using sudoedit -s or sudoedit -i command with command-line argument that ends with a single backslash character from an unprivileged user it's possible to elevate the user privileges to root.
|
||||
condition: spawned_process and user.uid!= 0 and proc.name=sudoedit and (proc.args contains -s or proc.args contains -i) and (proc.args contains "\ " or proc.args endswith \)
|
||||
condition: spawned_process and user.uid != 0 and proc.name=sudoedit and (proc.args contains -s or proc.args contains -i) and (proc.args contains "\ " or proc.args endswith \)
|
||||
output: "Detect Sudo Privilege Escalation Exploit (CVE-2021-3156) (user=%user.name parent=%proc.pname cmdline=%proc.cmdline %container.info)"
|
||||
priority: CRITICAL
|
||||
tags: [filesystem, mitre_privilege_escalation]
|
||||
|
||||
- rule: Debugfs Launched in Privileged Container
|
||||
desc: Detect file system debugger debugfs launched inside a privilegd container which might lead to container escape.
|
||||
desc: Detect file system debugger debugfs launched inside a privileged container which might lead to container escape.
|
||||
condition: >
|
||||
spawned_process and container
|
||||
and container.privileged=true
|
||||
@@ -3054,6 +3056,24 @@
|
||||
priority: WARNING
|
||||
tags: [container, cis, mitre_lateral_movement]
|
||||
|
||||
- macro: consider_userfaultfd_activities
|
||||
condition: (always_true)
|
||||
|
||||
- list: user_known_userfaultfd_processes
|
||||
items: []
|
||||
|
||||
- rule: Unprivileged Delegation of Page Faults Handling to a Userspace Process
|
||||
desc: Detect a successful unprivileged userfaultfd syscall which might act as an attack primitive to exploit other bugs
|
||||
condition: >
|
||||
consider_userfaultfd_activities and
|
||||
evt.type = userfaultfd and
|
||||
user.uid != 0 and
|
||||
(evt.rawres >= 0 or evt.res != -1) and
|
||||
not proc.name in (user_known_userfaultfd_processes)
|
||||
output: An userfaultfd syscall was successfully executed by an unprivileged user (user=%user.name user_loginuid=%user.loginuid process=%proc.name command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
||||
priority: CRITICAL
|
||||
tags: [syscall, mitre_defense_evasion]
|
||||
|
||||
# Application rules have moved to application_rules.yaml. Please look
|
||||
# there if you want to enable them by adding to
|
||||
# falco_rules.local.yaml.
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
- list: known_sa_list
|
||||
items: ["pod-garbage-collector","resourcequota-controller","cronjob-controller","generic-garbage-collector",
|
||||
"daemon-set-controller","endpointslice-controller","deployment-controller", "replicaset-controller",
|
||||
"endpoint-controller"]
|
||||
"endpoint-controller", "namespace-controller", "statefulset-controller", "disruption-controller"]
|
||||
|
||||
- macro: trusted_sa
|
||||
condition: (ka.target.name in (known_sa_list, user_known_sa_list))
|
||||
|
||||
@@ -763,7 +763,7 @@ trace_files: !mux
|
||||
- "Non sudo setuid": 1
|
||||
- "Create files below dev": 1
|
||||
- "Modify binary dirs": 2
|
||||
- "Change thread namespace": 1
|
||||
- "Change thread namespace": 0
|
||||
|
||||
disabled_tags_a:
|
||||
detect: True
|
||||
|
||||
@@ -23,10 +23,10 @@ has_json_output: !mux
|
||||
traces: !mux
|
||||
change-thread-namespace:
|
||||
trace_file: traces-positive/change-thread-namespace.scap
|
||||
detect: True
|
||||
detect: False
|
||||
detect_level: NOTICE
|
||||
detect_counts:
|
||||
- "Change thread namespace": 1
|
||||
- "Change thread namespace": 0
|
||||
|
||||
container-privileged:
|
||||
trace_file: traces-positive/container-privileged.scap
|
||||
@@ -73,7 +73,7 @@ traces: !mux
|
||||
- "Non sudo setuid": 1
|
||||
- "Create files below dev": 1
|
||||
- "Modify binary dirs": 2
|
||||
- "Change thread namespace": 1
|
||||
- "Change thread namespace": 0
|
||||
|
||||
mkdir-binary-dirs:
|
||||
trace_file: traces-positive/mkdir-binary-dirs.scap
|
||||
|
||||
@@ -9,5 +9,5 @@ PyYAML==5.4
|
||||
requests==2.23.0
|
||||
six==1.14.0
|
||||
stevedore==1.32.0
|
||||
urllib3==1.25.9
|
||||
urllib3==1.26.5
|
||||
watchdog==0.10.2
|
||||
|
||||
@@ -46,7 +46,6 @@ if(FALCO_BUILD_TESTS)
|
||||
PUBLIC "${CATCH2_INCLUDE}"
|
||||
"${FAKEIT_INCLUDE}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/falco")
|
||||
else()
|
||||
@@ -55,7 +54,6 @@ if(FALCO_BUILD_TESTS)
|
||||
PUBLIC "${CATCH2_INCLUDE}"
|
||||
"${FAKEIT_INCLUDE}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${CIVETWEB_INCLUDE_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/falco")
|
||||
|
||||
@@ -70,3 +70,5 @@ else()
|
||||
FILES_MATCHING
|
||||
PATTERN *.lua)
|
||||
endif()
|
||||
|
||||
add_subdirectory(embeddable)
|
||||
|
||||
43
userspace/engine/embeddable/CMakeLists.txt
Normal file
43
userspace/engine/embeddable/CMakeLists.txt
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright (C) 2021 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(FALCO_ENGINE_EMBEDDABLE_SOURCE_FILES
|
||||
falco_engine_embeddable.cpp)
|
||||
|
||||
set(
|
||||
FALCO_LIBRARIES
|
||||
falco_engine
|
||||
sinsp
|
||||
"${LIBYAML_LIB}"
|
||||
"${YAMLCPP_LIB}"
|
||||
)
|
||||
|
||||
add_library(falco_engine_embeddable SHARED ${FALCO_ENGINE_EMBEDDABLE_SOURCE_FILES})
|
||||
add_dependencies(falco_engine_embeddable falco_engine)
|
||||
|
||||
target_include_directories(
|
||||
falco_engine_embeddable
|
||||
PUBLIC
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${LUAJIT_INCLUDE}"
|
||||
"${NJSON_INCLUDE}"
|
||||
"${TBB_INCLUDE_DIR}"
|
||||
"${STRING_VIEW_LITE_INCLUDE}"
|
||||
"${LIBSCAP_INCLUDE_DIRS}"
|
||||
"${LIBSINSP_INCLUDE_DIRS}"
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
||||
|
||||
target_link_libraries(falco_engine_embeddable ${FALCO_LIBRARIES})
|
||||
|
||||
#add_custom_target(example ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/example)
|
||||
#add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/example COMMAND go build ${CMAKE_CURRENT_SOURCE_DIR}/example.go -o ${CMAKE_CURRENT_BINARY_DIR}/example)
|
||||
|
||||
102
userspace/engine/embeddable/example/example.go
Normal file
102
userspace/engine/embeddable/example/example.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
//#cgo CFLAGS: -I../
|
||||
//#cgo LDFLAGS: -L/home/mstemm/work/falco-build/userspace/engine/embeddable -lfalco_engine_embeddable -Wl,-rpath=/home/mstemm/work/falco-build/userspace/engine/embeddable
|
||||
/*
|
||||
#include "stdio.h"
|
||||
#include "falco_engine_embeddable.h"
|
||||
|
||||
int open_engine(void **engine, void *rules_content)
|
||||
{
|
||||
int32_t rc;
|
||||
*engine = falco_engine_embed_init(&rc);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
char *errstr;
|
||||
rc = falco_engine_embed_load_rules_content(*engine, (const char *) rules_content, &errstr);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
fprintf(stderr, "%s", errstr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = falco_engine_embed_open(*engine, &errstr);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
fprintf(stderr, "%s", errstr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int next_result(void *engine, char **output)
|
||||
{
|
||||
|
||||
int32_t rc;
|
||||
falco_engine_embed_result *res;
|
||||
char *errstr;
|
||||
|
||||
rc = falco_engine_embed_next_result(engine, &res, &errstr);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
fprintf(stderr, "NEXT ERROR %s", errstr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*output = res->output_str;
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func doMain(rules_filename string) int {
|
||||
|
||||
rules_content, err := ioutil.ReadFile(rules_filename)
|
||||
if err != nil {
|
||||
fmt.Printf("Could not open rules file %s: %v", rules_filename, err)
|
||||
return 1
|
||||
}
|
||||
|
||||
var handle unsafe.Pointer
|
||||
rc := C.open_engine(&handle, C.CBytes(rules_content))
|
||||
|
||||
if rc != 0 {
|
||||
fmt.Printf("Could not open falco engine")
|
||||
return 1
|
||||
}
|
||||
|
||||
for true {
|
||||
var output *C.char
|
||||
rc := C.next_result(handle, &output)
|
||||
if rc != 0 {
|
||||
fmt.Printf("Could not get next result")
|
||||
return 1
|
||||
}
|
||||
fmt.Printf("GOT RESULT %s\n", C.GoString(output))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
os.Exit(doMain(os.Args[1]))
|
||||
}
|
||||
|
||||
|
||||
6
userspace/engine/embeddable/example/go.mod
Normal file
6
userspace/engine/embeddable/example/go.mod
Normal file
@@ -0,0 +1,6 @@
|
||||
module github.com/falcosecurity/falco/embedded/example
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
)
|
||||
356
userspace/engine/embeddable/falco_engine_embeddable.cpp
Normal file
356
userspace/engine/embeddable/falco_engine_embeddable.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
Copyright (C) 2021 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 <memory>
|
||||
#include <atomic>
|
||||
|
||||
#include <sinsp.h>
|
||||
#include <event.h>
|
||||
|
||||
#include <falco_engine.h>
|
||||
#include "falco_engine_embeddable.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class falco_engine_embed_int {
|
||||
public:
|
||||
falco_engine_embed_int();
|
||||
virtual ~falco_engine_embed_int();
|
||||
|
||||
bool load_rules_content(const char *rules_content, string &err);
|
||||
bool is_open();
|
||||
bool open(string &err);
|
||||
bool close(string &err);
|
||||
falco_engine_embed_rc next_result(falco_engine_embed_result **result, string &err);
|
||||
|
||||
private:
|
||||
|
||||
falco_engine_embed_result *rule_result_to_embed_result(sinsp_evt *ev,
|
||||
unique_ptr<falco_engine::rule_result> &res);
|
||||
|
||||
static void add_output_pair(const string &field, const string &val,
|
||||
char **&fields, char **&vals,
|
||||
uint32_t &len);
|
||||
|
||||
unique_ptr<sinsp_evt_formatter_cache> m_formatters;
|
||||
bool m_open;
|
||||
unique_ptr<sinsp> m_inspector;
|
||||
unique_ptr<falco_engine> m_falco_engine;
|
||||
atomic<bool> m_shutdown;
|
||||
};
|
||||
|
||||
falco_engine_embed_int::falco_engine_embed_int()
|
||||
: m_open(false),
|
||||
m_shutdown(false)
|
||||
{
|
||||
m_inspector.reset(new sinsp());
|
||||
m_falco_engine.reset(new falco_engine());
|
||||
m_falco_engine->set_inspector(m_inspector.get());
|
||||
|
||||
m_formatters.reset(new sinsp_evt_formatter_cache(m_inspector.get()));
|
||||
}
|
||||
|
||||
falco_engine_embed_int::~falco_engine_embed_int()
|
||||
{
|
||||
}
|
||||
|
||||
bool falco_engine_embed_int::load_rules_content(const char *rules_content, string &err)
|
||||
{
|
||||
bool verbose = false;
|
||||
bool all_events = true;
|
||||
|
||||
try {
|
||||
m_falco_engine->load_rules(string(rules_content), verbose, all_events);
|
||||
}
|
||||
catch(falco_exception &e)
|
||||
{
|
||||
err = e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool falco_engine_embed_int::is_open()
|
||||
{
|
||||
return m_open;
|
||||
}
|
||||
|
||||
bool falco_engine_embed_int::open(string &err)
|
||||
{
|
||||
try {
|
||||
m_inspector->open();
|
||||
}
|
||||
catch(exception &e)
|
||||
{
|
||||
err = e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_open = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool falco_engine_embed_int::close(string &err)
|
||||
{
|
||||
m_shutdown = true;
|
||||
m_open = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
falco_engine_embed_rc falco_engine_embed_int::next_result(falco_engine_embed_result **result, string &err)
|
||||
{
|
||||
*result = NULL;
|
||||
|
||||
while(!m_shutdown)
|
||||
{
|
||||
sinsp_evt* ev;
|
||||
|
||||
int32_t rc = m_inspector->next(&ev);
|
||||
|
||||
if (rc == SCAP_TIMEOUT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (rc == SCAP_EOF)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (rc != SCAP_SUCCESS)
|
||||
{
|
||||
err = m_inspector->getlasterr();
|
||||
return FE_EMB_RC_ERROR;
|
||||
}
|
||||
|
||||
if(!ev->simple_consumer_consider())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unique_ptr<falco_engine::rule_result> res = m_falco_engine->process_sinsp_event(ev);
|
||||
if(!res)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
*result = rule_result_to_embed_result(ev, res);
|
||||
|
||||
return FE_EMB_RC_OK;
|
||||
}
|
||||
|
||||
// Can only get here if shut down/eof.
|
||||
return FE_EMB_RC_EOF;
|
||||
}
|
||||
|
||||
falco_engine_embed_result * falco_engine_embed_int::rule_result_to_embed_result(sinsp_evt *ev,
|
||||
unique_ptr<falco_engine::rule_result> &res)
|
||||
{
|
||||
falco_engine_embed_result *result;
|
||||
|
||||
result = (falco_engine_embed_result *) malloc(sizeof(falco_engine_embed_result));
|
||||
|
||||
result->rule = strdup(res->rule.c_str());
|
||||
result->event_source = strdup(res->source.c_str());
|
||||
result->priority_num = res->priority_num;
|
||||
|
||||
// Copy output format string without resolving fields.
|
||||
result->output_format_str = strdup(res->format.c_str());
|
||||
|
||||
// Resolve output format string into resolved output
|
||||
string output;
|
||||
m_formatters->tostring(ev, res->format, &output);
|
||||
result->output_str = strdup(output.c_str());
|
||||
|
||||
result->output_fields = NULL;
|
||||
result->output_values = NULL;
|
||||
result->num_output_values = 0;
|
||||
|
||||
map<string, string> rule_output_fields;
|
||||
m_formatters->resolve_tokens(ev, res->format, rule_output_fields);
|
||||
for(auto &pair : rule_output_fields)
|
||||
{
|
||||
add_output_pair(pair.first, pair.second,
|
||||
result->output_fields, result->output_values,
|
||||
result->num_output_values);
|
||||
}
|
||||
|
||||
// Preceding * makes the formatting permissive (not ending at first empty value)
|
||||
std::string exformat = "*";
|
||||
for (const auto& exfield : res->exception_fields)
|
||||
{
|
||||
exformat += " %" + exfield;
|
||||
}
|
||||
|
||||
map<string, string> exception_output_fields;
|
||||
m_formatters->resolve_tokens(ev, exformat, exception_output_fields);
|
||||
for(auto &pair : exception_output_fields)
|
||||
{
|
||||
add_output_pair(pair.first, pair.second,
|
||||
result->output_fields, result->output_values,
|
||||
result->num_output_values);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void falco_engine_embed_int::add_output_pair(const string &field, const string &val,
|
||||
char **&fields, char **&vals,
|
||||
uint32_t &len)
|
||||
{
|
||||
len++;
|
||||
fields = (char **) realloc(fields, len*sizeof(char *));
|
||||
vals = (char **) realloc(vals, len*sizeof(char *));
|
||||
fields[len-1] = strdup(field.c_str());
|
||||
vals[len-1] = strdup(val.c_str());
|
||||
}
|
||||
|
||||
static const char *FALCO_ENGINE_EMBED_VERSION = "1.0.0";
|
||||
|
||||
char *falco_engine_embed_get_version()
|
||||
{
|
||||
return strdup(FALCO_ENGINE_EMBED_VERSION);
|
||||
}
|
||||
|
||||
void falco_engine_embed_free_result(falco_engine_embed_result *result)
|
||||
{
|
||||
free(result->rule);
|
||||
free(result->event_source);
|
||||
free(result->output_format_str);
|
||||
free(result->output_str);
|
||||
|
||||
for(int32_t i; i < result->num_output_values; i++)
|
||||
{
|
||||
free(result->output_fields[i]);
|
||||
free(result->output_values[i]);
|
||||
}
|
||||
free(result->output_fields);
|
||||
free(result->output_values);
|
||||
free(result);
|
||||
}
|
||||
|
||||
falco_engine_embed_t* falco_engine_embed_init(int32_t *rc)
|
||||
{
|
||||
falco_engine_embed_int *eengine = new falco_engine_embed_int();
|
||||
|
||||
*rc = FE_EMB_RC_OK;
|
||||
|
||||
return eengine;
|
||||
}
|
||||
|
||||
int32_t falco_engine_embed_destroy(falco_engine_embed_t *engine, char *errstr)
|
||||
{
|
||||
falco_engine_embed_int *eengine = (falco_engine_embed_int *) engine;
|
||||
|
||||
if(eengine->is_open())
|
||||
{
|
||||
errstr = strdup("Engine is open--must call close() first");
|
||||
return FE_EMB_RC_ERROR;
|
||||
}
|
||||
|
||||
delete(eengine);
|
||||
|
||||
return FE_EMB_RC_OK;
|
||||
}
|
||||
|
||||
int32_t falco_engine_embed_load_plugin(falco_engine_embed_t *engine,
|
||||
const char *path,
|
||||
const char* init_config,
|
||||
const char* open_params,
|
||||
char **errstr)
|
||||
{
|
||||
falco_engine_embed_int *eengine = (falco_engine_embed_int *) engine;
|
||||
|
||||
// XXX/mstemm fill in
|
||||
return FE_EMB_RC_OK;
|
||||
}
|
||||
|
||||
int32_t falco_engine_embed_load_rules_content(falco_engine_embed_t *engine,
|
||||
const char *rules_content,
|
||||
char **errstr)
|
||||
{
|
||||
falco_engine_embed_int *eengine = (falco_engine_embed_int *) engine;
|
||||
std::string err;
|
||||
|
||||
if (!eengine->load_rules_content(rules_content, err))
|
||||
{
|
||||
*errstr = strdup(err.c_str());
|
||||
return FE_EMB_RC_ERROR;
|
||||
}
|
||||
|
||||
return FE_EMB_RC_OK;
|
||||
}
|
||||
|
||||
int32_t falco_engine_embed_enable_source(falco_engine_embed_t *engine,
|
||||
int32_t source,
|
||||
bool enabled,
|
||||
char **errstr)
|
||||
{
|
||||
falco_engine_embed_int *eengine = (falco_engine_embed_int *) engine;
|
||||
|
||||
// XXX/mstemm fill in
|
||||
return FE_EMB_RC_OK;
|
||||
}
|
||||
|
||||
int32_t falco_engine_embed_open(falco_engine_embed_t *engine,
|
||||
char **errstr)
|
||||
{
|
||||
falco_engine_embed_int *eengine = (falco_engine_embed_int *) engine;
|
||||
std::string err;
|
||||
|
||||
if (!eengine->open(err))
|
||||
{
|
||||
*errstr = strdup(err.c_str());
|
||||
return FE_EMB_RC_ERROR;
|
||||
}
|
||||
|
||||
return FE_EMB_RC_OK;
|
||||
}
|
||||
|
||||
int32_t falco_engine_embed_close(falco_engine_embed_t *engine,
|
||||
char **errstr)
|
||||
{
|
||||
falco_engine_embed_int *eengine = (falco_engine_embed_int *) engine;
|
||||
std::string err;
|
||||
|
||||
if (!eengine->close(err))
|
||||
{
|
||||
*errstr = strdup(err.c_str());
|
||||
return FE_EMB_RC_ERROR;
|
||||
}
|
||||
|
||||
return FE_EMB_RC_OK;
|
||||
}
|
||||
|
||||
int32_t falco_engine_embed_next_result(falco_engine_embed_t *engine,
|
||||
falco_engine_embed_result **result,
|
||||
char **errstr)
|
||||
{
|
||||
falco_engine_embed_int *eengine = (falco_engine_embed_int *) engine;
|
||||
std::string err;
|
||||
falco_engine_embed_rc rc;
|
||||
|
||||
rc = eengine->next_result(result, err);
|
||||
|
||||
if(rc == FE_EMB_RC_ERROR)
|
||||
{
|
||||
*errstr = strdup(err.c_str());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
268
userspace/engine/embeddable/falco_engine_embeddable.h
Normal file
268
userspace/engine/embeddable/falco_engine_embeddable.h
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
This header file provides a C-only interface to the falco engine,
|
||||
suitable for embedding in other programs as a shared library. This
|
||||
interface handles:
|
||||
- Loading Rules Content
|
||||
- Enabling/Disabling syscall/k8s_audit event sources.
|
||||
- Loading and configuring source/extractor plugins
|
||||
- Starting/Stopping the event processing loop.
|
||||
|
||||
After setup, the main interface involves receiving "results" when
|
||||
syscall/k8s_audit/plugin events match rules.
|
||||
|
||||
This interface does not provide as many features as the c++
|
||||
falco_engine interface, such as interfaces to list rules, segregate
|
||||
rules by "ruleset", enabling/disabling specific rules etc.
|
||||
|
||||
Output handling (e.g. routing alerts to files, stdout, webhook,
|
||||
slack, etc) is not covered by this interface. After receiving a
|
||||
result, a program could use a program like falcosidekick for a rich
|
||||
set of output handling methods.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* A handle to an embeddable falco engine */
|
||||
typedef void falco_engine_embed_t;
|
||||
|
||||
/* Defined return values from API functions. */
|
||||
enum falco_engine_embed_rc
|
||||
{
|
||||
/* No Error */
|
||||
FE_EMB_RC_OK = 0,
|
||||
FE_EMB_RC_ERROR = 1,
|
||||
FE_EMB_RC_EOF = 2,
|
||||
};
|
||||
|
||||
/* Defined event sources. */
|
||||
enum falco_engine_embed_evt_source
|
||||
{
|
||||
FE_EMB_SRC_NONE = 0,
|
||||
FE_EMB_SRC_SYSCALL = 1,
|
||||
FE_EMB_K8S_AUDIT = 2,
|
||||
FE_EMB_PLUGINS = 3, // This includes any event from any plugin
|
||||
};
|
||||
|
||||
/* Represents a result (e.g. an event matching a falco rule)
|
||||
|
||||
When returned by a call to next_result(), the struct, as well as
|
||||
every allocated char * within the struct, is allocated via a call
|
||||
to malloc() and must be freed via a call to free().
|
||||
*/
|
||||
typedef struct falco_engine_embed_result
|
||||
{
|
||||
// The rule that matched the event
|
||||
char *rule;
|
||||
|
||||
// The event source of the event that matched the rule
|
||||
char *event_source;
|
||||
|
||||
// An int containing a falco_common::priority_type value of
|
||||
// the priority of the matching rule.
|
||||
int32_t priority_num;
|
||||
|
||||
// A copy of the rule's output string, *without* any
|
||||
// fields (e.g. %proc.name, ...) resolved to values.
|
||||
char *output_format_str;
|
||||
|
||||
// An output string, starting with the rule's output string
|
||||
// with all fields resolved to values.
|
||||
char *output_str;
|
||||
|
||||
// An allocated array of allocated field names from the output
|
||||
// string. Additional fields + values may be included in
|
||||
// addition to those in the output string, to aid in
|
||||
// debugging. Item i in this array maps to item i in
|
||||
// output_values.
|
||||
char **output_fields;
|
||||
|
||||
// An allocated array of allocated field values from the
|
||||
// output string. Additional fields + values may be included in
|
||||
// addition to those in the output string, to aid in
|
||||
// debugging. Item i in this array maps to item i in
|
||||
// output_fields.
|
||||
char **output_values;
|
||||
|
||||
// The length of output_fields/output_values
|
||||
uint32_t num_output_values;
|
||||
} falco_engine_embed_result;
|
||||
|
||||
/* A utility function to free a falco_engine_embed_result struct and
|
||||
* its allocated strings returned by a call to next_result() */
|
||||
void falco_engine_embed_free_result(falco_engine_embed_result *result);
|
||||
|
||||
// Interface to interact with an embeddable falco engine.
|
||||
|
||||
// NOTE: For all functions below that return a char *, the memory
|
||||
// pointed to by the char * is allocated using malloc() and should be
|
||||
// freed by the caller using free().
|
||||
|
||||
// Return the embedded engine version.
|
||||
//
|
||||
// Return value: a version string, in the following format:
|
||||
// "<major>.<minor>.<patch>", e.g. "1.2.3".
|
||||
// This interface is compatible following semver conventions:
|
||||
// <major> changes for incompatible api changes, <minor> for
|
||||
// backwards-compatible additions, <patch> for compatible bug
|
||||
// fixes.
|
||||
char* falco_engine_embed_get_version();
|
||||
|
||||
// Initialize a falco engine.
|
||||
//
|
||||
// Arguments:
|
||||
// - rc: pointer to an integer containing a falco_engine_embed_rc value.
|
||||
//
|
||||
// Return value: pointer to the engine state that is passed to
|
||||
// other API functions.
|
||||
falco_engine_embed_t* falco_engine_embed_init(int32_t *rc);
|
||||
|
||||
// Destroy a falco engine. This frees any resources allocated in
|
||||
// init(). If open() has been called, close() should be called before
|
||||
// destroy().
|
||||
//
|
||||
// Arguments:
|
||||
// - engine: returned by a prior succesful call to init().
|
||||
// - errstr: on error, errstr will point to an allocated
|
||||
// string with additional details on the errror. The string
|
||||
// must be freed via a call to free().
|
||||
//
|
||||
// Return value: an integer containing a falco_engine_embed_rc
|
||||
// value.
|
||||
int32_t falco_engine_embed_destroy(falco_engine_embed_t *engine, char *errstr);
|
||||
|
||||
// Load either a falco source or extractor plugin.
|
||||
//
|
||||
// Arguments:
|
||||
// - engine: returned by a prior succesful call to init().
|
||||
// - path: a file path pointing to a dynamic library that
|
||||
// can be dlopen()ed.
|
||||
// - init_config: a string that will be passed to the plugin's
|
||||
// init() function.
|
||||
// - open_params: a string that will be passed to the
|
||||
// plugin's open() function.
|
||||
// - errstr: on error, errstr will point to an allocated
|
||||
// string with additional details on the errror. The string
|
||||
// must be freed via a call to free().
|
||||
//
|
||||
// Return value: an integer containing a falco_engine_embed_rc
|
||||
// value.
|
||||
int32_t falco_engine_embed_load_plugin(falco_engine_embed_t *engine,
|
||||
const char *path,
|
||||
const char* init_config,
|
||||
const char* open_params,
|
||||
char **errstr);
|
||||
|
||||
// Load the provided rules content. These rules are applied on
|
||||
// top of any previously loaded rules content
|
||||
// (e.g. appending/overriding rule/macro/list objects as
|
||||
// specified via "append:" properties)
|
||||
//
|
||||
// NOTE: Plugins should be loaded before any rules are loaded.
|
||||
//
|
||||
// Arguments:
|
||||
// - engine: returned by a prior succesful call to init().
|
||||
// - rules_content: a null-terminated string containing
|
||||
// yaml rules content.
|
||||
// - errstr: on error, errstr will point to an allocated
|
||||
// string with additional details on the errror. The string
|
||||
// must be freed via a call to free().
|
||||
//
|
||||
// Return value: an integer containing a falco_engine_embed_rc
|
||||
// value.
|
||||
int32_t falco_engine_embed_load_rules_content(falco_engine_embed_t *engine,
|
||||
const char *rules_content,
|
||||
char **errstr);
|
||||
|
||||
// Enable/disable an event source.
|
||||
// By default all event sources are enabled. This function
|
||||
// enables/disables specific event sources.
|
||||
//
|
||||
// Arguments:
|
||||
// - engine: returned by a prior succesful call to init().
|
||||
// - source: an int containing a falco_engine_embed_evt_source value.
|
||||
// - enabled: whether to enable or disable the provided source
|
||||
// - errstr: on error, errstr will point to an allocated
|
||||
// string with additional details on the errror. The string
|
||||
// must be freed via a call to free().
|
||||
//
|
||||
// Return value: an integer containing a falco_engine_embed_rc
|
||||
// value.
|
||||
int32_t falco_engine_embed_enable_source(falco_engine_embed_t *engine,
|
||||
int32_t source,
|
||||
bool enabled,
|
||||
char **errstr);
|
||||
|
||||
// Open the engine, which starts event processing and matching
|
||||
// against the loaded set of rules.
|
||||
//
|
||||
// Arguments:
|
||||
// - engine: returned by a prior succesful call to init().
|
||||
// - errstr: on error, errstr will point to an allocated
|
||||
// string with additional details on the errror. The string
|
||||
// must be freed via a call to free().
|
||||
//
|
||||
// Return value: an integer containing a falco_engine_embed_rc
|
||||
// value.
|
||||
int32_t falco_engine_embed_open(falco_engine_embed_t *engine,
|
||||
char **errstr);
|
||||
|
||||
// Close the engine, which stops event processing.
|
||||
//
|
||||
// Arguments:
|
||||
// - engine: returned by a prior succesful call to init().
|
||||
// - errstr: on error, errstr will point to an allocated
|
||||
// string with additional details on the errror. The string
|
||||
// must be freed via a call to free().
|
||||
//
|
||||
// Return value: an integer containing a falco_engine_embed_rc
|
||||
// value.
|
||||
int32_t falco_engine_embed_close(falco_engine_embed_t *engine,
|
||||
char **errstr);
|
||||
|
||||
// Receive the next result (e.g. an event that matched a
|
||||
// rule). This function blocks until the next result is
|
||||
// available. close() is called, or an error occurs.
|
||||
//
|
||||
// Arguments:
|
||||
// - engine: returned by a prior succesful call to init().
|
||||
// - result: a pointer to a falco_engine_embed_result struct
|
||||
// pointer. On success, a struct will be allocated, and filled in
|
||||
// with allocated char* values, and the pointer updated to point to
|
||||
// the allocated struct.
|
||||
// - errstr: on error, errstr will point to an allocated
|
||||
// string with additional details on the errror. The string
|
||||
// must be freed via a call to free().
|
||||
//
|
||||
// Return value: an integer containing a falco_engine_embed_rc
|
||||
// value.
|
||||
int32_t falco_engine_embed_next_result(falco_engine_embed_t *engine,
|
||||
falco_engine_embed_result **result,
|
||||
char **errstr);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,6 @@ limitations under the License.
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
|
||||
#include "falco_engine.h"
|
||||
#include "falco_utils.h"
|
||||
@@ -57,8 +56,6 @@ falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
|
||||
|
||||
m_sinsp_rules.reset(new falco_sinsp_ruleset());
|
||||
m_k8s_audit_rules.reset(new falco_ruleset());
|
||||
m_plugin_rules.clear();
|
||||
m_required_plugin_versions.clear();
|
||||
|
||||
if(seed_rng)
|
||||
{
|
||||
@@ -182,7 +179,7 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
|
||||
bool json_include_output_property = false;
|
||||
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property);
|
||||
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, required_engine_version, m_required_plugin_versions);
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, required_engine_version);
|
||||
}
|
||||
|
||||
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
|
||||
@@ -217,11 +214,6 @@ void falco_engine::enable_rule(const string &substring, bool enabled, const stri
|
||||
|
||||
m_sinsp_rules->enable(substring, match_exact, enabled, ruleset_id);
|
||||
m_k8s_audit_rules->enable(substring, match_exact, enabled, ruleset_id);
|
||||
|
||||
for(auto &it : m_plugin_rules)
|
||||
{
|
||||
it.second->enable(substring, match_exact, enabled, ruleset_id);
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule(const string &substring, bool enabled)
|
||||
@@ -236,11 +228,6 @@ void falco_engine::enable_rule_exact(const string &rule_name, bool enabled, cons
|
||||
|
||||
m_sinsp_rules->enable(rule_name, match_exact, enabled, ruleset_id);
|
||||
m_k8s_audit_rules->enable(rule_name, match_exact, enabled, ruleset_id);
|
||||
|
||||
for(auto &it : m_plugin_rules)
|
||||
{
|
||||
it.second->enable(rule_name, match_exact, enabled, ruleset_id);
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_exact(const string &rule_name, bool enabled)
|
||||
@@ -254,11 +241,6 @@ void falco_engine::enable_rule_by_tag(const set<string> &tags, bool enabled, con
|
||||
|
||||
m_sinsp_rules->enable_tags(tags, enabled, ruleset_id);
|
||||
m_k8s_audit_rules->enable_tags(tags, enabled, ruleset_id);
|
||||
|
||||
for(auto &it : m_plugin_rules)
|
||||
{
|
||||
it.second->enable_tags(tags, enabled, ruleset_id);
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_by_tag(const set<string> &tags, bool enabled)
|
||||
@@ -289,16 +271,8 @@ uint64_t falco_engine::num_rules_for_ruleset(const std::string &ruleset)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
|
||||
uint32_t num_plugin_rules = 0;
|
||||
|
||||
for(auto &it : m_plugin_rules)
|
||||
{
|
||||
num_plugin_rules += it.second->num_rules_for_ruleset(ruleset_id);
|
||||
}
|
||||
|
||||
return m_sinsp_rules->num_rules_for_ruleset(ruleset_id) +
|
||||
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id) +
|
||||
num_plugin_rules;
|
||||
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::evttypes_for_ruleset(std::vector<bool> &evttypes, const std::string &ruleset)
|
||||
@@ -322,38 +296,13 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
|
||||
return unique_ptr<struct rule_result>();
|
||||
}
|
||||
|
||||
unique_ptr<struct rule_result> res;
|
||||
std::string source = "syscall";
|
||||
|
||||
if(ev->get_type() == PPME_PLUGINEVENT_E)
|
||||
if(!m_sinsp_rules->run(ev, ruleset_id))
|
||||
{
|
||||
sinsp_evt_param *parinfo = ev->get_param(0);
|
||||
ASSERT(parinfo->m_len == sizeof(int32_t));
|
||||
uint32_t plugin_id = *(int32_t *)parinfo->m_val;
|
||||
|
||||
// No rules for this plugin-->no rule match
|
||||
auto it = m_plugin_rules.find(plugin_id);
|
||||
if(it == m_plugin_rules.end())
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
// All plugin events have a single tag PPME_CONTAINER_X.
|
||||
if (!it->second->run((gen_event *) ev, PPME_CONTAINER_X, ruleset_id))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!m_sinsp_rules->run(ev, ruleset_id))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return unique_ptr<struct rule_result>();
|
||||
}
|
||||
|
||||
res.reset(new rule_result());
|
||||
res->source = source;
|
||||
unique_ptr<struct rule_result> res(new rule_result());
|
||||
res->source = "syscall";
|
||||
|
||||
populate_rule_result(res, ev);
|
||||
|
||||
@@ -529,11 +478,11 @@ void falco_engine::print_stats()
|
||||
|
||||
}
|
||||
|
||||
void falco_engine::add_syscall_filter(string &rule,
|
||||
set<uint32_t> &evttypes,
|
||||
set<uint32_t> &syscalls,
|
||||
set<string> &tags,
|
||||
sinsp_filter* filter)
|
||||
void falco_engine::add_sinsp_filter(string &rule,
|
||||
set<uint32_t> &evttypes,
|
||||
set<uint32_t> &syscalls,
|
||||
set<string> &tags,
|
||||
sinsp_filter* filter)
|
||||
{
|
||||
m_sinsp_rules->add(rule, evttypes, syscalls, tags, filter);
|
||||
}
|
||||
@@ -548,75 +497,10 @@ void falco_engine::add_k8s_audit_filter(string &rule,
|
||||
m_k8s_audit_rules->add(rule, tags, event_tags, filter);
|
||||
}
|
||||
|
||||
void falco_engine::add_plugin_filter(string &rule,
|
||||
set<string> &tags,
|
||||
sinsp_filter* filter,
|
||||
string &source)
|
||||
{
|
||||
// Find the loaded source plugin with event source == source
|
||||
// and add this filter to the map.
|
||||
// XXX/mstemm what to do with extractor plugins?
|
||||
std::shared_ptr<sinsp_plugin> plugin = m_inspector->get_source_plugin_by_source(source);
|
||||
|
||||
if(plugin)
|
||||
{
|
||||
// All plugin events have a single tag PPME_CONTAINER_X.
|
||||
std::set<uint32_t> event_tags = {PPME_CONTAINER_X};
|
||||
|
||||
sinsp_source_plugin *splugin = static_cast<sinsp_source_plugin *>(plugin.get());
|
||||
uint32_t id = splugin->id();
|
||||
|
||||
auto it = m_plugin_rules.find(id);
|
||||
|
||||
if(it == m_plugin_rules.end())
|
||||
{
|
||||
std::unique_ptr<falco_ruleset> add;
|
||||
add.reset(new falco_ruleset());
|
||||
m_plugin_rules[id] = std::move(add);
|
||||
it = m_plugin_rules.find(id);
|
||||
}
|
||||
|
||||
it->second->add(rule, tags, event_tags, filter);
|
||||
}
|
||||
}
|
||||
|
||||
bool falco_engine::is_plugin_compatible(const std::string &name,
|
||||
const std::string &version,
|
||||
std::string &required_version)
|
||||
{
|
||||
sinsp_plugin::version plugin_version(version.c_str());
|
||||
|
||||
if(!plugin_version.m_valid)
|
||||
{
|
||||
throw falco_exception(string("Plugin version string ") + version + " not valid");
|
||||
}
|
||||
|
||||
if(m_required_plugin_versions.find(name) == m_required_plugin_versions.end())
|
||||
{
|
||||
// No required engine versions, so no restrictions. Compatible.
|
||||
return true;
|
||||
}
|
||||
|
||||
for(auto &rversion : m_required_plugin_versions[name])
|
||||
{
|
||||
sinsp_plugin::version req_version(rversion.c_str());
|
||||
if(req_version.m_version_major > plugin_version.m_version_major)
|
||||
{
|
||||
required_version = rversion;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void falco_engine::clear_filters()
|
||||
{
|
||||
m_sinsp_rules.reset(new falco_sinsp_ruleset());
|
||||
m_k8s_audit_rules.reset(new falco_ruleset());
|
||||
m_plugin_rules.clear();
|
||||
m_required_plugin_versions.clear();
|
||||
}
|
||||
|
||||
void falco_engine::set_sampling_ratio(uint32_t sampling_ratio)
|
||||
|
||||
@@ -29,7 +29,6 @@ limitations under the License.
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "sinsp.h"
|
||||
#include "plugin.h"
|
||||
#include "filter.h"
|
||||
|
||||
#include "json_evt.h"
|
||||
@@ -234,22 +233,11 @@ public:
|
||||
// Add a filter, which is related to the specified set of
|
||||
// event types/syscalls, to the engine.
|
||||
//
|
||||
void add_syscall_filter(std::string &rule,
|
||||
std::set<uint32_t> &evttypes,
|
||||
std::set<uint32_t> &syscalls,
|
||||
std::set<std::string> &tags,
|
||||
sinsp_filter* filter);
|
||||
|
||||
void add_plugin_filter(std::string &rule,
|
||||
void add_sinsp_filter(std::string &rule,
|
||||
std::set<uint32_t> &evttypes,
|
||||
std::set<uint32_t> &syscalls,
|
||||
std::set<std::string> &tags,
|
||||
sinsp_filter* filter,
|
||||
std::string &source);
|
||||
|
||||
// Return whether the provided plugin name + version is
|
||||
// compatible with the current set of loaded rules files.
|
||||
// required_version will be filled in with the required
|
||||
// version when the method returns false.
|
||||
bool is_plugin_compatible(const std::string &name, const std::string &version, std::string &required_version);
|
||||
sinsp_filter* filter);
|
||||
|
||||
sinsp_filter_factory &sinsp_factory();
|
||||
json_event_filter_factory &json_factory();
|
||||
@@ -275,14 +263,6 @@ private:
|
||||
std::unique_ptr<falco_sinsp_ruleset> m_sinsp_rules;
|
||||
std::unique_ptr<falco_ruleset> m_k8s_audit_rules;
|
||||
|
||||
// Maps from plugin id to rules related to that plugin
|
||||
// XXX/mstemm how to handle extractor-only plugins?
|
||||
std::map<uint32_t, std::unique_ptr<falco_ruleset>> m_plugin_rules;
|
||||
|
||||
// Maps from plugin to a list of required plugin versions
|
||||
// found in any loaded rules files.
|
||||
std::map<std::string, std::list<std::string>> m_required_plugin_versions;
|
||||
|
||||
void populate_rule_result(unique_ptr<struct rule_result> &res, gen_event *ev);
|
||||
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2021 The Falco Authors.
|
||||
Copyright (C) 2020 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,11 +14,11 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// The version of rules/filter fields/etc supported by this Falco
|
||||
// The version of rules/filter fields/etc supported by this falco
|
||||
// engine.
|
||||
#define FALCO_ENGINE_VERSION (10)
|
||||
#define FALCO_ENGINE_VERSION (9)
|
||||
|
||||
// This is the result of running "falco --list -N | sha256sum" and
|
||||
// represents the fields supported by this version of Falco. It's used
|
||||
// represents the fields supported by this version of falco. It's used
|
||||
// at build time to detect a changed set of fields.
|
||||
#define FALCO_FIELDS_CHECKSUM "8183621f52451d842036eee409e2ed920d9c91bab33e0c4a44e4a871378d103f"
|
||||
|
||||
@@ -49,14 +49,6 @@ void falco_formats::init(sinsp *inspector,
|
||||
luaL_openlib(ls, "formats", ll_falco, 0);
|
||||
}
|
||||
|
||||
void falco_formats::create_sinsp_formatter(lua_State *ls, const std::string &format)
|
||||
{
|
||||
sinsp_evt_formatter *formatter;
|
||||
formatter = new sinsp_evt_formatter(s_inspector, format);
|
||||
lua_pushnil(ls);
|
||||
lua_pushlightuserdata(ls, formatter);
|
||||
}
|
||||
|
||||
int falco_formats::lua_formatter(lua_State *ls)
|
||||
{
|
||||
string source = luaL_checkstring(ls, -2);
|
||||
@@ -66,18 +58,17 @@ int falco_formats::lua_formatter(lua_State *ls)
|
||||
{
|
||||
if(source == "syscall")
|
||||
{
|
||||
create_sinsp_formatter(ls, format);
|
||||
sinsp_evt_formatter *formatter;
|
||||
formatter = new sinsp_evt_formatter(s_inspector, format);
|
||||
lua_pushnil(ls);
|
||||
lua_pushlightuserdata(ls, formatter);
|
||||
}
|
||||
else if (source == "k8s_audit")
|
||||
else
|
||||
{
|
||||
json_event_formatter *formatter;
|
||||
formatter = new json_event_formatter(s_engine->json_factory(), format);
|
||||
lua_pushnil(ls);
|
||||
lua_pushlightuserdata(ls, formatter);
|
||||
} else {
|
||||
// Not one of the built-in sources, so assume it's a plugin.
|
||||
// Plugins behave identically to syscall events for now.
|
||||
create_sinsp_formatter(ls, format);
|
||||
}
|
||||
}
|
||||
catch(exception &e)
|
||||
@@ -97,12 +88,6 @@ int falco_formats::lua_formatter(lua_State *ls)
|
||||
return 2;
|
||||
}
|
||||
|
||||
void falco_formats::delete_sinsp_formatter(lua_State *ls)
|
||||
{
|
||||
sinsp_evt_formatter *formatter = (sinsp_evt_formatter *)lua_topointer(ls, -1);
|
||||
delete(formatter);
|
||||
}
|
||||
|
||||
int falco_formats::lua_free_formatter(lua_State *ls)
|
||||
{
|
||||
if(!lua_islightuserdata(ls, -1) ||
|
||||
@@ -116,64 +101,18 @@ int falco_formats::lua_free_formatter(lua_State *ls)
|
||||
|
||||
if(source == "syscall")
|
||||
{
|
||||
delete_sinsp_formatter(ls);
|
||||
}
|
||||
else if (source == "k8s_audit")
|
||||
{
|
||||
json_event_formatter *formatter = (json_event_formatter *)lua_topointer(ls, -1);
|
||||
sinsp_evt_formatter *formatter = (sinsp_evt_formatter *)lua_topointer(ls, -1);
|
||||
delete(formatter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not one of the built-in sources, so assume it's a plugin.
|
||||
// Plugins behave identically to syscall events for now.
|
||||
delete_sinsp_formatter(ls);
|
||||
json_event_formatter *formatter = (json_event_formatter *)lua_topointer(ls, -1);
|
||||
delete(formatter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void falco_formats::format_sinsp_event(const gen_event *evt, const std::string &format,
|
||||
std::string &line, std::string &json_line, std::string &sformat)
|
||||
{
|
||||
// This is "output"
|
||||
s_formatters->tostring((sinsp_evt *)evt, sformat, &line);
|
||||
|
||||
if(s_json_output)
|
||||
{
|
||||
sinsp_evt::param_fmt cur_fmt = s_inspector->get_buffer_format();
|
||||
switch(cur_fmt)
|
||||
{
|
||||
case sinsp_evt::PF_NORMAL:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSON);
|
||||
break;
|
||||
case sinsp_evt::PF_EOLS:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONEOLS);
|
||||
break;
|
||||
case sinsp_evt::PF_HEX:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONHEX);
|
||||
break;
|
||||
case sinsp_evt::PF_HEXASCII:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONHEXASCII);
|
||||
break;
|
||||
case sinsp_evt::PF_BASE64:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONBASE64);
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
// This is output fields
|
||||
s_formatters->tostring((sinsp_evt *)evt, sformat, &json_line);
|
||||
|
||||
// The formatted string might have a leading newline. If it does, remove it.
|
||||
if(json_line[0] == '\n')
|
||||
{
|
||||
json_line.erase(0, 1);
|
||||
}
|
||||
s_inspector->set_buffer_format(cur_fmt);
|
||||
}
|
||||
}
|
||||
|
||||
string falco_formats::format_event(const gen_event *evt, const std::string &rule, const std::string &source,
|
||||
const std::string &level, const std::string &format)
|
||||
{
|
||||
@@ -182,11 +121,47 @@ string falco_formats::format_event(const gen_event *evt, const std::string &rule
|
||||
string json_line;
|
||||
string sformat = format;
|
||||
|
||||
if(source == "syscall")
|
||||
if(strcmp(source.c_str(), "syscall") == 0)
|
||||
{
|
||||
format_sinsp_event(evt, format, line, json_line, sformat);
|
||||
// This is "output"
|
||||
s_formatters->tostring((sinsp_evt *)evt, sformat, &line);
|
||||
|
||||
if(s_json_output)
|
||||
{
|
||||
sinsp_evt::param_fmt cur_fmt = s_inspector->get_buffer_format();
|
||||
switch(cur_fmt)
|
||||
{
|
||||
case sinsp_evt::PF_NORMAL:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSON);
|
||||
break;
|
||||
case sinsp_evt::PF_EOLS:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONEOLS);
|
||||
break;
|
||||
case sinsp_evt::PF_HEX:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONHEX);
|
||||
break;
|
||||
case sinsp_evt::PF_HEXASCII:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONHEXASCII);
|
||||
break;
|
||||
case sinsp_evt::PF_BASE64:
|
||||
s_inspector->set_buffer_format(sinsp_evt::PF_JSONBASE64);
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
// This is output fields
|
||||
s_formatters->tostring((sinsp_evt *)evt, sformat, &json_line);
|
||||
|
||||
// The formatted string might have a leading newline. If it does, remove it.
|
||||
if(json_line[0] == '\n')
|
||||
{
|
||||
json_line.erase(0, 1);
|
||||
}
|
||||
s_inspector->set_buffer_format(cur_fmt);
|
||||
}
|
||||
}
|
||||
else if (source == "k8s_audit")
|
||||
else
|
||||
{
|
||||
json_event_formatter formatter(s_engine->json_factory(), sformat);
|
||||
|
||||
@@ -196,10 +171,6 @@ string falco_formats::format_event(const gen_event *evt, const std::string &rule
|
||||
{
|
||||
json_line = formatter.tojson((json_event *)evt);
|
||||
}
|
||||
} else {
|
||||
// Not one of the built-in sources, so assume it's a plugin.
|
||||
// Plugins behave identically to syscall events for now.
|
||||
format_sinsp_event(evt, format, line, json_line, sformat);
|
||||
}
|
||||
|
||||
// For JSON output, the formatter returned a json-as-text
|
||||
@@ -263,16 +234,11 @@ map<string, string> falco_formats::resolve_tokens(const gen_event *evt, const st
|
||||
{
|
||||
s_formatters->resolve_tokens((sinsp_evt *)evt, sformat, values);
|
||||
}
|
||||
else if (source == "k8s_audit")
|
||||
// k8s_audit
|
||||
else
|
||||
{
|
||||
json_event_formatter json_formatter(s_engine->json_factory(), sformat);
|
||||
values = json_formatter.tomap((json_event *)evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not one of the built-in sources, so assume it's a plugin.
|
||||
// Plugins behave identically to syscall events for now.
|
||||
s_formatters->resolve_tokens((sinsp_evt *)evt, sformat, values);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@ limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "sinsp.h"
|
||||
|
||||
extern "C"
|
||||
@@ -43,18 +39,12 @@ public:
|
||||
bool json_output,
|
||||
bool json_include_output_property);
|
||||
|
||||
static void create_sinsp_formatter(lua_State *ls, const std::string &format);
|
||||
static void delete_sinsp_formatter(lua_State *ls);
|
||||
|
||||
// formatter = falco.formatter(format_string)
|
||||
static int lua_formatter(lua_State *ls);
|
||||
|
||||
// falco.free_formatter(formatter)
|
||||
static int lua_free_formatter(lua_State *ls);
|
||||
|
||||
static void format_sinsp_event(const gen_event *evt, const std::string &format,
|
||||
std::string &line, std::string &json_line, std::string &sformat);
|
||||
|
||||
static string format_event(const gen_event *evt, const std::string &rule, const std::string &source,
|
||||
const std::string &level, const std::string &format);
|
||||
|
||||
|
||||
@@ -426,29 +426,6 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
||||
return false, build_error_with_context(v['context'], "Rules require engine version "..v['required_engine_version']..", but engine version is "..falco_rules.engine_version(rules_mgr)), warnings
|
||||
end
|
||||
|
||||
elseif (v['required_plugin_versions']) then
|
||||
|
||||
for _, vobj in ipairs(v['required_plugin_versions']) do
|
||||
if vobj['name'] == nil then
|
||||
return false, build_error_with_context(v['context'], "required_plugin_versions item must have name property"), warnings
|
||||
end
|
||||
|
||||
if vobj['version'] == nil then
|
||||
return false, build_error_with_context(v['context'], "required_plugin_versions item must have version property"), warnings
|
||||
end
|
||||
|
||||
-- In the rules yaml, it's a name + version. But it's
|
||||
-- possible, although unlikely, that a single yaml blob
|
||||
-- contains multiple docs, withe each doc having its own
|
||||
-- required_engine_version entry. So populate a map plugin
|
||||
-- name -> list of required plugin versions.
|
||||
if load_state.required_plugin_versions[vobj['name']] == nil then
|
||||
load_state.required_plugin_versions[vobj['name']] = {}
|
||||
end
|
||||
|
||||
table.insert(load_state.required_plugin_versions[vobj['name']], vobj['version'])
|
||||
end
|
||||
|
||||
elseif (v['macro']) then
|
||||
|
||||
if (v['macro'] == nil or type(v['macro']) == "table") then
|
||||
@@ -792,7 +769,6 @@ end
|
||||
-- Returns:
|
||||
-- - Load Result: bool
|
||||
-- - required engine version. will be nil when load result is false
|
||||
-- - required_plugin_versions. will be nil when load_result is false
|
||||
-- - List of Errors
|
||||
-- - List of Warnings
|
||||
function load_rules(sinsp_lua_parser,
|
||||
@@ -807,7 +783,7 @@ function load_rules(sinsp_lua_parser,
|
||||
|
||||
local warnings = {}
|
||||
|
||||
local load_state = {lines={}, indices={}, cur_item_idx=0, min_priority=min_priority, required_engine_version=0, required_plugin_versions={}}
|
||||
local load_state = {lines={}, indices={}, cur_item_idx=0, min_priority=min_priority, required_engine_version=0}
|
||||
|
||||
load_state.lines, load_state.indices = split_lines(rules_content)
|
||||
|
||||
@@ -828,29 +804,29 @@ function load_rules(sinsp_lua_parser,
|
||||
row = tonumber(row)
|
||||
col = tonumber(col)
|
||||
|
||||
return false, nil, nil, build_error(load_state.lines, row, 3, docs), warnings
|
||||
return false, nil, build_error(load_state.lines, row, 3, docs), warnings
|
||||
end
|
||||
|
||||
if docs == nil then
|
||||
-- An empty rules file is acceptable
|
||||
return true, load_state.required_engine_version, {}, {}, warnings
|
||||
return true, load_state.required_engine_version, {}, warnings
|
||||
end
|
||||
|
||||
if type(docs) ~= "table" then
|
||||
return false, nil, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml"), warnings
|
||||
return false, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml"), warnings
|
||||
end
|
||||
|
||||
for docidx, doc in ipairs(docs) do
|
||||
|
||||
if type(doc) ~= "table" then
|
||||
return false, nil, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml"), warnings
|
||||
return false, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml"), warnings
|
||||
end
|
||||
|
||||
-- Look for non-numeric indices--implies that document is not array
|
||||
-- of objects.
|
||||
for key, val in pairs(doc) do
|
||||
if type(key) ~= "number" then
|
||||
return false, nil, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml array of objects"), warnings
|
||||
return false, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml array of objects"), warnings
|
||||
end
|
||||
end
|
||||
|
||||
@@ -863,7 +839,7 @@ function load_rules(sinsp_lua_parser,
|
||||
end
|
||||
|
||||
if not res then
|
||||
return res, nil, nil, errors, warnings
|
||||
return res, nil, errors, warnings
|
||||
end
|
||||
end
|
||||
|
||||
@@ -904,7 +880,7 @@ function load_rules(sinsp_lua_parser,
|
||||
local status, ast = compiler.compile_macro(v['condition'], state.macros, state.lists)
|
||||
|
||||
if status == false then
|
||||
return false, nil, nil, build_error_with_context(v['context'], ast), warnings
|
||||
return false, nil, build_error_with_context(v['context'], ast), warnings
|
||||
end
|
||||
|
||||
if v['source'] == "syscall" then
|
||||
@@ -936,7 +912,7 @@ function load_rules(sinsp_lua_parser,
|
||||
end
|
||||
|
||||
if err ~= nil then
|
||||
return false, nil, nil, build_error_with_context(v['context'], err), warnings
|
||||
return false, nil, build_error_with_context(v['context'], err), warnings
|
||||
end
|
||||
|
||||
if icond ~= "" then
|
||||
@@ -961,7 +937,7 @@ function load_rules(sinsp_lua_parser,
|
||||
state.macros, state.lists)
|
||||
|
||||
if status == false then
|
||||
return false, nil, nil, build_error_with_context(v['context'], filter_ast), warnings
|
||||
return false, nil, build_error_with_context(v['context'], filter_ast), warnings
|
||||
end
|
||||
|
||||
local evtttypes = {}
|
||||
@@ -984,7 +960,7 @@ function load_rules(sinsp_lua_parser,
|
||||
warnings[#warnings + 1] = msg
|
||||
|
||||
if not v['skip-if-unknown-filter'] then
|
||||
return false, nil, nil, build_error_with_context(v['context'], msg), warnings
|
||||
return false, nil, build_error_with_context(v['context'], msg), warnings
|
||||
else
|
||||
print("Skipping "..msg)
|
||||
goto next_rule
|
||||
@@ -1016,10 +992,6 @@ function load_rules(sinsp_lua_parser,
|
||||
install_filter(filter_ast.filter.value, k8s_audit_filter, json_lua_parser)
|
||||
|
||||
falco_rules.add_k8s_audit_filter(rules_mgr, v['rule'], v['tags'])
|
||||
else
|
||||
install_filter(filter_ast.filter.value, filter, sinsp_lua_parser)
|
||||
|
||||
falco_rules.add_plugin_filter(rules_mgr, v['rule'], v['tags'], v['source'])
|
||||
end
|
||||
|
||||
-- Rule ASTs are merged together into one big AST, with "OR" between each
|
||||
@@ -1074,10 +1046,10 @@ function load_rules(sinsp_lua_parser,
|
||||
if err == nil then
|
||||
formats.free_formatter(v['source'], formatter)
|
||||
else
|
||||
return false, nil, nil, build_error_with_context(v['context'], err), warnings
|
||||
return false, nil, build_error_with_context(v['context'], err), warnings
|
||||
end
|
||||
else
|
||||
return false, nil, nil, build_error_with_context(v['context'], "Unexpected type in load_rule: "..filter_ast.type), warnings
|
||||
return false, nil, build_error_with_context(v['context'], "Unexpected type in load_rule: "..filter_ast.type), warnings
|
||||
end
|
||||
|
||||
::next_rule::
|
||||
@@ -1100,7 +1072,7 @@ function load_rules(sinsp_lua_parser,
|
||||
|
||||
io.flush()
|
||||
|
||||
return true, load_state.required_engine_version, load_state.required_plugin_versions, {}, warnings
|
||||
return true, load_state.required_engine_version, {}, warnings
|
||||
end
|
||||
|
||||
local rule_fmt = "%-50s %s"
|
||||
|
||||
@@ -32,7 +32,6 @@ const static struct luaL_Reg ll_falco_rules[] =
|
||||
{"clear_filters", &falco_rules::clear_filters},
|
||||
{"add_filter", &falco_rules::add_filter},
|
||||
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
|
||||
{"add_plugin_filter", &falco_rules::add_plugin_filter},
|
||||
{"enable_rule", &falco_rules::enable_rule},
|
||||
{"engine_version", &falco_rules::engine_version},
|
||||
{NULL, NULL}};
|
||||
@@ -160,41 +159,6 @@ int falco_rules::add_k8s_audit_filter(lua_State *ls)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int falco_rules::add_plugin_filter(lua_State *ls)
|
||||
{
|
||||
if (! lua_islightuserdata(ls, -4) ||
|
||||
! lua_isstring(ls, -3) ||
|
||||
! lua_istable(ls, -2) ||
|
||||
! lua_isstring(ls, -1))
|
||||
{
|
||||
lua_pushstring(ls, "Invalid arguments passed to add_plugin_filter()");
|
||||
lua_error(ls);
|
||||
}
|
||||
|
||||
falco_rules *rules = (falco_rules *) lua_topointer(ls, -4);
|
||||
const char *rulec = lua_tostring(ls, -3);
|
||||
|
||||
set<string> tags;
|
||||
|
||||
lua_pushnil(ls); /* first key */
|
||||
while (lua_next(ls, -3) != 0) {
|
||||
// key is at index -2, value is at index
|
||||
// -1. We want the values.
|
||||
tags.insert(lua_tostring(ls, -1));
|
||||
|
||||
// Remove value, keep key for next iteration
|
||||
lua_pop(ls, 1);
|
||||
}
|
||||
|
||||
const char *sourcec = lua_tostring(ls, -1);
|
||||
|
||||
std::string rule = rulec;
|
||||
std::string source = sourcec;
|
||||
rules->add_plugin_filter(rule, tags, source);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void falco_rules::add_filter(string &rule, set<uint32_t> &evttypes, set<uint32_t> &syscalls, set<string> &tags)
|
||||
{
|
||||
// While the current rule was being parsed, a sinsp_filter
|
||||
@@ -202,7 +166,7 @@ void falco_rules::add_filter(string &rule, set<uint32_t> &evttypes, set<uint32_t
|
||||
// and pass it to the engine.
|
||||
sinsp_filter *filter = (sinsp_filter *) m_sinsp_lua_parser->get_filter(true);
|
||||
|
||||
m_engine->add_syscall_filter(rule, evttypes, syscalls, tags, filter);
|
||||
m_engine->add_sinsp_filter(rule, evttypes, syscalls, tags, filter);
|
||||
}
|
||||
|
||||
void falco_rules::add_k8s_audit_filter(string &rule, set<string> &tags)
|
||||
@@ -215,16 +179,6 @@ void falco_rules::add_k8s_audit_filter(string &rule, set<string> &tags)
|
||||
m_engine->add_k8s_audit_filter(rule, tags, filter);
|
||||
}
|
||||
|
||||
void falco_rules::add_plugin_filter(string &rule, set<string> &tags, string &source)
|
||||
{
|
||||
// While the current rule was being parsed, a sinsp_filter
|
||||
// object was being populated by lua_parser. Grab that filter
|
||||
// and pass it to the engine.
|
||||
sinsp_filter *filter = (sinsp_filter *) m_sinsp_lua_parser->get_filter(true);
|
||||
|
||||
m_engine->add_plugin_filter(rule, tags, filter, source);
|
||||
}
|
||||
|
||||
int falco_rules::enable_rule(lua_State *ls)
|
||||
{
|
||||
if (! lua_islightuserdata(ls, -3) ||
|
||||
@@ -290,48 +244,11 @@ static std::list<std::string> get_lua_table_values(lua_State *ls, int idx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void get_lua_table_list_values(lua_State *ls,
|
||||
int idx,
|
||||
std::map<std::string, std::list<std::string>> &required_plugin_versions)
|
||||
{
|
||||
if (lua_isnil(ls, idx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lua_pushnil(ls); /* first key */
|
||||
while (lua_next(ls, idx-1) != 0) {
|
||||
// key is at index -2, table of values is at index -1.
|
||||
if (! lua_isstring(ls, -2)) {
|
||||
std::string err = "Non-string key in table of strings";
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
std::string key = string(lua_tostring(ls, -2));
|
||||
std::list<std::string> vals = get_lua_table_values(ls, -1);
|
||||
|
||||
if (required_plugin_versions.find(key) == required_plugin_versions.end())
|
||||
{
|
||||
required_plugin_versions[key] = vals;
|
||||
}
|
||||
else
|
||||
{
|
||||
required_plugin_versions[key].insert(required_plugin_versions[key].end(),
|
||||
vals.begin(),
|
||||
vals.end());
|
||||
}
|
||||
|
||||
// Remove value, keep key for next iteration
|
||||
lua_pop(ls, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void falco_rules::load_rules(const string &rules_content,
|
||||
bool verbose, bool all_events,
|
||||
string &extra, bool replace_container_info,
|
||||
falco_common::priority_type min_priority,
|
||||
uint64_t &required_engine_version,
|
||||
std::map<std::string, std::list<std::string>> &required_plugin_versions)
|
||||
uint64_t &required_engine_version)
|
||||
{
|
||||
lua_getglobal(m_ls, m_lua_load_rules.c_str());
|
||||
if(lua_isfunction(m_ls, -1))
|
||||
@@ -532,7 +449,7 @@ void falco_rules::load_rules(const string &rules_content,
|
||||
lua_pushstring(m_ls, extra.c_str());
|
||||
lua_pushboolean(m_ls, (replace_container_info ? 1 : 0));
|
||||
lua_pushnumber(m_ls, min_priority);
|
||||
if(lua_pcall(m_ls, 9, 5, 0) != 0)
|
||||
if(lua_pcall(m_ls, 9, 4, 0) != 0)
|
||||
{
|
||||
const char* lerr = lua_tostring(m_ls, -1);
|
||||
|
||||
@@ -544,12 +461,10 @@ void falco_rules::load_rules(const string &rules_content,
|
||||
// Returns:
|
||||
// Load result: bool
|
||||
// required engine version: will be nil when load result is false
|
||||
// required_engine_versions: will be nil when load result is false
|
||||
// array of errors
|
||||
// array of warnings
|
||||
bool successful = lua_toboolean(m_ls, -5);
|
||||
required_engine_version = lua_tonumber(m_ls, -4);
|
||||
get_lua_table_list_values(m_ls, -3, required_plugin_versions);
|
||||
bool successful = lua_toboolean(m_ls, -4);
|
||||
required_engine_version = lua_tonumber(m_ls, -3);
|
||||
std::list<std::string> errors = get_lua_table_values(m_ls, -2);
|
||||
std::list<std::string> warnings = get_lua_table_values(m_ls, -1);
|
||||
|
||||
|
||||
@@ -39,15 +39,13 @@ class falco_rules
|
||||
void load_rules(const string &rules_content, bool verbose, bool all_events,
|
||||
std::string &extra, bool replace_container_info,
|
||||
falco_common::priority_type min_priority,
|
||||
uint64_t &required_engine_version,
|
||||
std::map<std::string, std::list<std::string>> &required_plugin_versions);
|
||||
uint64_t &required_engine_version);
|
||||
void describe_rule(string *rule);
|
||||
|
||||
static void init(lua_State *ls);
|
||||
static int clear_filters(lua_State *ls);
|
||||
static int add_filter(lua_State *ls);
|
||||
static int add_k8s_audit_filter(lua_State *ls);
|
||||
static int add_plugin_filter(lua_State *ls);
|
||||
static int enable_rule(lua_State *ls);
|
||||
static int engine_version(lua_State *ls);
|
||||
|
||||
@@ -55,7 +53,6 @@ class falco_rules
|
||||
void clear_filters();
|
||||
void add_filter(string &rule, std::set<uint32_t> &evttypes, std::set<uint32_t> &syscalls, std::set<string> &tags);
|
||||
void add_k8s_audit_filter(string &rule, std::set<string> &tags);
|
||||
void add_plugin_filter(string &rule, std::set<string> &tags, string &source);
|
||||
void enable_rule(string &rule, bool enabled);
|
||||
|
||||
lua_parser* m_sinsp_lua_parser;
|
||||
|
||||
@@ -28,7 +28,6 @@ limitations under the License.
|
||||
#define FALCO_SOURCE_DIR "${PROJECT_SOURCE_DIR}"
|
||||
#define FALCO_SOURCE_CONF_FILE "${PROJECT_SOURCE_DIR}/falco.yaml"
|
||||
#define FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml"
|
||||
#define FALCO_ENGINE_PLUGINS_DIR "${FALCO_ABSOLUTE_SHARE_DIR}/plugins/"
|
||||
|
||||
#define PROBE_NAME "@PROBE_NAME@"
|
||||
#define DRIVER_VERSION "@PROBE_VERSION@"
|
||||
@@ -16,9 +16,6 @@ limitations under the License.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -255,36 +252,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
||||
{
|
||||
throw logic_error("Error reading config file(" + m_config_file + "): the maximum consecutive timeouts without an event must be an unsigned integer > 0");
|
||||
}
|
||||
|
||||
std::set<std::string> load_plugins;
|
||||
|
||||
YAML::Node load_plugins_node;
|
||||
m_config->get_node(load_plugins_node, "load_plugins");
|
||||
|
||||
m_config->get_sequence<set<string>>(load_plugins, "load_plugins");
|
||||
|
||||
std::list<falco_configuration::plugin_config> plugins;
|
||||
try
|
||||
{
|
||||
m_config->get_sequence<std::list<falco_configuration::plugin_config>>(plugins, string("plugins"));
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
// Might be thrown due to not being able to open files
|
||||
throw logic_error("Error reading config file(" + m_config_file + "): could not load plugins config: " + e.what());
|
||||
}
|
||||
|
||||
// If load_plugins was specified, only save plugins matching those in values
|
||||
for (auto &p : plugins)
|
||||
{
|
||||
// If load_plugins was not specified at all, every
|
||||
// plugin is added. Otherwise, the plugin must be in
|
||||
// the load_plugins list.
|
||||
if(!load_plugins_node.IsDefined() || load_plugins.find(p.m_name) != load_plugins.end())
|
||||
{
|
||||
m_plugins.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void falco_configuration::read_rules_file_directory(const string &path, list<string> &rules_filenames)
|
||||
|
||||
@@ -25,9 +25,6 @@ limitations under the License.
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "config_falco.h"
|
||||
|
||||
#include "event_drops.h"
|
||||
#include "falco_outputs.h"
|
||||
@@ -180,11 +177,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void get_node(YAML::Node &ret, const std::string &key)
|
||||
{
|
||||
ret = m_root[key];
|
||||
}
|
||||
|
||||
private:
|
||||
YAML::Node m_root;
|
||||
};
|
||||
@@ -192,15 +184,6 @@ private:
|
||||
class falco_configuration
|
||||
{
|
||||
public:
|
||||
|
||||
typedef struct {
|
||||
public:
|
||||
std::string m_name;
|
||||
std::string m_library_path;
|
||||
std::string m_init_config;
|
||||
std::string m_open_params;
|
||||
} plugin_config;
|
||||
|
||||
falco_configuration();
|
||||
virtual ~falco_configuration();
|
||||
|
||||
@@ -246,8 +229,6 @@ public:
|
||||
|
||||
uint32_t m_syscall_evt_timeout_max_consecutives;
|
||||
|
||||
std::vector<plugin_config> m_plugins;
|
||||
|
||||
private:
|
||||
void init_cmdline_options(std::list<std::string>& cmdline_options);
|
||||
|
||||
@@ -261,102 +242,3 @@ private:
|
||||
|
||||
yaml_configuration* m_config;
|
||||
};
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
struct convert<falco_configuration::plugin_config> {
|
||||
|
||||
static bool read_file_from_key(const Node &node, const std::string &prefix, std::string &value)
|
||||
{
|
||||
std::string key = prefix;
|
||||
|
||||
if(node[key])
|
||||
{
|
||||
value = node[key].as<std::string>();
|
||||
return true;
|
||||
}
|
||||
|
||||
key += "_file";
|
||||
|
||||
if(node[key])
|
||||
{
|
||||
std::string path = node[key].as<std::string>();
|
||||
|
||||
// prepend share dir if path is not absolute
|
||||
if(path.at(0) != '/')
|
||||
{
|
||||
path = string(FALCO_ENGINE_PLUGINS_DIR) + path;
|
||||
}
|
||||
|
||||
// Intentionally letting potential
|
||||
// exception be thrown, will get
|
||||
// caught when reading config.
|
||||
std::ifstream f(path);
|
||||
std::string str((std::istreambuf_iterator<char>(f)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
value = str;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note that the distinction between
|
||||
// init_config/init_config_file and
|
||||
// open_params/open_params_file is lost. But also,
|
||||
// this class doesn't write yaml config anyway.
|
||||
static Node encode(const falco_configuration::plugin_config & rhs) {
|
||||
Node node;
|
||||
node["name"] = rhs.m_name;
|
||||
node["library_path"] = rhs.m_library_path;
|
||||
node["init_config"] = rhs.m_init_config;
|
||||
node["open_params"] = rhs.m_open_params;
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, falco_configuration::plugin_config & rhs) {
|
||||
if(!node.IsMap())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!node["name"])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rhs.m_name = node["name"].as<std::string>();
|
||||
}
|
||||
|
||||
if(!node["library_path"])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rhs.m_library_path = node["library_path"].as<std::string>();
|
||||
|
||||
// prepend share dir if path is not absolute
|
||||
if(rhs.m_library_path.at(0) != '/')
|
||||
{
|
||||
rhs.m_library_path = string(FALCO_ENGINE_PLUGINS_DIR) + rhs.m_library_path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!read_file_from_key(node, string("init_config"), rhs.m_init_config))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!read_file_from_key(node, string("open_params"), rhs.m_open_params))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ limitations under the License.
|
||||
#include "webserver.h"
|
||||
#include "grpc_server.h"
|
||||
#endif
|
||||
#include "plugin.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
|
||||
typedef function<void(sinsp* inspector)> open_t;
|
||||
@@ -129,7 +128,6 @@ static void usage()
|
||||
" -l <rule> Show the name and description of the rule with name <rule> and exit.\n"
|
||||
" --list [<source>] List all defined fields. If <source> is provided, only list those fields for\n"
|
||||
" the source <source>. Current values for <source> are \"syscall\", \"k8s_audit\"\n"
|
||||
" --list-plugins Print info on all loaded plugins and exit.\n"
|
||||
#ifndef MINIMAL_BUILD
|
||||
" -m <url[,marathon_url]>, --mesos-api <url[,marathon_url]>\n"
|
||||
" Enable Mesos support by connecting to the API server\n"
|
||||
@@ -480,7 +478,6 @@ int falco_init(int argc, char **argv)
|
||||
bool print_ignored_events = false;
|
||||
bool list_flds = false;
|
||||
string list_flds_source = "";
|
||||
bool list_plugins = false;
|
||||
bool print_support = false;
|
||||
string cri_socket_path;
|
||||
bool cri_async = true;
|
||||
@@ -521,7 +518,6 @@ int falco_init(int argc, char **argv)
|
||||
{"k8s-api-cert", required_argument, 0, 'K'},
|
||||
{"k8s-api", required_argument, 0, 'k'},
|
||||
{"list", optional_argument, 0},
|
||||
{"list-plugins", no_argument, 0},
|
||||
{"mesos-api", required_argument, 0, 'm'},
|
||||
{"option", required_argument, 0, 'o'},
|
||||
{"pidfile", required_argument, 0, 'P'},
|
||||
@@ -705,10 +701,6 @@ int falco_init(int argc, char **argv)
|
||||
list_flds_source = optarg;
|
||||
}
|
||||
}
|
||||
else if (string(long_options[long_index].name) == "list-plugins")
|
||||
{
|
||||
list_plugins = true;
|
||||
}
|
||||
else if (string(long_options[long_index].name) == "stats-interval")
|
||||
{
|
||||
stats_interval = atoi(optarg);
|
||||
@@ -773,6 +765,12 @@ int falco_init(int argc, char **argv)
|
||||
engine->set_inspector(inspector);
|
||||
engine->set_extra(output_format, replace_container_info);
|
||||
|
||||
if(list_flds)
|
||||
{
|
||||
list_source_fields(engine, verbose, names_only, list_flds_source);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if(disable_sources.size() > 0)
|
||||
{
|
||||
auto it = disable_sources.begin();
|
||||
@@ -867,67 +865,6 @@ int falco_init(int argc, char **argv)
|
||||
throw std::runtime_error("Could not find configuration file at " + conf_filename);
|
||||
}
|
||||
|
||||
std::shared_ptr<sinsp_plugin> input_plugin;
|
||||
for(auto &p : config.m_plugins)
|
||||
{
|
||||
bool avoid_async = true;
|
||||
|
||||
falco_logger::log(LOG_INFO, "Loading plugin (" + p.m_name + ") from file " + p.m_library_path + "\n");
|
||||
|
||||
std::shared_ptr<sinsp_plugin> plugin = sinsp_plugin::register_plugin(inspector,
|
||||
p.m_library_path,
|
||||
(p.m_init_config.empty() ? NULL : (char *)p.m_init_config.c_str()),
|
||||
avoid_async);
|
||||
|
||||
if(plugin->type() == TYPE_SOURCE_PLUGIN)
|
||||
{
|
||||
if(input_plugin)
|
||||
{
|
||||
throw std::invalid_argument(string("Can not load multiple source plugins. ") + input_plugin->name() + " already loaded");
|
||||
}
|
||||
|
||||
inspector->set_input_plugin(p.m_name);
|
||||
if(!p.m_open_params.empty())
|
||||
{
|
||||
inspector->set_input_plugin_open_params(p.m_open_params.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list<sinsp_plugin::info> infos = sinsp_plugin::plugin_infos(inspector);
|
||||
|
||||
if(list_plugins)
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
for(auto &info : infos)
|
||||
{
|
||||
os << "Name: " << info.name << std::endl;
|
||||
os << "Description: " << info.description << std::endl;
|
||||
os << "Contact: " << info.contact << std::endl;
|
||||
os << "Version: " << info.plugin_version.as_string() << std::endl;
|
||||
|
||||
if(info.type == TYPE_SOURCE_PLUGIN)
|
||||
{
|
||||
os << "Type: source plugin" << std::endl;
|
||||
os << "ID: " << info.id << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "Type: extractor plugin" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%lu Plugins Loaded:\n\n%s\n", infos.size(), os.str().c_str());
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if(list_flds)
|
||||
{
|
||||
list_source_fields(engine, verbose, names_only, list_flds_source);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (rules_filenames.size())
|
||||
{
|
||||
config.m_rules_filenames = rules_filenames;
|
||||
@@ -968,17 +905,6 @@ int falco_init(int argc, char **argv)
|
||||
required_engine_versions[filename] = required_engine_version;
|
||||
}
|
||||
|
||||
// Ensure that all plugins are compatible with the loaded set of rules
|
||||
for(auto &info : infos)
|
||||
{
|
||||
std::string required_version;
|
||||
|
||||
if(!engine->is_plugin_compatible(info.name, info.plugin_version.as_string(), required_version))
|
||||
{
|
||||
throw std::invalid_argument(std::string("Plugin ") + info.name + " version " + info.plugin_version.as_string() + " not compatible with required plugin version " + required_version);
|
||||
}
|
||||
}
|
||||
|
||||
// You can't both disable and enable rules
|
||||
if((disabled_rule_substrings.size() + disabled_rule_tags.size() > 0) &&
|
||||
enabled_rule_tags.size() > 0) {
|
||||
|
||||
Reference in New Issue
Block a user