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

api: Prevent downgrade operations to be done automatically #389

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ option(BUILD_TUFCTL "Set to ON to build sample tuf control application" OFF)
option(BUILD_P11 "Support for key storage in a HSM via PKCS#11" ON)
option(USE_COMPOSEAPP_ENGINE "Set to ON to build the app engine based on the composeapp utility" ON)
option(BUILD_WITH_CODE_COVERAGE_AKLITE "Enable gcov code coverage" OFF)
option(ACCEPT_LOWER_VERSION "By default, should a version lower than the current one be accepted as a valid update" OFF)

# If we build the sota tools we don't need aklite (???) and vice versa
# if we build aklite we don't need the sota tools
Expand Down Expand Up @@ -86,3 +87,4 @@ message(STATUS "BUILD_AKLITE_OFFLINE: ${BUILD_AKLITE_OFFLINE}")
message(STATUS "BUILD_TUFCTL: ${BUILD_TUFCTL}")
message(STATUS "BUILD_P11: ${BUILD_P11}")
message(STATUS "USE_COMPOSEAPP_ENGINE: ${USE_COMPOSEAPP_ENGINE}")
message(STATUS "ACCEPT_LOWER_VERSION: ${ACCEPT_LOWER_VERSION}")
5 changes: 3 additions & 2 deletions apps/aklite-offline/cmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ int InstallCmd::installUpdate(const po::variables_map& vm, const boost::filesyst
const LocalUpdateSource local_update_source{.tuf_repo = (src_dir / "tuf").string(),
.ostree_repo = (src_dir / "ostree_repo").string(),
.app_store = (src_dir / "apps").string()};
auto ret_code{
aklite::cli::Install(client, -1, target_name, InstallMode::OstreeOnly, force_downgrade, &local_update_source)};
auto ret_code{aklite::cli::Install(client, -1, target_name, InstallMode::OstreeOnly, force_downgrade,
&local_update_source, aklite::cli::PullMode::All, aklite::cli::CheckMode::Update,
true)};
switch (ret_code) {
case aklite::cli::StatusCode::InstallAppsNeedFinalization: {
std::cout << "Please run `aklite-offline run` command to start the updated Apps\n";
Expand Down
2 changes: 1 addition & 1 deletion dev-flow.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CXX ?= clang++
CC ?= clang
GTEST_FILTER ?= "*"
PKCS11_ENGINE_PATH ?= "/usr/lib/x86_64-linux-gnu/engines-3/pkcs11.so"
EXTRA_CMAKE_CONFIG_ARGS ?= -DUSE_COMPOSEAPP_ENGINE=ON -DBUILD_AKLITE_OFFLINE=ON
EXTRA_CMAKE_CONFIG_ARGS ?= -DUSE_COMPOSEAPP_ENGINE=ON -DBUILD_AKLITE_OFFLINE=ON -DACCEPT_LOWER_VERSION=OFF

all: config build

Expand Down
11 changes: 10 additions & 1 deletion include/aktualizr-lite/aklite_client_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ class GetTargetToInstallResult {
std::string reason;
};

/* Should aklite target selection mechanism by default accept a version lower than the current as a valid update */
#ifdef ACCEPT_LOWER_VERSION
#warning Allowing automatic downgrade in aktualizr-lite daemon
#define AKLITE_ACCEPT_LOWER_VER_DEFAULT true
#else
#define AKLITE_ACCEPT_LOWER_VER_DEFAULT false
#endif

/**
* @brief contains additional methods that consolidate functionality
* making it reusable between the main aklite daemon and other tools.
Expand Down Expand Up @@ -79,7 +87,8 @@ class AkliteClientExt : public AkliteClient {

GetTargetToInstallResult GetTargetToInstall(const CheckInResult &checkin_res, int version = -1,
const std::string &target_name = "", bool allow_bad_target = false,
bool force_apps_sync = false, bool offline_mode = false);
bool force_apps_sync = false, bool offline_mode = false,
bool accept_lower_ver = AKLITE_ACCEPT_LOWER_VER_DEFAULT);
InstallResult PullAndInstall(const TufTarget &target, const std::string &reason = "",
const std::string &correlation_id = "", InstallMode install_mode = InstallMode::All,
const LocalUpdateSource *local_update_source = nullptr, bool do_download = true,
Expand Down
4 changes: 2 additions & 2 deletions include/aktualizr-lite/cli/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ StatusCode CheckIn(AkliteClientExt &client, const LocalUpdateSource *local_updat

StatusCode Pull(AkliteClientExt &client, int version = -1, const std::string &target_name = "",
bool force_downgrade = true, const LocalUpdateSource *local_update_source = nullptr,
CheckMode check_mode = CheckMode::Update);
CheckMode check_mode = CheckMode::Update, bool accept_lower_ver = AKLITE_ACCEPT_LOWER_VER_DEFAULT);

StatusCode Install(AkliteClientExt &client, int version = -1, const std::string &target_name = "",
InstallMode install_mode = InstallMode::All, bool force_downgrade = true,
const LocalUpdateSource *local_update_source = nullptr, PullMode pull_mode = PullMode::All,
CheckMode check_mode = CheckMode::Update);
CheckMode check_mode = CheckMode::Update, bool accept_lower_ver = AKLITE_ACCEPT_LOWER_VER_DEFAULT);

StatusCode CompleteInstall(AkliteClient &client);

Expand Down
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ if(BUILD_P11)
add_definitions(-DBUILD_P11)
endif(BUILD_P11)

if(ACCEPT_LOWER_VERSION)
add_definitions(-DACCEPT_LOWER_VERSION)
endif(ACCEPT_LOWER_VERSION)

target_compile_definitions(${TARGET_EXE} PRIVATE BOOST_LOG_DYN_LINK)

set(INCS
Expand Down
15 changes: 14 additions & 1 deletion src/aklite_client_ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
// apps
GetTargetToInstallResult AkliteClientExt::GetTargetToInstall(const CheckInResult& checkin_res, int version,
const std::string& target_name, bool allow_bad_target,
bool force_apps_sync, bool is_offline_mode) {
bool force_apps_sync, bool is_offline_mode,
bool accept_lower_ver) {
client_->setAppsNotChecked();

std::string err;
Expand All @@ -55,6 +56,18 @@ GetTargetToInstallResult AkliteClientExt::GetTargetToInstall(const CheckInResult
}

const auto current = GetCurrent();
// It may occur that the TUF targets list only has versions lower than the current one.
// The `accept_lower_ver` parameter controls what to do in such situation: Should a version lower than the current
// one be accepted as a valid selected target for installation or not
if (!accept_lower_ver && version == -1 && target_name.empty() && candidate_target.Version() < current.Version()) {
if (!invoke_post_cb_at_checkin_) {
client_->notifyTufUpdateFinished(err);
}
LOG_INFO << "Preventing selection of a downgrade target. Current: " << current.Version()
<< " candidate: " << candidate_target.Version();
return {GetTargetToInstallResult::Status::NoUpdate, TufTarget(), ""};
}

if (IsRollback(current) && current.Name() == candidate_target.Name()) {
// Handle the case when Apps failed to start on boot just after an update.
// This is only possible with `pacman.create_containers_before_reboot = 0`.
Expand Down
14 changes: 8 additions & 6 deletions src/cli/cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ StatusCode CheckIn(AkliteClientExt &client, const LocalUpdateSource *local_updat
static StatusCode pullAndInstall(AkliteClientExt &client, int version, const std::string &target_name,
InstallMode install_mode, bool force_downgrade,
const LocalUpdateSource *local_update_source, PullMode pull_mode, bool do_install,
CheckMode check_mode) {
CheckMode check_mode, bool accept_lower_ver) {
// Check if the device is in a correct state to start a new update
if (client.IsInstallationInProgress()) {
LOG_ERROR << "Cannot start Target installation since there is ongoing installation; target: "
Expand All @@ -262,7 +262,8 @@ static StatusCode pullAndInstall(AkliteClientExt &client, int version, const std
return res2StatusCode<CheckInResult::Status>(c2s, ci_res.status);
}

auto gti_res = client.GetTargetToInstall(ci_res, version, target_name, true, true, local_update_source != nullptr);
auto gti_res = client.GetTargetToInstall(ci_res, version, target_name, true, true, local_update_source != nullptr,
accept_lower_ver);

//
if (gti_res.selected_target.IsUnknown()) {
Expand Down Expand Up @@ -293,6 +294,7 @@ static StatusCode pullAndInstall(AkliteClientExt &client, int version, const std
LOG_WARNING << "Found TUF Target is lower version than the current on; "
<< "current: " << current.Version() << ", found Target: " << gti_res.selected_target.Version();

// force_downgrade = false is only used by aklite-offline tool
if (!force_downgrade) {
LOG_ERROR << "Downgrade is not allowed by default, re-run the command with `--force` option to force downgrade";
return SC::InstallDowngradeAttempt;
Expand All @@ -307,16 +309,16 @@ static StatusCode pullAndInstall(AkliteClientExt &client, int version, const std
}

StatusCode Pull(AkliteClientExt &client, int version, const std::string &target_name, bool force_downgrade,
const LocalUpdateSource *local_update_source, CheckMode check_mode) {
const LocalUpdateSource *local_update_source, CheckMode check_mode, bool accept_lower_ver) {
return pullAndInstall(client, version, target_name, InstallMode::All, force_downgrade, local_update_source,
PullMode::All, false, check_mode);
PullMode::All, false, check_mode, accept_lower_ver);
}

StatusCode Install(AkliteClientExt &client, int version, const std::string &target_name, InstallMode install_mode,
bool force_downgrade, const LocalUpdateSource *local_update_source, PullMode pull_mode,
CheckMode check_mode) {
CheckMode check_mode, bool accept_lower_ver) {
return pullAndInstall(client, version, target_name, install_mode, force_downgrade, local_update_source, pull_mode,
true, check_mode);
true, check_mode, accept_lower_ver);
}

StatusCode CompleteInstall(AkliteClient &client) {
Expand Down