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

[POC] redpanda: verify enterprise license on upgrade #23327

Closed
wants to merge 5 commits into from
Closed
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
60 changes: 60 additions & 0 deletions src/v/cluster/feature_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

#include <absl/algorithm/container.h>

#include <stdexcept>

namespace cluster {

static constexpr std::chrono::seconds status_retry = 5s;
Expand Down Expand Up @@ -288,7 +290,65 @@ ss::future<> feature_manager::maybe_log_license_check_info() {
}
}

bool feature_manager::need_to_verify_enterprise_license() {
return features::is_major_version_upgrade(
_feature_table.local().get_active_version(),
_feature_table.local().get_latest_logical_version());
}

void feature_manager::verify_enterprise_license() {
vlog(clusterlog.info, "Verifying enterprise license...");

if (!need_to_verify_enterprise_license()) {
vlog(clusterlog.info, "Enterprise license verification skipped...");
_verified_enterprise_license = true;
return;
}

const auto& license = _feature_table.local().get_license();
auto license_missing_or_expired = !license || license->is_expired();
auto enterprise_features_used = license_required_feature_enabled();

vlog(
clusterlog.info,
"Verifying enterprise license: active_version={}, latest_version={}, "
"enterprise_features_used={}, license_missing_or_expired={}",
_feature_table.local().get_active_version(),
_feature_table.local().get_latest_logical_version(),
enterprise_features_used,
license_missing_or_expired);

if (enterprise_features_used && license_missing_or_expired) {
throw std::runtime_error{
"Looks like you’ve enabled a Redpanda Enterprise feature(s) "
"without a valid license. Please enter an active Redpanda "
"license key (e.g. rpk cluster license set <key>). If you "
"don’t have one, please request a new/trial license at "
"https://redpanda.com/license-request"};
}

_verified_enterprise_license = true;
}

ss::future<> feature_manager::maybe_update_feature_table() {
// Before doing any feature enablement or active version update, check that
// the cluster has an enterprise license if they use enterprise features
// It's possible that on ::start() the controller log hasn't synced yet, so
// check this every time we're about to update the active version to ensure
// that we abort before the update
if (need_to_verify_enterprise_license() && !_verified_enterprise_license) {
vlog(
clusterlog.debug,
"Waiting for enterprise license to be verified before checking for "
"active version updates...");
try {
co_await ss::sleep_abortable(status_retry, _as.local());
} catch (const ss::sleep_aborted&) {
// Shutting down - next iteration will drop out
}
co_return;
}

vlog(clusterlog.debug, "Checking for active version update...");
bool failed = false;
try {
Expand Down
5 changes: 5 additions & 0 deletions src/v/cluster/feature_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ class feature_manager {
ss::future<std::error_code> update_license(security::license&& license);

features::enterprise_feature_report report_enterprise_features() const;
bool need_to_verify_enterprise_license();
void verify_enterprise_license();

private:
void update_node_version(model::node_id, cluster_version v);
Expand Down Expand Up @@ -199,6 +201,9 @@ class feature_manager {
// Keep track of whether this node is the controller leader
// via leadership notifications
bool _am_controller_leader{false};

// Blocks cluster upgrades until the enterprise license has been verified
bool _verified_enterprise_license{false};
};

} // namespace cluster
28 changes: 9 additions & 19 deletions src/v/features/feature_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,29 +154,19 @@ std::string_view to_string_view(feature_state::state s) {

// The version that this redpanda node will report: increment this
// on protocol changes to raft0 structures, like adding new services.
//
// For your convenience, a rough guide to the history of how logical
// versions mapped to redpanda release versions:
// 22.1.1 -> 3 (22.1.5 was version 4)
// 22.2.1 -> 5 (22.2.6 later proceeds to version 6)
// 22.3.1 -> 7 (22.3.6 later proceeds to verison 8)
// 23.1.1 -> 9
// 23.2.1 -> 10
// 23.3.1 -> 11
// 24.1.1 -> 12
// 24.2.1 -> 13
// 24.3.1 -> 14
//
// Although some previous stable branches have included feature version
// bumps, this is _not_ the intended usage, as stable branches are
// meant to be safely downgradable within the branch, and new features
// imply that new data formats may be written.
static constexpr cluster_version latest_version = cluster_version{14};
static constexpr cluster_version latest_version = to_cluster_version(
release_version::MAX);

// The earliest version we can upgrade from. This is the version that
// a freshly initialized node will start at. All features up to this cluster
// version will automatically be enabled when Redpanda starts.
static constexpr cluster_version earliest_version = cluster_version{11};
static constexpr cluster_version earliest_version = to_cluster_version(
release_version::v23_3_1);

static_assert(
latest_version - earliest_version == 3L,
"Consider upgrading the earliest_version in lockstep whenever you increment "
"the latest_version");

// Extra features that will be wired into the feature table if a special
// environment variable is set
Expand Down
Loading