From 9d1d579c41137de0328f3a7b2b5de1f406643c1d Mon Sep 17 00:00:00 2001 From: John Olav Lund Date: Wed, 18 Dec 2024 09:26:20 +0100 Subject: [PATCH] fix: Clear the inventory data hash on re-authentication This fixes the case where e.g. a third party tool re-authenticates by using the D-Bus API while mender-update is waiting for the next poll interval to expire. The inventory will now be resubmitted when the poll triggers. Ticket: MEN-7873 Changelog: Title Signed-off-by: John Olav Lund --- src/api/auth.hpp | 11 ++++++++-- src/api/auth/auth.cpp | 5 +++-- src/api/client.cpp | 1 - src/api/client.hpp | 9 -------- src/mender-update/daemon/context.hpp | 3 --- .../daemon/state_machine/state_machine.cpp | 8 ++++++- src/mender-update/daemon/states.cpp | 21 +++---------------- src/mender-update/inventory.hpp | 2 ++ 8 files changed, 24 insertions(+), 36 deletions(-) diff --git a/src/api/auth.hpp b/src/api/auth.hpp index ebd0d4f2a..a1d48c27a 100644 --- a/src/api/auth.hpp +++ b/src/api/auth.hpp @@ -68,6 +68,7 @@ struct AuthData { using ExpectedAuthData = expected::expected; using AuthenticatedAction = function; +using ReAuthenticatedAction = function; class Authenticator { public: @@ -78,9 +79,15 @@ class Authenticator { } void ExpireToken(); - error::Error WithToken(AuthenticatedAction action); + // Register a callback to be called on re-authentication. Will overwrite the + // stored callback with the new one. + void RegisterTokenReceivedCallback(ReAuthenticatedAction action) { + action_ = action; + } + + protected: enum class NoTokenAction { Finish, @@ -97,11 +104,11 @@ class Authenticator { void HandleReceivedToken(common::ExpectedStringPair ex_auth_dbus_data, NoTokenAction no_token); events::EventLoop &loop_; - bool token_fetch_in_progress_ = false; vector pending_actions_; chrono::seconds auth_timeout_; events::Timer auth_timeout_timer_; + ReAuthenticatedAction action_ {nullptr}; }; #ifdef MENDER_USE_DBUS diff --git a/src/api/auth/auth.cpp b/src/api/auth/auth.cpp index 1ff8a70e6..0399c5f49 100644 --- a/src/api/auth/auth.cpp +++ b/src/api/auth/auth.cpp @@ -80,7 +80,6 @@ error::Error Authenticator::WithToken(AuthenticatedAction action) { } // else record that token is already being fetched (by GetJwtToken()). token_fetch_in_progress_ = true; - return error::NoError; } @@ -151,7 +150,9 @@ void Authenticator::HandleReceivedToken( return; } } - + if (no_token == NoTokenAction::Finish && action_ != nullptr) { + action_(); + } PostPendingActions(ex_auth_data); } diff --git a/src/api/client.cpp b/src/api/client.cpp index b6ff747af..170764857 100644 --- a/src/api/client.cpp +++ b/src/api/client.cpp @@ -87,7 +87,6 @@ error::Error HTTPClient::AsyncCall( }); return; } - reauthenticated_ = true; }; return authenticator_.WithToken( diff --git a/src/api/client.hpp b/src/api/client.hpp index f626ee052..d44191c18 100644 --- a/src/api/client.hpp +++ b/src/api/client.hpp @@ -79,19 +79,10 @@ class HTTPClient : public Client { authenticator_.ExpireToken(); } - bool HasReauthenticated() { - return reauthenticated_; - } - - void SetReauthenticated(bool reauthenticated) { - reauthenticated_ = reauthenticated; - } - private: events::EventLoop &event_loop_; http::Client http_client_; auth::Authenticator &authenticator_; - bool reauthenticated_ {false}; }; } // namespace api diff --git a/src/mender-update/daemon/context.hpp b/src/mender-update/daemon/context.hpp index e995a6192..a32b1a927 100644 --- a/src/mender-update/daemon/context.hpp +++ b/src/mender-update/daemon/context.hpp @@ -166,7 +166,6 @@ class Context { mender::auth::api::auth::AuthenticatorHttp authenticator; #endif -public: // For polling, and for making status updates. api::HTTPClient http_client; // For the artifact download. @@ -175,8 +174,6 @@ class Context { shared_ptr deployment_client; shared_ptr inventory_client; - bool has_submitted_inventory {false}; - struct { unique_ptr state_data; io::ReaderPtr artifact_reader; diff --git a/src/mender-update/daemon/state_machine/state_machine.cpp b/src/mender-update/daemon/state_machine/state_machine.cpp index 03900bf35..731d4b8f7 100644 --- a/src/mender-update/daemon/state_machine/state_machine.cpp +++ b/src/mender-update/daemon/state_machine/state_machine.cpp @@ -68,8 +68,14 @@ StateMachine::StateMachine(Context &ctx, events::EventLoop &event_loop) : runner_(ctx) { runner_.AddStateMachine(deployment_tracking_.states_); runner_.AddStateMachine(main_states_); - runner_.AttachToEventLoop(event_loop_); + ctx.authenticator.RegisterTokenReceivedCallback([&ctx]() { + if (ctx.inventory_client->has_submitted_inventory) { + log::Debug("Client has re-authenticated - clear inventory data cache"); + ctx.inventory_client->ClearDataCache(); + ctx.inventory_client->has_submitted_inventory = false; + } + }); using se = StateEvent; using tf = sm::TransitionFlag; diff --git a/src/mender-update/daemon/states.cpp b/src/mender-update/daemon/states.cpp index 016e6740d..a3e5a3676 100644 --- a/src/mender-update/daemon/states.cpp +++ b/src/mender-update/daemon/states.cpp @@ -157,7 +157,7 @@ void SubmitInventoryState::DoSubmitInventory(Context &ctx, sm::EventPosterhas_submitted_inventory = true; poster.PostEvent(StateEvent::Success); }; @@ -261,16 +261,7 @@ void PollForDeploymentState::OnEnter(Context &ctx, sm::EventPoster & [this, &ctx, &poster](mender::update::deployments::CheckUpdatesAPIResponse response) { if (!response) { log::Error("Error while polling for deployment: " + response.error().String()); - - // When unauthenticated, - // invalidate the cached inventory data so that it can be sent again - // and set clear the context flag so that it is triggered on re-authorization - if (response.error().code == auth::MakeError(auth::UnauthorizedError, "").code) { - if (ctx.has_submitted_inventory) { - ctx.inventory_client->ClearDataCache(); - ctx.has_submitted_inventory = false; - } - } else { + if (response.error().code != auth::MakeError(auth::UnauthorizedError, "").code) { // Replace the update poll timer with a backoff HandlePollingError(ctx, poster); } @@ -279,13 +270,7 @@ void PollForDeploymentState::OnEnter(Context &ctx, sm::EventPoster & } else if (!response.value()) { log::Info("No update available"); poster.PostEvent(StateEvent::NothingToDo); - if (ctx.http_client.HasReauthenticated()) { - log::Debug("Client has reauthenticated, clear inventory data cache"); - ctx.inventory_client->ClearDataCache(); - ctx.has_submitted_inventory = false; - ctx.http_client.SetReauthenticated(false); - } - if (not ctx.has_submitted_inventory) { + if (not ctx.inventory_client->has_submitted_inventory) { // If we have not submitted inventory successfully at least // once, schedule this after receiving a successful response // with no update. This enables inventory to be submitted diff --git a/src/mender-update/inventory.hpp b/src/mender-update/inventory.hpp index 7c4fecbd5..defbba9d7 100644 --- a/src/mender-update/inventory.hpp +++ b/src/mender-update/inventory.hpp @@ -72,6 +72,8 @@ class InventoryAPI { APIResponseHandler api_handler) = 0; virtual void ClearDataCache() = 0; + + bool has_submitted_inventory {false}; }; class InventoryClient : public InventoryAPI {