From ddd394a152e72ec634d52d1611cfcfe5c149db6f Mon Sep 17 00:00:00 2001 From: Dan Hermann Date: Wed, 13 Nov 2019 11:42:22 -0600 Subject: [PATCH 1/2] Validate monitoring password at parse time (#47740) --- .../exporter/http/HttpExporter.java | 51 ++++++++++++++----- .../exporter/http/HttpExporterTests.java | 20 ++++---- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java index 9c1f09f45340a..d6bbcf2861495 100644 --- a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java +++ b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java @@ -222,7 +222,45 @@ public Iterator> settings() { */ public static final Setting.AffixSetting AUTH_PASSWORD_SETTING = Setting.affixKeySetting("xpack.monitoring.exporters.","auth.password", - (key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered)); + (key) -> Setting.simpleString(key, + new Setting.Validator() { + @Override + public void validate(String password) { + // no password validation that is independent of other settings + } + + @Override + public void validate(String password, Map, Object> settings) { + final String namespace = + HttpExporter.AUTH_PASSWORD_SETTING.getNamespace( + HttpExporter.AUTH_PASSWORD_SETTING.getConcreteSetting(key)); + final String username = + (String) settings.get(AUTH_USERNAME_SETTING.getConcreteSettingForNamespace(namespace)); + + // username is required for any auth + if (Strings.isNullOrEmpty(username)) { + if (Strings.isNullOrEmpty(password) == false) { + throw new IllegalArgumentException( + "[" + AUTH_PASSWORD_SETTING.getConcreteSettingForNamespace(namespace).getKey() + "] without [" + + AUTH_USERNAME_SETTING.getConcreteSettingForNamespace(namespace).getKey() + "]"); + } + } + } + + @Override + public Iterator> settings() { + final String namespace = + HttpExporter.AUTH_PASSWORD_SETTING.getNamespace( + HttpExporter.AUTH_PASSWORD_SETTING.getConcreteSetting(key)); + final List> settings = List.of( + HttpExporter.AUTH_USERNAME_SETTING.getConcreteSettingForNamespace(namespace)); + return settings.iterator(); + } + + }, + Property.Dynamic, + Property.NodeScope, + Property.Filtered)); /** * The SSL settings. * @@ -626,17 +664,6 @@ private static CredentialsProvider createCredentialsProvider(final Config config final String username = AUTH_USERNAME_SETTING.getConcreteSettingForNamespace(config.name()).get(config.settings()); final String password = AUTH_PASSWORD_SETTING.getConcreteSettingForNamespace(config.name()).get(config.settings()); - // username is required for any auth - if (Strings.isNullOrEmpty(username)) { - if (Strings.isNullOrEmpty(password) == false) { - throw new SettingsException( - "[" + AUTH_PASSWORD_SETTING.getConcreteSettingForNamespace(config.name()).getKey() + "] without [" + - AUTH_USERNAME_SETTING.getConcreteSettingForNamespace(config.name()).getKey() + "]"); - } - // nothing to configure; default situation for most users - return null; - } - final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java index 3325c7190b0b5..52227b780e697 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterTests.java @@ -226,17 +226,17 @@ public void testExporterWithEmptyHeaders() { public void testExporterWithPasswordButNoUsername() { final String expected = "[xpack.monitoring.exporters._http.auth.password] without [xpack.monitoring.exporters._http.auth.username]"; - final Settings.Builder builder = Settings.builder() - .put("xpack.monitoring.exporters._http.type", HttpExporter.TYPE) - .put("xpack.monitoring.exporters._http.host", "localhost:9200") - .put("xpack.monitoring.exporters._http.auth.password", "_pass"); - - final Config config = createConfig(builder.build()); - - final SettingsException exception = expectThrows(SettingsException.class, - () -> new HttpExporter(config, sslService, threadContext)); + final String prefix = "xpack.monitoring.exporters._http"; + final Settings settings = Settings.builder() + .put(prefix + ".type", HttpExporter.TYPE) + .put(prefix + ".host", "localhost:9200") + .put(prefix + ".auth.password", "_pass") + .build(); - assertThat(exception.getMessage(), equalTo(expected)); + final IllegalArgumentException e = expectThrows( + IllegalArgumentException.class, + () -> HttpExporter.AUTH_PASSWORD_SETTING.getConcreteSetting(prefix + ".auth.password").get(settings)); + assertThat(e, hasToString(containsString(expected))); } public void testExporterWithUsernameButNoPassword() { From f80c4f35ea780534ec19ab851001a5e09c076ec9 Mon Sep 17 00:00:00 2001 From: Dan Hermann Date: Thu, 14 Nov 2019 07:18:50 -0600 Subject: [PATCH 2/2] Java8 compatibility --- .../xpack/monitoring/exporter/http/HttpExporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java index d6bbcf2861495..bb1d42afc6734 100644 --- a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java +++ b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java @@ -252,7 +252,7 @@ public Iterator> settings() { final String namespace = HttpExporter.AUTH_PASSWORD_SETTING.getNamespace( HttpExporter.AUTH_PASSWORD_SETTING.getConcreteSetting(key)); - final List> settings = List.of( + final List> settings = Collections.singletonList( HttpExporter.AUTH_USERNAME_SETTING.getConcreteSettingForNamespace(namespace)); return settings.iterator(); }