-
Notifications
You must be signed in to change notification settings - Fork 25.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Access SSL contexts using names instead of Settings #30953
Changes from 30 commits
8fbe6e1
222015b
a360d22
29077e2
9ea7a52
997a1ec
2999649
bcde8a5
6ce4d32
f9cc028
e0561ee
bee987c
7c060d7
2282d01
1aa0c14
39e6629
ef58ff1
d94dd57
ee32357
5a57fd6
cf2fdf0
42e3aa1
fb0505e
37cc028
817c565
2eb845a
2f6c87b
255a42e
8ea7e35
e8d8299
b11d61b
f4bab91
f637dc7
f774e6d
d1f3147
44c4cf1
9a0c026
bc3095e
9f6fa6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
/* | ||
* 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.xpack.monitoring.exporter.http; | ||
|
||
import org.elasticsearch.action.ActionFuture; | ||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; | ||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; | ||
import org.elasticsearch.common.settings.MockSecureSettings; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.env.Environment; | ||
import org.elasticsearch.env.TestEnvironment; | ||
import org.elasticsearch.test.ESIntegTestCase; | ||
import org.elasticsearch.test.ESIntegTestCase.Scope; | ||
import org.elasticsearch.test.http.MockWebServer; | ||
import org.elasticsearch.xpack.core.ssl.TestsSSLService; | ||
import org.elasticsearch.xpack.core.ssl.VerificationMode; | ||
import org.elasticsearch.xpack.monitoring.exporter.Exporter; | ||
import org.elasticsearch.xpack.monitoring.exporter.Exporters; | ||
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; | ||
import org.hamcrest.CoreMatchers; | ||
import org.junit.AfterClass; | ||
import org.junit.Before; | ||
|
||
import javax.net.ssl.SSLContext; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
|
||
import static org.hamcrest.Matchers.containsString; | ||
import static org.hamcrest.Matchers.instanceOf; | ||
import static org.hamcrest.Matchers.notNullValue; | ||
|
||
@ESIntegTestCase.ClusterScope(scope = Scope.SUITE, | ||
numDataNodes = 1, numClientNodes = 0, transportClientRatio = 0.0, supportsDedicatedMasters = false) | ||
public class HttpSslExporterIT extends MonitoringIntegTestCase { | ||
|
||
private final Settings globalSettings = Settings.builder().put("path.home", createTempDir()).build(); | ||
private final Environment environment = TestEnvironment.newEnvironment(globalSettings); | ||
|
||
private static MockWebServer webServer; | ||
private static Path keystore; | ||
private MockSecureSettings secureSettings; | ||
|
||
|
||
@AfterClass | ||
public static void cleanUpStatics() { | ||
if (webServer != null) { | ||
webServer.close(); | ||
webServer = null; | ||
} | ||
keystore = null; | ||
} | ||
|
||
@Override | ||
protected boolean ignoreExternalCluster() { | ||
return true; | ||
} | ||
|
||
@Override | ||
protected Settings nodeSettings(int nodeOrdinal) { | ||
if (keystore == null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jkakavas is there something that should be done here for the FIPS work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, thanks for catching this. @tvernum can you please add the key and certificate files and use those instead of the keystore when setting up the MockWebServer ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh FIPS why do you want to make my life complicated? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to use the |
||
keystore = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks"); | ||
assertThat(Files.exists(keystore), CoreMatchers.is(true)); | ||
} | ||
|
||
if (webServer == null) { | ||
try { | ||
webServer = buildWebServer(); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
final String address = "https://" + webServer.getHostName() + ":" + webServer.getPort(); | ||
final Settings.Builder builder = Settings.builder() | ||
.put(super.nodeSettings(nodeOrdinal)) | ||
.put("xpack.monitoring.exporters.plaintext.type", "http") | ||
.put("xpack.monitoring.exporters.plaintext.enabled", true) | ||
.put("xpack.monitoring.exporters.plaintext.host", address) | ||
.put("xpack.monitoring.exporters.plaintext.ssl.truststore.path", keystore) | ||
.put("xpack.monitoring.exporters.plaintext.ssl.truststore.password", "testnode") | ||
.put("xpack.monitoring.exporters.secure.type", "http") | ||
.put("xpack.monitoring.exporters.secure.enabled", true) | ||
.put("xpack.monitoring.exporters.secure.host", address) | ||
.put("xpack.monitoring.exporters.secure.ssl.truststore.path", keystore); | ||
|
||
secureSettings = new MockSecureSettings(); | ||
secureSettings.setString("xpack.monitoring.exporters.secure.ssl.truststore.secure_password", "testnode"); | ||
builder.setSecureSettings(secureSettings); | ||
|
||
return builder.build(); | ||
} | ||
|
||
private MockWebServer buildWebServer() throws IOException { | ||
final Settings sslSettings = Settings.builder() | ||
.put("xpack.ssl.keystore.path", keystore) | ||
.put("xpack.ssl.keystore.password", "testnode") | ||
.put(globalSettings) | ||
.build(); | ||
|
||
TestsSSLService sslService = new TestsSSLService(sslSettings, environment); | ||
final SSLContext sslContext = sslService.sslContext(Settings.EMPTY); | ||
MockWebServer server = new MockWebServer(sslContext, false); | ||
server.start(); | ||
return server; | ||
} | ||
|
||
@Before | ||
// Force the exporters to be built from closed secure settings (as they would be in a production environment) | ||
public void closeSecureSettings() throws IOException { | ||
if (secureSettings != null) { | ||
secureSettings.close(); | ||
} | ||
} | ||
|
||
public void testCannotUpdateSslSettingsWithSecureSettings() throws Exception { | ||
// Verify that it was created even though it has a secure setting | ||
assertExporterExists("secure"); | ||
|
||
// Verify that we cannot modify the SSL settings | ||
final ActionFuture<ClusterUpdateSettingsResponse> future = setVerificationMode("secure", VerificationMode.CERTIFICATE); | ||
final IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, future::actionGet); | ||
assertThat(iae.getCause(), instanceOf(IllegalStateException.class)); | ||
assertThat(iae.getCause().getMessage(), containsString("secure_password")); | ||
} | ||
|
||
public void testCanUpdateSslSettingsWithNoSecureSettings() { | ||
final ActionFuture<ClusterUpdateSettingsResponse> future = setVerificationMode("plaintext", VerificationMode.CERTIFICATE); | ||
final ClusterUpdateSettingsResponse response = future.actionGet(); | ||
assertThat(response, notNullValue()); | ||
clearTransientSettings("plaintext"); | ||
} | ||
|
||
public void testCanAddNewExporterWithSsl() { | ||
Path truststore = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks"); | ||
assertThat(Files.exists(truststore), CoreMatchers.is(true)); | ||
|
||
final ClusterUpdateSettingsRequest updateSettings = new ClusterUpdateSettingsRequest(); | ||
final Settings settings = Settings.builder() | ||
.put("xpack.monitoring.exporters._new.type", "http") | ||
.put("xpack.monitoring.exporters._new.host", "https://" + webServer.getHostName() + ":" + webServer.getPort()) | ||
.put("xpack.monitoring.exporters._new.ssl.truststore.path", truststore) | ||
.put("xpack.monitoring.exporters._new.ssl.truststore.password", "testnode") | ||
.put("xpack.monitoring.exporters._new.ssl.verification_mode", VerificationMode.NONE.name()) | ||
.build(); | ||
updateSettings.transientSettings(settings); | ||
final ActionFuture<ClusterUpdateSettingsResponse> future = client().admin().cluster().updateSettings(updateSettings); | ||
final ClusterUpdateSettingsResponse response = future.actionGet(); | ||
assertThat(response, notNullValue()); | ||
|
||
assertExporterExists("_new"); | ||
clearTransientSettings("_new"); | ||
} | ||
|
||
private void assertExporterExists(String secure) { | ||
final Exporter httpExporter = getExporter(secure); | ||
assertThat(httpExporter, notNullValue()); | ||
assertThat(httpExporter, instanceOf(HttpExporter.class)); | ||
} | ||
|
||
private Exporter getExporter(String name) { | ||
final Exporters exporters = internalCluster().getInstance(Exporters.class); | ||
assertThat(exporters, notNullValue()); | ||
return exporters.getExporter(name); | ||
} | ||
|
||
private ActionFuture<ClusterUpdateSettingsResponse> setVerificationMode(String name, VerificationMode mode) { | ||
final ClusterUpdateSettingsRequest updateSettings = new ClusterUpdateSettingsRequest(); | ||
final Settings settings = Settings.builder() | ||
.put("xpack.monitoring.exporters." + name + ".ssl.verification_mode", mode.name()) | ||
.build(); | ||
updateSettings.transientSettings(settings); | ||
return client().admin().cluster().updateSettings(updateSettings); | ||
} | ||
|
||
private void clearTransientSettings(String... names) { | ||
final ClusterUpdateSettingsRequest updateSettings = new ClusterUpdateSettingsRequest(); | ||
final Settings.Builder builder = Settings.builder(); | ||
for (String name : names) { | ||
builder.put("xpack.monitoring.exporters." + name + ".*", (String) null); | ||
} | ||
updateSettings.transientSettings(builder.build()); | ||
client().admin().cluster().updateSettings(updateSettings).actionGet(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a nit, but maybe
HttpExporterSslIT
so that if someone is looking forHttpExporter
test classes, they easily find itThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally named it
HttpExporterSslIT
but the combination of lower-casel
followed up uppercaseI
offended my eyes, so I changed it. I'll switch it back.