Make Upgrade API license aware (elastic/x-pack-elasticsearch#1401)

Upgrade API should only work with non-trial licenses

Relates to elastic/x-pack-elasticsearch#1214

Original commit: elastic/x-pack-elasticsearch@28fef0feeb
This commit is contained in:
Igor Motov 2017-05-12 17:14:02 -04:00
parent bb034f42b8
commit ad6b86481e
6 changed files with 115 additions and 7 deletions

View File

@ -54,6 +54,9 @@ public class XPackLicenseState {
messages.put(XPackPlugin.DEPRECATION, new String[] {
"Deprecation APIs are disabled"
});
messages.put(XPackPlugin.UPGRADE, new String[] {
"Upgrade API is disabled"
});
EXPIRATION_MESSAGES = Collections.unmodifiableMap(messages);
}
@ -457,4 +460,25 @@ public class XPackLicenseState {
public boolean isDeprecationAllowed() {
return status.active;
}
/**
* Determine if Upgrade API should be enabled.
* <p>
* Upgrade API is not available in for all license types except {@link OperationMode#TRIAL}
*
* @return {@code true} as long as the license is valid. Otherwise
* {@code false}.
*/
public boolean isUpgradeAllowed() {
// status is volatile
Status localStatus = status;
OperationMode operationMode = localStatus.mode;
boolean licensed = operationMode == OperationMode.BASIC || operationMode == OperationMode.STANDARD ||
operationMode == OperationMode.GOLD || operationMode == OperationMode.PLATINUM;
return licensed && localStatus.active;
}
}

View File

@ -150,6 +150,9 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
/** Name constant for the Deprecation API feature. */
public static final String DEPRECATION = "deprecation";
/** Name constant for the upgrade feature. */
public static final String UPGRADE = "upgrade";
// inside of YAML settings we still use xpack do not having handle issues with dashes
private static final String SETTINGS_NAME = "xpack";

View File

@ -27,8 +27,11 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.upgrade.IndexUpgradeService;
import org.elasticsearch.xpack.upgrade.UpgradeActionRequired;
@ -234,15 +237,19 @@ public class IndexUpgradeInfoAction extends Action<IndexUpgradeInfoAction.Reques
public static class TransportAction extends TransportMasterNodeReadAction<Request, Response> {
private final IndexUpgradeService indexUpgradeService;
private final XPackLicenseState licenseState;
@Inject
public TransportAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexUpgradeService indexUpgradeService,
IndexNameExpressionResolver indexNameExpressionResolver) {
IndexNameExpressionResolver indexNameExpressionResolver,
XPackLicenseState licenseState) {
super(settings, IndexUpgradeInfoAction.NAME, transportService, clusterService, threadPool, actionFilters,
indexNameExpressionResolver, Request::new);
this.indexUpgradeService = indexUpgradeService;
this.licenseState = licenseState;
}
@Override
@ -263,9 +270,13 @@ public class IndexUpgradeInfoAction extends Action<IndexUpgradeInfoAction.Reques
@Override
protected final void masterOperation(final Request request, ClusterState state, final ActionListener<Response> listener) {
Map<String, UpgradeActionRequired> results =
indexUpgradeService.upgradeInfo(request.indices(), request.indicesOptions(), request.extraParams(), state);
listener.onResponse(new Response(results));
if (licenseState.isUpgradeAllowed()) {
Map<String, UpgradeActionRequired> results =
indexUpgradeService.upgradeInfo(request.indices(), request.indicesOptions(), request.extraParams(), state);
listener.onResponse(new Response(results));
} else {
listener.onFailure(LicenseUtils.newComplianceException(XPackPlugin.UPGRADE));
}
}
}
}

View File

@ -75,6 +75,10 @@ public abstract class AbstractLicensesIntegrationTestCase extends ESIntegTestCas
latch.await();
}
protected void putLicenseTombstone() throws InterruptedException {
putLicense(LicensesMetaData.LICENSE_TOMBSTONE);
}
protected void wipeAllLicenses() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
ClusterService clusterService = internalCluster().getInstance(ClusterService.class, internalCluster().getMasterName());

View File

@ -5,24 +5,35 @@
*/
package org.elasticsearch.xpack.upgrade;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.AbstractLicensesIntegrationTestCase;
import org.elasticsearch.license.License;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.ml.MachineLearning;
import org.elasticsearch.xpack.upgrade.actions.IndexUpgradeInfoAction;
import org.elasticsearch.xpack.upgrade.actions.IndexUpgradeInfoAction.Response;
import org.junit.Before;
import java.util.Collection;
import java.util.Collections;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.core.IsEqual.equalTo;
public class IndexUpgradeIT extends ESIntegTestCase {
public class IndexUpgradeIT extends AbstractLicensesIntegrationTestCase {
@Before
public void resetLicensing() throws Exception {
enableLicensing();
}
@Override
protected boolean ignoreExternalCluster() {
@ -67,7 +78,7 @@ public class IndexUpgradeIT extends ESIntegTestCase {
public void testIndexUpgradeInfo() {
assertAcked(client().admin().indices().prepareCreate("test").get());
assertAcked(client().admin().indices().prepareCreate("kibana_test").get());
ensureYellow("test");
ensureYellow("test", "kibana_test");
Response response = client().prepareExecute(IndexUpgradeInfoAction.INSTANCE).setIndices("test", "kibana_test")
.setExtraParams(Collections.singletonMap("kibana_indices", "kibana_test")).get();
logger.info("Got response [{}]", Strings.toString(response));
@ -75,4 +86,42 @@ public class IndexUpgradeIT extends ESIntegTestCase {
assertThat(response.getActions().get("kibana_test"), equalTo(UpgradeActionRequired.UPGRADE));
assertThat(Strings.toString(response), containsString("kibana_test"));
}
public void testIndexUpgradeInfoLicense() throws Exception {
assertAcked(client().admin().indices().prepareCreate("test").get());
ensureYellow("test");
disableLicensing();
ElasticsearchSecurityException e = expectThrows(ElasticsearchSecurityException.class,
() -> client().prepareExecute(IndexUpgradeInfoAction.INSTANCE).setIndices("test").get());
assertThat(e.getMessage(), equalTo("current license is non-compliant for [upgrade]"));
enableLicensing();
Response response = client().prepareExecute(IndexUpgradeInfoAction.INSTANCE).setIndices("test").get();
assertThat(response.getActions().entrySet(), empty());
}
private static String randomValidLicenseType() {
return randomFrom("platinum", "gold", "standard", "basic");
}
private static String randomInvalidLicenseType() {
return randomFrom("missing", "trial");
}
public void disableLicensing() throws Exception {
updateLicensing(randomInvalidLicenseType());
}
public void enableLicensing() throws Exception {
updateLicensing(randomValidLicenseType());
}
public void updateLicensing(String licenseType) throws Exception {
wipeAllLicenses();
if (licenseType.equals("missing")) {
putLicenseTombstone();
} else {
License license = TestUtils.generateSignedLicense(licenseType, TimeValue.timeValueMinutes(1));
putLicense(license);
}
}
}

View File

@ -1,5 +1,22 @@
---
setup:
- do:
xpack.license.post:
body: >
{
"license": {
"uid": "b8520184-985d-4b04-8a89-b52da6e0aad1",
"type": "platinum",
"issue_date_in_millis": 1494510840000,
"expiry_date_in_millis": 2756814840000,
"max_nodes": 1,
"issued_to": "upgrade_api_test",
"issuer": "elasticsearch",
"signature": "AAAAAwAAAA0hsB+mfk9EqWiY6e1KAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQA6NkNF3Z219ptzRwZwGzgIwaXn5rXvOWSB9KK86xBqeYQMlO1ahCd4eW3FHWTuginPuqMX8okzN+UEMANPE3l0QxvrgCcTzNYPGqCJDwBb0ghuQ4Y5Cezn806sBnXLVF35B1HU2C1PYc1mZvisD63NqasrAVYb3GS6vwq8a7PYfKpfZfFCqG2SZIkSHACPGBTUiPbVEVv1iiOC04x/pjF4Kn26MPbFD5jbQBSY2V8TxoapMHf11EDpOTlMYkXgerbMg7VWtVCypTMJJrhoVguCrZvM8U/+sSnbodtnZUeAImnFbYeV10Rcw62dtrpka0yuo7h6Qtrvy9YqVHZDtyrM",
"start_date_in_millis": -1
}
}
- do:
indices.create:
index: test1