diff --git a/CMakeLists.txt b/CMakeLists.txt
index 368456e4..343bfb3b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,7 +29,9 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG")
add_definitions(-DPLATFORM_NAME="${CMAKE_SYSTEM_NAME}")
add_definitions(-DK8S_DISABLE_THREAD)
-add_definitions(-DHAS_CAPTURE)
+if(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ add_definitions(-DHAS_CAPTURE)
+endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(KBUILD_FLAGS "${DRAIOS_DEBUG_FLAGS} ${DRAIOS_FEATURE_FLAGS}")
@@ -46,6 +48,10 @@ set(CMAKE_INSTALL_PREFIX /usr)
set(CMD_MAKE make)
set(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig")
+# make luaJIT work on OS X
+if(APPLE)
+ set(CMAKE_EXE_LINKER_FLAGS "-pagezero_size 10000 -image_base 100000000")
+endif()
include(ExternalProject)
@@ -295,14 +301,18 @@ if(NOT USE_BUNDLED_LPEG)
else()
set(LPEG_SRC "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg")
set(LPEG_LIB "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg/build/lpeg.a")
+ set(LPEG_DEPENDENCIES "")
+ if(USE_BUNDLED_LUAJIT)
+ list(APPEND LPEG_DEPENDENCIES "luajit")
+ endif()
ExternalProject_Add(lpeg
- DEPENDS luajit
+ DEPENDS ${LPEG_DEPENDENCIES}
URL "http://s3.amazonaws.com/download.draios.com/dependencies/lpeg-1.0.0.tar.gz"
- URL_MD5 "0aec64ccd13996202ad0c099e2877ece"
- BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
- BUILD_IN_SOURCE 1
+ URL_MD5 "0aec64ccd13996202ad0c099e2877ece"
+ BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
+ BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
- INSTALL_COMMAND "")
+ INSTALL_COMMAND "")
endif()
#
@@ -332,11 +342,11 @@ else()
set(LIBYAML_LIB "${LIBYAML_SRC}/.libs/libyaml.a")
ExternalProject_Add(libyaml
URL "http://download.draios.com/dependencies/libyaml-0.1.4.tar.gz"
- URL_MD5 "4a4bced818da0b9ae7fc8ebc690792a7"
- BUILD_COMMAND ${CMD_MAKE}
- BUILD_IN_SOURCE 1
+ URL_MD5 "4a4bced818da0b9ae7fc8ebc690792a7"
+ BUILD_COMMAND ${CMD_MAKE}
+ BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./bootstrap && ./configure
- INSTALL_COMMAND "")
+ INSTALL_COMMAND "")
endif()
#
@@ -357,8 +367,15 @@ if(NOT USE_BUNDLED_LYAML)
else()
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
+ set(LYAML_DEPENDENCIES "")
+ if(USE_BUNDLED_LUAJIT)
+ list(APPEND LYAML_DEPENDENCIES "luajit")
+ endif()
+ if(USE_BUNDLED_LIBYAML)
+ list(APPEND LYAML_DEPENDENCIES "libyaml")
+ endif()
ExternalProject_Add(lyaml
- DEPENDS libyaml luajit
+ DEPENDS ${LYAML_DEPENDENCIES}
URL "http://download.draios.com/dependencies/lyaml-release-v6.0.tar.gz"
URL_MD5 "dc3494689a0dce7cf44e7a99c72b1f30"
BUILD_COMMAND ${CMD_MAKE}
@@ -370,7 +387,9 @@ endif()
install(FILES falco.yaml
DESTINATION "${FALCO_ETC_DIR}")
-add_subdirectory("${SYSDIG_DIR}/driver" "${PROJECT_BINARY_DIR}/driver")
+if(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ add_subdirectory("${SYSDIG_DIR}/driver" "${PROJECT_BINARY_DIR}/driver")
+endif()
add_subdirectory("${SYSDIG_DIR}/userspace/libscap" "${PROJECT_BINARY_DIR}/userspace/libscap")
add_subdirectory("${SYSDIG_DIR}/userspace/libsinsp" "${PROJECT_BINARY_DIR}/userspace/libsinsp")
diff --git a/examples/k8s-using-daemonset/README.md b/examples/k8s-using-daemonset/README.md
new file mode 100644
index 00000000..b81b6f3b
--- /dev/null
+++ b/examples/k8s-using-daemonset/README.md
@@ -0,0 +1,5 @@
+=Example K8s Services for Falco=
+
+The yaml file in this directory installs the following:
+ - Open Source Falco, as a DaemonSet. Falco is configured to communicate with the K8s API server via its service account, and changes its output to be K8s-friendly. It also sends to a slack webhook for the `#demo-falco-alerts` channel on our [public slack](https://sysdig.slack.com/messages/demo-falco-alerts/).
+ - The [Falco Event Generator](https://github.com/draios/falco/wiki/Generating-Sample-Events), as a deployment that ensures it runs on exactly 1 node.
diff --git a/examples/k8s-using-daemonset/falco-daemonset.yaml b/examples/k8s-using-daemonset/falco-daemonset.yaml
new file mode 100644
index 00000000..19ae8ba4
--- /dev/null
+++ b/examples/k8s-using-daemonset/falco-daemonset.yaml
@@ -0,0 +1,59 @@
+apiVersion: extensions/v1beta1
+kind: DaemonSet
+metadata:
+ name: falco
+ labels:
+ name: falco-daemonset
+ app: demo
+spec:
+ template:
+ metadata:
+ labels:
+ name: falco
+ app: demo
+ role: security
+ spec:
+ containers:
+ - name: falco
+ image: sysdig/falco:latest
+ securityContext:
+ privileged: true
+ command: [ "/usr/bin/falco", "-K", "/var/run/secrets/kubernetes.io/serviceaccount/token", "-k", "https://kubernetes", "-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/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"]
+ volumeMounts:
+ - mountPath: /host/var/run/docker.sock
+ name: docker-socket
+ readOnly: true
+ - mountPath: /host/dev
+ name: dev-fs
+ readOnly: true
+ - mountPath: /host/proc
+ name: proc-fs
+ readOnly: true
+ - mountPath: /host/boot
+ name: boot-fs
+ readOnly: true
+ - mountPath: /host/lib/modules
+ name: lib-modules
+ readOnly: true
+ - mountPath: /host/usr
+ name: usr-fs
+ readOnly: true
+ volumes:
+ - name: docker-socket
+ hostPath:
+ path: /var/run/docker.sock
+ - name: dev-fs
+ hostPath:
+ path: /dev
+ - name: proc-fs
+ hostPath:
+ path: /proc
+ - name: boot-fs
+ hostPath:
+ path: /boot
+ - name: lib-modules
+ hostPath:
+ path: /lib/modules
+ - name: usr-fs
+ hostPath:
+ path: /usr
diff --git a/examples/k8s-using-daemonset/falco-event-generator-deployment.yaml b/examples/k8s-using-daemonset/falco-event-generator-deployment.yaml
new file mode 100644
index 00000000..00789e8c
--- /dev/null
+++ b/examples/k8s-using-daemonset/falco-event-generator-deployment.yaml
@@ -0,0 +1,17 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: falco-event-generator-deployment
+ labels:
+ name: falco-event-generator-deployment
+ app: demo
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: falco-event-generator
+ spec:
+ containers:
+ - name: falco-event-generator
+ image: sysdig/falco-event-generator:latest
diff --git a/rules/falco_rules.yaml b/rules/falco_rules.yaml
index 3fba1462..6a453d5e 100644
--- a/rules/falco_rules.yaml
+++ b/rules/falco_rules.yaml
@@ -76,7 +76,7 @@
# dpkg -L login | grep bin | xargs ls -ld | grep -v '^d' | awk '{print $9}' | xargs -L 1 basename | tr "\\n" ","
- list: login_binaries
- items: [login, systemd, systemd-logind, su, nologin, faillog, lastlog, newgrp, sg]
+ items: [login, systemd, '"(systemd)"', systemd-logind, su, nologin, faillog, lastlog, newgrp, sg]
# dpkg -L passwd | grep bin | xargs ls -ld | grep -v '^d' | awk '{print $9}' | xargs -L 1 basename | tr "\\n" ","
- list: passwd_binaries
@@ -113,6 +113,9 @@
- list: db_server_binaries
items: [mysqld]
+- list: gitlab_binaries
+ items: [gitlab-shell, git]
+
- macro: server_procs
condition: proc.name in (http_server_binaries, db_server_binaries, docker_binaries, sshd)
@@ -256,7 +259,7 @@
package_mgmt_binaries, ssl_mgmt_binaries, dhcp_binaries,
ldconfig.real, ldconfig, confd, gpg, insserv,
apparmor_parser, update-mime, tzdata.config, tzdata.postinst,
- systemd-machine, debconf-show, rollerd, bind9.postinst)
+ systemd-machine, debconf-show, rollerd, bind9.postinst, sv)
and not proc.pname in (sysdigcloud_binaries)
and not fd.directory in (/etc/cassandra, /etc/ssl/certs/java)
and not ansible_running_python
@@ -365,7 +368,7 @@
logrotate, ansible, less, adduser, pycompile, py3compile,
pyclean, py3clean, pip, pip2, ansible-playboo, man-db,
init, pluto, mkinitramfs, unattended-upgr, watch, sysdig,
- landscape-sysin, nessusd, PM2, syslog-summary
+ landscape-sysin, nessusd, PM2, syslog-summary, erl_child_setup
]
- rule: Run shell untrusted
@@ -430,7 +433,7 @@
and shell_procs
and proc.pname exists
and not proc.pname in (shell_binaries, docker_binaries, k8s_binaries, lxd_binaries, aide_wrapper_binaries, nids_binaries,
- monitoring_binaries, initdb, pg_ctl, awk, apache2, falco, cron)
+ monitoring_binaries, gitlab_binaries, initdb, pg_ctl, awk, apache2, falco, cron, erl_child_setup)
and not trusted_containers
output: "Shell spawned in a container other than entrypoint (user=%user.name %container.info shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)"
priority: WARNING
@@ -469,7 +472,7 @@
tags: [host, users]
- list: allowed_dev_files
- items: [/dev/null, /dev/stdin, /dev/stdout, /dev/stderr, /dev/tty, /dev/random, /dev/urandom, /dev/console]
+ items: [/dev/null, /dev/stdin, /dev/stdout, /dev/stderr, /dev/random, /dev/urandom, /dev/console]
# (we may need to add additional checks against false positives, see: https://bugs.launchpad.net/ubuntu/+source/rkhunter/+bug/86153)
- rule: Create files below dev
@@ -479,6 +482,7 @@
(evt.type = creat or (evt.type = open and evt.arg.flags contains O_CREAT))
and not proc.name in (dev_creation_binaries)
and not fd.name in (allowed_dev_files)
+ and not fd.name startswith /dev/tty
output: "File created below /dev by untrusted program (user=%user.name command=%proc.cmdline file=%fd.name)"
priority: WARNING
tags: [filesystem]
diff --git a/userspace/engine/falco_common.cpp b/userspace/engine/falco_common.cpp
index 974dd23b..ac427a12 100644
--- a/userspace/engine/falco_common.cpp
+++ b/userspace/engine/falco_common.cpp
@@ -24,6 +24,10 @@ along with falco. If not, see .
falco_common::falco_common()
{
m_ls = lua_open();
+ if(!m_ls)
+ {
+ throw falco_exception("Cannot open lua");
+ }
luaL_openlibs(m_ls);
}
diff --git a/userspace/engine/formats.cpp b/userspace/engine/formats.cpp
index 7be6eaab..eb25e715 100644
--- a/userspace/engine/formats.cpp
+++ b/userspace/engine/formats.cpp
@@ -24,12 +24,14 @@ along with falco. If not, see .
sinsp* falco_formats::s_inspector = NULL;
-bool s_json_output = false;
+bool falco_formats::s_json_output = false;
+sinsp_evt_formatter_cache *falco_formats::s_formatters = NULL;
const static struct luaL_reg ll_falco [] =
{
{"formatter", &falco_formats::formatter},
{"free_formatter", &falco_formats::free_formatter},
+ {"free_formatters", &falco_formats::free_formatters},
{"format_event", &falco_formats::format_event},
{NULL,NULL}
};
@@ -38,6 +40,10 @@ void falco_formats::init(sinsp* inspector, lua_State *ls, bool json_output)
{
s_inspector = inspector;
s_json_output = json_output;
+ if(!s_formatters)
+ {
+ s_formatters = new sinsp_evt_formatter_cache(s_inspector);
+ }
luaL_openlib(ls, "formats", ll_falco, 0);
}
@@ -73,22 +79,43 @@ int falco_formats::free_formatter(lua_State *ls)
return 0;
}
+int falco_formats::free_formatters(lua_State *ls)
+{
+ if(s_formatters)
+ {
+ delete(s_formatters);
+ s_formatters = NULL;
+ }
+ return 0;
+}
+
int falco_formats::format_event (lua_State *ls)
{
string line;
- if (!lua_islightuserdata(ls, -1) ||
+ if (!lua_isstring(ls, -1) ||
!lua_isstring(ls, -2) ||
!lua_isstring(ls, -3) ||
!lua_islightuserdata(ls, -4)) {
- throw falco_exception("Invalid arguments passed to format_event()\n");
+ lua_pushstring(ls, "Invalid arguments passed to format_event()");
+ lua_error(ls);
}
sinsp_evt* evt = (sinsp_evt*)lua_topointer(ls, 1);
const char *rule = (char *) lua_tostring(ls, 2);
const char *level = (char *) lua_tostring(ls, 3);
- sinsp_evt_formatter* formatter = (sinsp_evt_formatter*)lua_topointer(ls, 4);
+ const char *format = (char *) lua_tostring(ls, 4);
- formatter->tostring(evt, &line);
+ string sformat = format;
+
+ try {
+ s_formatters->tostring(evt, sformat, &line);
+ }
+ catch (sinsp_exception& e)
+ {
+ string err = "Invalid output format '" + sformat + "': '" + string(e.what()) + "'";
+ lua_pushstring(ls, err.c_str());
+ lua_error(ls);
+ }
// For JSON output, the formatter returned just the output
// string containing the format text and values. Use this to
diff --git a/userspace/engine/formats.h b/userspace/engine/formats.h
index e5a2781a..c901460b 100644
--- a/userspace/engine/formats.h
+++ b/userspace/engine/formats.h
@@ -39,8 +39,13 @@ class falco_formats
// falco.free_formatter(formatter)
static int free_formatter(lua_State *ls);
+ // falco.free_formatters()
+ static int free_formatters(lua_State *ls);
+
// formatted_string = falco.format_event(evt, formatter)
static int format_event(lua_State *ls);
static sinsp* s_inspector;
+ static sinsp_evt_formatter_cache *s_formatters;
+ static bool s_json_output;
};
diff --git a/userspace/engine/rules.cpp b/userspace/engine/rules.cpp
index 63b9b416..cec545ec 100644
--- a/userspace/engine/rules.cpp
+++ b/userspace/engine/rules.cpp
@@ -49,7 +49,8 @@ int falco_rules::clear_filters(lua_State *ls)
{
if (! lua_islightuserdata(ls, -1))
{
- throw falco_exception("Invalid arguments passed to clear_filters()\n");
+ lua_pushstring(ls, "Invalid arguments passed to clear_filters()");
+ lua_error(ls);
}
falco_rules *rules = (falco_rules *) lua_topointer(ls, -1);
@@ -70,7 +71,8 @@ int falco_rules::add_filter(lua_State *ls)
! lua_istable(ls, -2) ||
! lua_istable(ls, -1))
{
- throw falco_exception("Invalid arguments passed to add_filter()\n");
+ lua_pushstring(ls, "Invalid arguments passed to add_filter()");
+ lua_error(ls);
}
falco_rules *rules = (falco_rules *) lua_topointer(ls, -4);
@@ -122,7 +124,8 @@ int falco_rules::enable_rule(lua_State *ls)
! lua_isstring(ls, -2) ||
! lua_isnumber(ls, -1))
{
- throw falco_exception("Invalid arguments passed to enable_rule()\n");
+ lua_pushstring(ls, "Invalid arguments passed to enable_rule()");
+ lua_error(ls);
}
falco_rules *rules = (falco_rules *) lua_topointer(ls, -3);
diff --git a/userspace/falco/lua/output.lua b/userspace/falco/lua/output.lua
index 5a50f9de..a6aa42fb 100644
--- a/userspace/falco/lua/output.lua
+++ b/userspace/falco/lua/output.lua
@@ -24,8 +24,6 @@ mod.levels = levels
local outputs = {}
-local formatters = {}
-
function mod.stdout(level, msg)
print (msg)
end
@@ -84,14 +82,8 @@ function output_event(event, rule, priority, format)
end
format = "*%evt.time: "..levels[level+1].." "..format
- if formatters[rule] == nil then
- formatter = formats.formatter(format)
- formatters[rule] = formatter
- else
- formatter = formatters[rule]
- end
- msg = formats.format_event(event, rule, levels[level+1], formatter)
+ msg = formats.format_event(event, rule, levels[level+1], format)
for index,o in ipairs(outputs) do
o.output(level, msg, o.config)
@@ -99,11 +91,7 @@ function output_event(event, rule, priority, format)
end
function output_cleanup()
- for rule, formatter in pairs(formatters) do
- formats.free_formatter(formatter)
- end
-
- formatters = {}
+ formats.free_formatters()
end
function add_output(output_name, config)