|
8 | 8 |
|
9 | 9 | package org.elasticsearch.packaging.test;
|
10 | 10 |
|
| 11 | +import org.elasticsearch.Version; |
11 | 12 | import org.elasticsearch.cli.ExitCodes;
|
| 13 | +import org.elasticsearch.common.Strings; |
| 14 | +import org.elasticsearch.common.ssl.PemKeyConfig; |
| 15 | +import org.elasticsearch.packaging.util.FileMatcher; |
12 | 16 | import org.elasticsearch.packaging.util.Installation;
|
13 | 17 | import org.elasticsearch.packaging.util.Packages;
|
14 | 18 | import org.elasticsearch.packaging.util.Shell;
|
| 19 | +import org.elasticsearch.test.http.MockResponse; |
| 20 | +import org.elasticsearch.test.http.MockWebServer; |
| 21 | +import org.elasticsearch.xcontent.XContentBuilder; |
| 22 | +import org.elasticsearch.xpack.core.security.EnrollmentToken; |
| 23 | +import org.hamcrest.CoreMatchers; |
15 | 24 | import org.junit.BeforeClass;
|
16 | 25 |
|
17 | 26 | import java.nio.file.Files;
|
18 | 27 | import java.nio.file.Path;
|
| 28 | +import java.nio.file.Paths; |
19 | 29 | import java.nio.file.StandardCopyOption;
|
| 30 | +import java.security.SecureRandom; |
20 | 31 | import java.util.List;
|
21 | 32 | import java.util.Optional;
|
22 | 33 | import java.util.function.Predicate;
|
| 34 | +import java.util.stream.Collectors; |
| 35 | +import java.util.stream.Stream; |
| 36 | + |
| 37 | +import javax.net.ssl.KeyManager; |
| 38 | +import javax.net.ssl.SSLContext; |
| 39 | +import javax.net.ssl.TrustManager; |
23 | 40 |
|
24 | 41 | import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
|
| 42 | +import static org.elasticsearch.packaging.util.FileMatcher.Fileness.Directory; |
| 43 | +import static org.elasticsearch.packaging.util.FileMatcher.Fileness.File; |
| 44 | +import static org.elasticsearch.packaging.util.FileMatcher.p660; |
| 45 | +import static org.elasticsearch.packaging.util.FileMatcher.p750; |
25 | 46 | import static org.elasticsearch.packaging.util.FileUtils.append;
|
26 | 47 | import static org.elasticsearch.packaging.util.Packages.assertInstalled;
|
27 | 48 | import static org.elasticsearch.packaging.util.Packages.assertRemoved;
|
28 | 49 | import static org.elasticsearch.packaging.util.Packages.installPackage;
|
29 | 50 | import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallation;
|
| 51 | +import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; |
30 | 52 | import static org.hamcrest.Matchers.containsString;
|
31 | 53 | import static org.hamcrest.Matchers.equalTo;
|
32 | 54 | import static org.hamcrest.Matchers.hasItem;
|
@@ -235,6 +257,69 @@ public void test72ReconfigureRetainsUserSettings() throws Exception {
|
235 | 257 | assertThat(newConfigurationLines, hasItem("node.name: testnodename"));
|
236 | 258 | }
|
237 | 259 |
|
| 260 | + public void test73ReconfigureCreatesFilesWithCorrectPermissions() throws Exception { |
| 261 | + cleanup(); |
| 262 | + assertRemoved(distribution()); |
| 263 | + installation = installPackage(sh, distribution(), successfulAutoConfiguration()); |
| 264 | + assertInstalled(distribution()); |
| 265 | + verifyPackageInstallation(installation, distribution(), sh); |
| 266 | + verifySecurityAutoConfigured(installation); |
| 267 | + assertNotNull(installation.getElasticPassword()); |
| 268 | + final PemKeyConfig keyConfig = new PemKeyConfig( |
| 269 | + Paths.get(getClass().getResource("http.crt").toURI()).toAbsolutePath().normalize().toString(), |
| 270 | + Paths.get(getClass().getResource("http.key").toURI()).toAbsolutePath().normalize().toString(), |
| 271 | + new char[0], |
| 272 | + Paths.get(getClass().getResource("http.crt").toURI()).getParent().toAbsolutePath().normalize() |
| 273 | + ); |
| 274 | + final SSLContext sslContext = SSLContext.getInstance("TLS"); |
| 275 | + sslContext.init(new KeyManager[] { keyConfig.createKeyManager() }, new TrustManager[] {}, new SecureRandom()); |
| 276 | + // We can't run multiple nodes as package installations. We mock an initial node that would respond to the enroll node API |
| 277 | + try (MockWebServer mockNode = new MockWebServer(sslContext, false)) { |
| 278 | + mockNode.start(); |
| 279 | + final String httpCaCertPemString = Files.readAllLines( |
| 280 | + Paths.get(getClass().getResource("http_ca.crt").toURI()).toAbsolutePath().normalize() |
| 281 | + ).stream().filter(l -> l.contains("-----") == false).collect(Collectors.joining()); |
| 282 | + final String httpCaKeyPemString = Files.readAllLines( |
| 283 | + Paths.get(getClass().getResource("http_ca.key").toURI()).toAbsolutePath().normalize() |
| 284 | + ).stream().filter(l -> l.contains("-----") == false).collect(Collectors.joining()); |
| 285 | + final String transportCaCertPemString = Files.readAllLines( |
| 286 | + Paths.get(getClass().getResource("transport_ca.crt").toURI()).toAbsolutePath().normalize() |
| 287 | + ).stream().filter(l -> l.contains("-----") == false).collect(Collectors.joining()); |
| 288 | + final String transportKeyPemString = Files.readAllLines( |
| 289 | + Paths.get(getClass().getResource("transport.key").toURI()).toAbsolutePath().normalize() |
| 290 | + ).stream().filter(l -> l.contains("-----") == false).collect(Collectors.joining()); |
| 291 | + final String transportCertPemString = Files.readAllLines( |
| 292 | + Paths.get(getClass().getResource("transport.crt").toURI()).toAbsolutePath().normalize() |
| 293 | + ).stream().filter(l -> l.contains("-----") == false).collect(Collectors.joining()); |
| 294 | + final XContentBuilder responseBuilder = jsonBuilder().startObject() |
| 295 | + .field("http_ca_key", httpCaKeyPemString) |
| 296 | + .field("http_ca_cert", httpCaCertPemString) |
| 297 | + .field("transport_ca_cert", transportCaCertPemString) |
| 298 | + .field("transport_key", transportKeyPemString) |
| 299 | + .field("transport_cert", transportCertPemString) |
| 300 | + .array("nodes_addresses", "192.168.1.23:9300") // won't be used, can be anything |
| 301 | + .endObject(); |
| 302 | + mockNode.enqueue(new MockResponse().setResponseCode(200).setBody(Strings.toString(responseBuilder))); |
| 303 | + final EnrollmentToken enrollmentToken = new EnrollmentToken( |
| 304 | + "some-api-key", |
| 305 | + "b0150fd8a29f9012207912de9a01aa1d1f0dd696c847d3a9353881f9045bf442", // fingerprint of http_ca.crt |
| 306 | + Version.CURRENT.toString(), |
| 307 | + List.of(mockNode.getHostName() + ":" + mockNode.getPort()) |
| 308 | + ); |
| 309 | + Shell.Result result = installation.executables().nodeReconfigureTool.run( |
| 310 | + "-v --enrollment-token " + enrollmentToken.getEncoded(), |
| 311 | + "y", |
| 312 | + true |
| 313 | + ); |
| 314 | + assertThat(result.exitCode(), CoreMatchers.equalTo(0)); |
| 315 | + assertThat(installation.config("certs"), FileMatcher.file(Directory, "root", "elasticsearch", p750)); |
| 316 | + Stream.of("http.p12", "http_ca.crt", "transport.p12") |
| 317 | + .forEach( |
| 318 | + file -> assertThat(installation.config("certs").resolve(file), FileMatcher.file(File, "root", "elasticsearch", p660)) |
| 319 | + ); |
| 320 | + } |
| 321 | + } |
| 322 | + |
238 | 323 | private Predicate<String> successfulAutoConfiguration() {
|
239 | 324 | Predicate<String> p1 = output -> output.contains("Authentication and authorization are enabled.");
|
240 | 325 | Predicate<String> p2 = output -> output.contains("TLS for the transport and HTTP layers is enabled and configured.");
|
|
0 commit comments