mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-30 16:42:34 +00:00
Compare commits
87 Commits
agent/0.85
...
0.14.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62c1a0440d | ||
|
|
ca7106c652 | ||
|
|
5e9bbd139c | ||
|
|
bd4c3ffa39 | ||
|
|
477fcb56f1 | ||
|
|
c111f282dd | ||
|
|
50c6515da5 | ||
|
|
9e0e3da617 | ||
|
|
513cf2ed8b | ||
|
|
a78212cc62 | ||
|
|
074a906af3 | ||
|
|
4fcd44e73a | ||
|
|
ec07f7c240 | ||
|
|
b8a25c6e71 | ||
|
|
edc8eb2fd8 | ||
|
|
21c7eece25 | ||
|
|
36a1cdd9bc | ||
|
|
ddf55d3c8e | ||
|
|
b76f60d419 | ||
|
|
889fcc8b50 | ||
|
|
6863675b76 | ||
|
|
c28892eba3 | ||
|
|
5e5742f87d | ||
|
|
611877e4d3 | ||
|
|
29b597dd9c | ||
|
|
840fc4bb41 | ||
|
|
ea303ba32f | ||
|
|
3bd0081753 | ||
|
|
67cde2980d | ||
|
|
e4e6d8845d | ||
|
|
67d1e6c51d | ||
|
|
f7c17bb1a5 | ||
|
|
21f16f0cb0 | ||
|
|
d1329af3bd | ||
|
|
1308d7fc35 | ||
|
|
c24fa324d2 | ||
|
|
e15ee1d28d | ||
|
|
1da02bf3ff | ||
|
|
4696519deb | ||
|
|
e321d7c8de | ||
|
|
bd7a9733fd | ||
|
|
3fd573e432 | ||
|
|
cd53c58808 | ||
|
|
c6169e1aaa | ||
|
|
b79670a79a | ||
|
|
1f28f85bdf | ||
|
|
ff4f7ca13b | ||
|
|
071e8de075 | ||
|
|
32f8e304eb | ||
|
|
6eac49e5ae | ||
|
|
53c7e101fe | ||
|
|
774046d57e | ||
|
|
438f647984 | ||
|
|
8c6ebd586d | ||
|
|
c531d91493 | ||
|
|
48d01203ef | ||
|
|
43126362c3 | ||
|
|
ef9c4ee6ab | ||
|
|
38771923ca | ||
|
|
5b060d2c0f | ||
|
|
47828f259f | ||
|
|
e614e64331 | ||
|
|
a3e336f782 | ||
|
|
7d24eba1b6 | ||
|
|
7dbdb00109 | ||
|
|
a2319d2b8a | ||
|
|
8d60d374f7 | ||
|
|
6ca316a7cc | ||
|
|
bc34e438ce | ||
|
|
7fa6fc1b70 | ||
|
|
e4ffa55d58 | ||
|
|
f746c4cd57 | ||
|
|
0499811762 | ||
|
|
ff299c1d43 | ||
|
|
5e38f130cc | ||
|
|
470710366b | ||
|
|
6acb13e6bb | ||
|
|
b496116fe3 | ||
|
|
2a0911dcfd | ||
|
|
94df00e512 | ||
|
|
3ee76637f4 | ||
|
|
e8aee19f6c | ||
|
|
74556e5f6e | ||
|
|
809d20c294 | ||
|
|
b0ae29c23a | ||
|
|
d1b6b2be87 | ||
|
|
e00181d553 |
18
.github/stale.yaml
vendored
Normal file
18
.github/stale.yaml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- cncf
|
||||
- roadmap
|
||||
- enhancement
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,3 +18,4 @@ docker/event-generator/mysqld
|
||||
docker/event-generator/httpd
|
||||
docker/event-generator/sha1sum
|
||||
docker/event-generator/vipw
|
||||
.vscode/*
|
||||
@@ -15,7 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
language: c
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env:
|
||||
- BUILD_TYPE=Debug
|
||||
- BUILD_TYPE=Release
|
||||
@@ -23,10 +24,8 @@ sudo: required
|
||||
services:
|
||||
- docker
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update
|
||||
install:
|
||||
- sudo apt-get --force-yes install g++-4.8
|
||||
- sudo apt-get install rpm linux-headers-$(uname -r) libelf-dev
|
||||
- git clone https://github.com/draios/sysdig.git ../sysdig
|
||||
- sudo apt-get install -y python-pip libvirt-dev jq dkms
|
||||
@@ -42,8 +41,6 @@ before_script:
|
||||
- export KERNELDIR=/lib/modules/$(uname -r)/build
|
||||
script:
|
||||
- set -e
|
||||
- export CC="gcc-4.8"
|
||||
- export CXX="g++-4.8"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DDRAIOS_DEBUG_FLAGS="-D_DEBUG -DNDEBUG"
|
||||
@@ -51,7 +48,7 @@ script:
|
||||
- make package
|
||||
- cp falco*.deb ../docker/local
|
||||
- cd ../docker/local
|
||||
- docker build -t sysdig/falco:test .
|
||||
- docker build -t falcosecurity/falco:test .
|
||||
- cd ../..
|
||||
- sudo test/run_regression_tests.sh $TRAVIS_BRANCH
|
||||
notifications:
|
||||
|
||||
112
CHANGELOG.md
112
CHANGELOG.md
@@ -2,6 +2,118 @@
|
||||
|
||||
This file documents all notable changes to Falco. The release numbering uses [semantic versioning](http://semver.org).
|
||||
|
||||
## v0.14.0
|
||||
|
||||
Released 2019-02-06
|
||||
|
||||
## Major Changes
|
||||
|
||||
* Rules versioning support: The falco engine and executable now have an *engine version* that represents the fields they support. Similarly, rules files have an optional *required_engine_version: NNN* object that names the minimum engine version required to read that rules file. Any time the engine adds new fields, event sources, etc, the engine version will be incremented, and any time a rules file starts using new fields, event sources, etc, the required engine version will be incremented. [[#492](https://github.com/falcosecurity/falco/pull/492)]
|
||||
|
||||
* Allow SSL for K8s audit endpoint/embedded webserver [[#471](https://github.com/falcosecurity/falco/pull/471)]
|
||||
|
||||
* Add stale issues bot that automatically flags old github issues as stale after 60 days of inactivity and closes issues after 67 days of inactivity. [[#500](https://github.com/falcosecurity/falco/pull/500)]
|
||||
|
||||
* Support bundle: When run with `--support`, falco will print a json object containing necessary information like falco version, command line, operating system information, and falco rules files contents. This could be useful when reporting issues. [[#517](https://github.com/falcosecurity/falco/pull/517)]
|
||||
|
||||
## Minor Changes
|
||||
|
||||
* Support new third-party library dependencies from open source sysdig. [[#498](https://github.com/falcosecurity/falco/pull/498)]
|
||||
|
||||
* Add CII best practices badge. [[#499](https://github.com/falcosecurity/falco/pull/499)]
|
||||
|
||||
* Fix kernel module builds when running on centos as a container by installing gcc 5 by hand instead of directly from debian/unstable. [[#501](https://github.com/falcosecurity/falco/pull/501)]
|
||||
|
||||
* Mount `/etc` when running as a container, which allows container to build kernel module/ebpf program on COS/Minikube. [[#475](https://github.com/falcosecurity/falco/pull/475)]
|
||||
|
||||
* Improved way to specify the source of generic event objects [[#480](https://github.com/falcosecurity/falco/pull/480)]
|
||||
|
||||
* Readability/clarity improvements to K8s Audit/K8s Daemonset READMEs. [[#503](https://github.com/falcosecurity/falco/pull/503)]
|
||||
|
||||
* Add additional RBAC permissions to track deployments/daemonsets/replicasets. [[#514](https://github.com/falcosecurity/falco/pull/514)]
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fix formatting of nodejs examples README [[#502](https://github.com/falcosecurity/falco/pull/502)]
|
||||
|
||||
## Rule Changes
|
||||
|
||||
* Remove FPs for `Launch Sensitive Mount Container` rule [[#509](https://github.com/falcosecurity/falco/pull/509/files)]
|
||||
|
||||
* Update Container rules/macros to use the more reliable `container.image.{repository,tag}` that always return the repository/tag of an image instead of `container.image`, which may not for some docker daemon versions. [[#513](https://github.com/falcosecurity/falco/pull/513)]
|
||||
|
||||
## v0.13.1
|
||||
|
||||
Released 2019-01-16
|
||||
|
||||
## Major Changes
|
||||
|
||||
|
||||
## Minor Changes
|
||||
|
||||
* Unbuffer outputs by default. This helps make output readable when used in environments like K8s. [[#494](https://github.com/falcosecurity/falco/pull/494)]
|
||||
|
||||
* Improved documentation for running Falco within K8s and getting K8s Audit Logging to work with Minikube and Falco as a Daemonset within K8s. [[#496](https://github.com/falcosecurity/falco/pull/496)]
|
||||
|
||||
* Fix AWS Permissions for Kubernetes Response Engine [[#465](https://github.com/falcosecurity/falco/pull/465)]
|
||||
|
||||
* Tighten compilation flags to include `-Wextra` and `-Werror` [[#479](https://github.com/falcosecurity/falco/pull/479)]
|
||||
|
||||
* Add `k8s.ns.name` to outputs when `-pk` argument is used [[#472](https://github.com/falcosecurity/falco/pull/472)]
|
||||
|
||||
* Remove kubernetes-response-engine from system:masters [[#488](https://github.com/falcosecurity/falco/pull/488)]
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Ensure `-pc`/`-pk` only apply to syscall rules and not k8s_audit rules [[#495](https://github.com/falcosecurity/falco/pull/495)]
|
||||
|
||||
* Fix a potential crash that could occur when using the falco engine and rulesets [[#468](https://github.com/falcosecurity/falco/pull/468)]
|
||||
|
||||
* Fix a regression where format output options were mistakenly removed [[#485](https://github.com/falcosecurity/falco/pull/485)]
|
||||
|
||||
## Rule Changes
|
||||
|
||||
* Fix FPs related to calico and writing files below etc [[#481](https://github.com/falcosecurity/falco/pull/481)]
|
||||
|
||||
* Fix FPs related to `apt-config`/`apt-cache`, `apk` [[#490](https://github.com/falcosecurity/falco/pull/490)]
|
||||
|
||||
* New rules `Launch Package Management Process in Container`, `Netcat Remote Code Execution in Container`, `Lauch Suspicious Network Tool in Container` look for host-level network tools like `netcat`, package management tools like `apt-get`, or network tool binaries being run in a container. [[#490](https://github.com/falcosecurity/falco/pull/490)]
|
||||
|
||||
* Fix the `inbound` and `outbound` macros so they work with sendto/recvfrom/sendmsg/recvmsg. [[#470](https://github.com/falcosecurity/falco/pull/470)]
|
||||
|
||||
* Fix FPs related to prometheus/openshift writing config below /etc. [[#470](https://github.com/falcosecurity/falco/pull/470)]
|
||||
|
||||
|
||||
## v0.13.0
|
||||
|
||||
Released 2018-11-09
|
||||
|
||||
## Major Changes
|
||||
|
||||
* **Support for K8s Audit Events** : Falco now supports [K8s Audit Events](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#audit-backends) as a second stream of events in addition to syscalls. For full details on the feature, see the [wiki](https://github.com/falcosecurity/falco/wiki/K8s-Audit-Event-Support).
|
||||
|
||||
* Transparent Config/Rule Reloading: On SIGHUP, Falco will now reload all config files/rules files and start processing new events. Allows rules changes without having to restart falco [[#457](https://github.com/falcosecurity/falco/pull/457)] [[#432](https://github.com/falcosecurity/falco/issues/432)]
|
||||
|
||||
## Minor Changes
|
||||
|
||||
* The reference integration of falco into a action engine now supports aws actions like lambda, etc. [[#460](https://github.com/falcosecurity/falco/pull/460)]
|
||||
|
||||
* Add netcat to falco docker images, which allows easier integration of program outputs to external servers [[#456](https://github.com/falcosecurity/falco/pull/456)] [[#433](https://github.com/falcosecurity/falco/issues/433)]
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Links cleanup related to the draios/falco -> falcosecurity/falco move [[#447](https://github.com/falcosecurity/falco/pull/447)]
|
||||
|
||||
* Properly load/unload kernel module when the falco service is started/stopped [[#459](https://github.com/falcosecurity/falco/pull/459)] [[#418](https://github.com/falcosecurity/falco/issues/418)]
|
||||
|
||||
## Rule Changes
|
||||
|
||||
* Better coverage (e.g. reduced FPs) for critical stack, hids systems, ufw, cloud-init, etc. [[#445](https://github.com/falcosecurity/falco/pull/445)]
|
||||
|
||||
* New rules `Launch Package Management Process in Container`, `Netcat Remote Code Execution in Container`, and `Lauch Suspicious Network Tool in Container` look for running various suspicious programs in a container. [[#461](https://github.com/falcosecurity/falco/pull/461)]
|
||||
|
||||
* Misc changes to address false positives in GKE, Istio, etc. [[#455](https://github.com/falcosecurity/falco/pull/455)] [[#439](https://github.com/falcosecurity/falco/issues/439)]
|
||||
|
||||
## v0.12.1
|
||||
|
||||
Released 2018-09-11
|
||||
|
||||
159
CMakeLists.txt
159
CMakeLists.txt
@@ -19,6 +19,8 @@ cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(falco)
|
||||
|
||||
option(BUILD_WARNINGS_AS_ERRORS "Enable building with -Wextra -Werror flags")
|
||||
|
||||
if(NOT DEFINED FALCO_VERSION)
|
||||
set(FALCO_VERSION "0.1.1dev")
|
||||
endif()
|
||||
@@ -35,8 +37,15 @@ if(NOT DRAIOS_DEBUG_FLAGS)
|
||||
set(DRAIOS_DEBUG_FLAGS "-D_DEBUG")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -ggdb --std=c++0x ${DRAIOS_FEATURE_FLAGS}")
|
||||
set(CMAKE_COMMON_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS}")
|
||||
|
||||
if(BUILD_WARNINGS_AS_ERRORS)
|
||||
set(CMAKE_SUPPRESSED_WARNINGS "-Wno-unused-parameter -Wno-missing-field-initializers -Wno-sign-compare -Wno-type-limits -Wno-implicit-fallthrough -Wno-format-truncation")
|
||||
set(CMAKE_COMMON_FLAGS "${CMAKE_COMMON_FLAGS} -Wextra -Werror ${CMAKE_SUPPRESSED_WARNINGS}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_COMMON_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "--std=c++0x ${CMAKE_COMMON_FLAGS}")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}")
|
||||
@@ -136,6 +145,32 @@ set(JSONCPP_SRC "${SYSDIG_DIR}/userspace/libsinsp/third-party/jsoncpp")
|
||||
set(JSONCPP_INCLUDE "${JSONCPP_SRC}")
|
||||
set(JSONCPP_LIB_SRC "${JSONCPP_SRC}/jsoncpp.cpp")
|
||||
|
||||
#
|
||||
# nlohmann-json
|
||||
#
|
||||
option(USE_BUNDLED_NJSON "Enable building of the bundled nlohmann-json" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(NOT USE_BUNDLED_NJSON)
|
||||
find_path(NJSON_INCLUDE json.hpp PATH_SUFFIXES nlohmann)
|
||||
if(NJSON_INCLUDE)
|
||||
message(STATUS "Found nlohmann-json: include: ${NJSON_INCLUDE}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system nlohmann-json")
|
||||
endif()
|
||||
else()
|
||||
# No distinction needed for windows. The implementation is
|
||||
# solely in json.hpp.
|
||||
set(NJSON_SRC "${PROJECT_BINARY_DIR}/njson-prefix/src/njson")
|
||||
message(STATUS "Using bundled nlohmann-json in '${NJSON_SRC}'")
|
||||
set(NJSON_INCLUDE "${NJSON_SRC}/single_include")
|
||||
ExternalProject_Add(njson
|
||||
URL "http://download.draios.com/dependencies/njson-3.3.0.tar.gz"
|
||||
URL_MD5 "e26760e848656a5da400662e6c5d999a"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
endif()
|
||||
|
||||
#
|
||||
# curses
|
||||
#
|
||||
@@ -438,6 +473,126 @@ else()
|
||||
INSTALL_COMMAND "")
|
||||
endif()
|
||||
|
||||
#
|
||||
# civetweb
|
||||
#
|
||||
option(USE_BUNDLED_CIVETWEB "Enable building of the bundled civetweb" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(NOT USE_BUNDLED_CIVETWEB)
|
||||
find_library(CIVETWEB_LIB NAMES civetweb)
|
||||
if(CIVETWEB_LIB)
|
||||
message(STATUS "Found civetweb: lib: ${CIVETWEB_LIB}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system civetweb")
|
||||
endif()
|
||||
else()
|
||||
set(CIVETWEB_SRC "${PROJECT_BINARY_DIR}/civetweb-prefix/src/civetweb/")
|
||||
set(CIVETWEB_LIB "${CIVETWEB_SRC}/install/lib/libcivetweb.a")
|
||||
set(CIVETWEB_INCLUDE_DIR "${CIVETWEB_SRC}/install/include")
|
||||
message(STATUS "Using bundled civetweb in '${CIVETWEB_SRC}'")
|
||||
set(CIVETWEB_DEPENDENCIES "")
|
||||
if(USE_BUNDLED_OPENSSL)
|
||||
list(APPEND CIVETWEB_DEPENDENCIES "openssl")
|
||||
endif()
|
||||
ExternalProject_Add(civetweb
|
||||
DEPENDS ${CIVETWEB_DEPENDENCIES}
|
||||
URL "http://s3.amazonaws.com/download.draios.com/dependencies/civetweb-1.11.tar.gz"
|
||||
URL_MD5 "b6d2175650a27924bccb747cbe084cd4"
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/lib
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/include
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
|
||||
INSTALL_COMMAND ${CMD_MAKE} install-lib install-headers PREFIX=${CIVETWEB_SRC}/install WITH_CPP=1)
|
||||
endif()
|
||||
|
||||
option(USE_BUNDLED_CARES "Enable building of the bundled c-ares" ${USE_BUNDLED_DEPS})
|
||||
if(NOT USE_BUNDLED_CARES)
|
||||
find_path(CARES_INCLUDE NAMES cares/ares.h)
|
||||
find_library(CARES_LIB NAMES libcares.a)
|
||||
if(CARES_INCLUDE AND CARES_LIB)
|
||||
message(STATUS "Found c-ares: include: ${CARES_INCLUDE}, lib: ${CARES_LIB}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system c-ares")
|
||||
endif()
|
||||
else()
|
||||
set(CARES_SRC "${PROJECT_BINARY_DIR}/c-ares-prefix/src/c-ares")
|
||||
message(STATUS "Using bundled c-ares in '${CARES_SRC}'")
|
||||
set(CARES_INCLUDE "${CARES_SRC}/target/include")
|
||||
set(CARES_LIB "${CARES_SRC}/target/lib/libcares.a")
|
||||
ExternalProject_Add(c-ares
|
||||
URL "https://download.sysdig.com/dependencies/c-ares-1.13.0.tar.gz"
|
||||
URL_MD5 "d2e010b43537794d8bedfb562ae6bba2"
|
||||
CONFIGURE_COMMAND ./configure --prefix=${CARES_SRC}/target
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${CARES_INCLUDE} ${CARES_LIB}
|
||||
INSTALL_COMMAND ${CMD_MAKE} install)
|
||||
endif()
|
||||
|
||||
option(USE_BUNDLED_PROTOBUF "Enable building of the bundled protobuf" ${USE_BUNDLED_DEPS})
|
||||
if(NOT USE_BUNDLED_PROTOBUF)
|
||||
find_program(PROTOC NAMES protoc)
|
||||
find_path(PROTOBUF_INCLUDE NAMES google/protobuf/message.h)
|
||||
find_library(PROTOBUF_LIB NAMES libprotobuf.a)
|
||||
if(PROTOC AND PROTOBUF_INCLUDE AND PROTOBUF_LIB)
|
||||
message(STATUS "Found protobuf: compiler: ${PROTOC}, include: ${PROTOBUF_INCLUDE}, lib: ${PROTOBUF_LIB}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system protobuf")
|
||||
endif()
|
||||
else()
|
||||
set(PROTOBUF_SRC "${PROJECT_BINARY_DIR}/protobuf-prefix/src/protobuf")
|
||||
message(STATUS "Using bundled protobuf in '${PROTOBUF_SRC}'")
|
||||
set(PROTOC "${PROTOBUF_SRC}/target/bin/protoc")
|
||||
set(PROTOBUF_INCLUDE "${PROTOBUF_SRC}/target/include")
|
||||
set(PROTOBUF_LIB "${PROTOBUF_SRC}/target/lib/libprotobuf.a")
|
||||
ExternalProject_Add(protobuf
|
||||
DEPENDS openssl zlib
|
||||
URL "https://github.com/google/protobuf/releases/download/v3.5.0/protobuf-cpp-3.5.0.tar.gz"
|
||||
URL_MD5 "e4ba8284a407712168593e79e6555eb2"
|
||||
# TODO what if using system zlib?
|
||||
CONFIGURE_COMMAND /usr/bin/env CPPFLAGS=-I${ZLIB_INCLUDE} LDFLAGS=-L${ZLIB_SRC} ./configure --with-zlib --prefix=${PROTOBUF_SRC}/target
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${PROTOC} ${PROTOBUF_INCLUDE} ${PROTOBUF_LIB}
|
||||
# TODO s390x support
|
||||
INSTALL_COMMAND make install)
|
||||
endif()
|
||||
|
||||
option(USE_BUNDLED_GRPC "Enable building of the bundled grpc" ${USE_BUNDLED_DEPS})
|
||||
if(NOT USE_BUNDLED_GRPC)
|
||||
find_path(GRPC_INCLUDE grpc++/impl/codegen/rpc_method.h)
|
||||
find_library(GRPC_LIB NAMES libgrpc_unsecure.a)
|
||||
find_library(GRPCPP_LIB NAMES libgrpc++_unsecure.a)
|
||||
if(GRPC_INCLUDE AND GRPC_LIB AND GRPCPP_LIB)
|
||||
message(STATUS "Found grpc: include: ${GRPC_INCLUDE}, C lib: ${GRPC_LIB}, C++ lib: ${GRPC_PP_LIB}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system grpc")
|
||||
endif()
|
||||
else()
|
||||
set(GRPC_SRC "${PROJECT_BINARY_DIR}/grpc-prefix/src/grpc")
|
||||
message(STATUS "Using bundled grpc in '${GRPC_SRC}'")
|
||||
set(GRPC_INCLUDE "${GRPC_SRC}/include")
|
||||
set(GRPC_LIB "${GRPC_SRC}/libs/opt/libgrpc_unsecure.a")
|
||||
set(GRPCPP_LIB "${GRPC_SRC}/libs/opt/libgrpc++_unsecure.a")
|
||||
|
||||
get_filename_component(PROTOC_DIR ${PROTOC} DIRECTORY)
|
||||
|
||||
ExternalProject_Add(grpc
|
||||
DEPENDS protobuf zlib c-ares
|
||||
URL "http://download.draios.com/dependencies/grpc-1.8.1.tar.gz"
|
||||
URL_MD5 "2fc42c182a0ed1b48ad77397f76bb3bc"
|
||||
CONFIGURE_COMMAND ""
|
||||
# TODO what if using system openssl, protobuf or cares?
|
||||
BUILD_COMMAND HAS_SYSTEM_ZLIB=false LDFLAGS=-static PATH=${PROTOC_DIR}:$ENV{PATH} PKG_CONFIG_PATH=${OPENSSL_BUNDLE_DIR}:${PROTOBUF_SRC}:${CARES_SRC} make grpc_cpp_plugin static_cxx static_c
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${GRPC_LIB} ${GRPCPP_LIB}
|
||||
# TODO s390x support
|
||||
# TODO what if using system zlib
|
||||
PATCH_COMMAND rm -rf third_party/zlib && ln -s ${ZLIB_SRC} third_party/zlib && wget https://download.sysdig.com/dependencies/grpc-1.1.4-Makefile.patch && patch < grpc-1.1.4-Makefile.patch
|
||||
INSTALL_COMMAND "")
|
||||
endif()
|
||||
|
||||
|
||||
install(FILES falco.yaml
|
||||
DESTINATION "${FALCO_ETC_DIR}")
|
||||
|
||||
|
||||
39
CODE_OF_CONDUCT
Normal file
39
CODE_OF_CONDUCT
Normal file
@@ -0,0 +1,39 @@
|
||||
## CNCF Community Code of Conduct v1.0
|
||||
|
||||
### Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering
|
||||
an open and welcoming community, we pledge to respect all people who contribute
|
||||
through reporting issues, posting feature requests, updating documentation,
|
||||
submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for
|
||||
everyone, regardless of level of experience, gender, gender identity and expression,
|
||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
|
||||
religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are not
|
||||
aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers
|
||||
commit themselves to fairly and consistently applying these principles to every aspect
|
||||
of managing this project. Project maintainers who do not follow or enforce the Code of
|
||||
Conduct may be permanently removed from the project team.
|
||||
|
||||
This code of conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a CNCF project maintainer, Sarah Novotny <sarahnovotny@google.com>, and/or Dan Kohn <dan@linuxfoundation.org>.
|
||||
|
||||
This Code of Conduct is adapted from the Contributor Covenant
|
||||
(http://contributor-covenant.org), version 1.2.0, available at
|
||||
http://contributor-covenant.org/version/1/2/0/
|
||||
55
GOVERNANCE
Normal file
55
GOVERNANCE
Normal file
@@ -0,0 +1,55 @@
|
||||
# Process for becoming a maintainer
|
||||
|
||||
* Express interest to the existing maintainers that you or your organization is interested in becoming a
|
||||
maintainer. Becoming a maintainer generally means that you are going to be spending substantial
|
||||
time (>25%) on Falco for the foreseeable future. You should have domain expertise and be extremely
|
||||
proficient in C++. Ultimately your goal is to become a maintainer that will represent your
|
||||
organization.
|
||||
* We will expect you to start contributing increasingly complicated PRs, under the guidance
|
||||
of the existing maintainers.
|
||||
* We may ask you to do some PRs from our backlog.
|
||||
* As you gain experience with the code base and our standards, we will ask you to do code reviews
|
||||
for incoming PRs (i.e., all maintainers are expected to shoulder a proportional share of
|
||||
community reviews).
|
||||
* After a period of approximately 2-3 months of working together and making sure we see eye to eye,
|
||||
the existing maintainers will confer and decide whether to grant maintainer status or not.
|
||||
We make no guarantees on the length of time this will take, but 2-3 months is the approximate
|
||||
goal.
|
||||
|
||||
## Maintainer responsibilities
|
||||
|
||||
* Monitor Slack (delayed response is perfectly acceptable).
|
||||
* Triage GitHub issues and perform pull request reviews for other maintainers and the community.
|
||||
* During GitHub issue triage, apply all applicable [labels](https://github.com/falcosecurity/falco/labels)
|
||||
to each new issue. Labels are extremely useful for future issue follow up. Which labels to apply
|
||||
is somewhat subjective so just use your best judgment.
|
||||
* Make sure that ongoing PRs are moving forward at the right pace or closing them.
|
||||
* Participate when called upon in the security releases. Note that although this should be a rare
|
||||
occurrence, if a serious vulnerability is found, the process may take up to several full days of
|
||||
work to implement. This reality should be taken into account when discussing time commitment
|
||||
obligations with employers.
|
||||
* In general continue to be willing to spend at least 25% of ones time working on Falco (~1.25
|
||||
business days per week).
|
||||
|
||||
## When does a maintainer lose maintainer status
|
||||
|
||||
If a maintainer is no longer interested or cannot perform the maintainer duties listed above, they
|
||||
should volunteer to be moved to emeritus status. In extreme cases this can also occur by a vote of
|
||||
the maintainers per the voting process below.
|
||||
|
||||
# Conflict resolution and voting
|
||||
|
||||
In general, we prefer that technical issues and maintainer membership are amicably worked out
|
||||
between the persons involved. If a dispute cannot be decided independently, the maintainers can be
|
||||
called in to decide an issue. If the maintainers themselves cannot decide an issue, the issue will
|
||||
be resolved by voting. The voting process is a simple majority in which each senior maintainer
|
||||
receives two votes and each normal maintainer receives one vote.
|
||||
|
||||
# Adding new projects to the falcosecurity GitHub organization
|
||||
|
||||
New projects will be added to the falcosecurity organization via GitHub issue discussion in one of the
|
||||
existing projects in the organization. Once sufficient discussion has taken place (~3-5 business
|
||||
days but depending on the volume of conversation), the maintainers of *the project where the issue
|
||||
was opened* (since different projects in the organization may have different maintainers) will
|
||||
decide whether the new project should be added. See the section above on voting if the maintainers
|
||||
cannot easily decide.
|
||||
9
MAINTAINERS
Normal file
9
MAINTAINERS
Normal file
@@ -0,0 +1,9 @@
|
||||
Current maintainers:
|
||||
@mstemm - Mark Stemm <mark.stemm@sysdig.com>
|
||||
@ldegio - Loris Degioanni <loris@sysdig.com>
|
||||
|
||||
Community Mangement:
|
||||
@mfdii - Michael Ducy <michael@sysdig.com>
|
||||
|
||||
Emeritus maintainers:
|
||||
@henridf - Henri Dubois-Ferriere <henri.dubois-ferriere@sysdig.com>
|
||||
32
README.md
32
README.md
@@ -1,19 +1,23 @@
|
||||
# Sysdig Falco
|
||||
# Falco
|
||||
|
||||
#### Latest release
|
||||
|
||||
**v0.12.1**
|
||||
Read the [change log](https://github.com/draios/falco/blob/dev/CHANGELOG.md)
|
||||
**v0.14.0**
|
||||
Read the [change log](https://github.com/falcosecurity/falco/blob/dev/CHANGELOG.md)
|
||||
|
||||
Dev Branch: [](https://travis-ci.org/falcosecurity/falco)<br />
|
||||
Master Branch: [](https://travis-ci.org/falcosecurity/falco)<br />
|
||||
CII Best Practices: [](https://bestpractices.coreinfrastructure.org/projects/2317)
|
||||
|
||||
Dev Branch: [](https://travis-ci.org/draios/falco)<br />
|
||||
Master Branch: [](https://travis-ci.org/draios/falco)
|
||||
|
||||
## Overview
|
||||
Sysdig Falco is a behavioral activity monitor designed to detect anomalous activity in your applications. Powered by sysdig’s system call capture infrastructure, falco lets you continuously monitor and detect container, application, host, and network activity... all in one place, from one source of data, with one set of rules.
|
||||
Falco is a behavioral activity monitor designed to detect anomalous activity in your applications. Powered by [sysdig’s](https://github.com/draios/sysdig) system call capture infrastructure, Falco lets you continuously monitor and detect container, application, host, and network activity... all in one place, from one source of data, with one set of rules.
|
||||
|
||||
Falco is hosted by the Cloud Native Computing Foundation (CNCF) as a sandbox level project. If you are an organization that wants to help shape the evolution of technologies that are container-packaged, dynamically-scheduled and microservices-oriented, consider joining the CNCF. For details read the [Falco CNCF project proposal](https://github.com/cncf/toc/tree/master/proposals/falco.adoc).
|
||||
|
||||
#### What kind of behaviors can Falco detect?
|
||||
|
||||
Falco can detect and alert on any behavior that involves making Linux system calls. Thanks to Sysdig's core decoding and state tracking functionality, falco alerts can be triggered by the use of specific system calls, their arguments, and by properties of the calling process. For example, you can easily detect things like:
|
||||
Falco can detect and alert on any behavior that involves making Linux system calls. Falco alerts can be triggered by the use of specific system calls, their arguments, and by properties of the calling process. For example, you can easily detect things like:
|
||||
|
||||
- A shell is run inside a container
|
||||
- A container is running in privileged mode, or is mounting a sensitive path like `/proc` from the host.
|
||||
@@ -24,18 +28,18 @@ Falco can detect and alert on any behavior that involves making Linux system cal
|
||||
|
||||
#### How Falco Compares to Other Security Tools like SELinux, Auditd, etc.
|
||||
|
||||
One of the questions we often get when we talk about Sysdig Falco is “How does it compare to other tools like SELinux, AppArmor, Auditd, etc. that also have security policies?”. We wrote a [blog post](https://sysdig.com/blog/selinux-seccomp-falco-technical-discussion/) comparing Falco to other tools.
|
||||
One of the questions we often get when we talk about Falco is “How does it compare to other tools like SELinux, AppArmor, Auditd, etc. that also have security policies?”. We wrote a [blog post](https://sysdig.com/blog/selinux-seccomp-falco-technical-discussion/) comparing Falco to other tools.
|
||||
|
||||
|
||||
Documentation
|
||||
---
|
||||
[Visit the wiki](https://github.com/draios/falco/wiki) for full documentation on falco.
|
||||
[Visit the wiki](https://github.com/falcosecurity/falco/wiki) for full documentation on falco.
|
||||
|
||||
Join the Community
|
||||
---
|
||||
* Follow us on [Twitter](https://twitter.com/sysdig) for general falco and sysdig news.
|
||||
* This is our [blog](https://sysdig.com/blog/), where you can find the latest [falco](https://sysdig.com/blog/tag/falco/) posts.
|
||||
* Join our [Public Slack](https://slack.sysdig.com) channel for sysdig and falco announcements and discussions.
|
||||
* [Website](https://falco.org) for Falco.
|
||||
* We are working on a blog for the Falco project. In the meantime you can find [Falco](https://sysdig.com/blog/tag/falco/) posts over on the Sysdig blog.
|
||||
* Join our [Public Slack](https://slack.sysdig.com) channel for open source sysdig and Falco announcements and discussions.
|
||||
|
||||
License Terms
|
||||
---
|
||||
@@ -44,7 +48,7 @@ Falco is licensed to you under the [Apache 2.0](./COPYING) open source license.
|
||||
Contributor License Agreements
|
||||
---
|
||||
### Background
|
||||
As we did for sysdig, we are formalizing the way that we accept contributions of code from the contributing community. We must now ask that contributions to falco be provided subject to the terms and conditions of a [Contributor License Agreement (CLA)](./cla). The CLA comes in two forms, applicable to contributions by individuals, or by legal entities such as corporations and their employees. We recognize that entering into a CLA with us involves real consideration on your part, and we’ve tried to make this process as clear and simple as possible.
|
||||
We are formalizing the way that we accept contributions of code from the contributing community. We must now ask that contributions to falco be provided subject to the terms and conditions of a [Contributor License Agreement (CLA)](./cla). The CLA comes in two forms, applicable to contributions by individuals, or by legal entities such as corporations and their employees. We recognize that entering into a CLA with us involves real consideration on your part, and we’ve tried to make this process as clear and simple as possible.
|
||||
|
||||
We’ve modeled our CLA off of industry standards, such as [the CLA used by Kubernetes](https://github.com/kubernetes/kubernetes/blob/master/CONTRIBUTING.md). Note that this agreement is not a transfer of copyright ownership, this simply is a license agreement for contributions, intended to clarify the intellectual property license granted with contributions from any person or entity. It is for your protection as a contributor as well as the protection of falco; it does not change your rights to use your own contributions for any other purpose.
|
||||
|
||||
@@ -75,7 +79,7 @@ falco-CLA-1.0-signed-off-by: Joe Smith <joe.smith@email.com>
|
||||
|
||||
Use a real name of a natural person who is an authorized representative of the contributing entity; pseudonyms or anonymous contributions are not allowed.
|
||||
|
||||
**Government contributions**: Employees or officers of the United States Government, must review the [Government Contributor License Agreement](https://github.com/draios/falco/blob/dev/cla/falco_govt_contributor_agreement.txt), must be an authorized representative of the contributing entity, and indicate agreement to it on behalf of the contributing entity by adding the following lines to every GIT commit message:
|
||||
**Government contributions**: Employees or officers of the United States Government, must review the [Government Contributor License Agreement](https://github.com/falcosecurity/falco/blob/dev/cla/falco_govt_contributor_agreement.txt), must be an authorized representative of the contributing entity, and indicate agreement to it on behalf of the contributing entity by adding the following lines to every GIT commit message:
|
||||
|
||||
```
|
||||
falco-CLA-1.0-contributing-govt-entity: Full Legal Name of Entity
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM debian:unstable
|
||||
|
||||
MAINTAINER Sysdig <support@sysdig.com>
|
||||
LABEL maintainer="Sysdig <support@sysdig.com>"
|
||||
|
||||
ENV FALCO_REPOSITORY dev
|
||||
|
||||
@@ -24,16 +24,31 @@ RUN apt-get update \
|
||||
dkms \
|
||||
gnupg2 \
|
||||
gcc \
|
||||
gcc-5 \
|
||||
gcc-6 \
|
||||
gdb \
|
||||
jq \
|
||||
libc6-dev \
|
||||
libelf-dev \
|
||||
llvm-7 \
|
||||
netcat \
|
||||
xz-utils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# gcc 5 is no longer included in debian unstable, but we need it to
|
||||
# build centos kernels, which are 3.x based and explicitly want a gcc
|
||||
# version 3, 4, or 5 compiler. So grab copies we've saved from debian
|
||||
# snapshots with the prefix https://snapshot.debian.org/archive/debian/20190122T000000Z.
|
||||
|
||||
RUN curl -o cpp-5_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/cpp-5_5.5.0-12_amd64.deb \
|
||||
&& curl -o gcc-5-base_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/gcc-5-base_5.5.0-12_amd64.deb \
|
||||
&& curl -o gcc-5_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/gcc-5_5.5.0-12_amd64.deb \
|
||||
&& curl -o libasan2_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libasan2_5.5.0-12_amd64.deb \
|
||||
&& curl -o libgcc-5-dev_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libgcc-5-dev_5.5.0-12_amd64.deb \
|
||||
&& curl -o libisl15_0.18-4_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libisl15_0.18-4_amd64.deb \
|
||||
&& curl -o libmpx0_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libmpx0_5.5.0-12_amd64.deb \
|
||||
&& dpkg -i cpp-5_5.5.0-12_amd64.deb gcc-5-base_5.5.0-12_amd64.deb gcc-5_5.5.0-12_amd64.deb libasan2_5.5.0-12_amd64.deb libgcc-5-dev_5.5.0-12_amd64.deb libisl15_0.18-4_amd64.deb libmpx0_5.5.0-12_amd64.deb \
|
||||
&& rm -f cpp-5_5.5.0-12_amd64.deb gcc-5-base_5.5.0-12_amd64.deb gcc-5_5.5.0-12_amd64.deb libasan2_5.5.0-12_amd64.deb libgcc-5-dev_5.5.0-12_amd64.deb libisl15_0.18-4_amd64.deb libmpx0_5.5.0-12_amd64.deb
|
||||
|
||||
# Since our base Debian image ships with GCC 7 which breaks older kernels, revert the
|
||||
# default to gcc-5.
|
||||
RUN rm -rf /usr/bin/gcc && ln -s /usr/bin/gcc-5 /usr/bin/gcc
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM debian:unstable
|
||||
|
||||
MAINTAINER Sysdig <support@sysdig.com>
|
||||
LABEL maintainer="Sysdig <support@sysdig.com>"
|
||||
|
||||
ENV FALCO_VERSION 0.1.1dev
|
||||
|
||||
@@ -24,15 +24,30 @@ RUN apt-get update \
|
||||
dkms \
|
||||
gnupg2 \
|
||||
gcc \
|
||||
gcc-5 \
|
||||
gcc-6 \
|
||||
jq \
|
||||
libc6-dev \
|
||||
libelf-dev \
|
||||
llvm-7 \
|
||||
netcat \
|
||||
xz-utils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# gcc 5 is no longer included in debian unstable, but we need it to
|
||||
# build centos kernels, which are 3.x based and explicitly want a gcc
|
||||
# version 3, 4, or 5 compiler. So grab copies we've saved from debian
|
||||
# snapshots with the prefix https://snapshot.debian.org/archive/debian/20190122T000000Z.
|
||||
|
||||
RUN curl -o cpp-5_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/cpp-5_5.5.0-12_amd64.deb \
|
||||
&& curl -o gcc-5-base_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/gcc-5-base_5.5.0-12_amd64.deb \
|
||||
&& curl -o gcc-5_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/gcc-5_5.5.0-12_amd64.deb \
|
||||
&& curl -o libasan2_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libasan2_5.5.0-12_amd64.deb \
|
||||
&& curl -o libgcc-5-dev_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libgcc-5-dev_5.5.0-12_amd64.deb \
|
||||
&& curl -o libisl15_0.18-4_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libisl15_0.18-4_amd64.deb \
|
||||
&& curl -o libmpx0_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libmpx0_5.5.0-12_amd64.deb \
|
||||
&& dpkg -i cpp-5_5.5.0-12_amd64.deb gcc-5-base_5.5.0-12_amd64.deb gcc-5_5.5.0-12_amd64.deb libasan2_5.5.0-12_amd64.deb libgcc-5-dev_5.5.0-12_amd64.deb libisl15_0.18-4_amd64.deb libmpx0_5.5.0-12_amd64.deb \
|
||||
&& rm -f cpp-5_5.5.0-12_amd64.deb gcc-5-base_5.5.0-12_amd64.deb gcc-5_5.5.0-12_amd64.deb libasan2_5.5.0-12_amd64.deb libgcc-5-dev_5.5.0-12_amd64.deb libisl15_0.18-4_amd64.deb libmpx0_5.5.0-12_amd64.deb
|
||||
|
||||
# Since our base Debian image ships with GCC 7 which breaks older kernels, revert the
|
||||
# default to gcc-5.
|
||||
RUN rm -rf /usr/bin/gcc && ln -s /usr/bin/gcc-5 /usr/bin/gcc
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM debian:unstable
|
||||
|
||||
MAINTAINER Sysdig <support@sysdig.com>
|
||||
LABEL maintainer="Sysdig <support@sysdig.com>"
|
||||
|
||||
ENV FALCO_REPOSITORY stable
|
||||
|
||||
@@ -24,15 +24,30 @@ RUN apt-get update \
|
||||
dkms \
|
||||
gnupg2 \
|
||||
gcc \
|
||||
gcc-5 \
|
||||
gcc-6 \
|
||||
jq \
|
||||
libc6-dev \
|
||||
libelf-dev \
|
||||
llvm-7 \
|
||||
netcat \
|
||||
xz-utils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# gcc 5 is no longer included in debian unstable, but we need it to
|
||||
# build centos kernels, which are 3.x based and explicitly want a gcc
|
||||
# version 3, 4, or 5 compiler. So grab copies we've saved from debian
|
||||
# snapshots with the prefix https://snapshot.debian.org/archive/debian/20190122T000000Z.
|
||||
|
||||
RUN curl -o cpp-5_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/cpp-5_5.5.0-12_amd64.deb \
|
||||
&& curl -o gcc-5-base_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/gcc-5-base_5.5.0-12_amd64.deb \
|
||||
&& curl -o gcc-5_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/gcc-5_5.5.0-12_amd64.deb \
|
||||
&& curl -o libasan2_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libasan2_5.5.0-12_amd64.deb \
|
||||
&& curl -o libgcc-5-dev_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libgcc-5-dev_5.5.0-12_amd64.deb \
|
||||
&& curl -o libisl15_0.18-4_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libisl15_0.18-4_amd64.deb \
|
||||
&& curl -o libmpx0_5.5.0-12_amd64.deb https://s3.amazonaws.com/download.draios.com/dependencies/libmpx0_5.5.0-12_amd64.deb \
|
||||
&& dpkg -i cpp-5_5.5.0-12_amd64.deb gcc-5-base_5.5.0-12_amd64.deb gcc-5_5.5.0-12_amd64.deb libasan2_5.5.0-12_amd64.deb libgcc-5-dev_5.5.0-12_amd64.deb libisl15_0.18-4_amd64.deb libmpx0_5.5.0-12_amd64.deb \
|
||||
&& rm -f cpp-5_5.5.0-12_amd64.deb gcc-5-base_5.5.0-12_amd64.deb gcc-5_5.5.0-12_amd64.deb libasan2_5.5.0-12_amd64.deb libgcc-5-dev_5.5.0-12_amd64.deb libisl15_0.18-4_amd64.deb libmpx0_5.5.0-12_amd64.deb
|
||||
|
||||
# Since our base Debian image ships with GCC 7 which breaks older kernels, revert the
|
||||
# default to gcc-5.
|
||||
RUN rm -rf /usr/bin/gcc && ln -s /usr/bin/gcc-5 /usr/bin/gcc
|
||||
|
||||
38
examples/k8s_audit_config/README.md
Normal file
38
examples/k8s_audit_config/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Introduction
|
||||
|
||||
The files in this directory can be used to configure k8s audit logging. The relevant files are:
|
||||
|
||||
* [audit-policy.yaml](./audit-policy.yaml): The k8s audit log configuration we used to create the rules in [k8s_audit_rules.yaml](../../rules/k8s_audit_rules.yaml). You may find it useful as a reference when creating your own K8s Audit Log configuration.
|
||||
* [webhook-config.yaml.in](./webhook-config.yaml.in): A (templated) webhook configuration that sends audit events to an ip associated with the falco service, port 8765. It is templated in that the *actual* ip is defined in an environment variable `FALCO_SERVICE_CLUSTERIP`, which can be plugged in using a program like `envsubst`. You may find it useful as a starting point when deciding how to route audit events to the embedded webserver within falco.
|
||||
|
||||
These files are only needed when using Minikube, which doesn't currently
|
||||
have the ability to provide an audit config/webhook config directly
|
||||
from the minikube commandline. See [this issue](https://github.com/kubernetes/minikube/issues/2741) for more details.
|
||||
|
||||
* [apiserver-config.patch.sh](./apiserver-config.patch.sh): A script that changes the configuration file `/etc/kubernetes/manifests/kube-apiserver.yaml` to add necessary config options and mounts for the kube-apiserver container that runs within the minikube vm.
|
||||
|
||||
A way to use these files with minikube to run falco and enable audit logging would be the following:
|
||||
|
||||
#### Start Minikube with Audit Logging Enabled
|
||||
|
||||
Run the following to start minikube with Audit Logging Enabled:
|
||||
|
||||
```
|
||||
minikube start --kubernetes-version v1.11.0 --mount --mount-string $PWD:/tmp/k8s_audit_config --feature-gates AdvancedAuditing=true
|
||||
```
|
||||
|
||||
#### Create a Falco DaemonSet and Supporting Accounts/Services
|
||||
|
||||
Follow the [K8s Using Daemonset](../../integrations/k8s-using-daemonset/README.md) instructions to create a falco service account, service, configmap, and daemonset.
|
||||
|
||||
#### Configure Audit Logging with a Policy and Webhook
|
||||
|
||||
Run the following commands to fill in the template file with the ClusterIP ip address you created with the `falco-service` service above, and configure audit logging to use a policy and webhook that directs the right events to the falco daemonset. Although services like `falco-service.default.svc.cluster.local` can not be resolved from the kube-apiserver container within the minikube vm (they're run as pods but not *really* a part of the cluster), the ClusterIPs associated with those services are routable.
|
||||
|
||||
```
|
||||
FALCO_SERVICE_CLUSTERIP=$(kubectl get service falco-service -o=jsonpath={.spec.clusterIP}) envsubst < webhook-config.yaml.in > webhook-config.yaml
|
||||
minikube ssh sudo bash /tmp/k8s_audit_config/apiserver-config.patch.sh
|
||||
```
|
||||
|
||||
K8s audit events will then be routed to the falco daemonset within the cluster, which you can observe via `kubectl logs -f $(kubectl get pods -l app=falco-example -o jsonpath={.items[0].metadata.name})`.
|
||||
|
||||
40
examples/k8s_audit_config/apiserver-config.patch.sh
Normal file
40
examples/k8s_audit_config/apiserver-config.patch.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
IFS=''
|
||||
|
||||
FILENAME="/etc/kubernetes/manifests/kube-apiserver.yaml"
|
||||
|
||||
if grep audit-webhook-config-file $FILENAME ; then
|
||||
echo audit-webhook patch already applied
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMPFILE="/tmp/kube-apiserver.yaml.patched"
|
||||
rm -f "$TMPFILE"
|
||||
|
||||
while read LINE
|
||||
do
|
||||
echo "$LINE" >> "$TMPFILE"
|
||||
case "$LINE" in
|
||||
*"- kube-apiserver"*)
|
||||
echo " - --audit-log-path=/tmp/k8s_audit_config/audit.log" >> "$TMPFILE"
|
||||
echo " - --audit-policy-file=/tmp/k8s_audit_config/audit-policy.yaml" >> "$TMPFILE"
|
||||
echo " - --audit-webhook-config-file=/tmp/k8s_audit_config/webhook-config.yaml" >> "$TMPFILE"
|
||||
echo " - --audit-webhook-batch-max-wait=5s" >> "$TMPFILE"
|
||||
;;
|
||||
*"volumeMounts:"*)
|
||||
echo " - mountPath: /tmp/k8s_audit_config/" >> "$TMPFILE"
|
||||
echo " name: data" >> "$TMPFILE"
|
||||
;;
|
||||
*"volumes:"*)
|
||||
echo " - hostPath:" >> "$TMPFILE"
|
||||
echo " path: /tmp/k8s_audit_config" >> "$TMPFILE"
|
||||
echo " name: data" >> "$TMPFILE"
|
||||
;;
|
||||
|
||||
esac
|
||||
done < "$FILENAME"
|
||||
|
||||
cp "$FILENAME" "/tmp/kube-apiserver.yaml.original"
|
||||
cp "$TMPFILE" "$FILENAME"
|
||||
|
||||
76
examples/k8s_audit_config/audit-policy.yaml
Normal file
76
examples/k8s_audit_config/audit-policy.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
apiVersion: audit.k8s.io/v1beta1 # This is required.
|
||||
kind: Policy
|
||||
# Don't generate audit events for all requests in RequestReceived stage.
|
||||
omitStages:
|
||||
- "RequestReceived"
|
||||
rules:
|
||||
# Log pod changes at RequestResponse level
|
||||
- level: RequestResponse
|
||||
resources:
|
||||
- group: ""
|
||||
# Resource "pods" doesn't match requests to any subresource of pods,
|
||||
# which is consistent with the RBAC policy.
|
||||
resources: ["pods", "deployments"]
|
||||
|
||||
- level: RequestResponse
|
||||
resources:
|
||||
- group: "rbac.authorization.k8s.io"
|
||||
# Resource "pods" doesn't match requests to any subresource of pods,
|
||||
# which is consistent with the RBAC policy.
|
||||
resources: ["clusterroles", "clusterrolebindings"]
|
||||
|
||||
# Log "pods/log", "pods/status" at Metadata level
|
||||
- level: Metadata
|
||||
resources:
|
||||
- group: ""
|
||||
resources: ["pods/log", "pods/status"]
|
||||
|
||||
# Don't log requests to a configmap called "controller-leader"
|
||||
- level: None
|
||||
resources:
|
||||
- group: ""
|
||||
resources: ["configmaps"]
|
||||
resourceNames: ["controller-leader"]
|
||||
|
||||
# Don't log watch requests by the "system:kube-proxy" on endpoints or services
|
||||
- level: None
|
||||
users: ["system:kube-proxy"]
|
||||
verbs: ["watch"]
|
||||
resources:
|
||||
- group: "" # core API group
|
||||
resources: ["endpoints", "services"]
|
||||
|
||||
# Don't log authenticated requests to certain non-resource URL paths.
|
||||
- level: None
|
||||
userGroups: ["system:authenticated"]
|
||||
nonResourceURLs:
|
||||
- "/api*" # Wildcard matching.
|
||||
- "/version"
|
||||
|
||||
# Log the request body of configmap changes in kube-system.
|
||||
- level: Request
|
||||
resources:
|
||||
- group: "" # core API group
|
||||
resources: ["configmaps"]
|
||||
# This rule only applies to resources in the "kube-system" namespace.
|
||||
# The empty string "" can be used to select non-namespaced resources.
|
||||
namespaces: ["kube-system"]
|
||||
|
||||
# Log configmap and secret changes in all other namespaces at the RequestResponse level.
|
||||
- level: RequestResponse
|
||||
resources:
|
||||
- group: "" # core API group
|
||||
resources: ["secrets", "configmaps"]
|
||||
|
||||
# Log all other resources in core and extensions at the Request level.
|
||||
- level: Request
|
||||
resources:
|
||||
- group: "" # core API group
|
||||
- group: "extensions" # Version of group should NOT be included.
|
||||
|
||||
# A catch-all rule to log all other requests at the Metadata level.
|
||||
- level: Metadata
|
||||
# Long-running requests like watches that fall under this rule will not
|
||||
# generate an audit event in RequestReceived.
|
||||
omitStages:
|
||||
- "RequestReceived"
|
||||
14
examples/k8s_audit_config/webhook-config.yaml.in
Normal file
14
examples/k8s_audit_config/webhook-config.yaml.in
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- name: falco
|
||||
cluster:
|
||||
server: http://$FALCO_SERVICE_CLUSTERIP:8765/k8s_audit
|
||||
contexts:
|
||||
- context:
|
||||
cluster: falco
|
||||
user: ""
|
||||
name: default-context
|
||||
current-context: default-context
|
||||
preferences: {}
|
||||
users: []
|
||||
@@ -1,4 +1,4 @@
|
||||
#Demo of falco with bash exec via poorly designed REST API.
|
||||
# Demo of falco with bash exec via poorly designed REST API.
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -42,7 +42,7 @@ This starts the following containers:
|
||||
Run the following commands to execute arbitrary commands like 'ls', 'pwd', etc:
|
||||
|
||||
```
|
||||
$ curl http://localhost:8080/api/exec/ls
|
||||
$ curl http://localhost:8181/api/exec/ls
|
||||
|
||||
demo.yml
|
||||
node_modules
|
||||
@@ -52,7 +52,7 @@ server.js
|
||||
```
|
||||
|
||||
```
|
||||
$ curl http://localhost:8080/api/exec/pwd
|
||||
$ curl http://localhost:8181/api/exec/pwd
|
||||
|
||||
.../examples/nodejs-bad-rest-api
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
express_server:
|
||||
container_name: express_server
|
||||
image: node:latest
|
||||
command: bash -c "apt-get -y update && apt-get -y install runit && npm install && runsv /usr/src/app"
|
||||
command: bash -c "apt-get -y update && apt-get -y install runit && cd /usr/src/app && npm install && runsv /usr/src/app"
|
||||
ports:
|
||||
- "8181:8181"
|
||||
volumes:
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"name": "bad-rest-api",
|
||||
"main": "server.js",
|
||||
"dependencies": {
|
||||
"express": "~4.0.0"
|
||||
"express": "~4.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
23
falco.yaml
23
falco.yaml
@@ -31,6 +31,7 @@
|
||||
rules_file:
|
||||
- /etc/falco/falco_rules.yaml
|
||||
- /etc/falco/falco_rules.local.yaml
|
||||
- /etc/falco/k8s_audit_rules.yaml
|
||||
- /etc/falco/rules.d
|
||||
|
||||
# Whether to output events in json or text
|
||||
@@ -59,8 +60,8 @@ log_level: info
|
||||
priority: debug
|
||||
|
||||
# Whether or not output to any of the output channels below is
|
||||
# buffered. Defaults to true
|
||||
buffered_outputs: true
|
||||
# buffered. Defaults to false
|
||||
buffered_outputs: false
|
||||
|
||||
# A throttling mechanism implemented as a token bucket limits the
|
||||
# rate of falco notifications. This throttling is controlled by the following configuration
|
||||
@@ -100,6 +101,24 @@ file_output:
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
# Falco contains an embedded webserver that can be used to accept K8s
|
||||
# Audit Events. These config options control the behavior of that
|
||||
# webserver. (By default, the webserver is disabled).
|
||||
#
|
||||
# The ssl_certificate is a combination SSL Certificate and corresponding
|
||||
# key contained in a single file. You can generate a key/cert as follows:
|
||||
#
|
||||
# $ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
|
||||
# $ cat certificate.pem key.pem > falco.pem
|
||||
# $ sudo cp falco.pem /etc/falco/falco.pem
|
||||
|
||||
webserver:
|
||||
enabled: true
|
||||
listen_port: 8765
|
||||
k8s_audit_endpoint: /k8s_audit
|
||||
ssl_enabled: false
|
||||
ssl_certificate: /etc/falco/falco.pem
|
||||
|
||||
# Possible additional things you might want to do with program output:
|
||||
# - send to a slack webhook:
|
||||
# program: "jq '{text: .output}' | curl -d @- -X POST https://hooks.slack.com/services/XXX"
|
||||
|
||||
@@ -4,7 +4,7 @@ This directory gives you the required YAML files to stand up Sysdig Falco on Kub
|
||||
|
||||
The two options are provided to deploy a Daemon Set:
|
||||
- `k8s-with-rbac` - This directory provides a definition to deploy a Daemon Set on Kubernetes with RBAC enabled.
|
||||
- `k8s-without-rbac` - This directory provides a definition to deploy a Daemon Set on Kubernetes without RBAC enabled.
|
||||
- `k8s-without-rbac` - This directory provides a definition to deploy a Daemon Set on Kubernetes without RBAC enabled. **This method is deprecated in favor of RBAC-based installs, and won't be updated going forward.**
|
||||
|
||||
Also provided:
|
||||
- `falco-event-generator-deployment.yaml` - A Kubernetes Deployment to generate sample events. This is useful for testing, but note it will generate a large number of events.
|
||||
@@ -21,11 +21,20 @@ clusterrolebinding "falco-cluster-role-binding" created
|
||||
k8s-using-daemonset$
|
||||
```
|
||||
|
||||
The Daemon Set also relies on a Kubernetes ConfigMap to store the Falco configuration and make the configuration available to the Falco Pods. This allows you to manage custom configuration without rebuilding and redeploying the underlying Pods. In order to create the ConfigMap you'll need to first need to copy the required configuration from their location in this GitHub repo to the `k8s-with-rbac/falco-config/` directory. Any modification of the configuration should be performed on these copies rather than the original files.
|
||||
We also create a service that allows other services to reach the embedded webserver in falco, which listens on https port 8765:
|
||||
|
||||
```
|
||||
k8s-using-daemonset$ kubectl create -f k8s-with-rbac/falco-service.yaml
|
||||
service/falco-service created
|
||||
k8s-using-daemonset$
|
||||
```
|
||||
|
||||
The Daemon Set also relies on a Kubernetes ConfigMap to store the Falco configuration and make the configuration available to the Falco Pods. This allows you to manage custom configuration without rebuilding and redeploying the underlying Pods. In order to create the ConfigMap you'll need to first need to copy the required configuration from their location in this GitHub repo to the `k8s-with-rbac/falco-config/` directory (please note that you will need to create the /falco-config directory). Any modification of the configuration should be performed on these copies rather than the original files.
|
||||
|
||||
```
|
||||
k8s-using-daemonset$ cp ../../falco.yaml k8s-with-rbac/falco-config/
|
||||
k8s-using-daemonset$ cp ../../rules/falco_rules.* k8s-with-rbac/falco-config/
|
||||
k8s-using-daemonset$ cp ../../rules/k8s_audit_rules.yaml k8s-with-rbac/falco-config/
|
||||
```
|
||||
|
||||
If you want to send Falco alerts to a Slack channel, you'll want to modify the `falco.yaml` file to point to your Slack webhook. For more information on getting a webhook URL for your Slack team, refer to the [Slack documentation](https://api.slack.com/incoming-webhooks). Add the below to the bottom of the `falco.yaml` config file you just copied to enable Slack messages.
|
||||
@@ -54,7 +63,7 @@ k8s-using-daemonset$
|
||||
```
|
||||
|
||||
|
||||
## Deploying to Kubernetes without RBAC enabled
|
||||
## Deploying to Kubernetes without RBAC enabled (**Deprecated**)
|
||||
|
||||
If you are running Kubernetes with Legacy Authorization enabled, you can use `kubectl` to deploy the Daemon Set provided in the `k8s-without-rbac` directory. The example provides the ability to post messages to a Slack channel via a webhook. For more information on getting a webhook URL for your Slack team, refer to the [Slack documentation](https://api.slack.com/incoming-webhooks). Modify the [`args`](https://github.com/draios/falco/blob/dev/examples/k8s-using-daemonset/falco-daemonset.yaml#L21) passed to the Falco container to point to the appropriate URL for your webhook.
|
||||
|
||||
|
||||
@@ -2,14 +2,20 @@ apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: falco-account
|
||||
labels:
|
||||
app: falco-example
|
||||
role: security
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: falco-cluster-role
|
||||
labels:
|
||||
app: falco-example
|
||||
role: security
|
||||
rules:
|
||||
- apiGroups: ["extensions",""]
|
||||
resources: ["nodes","namespaces","pods","replicationcontrollers","services","events","configmaps"]
|
||||
resources: ["nodes","namespaces","pods","replicationcontrollers","replicasets","services","daemonsets","deployments","events","configmaps"]
|
||||
verbs: ["get","list","watch"]
|
||||
- nonResourceURLs: ["/healthz", "/healthz/*"]
|
||||
verbs: ["get"]
|
||||
@@ -19,6 +25,9 @@ apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: falco-cluster-role-binding
|
||||
namespace: default
|
||||
labels:
|
||||
app: falco-example
|
||||
role: security
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: falco-account
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: falco
|
||||
name: falco-daemonset
|
||||
labels:
|
||||
name: falco-daemonset
|
||||
app: demo
|
||||
app: falco-example
|
||||
role: security
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: falco
|
||||
app: demo
|
||||
app: falco-example
|
||||
role: security
|
||||
spec:
|
||||
serviceAccount: falco-account
|
||||
containers:
|
||||
- name: falco
|
||||
image: sysdig/falco:latest
|
||||
image: falcosecurity/falco:latest
|
||||
securityContext:
|
||||
privileged: true
|
||||
# Uncomment the 3 lines below to enable eBPF support for Falco.
|
||||
# This allows Falco to run on Google COS.
|
||||
# Leave blank for the default probe location, or set to the path
|
||||
# of a precompiled probe.
|
||||
# env:
|
||||
# - name: SYSDIG_BPF_PROBE
|
||||
# value: ""
|
||||
args: [ "/usr/bin/falco", "-K", "/var/run/secrets/kubernetes.io/serviceaccount/token", "-k", "https://kubernetes.default", "-pk"]
|
||||
volumeMounts:
|
||||
- mountPath: /host/var/run/docker.sock
|
||||
@@ -37,6 +43,9 @@ spec:
|
||||
- mountPath: /host/usr
|
||||
name: usr-fs
|
||||
readOnly: true
|
||||
- mountPath: /host/etc/
|
||||
name: etc-fs
|
||||
readOnly: true
|
||||
- mountPath: /etc/falco
|
||||
name: falco-config
|
||||
volumes:
|
||||
@@ -58,6 +67,9 @@ spec:
|
||||
- name: usr-fs
|
||||
hostPath:
|
||||
path: /usr
|
||||
- name: etc-fs
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: falco-config
|
||||
configMap:
|
||||
name: falco-config
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: falco-service
|
||||
labels:
|
||||
app: falco-example
|
||||
role: security
|
||||
spec:
|
||||
selector:
|
||||
app: falco-example
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8765
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: falco
|
||||
image: sysdig/falco:latest
|
||||
image: falcosecurity/falco:latest
|
||||
securityContext:
|
||||
privileged: true
|
||||
args: [ "/usr/bin/falco", "-K", "/var/run/secrets/kubernetes.io/serviceaccount/token", "-k", "https://kubernetes.default", "-pk", "-o", "json_output=true", "-o", "program_output.enabled=true", "-o", "program_output.program=jq '{text: .output}' | curl -d @- -X POST https://hooks.slack.com/services/see_your_slack_team/apps_settings_for/a_webhook_url"]
|
||||
|
||||
4
integrations/kubernetes-response-engine/deployment/aws/.gitignore
vendored
Normal file
4
integrations/kubernetes-response-engine/deployment/aws/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.terraform/*
|
||||
.terraform.*
|
||||
terraform.*
|
||||
aws-auth-patch.yml
|
||||
@@ -0,0 +1,17 @@
|
||||
deploy: rbac create configure
|
||||
|
||||
rbac:
|
||||
kubectl apply -f cluster-role.yaml
|
||||
kubectl apply -f cluster-role-binding.yaml
|
||||
|
||||
create:
|
||||
terraform apply -auto-approve
|
||||
|
||||
configure:
|
||||
kubectl get -n kube-system configmap/aws-auth -o yaml | awk "/mapRoles: \|/{print;print \"$(shell terraform output patch_for_aws_auth)\";next}1" > aws-auth-patch.yml
|
||||
kubectl -n kube-system replace -f aws-auth-patch.yml
|
||||
|
||||
clean:
|
||||
terraform destroy -force
|
||||
kubectl delete -f cluster-role-binding.yaml
|
||||
kubectl delete -f cluster-role.yaml
|
||||
@@ -0,0 +1,23 @@
|
||||
# Terraform manifests for Kubernetes Response Engine running on AWS
|
||||
|
||||
In this directory are the Terraform manifests for creating required infrasturcture
|
||||
for the Kubernetes Response Engine running with AWS technology: SNS for messaging
|
||||
and Lambda for executing the playbooks.
|
||||
|
||||
## Deploy
|
||||
|
||||
For creating the resources, just run default Makefile target:
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
This will ask for an IAM user which creates the bridge between EKS rbac and AWS IAM.
|
||||
|
||||
## Clean
|
||||
|
||||
You can clean IAM roles and SNS topics with:
|
||||
|
||||
```
|
||||
make clean
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: kubernetes-response-engine-cluster-role-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: kubernetes-response-engine-cluster-role
|
||||
subjects:
|
||||
- kind: User
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
name: kubernetes-response-engine
|
||||
@@ -0,0 +1,25 @@
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: kubernetes-response-engine-cluster-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- delete
|
||||
- list
|
||||
- patch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- nodes
|
||||
verbs:
|
||||
- patch
|
||||
- apiGroups:
|
||||
- batch
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- create
|
||||
@@ -0,0 +1,29 @@
|
||||
resource "aws_iam_user" "kubernetes-response-engine-user" {
|
||||
name = "kubernetes_response_engine"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "iam-for-lambda" {
|
||||
name = "iam_for_lambda"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": "lambda.amazonaws.com",
|
||||
"AWS": "${aws_iam_user.kubernetes-response-engine-user.arn}"
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "iam-for-lambda" {
|
||||
policy_arn = "arn:aws:iam::aws:policy/CloudWatchFullAccess"
|
||||
role = "${aws_iam_role.iam-for-lambda.name}"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
locals {
|
||||
patch_for_aws_auth = <<CONFIGMAPAWSAUTH
|
||||
- rolearn: ${aws_iam_role.iam-for-lambda.arn}\n
|
||||
username: kubernetes-response-engine
|
||||
CONFIGMAPAWSAUTH
|
||||
}
|
||||
|
||||
output "patch_for_aws_auth" {
|
||||
value = "${local.patch_for_aws_auth}"
|
||||
}
|
||||
|
||||
output "iam_for_lambda" {
|
||||
value = "${aws_iam_role.iam-for-lambda.arn}"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
resource "aws_sns_topic" "falco-alerts" {
|
||||
name = "falco-alerts"
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
deploy:
|
||||
kubectl apply -f nats/
|
||||
kubectl apply -f kubeless/
|
||||
kubectl apply -f network-policy.yaml
|
||||
kubectl apply -f .
|
||||
|
||||
clean:
|
||||
kubectl delete -f kubeless/
|
||||
kubectl delete -f nats/
|
||||
kubectl delete -f network-policy.yaml
|
||||
kubectl delete -f .
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: kubernetes-response-engine-cluster-role-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: kubernetes-response-engine-cluster-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: default
|
||||
@@ -0,0 +1,25 @@
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: kubernetes-response-engine-cluster-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- delete
|
||||
- list
|
||||
- patch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- nodes
|
||||
verbs:
|
||||
- patch
|
||||
- apiGroups:
|
||||
- batch
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- create
|
||||
@@ -125,7 +125,6 @@ subjects:
|
||||
namespace: kubeless
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
description: Kubernetes Native Serverless Framework
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: functions.kubeless.io
|
||||
@@ -139,7 +138,6 @@ spec:
|
||||
version: v1beta1
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
description: CRD object for HTTP trigger type
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: httptriggers.kubeless.io
|
||||
@@ -153,7 +151,6 @@ spec:
|
||||
version: v1beta1
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
description: CRD object for HTTP trigger type
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: cronjobtriggers.kubeless.io
|
||||
@@ -38,7 +38,6 @@ subjects:
|
||||
namespace: kubeless
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
description: CRD object for NATS trigger type
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: natstriggers.kubeless.io
|
||||
1
integrations/kubernetes-response-engine/falco-sns/.gitignore
vendored
Normal file
1
integrations/kubernetes-response-engine/falco-sns/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
falco-sns
|
||||
@@ -0,0 +1,8 @@
|
||||
FROM alpine:latest
|
||||
MAINTAINER Néstor Salceda<nestor.salceda@sysdig.com>
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
COPY ./falco-sns /bin/
|
||||
|
||||
CMD ["/bin/falco-sns"]
|
||||
12
integrations/kubernetes-response-engine/falco-sns/Makefile
Normal file
12
integrations/kubernetes-response-engine/falco-sns/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
build:
|
||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-s" -o falco-sns main.go
|
||||
|
||||
deps:
|
||||
go get -u github.com/aws/aws-sdk-go/
|
||||
|
||||
clean:
|
||||
rm falco-sns
|
||||
|
||||
docker: build
|
||||
docker build -t sysdig/falco-sns .
|
||||
docker push sysdig/falco-sns
|
||||
26
integrations/kubernetes-response-engine/falco-sns/README.md
Normal file
26
integrations/kubernetes-response-engine/falco-sns/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# SNS output for Sysdig Falco
|
||||
|
||||
As Falco does not support AWS SNS output natively, we have created this small
|
||||
golang utility wich reads Falco alerts from a named pipe and sends them to a
|
||||
SNS topic.
|
||||
|
||||
This utility is designed to being run in a sidecar container in the same
|
||||
Pod as Falco.
|
||||
|
||||
## Configuration
|
||||
|
||||
You have a [complete Kubernetes manifest available](https://github.com/draios/falco/tree/kubernetes-response-engine/deployment/falco/falco-daemonset.yaml) for future reading.
|
||||
|
||||
Take a look at sidecar container and to the initContainers directive which
|
||||
craetes the shared pipe between containers.
|
||||
|
||||
### Container image
|
||||
|
||||
You have this adapter available as a container image. Its name is *sysdig/falco-sns*.
|
||||
|
||||
### Parameters Reference
|
||||
|
||||
* -t: Specifies the ARN SNS topic where message will be published.
|
||||
|
||||
* -f: Specifies the named pipe path where Falco publishes its alerts. By default
|
||||
is: */var/run/falco/nats*
|
||||
101
integrations/kubernetes-response-engine/falco-sns/main.go
Normal file
101
integrations/kubernetes-response-engine/falco-sns/main.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2012-2018 The Sysdig Tech Marketing Team
|
||||
// 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/sns"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var topic = flag.String("t", "", "The AWS SNS topic ARN")
|
||||
var pipePath = flag.String("f", "/var/run/falco/nats", "The named pipe path")
|
||||
|
||||
log.SetFlags(0)
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
||||
session, err := session.NewSession(&aws.Config{Region: aws.String(os.Getenv("AWS_DEFAULT_REGION"))})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
svc := sns.New(session)
|
||||
|
||||
pipe, err := os.OpenFile(*pipePath, os.O_RDONLY, 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Printf("Opened pipe %s", *pipePath)
|
||||
|
||||
reader := bufio.NewReader(pipe)
|
||||
scanner := bufio.NewScanner(reader)
|
||||
|
||||
log.Printf("Scanning %s", *pipePath)
|
||||
|
||||
for scanner.Scan() {
|
||||
msg := []byte(scanner.Text())
|
||||
alert := parseAlert(msg)
|
||||
|
||||
params := &sns.PublishInput{
|
||||
Message: aws.String(string(msg)),
|
||||
MessageAttributes: map[string]*sns.MessageAttributeValue{
|
||||
"priority": &sns.MessageAttributeValue{
|
||||
DataType: aws.String("String"),
|
||||
StringValue: aws.String(alert.Priority),
|
||||
},
|
||||
"rule": &sns.MessageAttributeValue{
|
||||
DataType: aws.String("String"),
|
||||
StringValue: aws.String(alert.Rule),
|
||||
},
|
||||
},
|
||||
TopicArn: aws.String(*topic),
|
||||
}
|
||||
|
||||
_, err := svc.Publish(params)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
} else {
|
||||
log.Printf("Published [%s] : '%s'\n", *topic, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
log.Fatalf("Usage: falco-sns -t topic <subject> <msg> \n")
|
||||
}
|
||||
|
||||
type parsedAlert struct {
|
||||
Priority string `json:"priority"`
|
||||
Rule string `json:"rule"`
|
||||
}
|
||||
|
||||
func parseAlert(alert []byte) *parsedAlert {
|
||||
var result parsedAlert
|
||||
err := json.Unmarshal(alert, &result)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return &result
|
||||
}
|
||||
@@ -8,6 +8,8 @@ mamba = "*"
|
||||
expects = "*"
|
||||
doublex = "*"
|
||||
doublex-expects = "==0.7.0rc2"
|
||||
six = "*"
|
||||
playbooks = {path = "."}
|
||||
|
||||
[packages]
|
||||
kubernetes = "*"
|
||||
@@ -16,4 +18,4 @@ requests = "*"
|
||||
maya = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
python_version = "*"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "00ca5a9cb1f462d534a06bca990e987e75a05b7baf6ba5ddac529f03312135e6"
|
||||
"sha256": "ee8fff436e311a11069488c3d0955fef8cc3b4dd0d42ef8515e2e5858448623b"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.6"
|
||||
"python_version": "*"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
@@ -16,19 +16,70 @@
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"adal": {
|
||||
"hashes": [
|
||||
"sha256:ba52913c38d76b4a4d88eaab41a5763d056ab6d073f106e0605b051ab930f5c1",
|
||||
"sha256:bf79392b8e9e5e82aa6acac3835ba58bbac0ccf7e15befa215863f83d5f6a007"
|
||||
],
|
||||
"version": "==1.2.0"
|
||||
},
|
||||
"asn1crypto": {
|
||||
"hashes": [
|
||||
"sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
|
||||
"sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
|
||||
],
|
||||
"version": "==0.24.0"
|
||||
},
|
||||
"cachetools": {
|
||||
"hashes": [
|
||||
"sha256:90f1d559512fc073483fe573ef5ceb39bf6ad3d39edc98dc55178a2b2b176fa3",
|
||||
"sha256:d1c398969c478d336f767ba02040fa22617333293fb0b8968e79b16028dfee35"
|
||||
"sha256:0a258d82933a1dd18cb540aca4ac5d5690731e24d1239a08577b814998f49785",
|
||||
"sha256:4621965b0d9d4c82a79a29edbad19946f5e7702df4afae7d1ed2df951559a8cc"
|
||||
],
|
||||
"version": "==2.1.0"
|
||||
"version": "==3.0.0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
|
||||
"sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
|
||||
"sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c",
|
||||
"sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a"
|
||||
],
|
||||
"version": "==2018.4.16"
|
||||
"version": "==2018.10.15"
|
||||
},
|
||||
"cffi": {
|
||||
"hashes": [
|
||||
"sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743",
|
||||
"sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef",
|
||||
"sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50",
|
||||
"sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f",
|
||||
"sha256:3bb6bd7266598f318063e584378b8e27c67de998a43362e8fce664c54ee52d30",
|
||||
"sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93",
|
||||
"sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257",
|
||||
"sha256:495c5c2d43bf6cebe0178eb3e88f9c4aa48d8934aa6e3cddb865c058da76756b",
|
||||
"sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3",
|
||||
"sha256:57b2533356cb2d8fac1555815929f7f5f14d68ac77b085d2326b571310f34f6e",
|
||||
"sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc",
|
||||
"sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04",
|
||||
"sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6",
|
||||
"sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359",
|
||||
"sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596",
|
||||
"sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b",
|
||||
"sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd",
|
||||
"sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95",
|
||||
"sha256:a6a5cb8809091ec9ac03edde9304b3ad82ad4466333432b16d78ef40e0cce0d5",
|
||||
"sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e",
|
||||
"sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6",
|
||||
"sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca",
|
||||
"sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31",
|
||||
"sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1",
|
||||
"sha256:ca1bd81f40adc59011f58159e4aa6445fc585a32bb8ac9badf7a2c1aa23822f2",
|
||||
"sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085",
|
||||
"sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801",
|
||||
"sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4",
|
||||
"sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184",
|
||||
"sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917",
|
||||
"sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f",
|
||||
"sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb"
|
||||
],
|
||||
"version": "==1.11.5"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
@@ -37,6 +88,30 @@
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"cryptography": {
|
||||
"hashes": [
|
||||
"sha256:02602e1672b62e803e08617ec286041cc453e8d43f093a5f4162095506bc0beb",
|
||||
"sha256:10b48e848e1edb93c1d3b797c83c72b4c387ab0eb4330aaa26da8049a6cbede0",
|
||||
"sha256:17db09db9d7c5de130023657be42689d1a5f60502a14f6f745f6f65a6b8195c0",
|
||||
"sha256:227da3a896df1106b1a69b1e319dce218fa04395e8cc78be7e31ca94c21254bc",
|
||||
"sha256:2cbaa03ac677db6c821dac3f4cdfd1461a32d0615847eedbb0df54bb7802e1f7",
|
||||
"sha256:31db8febfc768e4b4bd826750a70c79c99ea423f4697d1dab764eb9f9f849519",
|
||||
"sha256:4a510d268e55e2e067715d728e4ca6cd26a8e9f1f3d174faf88e6f2cb6b6c395",
|
||||
"sha256:6a88d9004310a198c474d8a822ee96a6dd6c01efe66facdf17cb692512ae5bc0",
|
||||
"sha256:76936ec70a9b72eb8c58314c38c55a0336a2b36de0c7ee8fb874a4547cadbd39",
|
||||
"sha256:7e3b4aecc4040928efa8a7cdaf074e868af32c58ffc9bb77e7bf2c1a16783286",
|
||||
"sha256:8168bcb08403ef144ff1fb880d416f49e2728101d02aaadfe9645883222c0aa5",
|
||||
"sha256:8229ceb79a1792823d87779959184a1bf95768e9248c93ae9f97c7a2f60376a1",
|
||||
"sha256:8a19e9f2fe69f6a44a5c156968d9fc8df56d09798d0c6a34ccc373bb186cee86",
|
||||
"sha256:8d10113ca826a4c29d5b85b2c4e045ffa8bad74fb525ee0eceb1d38d4c70dfd6",
|
||||
"sha256:be495b8ec5a939a7605274b6e59fbc35e76f5ad814ae010eb679529671c9e119",
|
||||
"sha256:dc2d3f3b1548f4d11786616cf0f4415e25b0fbecb8a1d2cd8c07568f13fdde38",
|
||||
"sha256:e4aecdd9d5a3d06c337894c9a6e2961898d3f64fe54ca920a72234a3de0f9cb3",
|
||||
"sha256:e79ab4485b99eacb2166f3212218dd858258f374855e1568f728462b0e6ee0d9",
|
||||
"sha256:f995d3667301e1754c57b04e0bae6f0fa9d710697a9f8d6712e8cca02550910f"
|
||||
],
|
||||
"version": "==2.3.1"
|
||||
},
|
||||
"dateparser": {
|
||||
"hashes": [
|
||||
"sha256:940828183c937bcec530753211b70f673c0a9aab831e43273489b310538dff86",
|
||||
@@ -50,10 +125,10 @@
|
||||
},
|
||||
"google-auth": {
|
||||
"hashes": [
|
||||
"sha256:1745c9066f698eac3da99cef082914495fb71bc09597ba7626efbbb64c4acc57",
|
||||
"sha256:82a34e1a59ad35f01484d283d2a36b7a24c8c404a03a71b3afddd0a4d31e169f"
|
||||
"sha256:9ca363facbf2622d9ba828017536ccca2e0f58bd15e659b52f312172f8815530",
|
||||
"sha256:a4cf9e803f2176b5de442763bd339b313d3f1ed3002e3e1eb6eec1d7c9bbc9b4"
|
||||
],
|
||||
"version": "==1.5.0"
|
||||
"version": "==1.5.1"
|
||||
},
|
||||
"humanize": {
|
||||
"hashes": [
|
||||
@@ -68,20 +143,13 @@
|
||||
],
|
||||
"version": "==2.7"
|
||||
},
|
||||
"ipaddress": {
|
||||
"hashes": [
|
||||
"sha256:64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794",
|
||||
"sha256:b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c"
|
||||
],
|
||||
"version": "==1.0.22"
|
||||
},
|
||||
"kubernetes": {
|
||||
"hashes": [
|
||||
"sha256:b370ab4abd925309db69a14a4723487948e9a83de60ca92782ec14992b741c89",
|
||||
"sha256:c80dcf531deca2037105df09c933355c80830ffbf9e496b5e6a3967ac6809ef7"
|
||||
"sha256:0cc9ce02d838da660efa0a67270b4b7d47e6beb8889673cd45c86f897e2d6821",
|
||||
"sha256:54f8e7bb1dd9a55cf416dff76a63c4ae441764280942d9913f2243676f29d02c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.0.0"
|
||||
"version": "==8.0.0"
|
||||
},
|
||||
"maya": {
|
||||
"hashes": [
|
||||
@@ -115,120 +183,103 @@
|
||||
},
|
||||
"pyasn1": {
|
||||
"hashes": [
|
||||
"sha256:2f57960dc7a2820ea5a1782b872d974b639aa3b448ac6628d1ecc5d0fe3986f2",
|
||||
"sha256:3651774ca1c9726307560792877db747ba5e8a844ea1a41feb7670b319800ab3",
|
||||
"sha256:602fda674355b4701acd7741b2be5ac188056594bf1eecf690816d944e52905e",
|
||||
"sha256:8fb265066eac1d3bb5015c6988981b009ccefd294008ff7973ed5f64335b0f2d",
|
||||
"sha256:9334cb427609d2b1e195bb1e251f99636f817d7e3e1dffa150cb3365188fb992",
|
||||
"sha256:9a15cc13ff6bf5ed29ac936ca941400be050dff19630d6cd1df3fb978ef4c5ad",
|
||||
"sha256:a66dcda18dbf6e4663bde70eb30af3fc4fe1acb2d14c4867a861681887a5f9a2",
|
||||
"sha256:ba77f1e8d7d58abc42bfeddd217b545fdab4c1eeb50fd37c2219810ad56303bf",
|
||||
"sha256:cdc8eb2eaafb56de66786afa6809cd9db2df1b3b595dcb25aa5b9dc61189d40a",
|
||||
"sha256:d01fbba900c80b42af5c3fe1a999acf61e27bf0e452e0f1ef4619065e57622da",
|
||||
"sha256:f281bf11fe204f05859225ec2e9da7a7c140b65deccd8a4eb0bc75d0bd6949e0",
|
||||
"sha256:fb81622d8f3509f0026b0683fe90fea27be7284d3826a5f2edf97f69151ab0fc"
|
||||
"sha256:b9d3abc5031e61927c82d4d96c1cec1e55676c1a991623cfed28faea73cdd7ca",
|
||||
"sha256:f58f2a3d12fd754aa123e9fa74fb7345333000a035f3921dbdaa08597aa53137"
|
||||
],
|
||||
"version": "==0.4.3"
|
||||
"version": "==0.4.4"
|
||||
},
|
||||
"pyasn1-modules": {
|
||||
"hashes": [
|
||||
"sha256:041e9fbafac548d095f5b6c3b328b80792f006196e15a232b731a83c93d59493",
|
||||
"sha256:0cdca76a68dcb701fff58c397de0ef9922b472b1cb3ea9695ca19d03f1869787",
|
||||
"sha256:0cea139045c38f84abaa803bcb4b5e8775ea12a42af10019d942f227acc426c3",
|
||||
"sha256:0f2e50d20bc670be170966638fa0ae603f0bc9ed6ebe8e97a6d1d4cef30cc889",
|
||||
"sha256:47fb6757ab78fe966e7c58b2030b546854f78416d653163f0ce9290cf2278e8b",
|
||||
"sha256:598a6004ec26a8ab40a39ea955068cf2a3949ad9c0030da970f2e1ca4c9f1cc9",
|
||||
"sha256:72fd8b0c11191da088147c6e4678ec53e573923ecf60b57eeac9e97433e09fc2",
|
||||
"sha256:854700bbdd01394e2ada9c1bfbd0ed9f5d0c551350dbbd023e88b11d2771ae06",
|
||||
"sha256:af00ea8f2022b6287dc375b2c70f31ab5af83989fc6fe9eacd4976ce26cd7ccc",
|
||||
"sha256:b1f395cae2d669e0830cb023aa86f9f283b7a9aa32317d7f80d8e78aa2745812",
|
||||
"sha256:c6747146e95d2b14cc2a8399b2b0bde3f93778f8f9ec704690d2b589c376c137",
|
||||
"sha256:f53fe5bcebdf318f51399b250fe8325ef3a26d927f012cc0c8e0f9e9af7f9deb"
|
||||
"sha256:a0cf3e1842e7c60fde97cb22d275eb6f9524f5c5250489e292529de841417547",
|
||||
"sha256:a38a8811ea784c0136abfdba73963876328f66172db21a05a82f9515909bfb4e"
|
||||
],
|
||||
"version": "==0.2.1"
|
||||
"version": "==0.2.2"
|
||||
},
|
||||
"pycparser": {
|
||||
"hashes": [
|
||||
"sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
|
||||
],
|
||||
"version": "==2.19"
|
||||
},
|
||||
"pyjwt": {
|
||||
"hashes": [
|
||||
"sha256:30b1380ff43b55441283cc2b2676b755cca45693ae3097325dea01f3d110628c",
|
||||
"sha256:4ee413b357d53fd3fb44704577afac88e72e878716116270d722723d65b42176"
|
||||
],
|
||||
"version": "==1.6.4"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0",
|
||||
"sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8"
|
||||
"sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93",
|
||||
"sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02"
|
||||
],
|
||||
"version": "==2.7.3"
|
||||
"version": "==2.7.5"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555",
|
||||
"sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749"
|
||||
"sha256:31cb35c89bd7d333cd32c5f278fca91b523b0834369e757f4c5641ea252236ca",
|
||||
"sha256:8e0f8568c118d3077b46be7d654cc8167fa916092e28320cde048e54bfc9f1e6"
|
||||
],
|
||||
"version": "==2018.4"
|
||||
"version": "==2018.7"
|
||||
},
|
||||
"pytzdata": {
|
||||
"hashes": [
|
||||
"sha256:1d936da41ee06216d89fdc7ead1ee9a5da2811a8787515a976b646e110c3f622",
|
||||
"sha256:e4ef42e82b0b493c5849eed98b5ab49d6767caf982127e9a33167f1153b36cc5"
|
||||
"sha256:10c74b0cfc51a9269031f86ecd11096c9c6a141f5bb15a3b8a88f9979f6361e2",
|
||||
"sha256:279cbd9900d5da9a8f9053e60db0db7f42d9a799673744b76aaeb6b4f14abe77"
|
||||
],
|
||||
"version": "==2018.5"
|
||||
"version": "==2018.7"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8",
|
||||
"sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736",
|
||||
"sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f",
|
||||
"sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608",
|
||||
"sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8",
|
||||
"sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab",
|
||||
"sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7",
|
||||
"sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3",
|
||||
"sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1",
|
||||
"sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6",
|
||||
"sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8",
|
||||
"sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4",
|
||||
"sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca",
|
||||
"sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269"
|
||||
"sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b",
|
||||
"sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf",
|
||||
"sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a",
|
||||
"sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3",
|
||||
"sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1",
|
||||
"sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1",
|
||||
"sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613",
|
||||
"sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04",
|
||||
"sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f",
|
||||
"sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537",
|
||||
"sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
|
||||
],
|
||||
"version": "==3.12"
|
||||
"version": "==3.13"
|
||||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
"sha256:0201b4cb42f03842a75044a3d08b62a79114f753b33ee421182c631d9f5c81f5",
|
||||
"sha256:204524604456e3e0e25c3f24da4efc43db78edfe7623f1049e03d3aa51ddda48",
|
||||
"sha256:24c0e838bde42fe9d4d5650e75bff2d4bb5867968fb9409331dbe39154f6e8e2",
|
||||
"sha256:4360143da844cd985effb7fb9af04beaa2d371ab13e4a1996424aa2f6fbfb877",
|
||||
"sha256:4b8c6fd44dbd46cdbf755c20a7b9dedb32b8d15b707a0e470dfa66ba5df00a35",
|
||||
"sha256:4fb5622987f3863cfa76c40ab3338a7dc8ed2bac236bb53e638b21ea397a3252",
|
||||
"sha256:5eebefef6e3d97e4c1f9f77eac6555c32ed3afbd769955a9f7339256a4d50d6c",
|
||||
"sha256:7222204c6acb9e52688678ec7306b2dfd84df68bc8eb251be74fec4e9dd85bf9",
|
||||
"sha256:809cbbcbe291cf7bc9cf6aeac6a9a400a71318292d0a2a07effaf4b4782203a0",
|
||||
"sha256:9c9075c727afec23eab196be51737eedb00cd67bb4a2e0170fa8dc65163838f3",
|
||||
"sha256:a105b1d7287d412e8fe99959c1b80f7cbd76184b6466d63579b6d256a406a76e",
|
||||
"sha256:c3d9cfd214a3e5a25f2da9817c389e32069e210b067ebb901e10f3270da9b259",
|
||||
"sha256:c3ebfb5ec2dd750f7861734b25ea7d5ae89d6f33b427cccf3cafa36a1511d862",
|
||||
"sha256:c670acd71d975b0c91579d40ae7f703d0daa1c871f12e46394a2c7be0ec8e217",
|
||||
"sha256:e371482ee3e6e5ca19ea83cdfc84bf69cac230e3cb1073c8c3bebf3f143cd7a5"
|
||||
"sha256:384c78351ceb08b9f04e28552edea9af837d05ad4fda9a187a7bbd82759f29b6",
|
||||
"sha256:41b70db2608726396de185e7571a70391507ab47a64b564f59861ff13f2c50a5",
|
||||
"sha256:50f4b57696883fdbb0494cf1ff1cf6e04790d5e1848dff0b2cf28a2b97614351",
|
||||
"sha256:81515123132f9ab0cc8128d035ba7db7783206e4616bdabd3faba335b9add185",
|
||||
"sha256:91e965833a9f93b3e6abfef815026ccb8a9abe12c0958c723fc6c0d396384602",
|
||||
"sha256:9cb058e53c2488b6cba85a7e6ce6d659b3f33ebe00f613dc9fda46de788a1298",
|
||||
"sha256:b41a81228c3994789d4785d9fef96770f9a6b564a30c10af671bd5a4078da6f4",
|
||||
"sha256:cf20d6539e00021793df23c2a98d57aff84f9402f81ac5896fffb4f8c8a08897",
|
||||
"sha256:f937fdbcdb1e455c23709f5cf6df91a0ecfe8c23268f601606173232958daa8d"
|
||||
],
|
||||
"version": "==2018.6.9"
|
||||
"version": "==2018.11.6"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1",
|
||||
"sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a"
|
||||
"sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c",
|
||||
"sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.19.1"
|
||||
"version": "==2.20.0"
|
||||
},
|
||||
"requests-oauthlib": {
|
||||
"hashes": [
|
||||
"sha256:8886bfec5ad7afb391ed5443b1f697c6f4ae98d0e5620839d8b4499c032ada3f",
|
||||
"sha256:e21232e2465808c0e892e0e4dbb8c2faafec16ac6dc067dd546e9b466f3deac8",
|
||||
"sha256:fe3282f48fb134ee0035712159f5429215459407f6d5484013343031ff1a400d"
|
||||
"sha256:e21232e2465808c0e892e0e4dbb8c2faafec16ac6dc067dd546e9b466f3deac8"
|
||||
],
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"rsa": {
|
||||
"hashes": [
|
||||
"sha256:25df4e10c263fb88b5ace923dd84bf9aa7f5019687b5e55382ffcdb8bede9db5",
|
||||
"sha256:43f682fea81c452c98d09fc316aae12de6d30c4b5c84226642cf8f8fd1c93abd"
|
||||
"sha256:14ba45700ff1ec9eeb206a2ce76b32814958a98e372006c8fb76ba820211be66",
|
||||
"sha256:1a836406405730121ae9823e19c6e806c62bbad73f890574fff50efa4122c487"
|
||||
],
|
||||
"version": "==3.4.2"
|
||||
"version": "==4.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
@@ -251,17 +302,17 @@
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf",
|
||||
"sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5"
|
||||
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
|
||||
"sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"
|
||||
],
|
||||
"version": "==1.23"
|
||||
"version": "==1.24.1"
|
||||
},
|
||||
"websocket-client": {
|
||||
"hashes": [
|
||||
"sha256:18f1170e6a1b5463986739d9fd45c4308b0d025c1b2f9b88788d8f69e8a5eb4a",
|
||||
"sha256:db70953ae4a064698b27ae56dcad84d0ee68b7b43cb40940f537738f38f510c1"
|
||||
"sha256:8c8bf2d4f800c3ed952df206b18c28f7070d9e3dcbd6ca6291127574f57ee786",
|
||||
"sha256:e51562c91ddb8148e791f0155fdb01325d99bb52c4cdbb291aee7a3563fd0849"
|
||||
],
|
||||
"version": "==0.48.0"
|
||||
"version": "==0.54.0"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
@@ -281,11 +332,12 @@
|
||||
"hashes": [
|
||||
"sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba",
|
||||
"sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed",
|
||||
"sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a",
|
||||
"sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd",
|
||||
"sha256:0bf8cbbd71adfff0ef1f3a1531e6402d13b7b01ac50a79c97ca15f030dba6306",
|
||||
"sha256:10a46017fef60e16694a30627319f38a2b9b52e90182dddb6e37dcdab0f4bf95",
|
||||
"sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640",
|
||||
"sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2",
|
||||
"sha256:23d341cdd4a0371820eb2b0bd6b88f5003a7438bbedb33688cd33b8eae59affd",
|
||||
"sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162",
|
||||
"sha256:2a5b73210bad5279ddb558d9a2bfedc7f4bf6ad7f3c988641d83c40293deaec1",
|
||||
"sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508",
|
||||
"sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249",
|
||||
"sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694",
|
||||
@@ -305,25 +357,21 @@
|
||||
"sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c",
|
||||
"sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558",
|
||||
"sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f",
|
||||
"sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4",
|
||||
"sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91",
|
||||
"sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d",
|
||||
"sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9",
|
||||
"sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd",
|
||||
"sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d",
|
||||
"sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6",
|
||||
"sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77",
|
||||
"sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80",
|
||||
"sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e"
|
||||
"sha256:f05a636b4564104120111800021a92e43397bc12a5c72fed7036be8556e0029e",
|
||||
"sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80"
|
||||
],
|
||||
"version": "==4.5.1"
|
||||
},
|
||||
"doublex": {
|
||||
"hashes": [
|
||||
"sha256:062af49d9e4148bc47b7512d3fdc8e145dea4671d074ffd54b2464a19d3757ab"
|
||||
"sha256:bdfa5007ec6f93fcdb05683ef559dd7919b7fe217df41fd240f8d4b2f681ba21"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.8.4"
|
||||
"version": "==1.9.1"
|
||||
},
|
||||
"doublex-expects": {
|
||||
"hashes": [
|
||||
@@ -334,25 +382,25 @@
|
||||
},
|
||||
"expects": {
|
||||
"hashes": [
|
||||
"sha256:37538d7b0fa9c0d53e37d07b0e8c07d89754d3deec1f0f8ed1be27f4f10363dd"
|
||||
"sha256:419902ccafe81b7e9559eeb6b7a07ef9d5c5604eddb93000f0642b3b2d594f4c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.8.0"
|
||||
"version": "==0.9.0"
|
||||
},
|
||||
"mamba": {
|
||||
"hashes": [
|
||||
"sha256:63e70a8666039cf143a255000e23f29be4ea4b5b8169f2b053f94eb73a2ea9e2"
|
||||
"sha256:25328151ea94d97a0b461d7256dc7350c99b5f8d2de22d355978378edfeac545"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.9.3"
|
||||
"version": "==0.10"
|
||||
},
|
||||
"playbooks": {
|
||||
"path": "."
|
||||
},
|
||||
"pyhamcrest": {
|
||||
"hashes": [
|
||||
"sha256:6b672c02fdf7470df9674ab82263841ce8333fb143f32f021f6cb26f0e512420",
|
||||
"sha256:7a4bdade0ed98c699d728191a058a60a44d2f9c213c51e2dd1e6fb42f2c6128a",
|
||||
"sha256:8ffaa0a53da57e89de14ced7185ac746227a8894dbd5a3c718bf05ddbd1d56cd",
|
||||
"sha256:bac0bea7358666ce52e3c6c85139632ed89f115e9af52d44b3c36e0bf8cf16a9",
|
||||
"sha256:f30e9a310bcc1808de817a92e95169ffd16b60cbc5a016a49c8d0e8ababfae79"
|
||||
"sha256:8ffaa0a53da57e89de14ced7185ac746227a8894dbd5a3c718bf05ddbd1d56cd"
|
||||
],
|
||||
"version": "==1.9.0"
|
||||
},
|
||||
|
||||
@@ -33,7 +33,7 @@ trigger.
|
||||
|
||||
* -p: The playbook to deploy, it must match with the top-level script. In this
|
||||
example *slack.py* that contains the wiring between playbooks and Kubeless
|
||||
functions
|
||||
functions.
|
||||
|
||||
* -e: Sets configuration settings for Playbook. In this case the URL where we
|
||||
have to post messages. You can specify multiple *-e* flags.
|
||||
@@ -162,3 +162,67 @@ Kubernetes.
|
||||
|
||||
So as soon as we notice someone wrote under /bin (and additional binaries) or
|
||||
/etc, we disconnect that pod. It's like a trap for our attackers.
|
||||
|
||||
### Create an incident in Demisto
|
||||
|
||||
This playbook creates an incident in Demisto
|
||||
|
||||
```
|
||||
./deploy_playbook -p demisto -t "falco.*.*" -e DEMISTO_API_KEY=XxXxxXxxXXXx -e DEMISTO_BASE_URL=https://..."
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
* DEMISTO_API_KEY: This is the API key used for authenticating against Demisto. Create one under settings -> API keys
|
||||
* DEMISTO_BASE_URL: This is the base URL where your Demisto server lives on. Ensure there's no trailing slash.
|
||||
* VERIFY_SSL: Verify SSL certificates for HTTPS requests. By default is enabled.
|
||||
|
||||
In this example, when Falco raises any kind of alert, the alert will be created in Demisto
|
||||
|
||||
### Start a capture using Sysdig
|
||||
|
||||
This playbook starts to capture information about pod using sysdig and uploads
|
||||
to a s3 bucket.
|
||||
|
||||
```
|
||||
$ ./deploy_playbook -p capture -e CAPTURE_DURATION=300 -e AWS_S3_BUCKET=s3://xxxxxxx -e AWS_ACCESS_KEY_ID=xxxxXXXxxXXxXX -e AWS_SECRET_ACCESS_KEY=xxXxXXxxxxXXX -t "falco.notice.terminal_shell_in_container"
|
||||
```
|
||||
|
||||
#### Parameters:
|
||||
* CAPTURE_DURATION: Captures data for this duration in seconds. By default is
|
||||
120 seconds (2 minutes)
|
||||
* AWS_S3_BUCKET: This is the bucket where data is going to be uploaded. Jobs
|
||||
starts with sysdig- prefix and contain pod name and time where event starts.
|
||||
* AWS_ACCESS_KEY_ID: This is the Amazon access key id.
|
||||
* AWS_SECRET_ACCESS_KEY: This is the Amazon secret access key.
|
||||
|
||||
In this example, when we detect a shell in a container, we start to collect data
|
||||
for 300 seconds. This playbook requires permissions for creating a new pod from
|
||||
a Kubeless function.
|
||||
|
||||
### Create a container in Phantom
|
||||
This playbook creates a container in Phantom
|
||||
|
||||
```
|
||||
./deploy_playbook -p phantom -t "falco.*.*" -e PHANTOM_USER=user -e PHANTOM_PASSWORD=xxxXxxxX -e PHANTOM_BASE_URL=https://..."
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
* PHANTOM_USER: This is the user used to connect to Phantom
|
||||
* PHANTOM_PASSWORD: This is the password used to connect to Phantom
|
||||
* PHANTOM_BASE_URL: This is the base URL where your Phantom server lives on. Ensure there's no trailing slash.
|
||||
* VERIFY_SSL: Verify SSL certificates for HTTPS requests. By default is enabled.
|
||||
|
||||
In this example, when Falco raises any kind of alert, the alert will be created in Phantom.
|
||||
|
||||
## Deploying playbooks to AWS Lambda
|
||||
|
||||
You can deploy functions to AWS Lambda using the `./deploy_playbook_aws` script.
|
||||
|
||||
### Parameters
|
||||
|
||||
* -p: The playbook to deploy, it must match with the top-level script.
|
||||
|
||||
* -e: Sets configuration settings for Playbook. You can specify multiple *-e* flags.
|
||||
|
||||
* -k: EKS cluster name against playbook is going to connect via K8s API.
|
||||
|
||||
@@ -16,20 +16,24 @@ You must pass the playbook and at least one topic to subscribe.
|
||||
|
||||
Example:
|
||||
|
||||
deploy_playbook -r slack -t "falco.error.*" -e SLACK_WEBHOOK_URL=http://foobar.com/...
|
||||
deploy_playbook -p slack -t "falco.error.*" -e SLACK_WEBHOOK_URL=http://foobar.com/...
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
function join { local IFS="$1"; shift; echo "$*"; }
|
||||
function create_environment_flags {
|
||||
for env in ${environment[*]}; do
|
||||
echo "--env ${env} "
|
||||
done
|
||||
}
|
||||
|
||||
playbook=""
|
||||
environment=()
|
||||
topics=()
|
||||
|
||||
while getopts "r:e:t:" arg; do
|
||||
while getopts "p:e:t:" arg; do
|
||||
case $arg in
|
||||
r)
|
||||
p)
|
||||
playbook="${OPTARG}"
|
||||
;;
|
||||
e)
|
||||
@@ -50,16 +54,31 @@ fi
|
||||
|
||||
pipenv lock --requirements | sed '/^-/ d' > requirements.txt
|
||||
|
||||
zip "${playbook}".zip -r playbooks/*.py "${playbook}".py
|
||||
mkdir -p kubeless-function
|
||||
|
||||
cp -r playbooks kubeless-function/
|
||||
|
||||
cat > kubeless-function/"${playbook}".py <<EOL
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
EOL
|
||||
cat functions/"${playbook}".py >> kubeless-function/"${playbook}".py
|
||||
|
||||
|
||||
cd kubeless-function
|
||||
zip ../"${playbook}".zip -r *
|
||||
cd ..
|
||||
|
||||
kubeless function deploy --from-file "${playbook}".zip \
|
||||
--dependencies requirements.txt \
|
||||
--env "$(join , ${environment[*]})" \
|
||||
$(create_environment_flags ${environment[*]}) \
|
||||
--runtime python3.6 \
|
||||
--handler "${playbook}".handler \
|
||||
falco-"${playbook}"
|
||||
|
||||
rm requirements.txt ${playbook}.zip
|
||||
rm -fr requirements.txt ${playbook}.zip kubeless-function
|
||||
|
||||
for index in ${!topics[*]}; do
|
||||
kubeless trigger nats create falco-"${playbook}"-trigger-"${index}" \
|
||||
|
||||
76
integrations/kubernetes-response-engine/playbooks/deploy_playbook_aws
Executable file
76
integrations/kubernetes-response-engine/playbooks/deploy_playbook_aws
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Deploys a playbook
|
||||
|
||||
set -e
|
||||
|
||||
function usage() {
|
||||
cat<<EOF
|
||||
Usage: $0 [options]
|
||||
|
||||
-p playbook Playbook to be deployed. Is the script for Kubeless: slack, taint, isolate.
|
||||
-e environment Environment variables for the Kubeless function. You can pass multiple environment variables passing several -e parameters.
|
||||
-k kubernetes_cluster Kubernetes cluster from aws eks list-clusters where function will be applied.
|
||||
|
||||
You must pass the playbook and at least one topic to subscribe.
|
||||
|
||||
Example:
|
||||
|
||||
deploy_playbook -p slack -e SLACK_WEBHOOK_URL=http://foobar.com/... -k sysdig_eks
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
function join { local IFS="$1"; shift; echo "$*"; }
|
||||
|
||||
playbook=""
|
||||
environment=("KUBECONFIG=kubeconfig" "KUBERNETES_LOAD_KUBE_CONFIG=1")
|
||||
eks_cluster="${EKS_CLUSTER}"
|
||||
|
||||
while getopts "p:e:k:" arg; do
|
||||
case $arg in
|
||||
p)
|
||||
playbook="${OPTARG}"
|
||||
;;
|
||||
e)
|
||||
environment+=("${OPTARG}")
|
||||
;;
|
||||
k)
|
||||
eks_cluster="${OPTARG}"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "${playbook}" == "" ]] || [[ "${eks_cluster}" == "" ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
pipenv lock --requirements | sed '/^-/ d' > requirements.txt
|
||||
|
||||
mkdir -p lambda
|
||||
pip install -t lambda -r requirements.txt
|
||||
pip install -t lambda .
|
||||
|
||||
aws eks update-kubeconfig --name "${eks_cluster}" --kubeconfig lambda/kubeconfig
|
||||
sed -i "s/command: aws-iam-authenticator/command: .\/aws-iam-authenticator/g" lambda/kubeconfig
|
||||
|
||||
cp extra/aws-iam-authenticator lambda/
|
||||
|
||||
cp functions/"${playbook}".py lambda/
|
||||
|
||||
cd lambda
|
||||
zip ../"${playbook}".zip -r *
|
||||
cd ..
|
||||
|
||||
aws lambda create-function \
|
||||
--function-name falco-"${playbook}" \
|
||||
--runtime python2.7 \
|
||||
--role $(terraform output --state=../deployment/aws/terraform.tfstate iam_for_lambda) \
|
||||
--environment Variables={"$(join , ${environment[*]})"} \
|
||||
--handler "${playbook}".handler \
|
||||
--zip-file fileb://./"${playbook}".zip
|
||||
|
||||
rm -fr "${playbook}".zip lambda requirements.txt
|
||||
BIN
integrations/kubernetes-response-engine/playbooks/extra/aws-iam-authenticator
Executable file
BIN
integrations/kubernetes-response-engine/playbooks/extra/aws-iam-authenticator
Executable file
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
import os
|
||||
import playbooks
|
||||
from playbooks import infrastructure
|
||||
|
||||
|
||||
playbook = playbooks.StartSysdigCaptureForContainer(
|
||||
infrastructure.KubernetesClient(),
|
||||
int(os.environ.get('CAPTURE_DURATION', 120)),
|
||||
os.environ['AWS_S3_BUCKET'],
|
||||
os.environ['AWS_ACCESS_KEY_ID'],
|
||||
os.environ['AWS_SECRET_ACCESS_KEY']
|
||||
)
|
||||
|
||||
|
||||
def handler(event, context):
|
||||
playbook.run(event['data'])
|
||||
@@ -1,8 +1,3 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
import os
|
||||
import playbooks
|
||||
from playbooks import infrastructure
|
||||
|
||||
@@ -13,4 +8,4 @@ playbook = playbooks.DeletePod(
|
||||
|
||||
|
||||
def handler(event, context):
|
||||
playbook.run(event['data'])
|
||||
playbook.run(playbooks.falco_alert(event))
|
||||
@@ -0,0 +1,22 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
import os
|
||||
import playbooks
|
||||
from playbooks import infrastructure
|
||||
|
||||
|
||||
def _to_bool(value):
|
||||
return value.lower() in ('yes', 'true', '1')
|
||||
|
||||
|
||||
playbook = playbooks.CreateIncidentInDemisto(
|
||||
infrastructure.DemistoClient(os.environ['DEMISTO_API_KEY'],
|
||||
os.environ['DEMISTO_BASE_URL']
|
||||
verify_ssl=_to_bool(os.environ.get('VERIFY_SSL', 'True')))
|
||||
)
|
||||
|
||||
|
||||
def handler(event, context):
|
||||
playbook.run(event['data'])
|
||||
@@ -1,8 +1,3 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
import os
|
||||
import playbooks
|
||||
from playbooks import infrastructure
|
||||
|
||||
@@ -13,4 +8,4 @@ playbook = playbooks.NetworkIsolatePod(
|
||||
|
||||
|
||||
def handler(event, context):
|
||||
playbook.run(event['data'])
|
||||
playbook.run(playbooks.falco_alert(event))
|
||||
@@ -0,0 +1,25 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
import os
|
||||
import playbooks
|
||||
from playbooks import infrastructure
|
||||
|
||||
|
||||
def _to_bool(value):
|
||||
return value.lower() in ('yes', 'true', '1')
|
||||
|
||||
|
||||
playbook = playbooks.CreateContainerInPhantom(
|
||||
infrastructure.PhantomClient(
|
||||
os.environ['PHANTOM_USER'],
|
||||
os.environ['PHANTOM_PASSWORD'],
|
||||
os.environ['PHANTOM_BASE_URL'],
|
||||
verify_ssl=_to_bool(os.environ.get('VERIFY_SSL', 'True'))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def handler(event, context):
|
||||
playbook.run(event['data'])
|
||||
@@ -1,7 +1,3 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
import os
|
||||
import playbooks
|
||||
from playbooks import infrastructure
|
||||
@@ -13,4 +9,4 @@ playbook = playbooks.AddMessageToSlack(
|
||||
|
||||
|
||||
def handler(event, context):
|
||||
playbook.run(event['data'])
|
||||
playbook.run(playbooks.falco_alert(event))
|
||||
@@ -1,7 +1,3 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__))))
|
||||
|
||||
import os
|
||||
import playbooks
|
||||
from playbooks import infrastructure
|
||||
@@ -16,4 +12,4 @@ playbook = playbooks.TaintNode(
|
||||
|
||||
|
||||
def handler(event, context):
|
||||
playbook.run(event['data'])
|
||||
playbook.run(playbooks.falco_alert(event))
|
||||
@@ -1,7 +1,8 @@
|
||||
import json
|
||||
import maya
|
||||
|
||||
|
||||
class DeletePod:
|
||||
class DeletePod(object):
|
||||
def __init__(self, k8s_client):
|
||||
self._k8s_client = k8s_client
|
||||
|
||||
@@ -11,7 +12,7 @@ class DeletePod:
|
||||
self._k8s_client.delete_pod(pod_name)
|
||||
|
||||
|
||||
class AddMessageToSlack:
|
||||
class AddMessageToSlack(object):
|
||||
def __init__(self, slack_client):
|
||||
self._slack_client = slack_client
|
||||
|
||||
@@ -23,7 +24,7 @@ class AddMessageToSlack:
|
||||
|
||||
def _build_slack_message(self, alert):
|
||||
return {
|
||||
'text': self._output(alert),
|
||||
'text': _output_from_alert(alert),
|
||||
'attachments': [{
|
||||
'color': self._color_from(alert['priority']),
|
||||
'fields': [
|
||||
@@ -56,12 +57,6 @@ class AddMessageToSlack:
|
||||
}]
|
||||
}
|
||||
|
||||
def _output(self, alert):
|
||||
output = alert['output'].split(': ')[1]
|
||||
priority_plus_whitespace_length = len(alert['priority']) + 1
|
||||
|
||||
return output[priority_plus_whitespace_length:]
|
||||
|
||||
_COLORS = {
|
||||
'Emergency': '#b12737',
|
||||
'Alert': '#f24141',
|
||||
@@ -77,7 +72,14 @@ class AddMessageToSlack:
|
||||
return self._COLORS.get(priority, '#eeeeee')
|
||||
|
||||
|
||||
class TaintNode:
|
||||
def _output_from_alert(alert):
|
||||
output = alert['output'].split(': ')[1]
|
||||
priority_plus_whitespace_length = len(alert['priority']) + 1
|
||||
|
||||
return output[priority_plus_whitespace_length:]
|
||||
|
||||
|
||||
class TaintNode(object):
|
||||
def __init__(self, k8s_client, key, value, effect):
|
||||
self._k8s_client = k8s_client
|
||||
self._key = key
|
||||
@@ -91,7 +93,7 @@ class TaintNode:
|
||||
self._k8s_client.taint_node(node, self._key, self._value, self._effect)
|
||||
|
||||
|
||||
class NetworkIsolatePod:
|
||||
class NetworkIsolatePod(object):
|
||||
def __init__(self, k8s_client):
|
||||
self._k8s_client = k8s_client
|
||||
|
||||
@@ -99,3 +101,110 @@ class NetworkIsolatePod:
|
||||
pod = alert['output_fields']['k8s.pod.name']
|
||||
|
||||
self._k8s_client.add_label_to_pod(pod, 'isolated', 'true')
|
||||
|
||||
|
||||
class CreateIncidentInDemisto(object):
|
||||
def __init__(self, demisto_client):
|
||||
self._demisto_client = demisto_client
|
||||
|
||||
def run(self, alert):
|
||||
incident = {
|
||||
'type': 'Policy Violation',
|
||||
'name': alert['rule'],
|
||||
'details': _output_from_alert(alert),
|
||||
'severity': self._severity_from(alert['priority']),
|
||||
'occurred': alert['time'],
|
||||
'labels': [
|
||||
{'type': 'Brand', 'value': 'Sysdig'},
|
||||
{'type': 'Application', 'value': 'Falco'},
|
||||
{'type': 'container.id', 'value': alert['output_fields']['container.id']},
|
||||
{'type': 'k8s.pod.name', 'value': alert['output_fields']['k8s.pod.name']}
|
||||
]
|
||||
}
|
||||
self._demisto_client.create_incident(incident)
|
||||
|
||||
return incident
|
||||
|
||||
def _severity_from(self, priority):
|
||||
return self._SEVERITIES.get(priority, 0)
|
||||
|
||||
_SEVERITIES = {
|
||||
'Emergency': 4,
|
||||
'Alert': 4,
|
||||
'Critical': 4,
|
||||
'Error': 3,
|
||||
'Warning': 2,
|
||||
'Notice': 1,
|
||||
'Informational': 5,
|
||||
'Debug': 5,
|
||||
}
|
||||
|
||||
|
||||
class StartSysdigCaptureForContainer(object):
|
||||
def __init__(self, k8s_client, duration_in_seconds, s3_bucket,
|
||||
aws_access_key_id, aws_secret_access_key):
|
||||
self._k8s_client = k8s_client
|
||||
self._duration_in_seconds = duration_in_seconds
|
||||
self._s3_bucket = s3_bucket
|
||||
self._aws_access_key_id = aws_access_key_id
|
||||
self._aws_secret_access_key = aws_secret_access_key
|
||||
|
||||
def run(self, alert):
|
||||
pod = alert['output_fields']['k8s.pod.name']
|
||||
event_time = alert['output_fields']['evt.time']
|
||||
|
||||
self._k8s_client.start_sysdig_capture_for(pod,
|
||||
event_time,
|
||||
self._duration_in_seconds,
|
||||
self._s3_bucket,
|
||||
self._aws_access_key_id,
|
||||
self._aws_secret_access_key)
|
||||
|
||||
|
||||
class CreateContainerInPhantom(object):
|
||||
def __init__(self, phantom_client):
|
||||
self._phantom_client = phantom_client
|
||||
|
||||
def run(self, alert):
|
||||
container = self._build_container_from(alert)
|
||||
self._phantom_client.create_container(container)
|
||||
|
||||
return container
|
||||
|
||||
def _build_container_from(self, alert):
|
||||
return {
|
||||
'description': _output_from_alert(alert),
|
||||
'name': alert['rule'],
|
||||
'start_time': maya.parse(alert['time']).iso8601(),
|
||||
'severity': self._severity_from(alert['priority']),
|
||||
'label': 'events',
|
||||
'status': 'new',
|
||||
'data': {
|
||||
'container.id': alert['output_fields']['container.id'],
|
||||
'k8s.pod.name': alert['output_fields']['k8s.pod.name'],
|
||||
}
|
||||
}
|
||||
|
||||
def _severity_from(self, priority):
|
||||
return self._SEVERITIES.get(priority, 0)
|
||||
|
||||
_SEVERITIES = {
|
||||
'Emergency': 'high',
|
||||
'Alert': 'high',
|
||||
'Critical': 'high',
|
||||
'Error': 'medium',
|
||||
'Warning': 'medium',
|
||||
'Notice': 'low',
|
||||
'Informational': 'low',
|
||||
'Debug': 'low',
|
||||
}
|
||||
|
||||
|
||||
def falco_alert(event):
|
||||
if 'data' in event:
|
||||
return event['data']
|
||||
|
||||
if 'Records' in event:
|
||||
return json.loads(event['Records'][0]['Sns']['Message'])
|
||||
|
||||
return event
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import os
|
||||
import json
|
||||
from six.moves import http_client
|
||||
|
||||
from kubernetes import client, config
|
||||
import requests
|
||||
|
||||
|
||||
class KubernetesClient:
|
||||
class KubernetesClient(object):
|
||||
def __init__(self):
|
||||
if 'KUBERNETES_LOAD_KUBE_CONFIG' in os.environ:
|
||||
config.load_kube_config()
|
||||
@@ -13,6 +14,7 @@ class KubernetesClient:
|
||||
config.load_incluster_config()
|
||||
|
||||
self._v1 = client.CoreV1Api()
|
||||
self._batch_v1 = client.BatchV1Api()
|
||||
|
||||
def delete_pod(self, name):
|
||||
namespace = self._find_pod_namespace(name)
|
||||
@@ -64,11 +66,202 @@ class KubernetesClient:
|
||||
|
||||
return self._v1.patch_namespaced_pod(name, namespace, body)
|
||||
|
||||
def start_sysdig_capture_for(self, pod_name, event_time,
|
||||
duration_in_seconds, s3_bucket,
|
||||
aws_access_key_id, aws_secret_access_key):
|
||||
job_name = 'sysdig-{}-{}'.format(pod_name, event_time)
|
||||
|
||||
class SlackClient:
|
||||
node_name = self.find_node_running_pod(pod_name)
|
||||
namespace = self._find_pod_namespace(pod_name)
|
||||
body = self._build_sysdig_capture_job_body(job_name,
|
||||
node_name,
|
||||
duration_in_seconds,
|
||||
s3_bucket,
|
||||
aws_access_key_id,
|
||||
aws_secret_access_key)
|
||||
|
||||
return self._batch_v1.create_namespaced_job(namespace, body)
|
||||
|
||||
def _build_sysdig_capture_job_body(self, job_name, node_name,
|
||||
duration_in_seconds, s3_bucket,
|
||||
aws_access_key_id, aws_secret_access_key):
|
||||
return client.V1Job(
|
||||
metadata=client.V1ObjectMeta(
|
||||
name=job_name
|
||||
),
|
||||
spec=client.V1JobSpec(
|
||||
template=client.V1PodTemplateSpec(
|
||||
metadata=client.V1ObjectMeta(
|
||||
name=job_name
|
||||
),
|
||||
spec=client.V1PodSpec(
|
||||
containers=[client.V1Container(
|
||||
name='capturer',
|
||||
image='sysdig/capturer',
|
||||
image_pull_policy='Always',
|
||||
security_context=client.V1SecurityContext(
|
||||
privileged=True
|
||||
),
|
||||
env=[
|
||||
client.V1EnvVar(
|
||||
name='AWS_S3_BUCKET',
|
||||
value=s3_bucket
|
||||
),
|
||||
client.V1EnvVar(
|
||||
name='CAPTURE_DURATION',
|
||||
value=str(duration_in_seconds)
|
||||
),
|
||||
client.V1EnvVar(
|
||||
name='CAPTURE_FILE_NAME',
|
||||
value=job_name
|
||||
),
|
||||
client.V1EnvVar(
|
||||
name='AWS_ACCESS_KEY_ID',
|
||||
value=aws_access_key_id,
|
||||
),
|
||||
client.V1EnvVar(
|
||||
name='AWS_SECRET_ACCESS_KEY',
|
||||
value=aws_secret_access_key,
|
||||
)
|
||||
],
|
||||
volume_mounts=[
|
||||
client.V1VolumeMount(
|
||||
mount_path='/host/var/run/docker.sock',
|
||||
name='docker-socket'
|
||||
),
|
||||
client.V1VolumeMount(
|
||||
mount_path='/host/dev',
|
||||
name='dev-fs'
|
||||
),
|
||||
client.V1VolumeMount(
|
||||
mount_path='/host/proc',
|
||||
name='proc-fs',
|
||||
read_only=True
|
||||
),
|
||||
client.V1VolumeMount(
|
||||
mount_path='/host/boot',
|
||||
name='boot-fs',
|
||||
read_only=True
|
||||
),
|
||||
client.V1VolumeMount(
|
||||
mount_path='/host/lib/modules',
|
||||
name='lib-modules',
|
||||
read_only=True
|
||||
),
|
||||
client.V1VolumeMount(
|
||||
mount_path='/host/usr',
|
||||
name='usr-fs',
|
||||
read_only=True
|
||||
),
|
||||
client.V1VolumeMount(
|
||||
mount_path='/dev/shm',
|
||||
name='dshm'
|
||||
)
|
||||
]
|
||||
)],
|
||||
volumes=[
|
||||
client.V1Volume(
|
||||
name='dshm',
|
||||
empty_dir=client.V1EmptyDirVolumeSource(
|
||||
medium='Memory'
|
||||
)
|
||||
),
|
||||
client.V1Volume(
|
||||
name='docker-socket',
|
||||
host_path=client.V1HostPathVolumeSource(
|
||||
path='/var/run/docker.sock'
|
||||
)
|
||||
),
|
||||
client.V1Volume(
|
||||
name='dev-fs',
|
||||
host_path=client.V1HostPathVolumeSource(
|
||||
|
||||
path='/dev'
|
||||
)
|
||||
),
|
||||
client.V1Volume(
|
||||
name='proc-fs',
|
||||
host_path=client.V1HostPathVolumeSource(
|
||||
path='/proc'
|
||||
)
|
||||
),
|
||||
|
||||
client.V1Volume(
|
||||
name='boot-fs',
|
||||
host_path=client.V1HostPathVolumeSource(
|
||||
path='/boot'
|
||||
)
|
||||
),
|
||||
client.V1Volume(
|
||||
name='lib-modules',
|
||||
host_path=client.V1HostPathVolumeSource(
|
||||
path='/lib/modules'
|
||||
)
|
||||
),
|
||||
client.V1Volume(
|
||||
name='usr-fs',
|
||||
host_path=client.V1HostPathVolumeSource(
|
||||
path='/usr'
|
||||
)
|
||||
)
|
||||
],
|
||||
node_name=node_name,
|
||||
restart_policy='Never'
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SlackClient(object):
|
||||
def __init__(self, slack_webhook_url):
|
||||
self._slack_webhook_url = slack_webhook_url
|
||||
|
||||
def post_message(self, message):
|
||||
requests.post(self._slack_webhook_url,
|
||||
data=json.dumps(message))
|
||||
|
||||
|
||||
class DemistoClient(object):
|
||||
def __init__(self, api_key, base_url, verify_ssl=True):
|
||||
self._api_key = api_key
|
||||
self._base_url = base_url
|
||||
self._verify_ssl = verify_ssl
|
||||
|
||||
def create_incident(self, incident):
|
||||
response = requests.post(self._base_url + '/incident',
|
||||
headers=self._headers(),
|
||||
data=json.dumps(incident),
|
||||
verify=self._verify_ssl)
|
||||
|
||||
if response.status_code != http_client.CREATED:
|
||||
raise RuntimeError(response.text)
|
||||
|
||||
def _headers(self):
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'Authorization': self._api_key,
|
||||
}
|
||||
|
||||
|
||||
class PhantomClient(object):
|
||||
def __init__(self, user, password, base_url, verify_ssl=True):
|
||||
self._user = user
|
||||
self._password = password
|
||||
self._base_url = base_url
|
||||
self._verify_ssl = verify_ssl
|
||||
|
||||
def create_container(self, container):
|
||||
response = requests.post(self._base_url + '/rest/container',
|
||||
data=json.dumps(container),
|
||||
auth=(self._user, self._password),
|
||||
verify=self._verify_ssl)
|
||||
|
||||
response_as_json = response.json()
|
||||
if 'success' in response_as_json:
|
||||
result = container.copy()
|
||||
result['id'] = response_as_json['id']
|
||||
return result
|
||||
|
||||
raise RuntimeError(response_as_json['message'])
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
from mamba import description, it, context, before
|
||||
from expects import expect, raise_error
|
||||
|
||||
import os
|
||||
|
||||
from playbooks import infrastructure
|
||||
|
||||
|
||||
with description(infrastructure.DemistoClient) as self:
|
||||
with before.each:
|
||||
self.demisto_client = infrastructure.DemistoClient(
|
||||
os.environ['DEMISTO_API_KEY'],
|
||||
os.environ['DEMISTO_BASE_URL'],
|
||||
verify_ssl=False
|
||||
)
|
||||
|
||||
with it('creates an incident'):
|
||||
incident = {
|
||||
"type": "Policy Violation",
|
||||
"name": "Falco incident",
|
||||
"severity": 2,
|
||||
"details": "Some incident details"
|
||||
}
|
||||
|
||||
self.demisto_client.create_incident(incident)
|
||||
|
||||
with context('when an error happens'):
|
||||
with it('raises an exception'):
|
||||
incident = {}
|
||||
|
||||
expect(lambda: self.demisto_client.create_incident(incident)).\
|
||||
to(raise_error(RuntimeError))
|
||||
@@ -1,8 +1,9 @@
|
||||
from mamba import description, context, it, before
|
||||
from expects import expect, be_false, be_true, start_with, equal, have_key
|
||||
from expects import expect, be_false, be_true, start_with, equal, have_key, be_none
|
||||
|
||||
import subprocess
|
||||
import os.path
|
||||
import time
|
||||
|
||||
from playbooks import infrastructure
|
||||
|
||||
@@ -46,7 +47,7 @@ with description(infrastructure.KubernetesClient) as self:
|
||||
expect(node.spec.taints[0].key).to(equal('playbooks'))
|
||||
expect(node.spec.taints[0].value).to(equal('true'))
|
||||
|
||||
with it('adds labels to a pod'):
|
||||
with it('adds label to a pod'):
|
||||
self._create_nginx_pod()
|
||||
|
||||
pod = self.kubernetes_client.add_label_to_pod('nginx',
|
||||
@@ -55,6 +56,18 @@ with description(infrastructure.KubernetesClient) as self:
|
||||
|
||||
expect(pod.metadata.labels).to(have_key('testing', 'true'))
|
||||
|
||||
with it('starts sysdig capture for'):
|
||||
self._create_nginx_pod()
|
||||
|
||||
job = self.kubernetes_client.start_sysdig_capture_for('nginx',
|
||||
int(time.time()),
|
||||
10,
|
||||
'any s3 bucket',
|
||||
'any aws key id',
|
||||
'any aws secret key')
|
||||
|
||||
expect(job).not_to(be_none)
|
||||
|
||||
def _create_nginx_pod(self):
|
||||
current_directory = os.path.dirname(os.path.realpath(__file__))
|
||||
pod_manifesto = os.path.join(current_directory,
|
||||
@@ -62,4 +75,4 @@ with description(infrastructure.KubernetesClient) as self:
|
||||
'support',
|
||||
'deployment.yaml')
|
||||
|
||||
subprocess.run(['kubectl', 'create', '-f', pod_manifesto])
|
||||
subprocess.call(['kubectl', 'create', '-f', pod_manifesto])
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
from mamba import description, it, before, context
|
||||
from expects import expect, be_none, raise_error
|
||||
|
||||
import os
|
||||
|
||||
from playbooks import infrastructure
|
||||
|
||||
|
||||
with description(infrastructure.PhantomClient) as self:
|
||||
with before.each:
|
||||
self.phantom_client = infrastructure.PhantomClient(
|
||||
os.environ['PHANTOM_USER'],
|
||||
os.environ['PHANTOM_PASSWORD'],
|
||||
os.environ['PHANTOM_BASE_URL'],
|
||||
verify_ssl=False
|
||||
)
|
||||
|
||||
with it('creates a container in Phantom Server'):
|
||||
container = {
|
||||
'name': 'My Container',
|
||||
'description': 'Useful description of this container.',
|
||||
'label': 'events',
|
||||
'run_automation': False,
|
||||
'severity': 'high',
|
||||
'status': 'new',
|
||||
'start_time': '2015-03-21T19:28:13.759Z',
|
||||
}
|
||||
|
||||
container = self.phantom_client.create_container(container)
|
||||
|
||||
expect(container['id']).not_to(be_none)
|
||||
|
||||
with context('when an error happens'):
|
||||
with it('raises an error'):
|
||||
container = {
|
||||
'description': 'Useful description of this container.',
|
||||
'label': 'events',
|
||||
'run_automation': False,
|
||||
'severity': 'high',
|
||||
'status': 'new',
|
||||
'start_time': '2015-03-21T19:28:13.759Z',
|
||||
}
|
||||
|
||||
expect(lambda: self.phantom_client.create_container(container))\
|
||||
.to(raise_error(RuntimeError))
|
||||
@@ -0,0 +1,63 @@
|
||||
from mamba import description, it, before, context
|
||||
from expects import expect, have_key
|
||||
|
||||
from doublex import Spy
|
||||
from doublex_expects import have_been_called_with
|
||||
|
||||
from playbooks import infrastructure
|
||||
import playbooks
|
||||
|
||||
|
||||
with description(playbooks.CreateContainerInPhantom) as self:
|
||||
with before.each:
|
||||
self.phantom_client = Spy(infrastructure.PhantomClient)
|
||||
self.playbook = playbooks.CreateContainerInPhantom(self.phantom_client)
|
||||
|
||||
self.alert = {
|
||||
"output": "10:22:15.576767292: Notice Unexpected setuid call by non-sudo, non-root program (user=bin cur_uid=2 parent=event_generator command=event_generator uid=root) k8s.pod=falco-event-generator-6fd89678f9-cdkvz container=1c76f49f40b4",
|
||||
"output_fields": {
|
||||
"container.id": "1c76f49f40b4",
|
||||
"evt.arg.uid": "root",
|
||||
"evt.time": 1527157335576767292,
|
||||
"k8s.pod.name": "falco-event-generator-6fd89678f9-cdkvz",
|
||||
"proc.cmdline": "event_generator ",
|
||||
"proc.pname": "event_generator",
|
||||
"user.name": "bin",
|
||||
"user.uid": 2
|
||||
},
|
||||
"priority": "Notice",
|
||||
"rule": "Non sudo setuid",
|
||||
"time": "2018-05-24T10:22:15.576767292Z"
|
||||
}
|
||||
|
||||
self.container = self.playbook.run(self.alert)
|
||||
|
||||
with it('creates the container in phantom'):
|
||||
expect(self.phantom_client.create_container).to(have_been_called_with(self.container))
|
||||
|
||||
with it('includes falco output'):
|
||||
falco_output = 'Unexpected setuid call by non-sudo, non-root program (user=bin cur_uid=2 parent=event_generator command=event_generator uid=root) k8s.pod=falco-event-generator-6fd89678f9-cdkvz container=1c76f49f40b4'
|
||||
|
||||
expect(self.container).to(have_key('description', falco_output))
|
||||
|
||||
with it('includes severity'):
|
||||
expect(self.container).to(have_key('severity', 'low'))
|
||||
|
||||
with it('includes rule name'):
|
||||
expect(self.container).to(have_key('name', 'Non sudo setuid'))
|
||||
|
||||
with it('includes time when alert happened'):
|
||||
expect(self.container).to(have_key('start_time', '2018-05-24T10:22:15.576767Z'))
|
||||
|
||||
with it('includes label'):
|
||||
expect(self.container).to(have_key('label', 'events'))
|
||||
|
||||
with it('includes status'):
|
||||
expect(self.container).to(have_key('status', 'new'))
|
||||
|
||||
with context('when building additional data'):
|
||||
with it('includes kubernetes pod name'):
|
||||
expect(self.container['data']).to(have_key('k8s.pod.name', 'falco-event-generator-6fd89678f9-cdkvz'))
|
||||
|
||||
with it('includes container id'):
|
||||
expect(self.container['data']).to(have_key('container.id', '1c76f49f40b4'))
|
||||
@@ -0,0 +1,70 @@
|
||||
from mamba import description, it, before, context
|
||||
from expects import expect, have_key, have_keys, contain
|
||||
|
||||
from doublex import Spy
|
||||
from doublex_expects import have_been_called_with
|
||||
|
||||
from playbooks import infrastructure
|
||||
import playbooks
|
||||
|
||||
import os
|
||||
|
||||
|
||||
with description(playbooks.CreateIncidentInDemisto) as self:
|
||||
with before.each:
|
||||
self.demisto_client = Spy(infrastructure.DemistoClient)
|
||||
self.playbook = playbooks.CreateIncidentInDemisto(self.demisto_client)
|
||||
|
||||
with context('when publishing a message to slack'):
|
||||
with before.each:
|
||||
self.alert = {
|
||||
"output": "10:22:15.576767292: Notice Unexpected setuid call by non-sudo, non-root program (user=bin cur_uid=2 parent=event_generator command=event_generator uid=root) k8s.pod=falco-event-generator-6fd89678f9-cdkvz container=1c76f49f40b4",
|
||||
"output_fields": {
|
||||
"container.id": "1c76f49f40b4",
|
||||
"evt.arg.uid": "root",
|
||||
"evt.time": 1527157335576767292,
|
||||
"k8s.pod.name": "falco-event-generator-6fd89678f9-cdkvz",
|
||||
"proc.cmdline": "event_generator ",
|
||||
"proc.pname": "event_generator",
|
||||
"user.name": "bin",
|
||||
"user.uid": 2
|
||||
},
|
||||
"priority": "Notice",
|
||||
"rule": "Non sudo setuid",
|
||||
"time": "2018-05-24T10:22:15.576767292Z"
|
||||
}
|
||||
|
||||
self.incident = self.playbook.run(self.alert)
|
||||
|
||||
with it('creates incident in demisto'):
|
||||
expect(self.demisto_client.create_incident).to(have_been_called_with(self.incident))
|
||||
|
||||
with it('sets incident type as Policy Violation'):
|
||||
expect(self.incident).to(have_key('type', 'Policy Violation'))
|
||||
|
||||
with it('includes rule name'):
|
||||
expect(self.incident).to(have_key('name', 'Non sudo setuid'))
|
||||
|
||||
with it('includes falco output'):
|
||||
falco_output = 'Unexpected setuid call by non-sudo, non-root program (user=bin cur_uid=2 parent=event_generator command=event_generator uid=root) k8s.pod=falco-event-generator-6fd89678f9-cdkvz container=1c76f49f40b4'
|
||||
|
||||
expect(self.incident).to(have_key('details', falco_output))
|
||||
|
||||
with it('includes severity'):
|
||||
expect(self.incident).to(have_key('severity', 1))
|
||||
|
||||
with it('includes time when alert happened'):
|
||||
expect(self.incident).to(have_key('occurred', "2018-05-24T10:22:15.576767292Z"))
|
||||
|
||||
with context('when adding labels'):
|
||||
with it('includes Sysdig as Brand'):
|
||||
expect(self.incident['labels']).to(contain(have_keys(type='Brand', value='Sysdig')))
|
||||
|
||||
with it('includes Falco as Application'):
|
||||
expect(self.incident['labels']).to(contain(have_keys(type='Application', value='Falco')))
|
||||
|
||||
with it('includes container.id'):
|
||||
expect(self.incident['labels']).to(contain(have_keys(type='container.id', value='1c76f49f40b4')))
|
||||
|
||||
with it('includes k8s.pod.name'):
|
||||
expect(self.incident['labels']).to(contain(have_keys(type='k8s.pod.name', value='falco-event-generator-6fd89678f9-cdkvz')))
|
||||
@@ -0,0 +1,40 @@
|
||||
from mamba import description, it, before
|
||||
from expects import expect
|
||||
|
||||
from doublex import Spy
|
||||
from doublex_expects import have_been_called_with
|
||||
|
||||
from playbooks import infrastructure
|
||||
import playbooks
|
||||
|
||||
|
||||
with description(playbooks.StartSysdigCaptureForContainer) as self:
|
||||
with before.each:
|
||||
self.k8s_client = Spy(infrastructure.KubernetesClient)
|
||||
self.duration_in_seconds = 'any duration in seconds'
|
||||
self.s3_bucket = 'any s3 bucket url'
|
||||
self.aws_access_key_id = 'any aws access key id'
|
||||
self.aws_secret_access_key = 'any aws secret access key'
|
||||
self.playbook = playbooks.StartSysdigCaptureForContainer(self.k8s_client,
|
||||
self.duration_in_seconds,
|
||||
self.s3_bucket,
|
||||
self.aws_access_key_id,
|
||||
self.aws_secret_access_key)
|
||||
|
||||
with it('add starts capturing job in same node than Pod alerted'):
|
||||
pod_name = 'any pod name'
|
||||
event_time = 'any event time'
|
||||
alert = {'output_fields': {
|
||||
'k8s.pod.name': pod_name,
|
||||
'evt.time': event_time,
|
||||
}}
|
||||
|
||||
self.playbook.run(alert)
|
||||
|
||||
expect(self.k8s_client.start_sysdig_capture_for)\
|
||||
.to(have_been_called_with(pod_name,
|
||||
event_time,
|
||||
self.duration_in_seconds,
|
||||
self.s3_bucket,
|
||||
self.aws_access_key_id,
|
||||
self.aws_secret_access_key))
|
||||
@@ -0,0 +1,26 @@
|
||||
FROM sysdig/sysdig:latest
|
||||
|
||||
MAINTAINER Néstor Salceda <nestor.salceda@sysdig.com>
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get --fix-broken install -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
s3cmd \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# debian:unstable head contains binutils 2.31, which generates
|
||||
# binaries that are incompatible with kernels < 4.16. So manually
|
||||
# forcibly install binutils 2.30-22 instead.
|
||||
RUN curl -s -o binutils_2.30-22_amd64.deb http://snapshot.debian.org/archive/debian/20180622T211149Z/pool/main/b/binutils/binutils_2.30-22_amd64.deb \
|
||||
&& curl -s -o libbinutils_2.30-22_amd64.deb http://snapshot.debian.org/archive/debian/20180622T211149Z/pool/main/b/binutils/libbinutils_2.30-22_amd64.deb \
|
||||
&& curl -s -o binutils-x86-64-linux-gnu_2.30-22_amd64.deb http://snapshot.debian.org/archive/debian/20180622T211149Z/pool/main/b/binutils/binutils-x86-64-linux-gnu_2.30-22_amd64.deb \
|
||||
&& curl -s -o binutils-common_2.30-22_amd64.deb http://snapshot.debian.org/archive/debian/20180622T211149Z/pool/main/b/binutils/binutils-common_2.30-22_amd64.deb \
|
||||
&& dpkg -i *binutils*.deb
|
||||
|
||||
ENV CAPTURE_DURATION 120
|
||||
|
||||
COPY ./docker-entrypoint.sh /
|
||||
|
||||
RUN mkdir -p /captures
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
@@ -0,0 +1,7 @@
|
||||
all: build push
|
||||
|
||||
build:
|
||||
docker build -t sysdig/capturer .
|
||||
|
||||
push:
|
||||
docker push sysdig/capturer
|
||||
20
integrations/kubernetes-response-engine/sysdig-capturer/docker-entrypoint.sh
Executable file
20
integrations/kubernetes-response-engine/sysdig-capturer/docker-entrypoint.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eo
|
||||
|
||||
echo "* Setting up /usr/src links from host"
|
||||
|
||||
for i in $(ls $SYSDIG_HOST_ROOT/usr/src)
|
||||
do
|
||||
ln -s $SYSDIG_HOST_ROOT/usr/src/$i /usr/src/$i
|
||||
done
|
||||
|
||||
/usr/bin/sysdig-probe-loader
|
||||
|
||||
sysdig -S -M $CAPTURE_DURATION -pk -z -w /captures/$CAPTURE_FILE_NAME.scap.gz
|
||||
|
||||
if [ -n "$AWS_ACCESS_KEY_ID" ] && [ -n "$AWS_SECRET_ACCESS_KEY" ] && [ -n "$AWS_S3_BUCKET" ]; then
|
||||
s3cmd --access_key=$AWS_ACCESS_KEY_ID \
|
||||
--secret_key=$AWS_SECRET_ACCESS_KEY \
|
||||
put /captures/$CAPTURE_FILE_NAME.scap.gz $AWS_S3_BUCKET
|
||||
fi
|
||||
@@ -23,6 +23,7 @@ if(NOT DEFINED FALCO_RULES_DEST_FILENAME)
|
||||
set(FALCO_RULES_DEST_FILENAME "falco_rules.yaml")
|
||||
set(FALCO_LOCAL_RULES_DEST_FILENAME "falco_rules.local.yaml")
|
||||
set(FALCO_APP_RULES_DEST_FILENAME "application_rules.yaml")
|
||||
set(FALCO_K8S_AUDIT_RULES_DEST_FILENAME "k8s_audit_rules.yaml")
|
||||
endif()
|
||||
|
||||
if(DEFINED FALCO_COMPONENT)
|
||||
@@ -47,6 +48,10 @@ install(FILES falco_rules.local.yaml
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_LOCAL_RULES_DEST_FILENAME}")
|
||||
|
||||
install(FILES k8s_audit_rules.yaml
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_K8S_AUDIT_RULES_DEST_FILENAME}")
|
||||
|
||||
install(FILES application_rules.yaml
|
||||
DESTINATION "/etc/falco/rules.available"
|
||||
RENAME "${FALCO_APP_RULES_DEST_FILENAME}")
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
- required_engine_version: 2
|
||||
|
||||
################################################################
|
||||
# By default all application-related rules are disabled for
|
||||
# performance reasons. Depending on the application(s) you use,
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# See xxx for details on falco engine and rules versioning. Currently,
|
||||
# this specific rules file is compatible with engine version 0
|
||||
# (e.g. falco releases <= 0.13.1), so we'll keep the
|
||||
# required_engine_version lines commented out, so maintain
|
||||
# compatibility with older falco releases. With the first incompatible
|
||||
# change to this rules file, we'll uncomment this line and set it to
|
||||
# the falco engine version in use at the time.
|
||||
#
|
||||
#- required_engine_version: 2
|
||||
|
||||
# Currently disabled as read/write are ignored syscalls. The nearly
|
||||
# similar open_write/open_read check for files being opened for
|
||||
# reading/writing.
|
||||
@@ -136,7 +146,7 @@
|
||||
items: [docker, dockerd, exe, docker-compose, docker-entrypoi, docker-runc-cur, docker-current]
|
||||
|
||||
- list: k8s_binaries
|
||||
items: [hyperkube, skydns, kube2sky, exechealthz]
|
||||
items: [hyperkube, skydns, kube2sky, exechealthz, weave-net, loopback, bridge]
|
||||
|
||||
- list: lxd_binaries
|
||||
items: [lxd, lxcfs]
|
||||
@@ -170,7 +180,7 @@
|
||||
- list: rpm_binaries
|
||||
items: [dnf, rpm, rpmkey, yum, '"75-system-updat"', rhsmcertd-worke, subscription-ma,
|
||||
repoquery, rpmkeys, rpmq, yum-cron, yum-config-mana, yum-debug-dump,
|
||||
abrt-action-sav, rpmdb_stat, microdnf]
|
||||
abrt-action-sav, rpmdb_stat, microdnf, rhn_check, yumdb]
|
||||
|
||||
- macro: rpm_procs
|
||||
condition: proc.name in (rpm_binaries) or proc.name in (salt-minion)
|
||||
@@ -178,17 +188,23 @@
|
||||
- list: deb_binaries
|
||||
items: [dpkg, dpkg-preconfigu, dpkg-reconfigur, dpkg-divert, apt, apt-get, aptitude,
|
||||
frontend, preinst, add-apt-reposit, apt-auto-remova, apt-key,
|
||||
apt-listchanges, unattended-upgr, apt-add-reposit
|
||||
apt-listchanges, unattended-upgr, apt-add-reposit, apt-config, apt-cache
|
||||
]
|
||||
|
||||
# The truncated dpkg-preconfigu is intentional, process names are
|
||||
# truncated at the sysdig level.
|
||||
- list: package_mgmt_binaries
|
||||
items: [rpm_binaries, deb_binaries, update-alternat, gem, pip, pip3, sane-utils.post, alternatives, chef-client]
|
||||
items: [rpm_binaries, deb_binaries, update-alternat, gem, pip, pip3, sane-utils.post, alternatives, chef-client, apk]
|
||||
|
||||
- macro: package_mgmt_procs
|
||||
condition: proc.name in (package_mgmt_binaries)
|
||||
|
||||
- macro: package_mgmt_ancestor_procs
|
||||
condition: proc.pname in (package_mgmt_binaries) or
|
||||
proc.aname[2] in (package_mgmt_binaries) or
|
||||
proc.aname[3] in (package_mgmt_binaries) or
|
||||
proc.aname[4] in (package_mgmt_binaries)
|
||||
|
||||
- macro: coreos_write_ssh_dir
|
||||
condition: (proc.name=update-ssh-keys and fd.name startswith /home/core/.ssh)
|
||||
|
||||
@@ -199,12 +215,12 @@
|
||||
items: [ca-certificates]
|
||||
|
||||
- list: dhcp_binaries
|
||||
items: [dhclient, dhclient-script]
|
||||
items: [dhclient, dhclient-script, 11-dhclient]
|
||||
|
||||
# A canonical set of processes that run other programs with different
|
||||
# privileges or as a different user.
|
||||
- list: userexec_binaries
|
||||
items: [sudo, su, suexec]
|
||||
items: [sudo, su, suexec, critical-stack]
|
||||
|
||||
- list: known_setuid_binaries
|
||||
items: [
|
||||
@@ -220,7 +236,7 @@
|
||||
items: [blkid, rename_device, update_engine, sgdisk]
|
||||
|
||||
- list: hids_binaries
|
||||
items: [aide]
|
||||
items: [aide, aide.wrapper, update-aide.con, logcheck, syslog-summary, osqueryd, ossec-syscheckd]
|
||||
|
||||
- list: vpn_binaries
|
||||
items: [openvpn]
|
||||
@@ -242,7 +258,7 @@
|
||||
items: [
|
||||
update_conf, parse_mc, makemap_hash, newaliases, update_mk, update_tlsm4,
|
||||
update_db, update_mc, ssmtp.postinst, mailq, postalias, postfix.config.,
|
||||
postfix.config, postfix-script
|
||||
postfix.config, postfix-script, postconf
|
||||
]
|
||||
|
||||
- list: sensitive_file_names
|
||||
@@ -262,14 +278,18 @@
|
||||
# Network
|
||||
- macro: inbound
|
||||
condition: >
|
||||
(((evt.type in (accept,listen) and evt.dir=<)) or
|
||||
(((evt.type in (accept,listen) and evt.dir=<) or
|
||||
(evt.type in (recvfrom,recvmsg) and evt.dir=< and
|
||||
fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and
|
||||
(fd.typechar = 4 or fd.typechar = 6) and
|
||||
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and
|
||||
(evt.rawres >= 0 or evt.res = EINPROGRESS))
|
||||
|
||||
- macro: outbound
|
||||
condition: >
|
||||
(((evt.type = connect and evt.dir=<)) or
|
||||
(((evt.type = connect and evt.dir=<) or
|
||||
(evt.type in (sendto,sendmsg) and evt.dir=< and
|
||||
fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and
|
||||
(fd.typechar = 4 or fd.typechar = 6) and
|
||||
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and
|
||||
(evt.rawres >= 0 or evt.res = EINPROGRESS))
|
||||
@@ -362,6 +382,11 @@
|
||||
(proc.pname in (python, python2.7) and
|
||||
(proc.pcmdline contains /opt/draios/bin/sdchecks))
|
||||
|
||||
- macro: python_running_sdchecks
|
||||
condition: >
|
||||
(proc.name in (python, python2.7) and
|
||||
(proc.cmdline contains /opt/draios/bin/sdchecks))
|
||||
|
||||
- macro: parent_linux_image_upgrade_script
|
||||
condition: proc.pname startswith linux-image-
|
||||
|
||||
@@ -529,6 +554,9 @@
|
||||
- macro: perl_running_centrifydc
|
||||
condition: (proc.cmdline startswith "perl /usr/share/centrifydc")
|
||||
|
||||
- macro: runuser_reading_pam
|
||||
condition: (proc.name=runuser and fd.directory=/etc/pam.d)
|
||||
|
||||
- macro: parent_ucf_writing_conf
|
||||
condition: (proc.pname=ucf and proc.aname[2]=frontend)
|
||||
|
||||
@@ -572,11 +600,14 @@
|
||||
condition: (proc.pname=run-openldap.sh and fd.name startswith /etc/openldap)
|
||||
|
||||
- macro: ucpagent_writing_conf
|
||||
condition: (proc.name=apiserver and container.image startswith docker/ucp-agent and fd.name=/etc/authorization_config.cfg)
|
||||
condition: (proc.name=apiserver and container.image.repository=docker/ucp-agent and fd.name=/etc/authorization_config.cfg)
|
||||
|
||||
- macro: iscsi_writing_conf
|
||||
condition: (proc.name=iscsiadm and fd.name startswith /etc/iscsi)
|
||||
|
||||
- macro: istio_writing_conf
|
||||
condition: (proc.name=pilot-agent and fd.name startswith /etc/istio)
|
||||
|
||||
- macro: symantec_writing_conf
|
||||
condition: >
|
||||
((proc.name=symcfgd and fd.name startswith /etc/symantec) or
|
||||
@@ -617,7 +648,7 @@
|
||||
condition: (veritas_progs and (fd.name startswith /etc/vx or fd.name startswith /etc/opt/VRTS or fd.name startswith /etc/vom))
|
||||
|
||||
- macro: nginx_writing_conf
|
||||
condition: (proc.name=nginx and fd.name startswith /etc/nginx)
|
||||
condition: (proc.name in (nginx,nginx-ingress-c) and fd.name startswith /etc/nginx)
|
||||
|
||||
- macro: nginx_writing_certs
|
||||
condition: >
|
||||
@@ -669,6 +700,12 @@
|
||||
- macro: maven_writing_groovy
|
||||
condition: (proc.name=java and proc.cmdline contains "classpath /usr/local/apache-maven" and fd.name startswith /root/.groovy)
|
||||
|
||||
- macro: chef_writing_conf
|
||||
condition: (proc.name=chef-client and fd.name startswith /root/.chef)
|
||||
|
||||
- macro: kubectl_writing_state
|
||||
condition: (proc.name=kubectl and fd.name startswith /root/.kube)
|
||||
|
||||
- rule: Write below binary dir
|
||||
desc: an attempt to write to any file below a set of binary directories
|
||||
condition: >
|
||||
@@ -698,6 +735,13 @@
|
||||
- macro: user_ssh_directory
|
||||
condition: (fd.name startswith '/home' and fd.name contains '.ssh')
|
||||
|
||||
# google_accounts_(daemon)
|
||||
- macro: google_accounts_daemon_writing_ssh
|
||||
condition: (proc.name=google_accounts and user_ssh_directory)
|
||||
|
||||
- macro: cloud_init_writing_ssh
|
||||
condition: (proc.name=cloud-init and user_ssh_directory)
|
||||
|
||||
- macro: mkinitramfs_writing_boot
|
||||
condition: (proc.pname in (mkinitramfs, update-initramf) and fd.directory=/boot)
|
||||
|
||||
@@ -716,6 +760,8 @@
|
||||
and not exe_running_docker_save
|
||||
and not python_running_get_pip
|
||||
and not python_running_ms_oms
|
||||
and not google_accounts_daemon_writing_ssh
|
||||
and not cloud_init_writing_ssh
|
||||
output: >
|
||||
File below a monitored directory opened for writing (user=%user.name
|
||||
command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2])
|
||||
@@ -776,7 +822,7 @@
|
||||
condition: (proc.name=rabbitmq-server and fd.directory=/etc/rabbitmq)
|
||||
|
||||
- macro: rook_writing_conf
|
||||
condition: (proc.name=toolbox.sh and container.image startswith rook/toolbox
|
||||
condition: (proc.name=toolbox.sh and container.image.repository=rook/toolbox
|
||||
and fd.directory=/etc/ceph)
|
||||
|
||||
- macro: httpd_writing_conf_logs
|
||||
@@ -812,6 +858,19 @@
|
||||
- macro: dpkg_scripting
|
||||
condition: (proc.aname[2] in (dpkg-reconfigur, dpkg-preconfigu))
|
||||
|
||||
- macro: ufw_writing_conf
|
||||
condition: (proc.name=ufw and fd.directory=/etc/ufw)
|
||||
|
||||
- macro: calico_writing_conf
|
||||
condition: >
|
||||
(proc.name = calico-node and fd.name startswith /etc/calico)
|
||||
|
||||
- macro: prometheus_conf_writing_conf
|
||||
condition: (proc.name=prometheus-conf and fd.directory=/etc/prometheus/config_out)
|
||||
|
||||
- macro: openshift_writing_conf
|
||||
condition: (proc.name=oc and fd.name=/etc/origin/node/node.kubeconfig)
|
||||
|
||||
# Add conditions to this macro (probably in a separate file,
|
||||
# overwriting this macro) to allow for specific combinations of
|
||||
# programs writing below specific directories below
|
||||
@@ -912,6 +971,11 @@
|
||||
and not openldap_writing_conf
|
||||
and not ucpagent_writing_conf
|
||||
and not iscsi_writing_conf
|
||||
and not istio_writing_conf
|
||||
and not ufw_writing_conf
|
||||
and not calico_writing_conf
|
||||
and not prometheus_conf_writing_conf
|
||||
and not openshift_writing_conf
|
||||
|
||||
- rule: Write below etc
|
||||
desc: an attempt to write to any file below /etc
|
||||
@@ -923,7 +987,7 @@
|
||||
- list: known_root_files
|
||||
items: [/root/.monit.state, /root/.auth_tokens, /root/.bash_history, /root/.ash_history, /root/.aws/credentials,
|
||||
/root/.viminfo.tmp, /root/.lesshst, /root/.bzr.log, /root/.gitconfig.lock, /root/.babel.json, /root/.localstack,
|
||||
/root/.node_repl_history, /root/.mongorc.js, /root/.dbshell, /root/.augeas/history, /root/.rnd, /root/.wget-hsts]
|
||||
/root/.node_repl_history, /root/.mongorc.js, /root/.dbshell, /root/.augeas/history, /root/.rnd, /root/.wget-hsts, /health]
|
||||
|
||||
- list: known_root_directories
|
||||
items: [/root/.oracle_jre_usage, /root/.ssh, /root/.subversion, /root/.nami]
|
||||
@@ -978,6 +1042,8 @@
|
||||
and not airflow_writing_state
|
||||
and not rpm_writing_root_rpmdb
|
||||
and not maven_writing_groovy
|
||||
and not chef_writing_conf
|
||||
and not kubectl_writing_state
|
||||
and not known_root_conditions
|
||||
output: "File below / or /root opened for writing (user=%user.name command=%proc.cmdline parent=%proc.pname file=%fd.name program=%proc.name)"
|
||||
priority: ERROR
|
||||
@@ -1040,6 +1106,7 @@
|
||||
and not perl_running_updmap
|
||||
and not veritas_driver_script
|
||||
and not perl_running_centrifydc
|
||||
and not runuser_reading_pam
|
||||
output: >
|
||||
Sensitive file opened for reading by non-trusted program (user=%user.name program=%proc.name
|
||||
command=%proc.cmdline file=%fd.name parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4])
|
||||
@@ -1119,10 +1186,11 @@
|
||||
as a part of creating a container) by calling setns.
|
||||
condition: >
|
||||
evt.type = setns
|
||||
and not proc.name in (docker_binaries, k8s_binaries, lxd_binaries, sysdigcloud_binaries, sysdig, nsenter)
|
||||
and not proc.name in (docker_binaries, k8s_binaries, lxd_binaries, sysdigcloud_binaries, sysdig, nsenter, calico)
|
||||
and not proc.name in (user_known_change_thread_namespace_binaries)
|
||||
and not proc.name startswith "runc:"
|
||||
and not proc.pname in (sysdigcloud_binaries)
|
||||
and not python_running_sdchecks
|
||||
and not java_running_sdjagent
|
||||
and not kubelet_running_loopback
|
||||
output: >
|
||||
@@ -1277,32 +1345,45 @@
|
||||
priority: DEBUG
|
||||
tags: [shell]
|
||||
|
||||
- macro: allowed_openshift_registry_root
|
||||
condition: >
|
||||
(container.image.repository startswith openshift3/ or
|
||||
container.image.repository startswith registry.access.redhat.com/openshift3/)
|
||||
|
||||
# Source: https://docs.openshift.com/enterprise/3.2/install_config/install/disconnected_install.html
|
||||
- macro: openshift_image
|
||||
condition: >
|
||||
(allowed_openshift_registry_root and
|
||||
(container.image.repository contains logging-deployment or
|
||||
container.image.repository contains logging-elasticsearch or
|
||||
container.image.repository contains logging-kibana or
|
||||
container.image.repository contains logging-fluentd or
|
||||
container.image.repository contains logging-auth-proxy or
|
||||
container.image.repository contains metrics-deployer or
|
||||
container.image.repository contains metrics-hawkular-metrics or
|
||||
container.image.repository contains metrics-cassandra or
|
||||
container.image.repository contains metrics-heapster or
|
||||
container.image.repository contains ose-haproxy-router or
|
||||
container.image.repository contains ose-deployer or
|
||||
container.image.repository contains ose-sti-builder or
|
||||
container.image.repository contains ose-docker-builder or
|
||||
container.image.repository contains ose-pod or
|
||||
container.image.repository contains ose-docker-registry or
|
||||
container.image.repository contains image-inspector))
|
||||
|
||||
- list: trusted_images
|
||||
items: [
|
||||
sysdig/agent, sysdig/falco, sysdig/sysdig, gcr.io/google_containers/hyperkube,
|
||||
quay.io/coreos/flannel, gcr.io/google_containers/kube-proxy, calico/node,
|
||||
rook/toolbox, cloudnativelabs/kube-router, consul, mesosphere/mesos-slave,
|
||||
datadog/docker-dd-agent, datadog/agent, docker/ucp-agent, gliderlabs/logspout
|
||||
]
|
||||
|
||||
- macro: trusted_containers
|
||||
condition: (container.image startswith sysdig/agent or
|
||||
(container.image startswith sysdig/falco and
|
||||
not container.image startswith sysdig/falco-event-generator) or
|
||||
container.image startswith quay.io/sysdig or
|
||||
container.image startswith sysdig/sysdig or
|
||||
container.image startswith gcr.io/google_containers/hyperkube or
|
||||
container.image startswith quay.io/coreos/flannel or
|
||||
container.image startswith gcr.io/google_containers/kube-proxy or
|
||||
container.image startswith calico/node or
|
||||
container.image startswith rook/toolbox or
|
||||
container.image startswith registry.access.redhat.com/openshift3/logging-fluentd or
|
||||
container.image startswith registry.access.redhat.com/openshift3/logging-elasticsearch or
|
||||
container.image startswith registry.access.redhat.com/openshift3/metrics-cassandra or
|
||||
container.image startswith openshift3/ose-sti-builder or
|
||||
container.image startswith registry.access.redhat.com/openshift3/ose-sti-builder or
|
||||
container.image startswith registry.access.redhat.com/openshift3/ose-docker-builder or
|
||||
container.image startswith registry.access.redhat.com/openshift3/image-inspector or
|
||||
container.image startswith cloudnativelabs/kube-router or
|
||||
container.image startswith "consul:" or
|
||||
container.image startswith mesosphere/mesos-slave or
|
||||
container.image startswith istio/proxy_ or
|
||||
container.image startswith datadog/docker-dd-agent or
|
||||
container.image startswith datadog/agent or
|
||||
container.image startswith docker/ucp-agent or
|
||||
container.image startswith gliderlabs/logspout)
|
||||
condition: (openshift_image or
|
||||
container.image.repository in (trusted_images) or
|
||||
container.image.repository startswith istio/proxy_ or
|
||||
container.image.repository startswith quay.io/sysdig)
|
||||
|
||||
# Add conditions to this macro (probably in a separate file,
|
||||
# overwriting this macro) to specify additional containers that are
|
||||
@@ -1311,7 +1392,7 @@
|
||||
# In this file, it just takes one of the images in trusted_containers
|
||||
# and repeats it.
|
||||
- macro: user_trusted_containers
|
||||
condition: (container.image startswith sysdig/agent)
|
||||
condition: (container.image.repository=sysdig/agent)
|
||||
|
||||
# Add conditions to this macro (probably in a separate file,
|
||||
# overwriting this macro) to specify additional containers that are
|
||||
@@ -1320,7 +1401,7 @@
|
||||
# In this file, it just takes one of the images in trusted_containers
|
||||
# and repeats it.
|
||||
- macro: user_sensitive_mount_containers
|
||||
condition: (container.image startswith sysdig/agent)
|
||||
condition: (container.image.repository=sysdig/agent)
|
||||
|
||||
- rule: Launch Privileged Container
|
||||
desc: Detect the initial process started in a privileged container. Exceptions are made for known trusted images.
|
||||
@@ -1329,7 +1410,7 @@
|
||||
and container.privileged=true
|
||||
and not trusted_containers
|
||||
and not user_trusted_containers
|
||||
output: Privileged container started (user=%user.name command=%proc.cmdline %container.info image=%container.image)
|
||||
output: Privileged container started (user=%user.name command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
||||
priority: INFO
|
||||
tags: [container, cis]
|
||||
|
||||
@@ -1340,6 +1421,8 @@
|
||||
- macro: sensitive_mount
|
||||
condition: (container.mount.dest[/proc*] != "N/A" or
|
||||
container.mount.dest[/var/run/docker.sock] != "N/A" or
|
||||
container.mount.dest[/var/lib/kubelet] != "N/A" or
|
||||
container.mount.dest[/var/lib/kubelet/pki] != "N/A" or
|
||||
container.mount.dest[/] != "N/A" or
|
||||
container.mount.dest[/etc] != "N/A" or
|
||||
container.mount.dest[/root*] != "N/A")
|
||||
@@ -1367,7 +1450,7 @@
|
||||
and sensitive_mount
|
||||
and not trusted_containers
|
||||
and not user_sensitive_mount_containers
|
||||
output: Container with sensitive mount started (user=%user.name command=%proc.cmdline %container.info image=%container.image mounts=%container.mounts)
|
||||
output: Container with sensitive mount started (user=%user.name command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag mounts=%container.mounts)
|
||||
priority: INFO
|
||||
tags: [container, cis]
|
||||
|
||||
@@ -1378,8 +1461,8 @@
|
||||
# alllowed, by using a filter that is guaranteed to evaluate to true
|
||||
# (the same proc.vpid=1 that's in the Launch Disallowed Container
|
||||
# rule). In the overridden macro, the condition would look something
|
||||
# like (container.image startswith vendor/container-1 or
|
||||
# container.image startswith vendor/container-2 or ...)
|
||||
# like (container.image.repository = vendor/container-1 or
|
||||
# container.image.repository = vendor/container-2 or ...)
|
||||
|
||||
- macro: allowed_containers
|
||||
condition: (proc.vpid=1)
|
||||
@@ -1388,7 +1471,7 @@
|
||||
desc: >
|
||||
Detect the initial process started by a container that is not in a list of allowed containers.
|
||||
condition: evt.type=execve and proc.vpid=1 and container and not allowed_containers
|
||||
output: Container started and not in allowed list (user=%user.name command=%proc.cmdline %container.info image=%container.image)
|
||||
output: Container started and not in allowed list (user=%user.name command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
||||
priority: WARNING
|
||||
tags: [container]
|
||||
|
||||
@@ -1630,8 +1713,8 @@
|
||||
# any way to know all the containers that should have access, so any
|
||||
# container is alllowed, by repeating the "container" macro. In the
|
||||
# overridden macro, the condition would look something like
|
||||
# (container.image startswith vendor/container-1 or container.image
|
||||
# startswith vendor/container-2 or ...)
|
||||
# (container.image.repository = vendor/container-1 or
|
||||
# container.image.repository = vendor/container-2 or ...)
|
||||
- macro: ec2_metadata_containers
|
||||
condition: container
|
||||
|
||||
@@ -1641,7 +1724,7 @@
|
||||
- rule: Contact EC2 Instance Metadata Service From Container
|
||||
desc: Detect attempts to contact the EC2 Instance Metadata Service from a container
|
||||
condition: outbound and fd.sip="169.254.169.254" and container and not ec2_metadata_containers
|
||||
output: Outbound connection to EC2 instance metadata service (command=%proc.cmdline connection=%fd.name %container.info image=%container.image)
|
||||
output: Outbound connection to EC2 instance metadata service (command=%proc.cmdline connection=%fd.name %container.info image=%container.image.repository:%container.image.tag)
|
||||
priority: NOTICE
|
||||
tags: [network, aws, container]
|
||||
|
||||
@@ -1657,16 +1740,14 @@
|
||||
# within a container.
|
||||
- macro: k8s_containers
|
||||
condition: >
|
||||
(container.image startswith gcr.io/google_containers/hyperkube-amd64 or
|
||||
container.image startswith gcr.io/google_containers/kube2sky or
|
||||
container.image startswith sysdig/agent or
|
||||
container.image startswith sysdig/falco or
|
||||
container.image startswith sysdig/sysdig)
|
||||
(container.image.repository in (gcr.io/google_containers/hyperkube-amd64,
|
||||
gcr.io/google_containers/kube2sky, sysdig/agent, sysdig/falco,
|
||||
sysdig/sysdig))
|
||||
|
||||
- rule: Contact K8S API Server From Container
|
||||
desc: Detect attempts to contact the K8S API Server from a container
|
||||
condition: outbound and k8s_api_server and container and not k8s_containers
|
||||
output: Unexpected connection to K8s API Server from container (command=%proc.cmdline %container.info image=%container.image connection=%fd.name)
|
||||
output: Unexpected connection to K8s API Server from container (command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag connection=%fd.name)
|
||||
priority: NOTICE
|
||||
tags: [network, k8s, container]
|
||||
|
||||
@@ -1686,6 +1767,46 @@
|
||||
priority: NOTICE
|
||||
tags: [network, k8s, container]
|
||||
|
||||
- list: network_tool_binaries
|
||||
items: [nc, ncat, nmap]
|
||||
|
||||
- macro: network_tool_procs
|
||||
condition: proc.name in (network_tool_binaries)
|
||||
|
||||
# Container is supposed to be immutable. Package management should be done in building the image.
|
||||
- rule: Launch Package Management Process in Container
|
||||
desc: Package management process ran inside container
|
||||
condition: >
|
||||
spawned_process and container and user.name != "_apt" and package_mgmt_procs and not package_mgmt_ancestor_procs
|
||||
output: >
|
||||
Package management process launched in container (user=%user.name
|
||||
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
priority: ERROR
|
||||
tags: [process]
|
||||
|
||||
- rule: Netcat Remote Code Execution in Container
|
||||
desc: Netcat Program runs inside container that allows remote code execution
|
||||
condition: >
|
||||
spawned_process and container and
|
||||
((proc.name = "nc" and (proc.args contains "-e" or proc.args contains "-c")) or
|
||||
(proc.name = "ncat" and (proc.args contains "--sh-exec" or proc.args contains "--exec"))
|
||||
)
|
||||
output: >
|
||||
Netcat runs inside container that allows remote code execution (user=%user.name
|
||||
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
priority: WARNING
|
||||
tags: [network, process]
|
||||
|
||||
- rule: Lauch Suspicious Network Tool in Container
|
||||
desc: Detect network tools launched inside container
|
||||
condition: >
|
||||
spawned_process and container and network_tool_procs
|
||||
output: >
|
||||
Network tool launched in container (user=%user.name
|
||||
command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
priority: NOTICE
|
||||
tags: [network, process]
|
||||
|
||||
# Application rules have moved to application_rules.yaml. Please look
|
||||
# there if you want to enable them by adding to
|
||||
# falco_rules.local.yaml.
|
||||
|
||||
437
rules/k8s_audit_rules.yaml
Normal file
437
rules/k8s_audit_rules.yaml
Normal file
@@ -0,0 +1,437 @@
|
||||
#
|
||||
# Copyright (C) 2016-2018 Draios Inc dba Sysdig.
|
||||
#
|
||||
# This file is part of falco.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
- required_engine_version: 2
|
||||
|
||||
# Generally only consider audit events once the response has completed
|
||||
- list: k8s_audit_stages
|
||||
items: ["ResponseComplete"]
|
||||
|
||||
# Generally exclude users starting with "system:"
|
||||
- macro: non_system_user
|
||||
condition: (not ka.user.name startswith "system:")
|
||||
|
||||
# This macro selects the set of Audit Events used by the below rules.
|
||||
- macro: kevt
|
||||
condition: (jevt.value[/stage] in (k8s_audit_stages))
|
||||
|
||||
- macro: kevt_started
|
||||
condition: (jevt.value[/stage]=ResponseStarted)
|
||||
|
||||
# If you wish to restrict activity to a specific set of users, override/append to this list.
|
||||
- list: allowed_k8s_users
|
||||
items: ["minikube", "minikube-user"]
|
||||
|
||||
- rule: Disallowed K8s User
|
||||
desc: Detect any k8s operation by users outside of an allowed set of users.
|
||||
condition: kevt and non_system_user and not ka.user.name in (allowed_k8s_users)
|
||||
output: K8s Operation performed by user not in allowed list of users (user=%ka.user.name target=%ka.target.name/%ka.target.resource verb=%ka.verb uri=%ka.uri resp=%ka.response.code)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# In a local/user rules file, you could override this macro to
|
||||
# explicitly enumerate the container images that you want to run in
|
||||
# your environment. In this main falco rules file, there isn't any way
|
||||
# to know all the containers that can run, so any container is
|
||||
# alllowed, by using a filter that is guaranteed to evaluate to true
|
||||
# (the event time existing). In the overridden macro, the condition
|
||||
# would look something like (ka.req.container.image.repository=my-repo/my-image)
|
||||
- macro: allowed_k8s_containers
|
||||
condition: (jevt.rawtime exists)
|
||||
|
||||
- macro: response_successful
|
||||
condition: (ka.response.code startswith 2)
|
||||
|
||||
- macro: kcreate
|
||||
condition: ka.verb=create
|
||||
|
||||
- macro: kmodify
|
||||
condition: (ka.verb in (create,update,patch))
|
||||
|
||||
- macro: kdelete
|
||||
condition: ka.verb=delete
|
||||
|
||||
- macro: pod
|
||||
condition: ka.target.resource=pods and not ka.target.subresource exists
|
||||
|
||||
- macro: pod_subresource
|
||||
condition: ka.target.resource=pods and ka.target.subresource exists
|
||||
|
||||
- macro: deployment
|
||||
condition: ka.target.resource=deployments
|
||||
|
||||
- macro: service
|
||||
condition: ka.target.resource=services
|
||||
|
||||
- macro: configmap
|
||||
condition: ka.target.resource=configmaps
|
||||
|
||||
- macro: namespace
|
||||
condition: ka.target.resource=namespaces
|
||||
|
||||
- macro: serviceaccount
|
||||
condition: ka.target.resource=serviceaccounts
|
||||
|
||||
- macro: clusterrole
|
||||
condition: ka.target.resource=clusterroles
|
||||
|
||||
- macro: clusterrolebinding
|
||||
condition: ka.target.resource=clusterrolebindings
|
||||
|
||||
- macro: role
|
||||
condition: ka.target.resource=roles
|
||||
|
||||
- macro: health_endpoint
|
||||
condition: ka.uri=/healthz
|
||||
|
||||
- rule: Create Disallowed Pod
|
||||
desc: >
|
||||
Detect an attempt to start a pod with a container image outside of a list of allowed images.
|
||||
condition: kevt and pod and kcreate and not allowed_k8s_containers
|
||||
output: Pod started with container not in allowed list (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace image=%ka.req.container.image)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- list: trusted_k8s_containers
|
||||
items: [sysdig/agent, sysdig/falco, quay.io/coreos/flannel, calico/node, rook/toolbox,
|
||||
gcr.io/google_containers/hyperkube, gcr.io/google_containers/kube-proxy,
|
||||
openshift3/ose-sti-builder,
|
||||
registry.access.redhat.com/openshift3/logging-fluentd,
|
||||
registry.access.redhat.com/openshift3/logging-elasticsearch,
|
||||
registry.access.redhat.com/openshift3/metrics-cassandra,
|
||||
registry.access.redhat.com/openshift3/ose-sti-builder,
|
||||
registry.access.redhat.com/openshift3/ose-docker-builder,
|
||||
registry.access.redhat.com/openshift3/image-inspector,
|
||||
cloudnativelabs/kube-router, istio/proxy,
|
||||
datadog/docker-dd-agent, datadog/agent,
|
||||
docker/ucp-agent,
|
||||
gliderlabs/logspout]
|
||||
|
||||
- rule: Create Privileged Pod
|
||||
desc: >
|
||||
Detect an attempt to start a pod with a privileged container
|
||||
condition: kevt and pod and kcreate and ka.req.container.privileged=true and not ka.req.container.image.repository in (trusted_k8s_containers)
|
||||
output: Pod started with privileged container (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace image=%ka.req.container.image)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- macro: sensitive_vol_mount
|
||||
condition: >
|
||||
(ka.req.volume.hostpath[/proc*]=true or
|
||||
ka.req.volume.hostpath[/var/run/docker.sock]=true or
|
||||
ka.req.volume.hostpath[/]=true or
|
||||
ka.req.volume.hostpath[/etc]=true or
|
||||
ka.req.volume.hostpath[/root*]=true)
|
||||
|
||||
- rule: Create Sensitive Mount Pod
|
||||
desc: >
|
||||
Detect an attempt to start a pod with a volume from a sensitive host directory (i.e. /proc).
|
||||
Exceptions are made for known trusted images.
|
||||
condition: kevt and pod and kcreate and sensitive_vol_mount and not ka.req.container.image.repository in (trusted_k8s_containers)
|
||||
output: Pod started with sensitive mount (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace image=%ka.req.container.image mounts=%jevt.value[/requestObject/spec/volumes])
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# Corresponds to K8s CIS Benchmark 1.7.4
|
||||
- rule: Create HostNetwork Pod
|
||||
desc: Detect an attempt to start a pod using the host network.
|
||||
condition: kevt and pod and kcreate and ka.req.container.host_network=true and not ka.req.container.image.repository in (trusted_k8s_containers)
|
||||
output: Pod started using host network (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace image=%ka.req.container.image)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: Create NodePort Service
|
||||
desc: >
|
||||
Detect an attempt to start a service with a NodePort service type
|
||||
condition: kevt and service and kcreate and ka.req.service.type=NodePort
|
||||
output: NodePort Service Created (user=%ka.user.name service=%ka.target.name ns=%ka.target.namespace ports=%ka.req.service.ports)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- macro: contains_private_credentials
|
||||
condition: >
|
||||
(ka.req.configmap.obj contains "aws_access_key_id" or
|
||||
ka.req.configmap.obj contains "aws-access-key-id" or
|
||||
ka.req.configmap.obj contains "aws_s3_access_key_id" or
|
||||
ka.req.configmap.obj contains "aws-s3-access-key-id" or
|
||||
ka.req.configmap.obj contains "password" or
|
||||
ka.req.configmap.obj contains "passphrase")
|
||||
|
||||
- rule: Create/Modify Configmap With Private Credentials
|
||||
desc: >
|
||||
Detect creating/modifying a configmap containing a private credential (aws key, password, etc.)
|
||||
condition: kevt and configmap and kmodify and contains_private_credentials
|
||||
output: K8s configmap with private credential (user=%ka.user.name verb=%ka.verb configmap=%ka.req.configmap.name config=%ka.req.configmap.obj)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# Corresponds to K8s CIS Benchmark, 1.1.1.
|
||||
- rule: Anonymous Request Allowed
|
||||
desc: >
|
||||
Detect any request made by the anonymous user that was allowed
|
||||
condition: kevt and ka.user.name=system:anonymous and ka.auth.decision!=reject and not health_endpoint
|
||||
output: Request by anonymous user allowed (user=%ka.user.name verb=%ka.verb uri=%ka.uri reason=%ka.auth.reason))
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# Roughly corresponds to K8s CIS Benchmark, 1.1.12. In this case,
|
||||
# notifies an attempt to exec/attach to a privileged container.
|
||||
|
||||
# Ideally, we'd add a more stringent rule that detects attaches/execs
|
||||
# to a privileged pod, but that requires the engine for k8s audit
|
||||
# events to be stateful, so it could know if a container named in an
|
||||
# attach request was created privileged or not. For now, we have a
|
||||
# less severe rule that detects attaches/execs to any pod.
|
||||
|
||||
- rule: Attach/Exec Pod
|
||||
desc: >
|
||||
Detect any attempt to attach/exec to a pod
|
||||
condition: kevt_started and pod_subresource and kcreate and ka.target.subresource in (exec,attach)
|
||||
output: Attach/Exec to pod (user=%ka.user.name pod=%ka.target.name ns=%ka.target.namespace action=%ka.target.subresource command=%ka.uri.param[command])
|
||||
priority: NOTICE
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# In a local/user rules fie, you can append to this list to add additional allowed namespaces
|
||||
- list: allowed_namespaces
|
||||
items: [kube-system, kube-public, default]
|
||||
|
||||
- rule: Create Disallowed Namespace
|
||||
desc: Detect any attempt to create a namespace outside of a set of known namespaces
|
||||
condition: kevt and namespace and kcreate and not ka.target.name in (allowed_namespaces)
|
||||
output: Disallowed namespace created (user=%ka.user.name ns=%ka.target.name)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# Detect any new pod created in the kube-system namespace
|
||||
- rule: Pod Created in Kube Namespace
|
||||
desc: Detect any attempt to create a pod in the kube-system or kube-public namespaces
|
||||
condition: kevt and pod and kcreate and ka.target.namespace in (kube-system, kube-public)
|
||||
output: Pod created in kube namespace (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace image=%ka.req.container.image)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# Detect creating a service account in the kube-system/kube-public namespace
|
||||
- rule: Service Account Created in Kube Namespace
|
||||
desc: Detect any attempt to create a serviceaccount in the kube-system or kube-public namespaces
|
||||
condition: kevt and serviceaccount and kcreate and ka.target.namespace in (kube-system, kube-public)
|
||||
output: Service account created in kube namespace (user=%ka.user.name serviceaccount=%ka.target.name ns=%ka.target.namespace)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# Detect any modify/delete to any ClusterRole starting with
|
||||
# "system:". "system:coredns" is excluded as changes are expected in
|
||||
# normal operation.
|
||||
- rule: System ClusterRole Modified/Deleted
|
||||
desc: Detect any attempt to modify/delete a ClusterRole/Role starting with system
|
||||
condition: kevt and (role or clusterrole) and (kmodify or kdelete) and (ka.target.name startswith "system:") and ka.target.name!="system:coredns"
|
||||
output: System ClusterRole/Role modified or deleted (user=%ka.user.name role=%ka.target.name ns=%ka.target.namespace action=%ka.verb)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# Detect any attempt to create a ClusterRoleBinding to the cluster-admin user
|
||||
# (exapand this to any built-in cluster role that does "sensitive" things)
|
||||
- rule: Attach to cluster-admin Role
|
||||
desc: Detect any attempt to create a ClusterRoleBinding to the cluster-admin user
|
||||
condition: kevt and clusterrolebinding and kcreate and ka.req.binding.role=cluster-admin
|
||||
output: Cluster Role Binding to cluster-admin role (user=%ka.user.name subject=%ka.req.binding.subjects)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: ClusterRole With Wildcard Created
|
||||
desc: Detect any attempt to create a Role/ClusterRole with wildcard resources or verbs
|
||||
condition: kevt and (role or clusterrole) and kcreate and (ka.req.role.rules.resources contains '"*"' or ka.req.role.rules.verbs contains '"*"')
|
||||
output: Created Role/ClusterRole with wildcard (user=%ka.user.name role=%ka.target.name rules=%ka.req.role.rules)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- macro: writable_verbs
|
||||
condition: >
|
||||
(ka.req.role.rules.verbs contains create or
|
||||
ka.req.role.rules.verbs contains update or
|
||||
ka.req.role.rules.verbs contains patch or
|
||||
ka.req.role.rules.verbs contains delete or
|
||||
ka.req.role.rules.verbs contains deletecollection)
|
||||
|
||||
- rule: ClusterRole With Write Privileges Created
|
||||
desc: Detect any attempt to create a Role/ClusterRole that can perform write-related actions
|
||||
condition: kevt and (role or clusterrole) and kcreate and writable_verbs
|
||||
output: Created Role/ClusterRole with write privileges (user=%ka.user.name role=%ka.target.name rules=%ka.req.role.rules)
|
||||
priority: NOTICE
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: ClusterRole With Pod Exec Created
|
||||
desc: Detect any attempt to create a Role/ClusterRole that can exec to pods
|
||||
condition: kevt and (role or clusterrole) and kcreate and ka.req.role.rules.resources contains "pods/exec"
|
||||
output: Created Role/ClusterRole with pod exec privileges (user=%ka.user.name role=%ka.target.name rules=%ka.req.role.rules)
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# The rules below this point are less discriminatory and generally
|
||||
# represent a stream of activity for a cluster. If you wish to disable
|
||||
# these events, modify the following macro.
|
||||
- macro: consider_activity_events
|
||||
condition: (jevt.rawtime exists)
|
||||
|
||||
- macro: kactivity
|
||||
condition: (kevt and consider_activity_events)
|
||||
|
||||
- rule: K8s Deployment Created
|
||||
desc: Detect any attempt to create a deployment
|
||||
condition: (kactivity and kcreate and deployment and response_successful)
|
||||
output: K8s Deployment Created (user=%ka.user.name deployment=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Deployment Deleted
|
||||
desc: Detect any attempt to delete a deployment
|
||||
condition: (kactivity and kdelete and deployment and response_successful)
|
||||
output: K8s Deployment Deleted (user=%ka.user.name deployment=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Service Created
|
||||
desc: Detect any attempt to create a service
|
||||
condition: (kactivity and kcreate and service and response_successful)
|
||||
output: K8s Service Created (user=%ka.user.name service=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Service Deleted
|
||||
desc: Detect any attempt to delete a service
|
||||
condition: (kactivity and kdelete and service and response_successful)
|
||||
output: K8s Service Deleted (user=%ka.user.name service=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s ConfigMap Created
|
||||
desc: Detect any attempt to create a configmap
|
||||
condition: (kactivity and kcreate and configmap and response_successful)
|
||||
output: K8s ConfigMap Created (user=%ka.user.name configmap=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s ConfigMap Deleted
|
||||
desc: Detect any attempt to delete a configmap
|
||||
condition: (kactivity and kdelete and configmap and response_successful)
|
||||
output: K8s ConfigMap Deleted (user=%ka.user.name configmap=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Namespace Created
|
||||
desc: Detect any attempt to create a namespace
|
||||
condition: (kactivity and kcreate and namespace and response_successful)
|
||||
output: K8s Namespace Created (user=%ka.user.name namespace=%ka.target.name resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Namespace Deleted
|
||||
desc: Detect any attempt to delete a namespace
|
||||
condition: (kactivity and non_system_user and kdelete and namespace and response_successful)
|
||||
output: K8s Namespace Deleted (user=%ka.user.name namespace=%ka.target.name resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Serviceaccount Created
|
||||
desc: Detect any attempt to create a service account
|
||||
condition: (kactivity and kcreate and serviceaccount and response_successful)
|
||||
output: K8s Serviceaccount Created (user=%ka.user.name user=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Serviceaccount Deleted
|
||||
desc: Detect any attempt to delete a service account
|
||||
condition: (kactivity and kdelete and serviceaccount and response_successful)
|
||||
output: K8s Serviceaccount Deleted (user=%ka.user.name user=%ka.target.name ns=%ka.target.namespace resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Role/Clusterrole Created
|
||||
desc: Detect any attempt to create a cluster role/role
|
||||
condition: (kactivity and kcreate and (clusterrole or role) and response_successful)
|
||||
output: K8s Cluster Role Created (user=%ka.user.name role=%ka.target.name rules=%ka.req.role.rules resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Role/Clusterrole Deleted
|
||||
desc: Detect any attempt to delete a cluster role/role
|
||||
condition: (kactivity and kdelete and (clusterrole or role) and response_successful)
|
||||
output: K8s Cluster Role Deleted (user=%ka.user.name role=%ka.target.name resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Role/Clusterrolebinding Created
|
||||
desc: Detect any attempt to create a clusterrolebinding
|
||||
condition: (kactivity and kcreate and clusterrolebinding and response_successful)
|
||||
output: K8s Cluster Role Binding Created (user=%ka.user.name binding=%ka.target.name subjects=%ka.req.binding.subjects role=%ka.req.binding.role resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason foo=%ka.req.binding.subject.has_name[cluster-admin])
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
- rule: K8s Role/Clusterrolebinding Deleted
|
||||
desc: Detect any attempt to delete a clusterrolebinding
|
||||
condition: (kactivity and kdelete and clusterrolebinding and response_successful)
|
||||
output: K8s Cluster Role Binding Deleted (user=%ka.user.name binding=%ka.target.name resp=%ka.response.code decision=%ka.auth.decision reason=%ka.auth.reason)
|
||||
priority: INFO
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# This rule generally matches all events, and as a result is disabled
|
||||
# by default. If you wish to enable these events, modify the
|
||||
# following macro.
|
||||
# condition: (jevt.rawtime exists)
|
||||
- macro: consider_all_events
|
||||
condition: (not jevt.rawtime exists)
|
||||
|
||||
- macro: kall
|
||||
condition: (kevt and consider_all_events)
|
||||
|
||||
- rule: All K8s Audit Events
|
||||
desc: Match all K8s Audit Events
|
||||
condition: kall
|
||||
output: K8s Audit Event received (user=%ka.user.name verb=%ka.verb uri=%ka.uri obj=%jevt.obj)
|
||||
priority: DEBUG
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
@@ -65,6 +65,9 @@ do_start()
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
if [ ! -d /sys/module/falco_probe ]; then
|
||||
/sbin/modprobe falco-probe || exit 1
|
||||
fi
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
@@ -94,6 +97,7 @@ do_stop()
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
/sbin/rmmod falco-probe
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright (C) 2016-2018 Draios Inc dba Sysdig.
|
||||
#
|
||||
@@ -16,7 +18,6 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#!/bin/sh
|
||||
#
|
||||
# falco syscall monitoring agent
|
||||
#
|
||||
@@ -53,6 +54,9 @@ start() {
|
||||
# [ -f $config ] || exit 6
|
||||
echo -n $"Starting $prog: "
|
||||
daemon $exec --daemon --pidfile=$pidfile
|
||||
if [ ! -d /sys/module/falco_probe ]; then
|
||||
/sbin/modprobe falco-probe || return $?
|
||||
fi
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && touch $lockfile
|
||||
@@ -64,6 +68,7 @@ stop() {
|
||||
killproc -p $pidfile
|
||||
retval=$?
|
||||
echo
|
||||
/sbin/rmmod falco-probe
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
465
test/falco_k8s_audit_tests.yaml
Normal file
465
test/falco_k8s_audit_tests.yaml
Normal file
@@ -0,0 +1,465 @@
|
||||
#
|
||||
# Copyright (C) 2016-2018 Draios Inc dba Sysdig.
|
||||
#
|
||||
# This file is part of falco.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
trace_files: !mux
|
||||
|
||||
user_outside_allowed_set:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/allow_namespace_foo.yaml
|
||||
detect_counts:
|
||||
- Disallowed K8s User: 1
|
||||
trace_file: trace_files/k8s_audit/some-user_creates_namespace_foo.json
|
||||
|
||||
user_in_allowed_set:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/allow_namespace_foo.yaml
|
||||
- ./rules/k8s_audit/allow_user_some-user.yaml
|
||||
- ./rules/k8s_audit/disallow_kactivity.yaml
|
||||
trace_file: trace_files/k8s_audit/some-user_creates_namespace_foo.json
|
||||
|
||||
create_disallowed_pod:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/allow_only_apache_container.yaml
|
||||
detect_counts:
|
||||
- Create Disallowed Pod: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_unprivileged.json
|
||||
|
||||
create_allowed_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/allow_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_unprivileged.json
|
||||
|
||||
create_privileged_pod:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Create Privileged Pod: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_privileged.json
|
||||
|
||||
create_privileged_2nd_container_pod:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Create Privileged Pod: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_privileged_2nd_container.json
|
||||
|
||||
create_privileged_trusted_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_privileged.json
|
||||
|
||||
create_unprivileged_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_unprivileged.json
|
||||
|
||||
create_unprivileged_trusted_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_unprivileged.json
|
||||
|
||||
create_sensitive_mount_pod:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Create Sensitive Mount Pod: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_sensitive_mount.json
|
||||
|
||||
create_sensitive_mount_2nd_container_pod:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Create Sensitive Mount Pod: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_sensitive_mount_2nd_container.json
|
||||
|
||||
create_sensitive_mount_trusted_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_sensitive_mount.json
|
||||
|
||||
create_unsensitive_mount_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_unsensitive_mount.json
|
||||
|
||||
create_unsensitive_mount_trusted_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_unsensitive_mount.json
|
||||
|
||||
create_hostnetwork_pod:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Create HostNetwork Pod: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_hostnetwork.json
|
||||
|
||||
create_hostnetwork_trusted_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_hostnetwork.json
|
||||
|
||||
create_nohostnetwork_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_nohostnetwork.json
|
||||
|
||||
create_nohostnetwork_trusted_pod:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_nohostnetwork.json
|
||||
|
||||
create_nodeport_service:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/disallow_kactivity.yaml
|
||||
detect_counts:
|
||||
- Create NodePort Service: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_service_nodeport.json
|
||||
|
||||
create_nonodeport_service:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/disallow_kactivity.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_service_nonodeport.json
|
||||
|
||||
create_configmap_private_creds:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/disallow_kactivity.yaml
|
||||
detect_counts:
|
||||
- Create/Modify Configmap With Private Credentials: 6
|
||||
trace_file: trace_files/k8s_audit/create_configmap_sensitive_values.json
|
||||
|
||||
create_configmap_no_private_creds:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/disallow_kactivity.yaml
|
||||
trace_file: trace_files/k8s_audit/create_configmap_no_sensitive_values.json
|
||||
|
||||
anonymous_user:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Anonymous Request Allowed: 1
|
||||
trace_file: trace_files/k8s_audit/anonymous_creates_namespace_foo.json
|
||||
|
||||
pod_exec:
|
||||
detect: True
|
||||
detect_level: NOTICE
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Attach/Exec Pod: 1
|
||||
trace_file: trace_files/k8s_audit/exec_pod.json
|
||||
|
||||
pod_attach:
|
||||
detect: True
|
||||
detect_level: NOTICE
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Attach/Exec Pod: 1
|
||||
trace_file: trace_files/k8s_audit/attach_pod.json
|
||||
|
||||
namespace_outside_allowed_set:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/allow_user_some-user.yaml
|
||||
detect_counts:
|
||||
- Create Disallowed Namespace: 1
|
||||
trace_file: trace_files/k8s_audit/some-user_creates_namespace_foo.json
|
||||
|
||||
namespace_in_allowed_set:
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/allow_namespace_foo.yaml
|
||||
- ./rules/k8s_audit/disallow_kactivity.yaml
|
||||
trace_file: trace_files/k8s_audit/minikube_creates_namespace_foo.json
|
||||
|
||||
create_pod_in_kube_system_namespace:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Pod Created in Kube Namespace: 1
|
||||
trace_file: trace_files/k8s_audit/create_pod_kube_system_namespace.json
|
||||
|
||||
create_pod_in_kube_public_namespace:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Pod Created in Kube Namespace: 1
|
||||
trace_file: trace_files/k8s_audit/create_pod_kube_public_namespace.json
|
||||
|
||||
create_serviceaccount_in_kube_system_namespace:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Service Account Created in Kube Namespace: 1
|
||||
trace_file: trace_files/k8s_audit/create_serviceaccount_kube_system_namespace.json
|
||||
|
||||
create_serviceaccount_in_kube_public_namespace:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Service Account Created in Kube Namespace: 1
|
||||
trace_file: trace_files/k8s_audit/create_serviceaccount_kube_public_namespace.json
|
||||
|
||||
system_clusterrole_deleted:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- System ClusterRole Modified/Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_cluster_role_kube_aggregator.json
|
||||
|
||||
system_clusterrole_modified:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- System ClusterRole Modified/Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/modify_cluster_role_node_problem_detector.json
|
||||
|
||||
attach_cluster_admin_role:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- Attach to cluster-admin Role: 1
|
||||
trace_file: trace_files/k8s_audit/attach_cluster_admin_role.json
|
||||
|
||||
create_cluster_role_wildcard_resources:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- ClusterRole With Wildcard Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_cluster_role_wildcard_resources.json
|
||||
|
||||
create_cluster_role_wildcard_verbs:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- ClusterRole With Wildcard Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_cluster_role_wildcard_verbs.json
|
||||
|
||||
create_writable_cluster_role:
|
||||
detect: True
|
||||
detect_level: NOTICE
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- ClusterRole With Write Privileges Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_cluster_role_write_privileges.json
|
||||
|
||||
create_pod_exec_cluster_role:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- ClusterRole With Pod Exec Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_cluster_role_pod_exec.json
|
||||
|
||||
create_deployment:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Deployment Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_deployment.json
|
||||
|
||||
delete_deployment:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Deployment Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_deployment.json
|
||||
|
||||
create_service:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Service Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_service.json
|
||||
|
||||
delete_service:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Service Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_service.json
|
||||
|
||||
create_configmap:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s ConfigMap Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_configmap.json
|
||||
|
||||
delete_configmap:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s ConfigMap Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_configmap.json
|
||||
|
||||
create_namespace:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/allow_namespace_foo.yaml
|
||||
- ./rules/k8s_audit/allow_user_some-user.yaml
|
||||
detect_counts:
|
||||
- K8s Namespace Created: 1
|
||||
trace_file: trace_files/k8s_audit/some-user_creates_namespace_foo.json
|
||||
|
||||
delete_namespace:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Namespace Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_namespace_foo.json
|
||||
|
||||
create_serviceaccount:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Serviceaccount Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_serviceaccount.json
|
||||
|
||||
delete_serviceaccount:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Serviceaccount Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_serviceaccount.json
|
||||
|
||||
create_clusterrole:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Role/Clusterrole Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_clusterrole.json
|
||||
|
||||
delete_clusterrole:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Role/Clusterrole Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_clusterrole.json
|
||||
|
||||
create_clusterrolebinding:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Role/Clusterrolebinding Created: 1
|
||||
trace_file: trace_files/k8s_audit/create_clusterrolebinding.json
|
||||
|
||||
delete_clusterrolebinding:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
detect_counts:
|
||||
- K8s Role/Clusterrolebinding Deleted: 1
|
||||
trace_file: trace_files/k8s_audit/delete_clusterrolebinding.json
|
||||
@@ -18,7 +18,7 @@
|
||||
trace_files: !mux
|
||||
|
||||
docker_package:
|
||||
package: docker:sysdig/falco:test
|
||||
package: docker:falcosecurity/falco:test
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file: /host/rules/rule_names_with_spaces.yaml
|
||||
@@ -33,7 +33,7 @@ trace_files: !mux
|
||||
# just to see if falco can load the driver.
|
||||
|
||||
docker_package_local_driver:
|
||||
package: docker:sysdig/falco:test
|
||||
package: docker:falcosecurity/falco:test
|
||||
addl_docker_run_args: -v /dev/null:/usr/sbin/dkms
|
||||
copy_local_driver: True
|
||||
detect: False
|
||||
@@ -264,6 +264,13 @@ trace_files: !mux
|
||||
- rules/rule_order.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
endswith:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/endswith.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
invalid_rule_output:
|
||||
exit_status: 1
|
||||
stderr_contains: "Runtime error: Error loading rules:.* Invalid output format 'An open was seen %not_a_real_field': 'invalid formatting token not_a_real_field'. Exiting."
|
||||
@@ -757,3 +764,10 @@ trace_files: !mux
|
||||
rules_file:
|
||||
- rules/skip_unknown_unspec.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
engine_version_mismatch:
|
||||
exit_status: 1
|
||||
stderr_contains: Rules require engine version 9999999, but engine version is
|
||||
rules_file:
|
||||
- rules/engine_version_mismatch.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
22
test/rules/endswith.yaml
Normal file
22
test/rules/endswith.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2016-2018 Draios Inc dba Sysdig.
|
||||
#
|
||||
# This file is part of falco.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
- rule: open_ending with null
|
||||
desc: A file ending with null is opened
|
||||
condition: evt.type=open and fd.name endswith null
|
||||
output: "An open was seen (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
34
test/rules/engine_version_mismatch.yaml
Normal file
34
test/rules/engine_version_mismatch.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# Copyright (C) 2016-2018 Draios Inc dba Sysdig.
|
||||
#
|
||||
# This file is part of falco.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
- required_engine_version: 9999999
|
||||
|
||||
- list: cat_binaries
|
||||
items: [cat]
|
||||
|
||||
- list: cat_capable_binaries
|
||||
items: [cat_binaries]
|
||||
|
||||
- macro: is_cat
|
||||
condition: proc.name in (cat_capable_binaries)
|
||||
|
||||
- rule: open_from_cat
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and is_cat
|
||||
output: "An open was seen (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
3
test/rules/k8s_audit/allow_namespace_foo.yaml
Normal file
3
test/rules/k8s_audit/allow_namespace_foo.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
- list: allowed_namespaces
|
||||
items: [foo]
|
||||
append: true
|
||||
3
test/rules/k8s_audit/allow_nginx_container.yaml
Normal file
3
test/rules/k8s_audit/allow_nginx_container.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
- macro: allowed_k8s_containers
|
||||
condition: (ka.req.container.image.repository=nginx)
|
||||
|
||||
3
test/rules/k8s_audit/allow_only_apache_container.yaml
Normal file
3
test/rules/k8s_audit/allow_only_apache_container.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
- macro: allowed_k8s_containers
|
||||
condition: (ka.req.container.image.repository=apache)
|
||||
|
||||
3
test/rules/k8s_audit/allow_user_some-user.yaml
Normal file
3
test/rules/k8s_audit/allow_user_some-user.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
- list: allowed_k8s_users
|
||||
items: [some-user]
|
||||
append: true
|
||||
2
test/rules/k8s_audit/disallow_kactivity.yaml
Normal file
2
test/rules/k8s_audit/disallow_kactivity.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
- macro: consider_activity_events
|
||||
condition: (not jevt.rawtime exists)
|
||||
3
test/rules/k8s_audit/trust_nginx_container.yaml
Normal file
3
test/rules/k8s_audit/trust_nginx_container.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
- list: trusted_k8s_containers
|
||||
items: [nginx]
|
||||
append: true
|
||||
@@ -15,6 +15,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
- required_engine_version: 2
|
||||
|
||||
- list: cat_binaries
|
||||
items: [cat]
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ function run_tests() {
|
||||
rm -rf /tmp/falco_outputs
|
||||
mkdir /tmp/falco_outputs
|
||||
TEST_RC=0
|
||||
for mult in $SCRIPTDIR/falco_traces.yaml $SCRIPTDIR/falco_tests.yaml; do
|
||||
for mult in $SCRIPTDIR/falco_traces.yaml $SCRIPTDIR/falco_tests.yaml $SCRIPTDIR/falco_k8s_audit_tests.yaml; do
|
||||
CMD="avocado run --multiplex $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
|
||||
echo "Running: $CMD"
|
||||
$CMD
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"kind":"Event","apiVersion":"audit.k8s.io/v1beta1","metadata":{"creationTimestamp":"2018-10-25T13:58:49Z"},"level":"Request","timestamp":"2018-10-25T13:58:49Z","auditID":"841d3e6d-90d2-43df-8da4-684738bee3d5","stage":"ResponseComplete","requestURI":"/api/v1/namespaces","verb":"create","user":{"username":"system:anonymous","groups":["system:masters","system:authenticated"]},"sourceIPs":["192.168.99.1"],"objectRef":{"resource":"namespaces","name":"foo","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":201},"requestObject":{"kind":"Namespace","apiVersion":"v1","metadata":{"name":"foo","creationTimestamp":null},"spec":{},"status":{"phase":"Active"}},"requestReceivedTimestamp":"2018-10-25T13:58:49.730588Z","stageTimestamp":"2018-10-25T13:58:49.736141Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""}}
|
||||
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"c97244c7-4aec-4714-946a-8204d00ecdca","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T14:26:34Z"},"objectRef":{"apiGroup":"rbac.authorization.k8s.io","apiVersion":"v1","name":"some-reader-binding","resource":"clusterrolebindings"},"requestObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-02T20:09:26Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader-binding"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cluster-admin"},"subjects":[{"apiGroup":"rbac.authorization.k8s.io","kind":"User","name":"minikube"}]},"requestReceivedTimestamp":"2018-10-26T14:26:34.238974Z","requestURI":"/apis/rbac.authorization.k8s.io/v1/clusterrolebindings","responseObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-26T14:26:34Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader-binding","resourceVersion":"270440","selfLink":"/apis/rbac.authorization.k8s.io/v1/clusterrolebindings/some-reader-binding","uid":"23cf124e-d92b-11e8-a2e6-080027728ac4"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cluster-admin"},"subjects":[{"apiGroup":"rbac.authorization.k8s.io","kind":"User","name":"minikube"}]},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T14:26:34.242498Z","timestamp":"2018-10-26T14:26:34Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
1
test/trace_files/k8s_audit/attach_pod.json
Normal file
1
test/trace_files/k8s_audit/attach_pod.json
Normal file
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"14933b4e-7b09-4964-af09-b7987367e1ba","kind":"Event","level":"Request","metadata":{"creationTimestamp":"2018-10-26T13:42:46Z"},"objectRef":{"apiVersion":"v1","name":"nginx-deployment-7998647bdf-phvq7","namespace":"default","resource":"pods","subresource":"attach"},"requestReceivedTimestamp":"2018-10-26T13:42:46.764713Z","requestURI":"/api/v1/namespaces/default/pods/nginx-deployment-7998647bdf-phvq7/attach?container=nginx1&stderr=true&stdin=true&stdout=true","responseStatus":{"code":101,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseStarted","stageTimestamp":"2018-10-26T13:42:46.808261Z","timestamp":"2018-10-26T13:42:46Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"412a7809-4016-4228-a670-182be4bd18ec","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T14:35:50Z"},"objectRef":{"apiGroup":"rbac.authorization.k8s.io","apiVersion":"v1","name":"some-reader","resource":"clusterroles"},"requestObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-02T17:41:53Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader"},"rules":[{"apiGroups":[""],"resources":["pods/exec"],"verbs":["get"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"requestReceivedTimestamp":"2018-10-26T14:35:50.621493Z","requestURI":"/apis/rbac.authorization.k8s.io/v1/clusterroles","responseObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-26T14:35:50Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader","resourceVersion":"271128","selfLink":"/apis/rbac.authorization.k8s.io/v1/clusterroles/some-reader","uid":"6f7056c9-d92c-11e8-a2e6-080027728ac4"},"rules":[{"apiGroups":[""],"resources":["pods/exec"],"verbs":["get"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T14:35:50.627514Z","timestamp":"2018-10-26T14:35:50Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"d8964c73-0042-4f35-b253-4711092185a1","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T14:21:53Z"},"objectRef":{"apiGroup":"rbac.authorization.k8s.io","apiVersion":"v1","name":"some-reader","resource":"clusterroles"},"requestObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-02T17:41:53Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader"},"rules":[{"apiGroups":[""],"resources":["*"],"verbs":["get","list"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"requestReceivedTimestamp":"2018-10-26T14:21:53.885708Z","requestURI":"/apis/rbac.authorization.k8s.io/v1/clusterroles","responseObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-26T14:21:53Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader","resourceVersion":"270097","selfLink":"/apis/rbac.authorization.k8s.io/v1/clusterroles/some-reader","uid":"7cb48d08-d92a-11e8-a2e6-080027728ac4"},"rules":[{"apiGroups":[""],"resources":["*"],"verbs":["get","list"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T14:21:53.889736Z","timestamp":"2018-10-26T14:21:53Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"0dc97dd4-aa34-4071-b8cc-e1a1036c9ae9","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T14:24:52Z"},"objectRef":{"apiGroup":"rbac.authorization.k8s.io","apiVersion":"v1","name":"some-reader","resource":"clusterroles"},"requestObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-02T17:41:53Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["*"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"requestReceivedTimestamp":"2018-10-26T14:24:52.737769Z","requestURI":"/apis/rbac.authorization.k8s.io/v1/clusterroles","responseObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-26T14:24:52Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader","resourceVersion":"270313","selfLink":"/apis/rbac.authorization.k8s.io/v1/clusterroles/some-reader","uid":"e74f3721-d92a-11e8-a2e6-080027728ac4"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["*"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T14:24:52.741516Z","timestamp":"2018-10-26T14:24:52Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"25cd4bc5-50c9-4ce5-aa9a-b9ab6065929d","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T14:32:32Z"},"objectRef":{"apiGroup":"rbac.authorization.k8s.io","apiVersion":"v1","name":"some-reader","resource":"clusterroles"},"requestObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-02T17:41:53Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["get"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["delete"]}]},"requestReceivedTimestamp":"2018-10-26T14:32:32.179779Z","requestURI":"/apis/rbac.authorization.k8s.io/v1/clusterroles","responseObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-26T14:32:32Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader","resourceVersion":"270886","selfLink":"/apis/rbac.authorization.k8s.io/v1/clusterroles/some-reader","uid":"f9287d7e-d92b-11e8-a2e6-080027728ac4"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["get"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["delete"]}]},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T14:32:32.182250Z","timestamp":"2018-10-26T14:32:32Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
1
test/trace_files/k8s_audit/create_clusterrole.json
Normal file
1
test/trace_files/k8s_audit/create_clusterrole.json
Normal file
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"b8dfba33-a6e6-4f3c-b2cb-d47de1c4e74b","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T13:25:18Z"},"objectRef":{"apiGroup":"rbac.authorization.k8s.io","apiVersion":"v1","name":"some-reader","resource":"clusterroles"},"requestObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-02T17:41:53Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["get","list"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"requestReceivedTimestamp":"2018-10-26T13:25:18.266512Z","requestURI":"/apis/rbac.authorization.k8s.io/v1/clusterroles","responseObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-26T13:25:18Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader","resourceVersion":"266028","selfLink":"/apis/rbac.authorization.k8s.io/v1/clusterroles/some-reader","uid":"94c25719-d922-11e8-a2e6-080027728ac4"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["get","list"]},{"nonResourceURLs":["/api","/api/*","/apis","/apis/*","/healthz","/openapi","/openapi/*","/swagger-2.0.0.pb-v1","/swagger.json","/swaggerapi","/swaggerapi/*","/version","/version/"],"verbs":["get"]}]},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T13:25:18.275010Z","timestamp":"2018-10-26T13:25:18Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"e040d0ab-473c-442c-9707-88553173e962","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T13:25:18Z"},"objectRef":{"apiGroup":"rbac.authorization.k8s.io","apiVersion":"v1","name":"some-reader-binding","resource":"clusterrolebindings"},"requestObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-02T20:09:26Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader-binding"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"system:basic-user"},"subjects":[{"apiGroup":"rbac.authorization.k8s.io","kind":"User","name":"minikube"}]},"requestReceivedTimestamp":"2018-10-26T13:25:18.279128Z","requestURI":"/apis/rbac.authorization.k8s.io/v1/clusterrolebindings","responseObject":{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{"rbac.authorization.kubernetes.io/autoupdate":"true"},"creationTimestamp":"2018-10-26T13:25:18Z","labels":{"kubernetes.io/bootstrapping":"rbac-defaults"},"name":"some-reader-binding","resourceVersion":"266029","selfLink":"/apis/rbac.authorization.k8s.io/v1/clusterrolebindings/some-reader-binding","uid":"94c41db6-d922-11e8-a2e6-080027728ac4"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"system:basic-user"},"subjects":[{"apiGroup":"rbac.authorization.k8s.io","kind":"User","name":"minikube"}]},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T13:25:18.286399Z","timestamp":"2018-10-26T13:25:18Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
1
test/trace_files/k8s_audit/create_configmap.json
Normal file
1
test/trace_files/k8s_audit/create_configmap.json
Normal file
@@ -0,0 +1 @@
|
||||
{"annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""},"auditID":"155b887c-c27c-4fdb-9667-999f74512d0a","kind":"Event","level":"RequestResponse","metadata":{"creationTimestamp":"2018-10-26T13:13:03Z"},"objectRef":{"apiVersion":"v1","name":"my-config","namespace":"default","resource":"configmaps","uid":"b4952dc3-d670-11e5-8cd0-68f728db1985"},"requestObject":{"apiVersion":"v1","data":{"ui.properties":"color.good=purple\ncolor.bad=yellow\nallow.textmode=true\n"},"kind":"ConfigMap","metadata":{"creationTimestamp":"2016-02-18T18:52:05Z","name":"my-config","namespace":"default","selfLink":"/api/v1/namespaces/default/configmaps/my-config","uid":"b4952dc3-d670-11e5-8cd0-68f728db1985"}},"requestReceivedTimestamp":"2018-10-26T13:13:03.539180Z","requestURI":"/api/v1/namespaces/default/configmaps","responseObject":{"apiVersion":"v1","data":{"ui.properties":"color.good=purple\ncolor.bad=yellow\nallow.textmode=true\n"},"kind":"ConfigMap","metadata":{"creationTimestamp":"2018-10-26T13:13:03Z","name":"my-config","namespace":"default","resourceVersion":"265142","selfLink":"/api/v1/namespaces/default/configmaps/my-config","uid":"ded3abb9-d920-11e8-a2e6-080027728ac4"}},"responseStatus":{"code":201,"metadata":{}},"sourceIPs":["192.168.99.1"],"stage":"ResponseComplete","stageTimestamp":"2018-10-26T13:13:03.544952Z","timestamp":"2018-10-26T13:13:03Z","user":{"groups":["system:masters","system:authenticated"],"username":"minikube-user"},"verb":"create"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user