Skip to content

Commit d9cfc51

Browse files
committed
[PLAT-18873]: Allow non-restart upgrade for certs rotate.
Summary: Allowed non-restart upgrade for certs rotate for VM based universe. Test Plan: Tested manually Reviewers: anabaria, #yba-api-review! Reviewed By: anabaria Subscribers: yugaware Differential Revision: https://phorge.dev.yugabyte.com/D48192
1 parent 635a95e commit d9cfc51

File tree

2 files changed

+68
-8
lines changed

2 files changed

+68
-8
lines changed

managed/src/main/java/com/yugabyte/yw/commissioner/tasks/upgrade/CertsRotate.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ public void run() {
100100
// For rootCA root certificate rotation, we would need to do it in three rounds
101101
// so that node to node communications are not disturbed during the upgrade.
102102
// For other cases we can do it in one round by updating respective certs.
103-
if (taskParams().upgradeOption == UpgradeOption.ROLLING_UPGRADE
103+
// This 3-round process works for both ROLLING_UPGRADE and NON_RESTART_UPGRADE.
104+
if ((taskParams().upgradeOption == UpgradeOption.ROLLING_UPGRADE
105+
|| taskParams().upgradeOption == UpgradeOption.NON_RESTART_UPGRADE)
104106
&& taskParams().rootCARotationType == CertRotationType.RootCert) {
105107
// Update the rootCA in platform to generate a multi-cert containing both old cert and
106108
// new cert. If it is already a multi-cert or the root CA of the universe is already
@@ -111,14 +113,14 @@ && taskParams().rootCARotationType == CertRotationType.RootCert) {
111113
createCertUpdateTasks(allNodes, CertRotateAction.APPEND_NEW_ROOT_CERT);
112114

113115
// Add task to use the updated certs
114-
createActivateCertsTask(universe, nodes, UpgradeOption.ROLLING_UPGRADE, false);
116+
createActivateCertsTask(universe, nodes, taskParams().upgradeOption, false);
115117

116118
// Copy new server certs to all nodes. This deletes the old certs and uploads the new
117119
// files to the same location.
118120
createCertUpdateTasks(allNodes, CertRotateAction.ROTATE_CERTS);
119121

120122
// Add task to use the updated certs.
121-
createActivateCertsTask(getUniverse(), nodes, UpgradeOption.ROLLING_UPGRADE, false);
123+
createActivateCertsTask(getUniverse(), nodes, taskParams().upgradeOption, false);
122124

123125
// Remove old root cert from the ca.crt by replacing (moving) the old cert with the new
124126
// one.
@@ -137,7 +139,7 @@ && taskParams().rootCARotationType == CertRotationType.RootCert) {
137139

138140
// Add task to use the updated certs.
139141
createActivateCertsTask(
140-
getUniverse(), nodes, UpgradeOption.ROLLING_UPGRADE, taskParams().isYbcInstalled());
142+
getUniverse(), nodes, taskParams().upgradeOption, taskParams().isYbcInstalled());
141143

142144
} else {
143145
// Update the rootCA in platform to have both old cert and new cert.
@@ -243,12 +245,16 @@ private void createActivateCertsTask(
243245
UpgradeOption upgradeOption,
244246
boolean ybcInstalled) {
245247

246-
boolean n2nCertExpired = CertificateHelper.checkNode2NodeCertsExpiry(universe);
247-
if (isCertReloadable(universe) && !n2nCertExpired) {
248+
boolean canReloadCert =
249+
isCertReloadable(universe) && !CertificateHelper.checkNode2NodeCertsExpiry(universe);
250+
if (taskParams().upgradeOption == UpgradeOption.NON_RESTART_UPGRADE) {
251+
if (!canReloadCert) {
252+
throw new RuntimeException(
253+
"Node-to-node certificates are expired, only non-rolling upgrade is supported");
254+
}
248255
// cert reload can be performed.
249256
log.info("adding cert rotate via reload task ...");
250257
createCertReloadTask(nodes, universe.getUniverseUUID(), getUserTaskUUID());
251-
252258
} else {
253259
// Do a restart to rotate certificate.
254260
log.info("adding a cert rotate via restart task ...");

managed/src/main/java/com/yugabyte/yw/forms/CertsRotateParams.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import com.yugabyte.yw.common.certmgmt.CertConfigType;
1414
import com.yugabyte.yw.common.certmgmt.CertificateHelper;
1515
import com.yugabyte.yw.common.certmgmt.EncryptionInTransitUtil;
16+
import com.yugabyte.yw.common.config.GlobalConfKeys;
17+
import com.yugabyte.yw.common.config.RuntimeConfGetter;
18+
import com.yugabyte.yw.common.inject.StaticInjectorHolder;
1619
import com.yugabyte.yw.models.CertificateInfo;
1720
import com.yugabyte.yw.models.Universe;
1821
import com.yugabyte.yw.models.helpers.CommonUtils;
@@ -81,6 +84,56 @@ private void verifyCertificateValidity(Universe universe) {
8184
}
8285
}
8386

87+
private void verifyNonRestartUpgradeSupport(Universe universe) {
88+
UserIntent userIntent = universe.getUniverseDetails().getPrimaryCluster().userIntent;
89+
String softwareVersion = userIntent.ybSoftwareVersion;
90+
91+
// Check if YB version supports cert reload (>= 2.14.0.0-b1)
92+
if (Util.compareYbVersions(softwareVersion, "2.14.0.0-b1", true) < 0) {
93+
throw new PlatformServiceException(
94+
Status.BAD_REQUEST,
95+
"Non-restart certificate rotation is not supported for universe with software version: "
96+
+ softwareVersion
97+
+ ". Minimum required version is 2.14.0.0-b1.");
98+
}
99+
100+
// Check if cert reload feature flag is enabled
101+
if (runtimeConfGetter == null) {
102+
runtimeConfGetter = StaticInjectorHolder.injector().instanceOf(RuntimeConfGetter.class);
103+
}
104+
boolean featureFlagEnabled = runtimeConfGetter.getGlobalConf(GlobalConfKeys.enableCertReload);
105+
if (!featureFlagEnabled) {
106+
throw new PlatformServiceException(
107+
Status.BAD_REQUEST,
108+
"Non-restart certificate rotation requires the cert reload feature to be enabled. "
109+
+ "Please enable the feature flag 'yb.features.cert_reload.enabled' and retry.");
110+
}
111+
112+
// Check if universe is configured for cert reload
113+
boolean universeConfigured =
114+
Boolean.parseBoolean(
115+
universe
116+
.getConfig()
117+
.getOrDefault(Universe.KEY_CERT_HOT_RELOADABLE, Boolean.FALSE.toString()));
118+
if (!universeConfigured) {
119+
throw new PlatformServiceException(
120+
Status.BAD_REQUEST,
121+
"Non-restart certificate rotation requires the universe to be configured for cert "
122+
+ "reload. The universe will be automatically configured during the first cert "
123+
+ "rotation, but for non-restart upgrades, it must be configured beforehand. "
124+
+ "Please perform a rolling cert rotation first to configure the universe.");
125+
}
126+
127+
// Check if node-to-node certs are expired (non-restart upgrade cannot proceed if expired)
128+
boolean n2nCertExpired = CertificateHelper.checkNode2NodeCertsExpiry(universe);
129+
if (n2nCertExpired) {
130+
throw new PlatformServiceException(
131+
Status.BAD_REQUEST,
132+
"Non-restart certificate rotation cannot be performed when node-to-node certificates "
133+
+ "have expired. Please use rolling or non-rolling upgrade option instead.");
134+
}
135+
}
136+
84137
private void commonValidation(Universe universe) {
85138
UniverseDefinitionTaskParams universeDetails = universe.getUniverseDetails();
86139
UserIntent userIntent = universeDetails.getPrimaryCluster().userIntent;
@@ -113,8 +166,9 @@ private void verifyParamsForNormalUpgrade(Universe universe, boolean isFirstTry)
113166
UUID currentRootCA = universeDetails.rootCA;
114167
UUID currentClientRootCA = universeDetails.clientRootCA;
115168

169+
// Validate non-restart upgrade option for non-Kubernetes universes
116170
if (upgradeOption == UpgradeOption.NON_RESTART_UPGRADE) {
117-
throw new PlatformServiceException(Status.BAD_REQUEST, "Cert upgrade cannot be non restart.");
171+
verifyNonRestartUpgradeSupport(universe);
118172
}
119173

120174
// Make sure rootCA and clientRootCA respects the rootAndClientRootCASame property

0 commit comments

Comments
 (0)