diff --git a/engine/cli/command_line_parser.cc b/engine/cli/command_line_parser.cc index a5f0363ab..99f51983e 100644 --- a/engine/cli/command_line_parser.cc +++ b/engine/cli/command_line_parser.cc @@ -86,7 +86,7 @@ bool CommandLineParser::SetupCommand(int argc, char** argv) { #else CLI_LOG("default"); #endif -(void) c; + (void)c; }; app_.add_flag_function("-v,--version", cb, "Get Cortex version"); @@ -436,7 +436,7 @@ void CommandLineParser::SetupConfigsCommands() { auto is_empty = true; for (const auto& [key, value] : config_update_opts_) { - if (!value.empty() || CONFIGURATIONS.at(key).allow_empty) { + if (!value.empty() || key == "api_keys") { is_empty = false; break; } diff --git a/engine/cli/commands/config_upd_cmd.cc b/engine/cli/commands/config_upd_cmd.cc index 37deb0571..39aff1811 100644 --- a/engine/cli/commands/config_upd_cmd.cc +++ b/engine/cli/commands/config_upd_cmd.cc @@ -2,6 +2,7 @@ #include "commands/server_start_cmd.h" #include "common/api_server_configuration.h" #include "utils/curl_utils.h" +#include "utils/file_manager_utils.h" #include "utils/logging_utils.h" #include "utils/string_utils.h" #include "utils/url_parser.h" @@ -46,22 +47,40 @@ inline Json::Value NormalizeJson( void commands::ConfigUpdCmd::Exec( const std::string& host, int port, const std::unordered_map& options) { - if (!commands::IsServerAlive(host, port)) { - CLI_LOG("Starting server ..."); - commands::ServerStartCmd ssc; - if (!ssc.Exec(host, port)) { - return; - } - } auto non_null_opts = std::unordered_map(); for (const auto& [key, value] : options) { - if (value.empty() && !CONFIGURATIONS.at(key).allow_empty) { + // In case of api_keys, we allow empty value + if (value.empty() && key != "api_keys") { continue; } non_null_opts[key] = value; } + if (non_null_opts.size() == 1) { + for (const auto& [key, value] : non_null_opts) { + if (key == "api_keys") { + auto config = file_manager_utils::GetCortexConfig(); + config.apiKeys = string_utils::SplitBy(value, ","); + auto result = file_manager_utils::UpdateCortexConfig(config); + if (result.has_error()) { + CLI_LOG_ERROR(result.error()); + } else { + CLI_LOG("Configuration updated successfully!"); + } + return; + } + } + } + + if (!commands::IsServerAlive(host, port)) { + CLI_LOG("Starting server ..."); + commands::ServerStartCmd ssc; + if (!ssc.Exec(host, port)) { + return; + } + } + auto url = url_parser::Url{ /* .protocol = */ "http", /* .host = */ host + ":" + std::to_string(port), diff --git a/engine/common/api_server_configuration.h b/engine/common/api_server_configuration.h index 9a444c34a..e0187170f 100644 --- a/engine/common/api_server_configuration.h +++ b/engine/common/api_server_configuration.h @@ -80,6 +80,15 @@ static const std::unordered_map /* .accept_value = */ "string", /* .default_value = */ "", /* .allow_empty = */ true}}, + {"api_keys", + ApiConfigurationMetadata{ + /* .name = */ "api_keys", + /* .desc = */ "API header key to get access to server APIs", + /* .group = */ "Token", + /* .accept_value = */ " comma separated", + /* .default_value = */ "", + /* .allow_empty = */ true}}, + }; class ApiServerConfiguration { @@ -316,4 +325,4 @@ class ApiServerConfiguration { } } }; -}; +}; \ No newline at end of file diff --git a/engine/main.cc b/engine/main.cc index 55bc7275a..a7b5bb81f 100644 --- a/engine/main.cc +++ b/engine/main.cc @@ -253,7 +253,13 @@ void RunServer(std::optional host, std::optional port, auto validate_api_key = [config_service](const drogon::HttpRequestPtr& req) { auto api_keys = config_service->GetApiServerConfiguration()->api_keys; static const std::unordered_set public_endpoints = { - "/openapi.json", "/healthz", "/processManager/destroy"}; + "/openapi.json", "/healthz", "/processManager/destroy", "/events"}; + + if (req->getHeader("Authorization").empty() && + req->path() == "/v1/configs") { + CTL_WRN("Require API key to access /v1/configs"); + return false; + } // If API key is not set, skip validation if (api_keys.empty()) { @@ -377,6 +383,7 @@ void print_help() { "~/cortexcpp)\n"; std::cout << " --host Host name (default: 127.0.0.1)\n"; std::cout << " --port Port number (default: 39281)\n"; + std::cout << " --api_configs Keys to acess API endpoints\n"; std::cout << " --ignore_cout Ignore cout output\n"; std::cout << " --loglevel Set log level\n"; @@ -405,6 +412,7 @@ int main(int argc, char* argv[]) { std::optional server_host; std::optional server_port; + std::optional api_keys; bool ignore_cout_log = false; #if defined(_WIN32) for (int i = 0; i < argc; i++) { @@ -421,6 +429,8 @@ int main(int argc, char* argv[]) { server_host = cortex::wc::WstringToUtf8(argv[i + 1]); } else if (command == L"--port") { server_port = std::stoi(argv[i + 1]); + } else if (command == L"--api_keys") { + api_keys = cortex::wc::WstringToUtf8(argv[i + 1]); } else if (command == L"--ignore_cout") { ignore_cout_log = true; } else if (command == L"--loglevel") { @@ -441,6 +451,8 @@ int main(int argc, char* argv[]) { server_host = argv[i + 1]; } else if (strcmp(argv[i], "--port") == 0) { server_port = std::stoi(argv[i + 1]); + } else if (strcmp(argv[i], "--api_keys") == 0) { + api_keys = argv[i + 1]; } else if (strcmp(argv[i], "--ignore_cout") == 0) { ignore_cout_log = true; } else if (strcmp(argv[i], "--loglevel") == 0) { @@ -476,6 +488,15 @@ int main(int argc, char* argv[]) { } } + if (api_keys) { + auto config = file_manager_utils::GetCortexConfig(); + config.apiKeys = string_utils::SplitBy(*api_keys, ","); + auto result = file_manager_utils::UpdateCortexConfig(config); + if (result.has_error()) { + CTL_ERR(result.error()); + } + } + // check if migration is needed if (auto res = cortex::migr::MigrationManager( cortex::db::Database::GetInstance().db())