Merge pull request #224 from draios/own-driver

Own driver
This commit is contained in:
Mark Stemm 2017-03-24 21:35:48 -07:00 committed by GitHub
commit 3c2051176e
16 changed files with 291 additions and 47 deletions

View File

@ -2,6 +2,9 @@ language: c
env: env:
- BUILD_TYPE=Debug - BUILD_TYPE=Debug
- BUILD_TYPE=Release - BUILD_TYPE=Release
sudo: required
services:
- docker
before_install: before_install:
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update - sudo apt-get update
@ -9,12 +12,12 @@ install:
- sudo apt-get --force-yes install g++-4.8 - sudo apt-get --force-yes install g++-4.8
- sudo apt-get install rpm linux-headers-$(uname -r) - sudo apt-get install rpm linux-headers-$(uname -r)
- git clone https://github.com/draios/sysdig.git ../sysdig - git clone https://github.com/draios/sysdig.git ../sysdig
- sudo apt-get install -y python-pip libvirt-dev jq - sudo apt-get install -y python-pip libvirt-dev jq dkms
- cd .. - cd ..
- curl -Lo avocado-36.0-tar.gz https://github.com/avocado-framework/avocado/archive/36.0lts.tar.gz - curl -Lo avocado-36.0-tar.gz https://github.com/avocado-framework/avocado/archive/36.0lts.tar.gz
- tar -zxvf avocado-36.0-tar.gz - tar -zxvf avocado-36.0-tar.gz
- cd avocado-36.0lts - cd avocado-36.0lts
- sudo pip install -r requirements-travis.txt - sudo -H pip install -r requirements.txt
- sudo python setup.py install - sudo python setup.py install
- cd ../falco - cd ../falco
before_script: before_script:
@ -35,7 +38,10 @@ script:
- cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DDRAIOS_DEBUG_FLAGS="-D_DEBUG -DNDEBUG" - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DDRAIOS_DEBUG_FLAGS="-D_DEBUG -DNDEBUG"
- make VERBOSE=1 - make VERBOSE=1
- make package - make package
- cd .. - cp falco*.deb ../docker/local
- cd ../docker/local
- docker build -t sysdig/falco:test .
- cd ../..
- sudo test/run_regression_tests.sh $TRAVIS_BRANCH - sudo test/run_regression_tests.sh $TRAVIS_BRANCH
notifications: notifications:
webhooks: webhooks:

View File

@ -41,8 +41,8 @@ endif()
set(PACKAGE_NAME "falco") set(PACKAGE_NAME "falco")
set(PROBE_VERSION "${FALCO_VERSION}") set(PROBE_VERSION "${FALCO_VERSION}")
set(PROBE_NAME "sysdig-probe") set(PROBE_NAME "falco-probe")
set(PROBE_DEVICE_NAME "sysdig") set(PROBE_DEVICE_NAME "falco")
set(CMAKE_INSTALL_PREFIX /usr) set(CMAKE_INSTALL_PREFIX /usr)
set(CMD_MAKE make) set(CMD_MAKE make)
@ -415,12 +415,12 @@ set(CPACK_GENERATOR DEB RPM TGZ)
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Sysdig <support@sysdig.com>") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Sysdig <support@sysdig.com>")
set(CPACK_DEBIAN_PACKAGE_SECTION "utils") set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://www.sysdig.org") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://www.sysdig.org")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "sysdig") set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0)")
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${PROJECT_SOURCE_DIR}/scripts/debian/postinst;${PROJECT_SOURCE_DIR}/scripts/debian/prerm;${PROJECT_SOURCE_DIR}/scripts/debian/postrm") set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_BINARY_DIR}/scripts/debian/postinst;${CMAKE_BINARY_DIR}/scripts/debian/prerm;${PROJECT_SOURCE_DIR}/scripts/debian/postrm")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2") set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
set(CPACK_RPM_PACKAGE_URL "http://www.sysdig.org") set(CPACK_RPM_PACKAGE_URL "http://www.sysdig.org")
set(CPACK_RPM_PACKAGE_REQUIRES "sysdig") set(CPACK_RPM_PACKAGE_REQUIRES "dkms, gcc, make, kernel-devel, perl")
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/postinstall") set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/postinstall")
set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/preuninstall") set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/preuninstall")
set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/postuninstall") set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/postuninstall")

View File

@ -11,7 +11,7 @@ if [[ -z "${SYSDIG_SKIP_LOAD}" ]]; then
ln -s $SYSDIG_HOST_ROOT/usr/src/$i /usr/src/$i ln -s $SYSDIG_HOST_ROOT/usr/src/$i /usr/src/$i
done done
/usr/bin/sysdig-probe-loader /usr/bin/falco-probe-loader
fi fi
exec "$@" exec "$@"

View File

@ -25,7 +25,7 @@ RUN echo "deb http://httpredir.debian.org/debian jessie main" > /etc/apt/sources
gcc \ gcc \
gcc-5 \ gcc-5 \
gcc-4.9 \ gcc-4.9 \
sysdig && rm -rf /var/lib/apt/lists/* dkms && rm -rf /var/lib/apt/lists/*
# Since our base Debian image ships with GCC 5.0 which breaks older kernels, revert the # Since our base Debian image ships with GCC 5.0 which breaks older kernels, revert the
# default to gcc-4.9. Also, since some customers use some very old distributions whose kernel # default to gcc-4.9. Also, since some customers use some very old distributions whose kernel

View File

@ -11,7 +11,7 @@ if [[ -z "${SYSDIG_SKIP_LOAD}" ]]; then
ln -s $SYSDIG_HOST_ROOT/usr/src/$i /usr/src/$i ln -s $SYSDIG_HOST_ROOT/usr/src/$i /usr/src/$i
done done
/usr/bin/sysdig-probe-loader /usr/bin/falco-probe-loader
fi fi
exec "$@" exec "$@"

View File

@ -11,7 +11,7 @@ if [[ -z "${SYSDIG_SKIP_LOAD}" ]]; then
ln -s $SYSDIG_HOST_ROOT/usr/src/$i /usr/src/$i ln -s $SYSDIG_HOST_ROOT/usr/src/$i /usr/src/$i
done done
/usr/bin/sysdig-probe-loader /usr/bin/falco-probe-loader
fi fi
exec "$@" exec "$@"

View File

@ -1,5 +1,12 @@
configure_file(debian/postinst.in debian/postinst)
configure_file(debian/prerm.in debian/prerm)
file(COPY "${PROJECT_SOURCE_DIR}/scripts/debian/falco" file(COPY "${PROJECT_SOURCE_DIR}/scripts/debian/falco"
DESTINATION "${PROJECT_BINARY_DIR}/scripts/debian") DESTINATION "${PROJECT_BINARY_DIR}/scripts/debian")
file(COPY "${PROJECT_SOURCE_DIR}/scripts/rpm/falco" file(COPY "${PROJECT_SOURCE_DIR}/scripts/rpm/falco"
DESTINATION "${PROJECT_BINARY_DIR}/scripts/rpm") DESTINATION "${PROJECT_BINARY_DIR}/scripts/rpm")
install(PROGRAMS ${SYSDIG_DIR}/scripts/sysdig-probe-loader
DESTINATION bin
RENAME falco-probe-loader)

View File

@ -1,9 +0,0 @@
#!/bin/sh
set -e
NAME=falco
if [ -x "/etc/init.d/$NAME" ]; then
update-rc.d $NAME defaults >/dev/null
fi

32
scripts/debian/postinst.in Executable file
View File

@ -0,0 +1,32 @@
#!/bin/sh
set -e
DKMS_PACKAGE_NAME="@PACKAGE_NAME@"
DKMS_VERSION="@PROBE_VERSION@"
NAME="@PACKAGE_NAME@"
postinst_found=0
case "$1" in
configure)
for DKMS_POSTINST in /usr/lib/dkms/common.postinst /usr/share/$DKMS_PACKAGE_NAME/postinst; do
if [ -f $DKMS_POSTINST ]; then
$DKMS_POSTINST $DKMS_PACKAGE_NAME $DKMS_VERSION /usr/share/$DKMS_PACKAGE_NAME "" $2
postinst_found=1
break
fi
done
if [ "$postinst_found" -eq 0 ]; then
echo "ERROR: DKMS version is too old and $DKMS_PACKAGE_NAME was not"
echo "built with legacy DKMS support."
echo "You must either rebuild $DKMS_PACKAGE_NAME with legacy postinst"
echo "support or upgrade DKMS to a more current version."
exit 1
fi
;;
esac
if [ -x "/etc/init.d/$NAME" ]; then
update-rc.d $NAME defaults >/dev/null
fi

View File

@ -1,13 +0,0 @@
#!/bin/sh
set -e
NAME=falco
if [ -x "/etc/init.d/$NAME" ]; then
if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
invoke-rc.d $NAME stop || exit $?
else
/etc/init.d/$NAME stop || exit $?
fi
fi

23
scripts/debian/prerm.in Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
set -e
NAME="@PACKAGE_NAME@"
if [ -x "/etc/init.d/$NAME" ]; then
if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
invoke-rc.d $NAME stop || exit $?
else
/etc/init.d/$NAME stop || exit $?
fi
fi
DKMS_PACKAGE_NAME="@PACKAGE_NAME@"
DKMS_VERSION="@PROBE_VERSION@"
case "$1" in
remove|upgrade|deconfigure)
if [ "$(dkms status -m $DKMS_PACKAGE_NAME -v $DKMS_VERSION)" ]; then
dkms remove -m $DKMS_PACKAGE_NAME -v $DKMS_VERSION --all
fi
;;
esac

View File

@ -1 +1,15 @@
dkms add -m falco -v %{version} --rpm_safe_upgrade
if [ `uname -r | grep -c "BOOT"` -eq 0 ] && [ -e /lib/modules/`uname -r`/build/include ]; then
dkms build -m falco -v %{version}
dkms install --force -m falco -v %{version}
elif [ `uname -r | grep -c "BOOT"` -gt 0 ]; then
echo -e ""
echo -e "Module build for the currently running kernel was skipped since you"
echo -e "are running a BOOT variant of the kernel."
else
echo -e ""
echo -e "Module build for the currently running kernel was skipped since the"
echo -e "kernel source for this kernel does not seem to be installed."
fi
/sbin/chkconfig --add falco /sbin/chkconfig --add falco

View File

@ -2,3 +2,5 @@ if [ $1 = 0 ]; then
/sbin/service falco stop > /dev/null 2>&1 /sbin/service falco stop > /dev/null 2>&1
/sbin/chkconfig --del falco /sbin/chkconfig --del falco
fi fi
dkms remove -m falco -v %{version} --all --rpm_safe_upgrade

View File

@ -4,6 +4,9 @@ import os
import re import re
import json import json
import sets import sets
import glob
import shutil
import subprocess
from avocado import Test from avocado import Test
from avocado.utils import process from avocado.utils import process
@ -21,9 +24,9 @@ class FalcoTest(Test):
self.stderr_contains = self.params.get('stderr_contains', '*', default='') self.stderr_contains = self.params.get('stderr_contains', '*', default='')
self.exit_status = self.params.get('exit_status', '*', default=0) self.exit_status = self.params.get('exit_status', '*', default=0)
self.should_detect = self.params.get('detect', '*', default=False) self.should_detect = self.params.get('detect', '*', default=False)
self.trace_file = self.params.get('trace_file', '*') self.trace_file = self.params.get('trace_file', '*', default='')
if not os.path.isabs(self.trace_file): if self.trace_file and not os.path.isabs(self.trace_file):
self.trace_file = os.path.join(self.basedir, self.trace_file) self.trace_file = os.path.join(self.basedir, self.trace_file)
self.json_output = self.params.get('json_output', '*', default=False) self.json_output = self.params.get('json_output', '*', default=False)
@ -43,6 +46,8 @@ class FalcoTest(Test):
if not os.path.isabs(self.conf_file): if not os.path.isabs(self.conf_file):
self.conf_file = os.path.join(self.basedir, self.conf_file) self.conf_file = os.path.join(self.basedir, self.conf_file)
self.run_duration = self.params.get('run_duration', '*', default='')
self.disabled_rules = self.params.get('disabled_rules', '*', default='') self.disabled_rules = self.params.get('disabled_rules', '*', default='')
if self.disabled_rules == '': if self.disabled_rules == '':
@ -89,15 +94,23 @@ class FalcoTest(Test):
if not isinstance(self.detect_level, list): if not isinstance(self.detect_level, list):
self.detect_level = [self.detect_level] self.detect_level = [self.detect_level]
# Doing this in 2 steps instead of simply using self.package = self.params.get('package', '*', default='None')
# module_is_loaded to avoid logging lsmod output to the log.
lsmod_output = process.system_output("lsmod", verbose=False)
if linux_modules.parse_lsmod_for_module(lsmod_output, 'sysdig_probe') == {}: if self.package == 'None':
self.log.debug("Loading sysdig kernel module") # Doing this in 2 steps instead of simply using
process.run('sudo insmod {}/driver/sysdig-probe.ko'.format(self.falcodir)) # module_is_loaded to avoid logging lsmod output to the log.
lsmod_output = process.system_output("lsmod", verbose=False)
self.str_variant = self.trace_file if linux_modules.parse_lsmod_for_module(lsmod_output, 'falco_probe') == {}:
self.log.debug("Loading falco kernel module")
process.run('insmod {}/driver/falco-probe.ko'.format(self.falcodir), sudo=True)
self.addl_docker_run_args = self.params.get('addl_docker_run_args', '*', default='')
self.copy_local_driver = self.params.get('copy_local_driver', '*', default=False)
# Used by possibly_copy_local_driver as well as docker run
self.module_dir = os.path.expanduser("~/.sysdig")
self.outputs = self.params.get('outputs', '*', default='') self.outputs = self.params.get('outputs', '*', default='')
@ -111,6 +124,10 @@ class FalcoTest(Test):
output['file'] = item2[0] output['file'] = item2[0]
output['line'] = item2[1] output['line'] = item2[1]
outputs.append(output) outputs.append(output)
filedir = os.path.dirname(output['file'])
# Create the parent directory for the trace file if it doesn't exist.
if not os.path.isdir(filedir):
os.makedirs(filedir)
self.outputs = outputs self.outputs = outputs
self.disable_tags = self.params.get('disable_tags', '*', default='') self.disable_tags = self.params.get('disable_tags', '*', default='')
@ -123,6 +140,10 @@ class FalcoTest(Test):
if self.run_tags == '': if self.run_tags == '':
self.run_tags=[] self.run_tags=[]
def tearDown(self):
if self.package != 'None':
self.uninstall_package()
def check_rules_warnings(self, res): def check_rules_warnings(self, res):
found_warning = sets.Set() found_warning = sets.Set()
@ -231,12 +252,103 @@ class FalcoTest(Test):
if not attr in obj: if not attr in obj:
self.fail("Falco JSON object {} does not contain property \"{}\"".format(line, attr)) self.fail("Falco JSON object {} does not contain property \"{}\"".format(line, attr))
def install_package(self):
if self.package.startswith("docker:"):
image = self.package.split(":", 1)[1]
# Remove an existing falco-test container first. Note we don't check the output--docker rm
# doesn't have an -i equivalent.
res = process.run("docker rm falco-test", ignore_status=True)
rules_dir = os.path.abspath(os.path.join(self.basedir, "./rules"))
conf_dir = os.path.abspath(os.path.join(self.basedir, "../"))
traces_dir = os.path.abspath(os.path.join(self.basedir, "./trace_files"))
self.falco_binary_path = "docker run -i -t --name falco-test --privileged " \
"-v {}:/host/rules -v {}:/host/conf -v {}:/host/traces " \
"-v /var/run/docker.sock:/host/var/run/docker.sock " \
"-v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro " \
"-v /lib/modules:/host/lib/modules:ro -v {}:/root/.sysdig:ro -v " \
"/usr:/host/usr:ro {} {} falco".format(
rules_dir, conf_dir, traces_dir,
self.module_dir, self.addl_docker_run_args, image)
elif self.package.endswith(".deb"):
self.falco_binary_path = '/usr/bin/falco';
package_glob = "{}/{}".format(self.falcodir, self.package)
matches = glob.glob(package_glob)
if len(matches) != 1:
self.fail("Package path {} did not match exactly 1 file. Instead it matched: {}", package_glob, ",".join(matches))
package_path = matches[0]
cmdline = "dpkg -i {}".format(package_path)
self.log.debug("Installing debian package via \"{}\"".format(cmdline))
res = process.run(cmdline, timeout=120, sudo=True)
def uninstall_package(self):
if self.package.startswith("docker:"):
# Remove the falco-test image. Here we *do* check the return value
res = process.run("docker rm falco-test")
elif self.package.endswith(".deb"):
cmdline = "dpkg -r falco"
self.log.debug("Uninstalling debian package via \"{}\"".format(cmdline))
res = process.run(cmdline, timeout=120, sudo=True)
def possibly_copy_driver(self):
# Remove the contents of ~/.sysdig regardless of
# copy_local_driver.
self.log.debug("Checking for module dir {}".format(self.module_dir))
if os.path.isdir(self.module_dir):
self.log.info("Removing files below directory {}".format(self.module_dir))
for rmfile in glob.glob(self.module_dir + "/*"):
self.log.debug("Removing file {}".format(rmfile))
os.remove(rmfile)
if self.copy_local_driver:
verstr = subprocess.check_output([self.falco_binary_path, "--version"]).rstrip()
self.log.info("verstr {}".format(verstr))
falco_version = verstr.split(" ")[2]
self.log.info("falco_version {}".format(falco_version))
arch = subprocess.check_output(["uname", "-m"]).rstrip()
self.log.info("arch {}".format(arch))
kernel_release = subprocess.check_output(["uname", "-r"]).rstrip()
self.log.info("kernel release {}".format(kernel_release))
# sysdig-probe-loader has a more comprehensive set of ways to
# find the config hash. We only look at /boot/config-<kernel release>
md5_output = subprocess.check_output(["md5sum", "/boot/config-{}".format(kernel_release)]).rstrip()
config_hash = md5_output.split(" ")[0]
probe_filename = "falco-probe-{}-{}-{}-{}.ko".format(falco_version, arch, kernel_release, config_hash)
driver_path = os.path.join(self.falcodir, "driver", "falco-probe.ko")
module_path = os.path.join(self.module_dir, probe_filename)
self.log.debug("Copying {} to {}".format(driver_path, module_path))
shutil.copyfile(driver_path, module_path)
def test(self): def test(self):
self.log.info("Trace file %s", self.trace_file) self.log.info("Trace file %s", self.trace_file)
# Run the provided trace file though falco self.falco_binary_path = '{}/userspace/falco/falco'.format(self.falcodir)
cmd = '{}/userspace/falco/falco {} {} -c {} -e {} -o json_output={} -v'.format(
self.falcodir, self.rules_args, self.disabled_args, self.conf_file, self.trace_file, self.json_output) self.possibly_copy_driver()
if self.package != 'None':
# This sets falco_binary_path as a side-effect.
self.install_package()
trace_arg = self.trace_file
if self.trace_file:
trace_arg = "-e {}".format(self.trace_file)
# Run falco
cmd = '{} {} {} -c {} {} -o json_output={} -v'.format(
self.falco_binary_path, self.rules_args, self.disabled_args, self.conf_file, trace_arg, self.json_output)
for tag in self.disable_tags: for tag in self.disable_tags:
cmd += ' -T {}'.format(tag) cmd += ' -T {}'.format(tag)
@ -244,6 +356,9 @@ class FalcoTest(Test):
for tag in self.run_tags: for tag in self.run_tags:
cmd += ' -t {}'.format(tag) cmd += ' -t {}'.format(tag)
if self.run_duration:
cmd += ' -M {}'.format(self.run_duration)
self.falco_proc = process.SubProcess(cmd) self.falco_proc = process.SubProcess(cmd)
res = self.falco_proc.run(timeout=180, sig=9) res = self.falco_proc.run(timeout=180, sig=9)

View File

@ -1,4 +1,38 @@
trace_files: !mux trace_files: !mux
docker_package:
package: docker:sysdig/falco:test
detect: True
detect_level: WARNING
rules_file: /host/rules/rule_names_with_spaces.yaml
trace_file: /host/traces/cat_write.scap
conf_file: /host/conf/falco.yaml
# This uses a volume mount to overwrite and prevent /usr/sbin/dkms
# from being run. As a result, it will force falco-probe-loader to
# fall back to loading the driver from ~/.sysdig. Setting
# copy_local_driver to True copied the driver to ~/.sysdig, so it
# will be available. In this case, we're running live for 5 seconds
# just to see if falco can load the driver.
docker_package_local_driver:
package: docker:sysdig/falco:test
addl_docker_run_args: -v /dev/null:/usr/sbin/dkms
copy_local_driver: True
detect: False
detect_level: WARNING
rules_file: /host/rules/tagged_rules.yaml
conf_file: /host/conf/falco.yaml
run_duration: 5
debian_package:
package: falco*.deb
detect: True
detect_level: WARNING
rules_file:
- rules/rule_names_with_spaces.yaml
trace_file: trace_files/cat_write.scap
builtin_rules_no_warnings: builtin_rules_no_warnings:
detect: False detect: False
trace_file: trace_files/empty.scap trace_file: trace_files/empty.scap

View File

@ -53,6 +53,7 @@ static void signal_callback(int signal)
static void usage() static void usage()
{ {
printf( printf(
"falco version " FALCO_VERSION "\n"
"Usage: falco [options]\n\n" "Usage: falco [options]\n\n"
"Options:\n" "Options:\n"
" -h, --help Print this page\n" " -h, --help Print this page\n"
@ -86,6 +87,7 @@ static void usage()
" Marathon url is optional and defaults to Mesos address, port 8080.\n" " Marathon url is optional and defaults to Mesos address, port 8080.\n"
" The API servers can also be specified via the environment variable\n" " The API servers can also be specified via the environment variable\n"
" FALCO_MESOS_API.\n" " FALCO_MESOS_API.\n"
" -M <num_seconds> Stop collecting after <num_seconds> reached.\n"
" -o, --option <key>=<val> Set the value of option <key> to <val>. Overrides values in configuration file.\n" " -o, --option <key>=<val> Set the value of option <key> to <val>. Overrides values in configuration file.\n"
" <key> can be a two-part <key>.<subkey>\n" " <key> can be a two-part <key>.<subkey>\n"
" -p <output_format>, --print=<output_format>\n" " -p <output_format>, --print=<output_format>\n"
@ -106,6 +108,7 @@ static void usage()
" -t <tag> Only run those rules with a tag=<tag>. Can be specified multiple times.\n" " -t <tag> Only run those rules with a tag=<tag>. Can be specified multiple times.\n"
" Can not be specified with -T/-D.\n" " Can not be specified with -T/-D.\n"
" -v Verbose output.\n" " -v Verbose output.\n"
" --version Print version number.\n"
"\n" "\n"
); );
} }
@ -133,12 +136,14 @@ std::list<string> cmdline_options;
uint64_t do_inspect(falco_engine *engine, uint64_t do_inspect(falco_engine *engine,
falco_outputs *outputs, falco_outputs *outputs,
sinsp* inspector, sinsp* inspector,
uint64_t duration_to_tot_ns,
string &stats_filename) string &stats_filename)
{ {
uint64_t num_evts = 0; uint64_t num_evts = 0;
int32_t res; int32_t res;
sinsp_evt* ev; sinsp_evt* ev;
StatsFileWriter writer; StatsFileWriter writer;
uint64_t duration_start = 0;
if (stats_filename != "") if (stats_filename != "")
{ {
@ -182,6 +187,17 @@ uint64_t do_inspect(falco_engine *engine,
throw sinsp_exception(inspector->getlasterr().c_str()); throw sinsp_exception(inspector->getlasterr().c_str());
} }
if (duration_start == 0)
{
duration_start = ev->get_ts();
} else if(duration_to_tot_ns > 0)
{
if(ev->get_ts() - duration_start >= duration_to_tot_ns)
{
break;
}
}
if(!inspector->is_debug_enabled() && if(!inspector->is_debug_enabled() &&
ev->get_category() & EC_INTERNAL) ev->get_category() & EC_INTERNAL)
{ {
@ -232,6 +248,7 @@ int falco_init(int argc, char **argv)
string* mesos_api = 0; string* mesos_api = 0;
string output_format = ""; string output_format = "";
bool replace_container_info = false; bool replace_container_info = false;
int duration_to_tot = 0;
// Used for writing trace files // Used for writing trace files
int duration_seconds = 0; int duration_seconds = 0;
@ -255,6 +272,7 @@ int falco_init(int argc, char **argv)
{"option", required_argument, 0, 'o'}, {"option", required_argument, 0, 'o'},
{"print", required_argument, 0, 'p' }, {"print", required_argument, 0, 'p' },
{"pidfile", required_argument, 0, 'P' }, {"pidfile", required_argument, 0, 'P' },
{"version", no_argument, 0, 0 },
{"writefile", required_argument, 0, 'w' }, {"writefile", required_argument, 0, 'w' },
{0, 0, 0, 0} {0, 0, 0, 0}
@ -272,7 +290,7 @@ int falco_init(int argc, char **argv)
// Parse the args // Parse the args
// //
while((op = getopt_long(argc, argv, while((op = getopt_long(argc, argv,
"hc:AdD:e:k:K:Ll:m:o:P:p:r:s:T:t:vw:", "hc:AdD:e:k:K:Ll:m:M:o:P:p:r:s:T:t:vw:",
long_options, &long_index)) != -1) long_options, &long_index)) != -1)
{ {
switch(op) switch(op)
@ -313,6 +331,13 @@ int falco_init(int argc, char **argv)
case 'm': case 'm':
mesos_api = new string(optarg); mesos_api = new string(optarg);
break; break;
case 'M':
duration_to_tot = atoi(optarg);
if(duration_to_tot <= 0)
{
throw sinsp_exception(string("invalid duration") + optarg);
}
break;
case 'o': case 'o':
cmdline_options.push_back(optarg); cmdline_options.push_back(optarg);
break; break;
@ -368,6 +393,13 @@ int falco_init(int argc, char **argv)
} }
if(string(long_options[long_index].name) == "version")
{
printf("falco version %s\n", FALCO_VERSION);
return EXIT_SUCCESS;
}
inspector = new sinsp(); inspector = new sinsp();
engine = new falco_engine(); engine = new falco_engine();
engine->set_inspector(inspector); engine->set_inspector(inspector);
@ -652,6 +684,7 @@ int falco_init(int argc, char **argv)
num_evts = do_inspect(engine, num_evts = do_inspect(engine,
outputs, outputs,
inspector, inspector,
uint64_t(duration_to_tot*ONE_SECOND_IN_NS),
stats_filename); stats_filename);
duration = ((double)clock()) / CLOCKS_PER_SEC - duration; duration = ((double)clock()) / CLOCKS_PER_SEC - duration;