This is an automated email from the ASF dual-hosted git repository. szaszm pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit 4b6a0aff7fb356cb6b4a68b76a1226bdfccb2a42 Author: Gabor Gyimesi <[email protected]> AuthorDate: Wed Apr 20 17:54:23 2022 +0200 MINIFICPP-1794 Remove sensitive properties from agent manifest Closes #1296 Signed-off-by: Marton Szasz <[email protected]> --- encrypt-config/ConfigFile.cpp | 39 ++---------------- encrypt-config/ConfigFile.h | 3 -- encrypt-config/tests/ConfigFileTests.cpp | 44 -------------------- .../tests/C2DescribeCoreComponentStateTest.cpp | 17 +++++--- .../http-curl/tests/C2DescribeManifestTest.cpp | 18 +++++++-- extensions/http-curl/tests/C2JstackTest.cpp | 13 +----- extensions/http-curl/tests/HTTPHandlers.h | 6 +++ extensions/http-curl/tests/HTTPIntegrationBase.h | 13 ++++-- .../tests/unit/ConfigurationTests.cpp | 47 ++++++++++++++++++++++ libminifi/include/core/Property.h | 3 +- libminifi/include/properties/Configuration.h | 7 +++- libminifi/src/Configuration.cpp | 32 +++++++++++++++ .../src/core/state/nodes/SupportedOperations.cpp | 10 +++-- 13 files changed, 140 insertions(+), 112 deletions(-) diff --git a/encrypt-config/ConfigFile.cpp b/encrypt-config/ConfigFile.cpp index 9b01746cf..d4abed332 100644 --- a/encrypt-config/ConfigFile.cpp +++ b/encrypt-config/ConfigFile.cpp @@ -25,24 +25,10 @@ #include "utils/StringUtils.h" #include "properties/Configuration.h" -namespace org { -namespace apache { -namespace nifi { -namespace minifi { -namespace encrypt_config { - -constexpr std::array<const char*, 2> DEFAULT_SENSITIVE_PROPERTIES{Configuration::nifi_security_client_pass_phrase, - Configuration::nifi_rest_api_password}; -constexpr const char* ADDITIONAL_SENSITIVE_PROPS_PROPERTY_NAME = Configuration::nifi_sensitive_props_additional_keys; +namespace org::apache::nifi::minifi::encrypt_config { std::vector<std::string> ConfigFile::getSensitiveProperties() const { - std::vector<std::string> sensitive_properties(DEFAULT_SENSITIVE_PROPERTIES.begin(), DEFAULT_SENSITIVE_PROPERTIES.end()); - const std::optional<std::string> additional_sensitive_props_list = getValue(ADDITIONAL_SENSITIVE_PROPS_PROPERTY_NAME); - if (additional_sensitive_props_list) { - std::vector<std::string> additional_sensitive_properties = utils::StringUtils::split(*additional_sensitive_props_list, ","); - sensitive_properties = mergeProperties(sensitive_properties, additional_sensitive_properties); - } - + auto sensitive_properties = Configuration::getSensitiveProperties([this](const std::string& sensitive_props) { return getValue(sensitive_props); }); const auto not_found = [this](const std::string& property_name) { return !hasValue(property_name); }; const auto new_end = std::remove_if(sensitive_properties.begin(), sensitive_properties.end(), not_found); sensitive_properties.erase(new_end, sensitive_properties.end()); @@ -50,23 +36,4 @@ std::vector<std::string> ConfigFile::getSensitiveProperties() const { return sensitive_properties; } -std::vector<std::string> ConfigFile::mergeProperties(std::vector<std::string> properties, - const std::vector<std::string>& additional_properties) { - for (const auto& property_name : additional_properties) { - std::string property_name_trimmed = utils::StringUtils::trim(property_name); - if (!property_name_trimmed.empty()) { - properties.push_back(std::move(property_name_trimmed)); - } - } - - std::sort(properties.begin(), properties.end()); - auto new_end = std::unique(properties.begin(), properties.end()); - properties.erase(new_end, properties.end()); - return properties; -} - -} // namespace encrypt_config -} // namespace minifi -} // namespace nifi -} // namespace apache -} // namespace org +} // namespace org::apache::nifi::minifi::encrypt_config diff --git a/encrypt-config/ConfigFile.h b/encrypt-config/ConfigFile.h index 53b7e58b0..634c9a89c 100644 --- a/encrypt-config/ConfigFile.h +++ b/encrypt-config/ConfigFile.h @@ -35,10 +35,7 @@ class ConfigFile : public PropertiesFile { [[nodiscard]] std::vector<std::string> getSensitiveProperties() const; private: - friend class ConfigFileTestAccessor; friend bool operator==(const ConfigFile&, const ConfigFile&); - static std::vector<std::string> mergeProperties(std::vector<std::string> properties, - const std::vector<std::string>& additional_properties); }; } // namespace encrypt_config diff --git a/encrypt-config/tests/ConfigFileTests.cpp b/encrypt-config/tests/ConfigFileTests.cpp index 894cd3a40..ab5d9bd78 100644 --- a/encrypt-config/tests/ConfigFileTests.cpp +++ b/encrypt-config/tests/ConfigFileTests.cpp @@ -29,27 +29,7 @@ #include "Catch.h" #include "utils/file/FileUtils.h" -namespace org { -namespace apache { -namespace nifi { -namespace minifi { -namespace encrypt_config { - -class ConfigFileTestAccessor { - public: - static std::vector<std::string> mergeProperties(std::vector<std::string> left, const std::vector<std::string>& right) { - return ConfigFile::mergeProperties(left, right); - } -}; - -} // namespace encrypt_config -} // namespace minifi -} // namespace nifi -} // namespace apache -} // namespace org - using org::apache::nifi::minifi::encrypt_config::ConfigFile; -using org::apache::nifi::minifi::encrypt_config::ConfigFileTestAccessor; using org::apache::nifi::minifi::Configuration; TEST_CASE("ConfigLine can be constructed from a line", "[encrypt-config][constructor]") { @@ -205,30 +185,6 @@ TEST_CASE("ConfigFile will throw if we try to write to an invalid file name", "[ REQUIRE_THROWS(test_file.writeTo(file_path)); } -TEST_CASE("ConfigFile can merge lists of property names", "[encrypt-config][mergeProperties]") { - using vector = std::vector<std::string>; - - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{}, vector{}) == vector{}); - - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a"}, vector{}) == vector{"a"}); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a"}, vector{"a"}) == vector{"a"}); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a"}, vector{"b"}) == (vector{"a", "b"})); - - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"c"}) == (vector{"a", "b", "c"})); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"a", "b"}) == (vector{"a", "b"})); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"a", "c"}) == (vector{"a", "b", "c"})); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"b", "c"}) == (vector{"a", "b", "c"})); - - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a"}, vector{" a"}) == vector{"a"}); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a"}, vector{"a "}) == vector{"a"}); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a"}, vector{" a "}) == vector{"a"}); - - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"\tc"}) == (vector{"a", "b", "c"})); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"a\n", "b"}) == (vector{"a", "b"})); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"a", "c\r\n"}) == (vector{"a", "b", "c"})); - REQUIRE(ConfigFileTestAccessor::mergeProperties(vector{"a", "b"}, vector{"b\n", "\t c"}) == (vector{"a", "b", "c"})); -} - TEST_CASE("ConfigFile can find the list of sensitive properties", "[encrypt-config][getSensitiveProperties]") { SECTION("default properties") { ConfigFile test_file{std::ifstream{"resources/minifi.properties"}}; diff --git a/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp b/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp index cf2f619e9..8754bfa0f 100644 --- a/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp +++ b/extensions/http-curl/tests/C2DescribeCoreComponentStateTest.cpp @@ -28,7 +28,8 @@ class VerifyC2DescribeCoreComponentState : public VerifyC2Describe { public: - VerifyC2DescribeCoreComponentState() { + explicit VerifyC2DescribeCoreComponentState(std::atomic_bool& verified) + : VerifyC2Describe(verified) { temp_dir_ = testController.createTempDirectory(); test_file_1_ = utils::file::FileUtils::concat_path(temp_dir_, "test1.txt"); @@ -62,8 +63,9 @@ class VerifyC2DescribeCoreComponentState : public VerifyC2Describe { class DescribeCoreComponentStateHandler: public HeartbeatHandler { public: - explicit DescribeCoreComponentStateHandler(std::shared_ptr<minifi::Configure> configuration) - : HeartbeatHandler(std::move(configuration)) { + explicit DescribeCoreComponentStateHandler(std::shared_ptr<minifi::Configure> configuration, std::atomic_bool& verified) + : HeartbeatHandler(std::move(configuration)), + verified_(verified) { } void handleHeartbeat(const rapidjson::Document&, struct mg_connection * conn) override { @@ -86,14 +88,19 @@ class DescribeCoreComponentStateHandler: public HeartbeatHandler { assertExpectedTailFileState("2438e3c8-015a-1000-79ca-83af40ec1993", "test1.txt", "4"); assertExpectedTailFileState("2438e3c8-015a-1000-79ca-83af40ec1994", "test2.txt", "7"); + verified_ = true; } + + private: + std::atomic_bool& verified_; }; int main(int argc, char **argv) { + std::atomic_bool verified{false}; const cmd_args args = parse_cmdline_args(argc, argv, "api/heartbeat"); - VerifyC2DescribeCoreComponentState harness; + VerifyC2DescribeCoreComponentState harness(verified); harness.setKeyDir(args.key_dir); - DescribeCoreComponentStateHandler handler(harness.getConfiguration()); + DescribeCoreComponentStateHandler handler(harness.getConfiguration(), verified); harness.setUrl(args.url, &handler); harness.run(args.test_file); return 0; diff --git a/extensions/http-curl/tests/C2DescribeManifestTest.cpp b/extensions/http-curl/tests/C2DescribeManifestTest.cpp index a6a9a38c6..242800ee4 100644 --- a/extensions/http-curl/tests/C2DescribeManifestTest.cpp +++ b/extensions/http-curl/tests/C2DescribeManifestTest.cpp @@ -26,8 +26,9 @@ class DescribeManifestHandler: public HeartbeatHandler { public: - explicit DescribeManifestHandler(std::shared_ptr<minifi::Configure> configuration) - : HeartbeatHandler(std::move(configuration)) { + explicit DescribeManifestHandler(std::shared_ptr<minifi::Configure> configuration, std::atomic<bool>& verified) + : HeartbeatHandler(std::move(configuration)), + verified_(verified) { } void handleHeartbeat(const rapidjson::Document&, struct mg_connection * conn) override { @@ -36,22 +37,31 @@ class DescribeManifestHandler: public HeartbeatHandler { void handleAcknowledge(const rapidjson::Document& root) override { verifyJsonHasAgentManifest(root, {"InvokeHTTP", "LogAttribute"}, {"nifi.extension.path", "nifi.python.processor.dir"}); + verified_ = true; } + + private: + std::atomic<bool>& verified_; }; int main(int argc, char **argv) { const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat"); - VerifyC2Describe harness; + std::atomic_bool verified{false}; + VerifyC2Describe harness(verified); utils::crypto::Bytes encryption_key = utils::StringUtils::from_hex("4024b327fdc987ce3eb43dd1f690b9987e4072e0020e3edf4349ce1ad91a4e38"); minifi::Decryptor decryptor{utils::crypto::EncryptionProvider{encryption_key}}; std::string encrypted_value = "l3WY1V27knTiPa6jVX0jrq4qjmKsySOu||ErntqZpHP1M+6OkA14p5sdnqJhuNHWHDVUU5EyMloTtSytKk9a5xNKo="; harness.setConfiguration(std::make_shared<minifi::Configure>(decryptor)); harness.setKeyDir(args.key_dir); - DescribeManifestHandler responder(harness.getConfiguration()); + DescribeManifestHandler responder(harness.getConfiguration(), verified); harness.getConfiguration()->set(minifi::Configuration::nifi_rest_api_password, encrypted_value); harness.getConfiguration()->set(std::string(minifi::Configuration::nifi_rest_api_password) + ".protected", utils::crypto::EncryptionType::name()); + harness.getConfiguration()->set(minifi::Configuration::nifi_server_name, "server_name"); + harness.getConfiguration()->set(minifi::Configuration::nifi_framework_dir, "framework_path"); + harness.getConfiguration()->set(minifi::Configuration::nifi_sensitive_props_additional_keys, + std::string(minifi::Configuration::nifi_framework_dir) + ", " + std::string(minifi::Configuration::nifi_server_name)); harness.setUrl(args.url, &responder); harness.run(args.test_file); diff --git a/extensions/http-curl/tests/C2JstackTest.cpp b/extensions/http-curl/tests/C2JstackTest.cpp index b7cfb8aeb..f1b9b4521 100644 --- a/extensions/http-curl/tests/C2JstackTest.cpp +++ b/extensions/http-curl/tests/C2JstackTest.cpp @@ -25,17 +25,6 @@ #include "HTTPHandlers.h" #include "utils/IntegrationTestUtils.h" -class VerifyC2DescribeJstack : public VerifyC2Describe { - public: - explicit VerifyC2DescribeJstack(const std::atomic_bool& acknowledgement_received) : VerifyC2Describe(), acknowledgement_received_(acknowledgement_received) {} - void runAssertions() override { - using org::apache::nifi::minifi::utils::verifyEventHappenedInPollTime; - assert(verifyEventHappenedInPollTime(std::chrono::milliseconds(wait_time_), [&] { return acknowledgement_received_.load(); })); - } - protected: - const std::atomic_bool& acknowledgement_received_; -}; - class DescribeJstackHandler : public HeartbeatHandler { public: explicit DescribeJstackHandler(std::atomic_bool& acknowledgement_received, std::shared_ptr<minifi::Configure> configuration) @@ -58,7 +47,7 @@ class DescribeJstackHandler : public HeartbeatHandler { int main(int argc, char **argv) { const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat"); std::atomic_bool acknowledgement_received{ false }; - VerifyC2DescribeJstack harness{acknowledgement_received}; + VerifyC2Describe harness{acknowledgement_received}; harness.setKeyDir(args.key_dir); DescribeJstackHandler responder{acknowledgement_received, harness.getConfiguration()}; harness.setUrl(args.url, &responder); diff --git a/extensions/http-curl/tests/HTTPHandlers.h b/extensions/http-curl/tests/HTTPHandlers.h index c136ab179..92478a00a 100644 --- a/extensions/http-curl/tests/HTTPHandlers.h +++ b/extensions/http-curl/tests/HTTPHandlers.h @@ -552,7 +552,13 @@ class HeartbeatHandler : public ServerAwareHandler { } case minifi::c2::Operation::UPDATE: { std::vector<std::unordered_map<std::string, std::string>> config_properties; + const auto prop_reader = [this](const std::string& sensitive_props) { return configuration_->getString(sensitive_props); }; + const auto sensitive_props = minifi::Configuration::getSensitiveProperties(prop_reader); for (const auto& property : minifi::Configuration::CONFIGURATION_PROPERTIES) { + if (ranges::find(sensitive_props, property.name) != ranges::end(sensitive_props)) { + continue; + } + std::unordered_map<std::string, std::string> config_property; if (ranges::find(disallowed_properties, property.name) == ranges::end(disallowed_properties)) { config_property.emplace("propertyName", property.name); diff --git a/extensions/http-curl/tests/HTTPIntegrationBase.h b/extensions/http-curl/tests/HTTPIntegrationBase.h index 407399f0a..1136f217b 100644 --- a/extensions/http-curl/tests/HTTPIntegrationBase.h +++ b/extensions/http-curl/tests/HTTPIntegrationBase.h @@ -19,6 +19,7 @@ #include <memory> #include <string> +#include <atomic> #include "CivetServer.h" #include "integration/IntegrationBase.h" @@ -146,6 +147,10 @@ class VerifyC2Base : public HTTPIntegrationBase { class VerifyC2Describe : public VerifyC2Base { public: + explicit VerifyC2Describe(std::atomic<bool>& verified) + : verified_(verified) { + } + void testSetup() override { LogTestController::getInstance().setTrace<minifi::c2::C2Agent>(); LogTestController::getInstance().setDebug<minifi::c2::RESTSender>(); @@ -158,10 +163,12 @@ class VerifyC2Describe : public VerifyC2Base { } void runAssertions() override { - // This class is never used for running assertions, but we are forced to wait for DescribeManifestHandler to verifyJsonHasAgentManifest - // if we were to log something on finished verification, we could poll on finding it - std::this_thread::sleep_for(std::chrono::milliseconds(wait_time_)); + using org::apache::nifi::minifi::utils::verifyEventHappenedInPollTime; + assert(verifyEventHappenedInPollTime(std::chrono::milliseconds(wait_time_), [&] { return verified_.load(); })); } + + protected: + std::atomic<bool>& verified_; }; class VerifyC2Update : public HTTPIntegrationBase { diff --git a/extensions/standard-processors/tests/unit/ConfigurationTests.cpp b/extensions/standard-processors/tests/unit/ConfigurationTests.cpp new file mode 100644 index 000000000..eb8d95dc9 --- /dev/null +++ b/extensions/standard-processors/tests/unit/ConfigurationTests.cpp @@ -0,0 +1,47 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 "TestBase.h" +#include "Catch.h" + +#include "properties/Configuration.h" + +using org::apache::nifi::minifi::Configuration; + +TEST_CASE("Configuration can merge lists of property names", "[mergeProperties]") { + using vector = std::vector<std::string>; + + REQUIRE(Configuration::mergeProperties(vector{}, vector{}) == vector{}); + + REQUIRE(Configuration::mergeProperties(vector{"a"}, vector{}) == vector{"a"}); + REQUIRE(Configuration::mergeProperties(vector{"a"}, vector{"a"}) == vector{"a"}); + REQUIRE(Configuration::mergeProperties(vector{"a"}, vector{"b"}) == (vector{"a", "b"})); + + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"c"}) == (vector{"a", "b", "c"})); + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"a", "b"}) == (vector{"a", "b"})); + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"a", "c"}) == (vector{"a", "b", "c"})); + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"b", "c"}) == (vector{"a", "b", "c"})); + + REQUIRE(Configuration::mergeProperties(vector{"a"}, vector{" a"}) == vector{"a"}); + REQUIRE(Configuration::mergeProperties(vector{"a"}, vector{"a "}) == vector{"a"}); + REQUIRE(Configuration::mergeProperties(vector{"a"}, vector{" a "}) == vector{"a"}); + + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"\tc"}) == (vector{"a", "b", "c"})); + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"a\n", "b"}) == (vector{"a", "b"})); + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"a", "c\r\n"}) == (vector{"a", "b", "c"})); + REQUIRE(Configuration::mergeProperties(vector{"a", "b"}, vector{"b\n", "\t c"}) == (vector{"a", "b", "c"})); +} diff --git a/libminifi/include/core/Property.h b/libminifi/include/core/Property.h index 00e6dd11a..0ca55efca 100644 --- a/libminifi/include/core/Property.h +++ b/libminifi/include/core/Property.h @@ -469,7 +469,8 @@ class ConstrainedProperty : public std::enable_shared_from_this<ConstrainedPrope }; struct ConfigurationProperty { - explicit ConfigurationProperty(std::string_view name, gsl::not_null<PropertyValidator*> validator = gsl::make_not_null(StandardValidators::get().VALID_VALIDATOR.get())) + explicit ConfigurationProperty(std::string_view name, + gsl::not_null<PropertyValidator*> validator = gsl::make_not_null(StandardValidators::get().VALID_VALIDATOR.get())) : name(name), validator(validator) { } diff --git a/libminifi/include/properties/Configuration.h b/libminifi/include/properties/Configuration.h index 840953e05..6f7a3394c 100644 --- a/libminifi/include/properties/Configuration.h +++ b/libminifi/include/properties/Configuration.h @@ -17,8 +17,8 @@ #pragma once -#include <mutex> #include <vector> +#include <string> #include "properties/Properties.h" #include "utils/OptionalUtils.h" @@ -163,6 +163,11 @@ class Configuration : public Properties { static constexpr const char *nifi_log_compression_compressed_log_max_size = "nifi.log.compression.compressed.log.max.size"; MINIFIAPI static const std::vector<core::ConfigurationProperty> CONFIGURATION_PROPERTIES; + MINIFIAPI static const std::array<const char*, 2> DEFAULT_SENSITIVE_PROPERTIES; + + static std::vector<std::string> mergeProperties(std::vector<std::string> properties, + const std::vector<std::string>& additional_properties); + static std::vector<std::string> getSensitiveProperties(std::function<std::optional<std::string>(const std::string&)> reader); }; } // namespace minifi diff --git a/libminifi/src/Configuration.cpp b/libminifi/src/Configuration.cpp index 3e916ec7a..91a50cff0 100644 --- a/libminifi/src/Configuration.cpp +++ b/libminifi/src/Configuration.cpp @@ -14,6 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include <algorithm> + #include "properties/Configuration.h" #include "core/Property.h" @@ -129,4 +131,34 @@ const std::vector<core::ConfigurationProperty> Configuration::CONFIGURATION_PROP core::ConfigurationProperty{Configuration::nifi_log_compression_compressed_log_max_size, gsl::make_not_null(core::StandardValidators::get().DATA_SIZE_VALIDATOR.get())} }; +const std::array<const char*, 2> Configuration::DEFAULT_SENSITIVE_PROPERTIES = {Configuration::nifi_security_client_pass_phrase, + Configuration::nifi_rest_api_password}; + +std::vector<std::string> Configuration::mergeProperties(std::vector<std::string> properties, + const std::vector<std::string>& additional_properties) { + for (const auto& property_name : additional_properties) { + std::string property_name_trimmed = utils::StringUtils::trim(property_name); + if (!property_name_trimmed.empty()) { + properties.push_back(std::move(property_name_trimmed)); + } + } + + std::sort(properties.begin(), properties.end()); + auto new_end = std::unique(properties.begin(), properties.end()); + properties.erase(new_end, properties.end()); + return properties; +} + +std::vector<std::string> Configuration::getSensitiveProperties(std::function<std::optional<std::string>(const std::string&)> reader) { + std::vector<std::string> sensitive_properties(Configuration::DEFAULT_SENSITIVE_PROPERTIES.begin(), Configuration::DEFAULT_SENSITIVE_PROPERTIES.end()); + if (reader) { + const auto additional_sensitive_props_list = reader(Configuration::nifi_sensitive_props_additional_keys); + if (additional_sensitive_props_list) { + std::vector<std::string> additional_sensitive_properties = utils::StringUtils::split(*additional_sensitive_props_list, ","); + return Configuration::mergeProperties(sensitive_properties, additional_sensitive_properties); + } + } + return sensitive_properties; +} + } // namespace org::apache::nifi::minifi diff --git a/libminifi/src/core/state/nodes/SupportedOperations.cpp b/libminifi/src/core/state/nodes/SupportedOperations.cpp index e7ff1f61f..f96e8b2d8 100644 --- a/libminifi/src/core/state/nodes/SupportedOperations.cpp +++ b/libminifi/src/core/state/nodes/SupportedOperations.cpp @@ -18,6 +18,7 @@ #include "core/state/nodes/SupportedOperations.h" #include "core/Resource.h" +#include "range/v3/algorithm/find.hpp" namespace org::apache::nifi::minifi::state::response { @@ -64,9 +65,12 @@ void SupportedOperations::addProperty(SerializedResponseNode& properties, const SupportedOperations::Metadata SupportedOperations::buildUpdatePropertiesMetadata() const { std::vector<std::unordered_map<std::string, std::string>> supported_config_updates; - for (const auto& config_property : minifi::Configuration::CONFIGURATION_PROPERTIES) { - if (!update_policy_controller_ || - (update_policy_controller_ && update_policy_controller_->canUpdate(std::string(config_property.name)))) { + for (const auto& config_property : Configuration::CONFIGURATION_PROPERTIES) { + auto sensitive_properties = Configuration::getSensitiveProperties(configuration_reader_); + if (ranges::find(sensitive_properties, config_property.name) != ranges::end(sensitive_properties)) { + continue; + } + if (!update_policy_controller_ || update_policy_controller_->canUpdate(std::string(config_property.name))) { std::unordered_map<std::string, std::string> property; property.emplace("propertyName", config_property.name); property.emplace("validator", config_property.validator->getName());
