diff --git a/falco.yaml b/falco.yaml index 61b4366d..a9e02737 100644 --- a/falco.yaml +++ b/falco.yaml @@ -963,6 +963,9 @@ webserver: prometheus_metrics_enabled: false ssl_enabled: false ssl_certificate: /etc/falco/falco.pem + # User and group id under which the server should run + uid: 1000 + gid: 1000 ############################################################################## # Falco logging / alerting / metrics related to software functioning (basic) # diff --git a/userspace/falco/config_json_schema.h b/userspace/falco/config_json_schema.h index 70a4c11b..5c491a80 100644 --- a/userspace/falco/config_json_schema.h +++ b/userspace/falco/config_json_schema.h @@ -796,6 +796,12 @@ const char config_schema_string[] = LONG_STRING_CONST( }, "ssl_certificate": { "type": "string" + }, + "uid": { + "type": "integer" + }, + "gid": { + "type": "integer" } }, "minProperties": 1, diff --git a/userspace/falco/configuration.cpp b/userspace/falco/configuration.cpp index bde20664..f2f6bc21 100644 --- a/userspace/falco/configuration.cpp +++ b/userspace/falco/configuration.cpp @@ -537,6 +537,8 @@ void falco_configuration::load_yaml(const std::string &config_name) { } m_webserver_config.m_prometheus_metrics_enabled = m_config.get_scalar("webserver.prometheus_metrics_enabled", false); + m_webserver_config.m_uid = m_config.get_scalar("webserver.uid", 1000); + m_webserver_config.m_gid = m_config.get_scalar("webserver.gid", 1000); std::list syscall_event_drop_acts; m_config.get_sequence(syscall_event_drop_acts, "syscall_event_drops.actions"); diff --git a/userspace/falco/configuration.h b/userspace/falco/configuration.h index f7a9c3a0..79e84564 100644 --- a/userspace/falco/configuration.h +++ b/userspace/falco/configuration.h @@ -95,6 +95,8 @@ public: bool m_ssl_enabled = false; std::string m_ssl_certificate; bool m_prometheus_metrics_enabled = false; + uint32_t m_uid = 1000; + uint32_t m_gid = 1000; }; enum class rule_selection_operation { enable, disable }; diff --git a/userspace/falco/webserver.cpp b/userspace/falco/webserver.cpp index 5b83162a..e071f4db 100644 --- a/userspace/falco/webserver.cpp +++ b/userspace/falco/webserver.cpp @@ -21,6 +21,7 @@ limitations under the License. #include "app/state.h" #include "versions_info.h" #include +#include falco_webserver::~falco_webserver() { stop(); @@ -58,47 +59,62 @@ void falco_webserver::start(const falco::app::state &state, res.set_content(versions_json_str, "application/json"); }); - // run server in a separate thread if(!m_server->is_valid()) { m_server = nullptr; throw falco_exception("invalid webserver configuration"); } m_failed.store(false, std::memory_order_release); - m_server_thread = std::thread([this, webserver_config] { + + // fork the server + m_pid = fork(); + + if(m_pid == 0) { + falco_logger::log(falco_logger::level::INFO, "Webserver: forked\n"); + int res = setgid(webserver_config.m_uid); + if(res != NOERROR) { + throw falco_exception("Webserver: an error occurred while setting group id: " + + std::to_string(errno)); + } + res = setuid(webserver_config.m_gid); + if(res != NOERROR) { + throw falco_exception("Webserver: an error occurred while setting user id: " + + std::to_string(errno)); + } + falco_logger::log(falco_logger::level::INFO, + "Webserver: fork running as " + std::to_string(webserver_config.m_uid) + + ":" + std::to_string(webserver_config.m_gid) + "\n"); try { this->m_server->listen(webserver_config.m_listen_address, webserver_config.m_listen_port); } catch(std::exception &e) { falco_logger::log(falco_logger::level::ERR, - "falco_webserver: " + std::string(e.what()) + "\n"); + "Webserver: " + std::string(e.what()) + "\n"); + m_failed.store(true, std::memory_order_release); } - this->m_failed.store(true, std::memory_order_release); - }); - - // wait for the server to actually start up - // note: is_running() is atomic - while(!m_server->is_running() && !m_failed.load(std::memory_order_acquire)) { - std::this_thread::yield(); - } - m_running = true; - if(m_failed.load(std::memory_order_acquire)) { - stop(); - throw falco_exception("an error occurred while starting webserver"); + } else if(m_pid < 0) { + throw falco_exception("Webserver: an error occurred while forking webserver"); } } void falco_webserver::stop() { - if(m_running) { + if(m_pid > 0) { + falco_logger::log(falco_logger::level::INFO, "Webserver: stopping server\n"); if(m_server != nullptr) { m_server->stop(); } - if(m_server_thread.joinable()) { - m_server_thread.join(); + falco_logger::log(falco_logger::level::INFO, "Webserver: killing fork\n"); + int res = kill(m_pid, SIGTERM); + if(res != 0) { + throw falco_exception("Webserver: an error occurred while killing fork: " + + std::to_string(errno)); } - m_server = nullptr; - m_running = false; + m_pid = 0; + falco_logger::log(falco_logger::level::INFO, "Webserver: stopping fork done\n"); } + + m_server = nullptr; + m_running = false; } void falco_webserver::enable_prometheus_metrics(const falco::app::state &state) { diff --git a/userspace/falco/webserver.h b/userspace/falco/webserver.h index e5d97e58..ac02dc78 100644 --- a/userspace/falco/webserver.h +++ b/userspace/falco/webserver.h @@ -47,4 +47,5 @@ private: std::unique_ptr m_server = nullptr; std::thread m_server_thread; std::atomic m_failed; + int m_pid = -1; };