Skip to content

Commit

Permalink
Merge 9e3a591 into fc6c4a2
Browse files Browse the repository at this point in the history
  • Loading branch information
danhermann committed Jan 27, 2020
2 parents fc6c4a2 + 9e3a591 commit 8583ce9
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 54 deletions.
17 changes: 11 additions & 6 deletions docs/reference/settings/monitoring-settings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ For more information, see <<monitor-elasticsearch-cluster>>.
==== General Monitoring Settings

`xpack.monitoring.enabled`::
Set to `true` (default) to enable {es} {monitoring} for {es} on the node.
Set to `true` (default) to enable {es} {monitoring} for {es} on the node.
+
--
NOTE: To enable data collection, you must also set `xpack.monitoring.collection.enabled`
to `true`. Its default value is `false`.
NOTE: To enable data collection, you must also set `xpack.monitoring.collection.enabled`
to `true`. Its default value is `false`.
--

[float]
Expand All @@ -51,7 +51,7 @@ this setting is `false` (default), {es} monitoring data is not collected and
all monitoring data from other sources such as {kib}, Beats, and Logstash is
ignored.

`xpack.monitoring.collection.interval` (<<cluster-update-settings,Dynamic>>)::
`xpack.monitoring.collection.interval` (<<cluster-update-settings,Dynamic>>)::

Setting to `-1` to disable data collection is no longer supported beginning with
7.0.0. deprecated[6.3.0, Use `xpack.monitoring.collection.enabled` set to `false` instead.]
Expand Down Expand Up @@ -198,11 +198,16 @@ xpack.monitoring.exporters:

`auth.username`::

The username is required if a `auth.password` is supplied.
The username is required if `auth.secure_password` or `auth.password` is supplied.

`auth.secure_password` ({ref}/secure-settings.html[Secure], {ref}/secure-settings.html#reloadable-secure-settings[reloadable])::

The password for the `auth.username`. Takes precedence over `auth.password` if it is also specified.

`auth.password`::

The password for the `auth.username`.
The password for the `auth.username`. This setting is ignored if `auth.secure_password` is also specified. This setting is
deprecated[7.7.0, Use `auth.secure_password` instead.].

`connection.timeout`::

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,13 @@ public MockRequest takeRequest() {
return requests.poll();
}

/**
* Removes all requests from the queue.
*/
public void clearRequests() {
requests.clear();
}

/**
* A utility method to peek into the requests and find out if #MockWebServer.takeRequests will not throw an out of bound exception
* @return true if more requests are available, false otherwise
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.plugins.ActionPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.ReloadablePlugin;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestHandler;
import org.elasticsearch.script.ScriptService;
Expand Down Expand Up @@ -68,7 +69,7 @@
import static java.util.Collections.singletonList;
import static org.elasticsearch.common.settings.Setting.boolSetting;

public class Monitoring extends Plugin implements ActionPlugin {
public class Monitoring extends Plugin implements ActionPlugin, ReloadablePlugin {

/**
* The ability to automatically cleanup ".watcher_history*" indices while also cleaning up Monitoring indices.
Expand All @@ -80,6 +81,8 @@ public class Monitoring extends Plugin implements ActionPlugin {
protected final Settings settings;
private final boolean enabled;

private Exporters exporters;

public Monitoring(Settings settings) {
this.settings = settings;
this.enabled = XPackSettings.MONITORING_ENABLED.get(settings);
Expand Down Expand Up @@ -110,8 +113,7 @@ public Collection<Object> createComponents(Client client, ClusterService cluster
Map<String, Exporter.Factory> exporterFactories = new HashMap<>();
exporterFactories.put(HttpExporter.TYPE, config -> new HttpExporter(config, dynamicSSLService, threadPool.getThreadContext()));
exporterFactories.put(LocalExporter.TYPE, config -> new LocalExporter(config, client, cleanerService));
final Exporters exporters = new Exporters(settings, exporterFactories, clusterService, getLicenseState(),
threadPool.getThreadContext());
exporters = new Exporters(settings, exporterFactories, clusterService, getLicenseState(), threadPool.getThreadContext());

Set<Collector> collectors = new HashSet<>();
collectors.add(new IndexStatsCollector(clusterService, getLicenseState(), client));
Expand Down Expand Up @@ -178,4 +180,13 @@ public List<String> getSettingsFilter() {
final String exportersKey = "xpack.monitoring.exporters.";
return List.of(exportersKey + "*.auth.*", exportersKey + "*.ssl.*");
}

@Override
public void reload(Settings settings) throws Exception {
final List<String> changedExporters = HttpExporter.loadSettings(settings);
for (String changedExporter : changedExporters) {
final Settings settingsForChangedExporter = settings.filter(x -> x.startsWith("xpack.monitoring.exporters." + changedExporter));
exporters.setExportersSetting(settingsForChangedExporter);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.elasticsearch.xpack.core.monitoring.exporter.MonitoringDoc;
import org.elasticsearch.xpack.monitoring.collector.Collector;
import org.elasticsearch.xpack.monitoring.exporter.Exporters;
import org.elasticsearch.xpack.monitoring.exporter.http.HttpExporter;

import java.io.Closeable;
import java.util.ArrayList;
Expand Down Expand Up @@ -104,6 +105,8 @@ public class MonitoringService extends AbstractLifecycleComponent {
.addSettingsUpdateConsumer(ELASTICSEARCH_COLLECTION_ENABLED, this::setElasticsearchCollectionEnabled);
clusterService.getClusterSettings().addSettingsUpdateConsumer(ENABLED, this::setMonitoringActive);
clusterService.getClusterSettings().addSettingsUpdateConsumer(INTERVAL, this::setInterval);

HttpExporter.loadSettings(settings);
}

void setElasticsearchCollectionEnabled(final boolean enabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static java.util.Collections.emptyMap;

Expand All @@ -58,15 +59,17 @@ public Exporters(Settings settings, Map<String, Exporter.Factory> factories,
this.clusterService = Objects.requireNonNull(clusterService);
this.licenseState = Objects.requireNonNull(licenseState);

clusterService.getClusterSettings().addSettingsUpdateConsumer(this::setExportersSetting, getSettings());
final List<Setting.AffixSetting<?>> dynamicSettings =
getSettings().stream().filter(Setting::isDynamic).collect(Collectors.toList());
clusterService.getClusterSettings().addSettingsUpdateConsumer(this::setExportersSetting, dynamicSettings);
HttpExporter.registerSettingValidators(clusterService);
// this ensures, that logging is happening by adding an empty consumer per affix setting
for (Setting.AffixSetting<?> affixSetting : getSettings()) {
// this ensures that logging is happening by adding an empty consumer per affix setting
for (Setting.AffixSetting<?> affixSetting : dynamicSettings) {
clusterService.getClusterSettings().addAffixUpdateConsumer(affixSetting, (s, o) -> {}, (s, o) -> {});
}
}

private void setExportersSetting(Settings exportersSetting) {
public void setExportersSetting(Settings exportersSetting) {
if (this.lifecycle.started()) {
Map<String, Exporter> updated = initExporters(exportersSetting);
closeExporters(logger, this.exporters.getAndSet(updated));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
Expand Down Expand Up @@ -52,6 +54,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Supplier;
Expand Down Expand Up @@ -206,23 +209,20 @@ public void validate(final String username, final Map<Setting<?>, Object> settin
final String namespace =
HttpExporter.AUTH_USERNAME_SETTING.getNamespace(
HttpExporter.AUTH_USERNAME_SETTING.getConcreteSetting(key));
final String password =
(String) settings.get(AUTH_PASSWORD_SETTING.getConcreteSettingForNamespace(namespace));

// password must be specified along with username for any auth
if (Strings.isNullOrEmpty(username) == false) {
if (Strings.isNullOrEmpty(password)) {
throw new SettingsException(
"[" + AUTH_USERNAME_SETTING.getConcreteSettingForNamespace(namespace).getKey() + "] is set " +
"but [" + AUTH_PASSWORD_SETTING.getConcreteSettingForNamespace(namespace).getKey() + "] is " +
"missing");
}
final String type =
(String) settings.get(Exporter.TYPE_SETTING.getConcreteSettingForNamespace(namespace));
if ("http".equals(type) == false) {
throw new SettingsException("username for [" + key + "] is set but type is [" + type + "]");
}
}

// it would be ideal to validate that just one of either AUTH_PASSWORD_SETTING or
// AUTH_SECURE_PASSWORD_SETTING were present here, but that is not currently possible with the settings
// validation framework.
// https://github.com/elastic/elasticsearch/issues/51332
}

@Override
Expand All @@ -232,8 +232,7 @@ public Iterator<Setting<?>> settings() {
HttpExporter.AUTH_USERNAME_SETTING.getConcreteSetting(key));

final List<Setting<?>> settings = List.of(
Exporter.TYPE_SETTING.getConcreteSettingForNamespace(namespace),
HttpExporter.AUTH_PASSWORD_SETTING.getConcreteSettingForNamespace(namespace));
Exporter.TYPE_SETTING.getConcreteSettingForNamespace(namespace));
return settings.iterator();
}

Expand Down Expand Up @@ -285,8 +284,18 @@ public Iterator<Setting<?>> settings() {
},
Property.Dynamic,
Property.NodeScope,
Property.Filtered),
Property.Filtered,
Property.Deprecated),
TYPE_DEPENDENCY);
/**
* Secure password for basic auth.
*/
public static final Setting.AffixSetting<SecureString> AUTH_SECURE_PASSWORD_SETTING =
Setting.affixKeySetting(
"xpack.monitoring.exporters.",
"auth.secure_password",
key -> SecureSetting.secureString(key, null),
TYPE_DEPENDENCY);
/**
* The SSL settings.
*
Expand Down Expand Up @@ -401,6 +410,7 @@ public Iterator<Setting<?>> settings() {
*/
private final AtomicBoolean clusterAlertsAllowed = new AtomicBoolean(false);

private static final ConcurrentHashMap<String, SecureString> SECURE_AUTH_PASSWORDS = new ConcurrentHashMap<>();
private final ThreadContext threadContext;
private final DateFormatter dateTimeFormatter;

Expand Down Expand Up @@ -689,6 +699,25 @@ private static void configureTimeouts(final RestClientBuilder builder, final Con
builder.setRequestConfigCallback(new TimeoutRequestConfigCallback(connectTimeout, socketTimeout));
}


/**
* Caches secure settings for use when dynamically configuring HTTP exporters
* @param settings settings used for configuring HTTP exporter
* @return names of HTTP exporters whose secure settings changed, if any
*/
public static List<String> loadSettings(Settings settings) {
final List<String> changedExporters = new ArrayList<>();
for (final String namespace : AUTH_SECURE_PASSWORD_SETTING.getNamespaces(settings)) {
final Setting<SecureString> s = AUTH_SECURE_PASSWORD_SETTING.getConcreteSettingForNamespace(namespace);
final SecureString securePassword = s.get(settings);
final SecureString existingPassword = SECURE_AUTH_PASSWORDS.put(namespace, securePassword);
if (securePassword.equals(existingPassword) == false) {
changedExporters.add(namespace);
}
}
return changedExporters;
}

/**
* Creates the optional {@link CredentialsProvider} with the username/password to use with <em>all</em> requests for user
* authentication.
Expand All @@ -700,7 +729,11 @@ private static void configureTimeouts(final RestClientBuilder builder, final Con
@Nullable
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());

final SecureString securePassword = SECURE_AUTH_PASSWORDS.get(config.name());
final String password = securePassword == null
? AUTH_PASSWORD_SETTING.getConcreteSettingForNamespace(config.name()).get(config.settings())
: securePassword.toString();

final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
Expand Down Expand Up @@ -865,9 +898,19 @@ public void doClose() {
}
}

public static List<Setting.AffixSetting<?>> getSettings() {
public static List<Setting.AffixSetting<?>> getDynamicSettings() {
return Arrays.asList(HOST_SETTING, TEMPLATE_CREATE_LEGACY_VERSIONS_SETTING, AUTH_PASSWORD_SETTING, AUTH_USERNAME_SETTING,
BULK_TIMEOUT_SETTING, CONNECTION_READ_TIMEOUT_SETTING, CONNECTION_TIMEOUT_SETTING, PIPELINE_CHECK_TIMEOUT_SETTING,
PROXY_BASE_PATH_SETTING, SNIFF_ENABLED_SETTING, TEMPLATE_CHECK_TIMEOUT_SETTING, SSL_SETTING, HEADERS_SETTING);
}

public static List<Setting.AffixSetting<?>> getSecureSettings() {
return List.of(AUTH_SECURE_PASSWORD_SETTING);
}

public static List<Setting.AffixSetting<?>> getSettings() {
List<Setting.AffixSetting<?>> allSettings = new ArrayList<>(getDynamicSettings());
allSettings.addAll(getSecureSettings());
return allSettings;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ protected List<XPackUsageFeatureAction> usageActions() {
}
}

final Monitoring monitoring;

public LocalStateMonitoring(final Settings settings, final Path configPath) throws Exception {
super(settings, configPath);
LocalStateMonitoring thisVar = this;

plugins.add(new Monitoring(settings) {
monitoring = new Monitoring(settings) {
@Override
protected SSLService getSslService() {
return thisVar.getSslService();
Expand All @@ -63,7 +65,8 @@ protected LicenseService getLicenseService() {
protected XPackLicenseState getLicenseState() {
return thisVar.getLicenseState();
}
});
};
plugins.add(monitoring);
plugins.add(new Watcher(settings) {
@Override
protected SSLService getSslService() {
Expand All @@ -78,6 +81,10 @@ protected XPackLicenseState getLicenseState() {
plugins.add(new IndexLifecycle(settings));
}

public Monitoring getMonitoring() {
return monitoring;
}

@Override
protected Class<? extends TransportAction<XPackUsageRequest, XPackUsageResponse>> getUsageAction() {
return MonitoringTransportXPackUsageAction.class;
Expand Down

0 comments on commit 8583ce9

Please sign in to comment.