Rules versioning (#492)

* Add ability to print field names only

Add ability to print field names only instead of all information about
fields (description, etc) using -N cmdline option.

This will be used to add some versioning support steps that check for a
changed set of fields.

* Add an engine version that changes w/ filter flds

Add a method falco_engine::engine_version() that returns the current
engine version (e.g. set of supported fields, rules objects, operators,
etc.). It's defined in falco_engine_version.h, starts at 2 and should be
updated whenever a breaking change is made.

The most common reason for an engine change will be an update to the set
of filter fields. To make this easy to diagnose, add a build time check
that compares the sha256 output of "falco --list -N" against a value
that's embedded in falco_engine_version.h. A mismatch fails the build.

* Check engine version when loading rules

A rules file can now have a field "required_engine_version N". If
present, the number is compared to the falco engine version. If the
falco engine version is less, an error is thrown.

* Unit tests for engine versioning

Add a required version: 2 to one trace file to check the positive case
and add a new test that verifies that a too-new rules file won't be loaded.

* Rename falco test docker image

Rename sysdig/falco to falcosecurity/falco in unit tests.

* Don't pin falco_rules.yaml to an engine version

Currently, falco_rules.yaml is compatible with versions <= 0.13.1 other
than the required_engine_version object itself, so keep that line
commented out so users can use this rules file with older falco
versions.

We'll uncomment it with the first incompatible falco engine change.
This commit is contained in:
Mark Stemm
2019-01-29 12:43:15 -08:00
committed by GitHub
parent a78212cc62
commit 513cf2ed8b
16 changed files with 247 additions and 61 deletions

View File

@@ -23,6 +23,7 @@ limitations under the License.
#include <fstream>
#include "falco_engine.h"
#include "falco_engine_version.h"
#include "config_falco_engine.h"
#include "formats.h"
@@ -76,6 +77,71 @@ falco_engine::~falco_engine()
}
}
uint32_t falco_engine::engine_version()
{
return (uint32_t) FALCO_ENGINE_VERSION;
}
#define DESCRIPTION_TEXT_START 16
#define CONSOLE_LINE_LEN 79
void falco_engine::list_fields(bool names_only)
{
for(auto &chk_field : json_factory().get_fields())
{
if(!names_only)
{
printf("\n----------------------\n");
printf("Field Class: %s (%s)\n\n", chk_field.name.c_str(), chk_field.desc.c_str());
}
for(auto &field : chk_field.fields)
{
uint32_t l, m;
printf("%s", field.name.c_str());
if(names_only)
{
printf("\n");
continue;
}
uint32_t namelen = field.name.size();
if(namelen >= DESCRIPTION_TEXT_START)
{
printf("\n");
namelen = 0;
}
for(l = 0; l < DESCRIPTION_TEXT_START - namelen; l++)
{
printf(" ");
}
size_t desclen = field.desc.size();
for(l = 0; l < desclen; l++)
{
if(l % (CONSOLE_LINE_LEN - DESCRIPTION_TEXT_START) == 0 && l != 0)
{
printf("\n");
for(m = 0; m < DESCRIPTION_TEXT_START; m++)
{
printf(" ");
}
}
printf("%c", field.desc.at(l));
}
printf("\n");
}
}
}
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
{
// The engine must have been given an inspector by now.

View File

@@ -53,6 +53,15 @@ public:
falco_engine(bool seed_rng=true, const std::string& alternate_lua_dir=FALCO_ENGINE_SOURCE_LUA_DIR);
virtual ~falco_engine();
// A given engine has a version which identifies the fields
// and rules file format it supports. This version will change
// any time the code that handles rules files, expression
// fields, etc, changes.
static uint32_t engine_version();
// Print to stdout (using printf) a description of each field supported by this engine.
void list_fields(bool names_only=false);
//
// Load rules either directly or from a filename.
//

View File

@@ -0,0 +1,27 @@
/*
Copyright (C) 2016-2018 Draios Inc dba Sysdig.
This file is part of falco.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// The version of rules/filter fields/etc supported by this falco
// engine.
#define FALCO_ENGINE_VERSION (2)
// This is the result of running "falco --list -N | sha256sum" and
// represents the fields supported by this version of falco. It's used
// at build time to detect a changed set of fields.
#define FALCO_FIELDS_CHECKSUM "32a91c003ab34f198dcb4c3100fbfb22bf402ad36549f193afa43d73f1f2eba3"

View File

@@ -215,7 +215,12 @@ function load_rules(sinsp_lua_parser,
error ("Unexpected element of type " ..type(v)..". Each element should be a yaml associative array.")
end
if (v['macro']) then
if (v['required_engine_version']) then
if falco_rules.engine_version(rules_mgr) < v['required_engine_version'] then
error("Rules require engine version "..v['required_engine_version']..", but engine version is "..falco_rules.engine_version(rules_mgr))
end
elseif (v['macro']) then
if v['source'] == nil then
v['source'] = "syscall"

View File

@@ -33,6 +33,7 @@ const static struct luaL_reg ll_falco_rules [] =
{"add_filter", &falco_rules::add_filter},
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
{"enable_rule", &falco_rules::enable_rule},
{"engine_version", &falco_rules::engine_version},
{NULL,NULL}
};
@@ -204,6 +205,21 @@ void falco_rules::enable_rule(string &rule, bool enabled)
m_engine->enable_rule(rule, enabled);
}
int falco_rules::engine_version(lua_State *ls)
{
if (! lua_islightuserdata(ls, -1))
{
lua_pushstring(ls, "Invalid arguments passed to engine_version()");
lua_error(ls);
}
falco_rules *rules = (falco_rules *) lua_topointer(ls, -1);
lua_pushnumber(ls, rules->m_engine->engine_version());
return 1;
}
void falco_rules::load_rules(const string &rules_content,
bool verbose, bool all_events,
string &extra, bool replace_container_info,

View File

@@ -49,6 +49,7 @@ class falco_rules
static int add_filter(lua_State *ls);
static int add_k8s_audit_filter(lua_State *ls);
static int enable_rule(lua_State *ls);
static int engine_version(lua_State *ls);
private:
void clear_filters();