From 3724feac3300f5227154a235537e5e2a7351872b Mon Sep 17 00:00:00 2001 From: Justin Cranford <89857999+justincr-elastic@users.noreply.github.com> Date: Thu, 21 Oct 2021 16:13:10 -0400 Subject: [PATCH] Put License API can return HTTP 500 (#79093) * Put License API can return HTTP 500 Put License now returns HTTP 400 if parsing user input fails, such as Base64 encoding or invalid signature. Closes #74058 --- .../org/elasticsearch/client/LicenseIT.java | 37 +++++++++++++++++++ .../org/elasticsearch/license/License.java | 6 +-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/LicenseIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/LicenseIT.java index d0423f893e8aa..a950abcb99bf4 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/LicenseIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/LicenseIT.java @@ -9,6 +9,7 @@ package org.elasticsearch.client; import org.elasticsearch.Build; +import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.license.DeleteLicenseRequest; import org.elasticsearch.client.license.GetBasicStatusResponse; @@ -23,6 +24,7 @@ import org.elasticsearch.client.license.StartTrialRequest; import org.elasticsearch.client.license.StartTrialResponse; import org.elasticsearch.common.Strings; +import org.elasticsearch.rest.RestStatus; import org.elasticsearch.xcontent.XContentParser; import org.elasticsearch.xcontent.json.JsonXContent; import org.junit.After; @@ -40,6 +42,7 @@ import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.emptyOrNullString; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.stringContainsInOrder; public class LicenseIT extends ESRestHighLevelClientTestCase { @@ -91,6 +94,40 @@ public void testStartTrial() throws Exception { } } + public void testPutInvalidTrialLicense() throws Exception { + assumeTrue("Trial license is only valid when tested against snapshot/test builds", + Build.CURRENT.isSnapshot()); + + // use a hard-coded trial license for 20 yrs to be able to roll back from another licenses + final String signature = "xx"; // Truncated, so it is expected to fail validation + final String licenseDefinition = Strings.toString(jsonBuilder() + .startObject() + .field("licenses", List.of( + Map.of( + "uid", "96fc37c6-6fc9-43e2-a40d-73143850cd72", + "type", "trial", + // 2018-10-16 07:02:48 UTC + "issue_date_in_millis", "1539673368158", + // 2038-10-11 07:02:48 UTC, 20 yrs later + "expiry_date_in_millis", "2170393368158", + "max_nodes", "5", + "issued_to", "client_rest-high-level_integTestCluster", + "issuer", "elasticsearch", + "start_date_in_millis", "-1", + "signature", signature))) + .endObject()); + + final PutLicenseRequest request = new PutLicenseRequest(); + request.setAcknowledge(true); + request.setLicenseDefinition(licenseDefinition); + ElasticsearchStatusException e = expectThrows( + ElasticsearchStatusException.class, + () -> highLevelClient().license().putLicense(request, RequestOptions.DEFAULT) + ); + assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST)); + assertThat(e.getMessage(), stringContainsInOrder("malformed signature for license")); + } + public static void putTrialLicense() throws IOException { assumeTrue("Trial license is only valid when tested against snapshot/test builds", Build.CURRENT.isSnapshot()); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java index fc9a01b6a9d9e..f08c147236991 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java @@ -642,7 +642,7 @@ public static License fromXContent(XContentParser parser) throws IOException { ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); version = byteBuffer.getInt(); } catch (Exception e) { - throw new ElasticsearchException("malformed signature for license [" + builder.uid + "]", e); + throw new ElasticsearchParseException("malformed signature for license [" + builder.uid + "]", e); } // we take the absolute version, because negative versions // mean that the license was generated by the cluster (see TrialLicense) @@ -651,9 +651,9 @@ public static License fromXContent(XContentParser parser) throws IOException { version *= -1; } if (version == 0) { - throw new ElasticsearchException("malformed signature for license [" + builder.uid + "]"); + throw new ElasticsearchParseException("malformed signature for license [" + builder.uid + "]"); } else if (version > VERSION_CURRENT) { - throw new ElasticsearchException("Unknown license version found, please upgrade all nodes to the latest " + + throw new ElasticsearchParseException("Unknown license version found, please upgrade all nodes to the latest " + "elasticsearch-license plugin"); } // signature version is the source of truth