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@ebfcf6d8b2
This commit is contained in:
Tim Brooks 2018-03-21 15:25:32 -04:00 committed by GitHub
parent 2cb044849f
commit e139b7ee31
6 changed files with 50 additions and 12 deletions

View File

@ -184,6 +184,8 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
final long now = clock.millis(); final long now = clock.millis();
if (!LicenseVerifier.verifyLicense(newLicense) || newLicense.issueDate() > now || newLicense.startDate() > now) { if (!LicenseVerifier.verifyLicense(newLicense) || newLicense.issueDate() > now || newLicense.startDate() > now) {
listener.onResponse(new PutLicenseResponse(true, LicensesStatus.INVALID)); 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) { } else if (newLicense.expiryDate() < now) {
listener.onResponse(new PutLicenseResponse(true, LicensesStatus.EXPIRED)); listener.onResponse(new PutLicenseResponse(true, LicensesStatus.EXPIRED));
} else { } else {

View File

@ -41,6 +41,11 @@ public class RestPutLicenseAction extends XPackRestHandler {
putLicenseRequest.timeout(request.paramAsTime("timeout", putLicenseRequest.timeout())); putLicenseRequest.timeout(request.paramAsTime("timeout", putLicenseRequest.timeout()));
putLicenseRequest.masterNodeTimeout(request.paramAsTime("master_timeout", putLicenseRequest.masterNodeTimeout())); 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, return channel -> client.es().admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest,
new RestToXContentListener<>(channel)); new RestToXContentListener<>(channel));
} }

View File

@ -10,6 +10,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue; 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.equalTo;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
@ -19,12 +20,12 @@ import static org.mockito.Mockito.verify;
public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase { public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase {
public void testAcknowledgment() throws Exception { public void testAcknowledgment() throws Exception {
XPackLicenseState licenseState = new XPackLicenseState(); 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(); licenseService.start();
// try installing a signed license // 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); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
// ensure acknowledgement message was part of the response // ensure acknowledgement message was part of the response
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true)); licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true));
@ -40,10 +41,10 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
public void testRejectUpgradeToProductionWithoutTLS() throws Exception { public void testRejectUpgradeToProductionWithoutTLS() throws Exception {
XPackLicenseState licenseState = new XPackLicenseState(); 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(); licenseService.start();
// try installing a signed license // 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); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
// ensure acknowledgement message was part of the response // ensure acknowledgement message was part of the response
IllegalStateException ise = expectThrows(IllegalStateException.class, () -> IllegalStateException ise = expectThrows(IllegalStateException.class, () ->
@ -53,11 +54,11 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
public void testUpgradeToProductionWithoutTLSAndSecurityDisabled() throws Exception { public void testUpgradeToProductionWithoutTLSAndSecurityDisabled() throws Exception {
XPackLicenseState licenseState = new XPackLicenseState(); 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()); .put("xpack.security.enabled", false).build());
licenseService.start(); licenseService.start();
// try installing a signed license // 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); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true)); licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true));
assertThat(licenseService.getLicense(), not(signedLicense)); assertThat(licenseService.getLicense(), not(signedLicense));
@ -72,12 +73,12 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
public void testUpgradeToProductionWithTLSAndSecurity() throws Exception { public void testUpgradeToProductionWithTLSAndSecurity() throws Exception {
XPackLicenseState licenseState = new XPackLicenseState(); 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.enabled", true)
.put("xpack.security.transport.ssl.enabled", true).build()); .put("xpack.security.transport.ssl.enabled", true).build());
licenseService.start(); licenseService.start();
// try installing a signed license // 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); PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true)); licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true));
assertThat(licenseService.getLicense(), not(signedLicense)); assertThat(licenseService.getLicense(), not(signedLicense));

View File

@ -122,6 +122,21 @@ public class LicensesTransportTests extends ESSingleNodeTestCase {
assertThat(getLicenseResponse.license(), not(tamperedLicense)); 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 { public void testPutExpiredLicense() throws Exception {
License expiredLicense = generateExpiredNonBasicLicense(); License expiredLicense = generateExpiredNonBasicLicense();
PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE); PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE);

View File

@ -243,13 +243,17 @@ public class TestUtils {
return generateSignedLicense(type, randomIntBetween(License.VERSION_START, License.VERSION_CURRENT), issueDate, expiryDuration); 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 { 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(); long issue = (issueDate != -1L) ? issueDate : System.currentTimeMillis() - TimeValue.timeValueHours(2).getMillis();
final String licenseType; final String licenseType;
if (version < License.VERSION_NO_FEATURE_TYPE) { if (version < License.VERSION_NO_FEATURE_TYPE) {
licenseType = randomFrom("subscription", "internal", "development"); licenseType = randomFrom("subscription", "internal", "development");
} else { } 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() final License.Builder builder = License.builder()
.uid(UUID.randomUUID().toString()) .uid(UUID.randomUUID().toString())

View File

@ -28,7 +28,7 @@ teardown:
xpack.license.post: xpack.license.post:
acknowledge: true acknowledge: true
body: | 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" } - match: { license_status: "valid" }
@ -84,7 +84,7 @@ teardown:
xpack.license.post: xpack.license.post:
acknowledge: true acknowledge: true
body: | 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" } - match: { license_status: "valid" }
@ -93,6 +93,17 @@ teardown:
- length: { license: 11 } - 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": "Should fail gracefully when body content is not provided":
- do: - do: