From 10bca720762eb85e9f840845024f0418e83464c8 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Thu, 27 Sep 2018 09:12:14 +0300 Subject: [PATCH 1/9] Add request and response objects --- .../client/EmptyBodyRequest.java | 34 +++++ .../security/GetSslCertificatesRequest.java | 38 ++++++ .../security/GetSslCertificatesResponse.java | 124 ++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java new file mode 100644 index 0000000000000..0ed72b476378f --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client; + +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; + +public class EmptyBodyRequest implements Validatable, ToXContentObject { + + @Override + public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject().endObject(); + } + +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java new file mode 100644 index 0000000000000..7b0812cfddbff --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.security; + +import org.apache.http.client.methods.HttpGet; +import org.elasticsearch.client.EmptyBodyRequest; +import org.elasticsearch.client.Request; + +public class GetSslCertificatesRequest extends EmptyBodyRequest { + + public static final GetSslCertificatesRequest INSTANCE = new GetSslCertificatesRequest(); + private final Request request; + + private GetSslCertificatesRequest() { + request = new Request(HttpGet.METHOD_NAME, "/_xpack/ssl/certificates"); + } + + public Request getRequest() { + return request; + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java new file mode 100644 index 0000000000000..b01e93a7319dc --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java @@ -0,0 +1,124 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.security; + +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; + +public class GetSslCertificatesResponse { + + private final String path; + private final String format; + private final String alias; + private final String subjectDn; + private final String serialNumber; + private final String expiry; + private final boolean hasPrivateKey; + + public GetSslCertificatesResponse(String path, String format, @Nullable String alias, String subjectDn, String serialNumber, String expiry, + boolean hasPrivateKey) { + this.path = path; + this.format = format; + this.alias = alias; + this.subjectDn = subjectDn; + this.serialNumber = serialNumber; + this.expiry = expiry; + this.hasPrivateKey = hasPrivateKey; + } + + /** + * @return The path to the certificate, as configured in the elasticsearch.yml file. + */ + public String getPath() { + return path; + } + + /** + * @return The format of the file. One of jks, PKCS12, PEM + */ + public String getFormat() { + return format; + } + + public @Nullable + String getAlias() { + return alias; + } + + public String getSubjectDn() { + return subjectDn; + } + + public String getSerialNumber() { + return serialNumber; + } + + public String getExpiry() { + return expiry; + } + + public boolean isHasPrivateKey() { + return hasPrivateKey; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final GetSslCertificatesResponse that = (GetSslCertificatesResponse) o; + return path.equals(that.path) && + format.equals(that.format) && + Objects.equals(alias, that.alias) && + serialNumber.equals(that.serialNumber) && + expiry.equals(that.expiry) && + hasPrivateKey == that.hasPrivateKey; + } + + @Override + public int hashCode() { + return Objects.hash(path, format, alias, serialNumber, expiry, hasPrivateKey); + } + + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<> + ("get_ssl_certificates_response", + true, args -> new GetSslCertificatesResponse((String) args[0], (String) args[1], (String) args[2], (String) args[3], + (String) args[4], (String) args[5], (boolean) args[6])); + + static { + PARSER.declareString(constructorArg(), new ParseField("path")); + PARSER.declareString(constructorArg(), new ParseField("format")); + PARSER.declareStringOrNull(constructorArg(), new ParseField("alias")); + PARSER.declareString(constructorArg(), new ParseField("subject_dn")); + PARSER.declareString(constructorArg(), new ParseField("serial_number")); + PARSER.declareString(constructorArg(), new ParseField("expiry")); + PARSER.declareBoolean(constructorArg(), new ParseField("has_private_key")); + } + + public static GetSslCertificatesResponse fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } +} From b20a5d275eee9370f0005d127355e835ee3bbec0 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Thu, 27 Sep 2018 15:14:26 +0300 Subject: [PATCH 2/9] Remove ConstructingObjectParser --- client/rest-high-level/build.gradle | 3 + .../elasticsearch/client/SecurityClient.java | 29 +++++ .../security/GetSslCertificatesResponse.java | 118 +++++++---------- .../security/support/CertificateInfo.java | 121 ++++++++++++++++++ .../SecurityDocumentationIT.java | 12 ++ client/rest-high-level/testnode.crt | 23 ++++ 6 files changed, 231 insertions(+), 75 deletions(-) create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java create mode 100644 client/rest-high-level/testnode.crt diff --git a/client/rest-high-level/build.gradle b/client/rest-high-level/build.gradle index c608d7c91f16e..781d62b9c99bc 100644 --- a/client/rest-high-level/build.gradle +++ b/client/rest-high-level/build.gradle @@ -76,6 +76,7 @@ forbiddenApisMain { addSignatureFiles 'http-signatures' signaturesFiles += files('src/main/resources/forbidden/rest-high-level-signatures.txt') } +File nodeCert = file("./testnode.crt") integTestRunner { systemProperty 'tests.rest.cluster.username', System.getProperty('tests.rest.cluster.username', 'test_user') @@ -85,11 +86,13 @@ integTestRunner { integTestCluster { setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.security.enabled', 'true' + setting 'xpack.ssl.certificate_authorities', 'testnode.crt' setupCommand 'setupDummyUser', 'bin/elasticsearch-users', 'useradd', System.getProperty('tests.rest.cluster.username', 'test_user'), '-p', System.getProperty('tests.rest.cluster.password', 'test-password'), '-r', 'superuser' + extraConfigFile nodeCert.name, nodeCert waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://${node.httpUri()}/_cluster/health?wait_for_nodes=>=${numNodes}&wait_for_status=yellow", diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java index a4bc34004c247..bdc2d217d1f86 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java @@ -22,6 +22,8 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.security.DisableUserRequest; import org.elasticsearch.client.security.EnableUserRequest; +import org.elasticsearch.client.security.GetSslCertificatesRequest; +import org.elasticsearch.client.security.GetSslCertificatesResponse; import org.elasticsearch.client.security.PutUserRequest; import org.elasticsearch.client.security.PutUserResponse; import org.elasticsearch.client.security.EmptyResponse; @@ -125,4 +127,31 @@ public void disableUserAsync(DisableUserRequest request, RequestOptions options, restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::disableUser, options, EmptyResponse::fromXContent, listener, emptySet()); } + + /** + * Synchronously retrieve the X.509 certificates that are used to encrypt communications in an Elasticsearch cluster. + * See + * the docs for more. + * + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response from the get certificates call + * @throws IOException in case there is a problem sending the request or parsing back the response + */ + public GetSslCertificatesResponse getSslCertificates(RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(GetSslCertificatesRequest.INSTANCE, GetSslCertificatesRequest::getRequest, + options, GetSslCertificatesResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously retrieve the X.509 certificates that are used to encrypt communications in an Elasticsearch cluster. + * See + * the docs for more. + * + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + */ + public void getSslCertificates(RequestOptions options, ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(GetSslCertificatesRequest.INSTANCE, GetSslCertificatesRequest::getRequest, + options, GetSslCertificatesResponse::fromXContent, listener, emptySet()); + } } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java index b01e93a7319dc..33cac9144bd6a 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java @@ -19,106 +19,74 @@ package org.elasticsearch.client.security; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.client.security.support.CertificateInfo; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.xcontent.DeprecationHandler; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Objects; -import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; - public class GetSslCertificatesResponse { - private final String path; - private final String format; - private final String alias; - private final String subjectDn; - private final String serialNumber; - private final String expiry; - private final boolean hasPrivateKey; - - public GetSslCertificatesResponse(String path, String format, @Nullable String alias, String subjectDn, String serialNumber, String expiry, - boolean hasPrivateKey) { - this.path = path; - this.format = format; - this.alias = alias; - this.subjectDn = subjectDn; - this.serialNumber = serialNumber; - this.expiry = expiry; - this.hasPrivateKey = hasPrivateKey; - } - - /** - * @return The path to the certificate, as configured in the elasticsearch.yml file. - */ - public String getPath() { - return path; - } + private final List certificates; - /** - * @return The format of the file. One of jks, PKCS12, PEM - */ - public String getFormat() { - return format; + public GetSslCertificatesResponse(List certificates) { + this.certificates = certificates; } - public @Nullable - String getAlias() { - return alias; - } + private static final DeprecationHandler DEPRECATION_HANDLER = new DeprecationHandler() { - public String getSubjectDn() { - return subjectDn; - } + @Override + public void usedDeprecatedName(String usedName, String modernName) { + } - public String getSerialNumber() { - return serialNumber; - } - - public String getExpiry() { - return expiry; - } - - public boolean isHasPrivateKey() { - return hasPrivateKey; - } + @Override + public void usedDeprecatedField(String usedName, String replacedWith) { + } + }; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final GetSslCertificatesResponse that = (GetSslCertificatesResponse) o; - return path.equals(that.path) && - format.equals(that.format) && - Objects.equals(alias, that.alias) && - serialNumber.equals(that.serialNumber) && - expiry.equals(that.expiry) && - hasPrivateKey == that.hasPrivateKey; + return Objects.equals(this.certificates, that.certificates); } @Override public int hashCode() { - return Objects.hash(path, format, alias, serialNumber, expiry, hasPrivateKey); + return Objects.hash(certificates); } - private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<> - ("get_ssl_certificates_response", - true, args -> new GetSslCertificatesResponse((String) args[0], (String) args[1], (String) args[2], (String) args[3], - (String) args[4], (String) args[5], (boolean) args[6])); - - static { - PARSER.declareString(constructorArg(), new ParseField("path")); - PARSER.declareString(constructorArg(), new ParseField("format")); - PARSER.declareStringOrNull(constructorArg(), new ParseField("alias")); - PARSER.declareString(constructorArg(), new ParseField("subject_dn")); - PARSER.declareString(constructorArg(), new ParseField("serial_number")); - PARSER.declareString(constructorArg(), new ParseField("expiry")); - PARSER.declareBoolean(constructorArg(), new ParseField("has_private_key")); + public static GetSslCertificatesResponse fromXContent(XContentParser parser) throws IOException { + List unparsedObjects = parser.list(); + if (unparsedObjects.isEmpty()) { + return new GetSslCertificatesResponse(Collections.emptyList()); + } + List certificates = new ArrayList(); + for (Object o : unparsedObjects) { + try (XContentBuilder builder = XContentFactory.jsonBuilder()) { + @SuppressWarnings("unchecked") + Map value = (Map) o; + builder.map(value); + try (XContentParser certificateInfoParser = XContentFactory.xContent(builder.contentType()).createParser( + NamedXContentRegistry.EMPTY, DEPRECATION_HANDLER, Strings.toString(builder))) { + certificates.add(CertificateInfo.PARSER.parse(certificateInfoParser, null)); + } + } + } + return new GetSslCertificatesResponse(certificates); } - public static GetSslCertificatesResponse fromXContent(XContentParser parser) throws IOException { - return PARSER.parse(parser, null); + public List getCertificates() { + return certificates; } } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java new file mode 100644 index 0000000000000..fff65c249e9fa --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java @@ -0,0 +1,121 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.security.support; + +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; + +/** + * Simple model of an X.509 certificate + */ +public class CertificateInfo implements ToXContentObject { + public static final ParseField PATH = new ParseField("path"); + public static final ParseField FORMAT = new ParseField("format"); + public static final ParseField ALIAS = new ParseField("alias"); + public static final ParseField SUBJECT_DN = new ParseField("subject_dn"); + public static final ParseField SERIAL_NUMBER = new ParseField("serial_number"); + public static final ParseField HAS_PRIVATE_KEY = new ParseField("has_private_key"); + public static final ParseField EXPIRY = new ParseField("expiry"); + + private final String path; + private final String format; + private final String alias; + private final String subjectDn; + private final String serialNumber; + private final boolean hasPrivateKey; + private final String expiry; + + public CertificateInfo(String path, String format, @Nullable String alias, String subjectDn, String serialNumber, boolean hasPrivateKey, + String expiry) { + this.path = path; + this.format = format; + this.alias = alias; + this.subjectDn = subjectDn; + this.serialNumber = serialNumber; + this.hasPrivateKey = hasPrivateKey; + this.expiry = expiry; + } + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("certificate_info", + true, args -> new CertificateInfo((String) args[0], (String) args[0], (String) args[0], (String) args[0], (String) args[0], + (boolean) args[5], (String) args[6])); + + static { + PARSER.declareString(constructorArg(), PATH); + PARSER.declareString(constructorArg(), FORMAT); + PARSER.declareStringOrNull(constructorArg(), ALIAS); + PARSER.declareString(constructorArg(), SUBJECT_DN); + PARSER.declareString(constructorArg(), SERIAL_NUMBER); + PARSER.declareBoolean(constructorArg(), HAS_PRIVATE_KEY); + PARSER.declareString(constructorArg(), EXPIRY); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + + final CertificateInfo that = (CertificateInfo) other; + return this.path.equals(that.path) + && this.format.equals(that.format) + && this.hasPrivateKey == that.hasPrivateKey + && Objects.equals(this.alias, that.alias) + && this.serialNumber.equals(that.serialNumber) + && this.subjectDn.equals(that.subjectDn) + && this.expiry.equals(that.expiry); + } + + @Override + public int hashCode() { + return Objects.hash(path, format, alias, subjectDn, serialNumber, hasPrivateKey, expiry); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(PATH.getPreferredName(), path); + builder.field(FORMAT.getPreferredName(), format); + builder.field(ALIAS.getPreferredName(), alias); + builder.field(SUBJECT_DN.getPreferredName(), subjectDn); + builder.field(SERIAL_NUMBER.getPreferredName(), serialNumber); + builder.field(HAS_PRIVATE_KEY.getPreferredName(), hasPrivateKey); + builder.field(EXPIRY.getPreferredName(), expiry); + builder.endObject(); + return builder; + } + + public static CertificateInfo fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java index 103b031fc0e03..f93cf9dc5810b 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java @@ -26,12 +26,16 @@ import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.security.DisableUserRequest; import org.elasticsearch.client.security.EnableUserRequest; +import org.elasticsearch.client.security.GetSslCertificatesRequest; +import org.elasticsearch.client.security.GetSslCertificatesResponse; import org.elasticsearch.client.security.PutUserRequest; import org.elasticsearch.client.security.PutUserResponse; import org.elasticsearch.client.security.RefreshPolicy; import org.elasticsearch.client.security.EmptyResponse; +import org.elasticsearch.client.security.support.CertificateInfo; import java.util.Collections; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -173,4 +177,12 @@ public void onFailure(Exception e) { assertTrue(latch.await(30L, TimeUnit.SECONDS)); } } + + public void testGetSslCertificates() throws Exception { + RestHighLevelClient client = highLevelClient(); + GetSslCertificatesResponse getSslCertificatesResponse = client.security().getSslCertificates(RequestOptions.DEFAULT); + List c = getSslCertificatesResponse.getCertificates(); + System.out.println(c.size()); + System.out.println(c.get(0)); + } } diff --git a/client/rest-high-level/testnode.crt b/client/rest-high-level/testnode.crt new file mode 100644 index 0000000000000..08c160bcea5ff --- /dev/null +++ b/client/rest-high-level/testnode.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID0zCCArugAwIBAgIJALi5bDfjMszLMA0GCSqGSIb3DQEBCwUAMEgxDDAKBgNV +BAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEgMB4GA1UEAxMXRWxhc3Rp +Y3NlYXJjaCBUZXN0IE5vZGUwHhcNMTUwOTIzMTg1MjU3WhcNMTkwOTIyMTg1MjU3 +WjBIMQwwCgYDVQQKEwNvcmcxFjAUBgNVBAsTDWVsYXN0aWNzZWFyY2gxIDAeBgNV +BAMTF0VsYXN0aWNzZWFyY2ggVGVzdCBOb2RlMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA3rGZ1QbsW0+MuyrSLmMfDFKtLBkIFW8V0gRuurFg1PUKKNR1 +Mq2tMVwjjYETAU/UY0iKZOzjgvYPKhDTYBTte/WHR1ZK4CYVv7TQX/gtFQG/ge/c +7u0sLch9p7fbd+/HZiLS/rBEZDIohvgUvzvnA8+OIYnw4kuxKo/5iboAIS41klMg +/lATm8V71LMY68inht71/ZkQoAHKgcR9z4yNYvQ1WqKG8DG8KROXltll3sTrKbl5 +zJhn660es/1ZnR6nvwt6xnSTl/mNHMjkfv1bs4rJ/py3qPxicdoSIn/KyojUcgHV +F38fuAy2CQTdjVG5fWj9iz+mQvLm3+qsIYQdFwIDAQABo4G/MIG8MAkGA1UdEwQC +MAAwHQYDVR0OBBYEFEMMWLWQi/g83PzlHYqAVnty5L7HMIGPBgNVHREEgYcwgYSC +CWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluggpsb2NhbGhvc3Q0ghds +b2NhbGhvc3Q0LmxvY2FsZG9tYWluNIIKbG9jYWxob3N0NoIXbG9jYWxob3N0Ni5s +b2NhbGRvbWFpbjaHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQEL +BQADggEBAMjGGXT8Nt1tbl2GkiKtmiuGE2Ej66YuZ37WSJViaRNDVHLlg87TCcHe +k2rdO+6sFqQbbzEfwQ05T7xGmVu7tm54HwKMRugoQ3wct0bQC5wEWYN+oMDvSyO6 +M28mZwWb4VtR2IRyWP+ve5DHwTM9mxWa6rBlGzsQqH6YkJpZojzqk/mQTug+Y8aE +mVoqRIPMHq9ob+S9qd5lp09+MtYpwPfTPx/NN+xMEooXWW/ARfpGhWPkg/FuCu4z +1tFmCqHgNcWirzMm3dQpF78muE9ng6OB2MXQwL4VgnVkxmlZNHbkR2v/t8MyZJxC +y4g6cTMM3S/UMt5/+aIB2JAuMKyuD+A= +-----END CERTIFICATE----- From e4a38a996e8f2633e4f16211118ecf6fb58b72de Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Thu, 27 Sep 2018 18:25:29 +0300 Subject: [PATCH 3/9] - --- .../elasticsearch/client/SecurityClient.java | 2 +- .../security/GetSslCertificatesResponse.java | 10 ++-- .../security/support/CertificateInfo.java | 48 ++++++++++++------ .../SecurityDocumentationIT.java | 49 +++++++++++++++++-- 4 files changed, 82 insertions(+), 27 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java index bdc2d217d1f86..9c5293ef6dde9 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java @@ -150,7 +150,7 @@ public GetSslCertificatesResponse getSslCertificates(RequestOptions options) thr * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion */ - public void getSslCertificates(RequestOptions options, ActionListener listener) { + public void getSslCertificatesAsync(RequestOptions options, ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(GetSslCertificatesRequest.INSTANCE, GetSslCertificatesRequest::getRequest, options, GetSslCertificatesResponse::fromXContent, listener, emptySet()); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java index 33cac9144bd6a..fab099a13a45b 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java @@ -67,15 +67,15 @@ public int hashCode() { } public static GetSslCertificatesResponse fromXContent(XContentParser parser) throws IOException { - List unparsedObjects = parser.list(); - if (unparsedObjects.isEmpty()) { + List unparsedCerts = parser.list(); + if (unparsedCerts.isEmpty()) { return new GetSslCertificatesResponse(Collections.emptyList()); } - List certificates = new ArrayList(); - for (Object o : unparsedObjects) { + List certificates = new ArrayList<>(); + for (Object cert : unparsedCerts) { try (XContentBuilder builder = XContentFactory.jsonBuilder()) { @SuppressWarnings("unchecked") - Map value = (Map) o; + Map value = (Map) cert; builder.map(value); try (XContentParser certificateInfoParser = XContentFactory.xContent(builder.contentType()).createParser( NamedXContentRegistry.EMPTY, DEPRECATION_HANDLER, Strings.toString(builder))) { diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java index fff65c249e9fa..b3ac143dac8be 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java @@ -34,7 +34,7 @@ /** * Simple model of an X.509 certificate */ -public class CertificateInfo implements ToXContentObject { +public class CertificateInfo { public static final ParseField PATH = new ParseField("path"); public static final ParseField FORMAT = new ParseField("format"); public static final ParseField ALIAS = new ParseField("alias"); @@ -62,9 +62,38 @@ public CertificateInfo(String path, String format, @Nullable String alias, Strin this.expiry = expiry; } + public String getPath() { + return path; + } + + public String getFormat() { + return format; + } + + public String getAlias() { + return alias; + } + + public String getSubjectDn() { + return subjectDn; + } + + public String getSerialNumber() { + return serialNumber; + } + + public boolean isHasPrivateKey() { + return hasPrivateKey; + } + + public String getExpiry() { + return expiry; + } + + @SuppressWarnings("unchecked") public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("certificate_info", - true, args -> new CertificateInfo((String) args[0], (String) args[0], (String) args[0], (String) args[0], (String) args[0], + true, args -> new CertificateInfo((String) args[0], (String) args[1], (String) args[2], (String) args[3], (String) args[4], (boolean) args[5], (String) args[6])); static { @@ -100,20 +129,7 @@ public boolean equals(Object other) { public int hashCode() { return Objects.hash(path, format, alias, subjectDn, serialNumber, hasPrivateKey, expiry); } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field(PATH.getPreferredName(), path); - builder.field(FORMAT.getPreferredName(), format); - builder.field(ALIAS.getPreferredName(), alias); - builder.field(SUBJECT_DN.getPreferredName(), subjectDn); - builder.field(SERIAL_NUMBER.getPreferredName(), serialNumber); - builder.field(HAS_PRIVATE_KEY.getPreferredName(), hasPrivateKey); - builder.field(EXPIRY.getPreferredName(), expiry); - builder.endObject(); - return builder; - } + public static CertificateInfo fromXContent(XContentParser parser) throws IOException { return PARSER.parse(parser, null); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java index f93cf9dc5810b..320297d85c086 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java @@ -26,13 +26,13 @@ import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.security.DisableUserRequest; import org.elasticsearch.client.security.EnableUserRequest; -import org.elasticsearch.client.security.GetSslCertificatesRequest; import org.elasticsearch.client.security.GetSslCertificatesResponse; import org.elasticsearch.client.security.PutUserRequest; import org.elasticsearch.client.security.PutUserResponse; import org.elasticsearch.client.security.RefreshPolicy; import org.elasticsearch.client.security.EmptyResponse; import org.elasticsearch.client.security.support.CertificateInfo; +import org.hamcrest.Matchers; import java.util.Collections; import java.util.List; @@ -180,9 +180,48 @@ public void onFailure(Exception e) { public void testGetSslCertificates() throws Exception { RestHighLevelClient client = highLevelClient(); - GetSslCertificatesResponse getSslCertificatesResponse = client.security().getSslCertificates(RequestOptions.DEFAULT); - List c = getSslCertificatesResponse.getCertificates(); - System.out.println(c.size()); - System.out.println(c.get(0)); + { + //tag::get-certificates-execute + GetSslCertificatesResponse response = client.security().getSslCertificates(RequestOptions.DEFAULT); + //end::get-certificates-execute + + assertNotNull(response); + + //tag::get-certificates-response + List certificates = response.getCertificates(); + //end::get-certificates-response + + assertThat(certificates.size(), Matchers.equalTo(1)); + assertThat(certificates.get(0).getSubjectDn(), Matchers.is("CN=Elasticsearch Test Node, OU=elasticsearch, O=org")); + + } + + { + // tag::get-certificates-execute-listener + ActionListener listener = new ActionListener() { + @Override + public void onResponse(GetSslCertificatesResponse getSslCertificatesResponse) { + + } + + @Override + public void onFailure(Exception e) { + + } + }; + + // end::get-certificates-execute-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::get-certificates-execute-async + client.security().getSslCertificatesAsync(RequestOptions.DEFAULT, listener); + // end::end-certificates-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + + } } } From 3c3b2621ced075c190ec968c4606214d193cf08e Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 28 Sep 2018 11:28:54 +0300 Subject: [PATCH 4/9] add docs and tests --- client/rest-high-level/build.gradle | 5 ++ .../SecurityDocumentationIT.java | 50 ++++++++++++++--- client/rest-high-level/testnode.jks | Bin 0 -> 9360 bytes .../security/get-certificates.asciidoc | 52 ++++++++++++++++++ .../high-level/supported-apis.asciidoc | 2 + 5 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 client/rest-high-level/testnode.jks create mode 100644 docs/java-rest/high-level/security/get-certificates.asciidoc diff --git a/client/rest-high-level/build.gradle b/client/rest-high-level/build.gradle index 781d62b9c99bc..bfe7c3d956cd2 100644 --- a/client/rest-high-level/build.gradle +++ b/client/rest-high-level/build.gradle @@ -77,6 +77,7 @@ forbiddenApisMain { signaturesFiles += files('src/main/resources/forbidden/rest-high-level-signatures.txt') } File nodeCert = file("./testnode.crt") +File nodeTrustStore = file("./testnode.jks") integTestRunner { systemProperty 'tests.rest.cluster.username', System.getProperty('tests.rest.cluster.username', 'test_user') @@ -86,13 +87,17 @@ integTestRunner { integTestCluster { setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.security.enabled', 'true' + // Truststore settings are not used since TLS is not enabled. Included for testing the get certificates API setting 'xpack.ssl.certificate_authorities', 'testnode.crt' + setting 'xpack.security.transport.ssl.truststore.path', 'testnode.jks' + setting 'xpack.security.transport.ssl.truststore.password', 'testnode' setupCommand 'setupDummyUser', 'bin/elasticsearch-users', 'useradd', System.getProperty('tests.rest.cluster.username', 'test_user'), '-p', System.getProperty('tests.rest.cluster.password', 'test-password'), '-r', 'superuser' extraConfigFile nodeCert.name, nodeCert + extraConfigFile nodeTrustStore.name, nodeTrustStore waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://${node.httpUri()}/_cluster/health?wait_for_nodes=>=${numNodes}&wait_for_status=yellow", diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java index 320297d85c086..7c46711d026ea 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java @@ -35,6 +35,7 @@ import org.hamcrest.Matchers; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -188,12 +189,47 @@ public void testGetSslCertificates() throws Exception { assertNotNull(response); //tag::get-certificates-response - List certificates = response.getCertificates(); + List certificates = response.getCertificates(); // <1> //end::get-certificates-response - assertThat(certificates.size(), Matchers.equalTo(1)); - assertThat(certificates.get(0).getSubjectDn(), Matchers.is("CN=Elasticsearch Test Node, OU=elasticsearch, O=org")); - + assertThat(certificates.size(), Matchers.equalTo(9)); + final Iterator it = certificates.iterator(); + CertificateInfo c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=testnode-client-profile")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=Elasticsearch Test Node, OU=elasticsearch, O=org")); + assertThat(c.getPath(), Matchers.equalTo("testnode.crt")); + assertThat(c.getFormat(), Matchers.equalTo("PEM")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=OpenLDAP, OU=Elasticsearch, O=Elastic, L=Mountain View, ST=CA, C=US")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=Elasticsearch Test Node, OU=elasticsearch, O=org")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=Elasticsearch Test Client, OU=elasticsearch, O=org")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=ad-ELASTICSEARCHAD-CA, DC=ad, DC=test, DC=elasticsearch, DC=com")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=Elasticsearch Test Node")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=samba4")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); + c = it.next(); + assertThat(c.getSubjectDn(), Matchers.equalTo("CN=Elasticsearch Test Node")); + assertThat(c.getPath(), Matchers.equalTo("testnode.jks")); + assertThat(c.getFormat(), Matchers.equalTo("jks")); } { @@ -201,12 +237,12 @@ public void testGetSslCertificates() throws Exception { ActionListener listener = new ActionListener() { @Override public void onResponse(GetSslCertificatesResponse getSslCertificatesResponse) { - + // <1> } @Override public void onFailure(Exception e) { - + // <2> } }; @@ -217,7 +253,7 @@ public void onFailure(Exception e) { listener = new LatchedActionListener<>(listener, latch); // tag::get-certificates-execute-async - client.security().getSslCertificatesAsync(RequestOptions.DEFAULT, listener); + client.security().getSslCertificatesAsync(RequestOptions.DEFAULT, listener); // <1> // end::end-certificates-execute-async assertTrue(latch.await(30L, TimeUnit.SECONDS)); diff --git a/client/rest-high-level/testnode.jks b/client/rest-high-level/testnode.jks new file mode 100644 index 0000000000000000000000000000000000000000..ebe6146124e8fd607e46a1a3129bdf9b4de0370d GIT binary patch literal 9360 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 literal 0 HcmV?d00001 diff --git a/docs/java-rest/high-level/security/get-certificates.asciidoc b/docs/java-rest/high-level/security/get-certificates.asciidoc new file mode 100644 index 0000000000000..63aab1c5c0142 --- /dev/null +++ b/docs/java-rest/high-level/security/get-certificates.asciidoc @@ -0,0 +1,52 @@ +[[java-rest-high-security-get-certificates]] +=== SSL Certificate API + +[[java-rest-high-security-get-certificates-execution]] +==== Execution + +The X.509 Certificates that are used to encrypt communications in an +Elasticsearch cluster using the `security().getSslCertificates()` method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-certificates-execute] +-------------------------------------------------- + +[[java-rest-high-security-get-certificates-response]] +==== Response + +The returned `GetSslCertificatesResponse` contains a single field, `certificates`. +This field, accessed with `getCertificates` returns a List of `CertificateInfo` +objects containing the information for all the certificates used. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-certificates-response] +-------------------------------------------------- +<1> `certificates` is a List of `CertificateInfo` + +[[java-rest-high-security-get-certificates-execute-async]] +==== Asynchronous Execution + +This request can be executed asynchronously: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-certificates-execute-async] +-------------------------------------------------- +<1> The `ActionListener` to use when the execution completes. + +The asynchronous method does not block and returns immediately. Once the request +has completed the `ActionListener` is called back using the `onResponse` method +if the execution successfully completed or using the `onFailure` method if +it failed. + +A typical listener for a `GetSslCertificatesResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-certificates-execute-listener] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument. +<2> Called in case of failure. The raised exception is provided as an argument. diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 90f44852c4349..86213340b945f 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -287,10 +287,12 @@ The Java High Level REST Client supports the following Security APIs: * <> * <> * <> +* <> include::security/put-user.asciidoc[] include::security/enable-user.asciidoc[] include::security/disable-user.asciidoc[] +include::security/get-certificates.asciidoc[] == Watcher APIs From 9ccbffb22ff0cd108625815aa1a1ad20c31e339b Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 28 Sep 2018 11:40:16 +0300 Subject: [PATCH 5/9] Remove unused import --- .../client/security/support/CertificateInfo.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java index b3ac143dac8be..aa84fada95689 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java @@ -22,8 +22,6 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.xcontent.ConstructingObjectParser; -import org.elasticsearch.common.xcontent.ToXContentObject; -import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; @@ -129,7 +127,7 @@ public boolean equals(Object other) { public int hashCode() { return Objects.hash(path, format, alias, subjectDn, serialNumber, hasPrivateKey, expiry); } - + public static CertificateInfo fromXContent(XContentParser parser) throws IOException { return PARSER.parse(parser, null); From 0be860f92b4ace56505d57185f2b3bf3c3a9b916 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Fri, 28 Sep 2018 13:55:34 +0300 Subject: [PATCH 6/9] Fix naming convention tests --- .../client/RestHighLevelClientTests.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java index acdfc50b5a13a..fda7ecdd6d6a2 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java @@ -721,10 +721,16 @@ public void testApiNamingConventions() throws Exception { methods.containsKey(apiName.substring(0, apiName.length() - 6))); assertThat(method.getReturnType(), equalTo(Void.TYPE)); assertEquals(0, method.getExceptionTypes().length); - assertEquals(3, method.getParameterTypes().length); - assertThat(method.getParameterTypes()[0].getSimpleName(), endsWith("Request")); - assertThat(method.getParameterTypes()[1], equalTo(RequestOptions.class)); - assertThat(method.getParameterTypes()[2], equalTo(ActionListener.class)); + if (apiName.equals("security.get_ssl_certificates_async")) { + assertEquals(2, method.getParameterTypes().length); + assertThat(method.getParameterTypes()[0], equalTo(RequestOptions.class)); + assertThat(method.getParameterTypes()[1], equalTo(ActionListener.class)); + } else { + assertEquals(3, method.getParameterTypes().length); + assertThat(method.getParameterTypes()[0].getSimpleName(), endsWith("Request")); + assertThat(method.getParameterTypes()[1], equalTo(RequestOptions.class)); + assertThat(method.getParameterTypes()[2], equalTo(ActionListener.class)); + } } else { //A few methods return a boolean rather than a response object if (apiName.equals("ping") || apiName.contains("exist")) { @@ -735,7 +741,7 @@ public void testApiNamingConventions() throws Exception { assertEquals(1, method.getExceptionTypes().length); //a few methods don't accept a request object as argument - if (apiName.equals("ping") || apiName.equals("info")) { + if (apiName.equals("ping") || apiName.equals("info") || apiName.equals("security.get_ssl_certificates")) { assertEquals(1, method.getParameterTypes().length); assertThat(method.getParameterTypes()[0], equalTo(RequestOptions.class)); } else { From c585d9700ad4e1ac00275de7df407ca8e671a544 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Tue, 2 Oct 2018 17:32:55 +0300 Subject: [PATCH 7/9] address feedback --- .../client/EmptyBodyRequest.java | 34 ------------------- .../security/GetSslCertificatesRequest.java | 15 ++++++-- .../security/GetSslCertificatesResponse.java | 19 ++++------- .../security/support/CertificateInfo.java | 2 +- .../SecurityDocumentationIT.java | 1 - .../security/get-certificates.asciidoc | 3 +- .../common/xcontent/DeprecationHandler.java | 15 ++++++++ 7 files changed, 37 insertions(+), 52 deletions(-) delete mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java deleted file mode 100644 index 0ed72b476378f..0000000000000 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.client; - -import org.elasticsearch.common.xcontent.ToXContentObject; -import org.elasticsearch.common.xcontent.XContentBuilder; - -import java.io.IOException; - -public class EmptyBodyRequest implements Validatable, ToXContentObject { - - @Override - public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().endObject(); - } - -} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java index 7b0812cfddbff..c4dbef4e422b6 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesRequest.java @@ -20,10 +20,17 @@ package org.elasticsearch.client.security; import org.apache.http.client.methods.HttpGet; -import org.elasticsearch.client.EmptyBodyRequest; import org.elasticsearch.client.Request; +import org.elasticsearch.client.Validatable; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; -public class GetSslCertificatesRequest extends EmptyBodyRequest { +import java.io.IOException; + +/** + * Request object to retrieve the X.509 certificates that are used to encrypt communications in an Elasticsearch cluster. + */ +public final class GetSslCertificatesRequest implements Validatable, ToXContentObject { public static final GetSslCertificatesRequest INSTANCE = new GetSslCertificatesRequest(); private final Request request; @@ -35,4 +42,8 @@ private GetSslCertificatesRequest() { public Request getRequest() { return request; } + + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject().endObject(); + } } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java index fab099a13a45b..ef4e14f14ac7d 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java @@ -34,7 +34,11 @@ import java.util.Map; import java.util.Objects; -public class GetSslCertificatesResponse { +/** + * Response object when retrieving the X.509 certificates that are used to encrypt communications in an Elasticsearch cluster. + * Returns a list of {@link CertificateInfo} objects describing each of the certificates. + */ +public final class GetSslCertificatesResponse { private final List certificates; @@ -42,17 +46,6 @@ public GetSslCertificatesResponse(List certificates) { this.certificates = certificates; } - private static final DeprecationHandler DEPRECATION_HANDLER = new DeprecationHandler() { - - @Override - public void usedDeprecatedName(String usedName, String modernName) { - } - - @Override - public void usedDeprecatedField(String usedName, String replacedWith) { - } - }; - @Override public boolean equals(Object o) { if (this == o) return true; @@ -78,7 +71,7 @@ public static GetSslCertificatesResponse fromXContent(XContentParser parser) thr Map value = (Map) cert; builder.map(value); try (XContentParser certificateInfoParser = XContentFactory.xContent(builder.contentType()).createParser( - NamedXContentRegistry.EMPTY, DEPRECATION_HANDLER, Strings.toString(builder))) { + NamedXContentRegistry.EMPTY, DeprecationHandler.IGNORE_DEPRECATION_HANDLER, Strings.toString(builder))) { certificates.add(CertificateInfo.PARSER.parse(certificateInfoParser, null)); } } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java index aa84fada95689..de93415d8b34e 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java @@ -32,7 +32,7 @@ /** * Simple model of an X.509 certificate */ -public class CertificateInfo { +public final class CertificateInfo { public static final ParseField PATH = new ParseField("path"); public static final ParseField FORMAT = new ParseField("format"); public static final ParseField ALIAS = new ParseField("alias"); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java index 7c46711d026ea..70e718bb21bb4 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java @@ -257,7 +257,6 @@ public void onFailure(Exception e) { // end::end-certificates-execute-async assertTrue(latch.await(30L, TimeUnit.SECONDS)); - } } } diff --git a/docs/java-rest/high-level/security/get-certificates.asciidoc b/docs/java-rest/high-level/security/get-certificates.asciidoc index 63aab1c5c0142..6820b1564fb8e 100644 --- a/docs/java-rest/high-level/security/get-certificates.asciidoc +++ b/docs/java-rest/high-level/security/get-certificates.asciidoc @@ -28,7 +28,8 @@ include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-certificates-respon [[java-rest-high-security-get-certificates-execute-async]] ==== Asynchronous Execution -This request can be executed asynchronously: +This request can be executed asynchronously using the `security().getSslCertificatesAsync()` +method: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java index 1b0dcf4568086..71637574ad8de 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java @@ -43,6 +43,21 @@ public void usedDeprecatedName(String usedName, String modernName) { } }; + /** + * Ignores deprecation warnings. This can be used when parsing responses + * from Elasticsearch. and when any warnings emitted there just mean that + * you are talking to an old version of Elasticsearch. + */ + DeprecationHandler IGNORE_DEPRECATION_HANDLER = new DeprecationHandler() { + @Override + public void usedDeprecatedName(String usedName, String modernName) { + } + + @Override + public void usedDeprecatedField(String usedName, String replacedWith) { + } + }; + /** * Called when the provided field name matches a deprecated name for the field. * @param usedName the provided field name From a21fe6e28d64763ca1ad1c0d9bb6661cd45ece7b Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Thu, 4 Oct 2018 16:16:10 +0300 Subject: [PATCH 8/9] Address feedback --- .../security/GetSslCertificatesResponse.java | 25 +++---------------- .../security/support/CertificateInfo.java | 2 -- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java index ef4e14f14ac7d..80f016b3ae1bf 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetSslCertificatesResponse.java @@ -20,18 +20,12 @@ package org.elasticsearch.client.security; import org.elasticsearch.client.security.support.CertificateInfo; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.xcontent.DeprecationHandler; -import org.elasticsearch.common.xcontent.NamedXContentRegistry; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentParserUtils; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; /** @@ -60,21 +54,10 @@ public int hashCode() { } public static GetSslCertificatesResponse fromXContent(XContentParser parser) throws IOException { - List unparsedCerts = parser.list(); - if (unparsedCerts.isEmpty()) { - return new GetSslCertificatesResponse(Collections.emptyList()); - } List certificates = new ArrayList<>(); - for (Object cert : unparsedCerts) { - try (XContentBuilder builder = XContentFactory.jsonBuilder()) { - @SuppressWarnings("unchecked") - Map value = (Map) cert; - builder.map(value); - try (XContentParser certificateInfoParser = XContentFactory.xContent(builder.contentType()).createParser( - NamedXContentRegistry.EMPTY, DeprecationHandler.IGNORE_DEPRECATION_HANDLER, Strings.toString(builder))) { - certificates.add(CertificateInfo.PARSER.parse(certificateInfoParser, null)); - } - } + XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_ARRAY, parser.nextToken(), parser::getTokenLocation); + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + certificates.add(CertificateInfo.PARSER.parse(parser, null)); } return new GetSslCertificatesResponse(certificates); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java index de93415d8b34e..28fd1c61c0d5c 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/CertificateInfo.java @@ -88,7 +88,6 @@ public String getExpiry() { return expiry; } - @SuppressWarnings("unchecked") public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("certificate_info", true, args -> new CertificateInfo((String) args[0], (String) args[1], (String) args[2], (String) args[3], (String) args[4], @@ -128,7 +127,6 @@ public int hashCode() { return Objects.hash(path, format, alias, subjectDn, serialNumber, hasPrivateKey, expiry); } - public static CertificateInfo fromXContent(XContentParser parser) throws IOException { return PARSER.parse(parser, null); } From 205b521424eab41025b13325c8903e332d15faf7 Mon Sep 17 00:00:00 2001 From: Ioannis Kakavas Date: Thu, 4 Oct 2018 16:44:36 +0300 Subject: [PATCH 9/9] revert unecessary changes --- .../common/xcontent/DeprecationHandler.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java index 71637574ad8de..1b0dcf4568086 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java @@ -43,21 +43,6 @@ public void usedDeprecatedName(String usedName, String modernName) { } }; - /** - * Ignores deprecation warnings. This can be used when parsing responses - * from Elasticsearch. and when any warnings emitted there just mean that - * you are talking to an old version of Elasticsearch. - */ - DeprecationHandler IGNORE_DEPRECATION_HANDLER = new DeprecationHandler() { - @Override - public void usedDeprecatedName(String usedName, String modernName) { - } - - @Override - public void usedDeprecatedField(String usedName, String replacedWith) { - } - }; - /** * Called when the provided field name matches a deprecated name for the field. * @param usedName the provided field name