Skip to content

Commit

Permalink
MINIFICPP-2314 - Add nifi.c2.rest.path.base agent property
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdebreceni committed Jun 19, 2024
1 parent f8330b2 commit f9d1871
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 6 deletions.
6 changes: 4 additions & 2 deletions C2.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ be requested via C2 DESCRIBE manifest command.
nifi.c2.rest.listener.cacert=<SSL Cert path>

# specify the rest URIs if using RESTSender
nifi.c2.rest.url=http://<your-c2-server>/<c2-api-path>/c2-protocol/heartbeat
nifi.c2.rest.url.ack=http://<your-c2-server>/<c2-api-path>/c2-protocol/acknowledge
nifi.c2.rest.path.base=https://<your-c2-server>/<c2-api-path>
# spicify either absolute url or relative to the nifi.c2.rest.path.base url for hearbeat and acknowledge
nifi.c2.rest.url=/c2-protocol/heartbeat
nifi.c2.rest.url.ack=/c2-protocol/acknowledge
nifi.c2.flow.base.url=http://<your-c2-server>/<c2-api-path>/c2-protocol/

# c2 agent identifier -- must be defined to run agent
Expand Down
1 change: 1 addition & 0 deletions conf/minifi.properties
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ nifi.content.repository.class.name=DatabaseContentRepository
## base URL of the c2 server,
## very likely the same base url of rest urls
#nifi.c2.flow.base.url=
#nifi.c2.rest.path.base=
#nifi.c2.rest.url=
#nifi.c2.rest.url.ack=
#nifi.c2.rest.ssl.context.service=
Expand Down
2 changes: 1 addition & 1 deletion libminifi/include/core/state/nodes/AssetInformation.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class AssetInformation : public ResponseNode {

void setAssetManager(std::shared_ptr<utils::file::AssetManager> asset_manager);

std::string getName() const override { return "assetInfo"; }
std::string getName() const override { return "resourceInfo"; }
std::vector<SerializedResponseNode> serialize() override;

private:
Expand Down
1 change: 1 addition & 0 deletions libminifi/include/properties/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class Configuration : public Properties {
static constexpr const char *nifi_c2_root_class_definitions = "nifi.c2.root.class.definitions";
static constexpr const char *nifi_c2_rest_listener_port = "nifi.c2.rest.listener.port";
static constexpr const char *nifi_c2_rest_listener_cacert = "nifi.c2.rest.listener.cacert";
static constexpr const char *nifi_c2_rest_path_base = "nifi.c2.rest.path.base";
static constexpr const char *nifi_c2_rest_url = "nifi.c2.rest.url";
static constexpr const char *nifi_c2_rest_url_ack = "nifi.c2.rest.url.ack";
static constexpr const char *nifi_c2_rest_ssl_context_service = "nifi.c2.rest.ssl.context.service";
Expand Down
1 change: 1 addition & 0 deletions libminifi/src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const std::unordered_map<std::string_view, gsl::not_null<const core::PropertyVal
{Configuration::nifi_c2_root_class_definitions, gsl::make_not_null(&core::StandardPropertyTypes::VALID_TYPE)},
{Configuration::nifi_c2_rest_listener_port, gsl::make_not_null(&core::StandardPropertyTypes::LISTEN_PORT_TYPE)},
{Configuration::nifi_c2_rest_listener_cacert, gsl::make_not_null(&core::StandardPropertyTypes::VALID_TYPE)},
{Configuration::nifi_c2_rest_path_base, gsl::make_not_null(&core::StandardPropertyTypes::VALID_TYPE)},
{Configuration::nifi_c2_rest_url, gsl::make_not_null(&core::StandardPropertyTypes::VALID_TYPE)},
{Configuration::nifi_c2_rest_url_ack, gsl::make_not_null(&core::StandardPropertyTypes::VALID_TYPE)},
{Configuration::nifi_c2_rest_ssl_context_service, gsl::make_not_null(&core::StandardPropertyTypes::VALID_TYPE)},
Expand Down
3 changes: 3 additions & 0 deletions libminifi/src/c2/C2Agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,9 @@ std::optional<std::string> C2Agent::resolveUrl(const std::string& url) const {
return url;
}
std::string base;
if (configuration_->get(Configuration::nifi_c2_rest_path_base, "c2.rest.path.base", base)) {
return base + url;
}
if (!configuration_->get(Configuration::nifi_c2_rest_url, "c2.rest.url", base)) {
logger_->log_error("Missing C2 REST URL");
return std::nullopt;
Expand Down
13 changes: 13 additions & 0 deletions libminifi/src/c2/protocols/RESTSender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,23 @@ void RESTSender::initialize(core::controller::ControllerServiceProvider* control
RESTProtocol::initialize(controller, configure);
// base URL when one is not specified.
if (nullptr != configure) {
std::optional<std::string> rest_base_path = configure->getWithFallback(Configuration::nifi_c2_rest_path_base, "c2.rest.path.base");
std::string update_str;
std::string ssl_context_service_str;
configure->get(Configuration::nifi_c2_rest_url, "c2.rest.url", rest_uri_);
configure->get(Configuration::nifi_c2_rest_url_ack, "c2.rest.url.ack", ack_uri_);
if (rest_uri_.starts_with("/")) {
if (!rest_base_path) {
throw Exception(ExceptionType::GENERAL_EXCEPTION, "Cannot use relative nifi.c2.rest.url unless the nifi.c2.rest.path.base is set");
}
rest_uri_ = rest_base_path.value() + rest_uri_;
}
if (ack_uri_.starts_with("/")) {
if (!rest_base_path) {
throw Exception(ExceptionType::GENERAL_EXCEPTION, "Cannot use relative nifi.c2.rest.url.ack unless the nifi.c2.rest.path.base is set");
}
ack_uri_ = rest_base_path.value() + ack_uri_;
}
if (controller && configure->get(Configuration::nifi_c2_rest_ssl_context_service, "c2.rest.ssl.context.service", ssl_context_service_str)) {
if (auto service = controller->getControllerService(ssl_context_service_str)) {
ssl_context_service_ = std::static_pointer_cast<minifi::controllers::SSLContextService>(service);
Expand Down
4 changes: 4 additions & 0 deletions libminifi/src/core/state/nodes/SupportedOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ void SupportedOperations::fillProperties(SerializedResponseNode& properties, min
}
break;
}
case minifi::c2::Operation::sync: {
serializeProperty<minifi::c2::SyncOperand>(properties);
break;
}
default:
break;
}
Expand Down
17 changes: 15 additions & 2 deletions libminifi/src/utils/file/AssetManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,24 @@ nonstd::expected<void, std::string> AssetManager::sync(
org::apache::nifi::minifi::utils::file::AssetLayout layout,
const std::function<nonstd::expected<std::vector<std::byte>, std::string>(std::string_view /*url*/)>& fetch) {
std::lock_guard lock(mtx_);
org::apache::nifi::minifi::utils::file::AssetLayout new_state{
.digest = state_.digest
};
std::string fetch_errors;
std::vector<std::pair<std::filesystem::path, std::vector<std::byte>>> new_file_contents;
for (auto& new_entry : layout.assets) {
if (std::find_if(state_.assets.begin(), state_.assets.end(), [&] (auto& entry) {return entry.id == new_entry.id;}) == state_.assets.end()) {
if (auto data = fetch(new_entry.url)) {
new_file_contents.emplace_back(new_entry.path, data.value());
new_state.assets.insert(new_entry);
} else {
return nonstd::make_unexpected(data.error());
fetch_errors += "Failed to fetch '" + new_entry.id + "' from '" + new_entry.url + "': " + data.error() + "\n";
}
}
}
if (fetch_errors.empty()) {
new_state.digest = layout.digest;
}

for (auto& old_entry : state_.assets) {
if (std::find_if(layout.assets.begin(), layout.assets.end(), [&] (auto& entry) {return entry.id == old_entry.id;}) == layout.assets.end()) {
Expand All @@ -134,8 +142,13 @@ nonstd::expected<void, std::string> AssetManager::sync(
std::ofstream{root_ / path, std::ios::binary}.write(reinterpret_cast<const char*>(content.data()), gsl::narrow<std::streamsize>(content.size()));
}

state_ = std::move(layout);
state_ = std::move(new_state);
persist();

if (!fetch_errors.empty()) {
return nonstd::make_unexpected(fetch_errors);
}

return {};
}

Expand Down
2 changes: 1 addition & 1 deletion libminifi/test/integration/C2AssetSyncTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class C2HeartbeatHandler : public HeartbeatHandler {
root.Accept(writer);
return std::string{buffer.GetString(), buffer.GetSize()};
}();
auto& asset_info_node = root["assetInfo"];
auto& asset_info_node = root["resourceInfo"];
auto& asset_hash_node = asset_info_node["hash"];
std::string asset_hash{asset_hash_node.GetString(), asset_hash_node.GetStringLength()};

Expand Down

0 comments on commit f9d1871

Please sign in to comment.