From e139b7ee31fb41921489a91a0f417f0d688ff99b Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 21 Mar 2018 15:25:32 -0400 Subject: [PATCH] Do not allow registering basic licenses (elastic/x-pack-elasticsearch#4087) This is related to elastic/x-pack-elasticsearch#3877. This commit introduces validation that blocks a user from registering a new basic license. Instead, the user should use the /start_basic route to install a basic license. Original commit: elastic/x-pack-elasticsearch@ebfcf6d8b28fe4fc2baca68b155f83054d956786 --- .../elasticsearch/license/LicenseService.java | 2 ++ .../license/RestPutLicenseAction.java | 5 +++++ .../license/LicensesAcknowledgementTests.java | 19 ++++++++++--------- .../license/LicensesTransportTests.java | 15 +++++++++++++++ .../org/elasticsearch/license/TestUtils.java | 6 +++++- .../test/license/20_put_license.yml | 15 +++++++++++++-- 6 files changed, 50 insertions(+), 12 deletions(-) diff --git a/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java b/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java index 26e10d3c34a..1170764052c 100644 --- a/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java +++ b/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java @@ -184,6 +184,8 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste final long now = clock.millis(); if (!LicenseVerifier.verifyLicense(newLicense) || newLicense.issueDate() > now || newLicense.startDate() > now) { listener.onResponse(new PutLicenseResponse(true, LicensesStatus.INVALID)); + } else if (newLicense.type().equals("basic")) { + listener.onFailure(new IllegalArgumentException("Registering basic licenses is not allowed.")); } else if (newLicense.expiryDate() < now) { listener.onResponse(new PutLicenseResponse(true, LicensesStatus.EXPIRED)); } else { diff --git a/plugin/core/src/main/java/org/elasticsearch/license/RestPutLicenseAction.java b/plugin/core/src/main/java/org/elasticsearch/license/RestPutLicenseAction.java index 626630fbce0..0a3a6ea2394 100644 --- a/plugin/core/src/main/java/org/elasticsearch/license/RestPutLicenseAction.java +++ b/plugin/core/src/main/java/org/elasticsearch/license/RestPutLicenseAction.java @@ -41,6 +41,11 @@ public class RestPutLicenseAction extends XPackRestHandler { putLicenseRequest.timeout(request.paramAsTime("timeout", putLicenseRequest.timeout())); putLicenseRequest.masterNodeTimeout(request.paramAsTime("master_timeout", putLicenseRequest.masterNodeTimeout())); + if ("basic".equals(putLicenseRequest.license().type())) { + throw new IllegalArgumentException("Installing basic licenses is no longer allowed. Use the POST " + + "/_xpack/license/start_basic API to install a basic license that does not expire."); + } + return channel -> client.es().admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest, new RestToXContentListener<>(channel)); } diff --git a/plugin/core/src/test/java/org/elasticsearch/license/LicensesAcknowledgementTests.java b/plugin/core/src/test/java/org/elasticsearch/license/LicensesAcknowledgementTests.java index 211215da21c..0f0f35d68ba 100644 --- a/plugin/core/src/test/java/org/elasticsearch/license/LicensesAcknowledgementTests.java +++ b/plugin/core/src/test/java/org/elasticsearch/license/LicensesAcknowledgementTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; +import static org.elasticsearch.common.unit.TimeValue.timeValueHours; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.mockito.Matchers.any; @@ -19,12 +20,12 @@ import static org.mockito.Mockito.verify; public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase { public void testAcknowledgment() throws Exception { - XPackLicenseState licenseState = new XPackLicenseState(); - setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licenseState, Settings.EMPTY); + setInitialState(TestUtils.generateSignedLicense("gold", timeValueHours(2)), licenseState, Settings.EMPTY); licenseService.start(); // try installing a signed license - License signedLicense = TestUtils.generateSignedLicense("basic", TimeValue.timeValueHours(10)); + long issueDate = System.currentTimeMillis() - TimeValue.timeValueHours(24 * 2).getMillis(); + License signedLicense = TestUtils.generateSignedLicense("trial", License.VERSION_CURRENT, issueDate, timeValueHours(10)); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense); // ensure acknowledgement message was part of the response licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true)); @@ -40,10 +41,10 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase public void testRejectUpgradeToProductionWithoutTLS() throws Exception { XPackLicenseState licenseState = new XPackLicenseState(); - setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licenseState, Settings.EMPTY); + setInitialState(TestUtils.generateSignedLicense("trial", timeValueHours(2)), licenseState, Settings.EMPTY); licenseService.start(); // try installing a signed license - License signedLicense = TestUtils.generateSignedLicense("platinum", TimeValue.timeValueHours(10)); + License signedLicense = TestUtils.generateSignedLicense("platinum", timeValueHours(10)); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense); // ensure acknowledgement message was part of the response IllegalStateException ise = expectThrows(IllegalStateException.class, () -> @@ -53,11 +54,11 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase public void testUpgradeToProductionWithoutTLSAndSecurityDisabled() throws Exception { XPackLicenseState licenseState = new XPackLicenseState(); - setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licenseState, Settings.builder() + setInitialState(TestUtils.generateSignedLicense("trial", timeValueHours(2)), licenseState, Settings.builder() .put("xpack.security.enabled", false).build()); licenseService.start(); // try installing a signed license - License signedLicense = TestUtils.generateSignedLicense("platinum", TimeValue.timeValueHours(10)); + License signedLicense = TestUtils.generateSignedLicense("platinum", timeValueHours(10)); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense); licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true)); assertThat(licenseService.getLicense(), not(signedLicense)); @@ -72,12 +73,12 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase public void testUpgradeToProductionWithTLSAndSecurity() throws Exception { XPackLicenseState licenseState = new XPackLicenseState(); - setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licenseState, Settings.builder() + setInitialState(TestUtils.generateSignedLicense("trial", timeValueHours(2)), licenseState, Settings.builder() .put("xpack.security.enabled", true) .put("xpack.security.transport.ssl.enabled", true).build()); licenseService.start(); // try installing a signed license - License signedLicense = TestUtils.generateSignedLicense("platinum", TimeValue.timeValueHours(10)); + License signedLicense = TestUtils.generateSignedLicense("platinum", timeValueHours(10)); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense); licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true)); assertThat(licenseService.getLicense(), not(signedLicense)); diff --git a/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java b/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java index f53f44911c3..a48132ef3d7 100644 --- a/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java +++ b/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java @@ -122,6 +122,21 @@ public class LicensesTransportTests extends ESSingleNodeTestCase { assertThat(getLicenseResponse.license(), not(tamperedLicense)); } + public void testPutBasicLicenseIsInvalid() throws Exception { + License signedLicense = generateSignedLicense("basic", License.VERSION_CURRENT, -1, TimeValue.timeValueMinutes(2)); + + PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE); + builder.setLicense(signedLicense); + + // try to put license (should be invalid) + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, builder::get); + assertEquals(iae.getMessage(), "Registering basic licenses is not allowed."); + + // try to get invalid license + GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), not(signedLicense)); + } + public void testPutExpiredLicense() throws Exception { License expiredLicense = generateExpiredNonBasicLicense(); PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE); diff --git a/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java b/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java index 8022f7f65b0..2610d6d7ce3 100644 --- a/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java +++ b/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java @@ -243,13 +243,17 @@ public class TestUtils { return generateSignedLicense(type, randomIntBetween(License.VERSION_START, License.VERSION_CURRENT), issueDate, expiryDuration); } + /** + * This method which chooses the license type randomly if the type is null. However, it will not randomly + * choose trial or basic types as those types can only be self-generated. + */ public static License generateSignedLicense(String type, int version, long issueDate, TimeValue expiryDuration) throws Exception { long issue = (issueDate != -1L) ? issueDate : System.currentTimeMillis() - TimeValue.timeValueHours(2).getMillis(); final String licenseType; if (version < License.VERSION_NO_FEATURE_TYPE) { licenseType = randomFrom("subscription", "internal", "development"); } else { - licenseType = (type != null) ? type : randomFrom( "silver", "dev", "gold", "platinum"); + licenseType = (type != null) ? type : randomFrom("silver", "dev", "gold", "platinum"); } final License.Builder builder = License.builder() .uid(UUID.randomUUID().toString()) diff --git a/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml b/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml index ae55df60deb..98e96318d7a 100644 --- a/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml +++ b/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml @@ -28,7 +28,7 @@ teardown: xpack.license.post: acknowledge: true body: | - {"licenses":[{"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"basic","issue_date_in_millis":1411948800000,"expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAgAAAA0lKPZ0a7aZquUltho/AAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQAALuQ44S3IG6SzolcXVJ6Z4CIXORDrYQ+wdLCeey0XdujTslAOj+k+vNgo6wauc7Uswi01esHu4lb5IgpvKy7RRCbh5bj/z2ubu2qMJqopp9BQyD7VQjVfqmG6seUMJwJ1a5Avvm9r41YPSPcrii3bKK2e1l6jK6N8ibCvnTyY/XkYGCJrBWTSJePDbg6ErbyodrZ37x1StLbPWcNAkmweyHjDJnvYnbeZZO7A3NmubXZjW7Ttf8/YwQyE00PqMcl7fVPY3hkKpAeHf8aaJbqkKYbqZuER3EWJX7ZvLVb1dNdNg8aXRn7YrkQcYwWgptYQpfV+D7yEJ4j5muAEoler"}]} + {"licenses":[{"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"gold","issue_date_in_millis":1411948800000,"expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issued_to","issuer":"issuer","signature":"AAAAAwAAAA2T3vqdBBetKQaBgxipAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQB7pGFYgawfLm9zzT80LvcLHjy1t/v2uSzCQWKdXXhrwSy4WrAH2uK/+PEiQ7aEpW5erLsyJ5KLA6OEZJDaP7r+mjOPuLt0++l5j4DMn7ybMzOPHXWBc6LETE3+pp0GZPyOmwsDkZSRUegTtciR2R6z+mdnGrhOYM80y08KVWwhdU/DHw41MK7ePo6tq73Nz49y9lDgt9fxA0t4ggEBPbnTDDBVQ25AjauY8sa0M5eg9rDDRayw1KamYWrara8PIGX+2YjhtUeQhmlCPdlxc9wECJ7/knPss5bI3ZoXQR3fyXhjcXNnHEIsblqLrMCal3pLxs7lI+KPYMa2ZYL/am4P"}]} - match: { license_status: "valid" } @@ -84,7 +84,7 @@ teardown: xpack.license.post: acknowledge: true body: | - {"license": {"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"basic","issue_date_in_millis":1411948800000,"expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAgAAAA1JRPDxCvXkXtEVEB1OAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQAALuQ44S3IG6SzolcXVJ6Z4CIXORDrYQ+wdLCeey0XdujTslAOj+k+vNgo6wauc7Uswi01esHu4lb5IgpvKy7RRCbh5bj/z2ubu2qMJqopp9BQyD7VQjVfqmG6seUMJwJ1a5Avvm9r41YPSPcrii3bKK2e1l6jK6N8ibCvnTyY/XkYGCJrBWTSJePDbg6ErbyodrZ37x1StLbPWcNAkmweyHjDJnvYnbeZZO7A3NmubXZjW7Ttf8/YwQyE00PqMcl7fVPY3hkKpAeHf8aaJbqkKYbqZuER3EWJX7ZvLVb1dNdNg8aXRn7YrkQcYwWgptYQpfV+D7yEJ4j5muAEoler"}} + {"license": {"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"gold","issue_date_in_millis":1411948800000,"expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issued_to","issuer":"issuer","signature":"AAAAAgAAAA3U8+YmnvwC+CWsV/mRAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQBe8GfzDm6T537Iuuvjetb3xK5dvg0K5NQapv+rczWcQFxgCuzbF8plkgetP1aAGZP4uRESDQPMlOCsx4d0UqqAm9f7GbBQ3l93P+PogInPFeEH9NvOmaAQovmxVM9SE6DsDqlX4cXSO+bgWpXPTd2LmpoQc1fXd6BZ8GeuyYpVHVKp9hVU0tAYjw6HzYOE7+zuO1oJYOxElqy66AnIfkvHrvni+flym3tE7tDTgsDRaz7W3iBhaqiSntEqabEkvHdPHQdSR99XGaEvnHO1paK01/35iZF6OXHsF7CCj+558GRXiVxzueOe7TsGSSt8g7YjZwV9bRCyU7oB4B/nidgI"}} - match: { license_status: "valid" } @@ -93,6 +93,17 @@ teardown: - length: { license: 11 } --- +"Cannot start basic": + + - do: + catch: bad_request + xpack.license.post: + acknowledge: true + body: | + {"license":{"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"basic","issue_date_in_millis":1411948800000,"expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAgAAAA0lKPZ0a7aZquUltho/AAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQAALuQ44S3IG6SzolcXVJ6Z4CIXORDrYQ+wdLCeey0XdujTslAOj+k+vNgo6wauc7Uswi01esHu4lb5IgpvKy7RRCbh5bj/z2ubu2qMJqopp9BQyD7VQjVfqmG6seUMJwJ1a5Avvm9r41YPSPcrii3bKK2e1l6jK6N8ibCvnTyY/XkYGCJrBWTSJePDbg6ErbyodrZ37x1StLbPWcNAkmweyHjDJnvYnbeZZO7A3NmubXZjW7Ttf8/YwQyE00PqMcl7fVPY3hkKpAeHf8aaJbqkKYbqZuER3EWJX7ZvLVb1dNdNg8aXRn7YrkQcYwWgptYQpfV+D7yEJ4j5muAEoler"}} + + - match: { error.root_cause.0.reason: 'Installing basic licenses is no longer allowed. Use the POST /_xpack/license/start_basic API to install a basic license that does not expire.' } +--- "Should fail gracefully when body content is not provided": - do: