Handle malformed license signatures (#37137)
This commit adds a more user friendly error message when a license signature is malformed/truncated in a way that it cannot be meaningfully parsed.
This commit is contained in:
parent
2a79c468f8
commit
9049263c2c
|
@ -469,9 +469,17 @@ public class License implements ToXContentObject {
|
||||||
}
|
}
|
||||||
// not a license spec
|
// not a license spec
|
||||||
if (builder.signature != null) {
|
if (builder.signature != null) {
|
||||||
byte[] signatureBytes = Base64.getDecoder().decode(builder.signature);
|
int version;
|
||||||
ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
|
// In case the signature is truncated/malformed we might end up with fewer than 4 bytes in the byteBuffer
|
||||||
int version = byteBuffer.getInt();
|
// or with a string that cannot be base64 decoded. In either case return a more friendly error instead of
|
||||||
|
// just throwing the BufferUnderflowException or the IllegalArgumentException
|
||||||
|
try {
|
||||||
|
byte[] signatureBytes = Base64.getDecoder().decode(builder.signature);
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
|
||||||
|
version = byteBuffer.getInt();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ElasticsearchException("malformed signature for license [" + builder.uid + "]", e);
|
||||||
|
}
|
||||||
// we take the absolute version, because negative versions
|
// we take the absolute version, because negative versions
|
||||||
// mean that the license was generated by the cluster (see TrialLicense)
|
// mean that the license was generated by the cluster (see TrialLicense)
|
||||||
// and positive version means that the license was signed
|
// and positive version means that the license was signed
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.license;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.common.bytes.BytesArray;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.nio.BufferUnderflowException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
|
||||||
|
public class LicenseTests extends ESTestCase {
|
||||||
|
|
||||||
|
public void testFromXContent() throws Exception {
|
||||||
|
|
||||||
|
String licenseString = "{\"license\":" +
|
||||||
|
"{\"uid\":\"4056779d-b823-4c12-a9cb-efa4a8d8c422\"," +
|
||||||
|
"\"type\":\"gold\"," +
|
||||||
|
"\"issue_date_in_millis\":1546589020459," +
|
||||||
|
"\"expiry_date_in_millis\":1546596340459," +
|
||||||
|
"\"max_nodes\":5," +
|
||||||
|
"\"issued_to\":\"customer\"," +
|
||||||
|
"\"issuer\":\"elasticsearch\"," +
|
||||||
|
"\"signature\":\"AAAAAgAAAA34V2kfTJVtvdL2LttwAAABmFJ6NGRnbEM3WVQrZVQwNkdKQmR1VytlMTMyM1J0dTZ1WGwyY2ZCVFhqMGtJU2gzZ3pnNTVpOW" +
|
||||||
|
"F5Y1NaUkwyN2VsTEtCYnlZR2c5WWtjQ0phaDlhRjlDUXViUmUwMWhjSkE2TFcwSGdneTJHbUV4N2RHUWJxV20ybjRsZHRzV2xkN0ZmdDlYblJmNVcxMlBWeU81" +
|
||||||
|
"V1hLUm1EK0V1dmF3cFdlSGZzTU5SZE1qUmFra3JkS1hCanBWVmVTaFFwV3BVZERzeG9Sci9rYnlJK2toODZXY09tNmFHUVNUL3IyUHExV3VSTlBneWNJcFQ0bX" +
|
||||||
|
"l0cmhNNnRwbE1CWE4zWjJ5eGFuWFo0NGhsb3B5WFd1eTdYbFFWQkxFVFFPSlBERlB0eVVJYXVSZ0lsR2JpRS9rN1h4MSsvNUpOcGN6cU1NOHN1cHNtSTFIUGN1" +
|
||||||
|
"bWNGNEcxekhrblhNOXZ2VEQvYmRzQUFwbytUZEpRR3l6QU5oS2ZFSFdSbGxxNDZyZ0xvUHIwRjdBL2JqcnJnNGFlK09Cek9pYlJ5Umc9PQAAAQAth77fQLF7CC" +
|
||||||
|
"EL7wA6Z0/UuRm/weECcsjW/50kBnPLO8yEs+9/bPa5LSU0bF6byEXOVeO0ebUQfztpjulbXh8TrBDSG+6VdxGtohPo2IYPBaXzGs3LOOor6An/lhptxBWdwYmf" +
|
||||||
|
"bcp0m8mnXZh1vN9rmbTsZXnhBIoPTaRDwUBi3vJ3Ms3iLaEm4S8Slrfmtht2jUjgGZ2vAeZ9OHU2YsGtrSpz6f\"}";
|
||||||
|
License license = License.fromSource(new BytesArray(licenseString.getBytes(StandardCharsets.UTF_8)),
|
||||||
|
XContentType.JSON);
|
||||||
|
assertThat(license.type(), equalTo("gold"));
|
||||||
|
assertThat(license.uid(), equalTo("4056779d-b823-4c12-a9cb-efa4a8d8c422"));
|
||||||
|
assertThat(license.issuer(), equalTo("elasticsearch"));
|
||||||
|
assertThat(license.issuedTo(), equalTo("customer"));
|
||||||
|
assertThat(license.expiryDate(), equalTo(1546596340459L));
|
||||||
|
assertThat(license.issueDate(), equalTo(1546589020459L));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNotEnoughBytesFromXContent() throws Exception {
|
||||||
|
|
||||||
|
String licenseString = "{\"license\": " +
|
||||||
|
"{\"uid\":\"4056779d-b823-4c12-a9cb-efa4a8d8c422\"," +
|
||||||
|
"\"type\":\"gold\"," +
|
||||||
|
"\"issue_date_in_millis\":1546589020459," +
|
||||||
|
"\"expiry_date_in_millis\":1546596340459," +
|
||||||
|
"\"max_nodes\":5," +
|
||||||
|
"\"issued_to\":\"customer\"," +
|
||||||
|
"\"issuer\":\"elasticsearch\"," +
|
||||||
|
"\"signature\":\"AA\"}" +
|
||||||
|
"}";
|
||||||
|
ElasticsearchException exception =
|
||||||
|
expectThrows(ElasticsearchException.class,
|
||||||
|
() -> {
|
||||||
|
License.fromSource(new BytesArray(licenseString.getBytes(StandardCharsets.UTF_8)),
|
||||||
|
XContentType.JSON);
|
||||||
|
});
|
||||||
|
assertThat(exception.getMessage(), containsString("malformed signature for license [4056779d-b823-4c12-a9cb-efa4a8d8c422]"));
|
||||||
|
assertThat(exception.getCause(), instanceOf(BufferUnderflowException.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMalformedSignatureFromXContent() throws Exception {
|
||||||
|
|
||||||
|
String licenseString = "{\"license\": " +
|
||||||
|
"{\"uid\":\"4056779d-b823-4c12-a9cb-efa4a8d8c422\"," +
|
||||||
|
"\"type\":\"gold\"," +
|
||||||
|
"\"issue_date_in_millis\":1546589020459," +
|
||||||
|
"\"expiry_date_in_millis\":1546596340459," +
|
||||||
|
"\"max_nodes\":5," +
|
||||||
|
"\"issued_to\":\"customer\"," +
|
||||||
|
"\"issuer\":\"elasticsearch\"," +
|
||||||
|
"\"signature\":\"" + randomAlphaOfLength(10) + "\"}" +
|
||||||
|
"}";
|
||||||
|
ElasticsearchException exception =
|
||||||
|
expectThrows(ElasticsearchException.class,
|
||||||
|
() -> {
|
||||||
|
License.fromSource(new BytesArray(licenseString.getBytes(StandardCharsets.UTF_8)),
|
||||||
|
XContentType.JSON);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnableToBase64DecodeFromXContent() throws Exception {
|
||||||
|
|
||||||
|
String licenseString = "{\"license\":" +
|
||||||
|
"{\"uid\":\"4056779d-b823-4c12-a9cb-efa4a8d8c422\"," +
|
||||||
|
"\"type\":\"gold\"," +
|
||||||
|
"\"issue_date_in_millis\":1546589020459," +
|
||||||
|
"\"expiry_date_in_millis\":1546596340459," +
|
||||||
|
"\"max_nodes\":5," +
|
||||||
|
"\"issued_to\":\"customer\"," +
|
||||||
|
"\"issuer\":\"elasticsearch\"," +
|
||||||
|
"\"signature\":\"AAAAAgAAAA34V2kfTJVtvdL2LttwAAABmFJ6NGRnbEM3WVQrZVQwNkdKQmR1VytlMTMyM1J0dTZ1WGwyY2ZCVFhqMGtJU2gzZ3pnNTVpOW" +
|
||||||
|
"F5Y1NaUkwyN2VsTEtCYnlZR2c5WWtjQ0phaDlhRjlDUXViUmUwMWhjSkE2TFcwSGdneTJHbUV4N2RHUWJxV20ybjRsZHRzV2xkN0ZmdDlYblJmNVcxMlBWeU81" +
|
||||||
|
"V1hLUm1EK0V1dmF3cFdlSGZzTU5SZE1qUmFra3JkS1hCanBWVmVTaFFwV3BVZERzeG9Sci9rYnlJK2toODZXY09tNmFHUVNUL3IyUHExV3VSTlBneWNJcFQ0bX" +
|
||||||
|
"l0cmhNNnRwbE1CWE4zWjJ5eGFuWFo0NGhsb3B5WFd1eTdYbFFWQkxFVFFPSlBERlB0eVVJYXVSZ0lsR2JpRS9rN1h4MSsvNUpOcGN6cU1NOHN1cHNtSTFIUGN1" +
|
||||||
|
"bWNGNEcxekhrblhNOXZ2VEQvYmRzQUFwbytUZEpRR3l6QU5oS2ZFSFdSbGxxNDZyZ0xvUHIwRjdBL2JqcnJnNGFlK09Cek9pYlJ5Umc9PQAAAQAth77fQLF7CC" +
|
||||||
|
"EL7wA6Z0/UuRm/weECcsjW/50kBnPLO8yEs+9/bPa5LSU0bF6byEXOVeO0ebUQfztpjulbXh8TrBDSG+6VdxGtohPo2IYPBaXzGs3LOOor6An/lhptxBWdwYmf" +
|
||||||
|
"+xHAQ8tyvRqP5G+PRU7tiluEwR/eyHGZV2exdJNzmoGzdPSWwueBM5HK2GexORICH+UFI4cuGz444/hL2MMM1RdpVWQkT0SJ6D9x/VuSmHuYPdtX59Pp41LXvl" +
|
||||||
|
"bcp0m8mnXZh1vN9rmbTsZXnhBIoPTaRDwUBi3vJ3Ms3iLaEm4S8Slrfmtht2jUjgGZ2vAeZ9OHU2YsGtrSpz6fd\"}";
|
||||||
|
ElasticsearchException exception =
|
||||||
|
expectThrows(ElasticsearchException.class,
|
||||||
|
() -> {
|
||||||
|
License.fromSource(new BytesArray(licenseString.getBytes(StandardCharsets.UTF_8)),
|
||||||
|
XContentType.JSON);
|
||||||
|
});
|
||||||
|
assertThat(exception.getMessage(), containsString("malformed signature for license [4056779d-b823-4c12-a9cb-efa4a8d8c422]"));
|
||||||
|
assertThat(exception.getCause(), instanceOf(IllegalArgumentException.class));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue