mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-17 10:25:15 +00:00
Merge branch 'master' into deprecate
Original commit: elastic/x-pack-elasticsearch@c9636bd3f1
This commit is contained in:
commit
670a57274a
@ -14,4 +14,5 @@ subprojects {
|
||||
approvedLicenses = ['Elasticsearch Confidential']
|
||||
additionalLicense 'ESCON', 'Elasticsearch Confidential', 'ELASTICSEARCH CONFIDENTIAL'
|
||||
}
|
||||
ext.projectSubstitutions += [ "org.elasticsearch.plugin:x-pack-client:${version}": ':x-plugins:elasticsearch:x-pack' ]
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ apply plugin: 'elasticsearch.rest-test'
|
||||
|
||||
dependencies {
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime')
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack-transport', configuration: 'runtime')
|
||||
}
|
||||
|
||||
String outputDir = "generated-resources/${project.name}"
|
||||
|
@ -14,7 +14,7 @@ import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
@ -118,6 +118,8 @@ public class SecurityTransportClientIT extends ESIntegTestCase {
|
||||
.put("cluster.name", clusterName)
|
||||
.build();
|
||||
|
||||
return new XPackTransportClient(settings).addTransportAddress(publishAddress);
|
||||
TransportClient client = new PreBuiltXPackTransportClient(settings);
|
||||
client.addTransportAddress(publishAddress);
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,10 @@ apply plugin: 'elasticsearch.build'
|
||||
|
||||
dependencies {
|
||||
provided "org.elasticsearch:elasticsearch:${versions.elasticsearch}"
|
||||
testCompile "org.elasticsearch.test:framework:${project.versions.elasticsearch}"
|
||||
provided project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime')
|
||||
|
||||
testCompile "org.elasticsearch.test:framework:${project.versions.elasticsearch}"
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack-transport', configuration: 'runtime')
|
||||
}
|
||||
|
||||
Map generateSubstitutions() {
|
||||
|
@ -21,7 +21,7 @@ import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -80,7 +80,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.build();
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
ClusterHealthResponse response = client.admin().cluster().prepareHealth().execute().actionGet();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
@ -100,7 +100,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER + randomAsciiOfLength(1))
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.build();
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
client.admin().cluster().prepareHealth().execute().actionGet();
|
||||
fail("authentication failure should have resulted in a NoNodesAvailableException");
|
||||
|
@ -2,6 +2,7 @@ apply plugin: 'elasticsearch.rest-test'
|
||||
|
||||
dependencies {
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime')
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack-transport', configuration: 'runtime')
|
||||
}
|
||||
|
||||
integTest {
|
||||
|
@ -15,7 +15,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
@ -77,12 +77,10 @@ public abstract class MigrateToolTestCase extends LuceneTestCase {
|
||||
.put(Security.USER_SETTING.getKey(), "transport_user:changeme")
|
||||
.build();
|
||||
|
||||
TransportClient client = new XPackTransportClient(clientSettings).addTransportAddresses(transportAddresses);
|
||||
|
||||
logger.info("--> Elasticsearch Java TransportClient started");
|
||||
|
||||
TransportClient client = new PreBuiltXPackTransportClient(clientSettings).addTransportAddresses(transportAddresses);
|
||||
Exception clientException = null;
|
||||
try {
|
||||
logger.info("--> Elasticsearch Java TransportClient started");
|
||||
ClusterHealthResponse health = client.admin().cluster().prepareHealth().get();
|
||||
logger.info("--> connected to [{}] cluster which is running [{}] node(s).",
|
||||
health.getClusterName(), health.getNumberOfNodes());
|
||||
|
30
elasticsearch/x-pack-transport/build.gradle
Normal file
30
elasticsearch/x-pack-transport/build.gradle
Normal file
@ -0,0 +1,30 @@
|
||||
import org.elasticsearch.gradle.precommit.PrecommitTasks
|
||||
|
||||
apply plugin: 'elasticsearch.build'
|
||||
apply plugin: 'nebula.maven-base-publish'
|
||||
apply plugin: 'nebula.maven-scm'
|
||||
|
||||
group = 'org.elasticsearch.client'
|
||||
|
||||
dependencies {
|
||||
compile "org.elasticsearch.plugin:x-pack-client:${version}"
|
||||
compile "org.elasticsearch.client:transport:${version}"
|
||||
testCompile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
|
||||
testCompile "junit:junit:${versions.junit}"
|
||||
testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}"
|
||||
}
|
||||
|
||||
dependencyLicenses.enabled = false
|
||||
|
||||
forbiddenApisTest {
|
||||
// we don't use the core test-framework, no lucene classes present so we don't want the es-test-signatures to
|
||||
// be pulled in
|
||||
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt'),
|
||||
PrecommitTasks.getResource('/forbidden/es-all-signatures.txt')]
|
||||
}
|
||||
|
||||
namingConventions {
|
||||
testClass = 'com.carrotsearch.randomizedtesting.RandomizedTest'
|
||||
//we don't have integration tests
|
||||
skipIntegTestInDisguise = true
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import io.netty.util.ThreadDeathWatcher;
|
||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.transport.client.PreBuiltTransportClient;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A builder to create an instance of {@link TransportClient} that pre-installs
|
||||
* all of the plugins installed by the {@link PreBuiltTransportClient} and the
|
||||
* {@link XPackPlugin} so that the client may be used with an x-pack enabled
|
||||
* cluster.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked","varargs"})
|
||||
public class PreBuiltXPackTransportClient extends PreBuiltTransportClient {
|
||||
|
||||
@SafeVarargs
|
||||
public PreBuiltXPackTransportClient(Settings settings, Class<? extends Plugin>... plugins) {
|
||||
this(settings, Arrays.asList(plugins));
|
||||
}
|
||||
|
||||
public PreBuiltXPackTransportClient(Settings settings, Collection<Class<? extends Plugin>> plugins) {
|
||||
super(settings, addPlugins(plugins, Collections.singletonList(XPackPlugin.class)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
if (NetworkModule.TRANSPORT_TYPE_SETTING.get(settings).equals(Security.NAME4)) {
|
||||
try {
|
||||
GlobalEventExecutor.INSTANCE.awaitInactivity(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
try {
|
||||
ThreadDeathWatcher.awaitInactivity(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.RandomizedTest;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link PreBuiltXPackTransportClient}
|
||||
*/
|
||||
public class PreBuiltXPackTransportClientTests extends RandomizedTest {
|
||||
|
||||
@Test
|
||||
public void testPluginInstalled() {
|
||||
try (TransportClient client = new PreBuiltXPackTransportClient(Settings.EMPTY)) {
|
||||
Settings settings = client.settings();
|
||||
assertEquals(Security.NAME4, NetworkModule.TRANSPORT_TYPE_SETTING.get(settings));
|
||||
}
|
||||
}
|
||||
}
|
@ -7,13 +7,17 @@ package org.elasticsearch.xpack.monitoring.collector.cluster;
|
||||
|
||||
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
|
||||
import org.elasticsearch.license.License;
|
||||
import org.elasticsearch.xpack.XPackFeatureSet;
|
||||
import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ClusterInfoMonitoringDoc extends MonitoringDoc {
|
||||
|
||||
private String clusterName;
|
||||
private String version;
|
||||
private License license;
|
||||
private List<XPackFeatureSet.Usage> usage;
|
||||
private ClusterStatsResponse clusterStats;
|
||||
|
||||
public ClusterInfoMonitoringDoc(String monitoringId, String monitoringVersion) {
|
||||
@ -44,6 +48,14 @@ public class ClusterInfoMonitoringDoc extends MonitoringDoc {
|
||||
this.license = license;
|
||||
}
|
||||
|
||||
public List<XPackFeatureSet.Usage> getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public void setUsage(List<XPackFeatureSet.Usage> usage) {
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
public ClusterStatsResponse getClusterStats() {
|
||||
return clusterStats;
|
||||
}
|
||||
|
@ -13,10 +13,13 @@ import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.LicenseService;
|
||||
import org.elasticsearch.license.LicenseUtils;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.xpack.XPackFeatureSet;
|
||||
import org.elasticsearch.xpack.action.XPackUsageRequestBuilder;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||
import org.elasticsearch.xpack.monitoring.collector.AbstractCollector;
|
||||
import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc;
|
||||
@ -60,25 +63,17 @@ public class ClusterStatsCollector extends AbstractCollector {
|
||||
|
||||
@Override
|
||||
protected Collection<MonitoringDoc> doCollect() throws Exception {
|
||||
List<MonitoringDoc> results = new ArrayList<>(1);
|
||||
final Supplier<ClusterStatsResponse> clusterStatsSupplier =
|
||||
() -> client.admin().cluster().prepareClusterStats().get(monitoringSettings.clusterStatsTimeout());
|
||||
final Supplier<List<XPackFeatureSet.Usage>> usageSupplier = () -> new XPackUsageRequestBuilder(client).get().getUsages();
|
||||
|
||||
// Retrieves cluster stats
|
||||
ClusterStatsResponse clusterStats = null;
|
||||
try {
|
||||
clusterStats = client.admin().cluster().prepareClusterStats().get(monitoringSettings.clusterStatsTimeout());
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
if (LicenseUtils.isLicenseExpiredException(e)) {
|
||||
logger.trace(
|
||||
(Supplier<?>) () -> new ParameterizedMessage(
|
||||
"collector [{}] - unable to collect data because of expired license", name()), e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
final ClusterStatsResponse clusterStats = clusterStatsSupplier.get();
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
String clusterUUID = clusterUUID();
|
||||
DiscoveryNode sourceNode = localNode();
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
final String clusterUUID = clusterUUID();
|
||||
final DiscoveryNode sourceNode = localNode();
|
||||
|
||||
final List<MonitoringDoc> results = new ArrayList<>(1);
|
||||
|
||||
// Adds a cluster info document
|
||||
ClusterInfoMonitoringDoc clusterInfoDoc = new ClusterInfoMonitoringDoc(monitoringId(), monitoringVersion());
|
||||
@ -89,6 +84,7 @@ public class ClusterStatsCollector extends AbstractCollector {
|
||||
clusterInfoDoc.setVersion(Version.CURRENT.toString());
|
||||
clusterInfoDoc.setLicense(licenseService.getLicense());
|
||||
clusterInfoDoc.setClusterStats(clusterStats);
|
||||
clusterInfoDoc.setUsage(collect(usageSupplier));
|
||||
results.add(clusterInfoDoc);
|
||||
|
||||
// Adds a cluster stats document
|
||||
@ -103,4 +99,21 @@ public class ClusterStatsCollector extends AbstractCollector {
|
||||
|
||||
return Collections.unmodifiableCollection(results);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> T collect(final Supplier<T> supplier) {
|
||||
try {
|
||||
return supplier.get();
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
if (LicenseUtils.isLicenseExpiredException(e)) {
|
||||
logger.trace((Supplier<?>) () -> new ParameterizedMessage(
|
||||
"collector [{}] - unable to collect data because of expired license", name()), e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,11 +11,13 @@ import org.elasticsearch.common.hash.MessageDigests;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.license.License;
|
||||
import org.elasticsearch.xpack.XPackFeatureSet;
|
||||
import org.elasticsearch.xpack.monitoring.collector.cluster.ClusterInfoMonitoringDoc;
|
||||
import org.elasticsearch.xpack.monitoring.resolver.MonitoringIndexNameResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClusterInfoResolver extends MonitoringIndexNameResolver.Data<ClusterInfoMonitoringDoc> {
|
||||
@ -34,27 +36,38 @@ public class ClusterInfoResolver extends MonitoringIndexNameResolver.Data<Cluste
|
||||
|
||||
@Override
|
||||
protected void buildXContent(ClusterInfoMonitoringDoc document, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
builder.field(Fields.CLUSTER_NAME, document.getClusterName());
|
||||
builder.field(Fields.VERSION, document.getVersion());
|
||||
builder.field("cluster_name", document.getClusterName());
|
||||
builder.field("version", document.getVersion());
|
||||
|
||||
License license = document.getLicense();
|
||||
final License license = document.getLicense();
|
||||
if (license != null) {
|
||||
builder.startObject(Fields.LICENSE);
|
||||
builder.startObject("license");
|
||||
Map<String, String> extraParams = new MapBuilder<String, String>()
|
||||
.put(License.REST_VIEW_MODE, "true")
|
||||
.map();
|
||||
params = new ToXContent.DelegatingMapParams(extraParams, params);
|
||||
license.toInnerXContent(builder, params);
|
||||
builder.field(Fields.HKEY, hash(license, document.getClusterUUID()));
|
||||
builder.field("hkey", hash(license, document.getClusterUUID()));
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
builder.startObject(Fields.CLUSTER_STATS);
|
||||
ClusterStatsResponse clusterStats = document.getClusterStats();
|
||||
final ClusterStatsResponse clusterStats = document.getClusterStats();
|
||||
if (clusterStats != null) {
|
||||
builder.startObject("cluster_stats");
|
||||
clusterStats.toXContent(builder, params);
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
final List<XPackFeatureSet.Usage> usages = document.getUsage();
|
||||
if (usages != null) {
|
||||
// in the future we may choose to add other usages under the stack_stats section, but it is only xpack for now
|
||||
// it may also be combined on the UI side of phone-home to add things like "kibana" and "logstash" under "stack_stats"
|
||||
builder.startObject("stack_stats").startObject("xpack");
|
||||
for (final XPackFeatureSet.Usage usage : usages) {
|
||||
builder.field(usage.name(), usage);
|
||||
}
|
||||
builder.endObject().endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
public static String hash(License license, String clusterName) {
|
||||
@ -66,15 +79,4 @@ public class ClusterInfoResolver extends MonitoringIndexNameResolver.Data<Cluste
|
||||
return MessageDigests.toHexString(MessageDigests.sha256().digest(toHash.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
static final class Fields {
|
||||
static final String CLUSTER_NAME = "cluster_name";
|
||||
static final String LICENSE = "license";
|
||||
static final String VERSION = "version";
|
||||
static final String CLUSTER_STATS = "cluster_stats";
|
||||
|
||||
static final String HKEY = "hkey";
|
||||
|
||||
static final String UID = "uid";
|
||||
static final String TYPE = "type";
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,16 @@ public class NodeStatsResolver extends MonitoringIndexNameResolver.Timestamped<N
|
||||
"node_stats.thread_pool.search.rejected",
|
||||
"node_stats.thread_pool.watcher.threads",
|
||||
"node_stats.thread_pool.watcher.queue",
|
||||
"node_stats.thread_pool.watcher.rejected");
|
||||
"node_stats.thread_pool.watcher.rejected",
|
||||
// Linux Only (at least for now)
|
||||
// Disk Info
|
||||
"node_stats.fs.data.spins",
|
||||
// Node IO Stats
|
||||
"node_stats.fs.io_stats.operations",
|
||||
"node_stats.fs.io_stats.read_operations",
|
||||
"node_stats.fs.io_stats.write_operations",
|
||||
"node_stats.fs.io_stats.read_kilobytes",
|
||||
"node_stats.fs.io_stats.write_kilobytes");
|
||||
FILTERS = Collections.unmodifiableSet(filters);
|
||||
}
|
||||
|
||||
|
@ -556,7 +556,34 @@
|
||||
}
|
||||
},
|
||||
"fs": {
|
||||
"type": "object"
|
||||
"properties": {
|
||||
"data": {
|
||||
"properties": {
|
||||
"spins": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io_stats": {
|
||||
"properties": {
|
||||
"operations": {
|
||||
"type": "long"
|
||||
},
|
||||
"read_operations": {
|
||||
"type": "long"
|
||||
},
|
||||
"write_operations": {
|
||||
"type": "long"
|
||||
},
|
||||
"read_kilobytes": {
|
||||
"type": "long"
|
||||
},
|
||||
"write_kilobytes": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"os": {
|
||||
"type": "object"
|
||||
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.license.License;
|
||||
import org.elasticsearch.xpack.monitoring.MonitoringFeatureSet;
|
||||
import org.elasticsearch.xpack.monitoring.collector.cluster.ClusterInfoMonitoringDoc;
|
||||
import org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils;
|
||||
import org.elasticsearch.xpack.monitoring.resolver.MonitoringIndexNameResolverTestCase;
|
||||
@ -49,6 +50,7 @@ public class ClusterInfoResolverTests extends MonitoringIndexNameResolverTestCas
|
||||
doc.setClusterName(randomAsciiOfLength(5));
|
||||
doc.setClusterStats(new ClusterStatsResponse(Math.abs(randomLong()), ClusterName.CLUSTER_NAME_SETTING
|
||||
.getDefault(Settings.EMPTY), randomAsciiOfLength(5), Collections.emptyList(), Collections.emptyList()));
|
||||
doc.setUsage(Collections.singletonList(new MonitoringFeatureSet.Usage(randomBoolean(), randomBoolean(), emptyMap())));
|
||||
return doc;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Failed to generated random ClusterInfoMonitoringDoc", e);
|
||||
@ -72,13 +74,14 @@ public class ClusterInfoResolverTests extends MonitoringIndexNameResolverTestCas
|
||||
assertThat(resolver.id(doc), equalTo(clusterUUID));
|
||||
|
||||
assertSource(resolver.source(doc, XContentType.JSON),
|
||||
Sets.newHashSet(
|
||||
"cluster_uuid",
|
||||
"timestamp",
|
||||
"source_node",
|
||||
"cluster_name",
|
||||
"version",
|
||||
"license",
|
||||
"cluster_stats"));
|
||||
Sets.newHashSet(
|
||||
"cluster_uuid",
|
||||
"timestamp",
|
||||
"source_node",
|
||||
"cluster_name",
|
||||
"version",
|
||||
"license",
|
||||
"cluster_stats",
|
||||
"stack_stats.xpack"));
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.isEmptyOrNullString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
@ -61,14 +62,14 @@ public class ClusterInfoTests extends MonitoringIntegTestCase {
|
||||
final String clusterUUID = client().admin().cluster().prepareState().setMetaData(true).get().getState().metaData().clusterUUID();
|
||||
assertTrue(Strings.hasText(clusterUUID));
|
||||
|
||||
logger.debug("--> waiting for the monitoring data index to be created (it should have been created by the ClusterInfoCollector)");
|
||||
// waiting for the monitoring data index to be created (it should have been created by the ClusterInfoCollector
|
||||
String dataIndex = ".monitoring-data-" + MonitoringTemplateUtils.TEMPLATE_VERSION;
|
||||
awaitIndexExists(dataIndex);
|
||||
|
||||
logger.debug("--> waiting for cluster info collector to collect data");
|
||||
// waiting for cluster info collector to collect data
|
||||
awaitMonitoringDocsCount(equalTo(1L), ClusterInfoResolver.TYPE);
|
||||
|
||||
logger.debug("--> retrieving cluster info document");
|
||||
// retrieving cluster info document
|
||||
GetResponse response = client().prepareGet(dataIndex, ClusterInfoResolver.TYPE, clusterUUID).get();
|
||||
assertTrue("cluster_info document does not exist in data index", response.isExists());
|
||||
|
||||
@ -80,20 +81,19 @@ public class ClusterInfoTests extends MonitoringIntegTestCase {
|
||||
assertThat(source.get(MonitoringIndexNameResolver.Fields.CLUSTER_UUID), notNullValue());
|
||||
assertThat(source.get(MonitoringIndexNameResolver.Fields.TIMESTAMP), notNullValue());
|
||||
assertThat(source.get(MonitoringIndexNameResolver.Fields.SOURCE_NODE), notNullValue());
|
||||
assertThat(source.get(ClusterInfoResolver.Fields.CLUSTER_NAME), equalTo(cluster().getClusterName()));
|
||||
assertThat(source.get(ClusterInfoResolver.Fields.VERSION), equalTo(Version.CURRENT.toString()));
|
||||
assertThat(source.get("cluster_name"), equalTo(cluster().getClusterName()));
|
||||
assertThat(source.get("version"), equalTo(Version.CURRENT.toString()));
|
||||
|
||||
logger.debug("--> checking that the document contains license information");
|
||||
Object licenseObj = source.get(ClusterInfoResolver.Fields.LICENSE);
|
||||
Object licenseObj = source.get("license");
|
||||
assertThat(licenseObj, instanceOf(Map.class));
|
||||
Map license = (Map) licenseObj;
|
||||
|
||||
assertThat(license, instanceOf(Map.class));
|
||||
|
||||
String uid = (String) license.get(ClusterInfoResolver.Fields.UID);
|
||||
String uid = (String) license.get("uid");
|
||||
assertThat(uid, not(isEmptyOrNullString()));
|
||||
|
||||
String type = (String) license.get(ClusterInfoResolver.Fields.TYPE);
|
||||
String type = (String) license.get("type");
|
||||
assertThat(type, not(isEmptyOrNullString()));
|
||||
|
||||
String status = (String) license.get(License.Fields.STATUS);
|
||||
@ -103,7 +103,7 @@ public class ClusterInfoTests extends MonitoringIntegTestCase {
|
||||
assertThat(expiryDate, greaterThan(0L));
|
||||
|
||||
// We basically recompute the hash here
|
||||
String hkey = (String) license.get(ClusterInfoResolver.Fields.HKEY);
|
||||
String hkey = (String) license.get("hkey");
|
||||
String recalculated = ClusterInfoResolver.hash(status, uid, type, String.valueOf(expiryDate), clusterUUID);
|
||||
assertThat(hkey, equalTo(recalculated));
|
||||
|
||||
@ -112,14 +112,30 @@ public class ClusterInfoTests extends MonitoringIntegTestCase {
|
||||
assertThat((Long) license.get(License.Fields.ISSUE_DATE_IN_MILLIS), greaterThan(0L));
|
||||
assertThat((Integer) license.get(License.Fields.MAX_NODES), greaterThan(0));
|
||||
|
||||
Object clusterStats = source.get(ClusterInfoResolver.Fields.CLUSTER_STATS);
|
||||
Object clusterStats = source.get("cluster_stats");
|
||||
assertNotNull(clusterStats);
|
||||
assertThat(clusterStats, instanceOf(Map.class));
|
||||
assertThat(((Map) clusterStats).size(), greaterThan(0));
|
||||
|
||||
Object stackStats = source.get("stack_stats");
|
||||
assertNotNull(stackStats);
|
||||
assertThat(stackStats, instanceOf(Map.class));
|
||||
assertThat(((Map) stackStats).size(), equalTo(1));
|
||||
|
||||
Object xpack = ((Map)stackStats).get("xpack");
|
||||
assertNotNull(xpack);
|
||||
assertThat(xpack, instanceOf(Map.class));
|
||||
// it must have at least monitoring, but others may be hidden
|
||||
assertThat(((Map) xpack).size(), greaterThanOrEqualTo(1));
|
||||
|
||||
Object monitoring = ((Map)xpack).get("monitoring");
|
||||
assertNotNull(monitoring);
|
||||
// we don't make any assumptions about what's in it, only that it's there
|
||||
assertThat(monitoring, instanceOf(Map.class));
|
||||
|
||||
waitForMonitoringTemplates();
|
||||
|
||||
logger.debug("--> check that the cluster_info is not indexed");
|
||||
// check that the cluster_info is not indexed
|
||||
securedFlush();
|
||||
securedRefresh();
|
||||
|
||||
@ -131,8 +147,7 @@ public class ClusterInfoTests extends MonitoringIntegTestCase {
|
||||
.should(QueryBuilders.matchQuery(License.Fields.STATUS, License.Status.ACTIVE.label()))
|
||||
.should(QueryBuilders.matchQuery(License.Fields.STATUS, License.Status.INVALID.label()))
|
||||
.should(QueryBuilders.matchQuery(License.Fields.STATUS, License.Status.EXPIRED.label()))
|
||||
.should(QueryBuilders.matchQuery(ClusterInfoResolver.Fields.CLUSTER_NAME,
|
||||
cluster().getClusterName()))
|
||||
.should(QueryBuilders.matchQuery("cluster_name", cluster().getClusterName()))
|
||||
.minimumNumberShouldMatch(1)
|
||||
).get(), 0L);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.cluster.routing.RecoverySource;
|
||||
import org.elasticsearch.cluster.routing.ShardRouting;
|
||||
import org.elasticsearch.cluster.routing.UnassignedInfo;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.transport.LocalTransportAddress;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
@ -81,6 +82,19 @@ public class NodeStatsResolverTests extends MonitoringIndexNameResolverTestCase<
|
||||
if (Constants.WINDOWS && field.startsWith("node_stats.os.cpu.load_average")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we only report IoStats and spins on Linux
|
||||
if (Constants.LINUX == false) {
|
||||
if (field.startsWith("node_stats.fs.io_stats")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// node_stats.fs.data.spins can be null and it's only reported on Linux
|
||||
if (field.startsWith("node_stats.fs.data.spins")) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.assertSourceField(field, sourceFields);
|
||||
}
|
||||
|
||||
@ -140,6 +154,22 @@ public class NodeStatsResolverTests extends MonitoringIndexNameResolverTestCase<
|
||||
new NodeIndicesStats(new CommonStats(), statsByShard), OsProbe.getInstance().osStats(),
|
||||
ProcessProbe.getInstance().processStats(), JvmStats.jvmStats(),
|
||||
new ThreadPoolStats(threadPoolStats),
|
||||
new FsInfo(0, null, pathInfo), null, null, null, null, null, null);
|
||||
new FsInfo(0, randomIoStats(), pathInfo), null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FsInfo.IoStats randomIoStats() {
|
||||
if (Constants.LINUX) {
|
||||
final int stats = randomIntBetween(1, 3);
|
||||
final FsInfo.DeviceStats[] devices = new FsInfo.DeviceStats[stats];
|
||||
|
||||
for (int i = 0; i < devices.length; ++i) {
|
||||
devices[i] = new FsInfo.DeviceStats(253, 0, "dm-" + i, 287734, 7185242, 8398869, 118857776, null);
|
||||
}
|
||||
|
||||
return new FsInfo.IoStats(devices);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -519,9 +519,6 @@ public abstract class MonitoringIntegTestCase extends ESIntegTestCase {
|
||||
"\n" +
|
||||
"admin:\n" +
|
||||
" cluster: [ 'cluster:monitor/nodes/info', 'cluster:monitor/nodes/liveness' ]\n" +
|
||||
"transport_client:\n" +
|
||||
" cluster: [ 'cluster:monitor/nodes/info', 'cluster:monitor/nodes/liveness' ]\n" +
|
||||
"\n" +
|
||||
"monitor:\n" +
|
||||
" cluster: [ 'cluster:monitor/nodes/info', 'cluster:monitor/nodes/liveness' ]\n"
|
||||
;
|
||||
|
@ -30,10 +30,7 @@ public class AuthenticateRequest extends ActionRequest<AuthenticateRequest> impl
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
Validation.Error error = Validation.Users.validateUsername(username);
|
||||
if (error != null) {
|
||||
return addValidationError(error.toString(), null);
|
||||
}
|
||||
// we cannot apply our validation rules here as an authenticate request could be for an LDAP user that doesn't fit our restrictions
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.security.InternalClient;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
||||
@ -740,9 +740,9 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||
+ REMOTE_CLIENT_SETTINGS.getKey() + ".hosts]");
|
||||
}
|
||||
final Settings theClientSetting = clientSettings.filter((s) -> s.startsWith("hosts") == false); // hosts is not a valid setting
|
||||
final TransportClient transportClient = new XPackTransportClient(Settings.builder()
|
||||
.put("node.name", DEFAULT_CLIENT_NAME + "-" + Node.NODE_NAME_SETTING.get(settings))
|
||||
.put(theClientSetting).build());
|
||||
final TransportClient transportClient = new TransportClient(Settings.builder()
|
||||
.put("node.name", DEFAULT_CLIENT_NAME + "-" + Node.NODE_NAME_SETTING.get(settings))
|
||||
.put(theClientSetting).build(), Settings.EMPTY, Collections.singletonList(XPackPlugin.class)) {};
|
||||
for (Tuple<String, Integer> pair : hostPortPairs) {
|
||||
try {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(pair.v1()), pair.v2()));
|
||||
|
@ -80,9 +80,6 @@ public class FileUserPasswdStore {
|
||||
}
|
||||
|
||||
public boolean verifyPassword(String username, SecuredString password) {
|
||||
if (users == null) {
|
||||
return false;
|
||||
}
|
||||
char[] hash = users.get(username);
|
||||
return hash != null && hasher.verify(password, hash);
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ public class FileUserRolesStore {
|
||||
continue;
|
||||
}
|
||||
String role = line.substring(0, i).trim();
|
||||
Validation.Error validationError = Validation.Roles.validateRoleName(role);
|
||||
Validation.Error validationError = Validation.Roles.validateRoleName(role, true);
|
||||
if (validationError != null) {
|
||||
logger.error("invalid role entry in users_roles file [{}], line [{}] - {}. skipping...", path.toAbsolutePath(), lineNr,
|
||||
validationError);
|
||||
|
@ -446,7 +446,7 @@ public class UsersTool extends MultiCommand {
|
||||
}
|
||||
String[] roles = rolesStr.split(",");
|
||||
for (String role : roles) {
|
||||
Validation.Error validationError = Validation.Roles.validateRoleName(role);
|
||||
Validation.Error validationError = Validation.Roles.validateRoleName(role, true);
|
||||
if (validationError != null) {
|
||||
throw new UserException(ExitCodes.DATA_ERROR, "Invalid role [" + role + "]... " + validationError);
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ public class RoleDescriptor implements ToXContent {
|
||||
|
||||
public static RoleDescriptor parse(String name, XContentParser parser) throws IOException {
|
||||
// validate name
|
||||
Validation.Error validationError = Validation.Roles.validateRoleName(name);
|
||||
Validation.Error validationError = Validation.Roles.validateRoleName(name, true);
|
||||
if (validationError != null) {
|
||||
ValidationException ve = new ValidationException();
|
||||
ve.addValidationError(validationError.toString());
|
||||
|
@ -5,6 +5,9 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.security.support;
|
||||
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@ -19,12 +22,16 @@ public final class Validation {
|
||||
private static final int MIN_PASSWD_LENGTH = 6;
|
||||
|
||||
public static Error validateUsername(String username) {
|
||||
return COMMON_NAME_PATTERN.matcher(username).matches() ?
|
||||
null :
|
||||
new Error("A valid username must be at least 1 character and no longer than 30 characters. " +
|
||||
"It must begin with a letter (`a-z` or `A-Z`) or an underscore (`_`). Subsequent " +
|
||||
"characters can be letters, underscores (`_`), digits (`0-9`) or any of the following " +
|
||||
"symbols `@`, `-`, `.` or `$`");
|
||||
if (COMMON_NAME_PATTERN.matcher(username).matches() == false) {
|
||||
return new Error("A valid username must be at least 1 character and no longer than 30 characters. " +
|
||||
"It must begin with a letter (`a-z` or `A-Z`) or an underscore (`_`). Subsequent " +
|
||||
"characters can be letters, underscores (`_`), digits (`0-9`) or any of the following " +
|
||||
"symbols `@`, `-`, `.` or `$`");
|
||||
}
|
||||
if (ReservedRealm.isReserved(username)) {
|
||||
return new Error("Username [" + username + "] is reserved and may not be used.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Error validatePassword(char[] password) {
|
||||
@ -38,12 +45,20 @@ public final class Validation {
|
||||
public static final class Roles {
|
||||
|
||||
public static Error validateRoleName(String roleName) {
|
||||
return COMMON_NAME_PATTERN.matcher(roleName).matches() ?
|
||||
null :
|
||||
new Error("A valid role name must be at least 1 character and no longer than 30 characters. " +
|
||||
"It must begin with a letter (`a-z` or `A-Z`) or an underscore (`_`). Subsequent " +
|
||||
"characters can be letters, underscores (`_`), digits (`0-9`) or any of the following " +
|
||||
"symbols `@`, `-`, `.` or `$`");
|
||||
return validateRoleName(roleName, false);
|
||||
}
|
||||
|
||||
public static Error validateRoleName(String roleName, boolean allowReserved) {
|
||||
if (COMMON_NAME_PATTERN.matcher(roleName).matches() == false) {
|
||||
return new Error("A valid role name must be at least 1 character and no longer than 30 characters. " +
|
||||
"It must begin with a letter (`a-z` or `A-Z`) or an underscore (`_`). Subsequent " +
|
||||
"characters can be letters, underscores (`_`), digits (`0-9`) or any of the following " +
|
||||
"symbols `@`, `-`, `.` or `$`");
|
||||
}
|
||||
if (allowReserved == false && ReservedRolesStore.isReserved(roleName)) {
|
||||
return new Error("Role [" + roleName + "] is reserved and may not be used.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,11 +43,6 @@ public class PermissionPrecedenceTests extends SecurityIntegTestCase {
|
||||
" - names: '*'\n" +
|
||||
" privileges: [ all ]" +
|
||||
"\n" +
|
||||
"transport_client:\n" +
|
||||
" cluster:\n" +
|
||||
" - cluster:monitor/nodes/info\n" +
|
||||
" - cluster:monitor/state\n" +
|
||||
"\n" +
|
||||
"user:\n" +
|
||||
" indices:\n" +
|
||||
" - names: 'test_*'\n" +
|
||||
|
@ -33,7 +33,7 @@ import org.elasticsearch.transport.Netty3Plugin;
|
||||
import org.elasticsearch.transport.Netty4Plugin;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.action.user.GetUsersResponse;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
@ -190,7 +190,7 @@ public class LicensingTests extends SecurityIntegTestCase {
|
||||
|
||||
public void testSecurityActionsByLicenseType() throws Exception {
|
||||
// security actions should not work!
|
||||
try (TransportClient client = new XPackTransportClient(internalCluster().transportClient().settings())) {
|
||||
try (TransportClient client = new TestXPackTransportClient(internalCluster().transportClient().settings())) {
|
||||
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
|
||||
new SecurityClient(client).prepareGetUsers().get();
|
||||
fail("security actions should not be enabled!");
|
||||
@ -204,7 +204,7 @@ public class LicensingTests extends SecurityIntegTestCase {
|
||||
License.OperationMode.PLATINUM, License.OperationMode.STANDARD);
|
||||
enableLicensing(mode);
|
||||
// security actions should not work!
|
||||
try (TransportClient client = new XPackTransportClient(internalCluster().transportClient().settings())) {
|
||||
try (TransportClient client = new TestXPackTransportClient(internalCluster().transportClient().settings())) {
|
||||
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
|
||||
GetUsersResponse response = new SecurityClient(client).prepareGetUsers().get();
|
||||
assertNotNull(response);
|
||||
@ -219,7 +219,7 @@ public class LicensingTests extends SecurityIntegTestCase {
|
||||
builder.remove(ThreadContext.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER);
|
||||
|
||||
// basic has no auth
|
||||
try (TransportClient client = new XPackTransportClient(builder.build())) {
|
||||
try (TransportClient client = new TestXPackTransportClient(builder.build())) {
|
||||
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
|
||||
assertGreenClusterState(client);
|
||||
}
|
||||
@ -229,7 +229,7 @@ public class LicensingTests extends SecurityIntegTestCase {
|
||||
License.OperationMode.PLATINUM, License.OperationMode.STANDARD);
|
||||
enableLicensing(mode);
|
||||
|
||||
try (TransportClient client = new XPackTransportClient(builder.build())) {
|
||||
try (TransportClient client = new TestXPackTransportClient(builder.build())) {
|
||||
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
|
||||
client.admin().cluster().prepareHealth().get();
|
||||
fail("should not have been able to connect to a node!");
|
||||
|
@ -57,7 +57,7 @@ public class SecuritySettingsSource extends ClusterDiscoveryConfiguration.Unicas
|
||||
public static final String DEFAULT_PASSWORD_HASHED = new String(Hasher.BCRYPT.hash(new SecuredString(DEFAULT_PASSWORD.toCharArray())));
|
||||
public static final String DEFAULT_ROLE = "user";
|
||||
|
||||
public static final String DEFAULT_TRANSPORT_CLIENT_ROLE = "trans_client_user";
|
||||
public static final String DEFAULT_TRANSPORT_CLIENT_ROLE = "transport_client";
|
||||
public static final String DEFAULT_TRANSPORT_CLIENT_USER_NAME = "test_trans_client_user";
|
||||
|
||||
public static final String CONFIG_STANDARD_USER =
|
||||
@ -73,10 +73,7 @@ public class SecuritySettingsSource extends ClusterDiscoveryConfiguration.Unicas
|
||||
" cluster: [ ALL ]\n" +
|
||||
" indices:\n" +
|
||||
" - names: '*'\n" +
|
||||
" privileges: [ ALL ]\n" +
|
||||
DEFAULT_TRANSPORT_CLIENT_ROLE + ":\n" +
|
||||
" cluster:\n" +
|
||||
" - transport_client";
|
||||
" privileges: [ ALL ]\n";
|
||||
|
||||
private final Path parentFolder;
|
||||
private final String subfolderPrefix;
|
||||
|
@ -22,7 +22,7 @@ import org.elasticsearch.xpack.security.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -39,8 +39,6 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
||||
static final String RUN_AS_USER = "run_as_user";
|
||||
static final String TRANSPORT_CLIENT_USER = "transport_user";
|
||||
static final String ROLES =
|
||||
"transport_client:\n" +
|
||||
" cluster: [ 'cluster:monitor/nodes/liveness' ]\n" +
|
||||
"run_as_role:\n" +
|
||||
" run_as: [ '" + SecuritySettingsSource.DEFAULT_USER_NAME + "', 'idontexist' ]\n";
|
||||
|
||||
@ -231,7 +229,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
||||
.put("xpack.security.transport.ssl.enabled", false)
|
||||
.build();
|
||||
|
||||
return new XPackTransportClient(settings)
|
||||
return new TestXPackTransportClient(settings)
|
||||
.addTransportAddress(publishAddress);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import org.elasticsearch.xpack.ssl.SSLClientAuth;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@ -155,7 +155,7 @@ public class PkiAuthenticationTests extends SecurityIntegTestCase {
|
||||
.put("cluster.name", internalCluster().getClusterName());
|
||||
builder.remove(Security.USER_SETTING.getKey());
|
||||
builder.remove("request.headers.Authorization");
|
||||
return new XPackTransportClient(builder.build());
|
||||
return new TestXPackTransportClient(builder.build());
|
||||
}
|
||||
|
||||
private String getNodeUrl() {
|
||||
|
@ -17,7 +17,7 @@ import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
@ -108,7 +108,7 @@ public class PkiOptionalClientAuthTests extends SecurityIntegTestCase {
|
||||
.build();
|
||||
|
||||
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
try (TransportClient client = new TestXPackTransportClient(settings)) {
|
||||
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), port));
|
||||
assertGreenClusterState(client);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ package org.elasticsearch.xpack.security.authz.store;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
@ -361,14 +360,14 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||
|
||||
assertThat(roles, hasKey("admin"));
|
||||
|
||||
List<String> events = CapturingLogger.output(logger.getName(), Level.WARN);
|
||||
List<String> events = CapturingLogger.output(logger.getName(), Level.ERROR);
|
||||
assertThat(events, notNullValue());
|
||||
assertThat(events, hasSize(4));
|
||||
// the system role will always be checked first
|
||||
assertThat(events.get(0), containsString("role [_system] is reserved"));
|
||||
assertThat(events.get(1), containsString("role [superuser] is reserved"));
|
||||
assertThat(events.get(2), containsString("role [kibana] is reserved"));
|
||||
assertThat(events.get(3), containsString("role [transport_client] is reserved"));
|
||||
assertThat(events.get(0), containsString("Role [_system] is reserved"));
|
||||
assertThat(events.get(1), containsString("Role [superuser] is reserved"));
|
||||
assertThat(events.get(2), containsString("Role [kibana] is reserved"));
|
||||
assertThat(events.get(3), containsString("Role [transport_client] is reserved"));
|
||||
}
|
||||
|
||||
public void testUsageStats() throws Exception {
|
||||
|
@ -5,11 +5,16 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.security.support;
|
||||
|
||||
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
|
||||
import org.elasticsearch.xpack.security.support.Validation.Error;
|
||||
import org.elasticsearch.xpack.security.support.Validation.Users;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.user.KibanaUser;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
@ -53,6 +58,13 @@ public class ValidationTests extends ESTestCase {
|
||||
assertThat(Users.validateUsername(name), nullValue());
|
||||
}
|
||||
|
||||
public void testReservedUsernames() {
|
||||
final String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME);
|
||||
final Error error = Users.validateUsername(username);
|
||||
assertNotNull(error);
|
||||
assertThat(error.toString(), containsString("is reserved"));
|
||||
}
|
||||
|
||||
public void testUsersValidateUsernameInvalidLength() throws Exception {
|
||||
int length = frequently() ? randomIntBetween(31, 200) : 0; // invalid length
|
||||
char[] name = new char[length];
|
||||
@ -84,6 +96,16 @@ public class ValidationTests extends ESTestCase {
|
||||
assertThat(Validation.Roles.validateRoleName(name), nullValue());
|
||||
}
|
||||
|
||||
public void testReservedRoleName() {
|
||||
final String rolename = randomFrom(ReservedRolesStore.names());
|
||||
final Error error = Validation.Roles.validateRoleName(rolename);
|
||||
assertNotNull(error);
|
||||
assertThat(error.toString(), containsString("is reserved"));
|
||||
|
||||
final Error allowed = Validation.Roles.validateRoleName(rolename, true);
|
||||
assertNull(allowed);
|
||||
}
|
||||
|
||||
public void testRolesValidateRoleNameInvalidLength() throws Exception {
|
||||
int length = frequently() ? randomIntBetween(31, 200) : 0; // invalid length
|
||||
char[] name = new char[length];
|
||||
|
@ -14,7 +14,7 @@ import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Files;
|
||||
@ -99,7 +99,7 @@ public class SslHostnameVerificationTests extends SecurityIntegTestCase {
|
||||
.put("xpack.ssl.verification_mode", "full")
|
||||
.build();
|
||||
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
try (TransportClient client = new TestXPackTransportClient(settings)) {
|
||||
client.addTransportAddress(new InetSocketTransportAddress(inetSocketAddress.getAddress(), inetSocketAddress.getPort()));
|
||||
client.admin().cluster().prepareHealth().get();
|
||||
fail("Expected a NoNodeAvailableException due to hostname verification failures");
|
||||
|
@ -26,7 +26,7 @@ import org.elasticsearch.http.HttpServerTransport;
|
||||
import org.elasticsearch.xpack.ssl.SSLService;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
@ -57,7 +57,7 @@ public class SslIntegrationTests extends SecurityIntegTestCase {
|
||||
|
||||
// no SSL exception as this is the exception is returned when connecting
|
||||
public void testThatUnconfiguredCiphersAreRejected() {
|
||||
try (TransportClient transportClient = new XPackTransportClient(Settings.builder()
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(Settings.builder()
|
||||
.put(transportClientSettings())
|
||||
.put("node.name", "programmatic_transport_client")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
@ -76,7 +76,7 @@ public class SslIntegrationTests extends SecurityIntegTestCase {
|
||||
|
||||
// no SSL exception as this is the exception is returned when connecting
|
||||
public void testThatTransportClientUsingSSLv3ProtocolIsRejected() {
|
||||
try(TransportClient transportClient = new XPackTransportClient(Settings.builder()
|
||||
try(TransportClient transportClient = new TestXPackTransportClient(Settings.builder()
|
||||
.put(transportClientSettings())
|
||||
.put("node.name", "programmatic_transport_client")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
|
@ -14,7 +14,7 @@ import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.ssl.SSLClientAuth;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.net.InetAddress;
|
||||
@ -103,7 +103,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put(additionalSettings)
|
||||
.build();
|
||||
return new XPackTransportClient(settings);
|
||||
return new TestXPackTransportClient(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,7 +236,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put("xpack.security.transport.ssl.enabled", false)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), getProfilePort("no_ssl")));
|
||||
assertGreenClusterState(transportClient);
|
||||
}
|
||||
@ -251,7 +251,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
|
||||
assertGreenClusterState(transportClient);
|
||||
fail("Expected NoNodeAvailableException");
|
||||
@ -269,7 +269,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), getProfilePort("client")));
|
||||
assertGreenClusterState(transportClient);
|
||||
fail("Expected NoNodeAvailableException");
|
||||
@ -287,7 +287,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(),
|
||||
getProfilePort("no_client_auth")));
|
||||
assertGreenClusterState(transportClient);
|
||||
@ -311,7 +311,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/truststore-testnode-only.jks"))
|
||||
.put("xpack.ssl.truststore.password", "truststore-testnode-only")
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(),
|
||||
getProfilePort("no_client_auth")));
|
||||
assertGreenClusterState(transportClient);
|
||||
@ -333,7 +333,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/truststore-testnode-only.jks"))
|
||||
.put("xpack.ssl.truststore.password", "truststore-testnode-only")
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), getProfilePort("client")));
|
||||
assertGreenClusterState(transportClient);
|
||||
fail("Expected NoNodeAvailableException");
|
||||
@ -357,7 +357,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/truststore-testnode-only.jks"))
|
||||
.put("xpack.ssl.truststore.password", "truststore-testnode-only")
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
|
||||
assertGreenClusterState(transportClient);
|
||||
fail("Expected NoNodeAvailableException");
|
||||
@ -380,7 +380,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/truststore-testnode-only.jks"))
|
||||
.put("xpack.ssl.truststore.password", "truststore-testnode-only")
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), getProfilePort("no_ssl")));
|
||||
assertGreenClusterState(transportClient);
|
||||
fail("Expected NoNodeAvailableException");
|
||||
@ -400,7 +400,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
|
||||
assertGreenClusterState(transportClient);
|
||||
fail("Expected NoNodeAvailableException");
|
||||
@ -420,7 +420,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), getProfilePort("client")));
|
||||
assertGreenClusterState(transportClient);
|
||||
fail("Expected NoNodeAvailableException");
|
||||
@ -440,7 +440,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.build();
|
||||
try (TransportClient transportClient = new XPackTransportClient(settings)) {
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(),
|
||||
getProfilePort("no_client_auth")));
|
||||
assertGreenClusterState(transportClient);
|
||||
|
@ -264,16 +264,16 @@ public class CertUtils {
|
||||
/**
|
||||
* Generates a CA certificate
|
||||
*/
|
||||
static X509Certificate generateCACertificate(X500Principal x500Principal, KeyPair keyPair) throws Exception {
|
||||
return generateSignedCertificate(x500Principal, null, keyPair, null, null, true);
|
||||
static X509Certificate generateCACertificate(X500Principal x500Principal, KeyPair keyPair, int days) throws Exception {
|
||||
return generateSignedCertificate(x500Principal, null, keyPair, null, null, true, days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a signed certificate using the provided CA private key and information from the CA certificate
|
||||
*/
|
||||
static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
|
||||
X509Certificate caCert, PrivateKey caPrivKey) throws Exception {
|
||||
return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false);
|
||||
X509Certificate caCert, PrivateKey caPrivKey, int days) throws Exception {
|
||||
return generateSignedCertificate(principal, subjectAltNames, keyPair, caCert, caPrivKey, false, days);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -289,9 +289,15 @@ public class CertUtils {
|
||||
* @throws Exception if an error occurs during the certificate creation
|
||||
*/
|
||||
private static X509Certificate generateSignedCertificate(X500Principal principal, GeneralNames subjectAltNames, KeyPair keyPair,
|
||||
X509Certificate caCert, PrivateKey caPrivKey, boolean isCa) throws Exception {
|
||||
X509Certificate caCert, PrivateKey caPrivKey, boolean isCa
|
||||
|
||||
, int days) throws
|
||||
Exception {
|
||||
final DateTime notBefore = new DateTime(DateTimeZone.UTC);
|
||||
final DateTime notAfter = notBefore.plusYears(1);
|
||||
if (days < 1) {
|
||||
throw new IllegalArgumentException("the certificate must be valid for at least one day");
|
||||
}
|
||||
final DateTime notAfter = notBefore.plusDays(days);
|
||||
final BigInteger serial = CertUtils.getSerial();
|
||||
JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
|
||||
|
||||
|
@ -67,6 +67,7 @@ public class CertificateTool extends SettingCommand {
|
||||
private static final String DESCRIPTION = "Simplifies certificate creation for use with the Elastic Stack";
|
||||
private static final String DEFAULT_CSR_FILE = "csr-bundle.zip";
|
||||
private static final String DEFAULT_CERT_FILE = "certificate-bundle.zip";
|
||||
private static final int DEFAULT_DAYS = 3 * 365;
|
||||
private static final int FILE_EXTENSION_LENGTH = 4;
|
||||
static final int MAX_FILENAME_LENGTH = 255 - FILE_EXTENSION_LENGTH;
|
||||
private static final Pattern ALLOWED_FILENAME_CHAR_PATTERN =
|
||||
@ -95,6 +96,7 @@ public class CertificateTool extends SettingCommand {
|
||||
private final OptionSpec<String> caDnSpec;
|
||||
private final OptionSpec<Integer> keysizeSpec;
|
||||
private final OptionSpec<String> inputFileSpec;
|
||||
private final OptionSpec<Integer> daysSpec;
|
||||
|
||||
CertificateTool() {
|
||||
super(DESCRIPTION);
|
||||
@ -114,6 +116,8 @@ public class CertificateTool extends SettingCommand {
|
||||
.withRequiredArg();
|
||||
keysizeSpec = parser.accepts("keysize", "size in bits of RSA keys").withRequiredArg().ofType(Integer.class);
|
||||
inputFileSpec = parser.accepts("in", "file containing details of the instances in yaml format").withRequiredArg();
|
||||
daysSpec =
|
||||
parser.accepts("days", "number of days that the generated certificates are valid").withRequiredArg().ofType(Integer.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@ -135,10 +139,11 @@ public class CertificateTool extends SettingCommand {
|
||||
final String dn = options.has(caDnSpec) ? caDnSpec.value(options) : AUTO_GEN_CA_DN;
|
||||
final boolean prompt = options.has(caPasswordSpec);
|
||||
final char[] keyPass = options.hasArgument(caPasswordSpec) ? caPasswordSpec.value(options).toCharArray() : null;
|
||||
CAInfo caInfo =
|
||||
getCAInfo(terminal, dn, caCertPathSpec.value(options), caKeyPathSpec.value(options), keyPass, prompt, env, keysize);
|
||||
final int days = options.hasArgument(daysSpec) ? daysSpec.value(options) : DEFAULT_DAYS;
|
||||
CAInfo caInfo = getCAInfo(terminal, dn, caCertPathSpec.value(options), caKeyPathSpec.value(options), keyPass, prompt, env,
|
||||
keysize, days);
|
||||
Collection<CertificateInformation> certificateInformations = getCertificateInformationList(terminal, inputFile, env);
|
||||
generateAndWriteSignedCertificates(outputFile, certificateInformations, caInfo, keysize);
|
||||
generateAndWriteSignedCertificates(outputFile, certificateInformations, caInfo, keysize, days);
|
||||
}
|
||||
printConclusion(terminal, csrOnly, outputFile);
|
||||
}
|
||||
@ -281,12 +286,15 @@ public class CertificateTool extends SettingCommand {
|
||||
* @param dn the distinguished name to use for the CA
|
||||
* @param caCertPath the path to the CA certificate or {@code null} if not provided
|
||||
* @param caKeyPath the path to the CA private key or {@code null} if not provided
|
||||
* @param prompt whether we should prompt the user for a password
|
||||
* @param keyPass the password to the private key. If not present and the key is encrypted the user will be prompted
|
||||
* @param env the environment for this tool to resolve files with
|
||||
* @param keysize the size of the key in bits
|
||||
* @param days the number of days that the certificate should be valid for
|
||||
* @return CA cert and private key
|
||||
*/
|
||||
static CAInfo getCAInfo(Terminal terminal, String dn, String caCertPath, String caKeyPath, char[] keyPass, boolean prompt,
|
||||
Environment env, int keysize) throws Exception {
|
||||
Environment env, int keysize, int days) throws Exception {
|
||||
if (caCertPath != null) {
|
||||
assert caKeyPath != null;
|
||||
Certificate[] certificates = CertUtils.readCertificates(Collections.singletonList(caCertPath), env);
|
||||
@ -302,7 +310,7 @@ public class CertificateTool extends SettingCommand {
|
||||
// generate the CA keys and cert
|
||||
X500Principal x500Principal = new X500Principal(dn);
|
||||
KeyPair keyPair = CertUtils.generateKeyPair(keysize);
|
||||
Certificate caCert = CertUtils.generateCACertificate(x500Principal, keyPair);
|
||||
Certificate caCert = CertUtils.generateCACertificate(x500Principal, keyPair, days);
|
||||
final char[] password;
|
||||
if (prompt) {
|
||||
password = terminal.readSecret("Enter password for CA private key: ");
|
||||
@ -317,9 +325,11 @@ public class CertificateTool extends SettingCommand {
|
||||
* @param outputFile the file that the certificates will be written to. This file must not exist
|
||||
* @param certificateInformations details for creation of the certificates
|
||||
* @param caInfo the CA information to sign the certificates with
|
||||
* @param keysize the size of the key in bits
|
||||
* @param days the number of days that the certificate should be valid for
|
||||
*/
|
||||
static void generateAndWriteSignedCertificates(Path outputFile, Collection<CertificateInformation> certificateInformations,
|
||||
CAInfo caInfo, int keysize) throws Exception {
|
||||
CAInfo caInfo, int keysize, int days) throws Exception {
|
||||
fullyWriteFile(outputFile, (outputStream, pemWriter) -> {
|
||||
// write out the CA info first if it was generated
|
||||
writeCAInfoIfGenerated(outputStream, pemWriter, caInfo);
|
||||
@ -328,7 +338,7 @@ public class CertificateTool extends SettingCommand {
|
||||
KeyPair keyPair = CertUtils.generateKeyPair(keysize);
|
||||
Certificate certificate = CertUtils.generateSignedCertificate(certificateInformation.name.x500Principal,
|
||||
getSubjectAlternativeNamesValue(certificateInformation.ipAddresses, certificateInformation.dnsNames),
|
||||
keyPair, caInfo.caCert, caInfo.privateKey);
|
||||
keyPair, caInfo.caCert, caInfo.privateKey, days);
|
||||
|
||||
final String dirName = certificateInformation.name.filename + "/";
|
||||
ZipEntry zipEntry = new ZipEntry(dirName);
|
||||
|
@ -9,7 +9,6 @@ import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
@ -17,14 +16,14 @@ import java.util.Collection;
|
||||
* TransportClient.Builder that installs the XPackPlugin by default.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked","varargs"})
|
||||
public class XPackTransportClient extends TransportClient {
|
||||
public class TestXPackTransportClient extends TransportClient {
|
||||
|
||||
@SafeVarargs
|
||||
public XPackTransportClient(Settings settings, Class<? extends Plugin>... plugins) {
|
||||
public TestXPackTransportClient(Settings settings, Class<? extends Plugin>... plugins) {
|
||||
this(settings, Arrays.asList(plugins));
|
||||
}
|
||||
|
||||
public XPackTransportClient(Settings settings, Collection<Class<? extends Plugin>> plugins) {
|
||||
public TestXPackTransportClient(Settings settings, Collection<Class<? extends Plugin>> plugins) {
|
||||
super(settings, Settings.EMPTY, addPlugins(plugins, XPackPlugin.class));
|
||||
}
|
||||
}
|
@ -42,6 +42,7 @@ import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAKey;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -207,14 +208,15 @@ public class CertificateToolTests extends ESTestCase {
|
||||
assertEquals(4, certInfos.size());
|
||||
|
||||
final int keysize = randomFrom(1024, 2048);
|
||||
final int days = randomIntBetween(1, 1024);
|
||||
KeyPair keyPair = CertUtils.generateKeyPair(keysize);
|
||||
X509Certificate caCert = CertUtils.generateCACertificate(new X500Principal("CN=test ca"), keyPair);
|
||||
X509Certificate caCert = CertUtils.generateCACertificate(new X500Principal("CN=test ca"), keyPair, days);
|
||||
|
||||
final boolean generatedCa = randomBoolean();
|
||||
final char[] keyPassword = randomBoolean() ? "changeme".toCharArray() : null;
|
||||
assertFalse(Files.exists(outputFile));
|
||||
CAInfo caInfo = new CAInfo(caCert, keyPair.getPrivate(), generatedCa, keyPassword);
|
||||
CertificateTool.generateAndWriteSignedCertificates(outputFile, certInfos, caInfo, keysize);
|
||||
CertificateTool.generateAndWriteSignedCertificates(outputFile, certInfos, caInfo, keysize, days);
|
||||
assertTrue(Files.exists(outputFile));
|
||||
|
||||
FileSystem fileSystem = FileSystems.newFileSystem(new URI("jar:" + outputFile.toUri()), Collections.emptyMap());
|
||||
@ -229,6 +231,8 @@ public class CertificateToolTests extends ESTestCase {
|
||||
X509Certificate parsedCaCert = readX509Certificate(reader);
|
||||
assertThat(parsedCaCert.getSubjectX500Principal().getName(), containsString("test ca"));
|
||||
assertEquals(caCert, parsedCaCert);
|
||||
long daysBetween = ChronoUnit.DAYS.between(caCert.getNotBefore().toInstant(), caCert.getNotAfter().toInstant());
|
||||
assertEquals(days, (int) daysBetween);
|
||||
}
|
||||
|
||||
// check the CA key
|
||||
@ -283,15 +287,17 @@ public class CertificateToolTests extends ESTestCase {
|
||||
terminal.addSecretInput("testnode");
|
||||
}
|
||||
|
||||
final int days = randomIntBetween(1, 1024);
|
||||
CAInfo caInfo = CertificateTool.getCAInfo(terminal, "CN=foo", testNodeCertPath.toString(), testNodeKeyPath.toString(),
|
||||
passwordPrompt ? null : "testnode".toCharArray(), passwordPrompt, env, randomFrom(1024, 2048));
|
||||
passwordPrompt ? null : "testnode".toCharArray(), passwordPrompt, env, randomFrom(1024, 2048), days);
|
||||
assertTrue(terminal.getOutput().isEmpty());
|
||||
assertThat(caInfo.caCert, instanceOf(X509Certificate.class));
|
||||
assertEquals(caInfo.caCert.getSubjectX500Principal().getName(),
|
||||
"CN=Elasticsearch Test Node,OU=elasticsearch,O=org");
|
||||
assertThat(caInfo.privateKey.getAlgorithm(), containsString("RSA"));
|
||||
assertEquals(2048, ((RSAKey) caInfo.privateKey).getModulus().bitLength());
|
||||
assertFalse(caInfo.generated);
|
||||
long daysBetween = ChronoUnit.DAYS.between(caInfo.caCert.getNotBefore().toInstant(), caInfo.caCert.getNotAfter().toInstant());
|
||||
assertEquals(1460L, daysBetween);
|
||||
|
||||
// test generation
|
||||
final boolean passwordProtected = randomBoolean();
|
||||
@ -303,13 +309,16 @@ public class CertificateToolTests extends ESTestCase {
|
||||
password = "testnode".toCharArray();
|
||||
}
|
||||
final int keysize = randomFrom(1024, 2048);
|
||||
caInfo = CertificateTool.getCAInfo(terminal, "CN=foo bar", null, null, password, passwordProtected && passwordPrompt, env, keysize);
|
||||
caInfo = CertificateTool.getCAInfo(terminal, "CN=foo bar", null, null, password, passwordProtected && passwordPrompt, env,
|
||||
keysize, days);
|
||||
assertTrue(terminal.getOutput().isEmpty());
|
||||
assertThat(caInfo.caCert, instanceOf(X509Certificate.class));
|
||||
assertEquals(caInfo.caCert.getSubjectX500Principal().getName(), "CN=foo bar");
|
||||
assertThat(caInfo.privateKey.getAlgorithm(), containsString("RSA"));
|
||||
assertTrue(caInfo.generated);
|
||||
assertEquals(keysize, ((RSAKey) caInfo.privateKey).getModulus().bitLength());
|
||||
daysBetween = ChronoUnit.DAYS.between(caInfo.caCert.getNotBefore().toInstant(), caInfo.caCert.getNotAfter().toInstant());
|
||||
assertEquals(days, (int) daysBetween);
|
||||
}
|
||||
|
||||
public void testNameValues() throws Exception {
|
||||
|
@ -20,7 +20,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
@ -98,7 +98,7 @@ public class SSLClientAuthTests extends SecurityIntegTestCase {
|
||||
.put(Security.USER_SETTING.getKey(),
|
||||
transportClientUsername() + ":" + new String(transportClientPassword().internalChars()))
|
||||
.build();
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
try (TransportClient client = new TestXPackTransportClient(settings)) {
|
||||
Transport transport = internalCluster().getDataNodeInstance(Transport.class);
|
||||
TransportAddress transportAddress = transport.boundAddress().publishAddress();
|
||||
client.addTransportAddress(transportAddress);
|
||||
|
@ -676,9 +676,6 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
|
||||
"\n" +
|
||||
"admin:\n" +
|
||||
" cluster: [ 'manage' ]\n" +
|
||||
"transport_client:\n" +
|
||||
" cluster: [ 'transport_client' ]\n" +
|
||||
"\n" +
|
||||
"monitor:\n" +
|
||||
" cluster: [ 'monitor' ]\n"
|
||||
;
|
||||
|
Loading…
x
Reference in New Issue
Block a user