Introduce AnycastUser interface for dynamic address updates.
This change adds an `AnycastUser` interface and a `FeedClientAnycastUser` implementation to allow the FeedClient to receive and update its target address based on the Redfish Authorizer's configuration. The Redfish Authorizer now registers and notifies these users when the configuration is reloaded.
PiperOrigin-RevId: 822346672
Change-Id: I4e61b5f3f3c7bfc82b1ceb8e4586b5520aec6773
diff --git a/g3/server.cc b/g3/server.cc
index 33ddd9a..65c53a1 100644
--- a/g3/server.cc
+++ b/g3/server.cc
@@ -7,6 +7,7 @@
#include <string_view>
#include "tlbmc/feed_client_grpc.h"
+#include "tlbmc/feed_client_interface.h"
#include "absl/status/status.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_format.h"
@@ -1162,6 +1163,7 @@
using ::milotic_hft::SubscriptionManager;
using ::milotic_hft::SubscriptionManagerFake;
using ::milotic_hft::SubscriptionManagerImpl;
+ using ::platforms_syshealth::collection::feed::FeedClientAnycastUser;
using ::milotic_tlbmc::StoreHftAdapter;
LOG(WARNING) << "Start gRPC server...";
@@ -1228,6 +1230,8 @@
absl::StatusOr<std::unique_ptr<milotic_hft::DataSource>> data_source =
milotic_tlbmc::StoreHftAdapter::Create(tlbmc_app->GetStore());
if (data_source.ok()) {
+ // Hardcode the peer role to FeedService for now as we only have one
+ // anycast user and is not expected to be changed.
std::string anycast_address =
BmcWebAuthorizerSingleton::GetInstance().GetAnycastAddress(
"FeedService");
@@ -1249,9 +1253,13 @@
config_.trust_bundle_path);
credentials = grpc_options.GetChannelCredentials();
}
- feed_client_ = std::make_unique<
+ feed_client_ = std::make_shared<
platforms_syshealth::collection::feed::FeedClientGrpc>(
feed_client_config, credentials);
+ feed_client_anycast_user_ =
+ std::make_unique<FeedClientAnycastUser>(feed_client_);
+ BmcWebAuthorizerSingleton::GetInstance().RegisterAnycastUser(
+ "FeedService", feed_client_anycast_user_.get());
subscription_manager = milotic_hft::SubscriptionManagerImpl::Create(
std::move(*data_source), feed_client_.get(),
{.get_policies_interval =
diff --git a/g3/server.h b/g3/server.h
index 2bb7211..e8b7593 100644
--- a/g3/server.h
+++ b/g3/server.h
@@ -205,8 +205,10 @@
std::unique_ptr<milotic_fast_sanity::FruServiceImpl> fru_service_;
std::unique_ptr<milotic_hft::HftServiceImpl> hft_service_;
ecclesia::SubscriptionService* subscription_service_ = nullptr;
- std::unique_ptr<platforms_syshealth::collection::feed::FeedClientInterface>
+ std::shared_ptr<platforms_syshealth::collection::feed::FeedClientInterface>
feed_client_;
+ std::unique_ptr<platforms_syshealth::collection::feed::AnycastUser>
+ feed_client_anycast_user_;
std::unique_ptr<grpc::Server> server_;
};
} // namespace milotic
diff --git a/redfish_authorization/bmcweb_authorizer_singleton.cc b/redfish_authorization/bmcweb_authorizer_singleton.cc
index bbf4c54..3552a55 100644
--- a/redfish_authorization/bmcweb_authorizer_singleton.cc
+++ b/redfish_authorization/bmcweb_authorizer_singleton.cc
@@ -14,6 +14,7 @@
#include <vector>
#include "gmi/machine_identity.pb.h"
+#include "tlbmc/feed_client_interface.h"
#include "one/network_interfaces.pb.h"
#include "one/offline_node_entities.pb.h"
#include "one/resolved_entities.pb.h"
@@ -68,6 +69,12 @@
redfish_authorizer_.ReloadConfiguration(configuration_path);
}
+void BmcWebAuthorizerSingleton::RegisterAnycastUser(
+ const std::string& service,
+ platforms_syshealth::collection::feed::AnycastUser* user) {
+ redfish_authorizer_.RegisterAnycastUser(service, user);
+}
+
BmcWebAuthorizerSingleton& BmcWebAuthorizerSingleton::GetInstance() {
return Initialize(/*options=*/{}, /*oauth_key_path=*/"");
}
@@ -487,4 +494,9 @@
host, primary_fqdn, absl::StrJoin(GetInterfaceFqdns(), " ")));
}
+void BmcWebAuthorizerSingleton::DeregisterAnycastUser(
+ const std::string& service) {
+ redfish_authorizer_.DeregisterAnycastUser(service);
+}
+
} // namespace milotic::authz
diff --git a/redfish_authorization/bmcweb_authorizer_singleton.h b/redfish_authorization/bmcweb_authorizer_singleton.h
index 9207110..d79b73a 100644
--- a/redfish_authorization/bmcweb_authorizer_singleton.h
+++ b/redfish_authorization/bmcweb_authorizer_singleton.h
@@ -106,6 +106,12 @@
// Reloads the redfish authorizer with the given configuration path.
void ReloadRedfishAuthorizer(const std::string& configuration_path);
+ void RegisterAnycastUser(
+ const std::string& service,
+ platforms_syshealth::collection::feed::AnycastUser* user);
+
+ void DeregisterAnycastUser(const std::string& service);
+
static ecclesia::Operation BoostVerbToOperation(
boost::beast::http::verb verb);
diff --git a/redfish_authorization/meson.build b/redfish_authorization/meson.build
index 43d4495..be5bb26 100644
--- a/redfish_authorization/meson.build
+++ b/redfish_authorization/meson.build
@@ -127,6 +127,7 @@
one_dep,
openssl,
zatar_dep,
+ tlbmc_lib_dep,
]
grpc_redfish_include = include_directories('.')
diff --git a/redfish_authorization/redfish_authorizer.cc b/redfish_authorization/redfish_authorizer.cc
index a483620..8a78e33 100644
--- a/redfish_authorization/redfish_authorizer.cc
+++ b/redfish_authorization/redfish_authorizer.cc
@@ -218,6 +218,10 @@
authz_configuration_.ReloadConfig(configuration_json,
platform_configuration_json);
+ for (const auto& [service, user] : anycast_users_) {
+ user->SetAnycastAddress(authz_configuration_.GetAnycastAddress(service));
+ }
+
std::string base_privilege_registry_path =
FindBasePrivilegeRegistryPath(configuration_json);
diff --git a/redfish_authorization/redfish_authorizer.h b/redfish_authorization/redfish_authorizer.h
index 64cbb19..cbad0ec 100644
--- a/redfish_authorization/redfish_authorizer.h
+++ b/redfish_authorization/redfish_authorizer.h
@@ -10,8 +10,10 @@
#include <unordered_set>
#include <vector>
+#include "tlbmc/feed_client_interface.h"
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
+#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/synchronization/mutex.h"
#include "authorizer_enums.h"
@@ -151,6 +153,26 @@
return redfish_entity_trie_.GetNodeIndexInPatternArray(uri);
}
+ void RegisterAnycastUser(
+ const std::string& service,
+ platforms_syshealth::collection::feed::AnycastUser* user) {
+ auto it = anycast_users_.find(service);
+ if (it != anycast_users_.end()) {
+ LOG(WARNING) << "Anycast user " << service << " already registered.";
+ return;
+ }
+ anycast_users_[service] = user;
+ }
+
+ void DeregisterAnycastUser(const std::string& service) {
+ auto it = anycast_users_.find(service);
+ if (it == anycast_users_.end()) {
+ LOG(WARNING) << "Anycast user " << service << " not found.";
+ return;
+ }
+ anycast_users_.erase(it);
+ }
+
// TODO(nanzhou): add property override support.
protected:
absl::flat_hash_map<ecclesia::Operation, std::vector<RedfishPrivileges>>
@@ -215,6 +237,10 @@
OverrideMappings override_mappings_ ABSL_GUARDED_BY(mutex_);
SubscriptionTracker subscription_tracker_;
+
+ absl::flat_hash_map<std::string,
+ platforms_syshealth::collection::feed::AnycastUser*>
+ anycast_users_;
};
} // namespace milotic::authz
diff --git a/tlbmc/feed_client_interface.h b/tlbmc/feed_client_interface.h
index a1c3d55..da5aff6 100644
--- a/tlbmc/feed_client_interface.h
+++ b/tlbmc/feed_client_interface.h
@@ -2,6 +2,8 @@
#ifndef PLATFORMS_SYSHEALTH_COLLECTION_FEED_FORWARD_CLIENT_LIB_FEED_CLIENT_INTERFACE_H_
#define PLATFORMS_SYSHEALTH_COLLECTION_FEED_FORWARD_CLIENT_LIB_FEED_CLIENT_INTERFACE_H_
+#include <memory>
+
#include "tlbmc/agent_config_service.pb.h"
#include "tlbmc/data_sink_service.pb.h"
#include "absl/status/statusor.h"
@@ -29,6 +31,29 @@
virtual bool IsDryRun() const = 0;
};
+class AnycastUser {
+ public:
+ virtual ~AnycastUser() = default;
+ virtual void SetAnycastAddress(absl::string_view anycast_address) = 0;
+};
+
+class FeedClientAnycastUser : public AnycastUser {
+ public:
+ explicit FeedClientAnycastUser(
+ std::shared_ptr<FeedClientInterface> feed_client)
+ : feed_client_(feed_client) {}
+
+ void SetAnycastAddress(absl::string_view anycast_address) override {
+ if (feed_client_ == nullptr) {
+ return;
+ }
+ feed_client_->SetTargetAddress(anycast_address);
+ }
+
+ private:
+ std::shared_ptr<FeedClientInterface> feed_client_;
+};
+
} // namespace platforms_syshealth::collection::feed
#endif // PLATFORMS_SYSHEALTH_COLLECTION_FEED_FORWARD_CLIENT_LIB_FEED_CLIENT_INTERFACE_H_