diff --git a/userspace/falco/CMakeLists.txt b/userspace/falco/CMakeLists.txt index f88bb4fd379..02873edd2ff 100644 --- a/userspace/falco/CMakeLists.txt +++ b/userspace/falco/CMakeLists.txt @@ -41,6 +41,7 @@ set( app_actions/start_grpc_server.cpp app_actions/start_webserver.cpp app_actions/validate_rules_files.cpp + app_actions/create_requested_paths.cpp configuration.cpp logger.cpp falco_outputs.cpp diff --git a/userspace/falco/app_actions/create_requested_paths.cpp b/userspace/falco/app_actions/create_requested_paths.cpp new file mode 100644 index 00000000000..de4d61e6761 --- /dev/null +++ b/userspace/falco/app_actions/create_requested_paths.cpp @@ -0,0 +1,111 @@ +/* +Copyright (C) 2022 The Falco Authors. + +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. +*/ + +#include "application.h" +#include "falco_utils.h" +#include + +#ifndef CPPPATH_SEP +#ifdef _MSC_VER +#define CPPPATH_SEP "\\" +#else +#define CPPPATH_SEP "/" +#endif +#endif + +using namespace falco::app; + +application::run_result application::create_requested_paths() +{ + if(!m_options.gvisor_config.empty()) + { + // This is bad: parsing gvisor config to get endpoint + // to be able to auto-create the path to the file for the user. + std::ifstream reader(m_options.gvisor_config); + if (reader.fail()) + { + return run_result::fatal(m_options.gvisor_config + ": cannot open file."); + } + + nlohmann::json parsed_json; + std::string gvisor_socket; + try + { + parsed_json = nlohmann::json::parse(reader); + } + catch (const std::exception &e) + { + return run_result::fatal(m_options.gvisor_config + ": cannot parse JSON: " + e.what()); + } + + try + { + gvisor_socket = parsed_json["trace_session"]["sinks"][0]["config"]["endpoint"]; + } + catch (const std::exception &e) + { + return run_result::fatal(m_options.gvisor_config + ": failed to fetch config.endpoint: " + e.what()); + } + + int ret = create_dir(gvisor_socket); + if (ret != 0) + { + return run_result::fatal(gvisor_socket + ": " + strerror(errno)); + } + } + + if (!m_state->config->m_grpc_bind_address.empty()) + { + if(falco::utils::network::is_unix_scheme(m_state->config->m_grpc_bind_address)) + { + auto server_path = m_state->config->m_grpc_bind_address.substr( + falco::utils::network::UNIX_SCHEME.length() + ); + int ret = create_dir(server_path); + if(ret != 0) + { + return run_result::fatal(server_path + ": " + strerror(errno)); + } + } + } + + // TODO: eventually other files written by Falco whose destination is + // customizable by users, must be handled here. + return run_result::ok(); +} + +int application::create_dir(const std::string &path) +{ + // Properly reset errno + errno = 0; + + istringstream f(path); + string path_until_token; + string s; + // Create all the subfolder stopping at last token (f.eof()); + // Examples: + // "/tmp/foo/bar" -> "", "tmp", "foo" -> mkdir("/") + mkdir("/tmp/") + midir("/tmp/foo/") + // "tmp/foo/bar" -> "tmp", "foo" -> mkdir("tmp/") + midir("tmp/foo/") + while (getline(f, s, *CPPPATH_SEP) && !f.eof()) { + path_until_token += s + CPPPATH_SEP; + int ret = mkdir(path_until_token.c_str(), 0600); + if (ret != 0 && errno != EEXIST) + { + return ret; + } + } + return 0; +} \ No newline at end of file diff --git a/userspace/falco/application.cpp b/userspace/falco/application.cpp index 39ea3edfc1e..274ed75d643 100644 --- a/userspace/falco/application.cpp +++ b/userspace/falco/application.cpp @@ -132,6 +132,7 @@ bool application::run(std::string &errstr, bool &restart) std::bind(&application::print_syscall_events, this), std::bind(&application::create_signal_handlers, this), std::bind(&application::load_config, this), + std::bind(&application::create_requested_paths, this), std::bind(&application::print_plugin_info, this), std::bind(&application::list_plugins, this), std::bind(&application::init_inspector, this), diff --git a/userspace/falco/application.h b/userspace/falco/application.h index 22bd0fcf05a..ae6c9c2de00 100644 --- a/userspace/falco/application.h +++ b/userspace/falco/application.h @@ -193,6 +193,7 @@ class application { run_result load_config(); run_result load_plugins(); run_result load_rules_files(); + run_result create_requested_paths(); run_result open_inspector(); run_result print_generated_gvisor_config(); run_result print_help(); @@ -219,6 +220,7 @@ class application { #endif // Methods called by the above methods + int create_dir(const std::string &path); bool create_handler(int sig, void (*func)(int), run_result &ret); void configure_output_format(); void check_for_ignored_events();