Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move options from format to the import subcommand #1354

Merged
merged 9 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ This changelog documents all notable user-facing changes of VAST.

## Unreleased

### 鈿★笍 Breaking Changes

- 鈿狅笍 The `infer` command has an improved heuristic for the number types `int`,
`count`, and `real`. [#1343](https://github.com/tenzir/vast/pull/1343)
[#1356](https://github.com/tenzir/vast/pull/1356)
Expand All @@ -27,6 +25,12 @@ This changelog documents all notable user-facing changes of VAST.
[#1356](https://github.com/tenzir/vast/pull/1356)
[@ngrodzitski](https://github.com/ngrodzitski)

- 鈿狅笍 The options `listen`, `read`, `schema`, `schema-file`, `type`, and `uds` can
from now on be supplied to the `import` command directly. Similarly, the
options `write` and `uds` can be supplied to the `export` command. All options
can still be used after the format subcommand, but that usage is deprecated.
[#1354](https://github.com/tenzir/vast/pull/1354)

- 鈿★笍 VAST now requires [{fmt} >= 5.2.1](https://fmt.dev) to be installed.
[#1330](https://github.com/tenzir/vast/pull/1330)

Expand Down
2 changes: 1 addition & 1 deletion doc/cli/vast-import-csv.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ E.g., to import Threat Intelligence data into VAST, the known type
`intel.indicator` can be used:

```bash
vast import csv --type=intel.indicator --read=path/to/indicators.csv
vast import --type=intel.indicator --read=path/to/indicators.csv csv
```
29 changes: 29 additions & 0 deletions libvast/src/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,34 @@ caf::error parse_impl(invocation& result, const command& cmd,
return parse_impl(result, **i, position + 1, last, target);
}

void fixup_options(invocation& inv) {
using namespace std::string_literals;
auto move_option_arg = [&](auto cmd, auto format, auto opt) {
tobim marked this conversation as resolved.
Show resolved Hide resolved
auto path = "vast."s + cmd + '.' + format + '.' + opt;
if (auto x = caf::get_if<std::string>(&inv.options, path)) {
// The logger isn't initialized yet.
#if VAST_LOG_LEVEL >= VAST_LOG_LEVEL_WARNING
fmt::print(stderr,
"The option '{}' is deprected for the '{}' subcommand and "
tobim marked this conversation as resolved.
Show resolved Hide resolved
"should be specified at the {} subcommand instead\n",
opt, format, cmd);
#endif
put(inv.options, "vast."s + cmd + '.' + opt, *x);
}
};
for (const auto& cmd : {"import", "spawn.source"})
for (const auto& format :
{"csv", "json", "suricata", "syslog", "zeek", "zeek-json"})
for (const auto& opt :
{"listen", "read", "schema", "schema-file", "type", "uds"})
move_option_arg(cmd, format, opt);
for (const auto& cmd : {"export", "spawn.sink"})
for (const auto& format :
{"arrow", "ascii", "csv", "json", "null", "pcap", "zeek"})
tobim marked this conversation as resolved.
Show resolved Hide resolved
for (const auto& opt : {"write", "uds"})
move_option_arg(cmd, format, opt);
}

caf::expected<invocation>
parse(const command& root, command::argument_iterator first,
command::argument_iterator last) {
Expand All @@ -380,6 +408,7 @@ parse(const command& root, command::argument_iterator first,
manfooter(std::cout);
return caf::no_error;
}
fixup_options(result);
return result;
}

Expand Down
3 changes: 1 addition & 2 deletions libvast/src/defaults.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
namespace vast::defaults::import {

size_t test::seed(const caf::settings& options) {
std::string cat = category;
if (auto val = caf::get_if<size_t>(&options, cat + ".seed"))
if (auto val = caf::get_if<size_t>(&options, "vast.import.test.seed"))
return *val;
std::random_device rd;
return rd();
Expand Down
6 changes: 3 additions & 3 deletions libvast/src/format/pcap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ reader::reader(const caf::settings& options, std::unique_ptr<std::istream>)
: super(options) {
using defaults_t = vast::defaults::import::pcap;
using caf::get_if;
std::string category = defaults_t::category;
std::string category = "vast.import.pcap";
if (auto interface = get_if<std::string>(&options, category + ".interface"))
interface_ = *interface;
input_ = get_or(options, category + ".read", defaults_t::read);
input_ = get_or(options, "vast.import.read", vast::defaults::import::read);
cutoff_ = get_or(options, category + ".cutoff", defaults_t::cutoff);
max_flows_ = get_or(options, category + ".max-flows", defaults_t::max_flows);
max_age_
Expand Down Expand Up @@ -482,7 +482,7 @@ void reader::shrink_to_max_size() {
writer::writer(const caf::settings& options) {
flush_interval_ = get_or(options, "vast.export.pcap.flush-interval",
defaults::flush_interval);
trace_ = get_or(options, "vast.export.pcap.write", defaults::write);
trace_ = get_or(options, "vast.export.write", vast::defaults::export_::write);
}

writer::~writer() {
Expand Down
3 changes: 1 addition & 2 deletions libvast/src/format/writer_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ template <class Writer>
caf::expected<std::unique_ptr<format::writer>>
make_writer(const caf::settings& options) {
using namespace std::string_literals;
using defaults = typename Writer::defaults;
using ostream_ptr = std::unique_ptr<std::ostream>;
if constexpr (std::is_constructible_v<Writer, ostream_ptr, caf::settings>) {
auto out = detail::make_output_stream<defaults>(options);
auto out = detail::make_output_stream(options);
if (!out)
return out.error();
return std::make_unique<Writer>(std::move(*out), options);
Expand Down
3 changes: 2 additions & 1 deletion libvast/src/format/zeek.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,8 @@ caf::error reader::parse_header() {
}

writer::writer(const caf::settings& options) {
auto output = get_or(options, "vast.export.zeek.write", defaults::write);
auto output
= get_or(options, "vast.export.write", vast::defaults::export_::write);
if (output != "-")
dir_ = std::move(output);
show_timestamp_tags_
Expand Down
7 changes: 3 additions & 4 deletions libvast/src/schema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,13 @@ bool convert(const schema& s, data& d) {
return true;
}

caf::expected<schema>
get_schema(const caf::settings& options, const std::string& category) {
caf::expected<schema> get_schema(const caf::settings& options) {
// Get the default schema from the registry.
auto schema_reg_ptr = event_types::get();
auto schema = schema_reg_ptr ? *schema_reg_ptr : vast::schema{};
// Update with an alternate schema, if requested.
auto sc = caf::get_if<std::string>(&options, category + ".schema");
auto sf = caf::get_if<std::string>(&options, category + ".schema-file");
auto sc = caf::get_if<std::string>(&options, "vast.import.schema");
auto sf = caf::get_if<std::string>(&options, "vast.import.schema-file");
if (sc && sf)
caf::make_error(ec::invalid_configuration,
"had both schema and schema-file "
Expand Down
68 changes: 41 additions & 27 deletions libvast/src/system/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ auto make_export_command() {
.add<bool>("unified,u", "marks a query as unified")
.add<bool>("disable-taxonomies", "don't substitute taxonomy identifiers")
.add<size_t>("max-events,n", "maximum number of results")
.add<std::string>("read,r", "path for reading the query"));
.add<std::string>("read,r", "path for reading the query")
.add<std::string>("write,w", "path to write events to")
.add<bool>("uds,d", "treat -w as UNIX domain socket to connect to"));
export_->add_subcommand("zeek", "exports query results in Zeek format",
documentation::vast_export_zeek,
sink_opts("?vast.export.zeek"));
Expand Down Expand Up @@ -184,9 +186,16 @@ auto make_import_command() {
.add<size_t>("batch-size", "upper bound for the size of a table slice")
.add<std::string>("batch-timeout", "timeout after which batched "
"table slices are forwarded")
.add<std::string>("read-timeout", "timeout for waiting for incoming data")
.add<bool>("blocking,b", "block until the IMPORTER forwarded all data")
.add<size_t>("max-events,n", "the maximum number of events to import"));
.add<std::string>("listen,l", "the endpoint to listen on "
"([host]:port/type)")
.add<size_t>("max-events,n", "the maximum number of events to import")
.add<std::string>("read,r", "path to input where to read events from")
.add<std::string>("read-timeout", "timeout for waiting for incoming data")
.add<std::string>("schema,S", "alternate schema as string")
.add<std::string>("schema-file,s", "path to alternate schema")
.add<std::string>("type,t", "filter event type based on prefix matching")
.add<bool>("uds,d", "treat -r as listening UNIX domain socket"));
import_->add_subcommand("zeek", "imports Zeek TSV logs from STDIN or file",
documentation::vast_import_zeek,
source_opts("?vast.import.zeek"));
Expand Down Expand Up @@ -268,8 +277,15 @@ auto make_spawn_source_command() {
.add<size_t>("batch-size", "upper bound for the size of a table slice")
.add<std::string>("batch-timeout", "timeout after which batched "
"table slices are forwarded")
.add<std::string>("listen,l", "the endpoint to listen on "
"([host]:port/type)")
.add<size_t>("max-events,n", "the maximum number of events to import")
.add<std::string>("read,r", "path to input where to read events from")
.add<std::string>("read-timeout", "timeout for waiting for incoming data")
.add<size_t>("max-events,n", "the maximum number of events to import"));
.add<std::string>("schema,S", "alternate schema as string")
.add<std::string>("schema-file,s", "path to alternate schema")
.add<std::string>("type,t", "filter event type based on prefix matching")
.add<bool>("uds,d", "treat -r as listening UNIX domain socket"));
spawn_source->add_subcommand("csv",
"creates a new CSV source inside the node",
documentation::vast_spawn_source_csv,
Expand Down Expand Up @@ -424,26 +440,19 @@ auto make_command_factory() {
{"export zeek", make_writer_command("zeek")},
{"get", get_command},
{"infer", infer_command},
{"import csv", import_command<format::csv::reader, defaults::import::csv>},
{"import csv", import_command<format::csv::reader>},
{"import json", import_command<
format::json::reader<format::json::default_selector>,
defaults::import::json>},
format::json::reader<format::json::default_selector>>},
#if VAST_ENABLE_PCAP
{"import pcap", import_command<format::pcap::reader,
defaults::import::pcap>},
{"import pcap", import_command<format::pcap::reader>},
#endif
{"import suricata", import_command<
format::json::reader<format::json::suricata_selector>,
defaults::import::suricata>},
{"import syslog", import_command<format::syslog::reader,
defaults::import::syslog>},
{"import test", import_command<format::test::reader,
defaults::import::test>},
{"import zeek", import_command<format::zeek::reader,
defaults::import::zeek>},
format::json::reader<format::json::suricata_selector>>},
{"import syslog", import_command<format::syslog::reader>},
{"import test", import_command<format::test::reader>},
{"import zeek", import_command<format::zeek::reader>},
{"import zeek-json", import_command<
format::json::reader<format::json::zeek_selector>,
defaults::import::zeek_json>},
format::json::reader<format::json::zeek_selector>>},
{"kill", remote_command},
{"peer", remote_command},
{"pivot", pivot_command},
Expand Down Expand Up @@ -475,7 +484,7 @@ auto make_command_factory() {
{"version", version_command},
};
// clang-format on
}
} // namespace

auto make_root_command(std::string_view path) {
// We're only interested in the application name, not in its path. For
Expand Down Expand Up @@ -590,13 +599,18 @@ void render_error(const command& root, const caf::error& err,

command::opts_builder source_opts(std::string_view category) {
return command::opts(category)
.add<std::string>("listen,l", "the endpoint to listen on "
"([host]:port/type)")
.add<std::string>("read,r", "path to input where to read events from")
.add<std::string>("schema-file,s", "path to alternate schema")
.add<std::string>("schema,S", "alternate schema as string")
.add<std::string>("type,t", "filter event type based on prefix matching")
.add<bool>("uds,d", "treat -r as listening UNIX domain socket");
.add<std::string>("listen,l", "deprecated - this option now applies to the "
"import command")
.add<std::string>("read,r", "deprecated - this option now applies to the "
"import command")
.add<std::string>("schema-file,s", "deprecated - this option now applies "
"to the import command")
.add<std::string>("schema,S", "deprecated - this option now applies to the "
"import command")
.add<std::string>("type,t", "deprecated - this option now applies to the "
"import command")
.add<bool>("uds,d", "deprecated - this option now applies to the import "
"command");
}

command::opts_builder sink_opts(std::string_view category) {
Expand Down
2 changes: 1 addition & 1 deletion libvast/src/system/infer_command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ caf::message
infer_command(const invocation& inv, [[maybe_unused]] caf::actor_system& sys) {
VAST_TRACE_SCOPE("{}", inv);
const auto& options = inv.options;
auto input = detail::make_input_stream<defaults::infer>(options);
auto input = detail::make_input_stream(options);
if (!input)
return make_message(input.error());
// Setup buffer for input data.
Expand Down
24 changes: 8 additions & 16 deletions libvast/src/system/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,34 +358,26 @@ auto make_component_factory() {
{"spawn index", lift_component_factory<spawn_index>()},
{"spawn pivoter", lift_component_factory<spawn_pivoter>()},
{"spawn source csv",
lift_component_factory<
spawn_source<format::csv::reader, defaults::import::csv>>()},
lift_component_factory<spawn_source<format::csv::reader>>()},
{"spawn source json",
lift_component_factory<
spawn_source<format::json::reader<format::json::default_selector>,
defaults::import::json>>()},
spawn_source<format::json::reader<format::json::default_selector>>>()},
#if VAST_ENABLE_PCAP
{"spawn source pcap",
lift_component_factory<
spawn_source<format::pcap::reader, defaults::import::pcap>>()},
lift_component_factory<spawn_source<format::pcap::reader>>()},
#endif
{"spawn source suricata",
lift_component_factory<
spawn_source<format::json::reader<format::json::suricata_selector>,
defaults::import::suricata>>()},
spawn_source<format::json::reader<format::json::suricata_selector>>>()},
{"spawn source syslog",
lift_component_factory<
spawn_source<format::syslog::reader, defaults::import::syslog>>()},
lift_component_factory<spawn_source<format::syslog::reader>>()},
{"spawn source test",
lift_component_factory<
spawn_source<format::test::reader, defaults::import::test>>()},
lift_component_factory<spawn_source<format::test::reader>>()},
{"spawn source zeek",
lift_component_factory<
spawn_source<format::zeek::reader, defaults::import::zeek>>()},
lift_component_factory<spawn_source<format::zeek::reader>>()},
{"spawn source zeek-json",
lift_component_factory<
spawn_source<format::json::reader<format::json::zeek_selector>,
defaults::import::zeek>>()},
spawn_source<format::json::reader<format::json::zeek_selector>>>()},
{"spawn sink pcap", lift_component_factory<spawn_pcap_sink>()},
{"spawn sink zeek", lift_component_factory<spawn_zeek_sink>()},
{"spawn sink csv", lift_component_factory<spawn_csv_sink>()},
Expand Down
5 changes: 1 addition & 4 deletions libvast/src/system/spawn_sink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
#include "vast/system/spawn_sink.hpp"

#include "vast/config.hpp"
#include "vast/defaults.hpp"
#include "vast/error.hpp"
#include "vast/format/writer.hpp"
#include "vast/format/zeek.hpp"
#include "vast/system/sink.hpp"
#include "vast/system/spawn_arguments.hpp"

Expand Down Expand Up @@ -57,8 +56,6 @@ spawn_generic_sink(caf::local_actor* self, spawn_arguments& args,
caf::expected<caf::actor>
spawn_pcap_sink([[maybe_unused]] caf::local_actor* self,
[[maybe_unused]] spawn_arguments& args) {
using defaults_t = defaults::export_::pcap;
std::string category = defaults_t::category;
#if !VAST_ENABLE_PCAP
return caf::make_error(ec::unspecified, "not compiled with pcap support");
#else // VAST_ENABLE_PCAP
Expand Down
8 changes: 4 additions & 4 deletions libvast/test/format/pcap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ TEST(PCAP read/write 1) {
// Initialize a PCAP source with no cutoff (-1), and at most 5 flow table
// entries.
caf::settings settings;
caf::put(settings, "vast.import.pcap.read", artifacts::traces::nmap_vsn);
caf::put(settings, "vast.import.read", artifacts::traces::nmap_vsn);
caf::put(settings, "vast.import.pcap.cutoff", static_cast<uint64_t>(-1));
caf::put(settings, "vast.import.pcap.max-flows", static_cast<size_t>(5));
// A non-positive value disables the timeout. We need to do this because the
Expand Down Expand Up @@ -104,7 +104,7 @@ TEST(PCAP read/write 1) {
CHECK_VARIANT_EQUAL((*community_id_column)[row], community_ids[row]);
MESSAGE("write out read packets");
auto file = "vast-unit-test-nmap-vsn.pcap";
caf::put(settings, "vast.export.pcap.write", file);
caf::put(settings, "vast.export.write", file);
format::pcap::writer writer{settings};
auto deleter = caf::detail::make_scope_guard([&] { rm(file); });
REQUIRE_EQUAL(writer.write(slice), caf::none);
Expand All @@ -114,7 +114,7 @@ TEST(PCAP read/write 2) {
// Spawn a PCAP source with a 64-byte cutoff, at most 100 flow table entries,
// with flows inactive for more than 5 seconds to be evicted every 2 seconds.
caf::settings settings;
caf::put(settings, "vast.import.pcap.read", artifacts::traces::nmap_vsn);
caf::put(settings, "vast.import.read", artifacts::traces::nmap_vsn);
caf::put(settings, "vast.import.pcap.cutoff", static_cast<uint64_t>(64));
caf::put(settings, "vast.import.pcap.max-flows", static_cast<size_t>(100));
caf::put(settings, "vast.import.pcap.max-flow-age", static_cast<size_t>(5));
Expand All @@ -139,7 +139,7 @@ TEST(PCAP read/write 2) {
CHECK_EQUAL(layout.name(), "pcap.packet");
MESSAGE("write out read packets");
auto file = "vast-unit-test-workshop-2011-browse.pcap";
caf::put(settings, "vast.export.pcap.write", file);
caf::put(settings, "vast.export.write", file);
format::pcap::writer writer{settings};
auto deleter = caf::detail::make_scope_guard([&] { rm(file); });
REQUIRE_EQUAL(writer.write(slice), caf::none);
Expand Down
2 changes: 1 addition & 1 deletion libvast/test/format/zeek.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ FIXTURE_SCOPE(zeek_writer_tests, writer_fixture)
TEST(zeek writer) {
// Perform the writing.
caf::settings options;
caf::put(options, "vast.export.zeek.write", directory.str());
caf::put(options, "vast.export.write", directory.str());
format::zeek::writer writer{options};
for (auto& slice : zeek_conn_log)
if (auto err = writer.write(slice))
Expand Down
2 changes: 1 addition & 1 deletion libvast/test/system/sink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ FIXTURE_SCOPE(sink_tests, fixtures::actor_system_and_events)
TEST(zeek sink) {
MESSAGE("constructing a sink");
caf::settings options;
caf::put(options, "vast.export.zeek.write", directory.str());
caf::put(options, "vast.export.write", directory.str());
auto writer = std::make_unique<format::zeek::writer>(options);
auto snk = self->spawn(sink, std::move(writer), 20u);
MESSAGE("sending table slices");
Expand Down