mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-21 23:32:15 +00:00
test: audit: cover audit_rules configuration
Audit rules enter through three paths (YAML, CQL, CLI), each with its own parsing and tracking -- cover all entry points before routing can depend on them. Test loading from YAML, live update via CQL and server API, CLI parsing, invalid value rejection at each path, and observer notification on live update. Refs SCYLLADB-1430
This commit is contained in:
@@ -8,13 +8,19 @@
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <seastar/core/sstring.hh>
|
||||
#include <seastar/json/json_elements.hh>
|
||||
|
||||
#include "audit/audit.hh"
|
||||
#include "audit/audit_rule.hh"
|
||||
#include "db/config.hh"
|
||||
|
||||
using namespace seastar;
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
namespace {
|
||||
|
||||
audit::audit_rule make_rule(std::vector<sstring> sinks,
|
||||
@@ -97,3 +103,114 @@ BOOST_AUTO_TEST_CASE(test_json_round_trip) {
|
||||
|
||||
BOOST_CHECK_EQUAL(audit::audit_rules_to_json_string({}), "[]");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_config_audit_rules_yaml) {
|
||||
db::config cfg;
|
||||
BOOST_CHECK(cfg.audit_rules().empty());
|
||||
|
||||
cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [table]\n"
|
||||
" categories: [DML, DDL]\n"
|
||||
" qualified_table_names: [ks.t1]\n"
|
||||
" roles: ['admin\\*', 'domain\\\\user', 'user[0-9]', '!(guest)']\n");
|
||||
|
||||
BOOST_CHECK(cfg.audit_rules.source() == utils::config_file::config_source::SettingsFile);
|
||||
BOOST_REQUIRE_EQUAL(cfg.audit_rules().size(), 1u);
|
||||
BOOST_CHECK(cfg.audit_rules()[0].categories.contains(audit::statement_category::DML));
|
||||
BOOST_CHECK(cfg.audit_rules()[0].categories.contains(audit::statement_category::DDL));
|
||||
BOOST_CHECK_EQUAL(cfg.audit_rules()[0].roles[0], "admin\\*");
|
||||
|
||||
auto parsed = audit::parse_audit_rules_from_json(cfg.audit_rules.value_as_json()._res);
|
||||
BOOST_REQUIRE_EQUAL(parsed.size(), 1u);
|
||||
BOOST_CHECK(parsed[0] == cfg.audit_rules()[0]);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_config_audit_rules_cql) {
|
||||
db::config cfg;
|
||||
|
||||
std::vector<audit::audit_rule> observed;
|
||||
auto observer = cfg.audit_rules.observe([&observed] (const std::vector<audit::audit_rule>& rules) {
|
||||
observed = rules;
|
||||
});
|
||||
BOOST_CHECK(cfg.audit_rules.set_value(
|
||||
R"([{"sinks":["syslog"],"categories":["AUTH"],"qualified_table_names":[],"roles":["*"]}])",
|
||||
utils::config_file::config_source::CQL));
|
||||
BOOST_CHECK(cfg.audit_rules.source() == utils::config_file::config_source::CQL);
|
||||
BOOST_REQUIRE_EQUAL(observed.size(), 1u);
|
||||
BOOST_CHECK_EQUAL(observed[0].sinks[0], "syslog");
|
||||
BOOST_CHECK(observed[0].categories.contains(audit::statement_category::AUTH));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_config_audit_rules_cli) {
|
||||
db::config cfg;
|
||||
|
||||
auto desc = cfg.get_options_description();
|
||||
bpo::variables_map vm;
|
||||
const char* argv[] = {"test", "--audit-rules", R"([{"sinks":["table"],"categories":["DML"],"qualified_table_names":["ks.t1"],"roles":["*"]}])"};
|
||||
bpo::store(bpo::parse_command_line(3, argv, desc), vm);
|
||||
bpo::notify(vm);
|
||||
BOOST_REQUIRE_EQUAL(cfg.audit_rules().size(), 1u);
|
||||
BOOST_CHECK_EQUAL(cfg.audit_rules()[0].qualified_table_names[0], "ks.t1");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_config_audit_rules_rejects_invalid_values) {
|
||||
db::config cfg;
|
||||
BOOST_CHECK_THROW(
|
||||
cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [kafka]\n"
|
||||
" categories: [DML]\n"
|
||||
" qualified_table_names: []\n"
|
||||
" roles: []\n"),
|
||||
std::exception);
|
||||
|
||||
// Each required field missing in turn.
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - categories: [DML]\n"
|
||||
" qualified_table_names: []\n"
|
||||
" roles: []\n"), std::exception);
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [table]\n"
|
||||
" qualified_table_names: []\n"
|
||||
" roles: []\n"), std::exception);
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [table]\n"
|
||||
" categories: [DML]\n"
|
||||
" roles: []\n"), std::exception);
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [table]\n"
|
||||
" categories: [DML]\n"
|
||||
" qualified_table_names: []\n"), std::exception);
|
||||
// Scalar value where array is expected.
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: table\n"
|
||||
" categories: [DML]\n"
|
||||
" qualified_table_names: []\n"
|
||||
" roles: []\n"), std::exception);
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [table]\n"
|
||||
" categories: DML\n"
|
||||
" qualified_table_names: []\n"
|
||||
" roles: []\n"), std::exception);
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [table]\n"
|
||||
" categories: [DML]\n"
|
||||
" qualified_table_names: ks.t1\n"
|
||||
" roles: []\n"), std::exception);
|
||||
BOOST_CHECK_THROW(cfg.read_from_yaml(
|
||||
"audit_rules:\n"
|
||||
" - sinks: [table]\n"
|
||||
" categories: [DML]\n"
|
||||
" qualified_table_names: []\n"
|
||||
" roles: '*'\n"), std::exception);
|
||||
|
||||
BOOST_CHECK_THROW(cfg.audit_rules.set_value(sstring("{not json}"), utils::config_file::config_source::CQL), std::exception);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user