Compare commits

...

60 Commits

Author SHA1 Message Date
Lorenzo Fontana
d1b0ccb89e rule(Create Disallowed Pod): required_engine_version 5
rule(Create Privileged Pod): required_engine_version 5
rule(Create Sensitive Mount Pod): required_engine_version 5
rule(Create HostNetwork Pod): required_engine_version 5
rule(Pod Created in Kube Namespace): required_engine_version 5
rule(ClusterRole With Wildcard Created): required_engine_version 5
rule(ClusterRole With Write Privileges Created): required_engine_version 5
rule(ClusterRole With Pod Exec Created): required_engine_version 5

Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-07-13 15:57:08 +02:00
Lorenzo Fontana
6abebbb913 rules(Container Drift Detected (open+create)): specify that rule is only
compatible with engine 6

Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-07-13 15:55:49 +02:00
Lorenzo Fontana
80e6f6de98 rules: the required_engine_version is now on by default
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-07-13 15:53:36 +02:00
Nicolas Marier
32bae35de2 rule(list package_mgmt_binaries): add snapd to list
Snap is a package manager by Canonical which was not in the
`package_mgmt_binaries` list.

Signed-off-by: Nicolas Marier <nmarier@coveo.com>
2020-07-10 10:04:26 +02:00
Leonardo Grasso
de147447ed update(userspace/falco): rename --stats_interval to --stats-interval
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-07-08 17:55:16 +02:00
Leonardo Di Donato
825e249294 update(userspace/falco): rename --stats_interval to --stats-interval
To match the style of other long flags of the Falco CLI.

Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-08 17:55:16 +02:00
Leonardo Di Donato
00689a5d97 fix(userspace/falco): allow stats interval greather than 999
milliseconds

Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-08 17:55:16 +02:00
Leonardo Grasso
4d31784a83 fix(docker): correct syntax error in the entrypoint script
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-07-08 12:11:33 +02:00
Leonardo Di Donato
2848eceb03 build(cmake/modules): update driver version to 85c889
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 21:19:08 +02:00
Leonardo Di Donato
c7ac1ef61b update(userspace/engine): const correctness for json_event class
Co-authored-by: Nathan Baker <nathan.baker@sysdig.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 21:19:08 +02:00
Leonardo Di Donato
5fd3c38422 build(cmake/modules): update driver version to 33c00f
This driver version, among other things (like userspace instrumentation
support) includes a fix for building the eBPF driver on CentOS 8
machines too.

Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 18:41:01 +02:00
Leo Di Donato
3bad1d2a56 docs: auto threadiness comment into Falco config
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 13:42:09 +02:00
Leonardo Di Donato
8ad5c4f834 update: default grpc server threadiness is 0 now ("auto")
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 13:42:09 +02:00
Leonardo Di Donato
553856ad68 chore(userspace): log the gRPC threadiness
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 13:42:09 +02:00
Leonardo Di Donato
2d52be603d update(userspace/falco): gRPC server threadiness 0 by default (which
means "auto")

The 0 ("auto") value sets the threadiness to the number of online cores
automatically.

Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 13:42:09 +02:00
Leonardo Di Donato
75e62269c3 new: hardware_concurrency helper
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-07 13:42:09 +02:00
Lorenzo Fontana
3d1f27d082 build: stale bot adjustements
Removed not existing labels and made the error message a bit more
verbose to tell people what to expect next.

Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-07-07 12:20:55 +02:00
Leonardo Grasso
ad960a9485 chore(docker): rename SKIP_MODULE_LOAD to SKIP_DRIVER_LOADER
As per https://github.com/falcosecurity/falco/blob/master/proposals/20200506-artifacts-scope-part-2.md#action-items

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-07-07 12:17:20 +02:00
kaizhe
d8d218230d rules update: create placeholder macros for customization
Signed-off-by: kaizhe <derek0405@gmail.com>
2020-07-03 20:54:36 +02:00
Leonardo Grasso
b7e7a10035 docs: add myself to owners
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-07-03 16:37:17 +02:00
Leonardo Grasso
fecf1a9fea fix(userspace/falco/lua): correct argument
This explain why `buffered_output: false` was not honored for stdout

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-07-03 11:45:00 +02:00
Leonardo Di Donato
54a6d5c523 build: do not download lyaml and lpeg from draios S3 anymore
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-02 06:01:12 +02:00
Leonardo Di Donato
9fe78bf658 build: fetch libb64 and luajit from github, not from draios repos
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-02 06:01:12 +02:00
Leonardo Di Donato
727755e276 build: fetch openssl, curl, njson dependencies from github not draios
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-07-02 06:01:12 +02:00
Lorenzo Fontana
352307431a fix: update k8s audit endpoint to /k8s-audit everywhere
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-07-01 13:29:51 +02:00
Leonardo Grasso
6cfb0ec2b8 update(test): setup bidi gRPC integration test
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-30 13:04:03 +02:00
Leonardo Grasso
4af769f84c new(test): add gRPC unix socket support
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-30 13:04:03 +02:00
Leonardo Grasso
82e0b5f217 fix(userspace/falco): honor -M also when using a trace file
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-30 13:04:03 +02:00
Leonardo Di Donato
b4d005eb51 new(test): read grpc config fields
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-30 13:04:03 +02:00
Leonardo Di Donato
061c5f5ac9 new(test): setup gRPC output test case
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-30 13:04:03 +02:00
Leonardo Di Donato
c06ccf8378 update(docker/tester): grpcurl
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-30 13:04:03 +02:00
samwhite-gl
3408ea9164 Add GitLab to ADOPTERS.md
GitLab is now using Falco to provide Container Host Security protection

Co-Authored-By: Kris Nova <kris@nivenly.com>
Signed-off-by: Kris Nova <kris@nivenly.com>
2020-06-30 11:45:58 +02:00
samwhite-gl
51aea00be8 Add GitLab to ADOPTERS.md
GitLab is now using Falco to provide Container Host Security protection

Co-Authored-By: Kris Nova <kris@nivenly.com>
Signed-off-by: Kris Nova <kris@nivenly.com>
2020-06-30 11:45:58 +02:00
Antoine Deschênes
a5cadbf5fa rule(Disallowed K8s User): whitelist kube-apiserver-healthcheck
kops 1.17 adds a kube-apiserver-healthcheck user: https://github.com/kubernetes/kops/tree/master/cmd/kube-apiserver-healthcheck

Logs are currently spammed with:
```
{"output":"18:02:15.466580992: Warning K8s Operation performed by user not in allowed list of users (user=kube-apiserver-healthcheck target=<NA>/<NA> verb=get uri=/healthz resp=200)","priority":"Warning","rule":"Disallowed K8s User","time":"2020-06-29T18:02:15.466580992Z", "output_fields": {"jevt.time":"18:02:15.466580992","ka.response.code":"200","ka.target.name":"<NA>","ka.target.resource":"<NA>","ka.uri":"/healthz","ka.user.name":"kube-apiserver-healthcheck","ka.verb":"get"}}
```

Signed-off-by: Antoine Deschênes <antoine.deschenes@equisoft.com>
2020-06-30 11:44:11 +02:00
Lorenzo Fontana
9eb0b7fb5f update(userspace/falco): avoid memory allocation for falco output
response

Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Lorenzo Fontana
869d883dc7 update(userspace/falco): better gRPC server logging
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
b88767f558 bc(userspace/falco): the Falco gRPC Outputs API are now "falco.outputs.service/get" and "falco.outputs.service/sub"
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
bdbdf7b830 update(userspace/falco): pluralize Falco output proto and service
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
4e2f3e2c71 update(proposals): keep Falco gRPC Outputs proposal in sync
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Lorenzo Fontana
3d9bc8f67b update(userspace/falco): remove keepalive from output request
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Lorenzo Fontana
c89c11c3c4 update(userspace/falco): remove output queue size
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Lorenzo Fontana
5bd9ba0529 update(userspace/falco/grpc): simpler bidirectional context state
transitions

Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Lorenzo Fontana
b9e6d65e69 update(userspace/falco/grpc): bidirectional sub implementation
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Lorenzo Fontana
0d194f2b40 update(userspace/falco/grpc): for stream contexts use a flag to detect
if it is still running or not

Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Lorenzo Fontana
d9f2cda8cf update(userspace/falco/grpc): dealing with multiple streaming requests
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
2ebc55f897 wip(userspace/falco): bidirectional gRPC outputs logic (initial)
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
01ae8701d9 new(userspace/falco): concrete initial implementation of the subscribe gRPC service
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
be6c4b273d new(userspace/falco): gRPC context for bidirectional services
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
a72f27c028 new(userspace/falco): macro to REGISTER_BIDI gRPC services
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
58adc5b60c new(userspace/falco): output gRPC service to provide a server streaming method and a bidirectional method to obtain Falco alerts
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
cf31712fad update(userspace/falco): context class for bidirectional gRPC services
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
a568c42adb update(userspace/falco): unsafe_size() method for falco::output::queue
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
Leonardo Di Donato
05dd170d70 fix(userspace/falco): virtual destructor of base grpc context
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-06-29 20:42:50 +02:00
kaizhe
e29a4c8560 rule(list network_tool_binaries): add zmap to the list
Signed-off-by: kaizhe <derek0405@gmail.com>
2020-06-29 18:17:28 +02:00
Lorenzo Fontana
c5ba95deff docs: teal logo is svg
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-06-29 09:14:50 -07:00
Leonardo Grasso
27037e64cc chore(rules): remove redundant condition from root_dir macro
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-26 19:57:18 +02:00
Leonardo Grasso
1859552834 fix(rules): correct root_dir macro to avoid unwanted matching
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-06-26 19:57:18 +02:00
Nicolas Marier
298ba29c88 rule(Change thread namespace): whitelist protokube, dockerd, tini and aws
These application binaries raise events in the `Change thread namespace`
rule as part of their normal operation.

Here are more details regarding each binary :

- `protokube` : See [this](https://github.com/kubernetes/kops/tree/master/protokube)
- `dockerd` : The `dockerd` process name is whitelisted already in this
  rule, but not if it is the parent, which will happen if you are doing
  docker-in-docker.
- `tini` : See [this](https://github.com/krallin/tini)
- `aws` : This one I noticed because Falco itself uses the AWS CLI to
  send events to SNS, which was triggering this rule.

Signed-off-by: Nicolas Marier <nmarier@coveo.com>
2020-06-24 11:02:12 +02:00
Nicolas Marier
0272b94bb1 rule(macro exe_running_docker_save): add new cmdline
While using Falco, I noticed we were getting many events that were
virtually identical to those that were previously filtered out by the
`exexe_running_docker_save` macro, but where the `cmdline` was something
like `exe /var/run/docker/netns/cc5c7b9bb110 all false`. I believe this
is caused by the use of docker-in-docker.

Signed-off-by: Nicolas Marier <nmarier@coveo.com>
2020-06-24 11:02:12 +02:00
Nicolas Marier
dbd86234ad rule(macro user_expected_terminal_shell_in_container_conditions): create the macro
A macro like this is useful because configuration management software
may need to run containers with an attached terminal to perform some of
its duties, and users may want to ignore this behavior.

Signed-off-by: Nicolas Marier <nmarier@coveo.com>
2020-06-23 21:53:41 +02:00
44 changed files with 1478 additions and 546 deletions

5
.github/stale.yml vendored
View File

@@ -6,7 +6,6 @@ daysUntilClose: 7
exemptLabels:
- cncf
- roadmap
- enhancement
- "help wanted"
# Label to use when marking an issue as stale
staleLabel: wontfix
@@ -15,5 +14,7 @@ markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
Issues labeled "cncf", "roadmap" and "help wanted" will not be automatically closed.
Please refer to a maintainer to get such label added if you think this should be kept open.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
closeComment: false

View File

@@ -8,6 +8,8 @@ This is a list of production adopters of Falco (in alphabetical order):
* [Frame.io](https://frame.io/) - Frame.io is a cloud-based (SaaS) video review and collaboration platform that enables users to securely upload source media, work-in-progress edits, dailies, and more into private workspaces where they can invite their team and clients to collaborate on projects. Understanding what is running on production servers, and the context around why things are running is even more tricky now that we have further abstractions like Docker and Kubernetes. To get this needed visibility into our system, we rely on Falco. Falco's ability to collect raw system calls such as open, connect, exec, along with their arguments offer key insights on what is happening on the production system and became the foundation of our intrusion detection and alerting system.
* [GitLab](https://about.gitlab.com/direction/defend/container_host_security/) - GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate. GitLab Ultimate provides the single tool teams need to find, triage, and fix vulnerabilities in applications, services, and cloud-native environments enabling them to manage their risk. This provides them with repeatable, defensible processes that automate security and compliance policies. GitLab includes a tight integration with Falco, allowing users to defend their containerized applications from attacks while running in production.
* [League](https://league.com/ca/) - League provides health benefits management services to help employees understand and get the most from their benefits, and employers to provide effective, efficient plans. Falco is used to monitor our deployed services on Kubernetes, protecting against malicious access to containerswhich could lead to leaks of PHI or other sensitive data. The Falco alerts are logged in Stackdriver for grouping and further analysis. In the future, we're hoping for integrations with Prometheus and AlertManager as well.
* [Logz.io](https://logz.io/) - Logz.io is a cloud observability platform for modern engineering teams. The Logz.io platform consists of three products — Log Management, Infrastructure Monitoring, and Cloud SIEM — that work together to unify the jobs of monitoring, troubleshooting, and security. We empower engineers to deliver better software by offering the world's most popular open source observability tools — the ELK Stack, Grafana, and Jaeger — in a single, easy to use, and powerful platform purpose-built for monitoring distributed cloud environments. Cloud SIEM supports data from multiple sources, including Falco's alerts, and offers useful rules and dashboards content to visualize and manage incidents across your systems in a unified UI.

View File

@@ -93,7 +93,7 @@ message(STATUS "Using bundled nlohmann-json in '${NJSON_SRC}'")
set(NJSON_INCLUDE "${NJSON_SRC}/single_include")
ExternalProject_Add(
njson
URL "https://s3.amazonaws.com/download.draios.com/dependencies/njson-3.3.0.tar.gz"
URL "https://github.com/nlohmann/json/archive/v3.3.0.tar.gz"
URL_HASH "SHA256=2fd1d207b4669a7843296c41d3b6ac5b23d00dec48dba507ba051d14564aa801"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
@@ -106,14 +106,15 @@ find_package(Curses REQUIRED)
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
# libb64
set(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
message(STATUS "Using bundled b64 in '${B64_SRC}'")
set(B64_INCLUDE "${B64_SRC}/include")
set(B64_LIB "${B64_SRC}/src/libb64.a")
ExternalProject_Add(
b64
URL "https://s3.amazonaws.com/download.draios.com/dependencies/libb64-1.2.src.zip"
URL_HASH "SHA256=343d8d61c5cbe3d3407394f16a5390c06f8ff907bd8d614c16546310b689bfd3"
URL "https://github.com/libb64/libb64/archive/v1.2.1.zip"
URL_HASH "SHA256=665134c2b600098a7ebd3d00b6a866cb34909a6d48e0e37a0eda226a4ad2638a"
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
@@ -135,8 +136,8 @@ set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
ExternalProject_Add(
luajit
URL "https://s3.amazonaws.com/download.draios.com/dependencies/LuaJIT-2.0.3.tar.gz"
URL_HASH "SHA256=55be6cb2d101ed38acca32c5b1f99ae345904b365b642203194c585d27bebd79"
URL "https://github.com/LuaJIT/LuaJIT/archive/v2.0.3.tar.gz"
URL_HASH "SHA256=8da3d984495a11ba1bce9a833ba60e18b532ca0641e7d90d97fafe85ff014baa"
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
@@ -151,8 +152,8 @@ list(APPEND LPEG_DEPENDENCIES "luajit")
ExternalProject_Add(
lpeg
DEPENDS ${LPEG_DEPENDENCIES}
URL "https://s3.amazonaws.com/download.draios.com/dependencies/lpeg-1.0.0.tar.gz"
URL_HASH "SHA256=10190ae758a22a16415429a9eb70344cf29cbda738a6962a9f94a732340abf8e"
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
@@ -175,7 +176,7 @@ list(APPEND LYAML_DEPENDENCIES "luajit")
ExternalProject_Add(
lyaml
DEPENDS ${LYAML_DEPENDENCIES}
URL "https://s3.amazonaws.com/download.draios.com/dependencies/lyaml-release-v6.0.tar.gz"
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1

2
OWNERS
View File

@@ -3,6 +3,7 @@ approvers:
- kris-nova
- leodido
- mstemm
- leogr
reviewers:
- fntlnz
- kaizhe
@@ -10,3 +11,4 @@ reviewers:
- leodido
- mfdii
- mstemm
- leogr

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -32,8 +32,8 @@ else()
ExternalProject_Add(
openssl
# START CHANGE for CVE-2017-3735, CVE-2017-3731, CVE-2017-3737, CVE-2017-3738, CVE-2017-3736
URL "https://s3.amazonaws.com/download.draios.com/dependencies/openssl-1.0.2n.tar.gz"
URL_HASH "SHA256=370babb75f278c39e0c50e8c4e7493bc0f18db6867478341a832a982fd15a8fe"
URL "https://github.com/openssl/openssl/archive/OpenSSL_1_0_2n.tar.gz"
URL_HASH "SHA256=4f4bc907caff1fee6ff8593729e5729891adcee412049153a3bb4db7625e8364"
# END CHANGE for CVE-2017-3735, CVE-2017-3731, CVE-2017-3737, CVE-2017-3738, CVE-2017-3736
CONFIGURE_COMMAND ./config shared --prefix=${OPENSSL_INSTALL_DIR}
BUILD_COMMAND ${CMD_MAKE}

View File

@@ -31,7 +31,7 @@ else()
curl
DEPENDS openssl
# START CHANGE for CVE-2017-8816, CVE-2017-8817, CVE-2017-8818, CVE-2018-1000007
URL "https://s3.amazonaws.com/download.draios.com/dependencies/curl-7.61.0.tar.bz2"
URL "https://github.com/curl/curl/releases/download/curl-7_61_0/curl-7.61.0.tar.bz2"
URL_HASH "SHA256=5f6f336921cf5b84de56afbd08dfb70adeef2303751ffb3e570c936c6d656c9c"
# END CHANGE for CVE-2017-8816, CVE-2017-8817, CVE-2017-8818, CVE-2018-1000007
CONFIGURE_COMMAND

View File

@@ -26,8 +26,8 @@ file(MAKE_DIRECTORY ${SYSDIG_CMAKE_WORKING_DIR})
# To update sysdig version for the next release, change the default below
# In case you want to test against another sysdig version just pass the variable - ie., `cmake -DSYSDIG_VERSION=dev ..`
if(NOT SYSDIG_VERSION)
set(SYSDIG_VERSION "422ab408c5706fbdd45432646cc197eb79459169")
set(SYSDIG_CHECKSUM "SHA256=367db2a480bca327a46f901bcc8384f151231bcddba88c719a06cf13971f4ab5")
set(SYSDIG_VERSION "85c88952b018fdbce2464222c3303229f5bfcfad")
set(SYSDIG_CHECKSUM "SHA256=6c3f5f2d699c9540e281f50cbc5cb6b580f0fc689798bc65d4a77f57f932a71c")
endif()
set(PROBE_VERSION "${SYSDIG_VERSION}")

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,10 +16,14 @@
# limitations under the License.
#
# todo(leogr): remove deprecation notice within a couple of releases
if [[ ! -z "${SKIP_MODULE_LOAD}" ]]; then
echo "* SKIP_MODULE_LOAD is deprecated and will be removed soon, use SKIP_DRIVER_LOADER instead"
fi
# Set the SKIP_MODULE_LOAD variable to skip loading the kernel module
# Set the SKIP_DRIVER_LOADER variable to skip loading the driver
if [[ -z "${SKIP_MODULE_LOAD}" ]]; then
if [[ -z "${SKIP_DRIVER_LOADER}" ]] && [[ -z "${SKIP_MODULE_LOAD}" ]]; then
echo "* Setting up /usr/src links from host"
for i in "$HOST_ROOT/usr/src"/*

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2020 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,9 +17,9 @@
#
# Set the SKIP_MODULE_LOAD variable to skip loading the kernel module
# Set the SKIP_DRIVER_LOADER variable to skip loading the driver
if [[ -z "${SKIP_MODULE_LOAD}" ]]; then
if [[ -z "${SKIP_DRIVER_LOADER}" ]]; then
echo "* Setting up /usr/src links from host"
for i in "$HOST_ROOT/usr/src"/*

View File

@@ -1,16 +1,20 @@
FROM fedora:31
LABEL name="falcosecurity/falco-tester"
LABEL usage="docker run -v /boot:/boot:ro -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/..:/source -v $PWD/build:/build -e FALCO_VERSION=<current_falco_version> --name <name> falcosecurity/falco-tester test"
LABEL usage="docker run -v /boot:/boot:ro -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/..:/source -v $PWD/build:/build --name <name> falcosecurity/falco-tester test"
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ENV FALCO_VERSION=
ENV BUILD_TYPE=release
ADD https://github.com/fullstorydev/grpcurl/releases/download/v1.6.0/grpcurl_1.6.0_linux_x86_64.tar.gz /
RUN dnf install -y python-pip python docker findutils jq unzip && dnf clean all
ENV PATH="/root/.local/bin/:${PATH}"
RUN pip install --user avocado-framework==69.0
RUN pip install --user avocado-framework-plugin-varianter-yaml-to-mux==69.0
RUN pip install --user watchdog==0.10.2
RUN pip install --user pathtools==0.1.2
RUN tar -C /usr/bin -xvf grpcurl_1.6.0_linux_x86_64.tar.gz
COPY ./root /

View File

@@ -182,7 +182,8 @@ http_output:
# grpc:
# enabled: true
# bind_address: "0.0.0.0:5060"
# threadiness: 8
# # when threadiness is 0, Falco sets it by automatically figuring out the number of online cores
# threadiness: 0
# private_key: "/etc/falco/certs/server.key"
# cert_chain: "/etc/falco/certs/server.crt"
# root_certs: "/etc/falco/certs/ca.crt"
@@ -191,7 +192,8 @@ http_output:
grpc:
enabled: false
bind_address: "unix:///var/run/falco.sock"
threadiness: 8
# when threadiness is 0, Falco automatically guesses it depending on the number of online cores
threadiness: 0
# gRPC output service.
# By default it is off.

View File

@@ -1,4 +1,4 @@
# gRPC Falco Output
# Falco gRPC Outputs
<!-- toc -->
@@ -25,7 +25,7 @@ An alert is an "output" when it goes over a transport, and it is emitted by Falc
At the current moment, however, Falco can deliver alerts in a very basic way, for example by dumping them to standard output.
For this reason, many Falco users asked, with issues - eg., [falco#528](https://github.com/falcosecurity/falco/issues/528) - or in the [slack channel](https://sysdig.slack.com) if we can find a more consumable way to implement Falco outputs in an extensible way.
For this reason, many Falco users asked, with issues - eg., [falco#528](https://github.com/falcosecurity/falco/issues/528) - or in the [slack channel](https://slack.k8s.io) if we can find a more consumable way to implement Falco outputs in an extensible way.
The motivation behind this proposal is to design a new output implementation that can meet our user's needs.
@@ -39,7 +39,10 @@ The motivation behind this proposal is to design a new output implementation tha
- To continue supporting the old output formats by implementing their same interface
- To be secure by default (**mutual TLS** authentication)
- To be **asynchronous** and **non-blocking**
- To implement a Go SDK
- To provide a connection over unix socket (no authentication)
- To implement a Go client
- To implement a Rust client
- To implement a Python client
### Non-Goals
@@ -77,26 +80,25 @@ syntax = "proto3";
import "google/protobuf/timestamp.proto";
import "schema.proto";
package falco.output;
package falco.outputs;
option go_package = "github.com/falcosecurity/client-go/pkg/api/output";
option go_package = "github.com/falcosecurity/client-go/pkg/api/outputs";
// The `subscribe` service defines the RPC call
// to perform an output `request` which will lead to obtain an output `response`.
// This service defines the RPC methods
// to `request` a stream of output `response`s.
service service {
rpc subscribe(request) returns (stream response);
// Subscribe to a stream of Falco outputs by sending a stream of requests.
rpc sub(stream request) returns (stream response);
// Get all the Falco outputs present in the system up to this call.
rpc get(request) returns (stream response);
}
// The `request` message is the logical representation of the request model.
// It is the input of the `subscribe` service.
// It is used to configure the kind of subscription to the gRPC streaming server.
// It is the input of the `output.service` service.
message request {
bool keepalive = 1;
// string duration = 2; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
// repeated string tags = 3; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
}
// The `response` message is the logical representation of the output model.
// The `response` message is the representation of the output model.
// It contains all the elements that Falco emits in an output along with the
// definitions for priorities and source.
message response {
@@ -106,7 +108,7 @@ message response {
string rule = 4;
string output = 5;
map<string, string> output_fields = 6;
// repeated string tags = 7; // TODO(leodido,fntlnz): tags not supported yet, keeping for reference
string hostname = 7;
}
```

File diff suppressed because it is too large Load Diff

View File

@@ -44,9 +44,17 @@
items: ["vpa-recommender", "vpa-updater"]
- list: allowed_k8s_users
items: [
"minikube", "minikube-user", "kubelet", "kops", "admin", "kube", "kube-proxy",
vertical_pod_autoscaler_users,
items:
[
"minikube",
"minikube-user",
"kubelet",
"kops",
"admin",
"kube",
"kube-proxy",
"kube-apiserver-healthcheck",
vertical_pod_autoscaler_users,
]
- rule: Disallowed K8s User
@@ -115,6 +123,7 @@
condition: ka.uri=/healthz
- rule: Create Disallowed Pod
required_engine_version: 5
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
@@ -124,6 +133,7 @@
tags: [k8s]
- rule: Create Privileged Pod
required_engine_version: 5
desc: >
Detect an attempt to start a pod with a privileged container
condition: kevt and pod and kcreate and ka.req.pod.containers.privileged intersects (true) and not ka.req.pod.containers.image.repository in (falco_privileged_images)
@@ -137,6 +147,7 @@
(ka.req.pod.volumes.hostpath intersects (/proc, /var/run/docker.sock, /, /etc, /root, /var/run/crio/crio.sock, /home/admin, /var/lib/kubelet, /var/lib/kubelet/pki, /etc/kubernetes, /etc/kubernetes/manifests))
- rule: Create Sensitive Mount Pod
required_engine_version: 5
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.
@@ -148,6 +159,7 @@
# Corresponds to K8s CIS Benchmark 1.7.4
- rule: Create HostNetwork Pod
required_engine_version: 5
desc: Detect an attempt to start a pod using the host network.
condition: kevt and pod and kcreate and ka.req.pod.host_network intersects (true) and not ka.req.pod.containers.image.repository in (falco_hostnetwork_images)
output: Pod started using host network (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace images=%ka.req.pod.containers.image)
@@ -155,10 +167,13 @@
source: k8s_audit
tags: [k8s]
- macro: user_known_node_port_service
condition: (k8s_audit_never_true)
- rule: Create NodePort Service
desc: >
Detect an attempt to start a service with a NodePort service type
condition: kevt and service and kcreate and ka.req.service.type=NodePort
condition: kevt and service and kcreate and ka.req.service.type=NodePort and not user_known_node_port_service
output: NodePort Service Created (user=%ka.user.name service=%ka.target.name ns=%ka.target.namespace ports=%ka.req.service.ports)
priority: WARNING
source: k8s_audit
@@ -175,7 +190,7 @@
- rule: Create/Modify Configmap With Private Credentials
desc: >
Detect creating/modifying a configmap containing a private credential (aws key, password, etc.)
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
@@ -201,10 +216,13 @@
# attach request was created privileged or not. For now, we have a
# less severe rule that detects attaches/execs to any pod.
- macro: user_known_exec_pod_activities
condition: (k8s_audit_never_true)
- rule: Attach/Exec Pod
desc: >
Detect any attempt to attach/exec to a pod
condition: kevt_started and pod_subresource and kcreate and ka.target.subresource in (exec,attach)
condition: kevt_started and pod_subresource and kcreate and ka.target.subresource in (exec,attach) and not user_known_exec_pod_activities
output: Attach/Exec to pod (user=%ka.user.name pod=%ka.target.name ns=%ka.target.namespace action=%ka.target.subresource command=%ka.uri.param[command])
priority: NOTICE
source: k8s_audit
@@ -222,19 +240,32 @@
source: k8s_audit
tags: [k8s]
- list: user_trusted_image_list
items: []
- macro: trusted_pod
condition: (ka.req.pod.containers.image.repository in (user_trusted_image_list))
# Detect any new pod created in the kube-system namespace
- rule: Pod Created in Kube Namespace
required_engine_version: 5
desc: Detect any attempt to create a pod in the kube-system or kube-public namespaces
condition: kevt and pod and kcreate and ka.target.namespace in (kube-system, kube-public)
condition: kevt and pod and kcreate and ka.target.namespace in (kube-system, kube-public) and not trusted_pod
output: Pod created in kube namespace (user=%ka.user.name pod=%ka.resp.name ns=%ka.target.namespace images=%ka.req.pod.containers.image)
priority: WARNING
source: k8s_audit
tags: [k8s]
- list: user_known_sa_list
items: []
- macro: trusted_sa
condition: (ka.target.name in (user_known_sa_list))
# Detect creating a service account in the kube-system/kube-public namespace
- rule: Service Account Created in Kube Namespace
desc: Detect any attempt to create a serviceaccount in the kube-system or kube-public namespaces
condition: kevt and serviceaccount and kcreate and ka.target.namespace in (kube-system, kube-public) and response_successful
condition: kevt and serviceaccount and kcreate and ka.target.namespace in (kube-system, kube-public) and response_successful and not trusted_sa
output: Service account created in kube namespace (user=%ka.user.name serviceaccount=%ka.target.name ns=%ka.target.namespace)
priority: WARNING
source: k8s_audit
@@ -262,6 +293,7 @@
tags: [k8s]
- rule: ClusterRole With Wildcard Created
required_engine_version: 5
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 intersects ("*") or ka.req.role.rules.verbs intersects ("*"))
output: Created Role/ClusterRole with wildcard (user=%ka.user.name role=%ka.target.name rules=%ka.req.role.rules)
@@ -274,6 +306,7 @@
(ka.req.role.rules.verbs intersects (create, update, patch, delete, deletecollection))
- rule: ClusterRole With Write Privileges Created
required_engine_version: 5
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)
@@ -282,6 +315,7 @@
tags: [k8s]
- rule: ClusterRole With Pod Exec Created
required_engine_version: 5
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 intersects ("pods/exec")
output: Created Role/ClusterRole with pod exec privileges (user=%ka.user.name role=%ka.target.name rules=%ka.req.role.rules)
@@ -444,20 +478,26 @@
source: k8s_audit
tags: [k8s]
# This macro disables following rule, change to k8s_audit_never_true to enable it
- macro: allowed_full_admin_users
condition: (k8s_audit_always_true)
# This list includes some of the default user names for an administrator in several K8s installations
- list: full_admin_k8s_users
items: ["admin", "kubernetes-admin", "kubernetes-admin@kubernetes", "kubernetes-admin@cluster.local", "minikube-user"]
items:
[
"admin",
"kubernetes-admin",
"kubernetes-admin@kubernetes",
"kubernetes-admin@cluster.local",
"minikube-user",
]
# This rules detect an operation triggered by an user name that is
# included in the list of those that are default administrators upon
# cluster creation. This may signify a permission setting too broader.
# As we can't check for role of the user on a general ka.* event, this
# may or may not be an administrator. Customize the full_admin_k8s_users
# This rules detect an operation triggered by an user name that is
# included in the list of those that are default administrators upon
# cluster creation. This may signify a permission setting too broader.
# As we can't check for role of the user on a general ka.* event, this
# may or may not be an administrator. Customize the full_admin_k8s_users
# list to your needs, and activate at your discrection.
# # How to test:
@@ -476,8 +516,6 @@
source: k8s_audit
tags: [k8s]
- macro: ingress
condition: ka.target.resource=ingresses
@@ -509,12 +547,10 @@
output: >
K8s Ingress Without TLS Cert Created (user=%ka.user.name ingress=%ka.target.name
namespace=%ka.target.namespace)
source: k8s_audit
source: k8s_audit
priority: WARNING
tags: [k8s, network]
- macro: node
condition: ka.target.resource=nodes
@@ -557,4 +593,3 @@
priority: WARNING
source: k8s_audit
tags: [k8s]

View File

@@ -0,0 +1,38 @@
#
# Copyright (C) 2020 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Whether to output events in json or text.
json_output: false
# Send information logs to stderr and/or syslog
# Note these are *not* security notification logs!
# These are just Falco lifecycle (and possibly error) logs.
log_stderr: false
log_syslog: false
# Where security notifications should go.
stdout_output:
enabled: false
# gRPC server using an unix socket.
grpc:
enabled: true
bind_address: "unix:///tmp/falco/falco.sock"
threadiness: 8
grpc_output:
enabled: true

View File

@@ -136,7 +136,7 @@ stdout_output:
webserver:
enabled: true
listen_port: 8765
k8s_audit_endpoint: /k8s_audit
k8s_audit_endpoint: /k8s-audit
ssl_enabled: false
ssl_certificate: /etc/falco/falco.pem

View File

@@ -28,6 +28,8 @@ import urllib.request
from avocado import Test
from avocado import main
from avocado.utils import process
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
class FalcoTest(Test):
@@ -195,6 +197,24 @@ class FalcoTest(Test):
os.makedirs(filedir)
self.outputs = outputs
self.grpcurl_res = None
self.grpc_observer = None
self.grpc_address = self.params.get('address', 'grpc/*', default='/var/run/falco.sock')
if self.grpc_address.startswith("unix://"):
self.is_grpc_using_unix_socket = True
self.grpc_address = self.grpc_address[len("unix://"):]
else:
self.is_grpc_using_unix_socket = False
self.grpc_proto = self.params.get('proto', 'grpc/*', default='')
self.grpc_service = self.params.get('service', 'grpc/*', default='')
self.grpc_method = self.params.get('method', 'grpc/*', default='')
self.grpc_results = self.params.get('results', 'grpc/*', default='')
if self.grpc_results == '':
self.grpc_results = []
else:
if type(self.grpc_results) == str:
self.grpc_results = [self.grpc_results]
self.disable_tags = self.params.get('disable_tags', '*', default='')
if self.disable_tags == '':
@@ -417,6 +437,48 @@ class FalcoTest(Test):
self.log.debug("Copying {} to {}".format(driver_path, module_path))
shutil.copyfile(driver_path, module_path)
def init_grpc_handler(self):
self.grpcurl_res = None
if len(self.grpc_results) > 0:
if not self.is_grpc_using_unix_socket:
self.fail("This test suite supports gRPC with unix socket only")
cmdline = "grpcurl -import-path ../userspace/falco " \
"-proto {} -plaintext -unix {} " \
"{}/{}".format(self.grpc_proto, self.grpc_address, self.grpc_service, self.grpc_method)
that = self
class GRPCUnixSocketEventHandler(PatternMatchingEventHandler):
def on_created(self, event):
# that.log.info("EVENT: {}", event)
that.grpcurl_res = process.run(cmdline)
path = os.path.dirname(self.grpc_address)
process.run("mkdir -p {}".format(path))
event_handler = GRPCUnixSocketEventHandler(patterns=['*'],
ignore_directories=True)
self.grpc_observer = Observer()
self.grpc_observer.schedule(event_handler, path, recursive=False)
self.grpc_observer.start()
def check_grpc(self):
if self.grpc_observer is not None:
self.grpc_observer.stop()
self.grpc_observer = None
if self.grpcurl_res is None:
self.fail("gRPC responses not found")
for exp_result in self.grpc_results:
found = False
for line in self.grpcurl_res.stdout.decode("utf-8").splitlines():
match = re.search(exp_result, line)
if match is not None:
found = True
if found == False:
self.fail("Could not find a line '{}' in gRPC responses".format(exp_result))
def test(self):
self.log.info("Trace file %s", self.trace_file)
@@ -424,6 +486,8 @@ class FalcoTest(Test):
self.possibly_copy_driver()
self.init_grpc_handler()
if self.package != 'None':
# This sets falco_binary_path as a side-effect.
self.install_package()
@@ -526,6 +590,7 @@ class FalcoTest(Test):
self.check_detections_by_rule(res)
self.check_json_output(res)
self.check_outputs()
self.check_grpc()
pass

View File

@@ -672,6 +672,22 @@ trace_files: !mux
outputs:
- /tmp/falco_outputs/program_output.txt: Warning An open was seen
grpc_unix_socket_outputs:
detect: True
detect_level: WARNING
rules_file:
- rules/single_rule.yaml
conf_file: confs/grpc_unix_socket.yaml
trace_file: trace_files/cat_write.scap
run_duration: 5
grpc:
address: unix:///tmp/falco/falco.sock
proto: outputs.proto
service: falco.outputs.service
method: get
results:
- "Warning An open was seen"
detect_counts:
detect: True
detect_level: WARNING

View File

@@ -3,9 +3,11 @@ avocado-framework-plugin-varianter-yaml-to-mux==69.0
certifi==2020.4.5.1
chardet==3.0.4
idna==2.9
pathtools==0.1.2
pbr==5.4.5
PyYAML==5.3.1
requests==2.23.0
six==1.14.0
stevedore==1.32.0
urllib3==1.25.9
watchdog==0.10.2

View File

@@ -1,3 +1,2 @@
- macro: allowed_k8s_containers
condition: (ka.req.pod.containers.image.repository in (nginx))

View File

@@ -52,6 +52,12 @@ std::string wrap_text(const std::string& str, uint32_t initial_pos, uint32_t ind
return ret;
}
uint32_t hardware_concurrency()
{
auto hc = std::thread::hardware_concurrency();
return hc ? hc : 1;
}
void readfile(const std::string& filename, std::string& data)
{
std::ifstream file(filename.c_str(), std::ios::in);

View File

@@ -21,6 +21,7 @@ limitations under the License.
#include <fstream>
#include <iostream>
#include <string>
#include <thread>
#include <nonstd/string_view.hpp>
#pragma once
@@ -34,6 +35,9 @@ namespace utils
std::string wrap_text(const std::string& str, uint32_t initial_pos, uint32_t indent, uint32_t line_len);
void readfile(const std::string& filename, std::string& data);
uint32_t hardware_concurrency();
namespace network
{
static const std::string UNIX_SCHEME("unix://");

View File

@@ -45,7 +45,7 @@ const json &json_event::jevt()
return m_jevt;
}
uint64_t json_event::get_ts()
uint64_t json_event::get_ts() const
{
return m_event_ts;
}

View File

@@ -38,14 +38,14 @@ public:
void set_jevt(nlohmann::json &evt, uint64_t ts);
const nlohmann::json &jevt();
uint64_t get_ts();
uint64_t get_ts() const;
inline uint16_t get_source()
inline uint16_t get_source() const
{
return ESRC_K8S_AUDIT;
}
inline uint16_t get_type()
inline uint16_t get_type() const
{
// All k8s audit events have the single tag "1". - see falco_engine::process_k8s_audit_event
return 1;

View File

@@ -19,23 +19,24 @@ add_custom_command(
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.h
${CMAKE_CURRENT_BINARY_DIR}/output.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/output.pb.h
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
COMMENT "Generate gRPC version API"
COMMENT "Generate gRPC API"
# Falco gRPC Version API
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
COMMENT "Generate gRPC outputs API"
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/output.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/output.proto
# Falco gRPC Outputs API
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
${CMAKE_CURRENT_SOURCE_DIR}/output.proto
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_executable(
@@ -54,8 +55,8 @@ add_executable(
grpc_server.cpp
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/output.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/output.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc)
add_dependencies(falco civetweb string-view-lite)

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2019 The Falco Authors.
Copyright (C) 2020 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ limitations under the License.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "falco_utils.h"
#include "configuration.h"
#include "logger.h"
@@ -32,7 +33,7 @@ falco_configuration::falco_configuration():
m_time_format_iso_8601(false),
m_webserver_enabled(false),
m_webserver_listen_port(8765),
m_webserver_k8s_audit_endpoint("/k8s_audit"),
m_webserver_k8s_audit_endpoint("/k8s-audit"),
m_webserver_ssl_enabled(false),
m_config(NULL)
{
@@ -148,11 +149,12 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
m_grpc_enabled = m_config->get_scalar<bool>("grpc", "enabled", false);
m_grpc_bind_address = m_config->get_scalar<string>("grpc", "bind_address", "0.0.0.0:5060");
m_grpc_threadiness = m_config->get_scalar<uint32_t>("grpc", "threadiness", 8); // todo > limit it to avoid overshubscription? std::thread::hardware_concurrency()
m_grpc_threadiness = m_config->get_scalar<uint32_t>("grpc", "threadiness", 0);
if(m_grpc_threadiness == 0)
{
throw logic_error("error reading config file (" + m_config_file + "): gRPC threadiness must be greater than 0");
m_grpc_threadiness = falco::utils::hardware_concurrency();
}
// todo > else limit threadiness to avoid oversubscription?
m_grpc_private_key = m_config->get_scalar<string>("grpc", "private_key", "/etc/falco/certs/server.key");
m_grpc_cert_chain = m_config->get_scalar<string>("grpc", "cert_chain", "/etc/falco/certs/server.crt");
m_grpc_root_certs = m_config->get_scalar<string>("grpc", "root_certs", "/etc/falco/certs/ca.crt");
@@ -198,7 +200,7 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
m_webserver_enabled = m_config->get_scalar<bool>("webserver", "enabled", false);
m_webserver_listen_port = m_config->get_scalar<uint32_t>("webserver", "listen_port", 8765);
m_webserver_k8s_audit_endpoint = m_config->get_scalar<string>("webserver", "k8s_audit_endpoint", "/k8s_audit");
m_webserver_k8s_audit_endpoint = m_config->get_scalar<string>("webserver", "k8s_audit_endpoint", "/k8s-audit");
m_webserver_ssl_enabled = m_config->get_scalar<bool>("webserver", "ssl_enabled", false);
m_webserver_ssl_certificate = m_config->get_scalar<string>("webserver", "ssl_certificate", "/etc/falco/falco.pem");
@@ -344,4 +346,4 @@ void falco_configuration::set_cmdline_option(const string &opt)
{
m_config->set_scalar(keyval.first, keyval.second);
}
}
}

View File

@@ -206,7 +206,7 @@ public:
bool m_time_format_iso_8601;
bool m_grpc_enabled;
int m_grpc_threadiness;
uint32_t m_grpc_threadiness;
std::string m_grpc_bind_address;
std::string m_grpc_private_key;
std::string m_grpc_cert_chain;

View File

@@ -140,9 +140,9 @@ static void usage()
" -P, --pidfile <pid_file> When run as a daemon, write pid to specified file\n"
" -r <rules_file> Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml).\n"
" Can be specified multiple times to read from multiple files/directories.\n"
" -s <stats_file> If specified, write statistics related to falco's reading/processing of events\n"
" to this file. (Only useful in live mode).\n"
" --stats_interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n"
" -s <stats_file> If specified, append statistics related to Falco's reading/processing of events\n"
" to this file (only useful in live mode).\n"
" --stats-interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n"
" This uses signals, so don't recommend intervals below 200 ms.\n"
" Defaults to 5000 (5 seconds).\n"
" -S <len>, --snaplen <len>\n"
@@ -479,7 +479,7 @@ int falco_init(int argc, char **argv)
{"print-base64", no_argument, 0, 'b'},
{"print", required_argument, 0, 'p'},
{"snaplen", required_argument, 0, 'S'},
{"stats_interval", required_argument, 0},
{"stats-interval", required_argument, 0},
{"support", no_argument, 0},
{"unbuffered", no_argument, 0, 'U'},
{"validate", required_argument, 0, 'V'},
@@ -646,7 +646,7 @@ int falco_init(int argc, char **argv)
list_flds_source = optarg;
}
}
else if (string(long_options[long_index].name) == "stats_interval")
else if (string(long_options[long_index].name) == "stats-interval")
{
stats_interval = atoi(optarg);
}
@@ -1206,6 +1206,7 @@ int falco_init(int argc, char **argv)
// gRPC server
if(config.m_grpc_enabled)
{
falco_logger::log(LOG_INFO, "gRPC server threadiness equals to " + to_string(config.m_grpc_threadiness) + "\n");
// TODO(fntlnz,leodido): when we want to spawn multiple threads we need to have a queue per thread, or implement
// different queuing mechanisms, round robin, fanout? What we want to achieve?
grpc_server.init(
@@ -1260,6 +1261,14 @@ int falco_init(int argc, char **argv)
}
// Honor -M also when using a trace file.
// Since inspection stops as soon as all events have been consumed
// just await the given duration is reached, if needed.
if(!trace_filename.empty() && duration_to_tot>0)
{
std::this_thread::sleep_for(std::chrono::seconds(duration_to_tot));
}
inspector->close();
engine->print_stats();
sdropmgr.print_stats();

View File

@@ -22,11 +22,10 @@ limitations under the License.
#include "formats.h"
#include "logger.h"
#include "falco_output_queue.h"
#include "falco_outputs_queue.h"
#include "banned.h" // This raises a compilation error when certain functions are used
using namespace std;
using namespace falco::output;
const static struct luaL_reg ll_falco_outputs [] =
{
@@ -316,7 +315,7 @@ int falco_outputs::handle_grpc(lua_State *ls)
lua_error(ls);
}
response grpc_res = response();
falco::outputs::response grpc_res;
// time
gen_event *evt = (gen_event *)lua_topointer(ls, 1);
@@ -366,7 +365,7 @@ int falco_outputs::handle_grpc(lua_State *ls)
auto host = grpc_res.mutable_hostname();
*host = (char *)lua_tostring(ls, 7);
falco::output::queue::get().push(grpc_res);
falco::outputs::queue::get().push(grpc_res);
return 1;
}

View File

@@ -16,12 +16,12 @@ limitations under the License.
#pragma once
#include "output.pb.h"
#include "outputs.pb.h"
#include "tbb/concurrent_queue.h"
namespace falco
{
namespace output
namespace outputs
{
typedef tbb::concurrent_queue<response> response_cq;

View File

@@ -36,7 +36,7 @@ class context
{
public:
context(::grpc::ServerContext* ctx);
~context() = default;
virtual ~context() = default;
void get_metadata(std::string key, std::string& val);
@@ -50,7 +50,7 @@ class stream_context : public context
public:
stream_context(::grpc::ServerContext* ctx):
context(ctx){};
~stream_context() = default;
virtual ~stream_context() = default;
enum : char
{
@@ -61,6 +61,15 @@ public:
mutable void* m_stream = nullptr; // todo(fntlnz, leodido) > useful in the future
mutable bool m_has_more = false;
mutable bool m_is_running = true;
};
class bidi_context : public stream_context
{
public:
bidi_context(::grpc::ServerContext* ctx):
stream_context(ctx){};
virtual ~bidi_context() = default;
};
} // namespace grpc

View File

@@ -24,12 +24,12 @@ namespace grpc
{
template<>
void request_stream_context<falco::output::service, falco::output::request, falco::output::response>::start(server* srv)
void request_stream_context<outputs::service, outputs::request, outputs::response>::start(server* srv)
{
m_state = request_context_base::REQUEST;
m_srv_ctx.reset(new ::grpc::ServerContext);
auto srvctx = m_srv_ctx.get();
m_res_writer.reset(new ::grpc::ServerAsyncWriter<output::response>(srvctx));
m_res_writer.reset(new ::grpc::ServerAsyncWriter<outputs::response>(srvctx));
m_stream_ctx.reset();
m_req.Clear();
auto cq = srv->m_completion_queue.get();
@@ -38,7 +38,7 @@ void request_stream_context<falco::output::service, falco::output::request, falc
}
template<>
void request_stream_context<falco::output::service, falco::output::request, falco::output::response>::process(server* srv)
void request_stream_context<outputs::service, outputs::request, outputs::response>::process(server* srv)
{
// When it is the 1st process call
if(m_state == request_context_base::REQUEST)
@@ -48,40 +48,46 @@ void request_stream_context<falco::output::service, falco::output::request, falc
}
// Processing
output::response res;
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // subscribe()
outputs::response res;
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // get()
if(!m_stream_ctx->m_is_running)
{
m_state = request_context_base::FINISH;
m_res_writer->Finish(::grpc::Status::OK, this);
return;
}
// When there are still more responses to stream
if(m_stream_ctx->m_has_more)
{
// todo(leodido) > log "write: tag=this, state=m_state"
m_res_writer->Write(res, this);
return;
}
// No more responses to stream
else
{
// Communicate to the gRPC runtime that we have finished.
// The memory address of "this" instance uniquely identifies the event.
m_state = request_context_base::FINISH;
// todo(leodido) > log "finish: tag=this, state=m_state"
m_res_writer->Finish(::grpc::Status::OK, this);
}
// Communicate to the gRPC runtime that we have finished.
// The memory address of "this" instance uniquely identifies the event.
m_state = request_context_base::FINISH;
// todo(leodido) > log "finish: tag=this, state=m_state"
m_res_writer->Finish(::grpc::Status::OK, this);
}
template<>
void request_stream_context<falco::output::service, falco::output::request, falco::output::response>::end(server* srv, bool errored)
void request_stream_context<outputs::service, outputs::request, outputs::response>::end(server* srv, bool error)
{
if(m_stream_ctx)
{
if(errored)
if(error)
{
// todo(leodido) > log error "error streaming: tag=this, state=m_state, stream=m_stream_ctx->m_stream"
}
m_stream_ctx->m_status = errored ? stream_context::ERROR : stream_context::SUCCESS;
m_stream_ctx->m_status = error ? stream_context::ERROR : stream_context::SUCCESS;
// Complete the processing
output::response res;
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // subscribe()
outputs::response res;
(srv->*m_process_func)(*m_stream_ctx, m_req, res); // get()
}
else
{
@@ -98,7 +104,7 @@ void request_stream_context<falco::output::service, falco::output::request, falc
}
template<>
void falco::grpc::request_context<falco::version::service, falco::version::request, falco::version::response>::start(server* srv)
void request_context<version::service, version::request, version::response>::start(server* srv)
{
m_state = request_context_base::REQUEST;
m_srv_ctx.reset(new ::grpc::ServerContext);
@@ -113,7 +119,7 @@ void falco::grpc::request_context<falco::version::service, falco::version::reque
}
template<>
void falco::grpc::request_context<falco::version::service, falco::version::request, falco::version::response>::process(server* srv)
void request_context<version::service, version::request, version::response>::process(server* srv)
{
version::response res;
(srv->*m_process_func)(m_srv_ctx.get(), m_req, res);
@@ -125,13 +131,85 @@ void falco::grpc::request_context<falco::version::service, falco::version::reque
}
template<>
void falco::grpc::request_context<falco::version::service, falco::version::request, falco::version::response>::end(server* srv, bool errored)
void request_context<version::service, version::request, version::response>::end(server* srv, bool error)
{
// todo(leodido) > handle processing errors here
// Ask to start processing requests
start(srv);
}
template<>
void request_bidi_context<outputs::service, outputs::request, outputs::response>::start(server* srv)
{
m_state = request_context_base::REQUEST;
m_srv_ctx.reset(new ::grpc::ServerContext);
auto srvctx = m_srv_ctx.get();
m_reader_writer.reset(new ::grpc::ServerAsyncReaderWriter<outputs::response, outputs::request>(srvctx));
m_req.Clear();
auto cq = srv->m_completion_queue.get();
// Request to start processing given requests.
// Using "this" - ie., the memory address of this context - as the tag that uniquely identifies the request.
// In this way, different contexts can serve different requests concurrently.
(srv->m_output_svc.*m_request_func)(srvctx, m_reader_writer.get(), cq, cq, this);
};
template<>
void request_bidi_context<outputs::service, outputs::request, outputs::response>::process(server* srv)
{
switch(m_state)
{
case request_context_base::REQUEST:
m_bidi_ctx.reset(new bidi_context(m_srv_ctx.get()));
m_bidi_ctx->m_status = bidi_context::STREAMING;
m_state = request_context_base::WRITE;
m_reader_writer->Read(&m_req, this);
return;
case request_context_base::WRITE:
// Processing
{
outputs::response res;
(srv->*m_process_func)(*m_bidi_ctx, m_req, res); // sub()
if(!m_bidi_ctx->m_is_running)
{
m_state = request_context_base::FINISH;
m_reader_writer->Finish(::grpc::Status::OK, this);
return;
}
if(m_bidi_ctx->m_has_more)
{
m_state = request_context_base::WRITE;
m_reader_writer->Write(res, this);
return;
}
m_state = request_context_base::WRITE;
m_reader_writer->Read(&m_req, this);
}
return;
default:
return;
}
};
template<>
void request_bidi_context<outputs::service, outputs::request, outputs::response>::end(server* srv, bool error)
{
if(m_bidi_ctx)
{
m_bidi_ctx->m_status = error ? bidi_context::ERROR : bidi_context::SUCCESS;
// Complete the processing
outputs::response res;
(srv->*m_process_func)(*m_bidi_ctx, m_req, res); // sub()
}
// Ask to start processing requests
start(srv);
};
} // namespace grpc
} // namespace falco
} // namespace falco

View File

@@ -29,7 +29,8 @@ class request_context_base
{
public:
request_context_base() = default;
~request_context_base() = default;
// virtual to guarantee that the derived classes are destructed properly
virtual ~request_context_base() = default;
std::unique_ptr<::grpc::ServerContext> m_srv_ctx;
enum : char
@@ -39,6 +40,7 @@ public:
WRITE,
FINISH
} m_state = UNKNOWN;
virtual void start(server* srv) = 0;
virtual void process(server* srv) = 0;
virtual void end(server* srv, bool isError) = 0;
@@ -63,7 +65,7 @@ public:
void start(server* srv);
void process(server* srv);
void end(server* srv, bool isError);
void end(server* srv, bool error);
private:
std::unique_ptr<::grpc::ServerAsyncWriter<Response>> m_res_writer;
@@ -90,11 +92,37 @@ public:
void start(server* srv);
void process(server* srv);
void end(server* srv, bool isError);
void end(server* srv, bool error);
private:
std::unique_ptr<::grpc::ServerAsyncResponseWriter<Response>> m_res_writer;
Request m_req;
};
template<class Service, class Request, class Response>
class request_bidi_context : public request_context_base
{
public:
request_bidi_context():
m_process_func(nullptr),
m_request_func(nullptr){};
~request_bidi_context() = default;
// Pointer to function that does actual processing
void (server::*m_process_func)(const bidi_context&, const Request&, Response&);
// Pointer to function that requests the system to start processing given requests
void (Service::AsyncService::*m_request_func)(::grpc::ServerContext*, ::grpc::ServerAsyncReaderWriter<Response, Request>*, ::grpc::CompletionQueue*, ::grpc::ServerCompletionQueue*, void*);
void start(server* srv);
void process(server* srv);
void end(server* srv, bool error);
private:
std::unique_ptr<::grpc::ServerAsyncReaderWriter<Response, Request>> m_reader_writer;
std::unique_ptr<bidi_context> m_bidi_ctx;
Request m_req;
};
} // namespace grpc
} // namespace falco
} // namespace falco

View File

@@ -44,6 +44,15 @@ limitations under the License.
c.start(this); \
}
#define REGISTER_BIDI(req, res, svc, rpc, impl, num) \
std::vector<request_bidi_context<svc, req, res>> rpc##_contexts(num); \
for(request_bidi_context<svc, req, res> & c : rpc##_contexts) \
{ \
c.m_process_func = &server::impl; \
c.m_request_func = &svc::AsyncService::Request##rpc; \
c.start(this); \
}
static void gpr_log_dispatcher_func(gpr_log_func_args* args)
{
int priority;
@@ -60,7 +69,10 @@ static void gpr_log_dispatcher_func(gpr_log_func_args* args)
break;
}
falco_logger::log(priority, args->message);
string copy = "grpc: ";
copy.append(args->message);
copy.push_back('\n');
falco_logger::log(priority, copy);
}
void falco::grpc::server::thread_process(int thread_index)
@@ -199,7 +211,8 @@ void falco::grpc::server::run()
// todo(leodido) > take a look at thread_stress_test.cc into grpc repository
REGISTER_UNARY(version::request, version::response, version::service, version, version, context_num)
REGISTER_STREAM(output::request, output::response, output::service, subscribe, subscribe, context_num)
REGISTER_STREAM(outputs::request, outputs::response, outputs::service, get, get, context_num)
REGISTER_BIDI(outputs::request, outputs::response, outputs::service, sub, sub, context_num)
m_threads.resize(m_threadiness);
int thread_idx = 0;
@@ -211,7 +224,7 @@ void falco::grpc::server::run()
while(server_impl::is_running())
{
sleep(1);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// todo(leodido) > log "stopping gRPC server"
stop();

View File

@@ -44,7 +44,7 @@ public:
void run();
void stop();
output::service::AsyncService m_output_svc;
outputs::service::AsyncService m_output_svc;
version::service::AsyncService m_version_svc;
std::unique_ptr<::grpc::ServerCompletionQueue> m_completion_queue;

View File

@@ -16,7 +16,8 @@ limitations under the License.
#include "config_falco.h"
#include "grpc_server_impl.h"
#include "falco_output_queue.h"
#include "falco_outputs_queue.h"
#include "logger.h"
#include "banned.h" // This raises a compilation error when certain functions are used
bool falco::grpc::server_impl::is_running()
@@ -28,29 +29,39 @@ bool falco::grpc::server_impl::is_running()
return true;
}
void falco::grpc::server_impl::subscribe(const stream_context& ctx, const output::request& req, output::response& res)
void falco::grpc::server_impl::get(const stream_context& ctx, const outputs::request& req, outputs::response& res)
{
if(ctx.m_status == stream_context::SUCCESS || ctx.m_status == stream_context::ERROR)
{
// todo(leodido) > log "status=ctx->m_status, stream=ctx->m_stream"
ctx.m_stream = nullptr;
return;
}
else
{
// Start or continue streaming
// todo(leodido) > check for m_status == stream_context::STREAMING?
// todo(leodido) > set m_stream
if(output::queue::get().try_pop(res) && !req.keepalive())
{
ctx.m_has_more = true;
return;
}
while(is_running() && !output::queue::get().try_pop(res) && req.keepalive())
{
}
ctx.m_has_more = !is_running() ? false : req.keepalive();
ctx.m_is_running = is_running();
// Start or continue streaming
// m_status == stream_context::STREAMING?
// todo(leodido) > set m_stream
ctx.m_has_more = outputs::queue::get().try_pop(res);
}
void falco::grpc::server_impl::sub(const bidi_context& ctx, const outputs::request& req, outputs::response& res)
{
if(ctx.m_status == stream_context::SUCCESS || ctx.m_status == stream_context::ERROR)
{
ctx.m_stream = nullptr;
return;
}
ctx.m_is_running = is_running();
// Start or continue streaming
// m_status == stream_context::STREAMING?
// todo(leodido) > set m_stream
ctx.m_has_more = outputs::queue::get().try_pop(res);
}
void falco::grpc::server_impl::version(const context& ctx, const version::request&, version::response& res)

View File

@@ -17,7 +17,7 @@ limitations under the License.
#pragma once
#include <atomic>
#include "output.grpc.pb.h"
#include "outputs.grpc.pb.h"
#include "version.grpc.pb.h"
#include "grpc_context.h"
@@ -36,8 +36,11 @@ public:
protected:
bool is_running();
void subscribe(const stream_context& ctx, const output::request& req, output::response& res);
// Outputs
void get(const stream_context& ctx, const outputs::request& req, outputs::response& res);
void sub(const bidi_context& ctx, const outputs::request& req, outputs::response& res);
// Version
void version(const context& ctx, const version::request& req, version::response& res);
private:

View File

@@ -18,7 +18,7 @@ local mod = {}
local outputs = {}
function mod.stdout(event, rule, source, priority, priority_num, msg, format, hostname, options)
mod.stdout_message(priority, priority_num, msg, outputs)
mod.stdout_message(priority, priority_num, msg, options)
end
function mod.stdout_message(priority, priority_num, msg, options)

View File

@@ -1,40 +0,0 @@
syntax = "proto3";
import "google/protobuf/timestamp.proto";
import "schema.proto";
package falco.output;
option go_package = "github.com/falcosecurity/client-go/pkg/api/output";
// The `subscribe` service defines the RPC call
// to perform an output `request` which will lead to obtain an output `response`.
service service {
rpc subscribe(request) returns (stream response);
}
// The `request` message is the logical representation of the request model.
// It is the input of the `subscribe` service.
// It is used to configure the kind of subscription to the gRPC streaming server.
//
// By default the request asks to the server to only receive the accumulated events.
// In case you want to wait indefinitely for new events to come set the keepalive option to true.
message request {
bool keepalive = 1;
// string duration = 2; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
// repeated string tags = 3; // TODO(leodido, fntlnz): not handled yet but keeping for reference.
}
// The `response` message is the logical representation of the output model.
// It contains all the elements that Falco emits in an output along with the
// definitions for priorities and source.
message response {
google.protobuf.Timestamp time = 1;
falco.schema.priority priority = 2;
falco.schema.source source = 3;
string rule = 4;
string output = 5;
map<string, string> output_fields = 6;
string hostname = 7;
// repeated string tags = 8; // TODO(leodido,fntlnz): tags not supported yet, keeping for reference
}

View File

@@ -0,0 +1,55 @@
/*
Copyright (C) 2020 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
syntax = "proto3";
import "google/protobuf/timestamp.proto";
import "schema.proto";
package falco.outputs;
option go_package = "github.com/falcosecurity/client-go/pkg/api/outputs";
// This service defines the RPC methods
// to `request` a stream of output `response`s.
service service {
// Subscribe to a stream of Falco outputs by sending a stream of requests.
rpc sub(stream request) returns (stream response);
// Get all the Falco outputs present in the system up to this call.
rpc get(request) returns (stream response);
}
// The `request` message is the logical representation of the request model.
// It is the input of the `output.service` service.
message request {
// TODO(leodido,fntlnz): tags not supported yet, keeping it for reference.
// repeated string tags = 1;
}
// The `response` message is the representation of the output model.
// It contains all the elements that Falco emits in an output along with the
// definitions for priorities and source.
message response {
google.protobuf.Timestamp time = 1;
falco.schema.priority priority = 2;
falco.schema.source source = 3;
string rule = 4;
string output = 5;
map<string, string> output_fields = 6;
string hostname = 7;
// TODO(leodido,fntlnz): tags not supported yet, keeping it for reference.
// repeated string tags = 8;
}

View File

@@ -1,3 +1,19 @@
/*
Copyright (C) 2020 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
syntax = "proto3";
package falco.schema;

View File

@@ -58,8 +58,8 @@ bool StatsFileWriter::init(sinsp *inspector, string &filename, uint32_t interval
return false;
}
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = interval_msec * 1000;
timer.it_value.tv_sec = interval_msec / 1000;
timer.it_value.tv_usec = (interval_msec % 1000) * 1000;
timer.it_interval = timer.it_value;
if (setitimer(ITIMER_REAL, &timer, NULL) == -1)
{

View File

@@ -1,3 +1,19 @@
/*
Copyright (C) 2020 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
syntax = "proto3";
package falco.version;