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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ROX-26516: Collector reads runtime config from configmap #1878

Merged
merged 16 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@
[submodule "third_party/uthash"]
path = builder/third_party/uthash
url = https://github.com/troydhanson/uthash.git
[submodule "builder/third_party/yaml-cpp"]
path = builder/third_party/yaml-cpp
url = https://github.com/jbeder/yaml-cpp.git
branch = master
13 changes: 13 additions & 0 deletions builder/install/10-yaml-cpp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

set -e

cd third_party/yaml-cpp
cp LICENSE "${LICENSE_DIR}/yaml-cpp-${YAMLCPP_VERSION}"

cmake -B build/ \
-DYAML_CPP_BUILD_CONTRIB=OFF \
-DYAML_CPP_BUILD_TOOLS=OFF \
-DYAML_BUILD_SHARED_LIBS=OFF \
-DYAML_CPP_INSTALL=ON
cmake --build build --target install ${NPROCS:+-j ${NPROCS}}
1 change: 1 addition & 0 deletions builder/install/versions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export VALIJSON_VERSION=0.6
export RE2_VERSION=2022-06-01
export GPERFTOOLS_VERSION=2.13
export UTHASH_VERSION=v1.9.8
export YAMLCPP_VERSION=0.8.0
1 change: 1 addition & 0 deletions builder/third_party/yaml-cpp
Submodule yaml-cpp added at f73201
2 changes: 2 additions & 0 deletions collector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ project(collector-bin)

find_package(Threads)
find_package(CURL REQUIRED)
find_package(yaml-cpp REQUIRED)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall --std=c++17 -pthread -Wno-deprecated-declarations -fno-omit-frame-pointer -rdynamic")
Expand Down Expand Up @@ -72,6 +73,7 @@ add_definitions(-DASSERT_TO_LOG)
add_subdirectory(lib)

add_executable(collector collector.cpp)
target_link_libraries(collector_lib yaml-cpp)
target_link_libraries(collector collector_lib)

target_link_libraries(collector libprometheus-cpp-pull.a)
Expand Down
53 changes: 53 additions & 0 deletions collector/lib/CollectorConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ PathEnvVar tls_ca_path("ROX_COLLECTOR_TLS_CA");
PathEnvVar tls_client_cert_path("ROX_COLLECTOR_TLS_CLIENT_CERT");
PathEnvVar tls_client_key_path("ROX_COLLECTOR_TLS_CLIENT_KEY");

PathEnvVar config_file("ROX_COLLECTOR_CONFIG_PATH", "/etc/stackrox/runtime_config.yaml");

} // namespace

constexpr bool CollectorConfig::kTurnOffScrape;
Expand Down Expand Up @@ -283,6 +285,7 @@ void CollectorConfig::InitCollectorConfig(CollectorArgs* args) {
HandleAfterglowEnvVars();
HandleConnectionStatsEnvVars();
HandleSinspEnvVars();
HandleConfig(config_file.value());

host_config_ = ProcessHostHeuristics(*this);
}
Expand Down Expand Up @@ -400,6 +403,56 @@ void CollectorConfig::HandleSinspEnvVars() {
}
}

bool CollectorConfig::YamlConfigToConfig(YAML::Node& yamlConfig) {
if (yamlConfig.IsNull() || !yamlConfig.IsDefined()) {
CLOG(FATAL) << "Unable to read config from config file";
return false;
}
YAML::Node networkConnectionConfig = yamlConfig["networkConnectionConfig"];
if (!networkConnectionConfig) {
CLOG(WARNING) << "No networkConnectionConfig in config file";
return false;
}

bool enableExternalIps = false;
if (networkConnectionConfig["enableExternalIps"]) {
enableExternalIps = networkConnectionConfig["enableExternalIps"].as<bool>(false);
}

sensor::CollectorConfig runtime_config;
auto* networkConfig = runtime_config.mutable_network_connection_config();
networkConfig->set_enable_external_ips(enableExternalIps);

SetRuntimeConfig(runtime_config);
CLOG(INFO) << "Runtime configuration:";
CLOG(INFO) << GetRuntimeConfigStr();

return true;
}

void CollectorConfig::HandleConfig(const std::filesystem::path& filePath) {
if (!std::filesystem::exists(filePath)) {
CLOG(DEBUG) << "No configuration file found. " << filePath;
return;
}

try {
YAML::Node yamlConfig = YAML::LoadFile(filePath);
YamlConfigToConfig(yamlConfig);
} catch (const YAML::BadFile& e) {
ovalenti marked this conversation as resolved.
Show resolved Hide resolved
CLOG(FATAL) << "Failed to open the configuration file: " << filePath
<< ". Error: " << e.what();
} catch (const YAML::ParserException& e) {
CLOG(FATAL) << "Failed to parse the configuration file: " << filePath
<< ". Error: " << e.what();
} catch (const YAML::Exception& e) {
CLOG(FATAL) << "An error occurred while loading the configuration file: " << filePath
<< ". Error: " << e.what();
} catch (const std::exception& e) {
CLOG(FATAL) << "An unexpected error occurred while trying to read: " << filePath << e.what();
}
}

bool CollectorConfig::TurnOffScrape() const {
return turn_off_scrape_;
}
Expand Down
11 changes: 11 additions & 0 deletions collector/lib/CollectorConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <vector>

#include <json/json.h>
#include <yaml-cpp/yaml.h>

#include <grpcpp/channel.h>

Expand Down Expand Up @@ -99,6 +100,14 @@ class CollectorConfig {
return enable_external_ips_;
}

std::string GetRuntimeConfigStr() {
if (runtime_config_.has_value()) {
const auto& cfg = runtime_config_.value();
return cfg.DebugString();
}
return "{}";
}

bool EnableConnectionStats() const { return enable_connection_stats_; }
bool EnableDetailedMetrics() const { return enable_detailed_metrics_; }
bool EnableRuntimeConfig() const { return enable_runtime_config_; }
Expand Down Expand Up @@ -188,6 +197,8 @@ class CollectorConfig {
void HandleAfterglowEnvVars();
void HandleConnectionStatsEnvVars();
void HandleSinspEnvVars();
bool YamlConfigToConfig(YAML::Node& yamlConfig);
void HandleConfig(const std::filesystem::path& filePath);

// Protected, used for testing purposes
void SetSinspBufferSize(unsigned int buffer_size);
Expand Down
71 changes: 71 additions & 0 deletions collector/test/CollectorConfigTest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <optional>

#include <internalapi/sensor/collector.pb.h>

#include "CollectorArgs.h"
#include "CollectorConfig.h"
#include "gmock/gmock.h"
Expand Down Expand Up @@ -32,6 +34,10 @@ class MockCollectorConfig : public CollectorConfig {
void MockSetEnableExternalIPs(bool value) {
SetEnableExternalIPs(value);
}

bool MockYamlConfigToConfig(YAML::Node& yamlConfig) {
return YamlConfigToConfig(yamlConfig);
}
Molter73 marked this conversation as resolved.
Show resolved Hide resolved
};

// Test that unmodified value is returned, when some dependency values are
Expand Down Expand Up @@ -145,4 +151,69 @@ TEST(CollectorConfigTest, TestEnableExternalIpsRuntimeConfig) {
EXPECT_TRUE(config.EnableExternalIPs());
}

TEST(CollectorConfigTest, TestYamlConfigToConfigMultiple) {
std::vector<std::pair<std::string, bool>> tests = {
{R"(
networkConnectionConfig:
enableExternalIps: true
)",
true},
{R"(
networkConnectionConfig:
enableExternalIps: false
)",
false},
{R"(
networkConnectionConfig:
)",
false},
{R"(
networkConnectionConfig:
unknownField: asdf
)",
false}};

for (const auto& [yamlStr, expected] : tests) {
YAML::Node yamlNode = YAML::Load(yamlStr);

MockCollectorConfig config;

bool result = config.MockYamlConfigToConfig(yamlNode);
auto runtime_config = config.GetRuntimeConfig();

EXPECT_TRUE(result);
EXPECT_TRUE(runtime_config.has_value());

const auto& cfg = runtime_config.value();
const auto& network_cfg = cfg.network_connection_config();
EXPECT_EQ(network_cfg.enable_external_ips(), expected);
EXPECT_EQ(config.EnableExternalIPs(), expected);
}
}

TEST(CollectorConfigTest, TestYamlConfigToConfigInvalid) {
std::string yamlStr = R"(
unknownField: asdf
)";

YAML::Node yamlNode = YAML::Load(yamlStr);

MockCollectorConfig config;

bool result = config.MockYamlConfigToConfig(yamlNode);
auto runtime_config = config.GetRuntimeConfig();

EXPECT_FALSE(result);
EXPECT_FALSE(runtime_config.has_value());
}

TEST(CollectorConfigTest, TestYamlConfigToConfigEmpty) {
std::string yamlStr = R"()";
YAML::Node yamlNode = YAML::Load(yamlStr);

MockCollectorConfig config;

EXPECT_DEATH({ config.MockYamlConfigToConfig(yamlNode); }, ".*");
Molter73 marked this conversation as resolved.
Show resolved Hide resolved
}

} // namespace collector
31 changes: 31 additions & 0 deletions docs/references.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ internal state of Collector. Refer to the
[troubleshooting](troubleshooting.md#introspection-endpoints) section for more details.
The default is false.

* `ROX_ENABLE_EXTERNAL_IPS`: Enables or disables the external IPs feature.

NOTE: Using environment variables is a preferred way of configuring Collector,
so if you're adding a new configuration knob, keep this in mind.

Expand All @@ -104,6 +106,35 @@ seconds. The default value is 30 seconds.

* `logLevel`: Sets logging level. The default is INFO.

### File mount or ConfigMap
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to document it!


The external IPs feature can be enabled or disabled using a file or ConfigMap. This is an optional
method and does not have to be used. This file overwites the ENABLE_EXTERNAL_IPS feature flag.
When using collector by itself a file can be mounted to it at /etc/stackrox/runtime_config.yaml. The
following is an example of the contents

```
networkConnectionConfig:
enableExternalIps: true
```

Alternatively, if collector is used as a part of Stackrox, the configuration can be set
using a ConfigMap. The following is an example of such a ConfigMap.

```
apiVersion: v1
kind: ConfigMap
metadata:
name: collector-config
namespace: stackrox
data:
runtime_config.yaml: |
networkConnectionConfig:
enableExternalIps: true
```

The file path can be set using the `ROX_COLLECTOR_CONFIG_PATH` environment variable.

### Other arguments

* `--collection-method`: Which technology to use for data gathering. Either
Expand Down
Loading