Merge branch 'master' into kibana-shield-user-role-ui
Original commit: elastic/x-pack-elasticsearch@631196d5b1
This commit is contained in:
commit
d0b8195f8f
|
@ -98,7 +98,7 @@ public class HistoryTemplateTransformMappingsTests extends AbstractWatcherIntegr
|
||||||
assertThat(mappingsResponse, notNullValue());
|
assertThat(mappingsResponse, notNullValue());
|
||||||
assertThat(mappingsResponse.getMappings().isEmpty(), is(false));
|
assertThat(mappingsResponse.getMappings().isEmpty(), is(false));
|
||||||
for (ObjectObjectCursor<String, ImmutableOpenMap<String, MappingMetaData>> metadatas : mappingsResponse.getMappings()) {
|
for (ObjectObjectCursor<String, ImmutableOpenMap<String, MappingMetaData>> metadatas : mappingsResponse.getMappings()) {
|
||||||
if (!metadatas.key.startsWith(".watch_history")) {
|
if (!metadatas.key.startsWith(".watcher-history")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MappingMetaData metadata = metadatas.value.get("watch_record");
|
MappingMetaData metadata = metadatas.value.get("watch_record");
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.watcher.test.integration;
|
package org.elasticsearch.messy.tests;
|
||||||
|
|
||||||
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
||||||
import org.elasticsearch.ExceptionsHelper;
|
import org.elasticsearch.ExceptionsHelper;
|
||||||
|
@ -18,6 +18,9 @@ import org.elasticsearch.discovery.zen.elect.ElectMasterService;
|
||||||
import org.elasticsearch.discovery.zen.ping.ZenPing;
|
import org.elasticsearch.discovery.zen.ping.ZenPing;
|
||||||
import org.elasticsearch.discovery.zen.ping.ZenPingService;
|
import org.elasticsearch.discovery.zen.ping.ZenPingService;
|
||||||
import org.elasticsearch.discovery.zen.ping.unicast.UnicastZenPing;
|
import org.elasticsearch.discovery.zen.ping.unicast.UnicastZenPing;
|
||||||
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
import org.elasticsearch.script.MockMustacheScriptEngine;
|
||||||
|
import org.elasticsearch.script.mustache.MustachePlugin;
|
||||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||||
import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode;
|
import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode;
|
||||||
import org.elasticsearch.test.discovery.ClusterDiscoveryConfiguration;
|
import org.elasticsearch.test.discovery.ClusterDiscoveryConfiguration;
|
||||||
|
@ -33,6 +36,10 @@ import org.elasticsearch.watcher.test.WatcherTestUtils;
|
||||||
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchResponse;
|
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchResponse;
|
||||||
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsResponse;
|
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsResponse;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||||
|
@ -81,6 +88,23 @@ public class NoMasterNodeTests extends AbstractWatcherIntegrationTestCase {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||||
|
Collection<Class<? extends Plugin>> types = new ArrayList<>();
|
||||||
|
types.addAll(super.nodePlugins());
|
||||||
|
// TODO remove dependency on mustache
|
||||||
|
types.add(MustachePlugin.class);
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Class<? extends Plugin>> getMockPlugins() {
|
||||||
|
Set<Class<? extends Plugin>> plugins = new HashSet<>(super.getMockPlugins());
|
||||||
|
// remove the mock because we use mustache here...
|
||||||
|
plugins.remove(MockMustacheScriptEngine.TestPlugin.class);
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
public void testSimpleFailure() throws Exception {
|
public void testSimpleFailure() throws Exception {
|
||||||
// we need 3 hosts here because we stop the master and start another - it doesn't restart the pre-existing node...
|
// we need 3 hosts here because we stop the master and start another - it doesn't restart the pre-existing node...
|
||||||
config = new ClusterDiscoveryConfiguration.UnicastZen(3, Settings.EMPTY);
|
config = new ClusterDiscoveryConfiguration.UnicastZen(3, Settings.EMPTY);
|
|
@ -3,7 +3,7 @@
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.watcher.transport.action.ack;
|
package org.elasticsearch.messy.tests;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
||||||
|
@ -13,6 +13,9 @@ import org.elasticsearch.action.get.GetRequest;
|
||||||
import org.elasticsearch.action.get.GetResponse;
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
import org.elasticsearch.action.index.IndexResponse;
|
import org.elasticsearch.action.index.IndexResponse;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
import org.elasticsearch.script.MockMustacheScriptEngine;
|
||||||
|
import org.elasticsearch.script.mustache.MustachePlugin;
|
||||||
import org.elasticsearch.watcher.actions.ActionStatus;
|
import org.elasticsearch.watcher.actions.ActionStatus;
|
||||||
import org.elasticsearch.watcher.client.WatcherClient;
|
import org.elasticsearch.watcher.client.WatcherClient;
|
||||||
import org.elasticsearch.watcher.condition.compare.CompareCondition;
|
import org.elasticsearch.watcher.condition.compare.CompareCondition;
|
||||||
|
@ -29,6 +32,10 @@ import org.elasticsearch.watcher.watch.Watch;
|
||||||
import org.elasticsearch.watcher.watch.WatchStore;
|
import org.elasticsearch.watcher.watch.WatchStore;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||||
|
@ -52,6 +59,24 @@ import static org.hamcrest.core.IsEqual.equalTo;
|
||||||
//test is just too slow, please fix it to not be sleep-based
|
//test is just too slow, please fix it to not be sleep-based
|
||||||
@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007")
|
@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007")
|
||||||
public class WatchAckTests extends AbstractWatcherIntegrationTestCase {
|
public class WatchAckTests extends AbstractWatcherIntegrationTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||||
|
Collection<Class<? extends Plugin>> types = new ArrayList<>();
|
||||||
|
types.addAll(super.nodePlugins());
|
||||||
|
// TODO remove dependency on mustache
|
||||||
|
types.add(MustachePlugin.class);
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Class<? extends Plugin>> getMockPlugins() {
|
||||||
|
Set<Class<? extends Plugin>> plugins = new HashSet<>(super.getMockPlugins());
|
||||||
|
// remove the mock because we use mustache here...
|
||||||
|
plugins.remove(MockMustacheScriptEngine.TestPlugin.class);
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
private IndexResponse indexTestDoc() {
|
private IndexResponse indexTestDoc() {
|
||||||
createIndex("actions", "events");
|
createIndex("actions", "events");
|
||||||
ensureGreen("actions", "events");
|
ensureGreen("actions", "events");
|
|
@ -10,7 +10,7 @@ integTest {
|
||||||
systemProperty 'es.shield.audit.enabled', 'true'
|
systemProperty 'es.shield.audit.enabled', 'true'
|
||||||
systemProperty 'es.shield.audit.outputs', 'index'
|
systemProperty 'es.shield.audit.outputs', 'index'
|
||||||
setupCommand 'setupDummyUser',
|
setupCommand 'setupDummyUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
waitCondition = { node, ant ->
|
waitCondition = { node, ant ->
|
||||||
File tmpFile = new File(node.cwd, 'wait.success')
|
File tmpFile = new File(node.cwd, 'wait.success')
|
||||||
ant.get(src: "http://${node.httpUri()}",
|
ant.get(src: "http://${node.httpUri()}",
|
||||||
|
|
|
@ -5,10 +5,14 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.shield.audit;
|
package org.elasticsearch.shield.audit;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
|
||||||
|
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.index.query.QueryBuilders;
|
import org.elasticsearch.index.query.QueryBuilders;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
import org.elasticsearch.shield.audit.index.IndexAuditTrail;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||||
import org.elasticsearch.test.ESIntegTestCase;
|
import org.elasticsearch.test.ESIntegTestCase;
|
||||||
|
@ -49,6 +53,35 @@ public class IndexAuditIT extends ESIntegTestCase {
|
||||||
assertThat((String) searchResponse.getHits().getAt(0).sourceAsMap().get("principal"), is(USER));
|
assertThat((String) searchResponse.getHits().getAt(0).sourceAsMap().get("principal"), is(USER));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAuditTrailTemplateIsRecreatedAfterDelete() throws Exception {
|
||||||
|
// this is already "tested" by the test framework since we wipe the templates before and after,
|
||||||
|
// but lets be explicit about the behavior
|
||||||
|
awaitIndexTemplateCreation();
|
||||||
|
|
||||||
|
// delete the template
|
||||||
|
DeleteIndexTemplateResponse deleteResponse = client().admin().indices()
|
||||||
|
.prepareDeleteTemplate(IndexAuditTrail.INDEX_TEMPLATE_NAME).execute().actionGet();
|
||||||
|
assertThat(deleteResponse.isAcknowledged(), is(true));
|
||||||
|
awaitIndexTemplateCreation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void awaitIndexTemplateCreation() throws InterruptedException {
|
||||||
|
boolean found = awaitBusy(() -> {
|
||||||
|
GetIndexTemplatesResponse response = client().admin().indices()
|
||||||
|
.prepareGetTemplates(IndexAuditTrail.INDEX_TEMPLATE_NAME).execute().actionGet();
|
||||||
|
if (response.getIndexTemplates().size() > 0) {
|
||||||
|
for (IndexTemplateMetaData indexTemplateMetaData : response.getIndexTemplates()) {
|
||||||
|
if (IndexAuditTrail.INDEX_TEMPLATE_NAME.equals(indexTemplateMetaData.name())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThat("index template [" + IndexAuditTrail.INDEX_TEMPLATE_NAME + "] was not created", found, is(true));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Settings externalClusterClientSettings() {
|
protected Settings externalClusterClientSettings() {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
|
|
|
@ -8,9 +8,9 @@ integTest {
|
||||||
cluster {
|
cluster {
|
||||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||||
setupCommand 'setupDummyUser',
|
setupCommand 'setupDummyUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
setupCommand 'setupTransportClientUser',
|
setupCommand 'setupTransportClientUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'transport', '-p', 'changeme', '-r', 'transport_client'
|
'bin/xpack/esusers', 'useradd', 'transport', '-p', 'changeme', '-r', 'transport_client'
|
||||||
waitCondition = { node, ant ->
|
waitCondition = { node, ant ->
|
||||||
File tmpFile = new File(node.cwd, 'wait.success')
|
File tmpFile = new File(node.cwd, 'wait.success')
|
||||||
ant.get(src: "http://${node.httpUri()}",
|
ant.get(src: "http://${node.httpUri()}",
|
||||||
|
|
|
@ -35,7 +35,7 @@ integTest {
|
||||||
systemProperty 'es.watcher.enabled', 'false'
|
systemProperty 'es.watcher.enabled', 'false'
|
||||||
systemProperty 'es.marvel.enabled', 'false'
|
systemProperty 'es.marvel.enabled', 'false'
|
||||||
setupCommand 'setupDummyUser',
|
setupCommand 'setupDummyUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
waitCondition = { node, ant ->
|
waitCondition = { node, ant ->
|
||||||
File tmpFile = new File(node.cwd, 'wait.success')
|
File tmpFile = new File(node.cwd, 'wait.success')
|
||||||
ant.get(src: "http://${node.httpUri()}",
|
ant.get(src: "http://${node.httpUri()}",
|
||||||
|
|
|
@ -23,7 +23,7 @@ integTest {
|
||||||
systemProperty 'es.shield.authc.realms.esusers.type', 'esusers'
|
systemProperty 'es.shield.authc.realms.esusers.type', 'esusers'
|
||||||
|
|
||||||
setupCommand 'setupDummyUser',
|
setupCommand 'setupDummyUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
waitCondition = { node, ant ->
|
waitCondition = { node, ant ->
|
||||||
File tmpFile = new File(node.cwd, 'wait.success')
|
File tmpFile = new File(node.cwd, 'wait.success')
|
||||||
ant.get(src: "http://${node.httpUri()}",
|
ant.get(src: "http://${node.httpUri()}",
|
||||||
|
|
|
@ -75,10 +75,10 @@
|
||||||
<property name="home" location="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
|
<property name="home" location="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
|
||||||
|
|
||||||
<echo>Adding roles.yml</echo>
|
<echo>Adding roles.yml</echo>
|
||||||
<copy file="shield-roles.yml" tofile="${home}/config/shield/roles.yml" overwrite="true"/>
|
<copy file="shield-roles.yml" tofile="${home}/config/xpack/roles.yml" overwrite="true"/>
|
||||||
|
|
||||||
<echo>Adding shield users...</echo>
|
<echo>Adding shield users...</echo>
|
||||||
<run-script script="${home}/bin/shield/esusers">
|
<run-script script="${home}/bin/xpack/esusers">
|
||||||
<nested>
|
<nested>
|
||||||
<arg value="useradd"/>
|
<arg value="useradd"/>
|
||||||
<arg value="test_admin"/>
|
<arg value="test_admin"/>
|
||||||
|
|
|
@ -63,10 +63,10 @@
|
||||||
<property name="home" location="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
|
<property name="home" location="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
|
||||||
|
|
||||||
<echo>Adding roles.yml with watcher roles</echo>
|
<echo>Adding roles.yml with watcher roles</echo>
|
||||||
<copy file="watcher-with-shield-roles.yml" tofile="${home}/config/shield/roles.yml" overwrite="true"/>
|
<copy file="watcher-with-shield-roles.yml" tofile="${home}/config/xpack/roles.yml" overwrite="true"/>
|
||||||
|
|
||||||
<echo>Adding shield users...</echo>
|
<echo>Adding shield users...</echo>
|
||||||
<run-script script="${home}/bin/shield/esusers">
|
<run-script script="${home}/bin/xpack/esusers">
|
||||||
<nested>
|
<nested>
|
||||||
<arg value="useradd"/>
|
<arg value="useradd"/>
|
||||||
<arg value="test_admin"/>
|
<arg value="test_admin"/>
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
<arg value="admin"/>
|
<arg value="admin"/>
|
||||||
</nested>
|
</nested>
|
||||||
</run-script>
|
</run-script>
|
||||||
<run-script script="${home}/bin/shield/esusers">
|
<run-script script="${home}/bin/xpack/esusers">
|
||||||
<nested>
|
<nested>
|
||||||
<arg value="useradd"/>
|
<arg value="useradd"/>
|
||||||
<arg value="watcher_manager"/>
|
<arg value="watcher_manager"/>
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
<arg value="watcher_manager"/>
|
<arg value="watcher_manager"/>
|
||||||
</nested>
|
</nested>
|
||||||
</run-script>
|
</run-script>
|
||||||
<run-script script="${home}/bin/shield/esusers">
|
<run-script script="${home}/bin/xpack/esusers">
|
||||||
<nested>
|
<nested>
|
||||||
<arg value="useradd"/>
|
<arg value="useradd"/>
|
||||||
<arg value="powerless_user"/>
|
<arg value="powerless_user"/>
|
||||||
|
|
|
@ -6,12 +6,12 @@ admin:
|
||||||
watcher_manager:
|
watcher_manager:
|
||||||
cluster: manage_watcher, cluster:monitor/nodes/info, cluster:monitor/health
|
cluster: manage_watcher, cluster:monitor/nodes/info, cluster:monitor/health
|
||||||
indices:
|
indices:
|
||||||
'.watch_history-*': all
|
'.watcher-history-*': all
|
||||||
|
|
||||||
watcher_monitor:
|
watcher_monitor:
|
||||||
cluster: monitor_watcher
|
cluster: monitor_watcher
|
||||||
indices:
|
indices:
|
||||||
'.watch_history-*': read
|
'.watcher-history-*': read
|
||||||
|
|
||||||
crapy_role:
|
crapy_role:
|
||||||
cluster:
|
cluster:
|
||||||
|
|
|
@ -57,9 +57,9 @@ integTest {
|
||||||
// copy keystore into config/
|
// copy keystore into config/
|
||||||
extraConfigFile keystore.name, keystore
|
extraConfigFile keystore.name, keystore
|
||||||
setupCommand 'setupTestUser',
|
setupCommand 'setupTestUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
setupCommand 'setupMarvelUser',
|
setupCommand 'setupMarvelUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'marvel_export', '-p', 'changeme', '-r', 'marvel_agent'
|
'bin/xpack/esusers', 'useradd', 'marvel_export', '-p', 'changeme', '-r', 'marvel_agent'
|
||||||
waitCondition = { node, ant ->
|
waitCondition = { node, ant ->
|
||||||
// we just return true, doing an https check is tricky here
|
// we just return true, doing an https check is tricky here
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -18,7 +18,7 @@ integTest {
|
||||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||||
|
|
||||||
setupCommand 'setupDummyUser',
|
setupCommand 'setupDummyUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
waitCondition = { node, ant ->
|
waitCondition = { node, ant ->
|
||||||
File tmpFile = new File(node.cwd, 'wait.success')
|
File tmpFile = new File(node.cwd, 'wait.success')
|
||||||
ant.get(src: "http://${node.httpUri()}",
|
ant.get(src: "http://${node.httpUri()}",
|
||||||
|
|
|
@ -58,5 +58,5 @@
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
search:
|
search:
|
||||||
index: .watch_history-*
|
index: .watcher-history-*
|
||||||
- match: { hits.hits.0._source.result.actions.0.logging.logged_text: "value1 value2" }
|
- match: { hits.hits.0._source.result.actions.0.logging.logged_text: "value1 value2" }
|
||||||
|
|
|
@ -20,13 +20,13 @@ integTest {
|
||||||
|
|
||||||
cluster {
|
cluster {
|
||||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
extraConfigFile 'xpack/roles.yml', 'roles.yml'
|
||||||
setupCommand 'setupTestAdminUser',
|
setupCommand 'setupTestAdminUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'admin'
|
'bin/xpack/esusers', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'admin'
|
||||||
setupCommand 'setupWatcherManagerUser',
|
setupCommand 'setupWatcherManagerUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'watcher_manager', '-p', 'changeme', '-r', 'watcher_manager'
|
'bin/xpack/esusers', 'useradd', 'watcher_manager', '-p', 'changeme', '-r', 'watcher_manager'
|
||||||
setupCommand 'setupPowerlessUser',
|
setupCommand 'setupPowerlessUser',
|
||||||
'bin/x-pack/esusers', 'useradd', 'powerless_user', '-p', 'changeme', '-r', 'crappy_role'
|
'bin/xpack/esusers', 'useradd', 'powerless_user', '-p', 'changeme', '-r', 'crappy_role'
|
||||||
waitCondition = { node, ant ->
|
waitCondition = { node, ant ->
|
||||||
File tmpFile = new File(node.cwd, 'wait.success')
|
File tmpFile = new File(node.cwd, 'wait.success')
|
||||||
ant.get(src: "http://${node.httpUri()}",
|
ant.get(src: "http://${node.httpUri()}",
|
||||||
|
|
|
@ -6,13 +6,13 @@ admin:
|
||||||
watcher_manager:
|
watcher_manager:
|
||||||
cluster: manage_watcher, cluster:monitor/nodes/info, cluster:monitor/health
|
cluster: manage_watcher, cluster:monitor/nodes/info, cluster:monitor/health
|
||||||
indices:
|
indices:
|
||||||
'.watch_history-*': all
|
'.watcher-history-*': all
|
||||||
run_as: powerless_user, watcher_manager
|
run_as: powerless_user, watcher_manager
|
||||||
|
|
||||||
watcher_monitor:
|
watcher_monitor:
|
||||||
cluster: monitor_watcher
|
cluster: monitor_watcher
|
||||||
indices:
|
indices:
|
||||||
'.watch_history-*': read
|
'.watcher-history-*': read
|
||||||
|
|
||||||
crappy_role:
|
crappy_role:
|
||||||
cluster:
|
cluster:
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<project name="shield-overrides"
|
|
||||||
xmlns:ac="antlib:net.sf.antcontrib">
|
|
||||||
|
|
||||||
<!-- redefined to work with auth -->
|
|
||||||
<macrodef name="waitfor-elasticsearch">
|
|
||||||
<attribute name="port"/>
|
|
||||||
<attribute name="timeoutproperty"/>
|
|
||||||
<sequential>
|
|
||||||
<echo>Waiting for elasticsearch to become available on port @{port}...</echo>
|
|
||||||
<waitfor maxwait="30" maxwaitunit="second"
|
|
||||||
checkevery="500" checkeveryunit="millisecond"
|
|
||||||
timeoutproperty="@{timeoutproperty}">
|
|
||||||
<socket server="127.0.0.1" port="@{port}"/>
|
|
||||||
</waitfor>
|
|
||||||
</sequential>
|
|
||||||
</macrodef>
|
|
||||||
|
|
||||||
<target name="start-external-cluster-with-plugins" depends="setup-workspace">
|
|
||||||
<ac:for list="${xplugins.list}" param="xplugin.name">
|
|
||||||
<sequential>
|
|
||||||
<fail message="Expected @{xplugin.name}-${version}.zip as a dependency, but could not be found in ${integ.deps}/plugins}">
|
|
||||||
<condition>
|
|
||||||
<not>
|
|
||||||
<available file="${integ.deps}/plugins/@{xplugin.name}-${elasticsearch.version}.zip" />
|
|
||||||
</not>
|
|
||||||
</condition>
|
|
||||||
</fail>
|
|
||||||
<ac:if>
|
|
||||||
<equals arg1="@{xplugin.name}" arg2="elasticsearch-marvel"/>
|
|
||||||
<ac:then>
|
|
||||||
<property name="marvel.enabled">true</property>
|
|
||||||
</ac:then>
|
|
||||||
</ac:if>
|
|
||||||
</sequential>
|
|
||||||
</ac:for>
|
|
||||||
|
|
||||||
<ac:for param="file">
|
|
||||||
<path>
|
|
||||||
<fileset dir="${integ.deps}/plugins"/>
|
|
||||||
</path>
|
|
||||||
<sequential>
|
|
||||||
<local name="plugin.name"/>
|
|
||||||
<convert-plugin-name file="@{file}" outputproperty="plugin.name"/>
|
|
||||||
<install-plugin name="${plugin.name}" file="@{file}"/>
|
|
||||||
</sequential>
|
|
||||||
</ac:for>
|
|
||||||
|
|
||||||
<local name="home"/>
|
|
||||||
<property name="home" location="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
|
|
||||||
|
|
||||||
<echo>Setting up Shield auth</echo>
|
|
||||||
<run-script script="${home}/bin/shield/esusers">
|
|
||||||
<nested>
|
|
||||||
<arg value="useradd"/>
|
|
||||||
<arg value="test_user"/>
|
|
||||||
<arg value="-p"/>
|
|
||||||
<arg value="changeme"/>
|
|
||||||
<arg value="-r"/>
|
|
||||||
<arg value="admin"/>
|
|
||||||
</nested>
|
|
||||||
</run-script>
|
|
||||||
|
|
||||||
<ac:if>
|
|
||||||
<equals arg1="${marvel.enabled}" arg2="true"/>
|
|
||||||
<ac:then>
|
|
||||||
<run-script script="${home}/bin/shield/esusers">
|
|
||||||
<nested>
|
|
||||||
<arg value="useradd"/>
|
|
||||||
<arg value="marvel_export"/>
|
|
||||||
<arg value="-p"/>
|
|
||||||
<arg value="changeme"/>
|
|
||||||
<arg value="-r"/>
|
|
||||||
<arg value="marvel_agent"/>
|
|
||||||
</nested>
|
|
||||||
</run-script>
|
|
||||||
|
|
||||||
<startup-elasticsearch>
|
|
||||||
<additional-args>
|
|
||||||
<arg value="-Des.marvel.agent.exporter.es.hosts=http://marvel_export:changeme@localhost:${integ.http.port}"/>
|
|
||||||
</additional-args>
|
|
||||||
</startup-elasticsearch>
|
|
||||||
</ac:then>
|
|
||||||
<ac:else>
|
|
||||||
<startup-elasticsearch/>
|
|
||||||
</ac:else>
|
|
||||||
</ac:if>
|
|
||||||
|
|
||||||
|
|
||||||
<echo>Checking we can connect with basic auth on port ${integ.http.port}...</echo>
|
|
||||||
<local name="temp.file"/>
|
|
||||||
<tempfile property="temp.file" destdir="${java.io.tmpdir}"/>
|
|
||||||
<get src="http://127.0.0.1:${integ.http.port}" dest="${temp.file}"
|
|
||||||
username="test_user" password="changeme" verbose="true" retries="10"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,14 +0,0 @@
|
||||||
ELASTICSEARCH CONFIDENTIAL
|
|
||||||
__________________
|
|
||||||
|
|
||||||
[2014] Elasticsearch Incorporated. All Rights Reserved.
|
|
||||||
|
|
||||||
NOTICE: All information contained herein is, and remains
|
|
||||||
the property of Elasticsearch Incorporated and its suppliers,
|
|
||||||
if any. The intellectual and technical concepts contained
|
|
||||||
herein are proprietary to Elasticsearch Incorporated
|
|
||||||
and its suppliers and may be covered by U.S. and Foreign Patents,
|
|
||||||
patents in process, and are protected by trade secret or copyright law.
|
|
||||||
Dissemination of this information or reproduction of this material
|
|
||||||
is strictly forbidden unless prior written permission is obtained
|
|
||||||
from Elasticsearch Incorporated.
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<additionalHeaders>
|
|
||||||
<javadoc_style>
|
|
||||||
<firstLine>/*</firstLine>
|
|
||||||
<beforeEachLine> * </beforeEachLine>
|
|
||||||
<endLine> */</endLine>
|
|
||||||
<!--skipLine></skipLine-->
|
|
||||||
<firstLineDetectionPattern>(\s|\t)*/\*.*$</firstLineDetectionPattern>
|
|
||||||
<lastLineDetectionPattern>.*\*/(\s|\t)*$</lastLineDetectionPattern>
|
|
||||||
<allowBlankLines>false</allowBlankLines>
|
|
||||||
<isMultiline>true</isMultiline>
|
|
||||||
</javadoc_style>
|
|
||||||
</additionalHeaders>
|
|
|
@ -3,7 +3,7 @@ import org.elasticsearch.gradle.test.NodeInfo
|
||||||
|
|
||||||
apply plugin: 'elasticsearch.esplugin'
|
apply plugin: 'elasticsearch.esplugin'
|
||||||
esplugin {
|
esplugin {
|
||||||
name 'x-pack'
|
name 'xpack'
|
||||||
description 'Elasticsearch Expanded Pack Plugin'
|
description 'Elasticsearch Expanded Pack Plugin'
|
||||||
classname 'org.elasticsearch.xpack.XPackPlugin'
|
classname 'org.elasticsearch.xpack.XPackPlugin'
|
||||||
// FIXME we still can't be isolated due to shield custom realms
|
// FIXME we still can't be isolated due to shield custom realms
|
||||||
|
@ -74,6 +74,9 @@ ext.expansions = [
|
||||||
// Used in marvel index templates
|
// Used in marvel index templates
|
||||||
'marvel.plugin.version': version,
|
'marvel.plugin.version': version,
|
||||||
'marvel.template.version': '1',
|
'marvel.template.version': '1',
|
||||||
|
// Used in watcher index template
|
||||||
|
'watcher.plugin.version': version,
|
||||||
|
'watcher.template.version': '1',
|
||||||
]
|
]
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
@ -111,13 +114,13 @@ bundlePlugin {
|
||||||
include 'LICENSE.txt'
|
include 'LICENSE.txt'
|
||||||
include 'NOTICE.txt'
|
include 'NOTICE.txt'
|
||||||
}
|
}
|
||||||
from('shield/bin/shield') {
|
from('shield/bin/xpack') {
|
||||||
into 'bin'
|
into 'bin'
|
||||||
}
|
}
|
||||||
from('shield/config/shield') {
|
from('shield/config/xpack') {
|
||||||
into 'config'
|
into 'config'
|
||||||
}
|
}
|
||||||
from('watcher/bin/watcher') {
|
from('watcher/bin/xpack') {
|
||||||
into 'bin'
|
into 'bin'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +129,7 @@ integTest {
|
||||||
// TODO: fix this rest test to not depend on a hardcoded port!
|
// TODO: fix this rest test to not depend on a hardcoded port!
|
||||||
systemProperty 'tests.rest.blacklist', 'getting_started/10_monitor_cluster_health/*'
|
systemProperty 'tests.rest.blacklist', 'getting_started/10_monitor_cluster_health/*'
|
||||||
cluster {
|
cluster {
|
||||||
setupCommand 'setupDummyUser', 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
setupCommand 'setupDummyUser', 'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
waitCondition = { NodeInfo node, AntBuilder ant ->
|
waitCondition = { NodeInfo node, AntBuilder ant ->
|
||||||
File tmpFile = new File(node.cwd, 'wait.success')
|
File tmpFile = new File(node.cwd, 'wait.success')
|
||||||
ant.get(src: "http://${node.httpUri()}",
|
ant.get(src: "http://${node.httpUri()}",
|
||||||
|
@ -154,7 +157,7 @@ artifacts {
|
||||||
}
|
}
|
||||||
|
|
||||||
run {
|
run {
|
||||||
setupCommand 'setupDummyUser', 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
setupCommand 'setupDummyUser', 'bin/xpack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin'
|
||||||
}
|
}
|
||||||
|
|
||||||
// classes are missing, e.g. com.ibm.icu.lang.UCharacter
|
// classes are missing, e.g. com.ibm.icu.lang.UCharacter
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
import org.elasticsearch.marvel.agent.settings.MarvelSettings;
|
import org.elasticsearch.marvel.agent.settings.MarvelSettings;
|
||||||
import org.elasticsearch.marvel.license.MarvelLicensee;
|
import org.elasticsearch.marvel.license.MarvelLicensee;
|
||||||
import org.elasticsearch.shield.InternalClient;
|
import org.elasticsearch.shield.InternalClient;
|
||||||
|
import org.elasticsearch.shield.ShieldPlugin;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -26,8 +27,6 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.elasticsearch.shield.ShieldPlugin.shieldEnabled;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collector for the Recovery API.
|
* Collector for the Recovery API.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -73,7 +72,7 @@ public class IndexRecoveryCollector extends AbstractCollector<IndexRecoveryColle
|
||||||
results.add(indexRecoveryDoc);
|
results.add(indexRecoveryDoc);
|
||||||
}
|
}
|
||||||
} catch (IndexNotFoundException e) {
|
} catch (IndexNotFoundException e) {
|
||||||
if (shieldEnabled(settings) && IndexNameExpressionResolver.isAllIndices(Arrays.asList(marvelSettings.indices()))) {
|
if (ShieldPlugin.enabled(settings) && IndexNameExpressionResolver.isAllIndices(Arrays.asList(marvelSettings.indices()))) {
|
||||||
logger.debug("collector [{}] - unable to collect data for missing index [{}]", name(), e.getIndex());
|
logger.debug("collector [{}] - unable to collect data for missing index [{}]", name(), e.getIndex());
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
import org.elasticsearch.marvel.agent.settings.MarvelSettings;
|
import org.elasticsearch.marvel.agent.settings.MarvelSettings;
|
||||||
import org.elasticsearch.marvel.license.MarvelLicensee;
|
import org.elasticsearch.marvel.license.MarvelLicensee;
|
||||||
import org.elasticsearch.shield.InternalClient;
|
import org.elasticsearch.shield.InternalClient;
|
||||||
|
import org.elasticsearch.shield.ShieldPlugin;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -28,8 +29,6 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.elasticsearch.shield.ShieldPlugin.shieldEnabled;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collector for indices statistics.
|
* Collector for indices statistics.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -87,7 +86,7 @@ public class IndexStatsCollector extends AbstractCollector<IndexStatsCollector>
|
||||||
results.add(indexStatsDoc);
|
results.add(indexStatsDoc);
|
||||||
}
|
}
|
||||||
} catch (IndexNotFoundException e) {
|
} catch (IndexNotFoundException e) {
|
||||||
if (shieldEnabled(settings) && IndexNameExpressionResolver.isAllIndices(Arrays.asList(marvelSettings.indices()))) {
|
if (ShieldPlugin.enabled(settings) && IndexNameExpressionResolver.isAllIndices(Arrays.asList(marvelSettings.indices()))) {
|
||||||
logger.debug("collector [{}] - unable to collect data for missing index [{}]", name(), e.getIndex());
|
logger.debug("collector [{}] - unable to collect data for missing index [{}]", name(), e.getIndex());
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -19,13 +19,12 @@ import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
import org.elasticsearch.marvel.agent.settings.MarvelSettings;
|
import org.elasticsearch.marvel.agent.settings.MarvelSettings;
|
||||||
import org.elasticsearch.marvel.license.MarvelLicensee;
|
import org.elasticsearch.marvel.license.MarvelLicensee;
|
||||||
import org.elasticsearch.shield.InternalClient;
|
import org.elasticsearch.shield.InternalClient;
|
||||||
|
import org.elasticsearch.shield.ShieldPlugin;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import static org.elasticsearch.shield.ShieldPlugin.shieldEnabled;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collector for indices statistics.
|
* Collector for indices statistics.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -72,7 +71,7 @@ public class IndicesStatsCollector extends AbstractCollector<IndicesStatsCollect
|
||||||
|
|
||||||
return Collections.singletonList(indicesStatsDoc);
|
return Collections.singletonList(indicesStatsDoc);
|
||||||
} catch (IndexNotFoundException e) {
|
} catch (IndexNotFoundException e) {
|
||||||
if (shieldEnabled(settings) && IndexNameExpressionResolver.isAllIndices(Arrays.asList(marvelSettings.indices()))) {
|
if (ShieldPlugin.enabled(settings) && IndexNameExpressionResolver.isAllIndices(Arrays.asList(marvelSettings.indices()))) {
|
||||||
logger.debug("collector [{}] - unable to collect data for missing index [{}]", name(), e.getIndex());
|
logger.debug("collector [{}] - unable to collect data for missing index [{}]", name(), e.getIndex());
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class MarvelPluginTests extends MarvelIntegTestCase {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertThat("x-pack plugin not found", found, equalTo(true));
|
assertThat("xpack plugin not found", found, equalTo(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ REM JAVA_OPTS=%JAVA_OPTS% -XX:HeapDumpPath=$ES_HOME/logs/heapdump.hprof
|
||||||
|
|
||||||
REM Disables explicit GC
|
REM Disables explicit GC
|
||||||
set JAVA_OPTS=%JAVA_OPTS% -XX:+DisableExplicitGC
|
set JAVA_OPTS=%JAVA_OPTS% -XX:+DisableExplicitGC
|
||||||
set ES_CLASSPATH=%ES_CLASSPATH%;%ES_HOME%/lib/elasticsearch-1.4.0-SNAPSHOT.jar;%ES_HOME%/lib/*;%ES_HOME%/lib/sigar/*;%ES_HOME%/plugins/x-pack/*
|
set ES_CLASSPATH=%ES_CLASSPATH%;%ES_HOME%/lib/*;%ES_HOME%/lib/sigar/*;%ES_HOME%/plugins/xpack/*
|
||||||
set ES_PARAMS=-Des.path.home="%ES_HOME%"
|
set ES_PARAMS=-Des.path.home="%ES_HOME%"
|
||||||
|
|
||||||
SET HOSTNAME=%COMPUTERNAME%
|
SET HOSTNAME=%COMPUTERNAME%
|
|
@ -102,9 +102,9 @@ if [ -e "$CONF_DIR" ]; then
|
||||||
case "$properties" in
|
case "$properties" in
|
||||||
*-Des.default.path.conf=*) ;;
|
*-Des.default.path.conf=*) ;;
|
||||||
*)
|
*)
|
||||||
if [ ! -d "$CONF_DIR/shield" ]; then
|
if [ ! -d "$CONF_DIR/xpack" ]; then
|
||||||
echo "ERROR: The configuration directory [$CONF_DIR/shield] does not exist. The esusers tool expects Shield configuration files in that location."
|
echo "ERROR: The configuration directory [$CONF_DIR/xpack] does not exist. The esusers tool expects security configuration files in that location."
|
||||||
echo "The plugin may not have been installed with the correct configuration path. If [$ES_HOME/config/shield] exists, please copy the shield directory to [$CONF_DIR]"
|
echo "The plugin may not have been installed with the correct configuration path. If [$ES_HOME/config/xpack] exists, please copy the 'xpack' directory to [$CONF_DIR]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
properties="$properties -Des.default.path.conf=$CONF_DIR"
|
properties="$properties -Des.default.path.conf=$CONF_DIR"
|
||||||
|
@ -123,7 +123,7 @@ fi
|
||||||
export HOSTNAME=`hostname -s`
|
export HOSTNAME=`hostname -s`
|
||||||
|
|
||||||
# include shield jars in classpath
|
# include shield jars in classpath
|
||||||
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/x-pack/*"
|
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/xpack/*"
|
||||||
|
|
||||||
cd "$ES_HOME" > /dev/null
|
cd "$ES_HOME" > /dev/null
|
||||||
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.authc.esusers.tool.ESUsersTool "$@"
|
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.authc.esusers.tool.ESUsersTool "$@"
|
|
@ -102,9 +102,9 @@ if [ -e "$CONF_DIR" ]; then
|
||||||
case "$properties" in
|
case "$properties" in
|
||||||
*-Des.default.path.conf=*) ;;
|
*-Des.default.path.conf=*) ;;
|
||||||
*)
|
*)
|
||||||
if [ ! -d "$CONF_DIR/shield" ]; then
|
if [ ! -d "$CONF_DIR/xpack" ]; then
|
||||||
echo "ERROR: The configuration directory [$CONF_DIR/shield] does not exist. The syskeygen tool expects Shield configuration files in that location."
|
echo "ERROR: The configuration directory [$CONF_DIR/xpack] does not exist. The syskeygen tool expects security configuration files in that location."
|
||||||
echo "The plugin may not have been installed with the correct configuration path. If [$ES_HOME/config/shield] exists, please copy the shield directory to [$CONF_DIR]"
|
echo "The plugin may not have been installed with the correct configuration path. If [$ES_HOME/config/xpack] exists, please copy the 'xpack' directory to [$CONF_DIR]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
properties="$properties -Des.default.path.conf=$CONF_DIR"
|
properties="$properties -Des.default.path.conf=$CONF_DIR"
|
||||||
|
@ -123,7 +123,7 @@ fi
|
||||||
export HOSTNAME=`hostname -s`
|
export HOSTNAME=`hostname -s`
|
||||||
|
|
||||||
# include shield jars in classpath
|
# include shield jars in classpath
|
||||||
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/x-pack/*"
|
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/xpack/*"
|
||||||
|
|
||||||
cd "$ES_HOME" > /dev/null
|
cd "$ES_HOME" > /dev/null
|
||||||
$JAVA $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.crypto.tool.SystemKeyTool "$@"
|
$JAVA $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.crypto.tool.SystemKeyTool "$@"
|
|
@ -6,7 +6,6 @@
|
||||||
package org.elasticsearch.shield;
|
package org.elasticsearch.shield;
|
||||||
|
|
||||||
import org.elasticsearch.action.ActionModule;
|
import org.elasticsearch.action.ActionModule;
|
||||||
import org.elasticsearch.client.Client;
|
|
||||||
import org.elasticsearch.common.component.LifecycleComponent;
|
import org.elasticsearch.common.component.LifecycleComponent;
|
||||||
import org.elasticsearch.common.inject.Module;
|
import org.elasticsearch.common.inject.Module;
|
||||||
import org.elasticsearch.common.network.NetworkModule;
|
import org.elasticsearch.common.network.NetworkModule;
|
||||||
|
@ -14,7 +13,6 @@ import org.elasticsearch.common.settings.Setting;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.settings.SettingsModule;
|
import org.elasticsearch.common.settings.SettingsModule;
|
||||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
import org.elasticsearch.env.Environment;
|
|
||||||
import org.elasticsearch.index.IndexModule;
|
import org.elasticsearch.index.IndexModule;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
import org.elasticsearch.shield.action.ShieldActionFilter;
|
import org.elasticsearch.shield.action.ShieldActionFilter;
|
||||||
|
@ -71,7 +69,6 @@ import org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport;
|
||||||
import org.elasticsearch.shield.transport.netty.ShieldNettyTransport;
|
import org.elasticsearch.shield.transport.netty.ShieldNettyTransport;
|
||||||
import org.elasticsearch.xpack.XPackPlugin;
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -85,22 +82,19 @@ import java.util.Map;
|
||||||
public class ShieldPlugin extends Plugin {
|
public class ShieldPlugin extends Plugin {
|
||||||
|
|
||||||
public static final String NAME = "shield";
|
public static final String NAME = "shield";
|
||||||
public static final String ENABLED_SETTING_NAME = NAME + ".enabled";
|
public static final String DLS_FLS_FEATURE = "shield.dls_fls";
|
||||||
public static final String OPT_OUT_QUERY_CACHE = "opt_out_cache";
|
public static final String OPT_OUT_QUERY_CACHE = "opt_out_cache";
|
||||||
public static final String DLS_FLS_ENABLED_SETTING = "shield.dls_fls.enabled";
|
|
||||||
|
|
||||||
private static final boolean DEFAULT_ENABLED_SETTING = true;
|
|
||||||
|
|
||||||
private final Settings settings;
|
private final Settings settings;
|
||||||
private final boolean enabled;
|
private final boolean enabled;
|
||||||
private final boolean clientMode;
|
private final boolean transportClientMode;
|
||||||
private ShieldLicenseState shieldLicenseState;
|
private ShieldLicenseState shieldLicenseState;
|
||||||
|
|
||||||
public ShieldPlugin(Settings settings) {
|
public ShieldPlugin(Settings settings) {
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.enabled = shieldEnabled(settings);
|
this.transportClientMode = XPackPlugin.transportClientMode(settings);
|
||||||
this.clientMode = clientMode(settings);
|
this.enabled = XPackPlugin.featureEnabled(settings, NAME, true);
|
||||||
if (enabled && clientMode == false) {
|
if (enabled && !transportClientMode) {
|
||||||
failIfShieldQueryCacheIsNotActive(settings, true);
|
failIfShieldQueryCacheIsNotActive(settings, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,11 +112,11 @@ public class ShieldPlugin extends Plugin {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Module> nodeModules() {
|
public Collection<Module> nodeModules() {
|
||||||
|
|
||||||
if (!enabled) {
|
if (enabled == false) {
|
||||||
return Collections.singletonList(new ShieldDisabledModule(settings));
|
return Collections.singletonList(new ShieldDisabledModule(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientMode) {
|
if (transportClientMode == true) {
|
||||||
return Arrays.<Module>asList(
|
return Arrays.<Module>asList(
|
||||||
new ShieldTransportModule(settings),
|
new ShieldTransportModule(settings),
|
||||||
new SSLModule(settings));
|
new SSLModule(settings));
|
||||||
|
@ -147,9 +141,13 @@ public class ShieldPlugin extends Plugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||||
if (enabled && clientMode == false) {
|
if (enabled == false || transportClientMode == true) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
List<Class<? extends LifecycleComponent>> list = new ArrayList<>();
|
List<Class<? extends LifecycleComponent>> list = new ArrayList<>();
|
||||||
if (AuditTrailModule.fileAuditLoggingEnabled(settings)) {
|
|
||||||
|
//TODO why only focus on file audit logs? shouldn't we just check if audit trail is enabled in general?
|
||||||
|
if (AuditTrailModule.fileAuditLoggingEnabled(settings) == true) {
|
||||||
list.add(LoggingAuditTrail.class);
|
list.add(LoggingAuditTrail.class);
|
||||||
}
|
}
|
||||||
list.add(ShieldLicensee.class);
|
list.add(ShieldLicensee.class);
|
||||||
|
@ -157,8 +155,7 @@ public class ShieldPlugin extends Plugin {
|
||||||
list.add(FileRolesStore.class);
|
list.add(FileRolesStore.class);
|
||||||
list.add(Realms.class);
|
list.add(Realms.class);
|
||||||
return list;
|
return list;
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -178,6 +175,7 @@ public class ShieldPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onModule(SettingsModule settingsModule) {
|
public void onModule(SettingsModule settingsModule) {
|
||||||
|
//TODO shouldn't we register these settings only if shield is enabled and we're not in a client mode?
|
||||||
settingsModule.registerSetting(IPFilter.IP_FILTER_ENABLED_SETTING);
|
settingsModule.registerSetting(IPFilter.IP_FILTER_ENABLED_SETTING);
|
||||||
settingsModule.registerSetting(IPFilter.IP_FILTER_ENABLED_HTTP_SETTING);
|
settingsModule.registerSetting(IPFilter.IP_FILTER_ENABLED_HTTP_SETTING);
|
||||||
settingsModule.registerSetting(IPFilter.HTTP_FILTER_ALLOW_SETTING);
|
settingsModule.registerSetting(IPFilter.HTTP_FILTER_ALLOW_SETTING);
|
||||||
|
@ -187,6 +185,9 @@ public class ShieldPlugin extends Plugin {
|
||||||
settingsModule.registerSetting(Setting.boolSetting("plugins.load_classpath_plugins", true, false, Setting.Scope.CLUSTER));
|
settingsModule.registerSetting(Setting.boolSetting("plugins.load_classpath_plugins", true, false, Setting.Scope.CLUSTER));
|
||||||
// TODO add real settings for this wildcard here
|
// TODO add real settings for this wildcard here
|
||||||
settingsModule.registerSetting(Setting.groupSetting("shield.", false, Setting.Scope.CLUSTER));
|
settingsModule.registerSetting(Setting.groupSetting("shield.", false, Setting.Scope.CLUSTER));
|
||||||
|
// TODO please let's just drop the old settings before releasing
|
||||||
|
settingsModule.registerSetting(Setting.groupSetting("xpack.shield.", false, Setting.Scope.CLUSTER));
|
||||||
|
|
||||||
String[] asArray = settings.getAsArray("shield.hide_settings");
|
String[] asArray = settings.getAsArray("shield.hide_settings");
|
||||||
for (String pattern : asArray) {
|
for (String pattern : asArray) {
|
||||||
settingsModule.registerSettingsFilter(pattern);
|
settingsModule.registerSettingsFilter(pattern);
|
||||||
|
@ -207,14 +208,15 @@ public class ShieldPlugin extends Plugin {
|
||||||
if (enabled == false) {
|
if (enabled == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert shieldLicenseState != null;
|
assert shieldLicenseState != null;
|
||||||
if (flsDlsEnabled(settings)) {
|
if (flsDlsEnabled(settings)) {
|
||||||
module.setSearcherWrapper((indexService) -> new ShieldIndexSearcherWrapper(indexService.getIndexSettings(),
|
module.setSearcherWrapper((indexService) -> new ShieldIndexSearcherWrapper(indexService.getIndexSettings(),
|
||||||
indexService.getQueryShardContext(), indexService.mapperService(),
|
indexService.newQueryShardContext(), indexService.mapperService(),
|
||||||
indexService.cache().bitsetFilterCache(), indexService.getIndexServices().getThreadPool().getThreadContext(),
|
indexService.cache().bitsetFilterCache(), indexService.getIndexServices().getThreadPool().getThreadContext(),
|
||||||
shieldLicenseState));
|
shieldLicenseState));
|
||||||
}
|
}
|
||||||
if (clientMode == false) {
|
if (transportClientMode == false) {
|
||||||
module.registerQueryCache(ShieldPlugin.OPT_OUT_QUERY_CACHE, OptOutQueryCache::new);
|
module.registerQueryCache(ShieldPlugin.OPT_OUT_QUERY_CACHE, OptOutQueryCache::new);
|
||||||
failIfShieldQueryCacheIsNotActive(module.getSettings(), false);
|
failIfShieldQueryCacheIsNotActive(module.getSettings(), false);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +227,7 @@ public class ShieldPlugin extends Plugin {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// registering the security filter only for nodes
|
// registering the security filter only for nodes
|
||||||
if (clientMode == false) {
|
if (transportClientMode == false) {
|
||||||
module.registerFilter(ShieldActionFilter.class);
|
module.registerFilter(ShieldActionFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,23 +243,21 @@ public class ShieldPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onModule(NetworkModule module) {
|
public void onModule(NetworkModule module) {
|
||||||
if (clientMode == false) {
|
|
||||||
// we want to expose the shield rest action even when the plugin is disabled
|
|
||||||
module.registerRestHandler(RestShieldInfoAction.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabled == false) {
|
if (transportClientMode) {
|
||||||
|
if (enabled) {
|
||||||
|
module.registerTransport(ShieldPlugin.NAME, ShieldNettyTransport.class);
|
||||||
|
module.registerTransportService(ShieldPlugin.NAME, ShieldClientTransportService.class);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.registerTransport(ShieldPlugin.NAME, ShieldNettyTransport.class);
|
// we want to expose the shield rest action even when the plugin is disabled
|
||||||
if (clientMode) {
|
module.registerRestHandler(RestShieldInfoAction.class);
|
||||||
module.registerTransportService(ShieldPlugin.NAME, ShieldClientTransportService.class);
|
|
||||||
} else {
|
|
||||||
module.registerTransportService(ShieldPlugin.NAME, ShieldServerTransportService.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientMode == false) {
|
if (enabled) {
|
||||||
|
module.registerTransport(ShieldPlugin.NAME, ShieldNettyTransport.class);
|
||||||
|
module.registerTransportService(ShieldPlugin.NAME, ShieldServerTransportService.class);
|
||||||
module.registerRestHandler(RestAuthenticateAction.class);
|
module.registerRestHandler(RestAuthenticateAction.class);
|
||||||
module.registerRestHandler(RestClearRealmCacheAction.class);
|
module.registerRestHandler(RestClearRealmCacheAction.class);
|
||||||
module.registerRestHandler(RestClearRolesCacheAction.class);
|
module.registerRestHandler(RestClearRolesCacheAction.class);
|
||||||
|
@ -290,39 +290,41 @@ public class ShieldPlugin extends Plugin {
|
||||||
.toCharArray())));
|
.toCharArray())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
We inject additional settings on each tribe client if the current node is a tribe node, to make sure that every tribe has shield
|
* If the current node is a tribe node, we inject additional settings on each tribe client. We do this to make sure
|
||||||
installed and enabled too:
|
* that every tribe cluster has shield installed and is enabled. We do that by:
|
||||||
- if shield is loaded on the tribe node we make sure it is also loaded on every tribe, by making it mandatory there
|
*
|
||||||
(this means that the tribe node will fail at startup if shield is not loaded on any tribe due to missing mandatory plugin)
|
* - making it mandatory on the tribe client (this means that the tribe node will fail at startup if shield is
|
||||||
- if shield is loaded and enabled on the tribe node, we make sure it is also enabled on every tribe, by forcibly enabling it
|
* not loaded on any tribe due to missing mandatory plugin)
|
||||||
(that means it's not possible to disable shield on the tribe clients)
|
*
|
||||||
|
* - forcibly enabling it (that means it's not possible to disable shield on the tribe clients)
|
||||||
*/
|
*/
|
||||||
private void addTribeSettings(Settings.Builder settingsBuilder) {
|
private void addTribeSettings(Settings.Builder settingsBuilder) {
|
||||||
Map<String, Settings> tribesSettings = settings.getGroups("tribe", true);
|
Map<String, Settings> tribesSettings = settings.getGroups("tribe", true);
|
||||||
if (tribesSettings.isEmpty()) {
|
if (tribesSettings.isEmpty()) {
|
||||||
|
// it's not a tribe node
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, Settings> tribeSettings : tribesSettings.entrySet()) {
|
for (Map.Entry<String, Settings> tribeSettings : tribesSettings.entrySet()) {
|
||||||
String tribePrefix = "tribe." + tribeSettings.getKey() + ".";
|
String tribePrefix = "tribe." + tribeSettings.getKey() + ".";
|
||||||
|
|
||||||
// we copy over existing mandatory plugins under additional settings, as they would get overridden otherwise (arrays don't get
|
// we copy over existing mandatory plugins under additional settings, as they would get overridden
|
||||||
// merged)
|
// otherwise (arrays don't get merged)
|
||||||
String[] existingMandatoryPlugins = tribeSettings.getValue().getAsArray("plugin.mandatory", null);
|
String[] existingMandatoryPlugins = tribeSettings.getValue().getAsArray("plugin.mandatory", null);
|
||||||
if (existingMandatoryPlugins == null) {
|
if (existingMandatoryPlugins == null) {
|
||||||
//shield is mandatory on every tribe if installed and enabled on the tribe node
|
//shield is mandatory on every tribe if installed and enabled on the tribe node
|
||||||
settingsBuilder.putArray(tribePrefix + "plugin.mandatory", NAME);
|
settingsBuilder.putArray(tribePrefix + "plugin.mandatory", XPackPlugin.NAME);
|
||||||
} else {
|
} else {
|
||||||
if (!isShieldMandatory(existingMandatoryPlugins)) {
|
if (Arrays.binarySearch(existingMandatoryPlugins, XPackPlugin.NAME) < 0) {
|
||||||
throw new IllegalStateException("when [plugin.mandatory] is explicitly configured, [" + NAME + "] must be included in" +
|
throw new IllegalStateException("when [plugin.mandatory] is explicitly configured, [" +
|
||||||
" this list");
|
XPackPlugin.NAME + "] must be included in this list");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final String tribeEnabledSetting = tribePrefix + ENABLED_SETTING_NAME;
|
final String tribeEnabledSetting = tribePrefix + XPackPlugin.featureEnabledSetting(NAME);
|
||||||
if (settings.get(tribeEnabledSetting) != null) {
|
if (settings.get(tribeEnabledSetting) != null) {
|
||||||
boolean enabled = shieldEnabled(tribeSettings.getValue());
|
boolean enabled = enabled(tribeSettings.getValue());
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
throw new IllegalStateException("tribe setting [" + tribeEnabledSetting + "] must be set to true but the value is ["
|
throw new IllegalStateException("tribe setting [" + tribeEnabledSetting + "] must be set to true but the value is ["
|
||||||
+ settings.get(tribeEnabledSetting) + "]");
|
+ settings.get(tribeEnabledSetting) + "]");
|
||||||
|
@ -334,43 +336,22 @@ public class ShieldPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
We need to forcefully overwrite the query cache implementation to use Shield's opt out query cache implementation.
|
* We need to forcefully overwrite the query cache implementation to use Shield's opt out query cache implementation.
|
||||||
This impl. disabled the query cache if field level security is used for a particular request. If we wouldn't do
|
* This impl. disabled the query cache if field level security is used for a particular request. If we wouldn't do
|
||||||
forcefully overwrite the query cache implementation then we leave the system vulnerable to leakages of data to
|
* forcefully overwrite the query cache implementation then we leave the system vulnerable to leakages of data to
|
||||||
unauthorized users.
|
* unauthorized users.
|
||||||
*/
|
*/
|
||||||
private void addQueryCacheSettings(Settings.Builder settingsBuilder) {
|
private void addQueryCacheSettings(Settings.Builder settingsBuilder) {
|
||||||
settingsBuilder.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), OPT_OUT_QUERY_CACHE);
|
settingsBuilder.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), OPT_OUT_QUERY_CACHE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isShieldMandatory(String[] existingMandatoryPlugins) {
|
public static boolean enabled(Settings settings) {
|
||||||
for (String existingMandatoryPlugin : existingMandatoryPlugins) {
|
return XPackPlugin.featureEnabled(settings, NAME, true);
|
||||||
if (NAME.equals(existingMandatoryPlugin)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Path configDir(Environment env) {
|
|
||||||
return env.configFile().resolve(XPackPlugin.NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Path resolveConfigFile(Environment env, String name) {
|
|
||||||
return configDir(env).resolve(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean clientMode(Settings settings) {
|
|
||||||
return !"node".equals(settings.get(Client.CLIENT_TYPE_SETTING_S.getKey()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean shieldEnabled(Settings settings) {
|
|
||||||
return settings.getAsBoolean(ENABLED_SETTING_NAME, DEFAULT_ENABLED_SETTING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean flsDlsEnabled(Settings settings) {
|
public static boolean flsDlsEnabled(Settings settings) {
|
||||||
return settings.getAsBoolean(DLS_FLS_ENABLED_SETTING, true);
|
return XPackPlugin.featureEnabled(settings, DLS_FLS_FEATURE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void failIfShieldQueryCacheIsNotActive(Settings settings, boolean nodeSettings) {
|
private void failIfShieldQueryCacheIsNotActive(Settings settings, boolean nodeSettings) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ import org.elasticsearch.shield.action.user.DeleteUserRequest;
|
||||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||||
import org.elasticsearch.shield.authc.support.Hasher;
|
import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
import org.elasticsearch.threadpool.ThreadPool;
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -458,10 +458,10 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
||||||
}
|
}
|
||||||
|
|
||||||
private <Response> void clearRealmCache(String username, ActionListener<Response> listener, Response response) {
|
private <Response> void clearRealmCache(String username, ActionListener<Response> listener, Response response) {
|
||||||
ShieldClient shieldClient = new ShieldClient(client);
|
SecurityClient securityClient = new SecurityClient(client);
|
||||||
ClearRealmCacheRequest request = shieldClient.prepareClearRealmCache()
|
ClearRealmCacheRequest request = securityClient.prepareClearRealmCache()
|
||||||
.usernames(username).request();
|
.usernames(username).request();
|
||||||
shieldClient.clearRealmCache(request, new ActionListener<ClearRealmCacheResponse>() {
|
securityClient.clearRealmCache(request, new ActionListener<ClearRealmCacheResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(ClearRealmCacheResponse nodes) {
|
public void onResponse(ClearRealmCacheResponse nodes) {
|
||||||
listener.onResponse(response);
|
listener.onResponse(response);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.shield.support.Validation;
|
||||||
import org.elasticsearch.watcher.FileChangesListener;
|
import org.elasticsearch.watcher.FileChangesListener;
|
||||||
import org.elasticsearch.watcher.FileWatcher;
|
import org.elasticsearch.watcher.FileWatcher;
|
||||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
@ -98,7 +99,7 @@ public class FileUserPasswdStore {
|
||||||
public static Path resolveFile(Settings settings, Environment env) {
|
public static Path resolveFile(Settings settings, Environment env) {
|
||||||
String location = settings.get("files.users");
|
String location = settings.get("files.users");
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
return ShieldPlugin.resolveConfigFile(env, "users");
|
return XPackPlugin.resolveConfigFile(env, "users");
|
||||||
}
|
}
|
||||||
return env.binFile().getParent().resolve(location);
|
return env.binFile().getParent().resolve(location);
|
||||||
}
|
}
|
||||||
|
@ -166,7 +167,7 @@ public class FileUserPasswdStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (users.isEmpty()) {
|
if (users.isEmpty()) {
|
||||||
logger.warn("no users found in users file [{}]. use bin/shield/esusers to add users and role mappings", path.toAbsolutePath());
|
logger.warn("no users found in users file [{}]. use bin/xpack/esusers to add users and role mappings", path.toAbsolutePath());
|
||||||
}
|
}
|
||||||
return unmodifiableMap(users);
|
return unmodifiableMap(users);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.elasticsearch.shield.support.Validation;
|
||||||
import org.elasticsearch.watcher.FileChangesListener;
|
import org.elasticsearch.watcher.FileChangesListener;
|
||||||
import org.elasticsearch.watcher.FileWatcher;
|
import org.elasticsearch.watcher.FileWatcher;
|
||||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
@ -91,7 +92,7 @@ public class FileUserRolesStore {
|
||||||
public static Path resolveFile(Settings settings, Environment env) {
|
public static Path resolveFile(Settings settings, Environment env) {
|
||||||
String location = settings.get("files.users_roles");
|
String location = settings.get("files.users_roles");
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
return ShieldPlugin.resolveConfigFile(env, "users_roles");
|
return XPackPlugin.resolveConfigFile(env, "users_roles");
|
||||||
}
|
}
|
||||||
return env.binFile().getParent().resolve(location);
|
return env.binFile().getParent().resolve(location);
|
||||||
}
|
}
|
||||||
|
@ -181,7 +182,7 @@ public class FileUserRolesStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usersRoles.isEmpty()) {
|
if (usersRoles.isEmpty()) {
|
||||||
logger.warn("no entries found in users_roles file [{}]. use bin/shield/esusers to add users and role mappings", path
|
logger.warn("no entries found in users_roles file [{}]. use bin/xpack/esusers to add users and role mappings", path
|
||||||
.toAbsolutePath());
|
.toAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.shield.authc.RealmConfig;
|
||||||
import org.elasticsearch.watcher.FileChangesListener;
|
import org.elasticsearch.watcher.FileChangesListener;
|
||||||
import org.elasticsearch.watcher.FileWatcher;
|
import org.elasticsearch.watcher.FileWatcher;
|
||||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -82,7 +83,7 @@ public class DnRoleMapper {
|
||||||
public static Path resolveFile(Settings settings, Environment env) {
|
public static Path resolveFile(Settings settings, Environment env) {
|
||||||
String location = settings.get(ROLE_MAPPING_FILE_SETTING);
|
String location = settings.get(ROLE_MAPPING_FILE_SETTING);
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
return ShieldPlugin.resolveConfigFile(env, DEFAULT_FILE_NAME);
|
return XPackPlugin.resolveConfigFile(env, DEFAULT_FILE_NAME);
|
||||||
}
|
}
|
||||||
return env.binFile().getParent().resolve(location);
|
return env.binFile().getParent().resolve(location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.shield.authc.support;
|
||||||
|
|
||||||
import org.elasticsearch.common.Base64;
|
import org.elasticsearch.common.Base64;
|
||||||
import org.elasticsearch.common.Randomness;
|
import org.elasticsearch.common.Randomness;
|
||||||
|
import org.elasticsearch.common.hash.MessageDigests;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
@ -142,7 +143,7 @@ public enum Hasher {
|
||||||
@Override
|
@Override
|
||||||
public char[] hash(SecuredString text) {
|
public char[] hash(SecuredString text) {
|
||||||
byte[] textBytes = CharArrays.toUtf8Bytes(text.internalChars());
|
byte[] textBytes = CharArrays.toUtf8Bytes(text.internalChars());
|
||||||
MessageDigest md = SHA1Provider.sha1();
|
MessageDigest md = MessageDigests.sha1();
|
||||||
md.update(textBytes);
|
md.update(textBytes);
|
||||||
String hash = Base64.encodeBytes(md.digest());
|
String hash = Base64.encodeBytes(md.digest());
|
||||||
return (SHA1_PREFIX + hash).toCharArray();
|
return (SHA1_PREFIX + hash).toCharArray();
|
||||||
|
@ -155,7 +156,7 @@ public enum Hasher {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
byte[] textBytes = CharArrays.toUtf8Bytes(text.internalChars());
|
byte[] textBytes = CharArrays.toUtf8Bytes(text.internalChars());
|
||||||
MessageDigest md = SHA1Provider.sha1();
|
MessageDigest md = MessageDigests.sha1();
|
||||||
md.update(textBytes);
|
md.update(textBytes);
|
||||||
String passwd64 = Base64.encodeBytes(md.digest());
|
String passwd64 = Base64.encodeBytes(md.digest());
|
||||||
String hashNoPrefix = hashStr.substring(SHA1_PREFIX.length());
|
String hashNoPrefix = hashStr.substring(SHA1_PREFIX.length());
|
||||||
|
@ -166,7 +167,7 @@ public enum Hasher {
|
||||||
MD5() {
|
MD5() {
|
||||||
@Override
|
@Override
|
||||||
public char[] hash(SecuredString text) {
|
public char[] hash(SecuredString text) {
|
||||||
MessageDigest md = MD5Provider.md5();
|
MessageDigest md = MessageDigests.md5();
|
||||||
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
||||||
String hash = Base64.encodeBytes(md.digest());
|
String hash = Base64.encodeBytes(md.digest());
|
||||||
return (MD5_PREFIX + hash).toCharArray();
|
return (MD5_PREFIX + hash).toCharArray();
|
||||||
|
@ -179,7 +180,7 @@ public enum Hasher {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
hashStr = hashStr.substring(MD5_PREFIX.length());
|
hashStr = hashStr.substring(MD5_PREFIX.length());
|
||||||
MessageDigest md = MD5Provider.md5();
|
MessageDigest md = MessageDigests.md5();
|
||||||
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
||||||
String computedHashStr = Base64.encodeBytes(md.digest());
|
String computedHashStr = Base64.encodeBytes(md.digest());
|
||||||
return SecuredString.constantTimeEquals(hashStr, computedHashStr);
|
return SecuredString.constantTimeEquals(hashStr, computedHashStr);
|
||||||
|
@ -189,7 +190,7 @@ public enum Hasher {
|
||||||
SSHA256() {
|
SSHA256() {
|
||||||
@Override
|
@Override
|
||||||
public char[] hash(SecuredString text) {
|
public char[] hash(SecuredString text) {
|
||||||
MessageDigest md = SHA256Provider.sha256();
|
MessageDigest md = MessageDigests.sha256();
|
||||||
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
||||||
char[] salt = SaltProvider.salt(8);
|
char[] salt = SaltProvider.salt(8);
|
||||||
md.update(CharArrays.toUtf8Bytes(salt));
|
md.update(CharArrays.toUtf8Bytes(salt));
|
||||||
|
@ -209,7 +210,7 @@ public enum Hasher {
|
||||||
}
|
}
|
||||||
hashStr = hashStr.substring(SSHA256_PREFIX.length());
|
hashStr = hashStr.substring(SSHA256_PREFIX.length());
|
||||||
char[] saltAndHash = hashStr.toCharArray();
|
char[] saltAndHash = hashStr.toCharArray();
|
||||||
MessageDigest md = SHA256Provider.sha256();
|
MessageDigest md = MessageDigests.sha256();
|
||||||
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
md.update(CharArrays.toUtf8Bytes(text.internalChars()));
|
||||||
md.update(new String(saltAndHash, 0, 8).getBytes(StandardCharsets.UTF_8));
|
md.update(new String(saltAndHash, 0, 8).getBytes(StandardCharsets.UTF_8));
|
||||||
String computedHash = Base64.encodeBytes(md.digest());
|
String computedHash = Base64.encodeBytes(md.digest());
|
||||||
|
@ -279,76 +280,6 @@ public enum Hasher {
|
||||||
|
|
||||||
public abstract boolean verify(SecuredString data, char[] hash);
|
public abstract boolean verify(SecuredString data, char[] hash);
|
||||||
|
|
||||||
static final class MD5Provider {
|
|
||||||
|
|
||||||
private static final MessageDigest digest;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
digest = MessageDigest.getInstance("MD5");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new IllegalStateException("unsupported digest algorithm [MD5]. Please verify you are running on Java 7 or above", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MessageDigest md5() {
|
|
||||||
try {
|
|
||||||
MessageDigest md5 = (MessageDigest) digest.clone();
|
|
||||||
md5.reset();
|
|
||||||
return md5;
|
|
||||||
} catch (CloneNotSupportedException e) {
|
|
||||||
throw new IllegalStateException("could not create MD5 digest", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class SHA1Provider {
|
|
||||||
|
|
||||||
private static final MessageDigest digest;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
digest = MessageDigest.getInstance("SHA-1");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new IllegalStateException("unsupported digest algorithm [SHA-1]", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MessageDigest sha1() {
|
|
||||||
try {
|
|
||||||
MessageDigest sha1 = (MessageDigest) digest.clone();
|
|
||||||
sha1.reset();
|
|
||||||
return sha1;
|
|
||||||
} catch (CloneNotSupportedException e) {
|
|
||||||
throw new IllegalStateException("could not create SHA-1 digest", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class SHA256Provider {
|
|
||||||
|
|
||||||
private static final MessageDigest digest;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
digest = MessageDigest.getInstance("SHA-256");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
String msg = "unsupported digest algorithm [SHA-256]. Please verify you are running on Java 7 or above";
|
|
||||||
throw new IllegalStateException(msg, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MessageDigest sha256() {
|
|
||||||
try {
|
|
||||||
MessageDigest sha = (MessageDigest) digest.clone();
|
|
||||||
sha.reset();
|
|
||||||
return sha;
|
|
||||||
} catch (CloneNotSupportedException e) {
|
|
||||||
throw new IllegalStateException("could not create [SHA-256] digest", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class SaltProvider {
|
static final class SaltProvider {
|
||||||
|
|
||||||
static final char[] ALPHABET = new char[]{
|
static final char[] ALPHABET = new char[]{
|
||||||
|
|
|
@ -48,7 +48,7 @@ import org.elasticsearch.shield.authc.AuthenticationService;
|
||||||
import org.elasticsearch.shield.authz.RoleDescriptor;
|
import org.elasticsearch.shield.authz.RoleDescriptor;
|
||||||
import org.elasticsearch.shield.authz.permission.Role;
|
import org.elasticsearch.shield.authz.permission.Role;
|
||||||
import org.elasticsearch.shield.authz.store.RolesStore;
|
import org.elasticsearch.shield.authz.store.RolesStore;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
import org.elasticsearch.threadpool.ThreadPool;
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -84,7 +84,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
||||||
private final ConcurrentHashMap<String, RoleAndVersion> roleCache = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, RoleAndVersion> roleCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Client client;
|
private Client client;
|
||||||
private ShieldClient shieldClient;
|
private SecurityClient securityClient;
|
||||||
private int scrollSize;
|
private int scrollSize;
|
||||||
private TimeValue scrollKeepAlive;
|
private TimeValue scrollKeepAlive;
|
||||||
private ScheduledFuture<?> versionChecker;
|
private ScheduledFuture<?> versionChecker;
|
||||||
|
@ -353,7 +353,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
||||||
try {
|
try {
|
||||||
if (state.compareAndSet(State.INITIALIZED, State.STARTING)) {
|
if (state.compareAndSet(State.INITIALIZED, State.STARTING)) {
|
||||||
this.client = clientProvider.get();
|
this.client = clientProvider.get();
|
||||||
this.shieldClient = new ShieldClient(client);
|
this.securityClient = new SecurityClient(client);
|
||||||
this.scrollSize = settings.getAsInt("shield.authc.native.scroll.size", 1000);
|
this.scrollSize = settings.getAsInt("shield.authc.native.scroll.size", 1000);
|
||||||
this.scrollKeepAlive = settings.getAsTime("shield.authc.native.scroll.keep_alive", TimeValue.timeValueSeconds(10L));
|
this.scrollKeepAlive = settings.getAsTime("shield.authc.native.scroll.keep_alive", TimeValue.timeValueSeconds(10L));
|
||||||
TimeValue pollInterval = settings.getAsTime("shield.authc.native.reload.interval", TimeValue.timeValueSeconds(30L));
|
TimeValue pollInterval = settings.getAsTime("shield.authc.native.reload.interval", TimeValue.timeValueSeconds(30L));
|
||||||
|
@ -407,7 +407,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
||||||
|
|
||||||
private <Response> void clearRoleCache(final String role, ActionListener<Response> listener, Response response) {
|
private <Response> void clearRoleCache(final String role, ActionListener<Response> listener, Response response) {
|
||||||
ClearRolesCacheRequest request = new ClearRolesCacheRequest().roles(role);
|
ClearRolesCacheRequest request = new ClearRolesCacheRequest().roles(role);
|
||||||
shieldClient.clearRolesCache(request, new ActionListener<ClearRolesCacheResponse>() {
|
securityClient.clearRolesCache(request, new ActionListener<ClearRolesCacheResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(ClearRolesCacheResponse nodes) {
|
public void onResponse(ClearRolesCacheResponse nodes) {
|
||||||
listener.onResponse(response);
|
listener.onResponse(response);
|
||||||
|
|
|
@ -32,16 +32,18 @@ public class IndexPrivilege extends AbstractAutomatonPrivilege<IndexPrivilege> {
|
||||||
public static final IndexPrivilege CREATE_INDEX = new IndexPrivilege("create_index", CreateIndexAction.NAME);
|
public static final IndexPrivilege CREATE_INDEX = new IndexPrivilege("create_index", CreateIndexAction.NAME);
|
||||||
public static final IndexPrivilege MANAGE_ALIASES = new IndexPrivilege("manage_aliases", "indices:admin/aliases*");
|
public static final IndexPrivilege MANAGE_ALIASES = new IndexPrivilege("manage_aliases", "indices:admin/aliases*");
|
||||||
public static final IndexPrivilege MONITOR = new IndexPrivilege("monitor", "indices:monitor/*");
|
public static final IndexPrivilege MONITOR = new IndexPrivilege("monitor", "indices:monitor/*");
|
||||||
public static final IndexPrivilege DATA_ACCESS = new IndexPrivilege("data_access", "indices:data/*");
|
public static final IndexPrivilege DATA_ACCESS = new IndexPrivilege("data_access", "indices:data/*", "indices:admin/mapping/put");
|
||||||
public static final IndexPrivilege CRUD = new IndexPrivilege("crud", "indices:data/write/*", "indices:data/read/*");
|
public static final IndexPrivilege CRUD =
|
||||||
|
new IndexPrivilege("crud", "indices:data/write/*", "indices:data/read/*", "indices:admin/mapping/put");
|
||||||
public static final IndexPrivilege READ = new IndexPrivilege("read", "indices:data/read/*");
|
public static final IndexPrivilege READ = new IndexPrivilege("read", "indices:data/read/*");
|
||||||
public static final IndexPrivilege SEARCH = new IndexPrivilege("search", SearchAction.NAME + "*", MultiSearchAction.NAME + "*",
|
public static final IndexPrivilege SEARCH =
|
||||||
SuggestAction.NAME + "*");
|
new IndexPrivilege("search", SearchAction.NAME + "*", MultiSearchAction.NAME + "*", SuggestAction.NAME + "*");
|
||||||
public static final IndexPrivilege GET = new IndexPrivilege("get", GetAction.NAME + "*", MultiGetAction.NAME + "*");
|
public static final IndexPrivilege GET = new IndexPrivilege("get", GetAction.NAME + "*", MultiGetAction.NAME + "*");
|
||||||
public static final IndexPrivilege SUGGEST = new IndexPrivilege("suggest", SuggestAction.NAME + "*");
|
public static final IndexPrivilege SUGGEST = new IndexPrivilege("suggest", SuggestAction.NAME + "*");
|
||||||
public static final IndexPrivilege INDEX = new IndexPrivilege("index", "indices:data/write/index*", "indices:data/write/update*");
|
public static final IndexPrivilege INDEX =
|
||||||
|
new IndexPrivilege("index", "indices:data/write/index*", "indices:data/write/update*", "indices:admin/mapping/put");
|
||||||
public static final IndexPrivilege DELETE = new IndexPrivilege("delete", "indices:data/write/delete*");
|
public static final IndexPrivilege DELETE = new IndexPrivilege("delete", "indices:data/write/delete*");
|
||||||
public static final IndexPrivilege WRITE = new IndexPrivilege("write", "indices:data/write/*");
|
public static final IndexPrivilege WRITE = new IndexPrivilege("write", "indices:data/write/*", "indices:admin/mapping/put");
|
||||||
|
|
||||||
private static final Set<IndexPrivilege> values = new CopyOnWriteArraySet<>();
|
private static final Set<IndexPrivilege> values = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,7 @@ public class SystemPrivilege extends Privilege<SystemPrivilege> {
|
||||||
"internal:*",
|
"internal:*",
|
||||||
"indices:monitor/*", // added for marvel
|
"indices:monitor/*", // added for marvel
|
||||||
"cluster:monitor/*", // added for marvel
|
"cluster:monitor/*", // added for marvel
|
||||||
"cluster:admin/reroute", // added for DiskThresholdDecider.DiskListener
|
"cluster:admin/reroute" // added for DiskThresholdDecider.DiskListener
|
||||||
"indices:admin/mapping/put" // ES 2.0 MappingUpdatedAction - updateMappingOnMasterSynchronously
|
|
||||||
));
|
));
|
||||||
|
|
||||||
SystemPrivilege() {
|
SystemPrivilege() {
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.elasticsearch.shield.support.Validation;
|
||||||
import org.elasticsearch.watcher.FileChangesListener;
|
import org.elasticsearch.watcher.FileChangesListener;
|
||||||
import org.elasticsearch.watcher.FileWatcher;
|
import org.elasticsearch.watcher.FileWatcher;
|
||||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -109,7 +110,7 @@ public class FileRolesStore extends AbstractLifecycleComponent<RolesStore> imple
|
||||||
public static Path resolveFile(Settings settings, Environment env) {
|
public static Path resolveFile(Settings settings, Environment env) {
|
||||||
String location = settings.get("shield.authz.store.files.roles");
|
String location = settings.get("shield.authz.store.files.roles");
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
return ShieldPlugin.resolveConfigFile(env, "roles.yml");
|
return XPackPlugin.resolveConfigFile(env, "roles.yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
return env.binFile().getParent().resolve(location);
|
return env.binFile().getParent().resolve(location);
|
||||||
|
@ -285,10 +286,10 @@ public class FileRolesStore extends AbstractLifecycleComponent<RolesStore> imple
|
||||||
if (token == XContentParser.Token.VALUE_STRING) {
|
if (token == XContentParser.Token.VALUE_STRING) {
|
||||||
names.add(parser.text());
|
names.add(parser.text());
|
||||||
} else {
|
} else {
|
||||||
logger.error("invalid role definition [{}] in roles file [{}]. could " +
|
logger.error("invalid role definition [{}] in roles file [{}]. " +
|
||||||
"not parse " +
|
"could not parse [{}] as index privilege. privilege " +
|
||||||
"[{}] as index privilege. privilege names must be strings. " +
|
"names must be strings. skipping role...", roleName,
|
||||||
"skipping role...", roleName, path.toAbsolutePath(), token);
|
path.toAbsolutePath(), token);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,26 +302,27 @@ public class FileRolesStore extends AbstractLifecycleComponent<RolesStore> imple
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if ((query != null || (fields != null && fields.isEmpty() == false)) &&
|
if ((query != null || (fields != null && fields.isEmpty() == false)) &&
|
||||||
ShieldPlugin.flsDlsEnabled(settings) == false) {
|
ShieldPlugin.flsDlsEnabled(settings) == false) {
|
||||||
logger.error("invalid role definition [{}] in roles file [{}]. document and field" +
|
logger.error("invalid role definition [{}] in roles file [{}]. " +
|
||||||
" level security is not enabled. set [{}] to [true] in the configuration " +
|
"document and field level security is not enabled. " +
|
||||||
"file. skipping role...", roleName, path.toAbsolutePath(), ShieldPlugin
|
"set [{}] to [true] in the configuration file. skipping role...",
|
||||||
.DLS_FLS_ENABLED_SETTING);
|
roleName, path.toAbsolutePath(),
|
||||||
|
XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
role.add(fields, query, IndexPrivilege.get(name), indices);
|
role.add(fields, query, IndexPrivilege.get(name), indices);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
logger.error("invalid role definition [{}] in roles file [{}]. could not resolve " +
|
logger.error("invalid role definition [{}] in roles file [{}]. could not " +
|
||||||
"indices privileges [{}]. skipping role...", roleName,
|
"resolve indices privileges [{}]. skipping role...", roleName,
|
||||||
path.toAbsolutePath(), name);
|
path.toAbsolutePath(), name);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
logger.error("invalid role definition [{}] in roles file [{}]. could not parse [{}] as " +
|
logger.error("invalid role definition [{}] in roles file [{}]. " +
|
||||||
"index privileges. privilege lists must either " +
|
"could not parse [{}] as index privileges. privilege lists must either " +
|
||||||
"be a comma delimited string or an array of strings. skipping role...", roleName,
|
"be a comma delimited string or an array of strings. skipping role...", roleName,
|
||||||
path.toAbsolutePath(), token);
|
path.toAbsolutePath(), token);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -44,19 +44,12 @@ import org.elasticsearch.shield.action.role.ClearRolesCacheResponse;
|
||||||
/**
|
/**
|
||||||
* A wrapper to elasticsearch clients that exposes all Shield related APIs
|
* A wrapper to elasticsearch clients that exposes all Shield related APIs
|
||||||
*/
|
*/
|
||||||
public class ShieldClient {
|
public class SecurityClient {
|
||||||
|
|
||||||
private final ElasticsearchClient client;
|
private final ElasticsearchClient client;
|
||||||
private final ShieldAuthcClient authcClient;
|
|
||||||
|
|
||||||
public ShieldClient(ElasticsearchClient client) {
|
public SecurityClient(ElasticsearchClient client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.authcClient = new ShieldAuthcClient(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public ShieldAuthcClient authc() {
|
|
||||||
return authcClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************
|
/****************
|
|
@ -1,54 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.shield.client;
|
|
||||||
|
|
||||||
import org.elasticsearch.action.ActionFuture;
|
|
||||||
import org.elasticsearch.action.ActionListener;
|
|
||||||
import org.elasticsearch.client.ElasticsearchClient;
|
|
||||||
import org.elasticsearch.shield.action.realm.ClearRealmCacheAction;
|
|
||||||
import org.elasticsearch.shield.action.realm.ClearRealmCacheRequest;
|
|
||||||
import org.elasticsearch.shield.action.realm.ClearRealmCacheRequestBuilder;
|
|
||||||
import org.elasticsearch.shield.action.realm.ClearRealmCacheResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A client to manage Shield's authentication
|
|
||||||
*
|
|
||||||
* @deprecated Use {@link ShieldClient} directly instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class ShieldAuthcClient {
|
|
||||||
|
|
||||||
private final ElasticsearchClient client;
|
|
||||||
|
|
||||||
ShieldAuthcClient(ElasticsearchClient client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the realm caches. It's possible to clear all user entries from all realms in the cluster or alternatively
|
|
||||||
* select the realms (by their unique names) and/or users (by their usernames) that should be evicted.
|
|
||||||
*/
|
|
||||||
public ClearRealmCacheRequestBuilder prepareClearRealmCache() {
|
|
||||||
return new ClearRealmCacheRequestBuilder(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the realm caches. It's possible to clear all user entries from all realms in the cluster or alternatively
|
|
||||||
* select the realms (by their unique names) and/or users (by their usernames) that should be evicted.
|
|
||||||
*/
|
|
||||||
public void clearRealmCache(ClearRealmCacheRequest request, ActionListener<ClearRealmCacheResponse> listener) {
|
|
||||||
client.execute(ClearRealmCacheAction.INSTANCE, request, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the realm caches. It's possible to clear all user entries from all realms in the cluster or alternatively
|
|
||||||
* select the realms (by their unique names) and/or users (by their usernames) that should be evicted.
|
|
||||||
*/
|
|
||||||
public ActionFuture<ClearRealmCacheResponse> clearRealmCache(ClearRealmCacheRequest request) {
|
|
||||||
return client.execute(ClearRealmCacheAction.INSTANCE, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.shield.authc.support.CharArrays;
|
||||||
import org.elasticsearch.watcher.FileChangesListener;
|
import org.elasticsearch.watcher.FileChangesListener;
|
||||||
import org.elasticsearch.watcher.FileWatcher;
|
import org.elasticsearch.watcher.FileWatcher;
|
||||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
@ -159,7 +160,7 @@ public class InternalCryptoService extends AbstractLifecycleComponent<InternalCr
|
||||||
public static Path resolveSystemKey(Settings settings, Environment env) {
|
public static Path resolveSystemKey(Settings settings, Environment env) {
|
||||||
String location = settings.get(FILE_SETTING);
|
String location = settings.get(FILE_SETTING);
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
return ShieldPlugin.resolveConfigFile(env, FILE_NAME);
|
return XPackPlugin.resolveConfigFile(env, FILE_NAME);
|
||||||
}
|
}
|
||||||
return env.binFile().getParent().resolve(location);
|
return env.binFile().getParent().resolve(location);
|
||||||
}
|
}
|
||||||
|
@ -564,30 +565,25 @@ public class InternalCryptoService extends AbstractLifecycleComponent<InternalCr
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider class for the HmacSHA1 {@link Mac} that provides an optimization by using clone instead of calling
|
* Provider class for the HmacSHA1 {@link Mac} that provides an optimization by using a thread local instead of calling
|
||||||
* Mac#getInstance and obtaining a lock
|
* Mac#getInstance and obtaining a lock (in the internals)
|
||||||
*/
|
*/
|
||||||
private static class HmacSHA1Provider {
|
private static class HmacSHA1Provider {
|
||||||
|
|
||||||
private static final Mac mac;
|
private static final ThreadLocal<Mac> MAC = ThreadLocal.withInitial(() -> {
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
try {
|
||||||
mac = Mac.getInstance(HMAC_ALGO);
|
return Mac.getInstance(HMAC_ALGO);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
throw new IllegalStateException("could not create message authentication code instance with algorithm [HmacSHA1]", e);
|
throw new IllegalStateException("could not create Mac instance with algorithm [" + HMAC_ALGO + "]", e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
private static Mac hmacSHA1() {
|
private static Mac hmacSHA1() {
|
||||||
try {
|
Mac instance = MAC.get();
|
||||||
Mac hmac = (Mac) mac.clone();
|
instance.reset();
|
||||||
hmac.reset();
|
return instance;
|
||||||
return hmac;
|
|
||||||
} catch (CloneNotSupportedException e) {
|
|
||||||
throw new IllegalStateException("could not create [HmacSHA1] MAC", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class RestShieldInfoAction extends BaseRestHandler {
|
||||||
super(settings, client);
|
super(settings, client);
|
||||||
this.clusterName = clusterName;
|
this.clusterName = clusterName;
|
||||||
this.shieldLicenseState = licenseState;
|
this.shieldLicenseState = licenseState;
|
||||||
this.shieldEnabled = ShieldPlugin.shieldEnabled(settings);
|
this.shieldEnabled = ShieldPlugin.enabled(settings);
|
||||||
controller.registerHandler(GET, "/_shield", this);
|
controller.registerHandler(GET, "/_shield", this);
|
||||||
controller.registerHandler(HEAD, "/_shield", this);
|
controller.registerHandler(HEAD, "/_shield", this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.action.realm.ClearRealmCacheRequest;
|
import org.elasticsearch.shield.action.realm.ClearRealmCacheRequest;
|
||||||
import org.elasticsearch.shield.action.realm.ClearRealmCacheResponse;
|
import org.elasticsearch.shield.action.realm.ClearRealmCacheResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public class RestClearRealmCacheAction extends BaseRestHandler {
|
||||||
|
|
||||||
ClearRealmCacheRequest req = new ClearRealmCacheRequest().realms(realms).usernames(usernames);
|
ClearRealmCacheRequest req = new ClearRealmCacheRequest().realms(realms).usernames(usernames);
|
||||||
|
|
||||||
new ShieldClient(client).clearRealmCache(req, new RestBuilderListener<ClearRealmCacheResponse>(channel) {
|
new SecurityClient(client).clearRealmCache(req, new RestBuilderListener<ClearRealmCacheResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(ClearRealmCacheResponse response, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(ClearRealmCacheResponse response, XContentBuilder builder) throws Exception {
|
||||||
response.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
response.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.action.role.AddRoleRequest;
|
import org.elasticsearch.shield.action.role.AddRoleRequest;
|
||||||
import org.elasticsearch.shield.action.role.AddRoleResponse;
|
import org.elasticsearch.shield.action.role.AddRoleResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rest endpoint to add a Role to the shield index
|
* Rest endpoint to add a Role to the shield index
|
||||||
|
@ -38,7 +38,7 @@ public class RestAddRoleAction extends BaseRestHandler {
|
||||||
AddRoleRequest addRoleReq = new AddRoleRequest(request.content());
|
AddRoleRequest addRoleReq = new AddRoleRequest(request.content());
|
||||||
addRoleReq.name(request.param("id"));
|
addRoleReq.name(request.param("id"));
|
||||||
|
|
||||||
new ShieldClient(client).addRole(addRoleReq, new RestBuilderListener<AddRoleResponse>(channel) {
|
new SecurityClient(client).addRole(addRoleReq, new RestBuilderListener<AddRoleResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(AddRoleResponse addRoleResponse, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(AddRoleResponse addRoleResponse, XContentBuilder builder) throws Exception {
|
||||||
return new BytesRestResponse(RestStatus.OK,
|
return new BytesRestResponse(RestStatus.OK,
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.action.role.ClearRolesCacheRequest;
|
import org.elasticsearch.shield.action.role.ClearRolesCacheRequest;
|
||||||
import org.elasticsearch.shield.action.role.ClearRolesCacheResponse;
|
import org.elasticsearch.shield.action.role.ClearRolesCacheResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class RestClearRolesCacheAction extends BaseRestHandler {
|
||||||
|
|
||||||
ClearRolesCacheRequest req = new ClearRolesCacheRequest().roles(roles);
|
ClearRolesCacheRequest req = new ClearRolesCacheRequest().roles(roles);
|
||||||
|
|
||||||
new ShieldClient(client).clearRolesCache(req, new RestBuilderListener<ClearRolesCacheResponse>(channel) {
|
new SecurityClient(client).clearRolesCache(req, new RestBuilderListener<ClearRolesCacheResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(ClearRolesCacheResponse response, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(ClearRolesCacheResponse response, XContentBuilder builder) throws Exception {
|
||||||
response.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
response.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.action.role.DeleteRoleRequest;
|
import org.elasticsearch.shield.action.role.DeleteRoleRequest;
|
||||||
import org.elasticsearch.shield.action.role.DeleteRoleResponse;
|
import org.elasticsearch.shield.action.role.DeleteRoleResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rest endpoint to delete a Role from the shield index
|
* Rest endpoint to delete a Role from the shield index
|
||||||
|
@ -37,7 +37,7 @@ public class RestDeleteRoleAction extends BaseRestHandler {
|
||||||
String role = request.param("id");
|
String role = request.param("id");
|
||||||
DeleteRoleRequest delRoleRequest = new DeleteRoleRequest(role);
|
DeleteRoleRequest delRoleRequest = new DeleteRoleRequest(role);
|
||||||
|
|
||||||
new ShieldClient(client).deleteRole(delRoleRequest, new RestBuilderListener<DeleteRoleResponse>(channel) {
|
new SecurityClient(client).deleteRole(delRoleRequest, new RestBuilderListener<DeleteRoleResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(DeleteRoleResponse response, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(DeleteRoleResponse response, XContentBuilder builder) throws Exception {
|
||||||
return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND,
|
return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND,
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.elasticsearch.rest.RestResponse;
|
||||||
import org.elasticsearch.rest.RestStatus;
|
import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.action.role.GetRolesResponse;
|
import org.elasticsearch.shield.action.role.GetRolesResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rest endpoint to retrieve a Role from the shield index
|
* Rest endpoint to retrieve a Role from the shield index
|
||||||
|
@ -38,7 +38,7 @@ public class RestGetRolesAction extends BaseRestHandler {
|
||||||
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
||||||
String[] roles = Strings.splitStringByCommaToArray(request.param("id"));
|
String[] roles = Strings.splitStringByCommaToArray(request.param("id"));
|
||||||
|
|
||||||
new ShieldClient(client).prepareGetRoles().roles(roles).execute(new RestBuilderListener<GetRolesResponse>(channel) {
|
new SecurityClient(client).prepareGetRoles().roles(roles).execute(new RestBuilderListener<GetRolesResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(GetRolesResponse getRolesResponse, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(GetRolesResponse getRolesResponse, XContentBuilder builder) throws Exception {
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.action.user.AddUserRequest;
|
import org.elasticsearch.shield.action.user.AddUserRequest;
|
||||||
import org.elasticsearch.shield.action.user.AddUserResponse;
|
import org.elasticsearch.shield.action.user.AddUserResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rest endpoint to add a User to the shield index
|
* Rest endpoint to add a User to the shield index
|
||||||
|
@ -40,7 +40,7 @@ public class RestAddUserAction extends BaseRestHandler {
|
||||||
addUserReq.username(request.param("username"));
|
addUserReq.username(request.param("username"));
|
||||||
addUserReq.source(request.content());
|
addUserReq.source(request.content());
|
||||||
|
|
||||||
new ShieldClient(client).addUser(addUserReq, new RestBuilderListener<AddUserResponse>(channel) {
|
new SecurityClient(client).addUser(addUserReq, new RestBuilderListener<AddUserResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(AddUserResponse addUserResponse, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(AddUserResponse addUserResponse, XContentBuilder builder) throws Exception {
|
||||||
return new BytesRestResponse(RestStatus.OK,
|
return new BytesRestResponse(RestStatus.OK,
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.action.user.DeleteUserRequest;
|
import org.elasticsearch.shield.action.user.DeleteUserRequest;
|
||||||
import org.elasticsearch.shield.action.user.DeleteUserResponse;
|
import org.elasticsearch.shield.action.user.DeleteUserResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rest action to delete a user from the shield index
|
* Rest action to delete a user from the shield index
|
||||||
|
@ -37,7 +37,7 @@ public class RestDeleteUserAction extends BaseRestHandler {
|
||||||
String user = request.param("username");
|
String user = request.param("username");
|
||||||
DeleteUserRequest delUserRequest = new DeleteUserRequest(user);
|
DeleteUserRequest delUserRequest = new DeleteUserRequest(user);
|
||||||
|
|
||||||
new ShieldClient(client).deleteUser(delUserRequest, new RestBuilderListener<DeleteUserResponse>(channel) {
|
new SecurityClient(client).deleteUser(delUserRequest, new RestBuilderListener<DeleteUserResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(DeleteUserResponse response, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(DeleteUserResponse response, XContentBuilder builder) throws Exception {
|
||||||
return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND,
|
return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND,
|
||||||
|
|
|
@ -21,7 +21,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||||
import org.elasticsearch.shield.User;
|
import org.elasticsearch.shield.User;
|
||||||
import org.elasticsearch.shield.action.user.GetUsersResponse;
|
import org.elasticsearch.shield.action.user.GetUsersResponse;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rest action to retrieve a user from the shield index
|
* Rest action to retrieve a user from the shield index
|
||||||
|
@ -39,7 +39,7 @@ public class RestGetUsersAction extends BaseRestHandler {
|
||||||
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
||||||
String[] users = Strings.splitStringByCommaToArray(request.param("username"));
|
String[] users = Strings.splitStringByCommaToArray(request.param("username"));
|
||||||
|
|
||||||
new ShieldClient(client).prepareGetUsers().users(users).execute(new RestBuilderListener<GetUsersResponse>(channel) {
|
new SecurityClient(client).prepareGetUsers().users(users).execute(new RestBuilderListener<GetUsersResponse>(channel) {
|
||||||
@Override
|
@Override
|
||||||
public RestResponse buildResponse(GetUsersResponse getUsersResponse, XContentBuilder builder) throws Exception {
|
public RestResponse buildResponse(GetUsersResponse getUsersResponse, XContentBuilder builder) throws Exception {
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
|
|
|
@ -22,7 +22,7 @@ public abstract class AbstractShieldModule extends AbstractModule {
|
||||||
public AbstractShieldModule(Settings settings) {
|
public AbstractShieldModule(Settings settings) {
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.clientMode = !"node".equals(settings.get(Client.CLIENT_TYPE_SETTING_S.getKey()));
|
this.clientMode = !"node".equals(settings.get(Client.CLIENT_TYPE_SETTING_S.getKey()));
|
||||||
this.shieldEnabled = ShieldPlugin.shieldEnabled(settings);
|
this.shieldEnabled = ShieldPlugin.enabled(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,7 +9,7 @@ SYNOPSIS
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
||||||
Generates the system key and stores in the system_key file. By default
|
Generates the system key and stores in the system_key file. By default
|
||||||
it will be stored in 'config/shield/.system_key' file. If the file location
|
it will be stored in 'config/xpack/system_key' file. If the file location
|
||||||
is customized in the elasticsearch.yml (under the 'shield.system_key.file'
|
is customized in the elasticsearch.yml (under the 'shield.system_key.file'
|
||||||
setting), the generated key will be stored in that custom location.
|
setting), the generated key will be stored in that custom location.
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
import org.elasticsearch.test.ShieldSettingsSource;
|
import org.elasticsearch.test.ShieldSettingsSource;
|
||||||
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ public class BulkUpdateTests extends ShieldIntegTestCase {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, randomBoolean())
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), randomBoolean())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
import org.elasticsearch.test.ShieldSettingsSource;
|
import org.elasticsearch.test.ShieldSettingsSource;
|
||||||
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
|
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
|
||||||
|
@ -140,11 +140,11 @@ public class ClearRealmsCacheTests extends ShieldIntegTestCase {
|
||||||
public abstract void executeRequest() throws Exception;
|
public abstract void executeRequest() throws Exception;
|
||||||
|
|
||||||
static void executeTransportRequest(ClearRealmCacheRequest request) throws Exception {
|
static void executeTransportRequest(ClearRealmCacheRequest request) throws Exception {
|
||||||
ShieldClient shieldClient = new ShieldClient(client());
|
SecurityClient securityClient = securityClient(client());
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
final AtomicReference<Throwable> error = new AtomicReference<>();
|
final AtomicReference<Throwable> error = new AtomicReference<>();
|
||||||
shieldClient.clearRealmCache(request, new ActionListener<ClearRealmCacheResponse>() {
|
securityClient.clearRealmCache(request, new ActionListener<ClearRealmCacheResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(ClearRealmCacheResponse response) {
|
public void onResponse(ClearRealmCacheResponse response) {
|
||||||
assertThat(response.getNodes().length, equalTo(internalCluster().getNodeNames().length));
|
assertThat(response.getNodes().length, equalTo(internalCluster().getNodeNames().length));
|
||||||
|
|
|
@ -21,7 +21,7 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||||
import org.elasticsearch.shield.authz.RoleDescriptor;
|
import org.elasticsearch.shield.authz.RoleDescriptor;
|
||||||
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
import org.elasticsearch.test.ShieldSettingsSource;
|
import org.elasticsearch.test.ShieldSettingsSource;
|
||||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||||
|
@ -57,7 +57,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||||
@Before
|
@Before
|
||||||
public void setupForTest() throws Exception {
|
public void setupForTest() throws Exception {
|
||||||
// Clear the realm cache for all realms since we use a SUITE scoped cluster
|
// Clear the realm cache for all realms since we use a SUITE scoped cluster
|
||||||
ShieldClient client = new ShieldClient(internalCluster().transportClient());
|
SecurityClient client = securityClient(internalCluster().transportClient());
|
||||||
client.prepareClearRealmCache().get();
|
client.prepareClearRealmCache().get();
|
||||||
|
|
||||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||||
|
@ -78,7 +78,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
// create roles
|
// create roles
|
||||||
for (String role : roles) {
|
for (String role : roles) {
|
||||||
c.prepareAddRole().name(role)
|
c.prepareAddRole().name(role)
|
||||||
|
@ -109,13 +109,13 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||||
|
|
||||||
public void testModifyingViaApiClearsCache() throws Exception {
|
public void testModifyingViaApiClearsCache() throws Exception {
|
||||||
Client client = internalCluster().transportClient();
|
Client client = internalCluster().transportClient();
|
||||||
ShieldClient shieldClient = new ShieldClient(client);
|
SecurityClient securityClient = securityClient(client);
|
||||||
|
|
||||||
int modifiedRolesCount = randomIntBetween(1, roles.length);
|
int modifiedRolesCount = randomIntBetween(1, roles.length);
|
||||||
List<String> toModify = randomSubsetOf(modifiedRolesCount, roles);
|
List<String> toModify = randomSubsetOf(modifiedRolesCount, roles);
|
||||||
logger.debug("--> modifying roles {} to have run_as", toModify);
|
logger.debug("--> modifying roles {} to have run_as", toModify);
|
||||||
for (String role : toModify) {
|
for (String role : toModify) {
|
||||||
AddRoleResponse response = shieldClient.prepareAddRole().name(role)
|
AddRoleResponse response = securityClient.prepareAddRole().name(role)
|
||||||
.cluster("none")
|
.cluster("none")
|
||||||
.addIndices(new String[] { "*" }, new String[] { "ALL" }, null, null)
|
.addIndices(new String[] { "*" }, new String[] { "ALL" }, null, null)
|
||||||
.runAs(role)
|
.runAs(role)
|
||||||
|
@ -124,7 +124,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||||
logger.debug("--> updated role [{}] with run_as", role);
|
logger.debug("--> updated role [{}] with run_as", role);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertRolesAreCorrect(shieldClient, toModify);
|
assertRolesAreCorrect(securityClient, toModify);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testModifyingDocumentsDirectly() throws Exception {
|
public void testModifyingDocumentsDirectly() throws Exception {
|
||||||
|
@ -144,7 +144,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||||
|
|
||||||
// in this test, the poller runs too frequently to check the cache still has roles without run as
|
// in this test, the poller runs too frequently to check the cache still has roles without run as
|
||||||
// clear the cache and we should definitely see the latest values!
|
// clear the cache and we should definitely see the latest values!
|
||||||
ShieldClient shieldClient = new ShieldClient(client);
|
SecurityClient securityClient = securityClient(client);
|
||||||
final boolean useHttp = randomBoolean();
|
final boolean useHttp = randomBoolean();
|
||||||
final boolean clearAll = randomBoolean();
|
final boolean clearAll = randomBoolean();
|
||||||
logger.debug("--> starting to clear roles. using http [{}] clearing all [{}]", useHttp, clearAll);
|
logger.debug("--> starting to clear roles. using http [{}] clearing all [{}]", useHttp, clearAll);
|
||||||
|
@ -163,18 +163,18 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||||
.execute();
|
.execute();
|
||||||
assertThat(response.getStatusCode(), is(RestStatus.OK.getStatus()));
|
assertThat(response.getStatusCode(), is(RestStatus.OK.getStatus()));
|
||||||
} else {
|
} else {
|
||||||
shieldClient.prepareClearRolesCache().roles(rolesToClear).get();
|
securityClient.prepareClearRolesCache().roles(rolesToClear).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertRolesAreCorrect(shieldClient, toModify);
|
assertRolesAreCorrect(securityClient, toModify);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDeletingRoleDocumentDirectly() throws Exception {
|
public void testDeletingRoleDocumentDirectly() throws Exception {
|
||||||
Client client = internalCluster().transportClient();
|
Client client = internalCluster().transportClient();
|
||||||
ShieldClient shieldClient = new ShieldClient(client);
|
SecurityClient securityClient = securityClient(client);
|
||||||
|
|
||||||
final String role = randomFrom(roles);
|
final String role = randomFrom(roles);
|
||||||
List<RoleDescriptor> foundRoles = shieldClient.prepareGetRoles().roles(role).get().roles();
|
List<RoleDescriptor> foundRoles = securityClient.prepareGetRoles().roles(role).get().roles();
|
||||||
assertThat(foundRoles.size(), is(1));
|
assertThat(foundRoles.size(), is(1));
|
||||||
logger.debug("--> deleting role [{}]", role);
|
logger.debug("--> deleting role [{}]", role);
|
||||||
DeleteResponse response = client.prepareDelete(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
|
DeleteResponse response = client.prepareDelete(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
|
||||||
|
@ -184,15 +184,15 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
|
||||||
assertBusy(new Runnable() {
|
assertBusy(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
assertThat(shieldClient.prepareGetRoles().roles(role).get().roles().isEmpty(), is(true));
|
assertThat(securityClient.prepareGetRoles().roles(role).get().roles().isEmpty(), is(true));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertRolesAreCorrect(ShieldClient shieldClient, List<String> toModify) {
|
private void assertRolesAreCorrect(SecurityClient securityClient, List<String> toModify) {
|
||||||
for (String role : roles) {
|
for (String role : roles) {
|
||||||
logger.debug("--> getting role [{}]", role);
|
logger.debug("--> getting role [{}]", role);
|
||||||
GetRolesResponse roleResponse = shieldClient.prepareGetRoles().roles(role).get();
|
GetRolesResponse roleResponse = securityClient.prepareGetRoles().roles(role).get();
|
||||||
assertThat(roleResponse.isExists(), is(true));
|
assertThat(roleResponse.isExists(), is(true));
|
||||||
final String[] runAs = roleResponse.roles().get(0).getRunAs();
|
final String[] runAs = roleResponse.roles().get(0).getRunAs();
|
||||||
if (toModify.contains(role)) {
|
if (toModify.contains(role)) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.shield.authc.support.Hasher;
|
import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ public class DocumentAndFieldLevelSecurityTests extends ShieldIntegTestCase {
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, true)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.shield.authc.support.Hasher;
|
import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -74,7 +75,7 @@ public class DocumentLevelSecurityRandomTests extends ShieldIntegTestCase {
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, true)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.shield.authc.support.Hasher;
|
import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, true)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.shield.authc.support.Hasher;
|
import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -111,7 +112,7 @@ public class FieldLevelSecurityRandomTests extends ShieldIntegTestCase {
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, true)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.test.ESIntegTestCase;
|
import org.elasticsearch.test.ESIntegTestCase;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -116,7 +117,7 @@ public class FieldLevelSecurityTests extends ShieldIntegTestCase {
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, true)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,11 @@ package org.elasticsearch.integration;
|
||||||
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
||||||
import org.elasticsearch.common.network.NetworkModule;
|
import org.elasticsearch.common.network.NetworkModule;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.node.Node;
|
import org.elasticsearch.test.ESIntegTestCase;
|
||||||
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -21,6 +22,7 @@ import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
//test is just too slow, please fix it to not be sleep-based
|
//test is just too slow, please fix it to not be sleep-based
|
||||||
@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007")
|
@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007")
|
||||||
|
@ESIntegTestCase.ClusterScope(randomDynamicTemplates = false)
|
||||||
public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
||||||
|
|
||||||
private String jsonDoc = "{ \"name\" : \"elasticsearch\"}";
|
private String jsonDoc = "{ \"name\" : \"elasticsearch\"}";
|
||||||
|
@ -94,8 +96,7 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
||||||
"u11:" + USERS_PASSWD_HASHED + "\n" +
|
"u11:" + USERS_PASSWD_HASHED + "\n" +
|
||||||
"u12:" + USERS_PASSWD_HASHED + "\n" +
|
"u12:" + USERS_PASSWD_HASHED + "\n" +
|
||||||
"u13:" + USERS_PASSWD_HASHED + "\n" +
|
"u13:" + USERS_PASSWD_HASHED + "\n" +
|
||||||
"u14:" + USERS_PASSWD_HASHED + "\n" +
|
"u14:" + USERS_PASSWD_HASHED + "\n";
|
||||||
"u15:" + USERS_PASSWD_HASHED + "\n";
|
|
||||||
|
|
||||||
public static final String USERS_ROLES =
|
public static final String USERS_ROLES =
|
||||||
"all_indices_role:admin,u8\n" +
|
"all_indices_role:admin,u8\n" +
|
||||||
|
@ -120,7 +121,6 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
||||||
protected Settings nodeSettings(int nodeOrdinal) {
|
protected Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
|
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||||
.put("action.disable_shutdown", true)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +139,17 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
||||||
return super.configUsersRoles() + USERS_ROLES;
|
return super.configUsersRoles() + USERS_ROLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we reduce the number of shards and replicas to help speed up this test since that is not the focus of this test
|
||||||
|
@Override
|
||||||
|
public int maximumNumberOfReplicas() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int maximumNumberOfShards() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void insertBaseDocumentsAsAdmin() throws Exception {
|
public void insertBaseDocumentsAsAdmin() throws Exception {
|
||||||
// indices: a,b,c,abc
|
// indices: a,b,c,abc
|
||||||
|
@ -296,24 +307,13 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
||||||
assertUserIsDenied("u14", "all", "c");
|
assertUserIsDenied("u14", "all", "c");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUserU15() throws Exception {
|
|
||||||
//u15 has access to manage and search a, so that adding warmer templates work
|
|
||||||
assertUserIsAllowed("u15", "manage", "a");
|
|
||||||
assertUserIsAllowed("u15", "search", "a");
|
|
||||||
assertAccessIsAllowed("u15", "PUT", "/a/_warmer/w1", "{ \"query\" : { \"match_all\" : {} } }");
|
|
||||||
assertAccessIsAllowed("u15", "DELETE", "/a/_warmer/w1");
|
|
||||||
|
|
||||||
assertUserIsDenied("u15", "all", "b");
|
|
||||||
assertUserIsDenied("u15", "all", "c");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testThatUnknownUserIsRejectedProperly() throws Exception {
|
public void testThatUnknownUserIsRejectedProperly() throws Exception {
|
||||||
HttpResponse response = executeRequest("idonotexist", "GET", "/", null, new HashMap<>());
|
HttpResponse response = executeRequest("idonotexist", "GET", "/", null, new HashMap<>());
|
||||||
assertThat(response.getStatusCode(), is(401));
|
assertThat(response.getStatusCode(), is(401));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertUserExecutes(String user, String action, String index, boolean userIsAllowed) throws Exception {
|
private void assertUserExecutes(String user, String action, String index, boolean userIsAllowed) throws Exception {
|
||||||
Map<String, String> refreshParams = singletonMap("refresh", "true");
|
Map<String, String> refreshParams = Collections.emptyMap();//singletonMap("refresh", "true");
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "all" :
|
case "all" :
|
||||||
|
@ -353,11 +353,6 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
||||||
assertAccessIsAllowed("admin", "PUT", "/" + index + "/foo/1", jsonDoc, refreshParams);
|
assertAccessIsAllowed("admin", "PUT", "/" + index + "/foo/1", jsonDoc, refreshParams);
|
||||||
client().admin().cluster().prepareHealth(index).setWaitForGreenStatus().get();
|
client().admin().cluster().prepareHealth(index).setWaitForGreenStatus().get();
|
||||||
assertAccessIsAllowed(user, "GET", "/" + index + "/_mapping/foo/field/name");
|
assertAccessIsAllowed(user, "GET", "/" + index + "/_mapping/foo/field/name");
|
||||||
// putting warmers only works if the user is allowed to search as well, as the query gets validated, added an own
|
|
||||||
// test for this
|
|
||||||
assertAccessIsAllowed("admin", "PUT", "/" + index + "/_warmer/w1", "{ \"query\" : { \"match_all\" : {} } }");
|
|
||||||
assertAccessIsAllowed(user, "GET", "/" + index + "/_warmer/w1");
|
|
||||||
assertAccessIsAllowed(user, "DELETE", "/" + index + "/_warmer/w1");
|
|
||||||
assertAccessIsAllowed(user, "GET", "/" + index + "/_settings");
|
assertAccessIsAllowed(user, "GET", "/" + index + "/_settings");
|
||||||
} else {
|
} else {
|
||||||
assertAccessIsDenied(user, "DELETE", "/" + index);
|
assertAccessIsDenied(user, "DELETE", "/" + index);
|
||||||
|
@ -372,9 +367,6 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
|
||||||
assertAccessIsDenied(user, "POST", "/" + index + "/_open");
|
assertAccessIsDenied(user, "POST", "/" + index + "/_open");
|
||||||
assertAccessIsDenied(user, "POST", "/" + index + "/_cache/clear");
|
assertAccessIsDenied(user, "POST", "/" + index + "/_cache/clear");
|
||||||
assertAccessIsDenied(user, "GET", "/" + index + "/_mapping/foo/field/name");
|
assertAccessIsDenied(user, "GET", "/" + index + "/_mapping/foo/field/name");
|
||||||
assertAccessIsDenied(user, "PUT", "/" + index + "/_warmer/w1", "{ \"query\" : { \"match_all\" : {} } }");
|
|
||||||
assertAccessIsDenied(user, "GET", "/" + index + "/_warmer/w1");
|
|
||||||
assertAccessIsDenied(user, "DELETE", "/" + index + "/_warmer/w1");
|
|
||||||
assertAccessIsDenied(user, "GET", "/" + index + "/_settings");
|
assertAccessIsDenied(user, "GET", "/" + index + "/_settings");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.shield.authc.support.Hasher;
|
import org.elasticsearch.shield.authc.support.Hasher;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ public class IndicesPermissionsWithAliasesWildcardsAndRegexsTests extends Shield
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, true)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.integration;
|
package org.elasticsearch.integration;
|
||||||
|
|
||||||
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
|
||||||
import org.elasticsearch.ElasticsearchSecurityException;
|
import org.elasticsearch.ElasticsearchSecurityException;
|
||||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
||||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||||
|
@ -33,8 +32,6 @@ import static org.hamcrest.Matchers.hasSize;
|
||||||
* actions that are normally categorized as index actions as cluster actions - for example,
|
* actions that are normally categorized as index actions as cluster actions - for example,
|
||||||
* index template actions.
|
* index template actions.
|
||||||
*/
|
*/
|
||||||
//test is just too slow, please fix it to not be sleep-based
|
|
||||||
@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007")
|
|
||||||
public class PermissionPrecedenceTests extends ShieldIntegTestCase {
|
public class PermissionPrecedenceTests extends ShieldIntegTestCase {
|
||||||
protected static final String USERS_PASSWD_HASHED = new String(Hasher.BCRYPT.hash(new SecuredString("test123".toCharArray())));
|
protected static final String USERS_PASSWD_HASHED = new String(Hasher.BCRYPT.hash(new SecuredString("test123".toCharArray())));
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class ShieldPluginEnabledDisabledTests extends ShieldIntegTestCase {
|
||||||
logger.info("******* shield is " + (enabled ? "enabled" : "disabled"));
|
logger.info("******* shield is " + (enabled ? "enabled" : "disabled"));
|
||||||
return Settings.settingsBuilder()
|
return Settings.settingsBuilder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.ENABLED_SETTING_NAME, enabled)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME), enabled)
|
||||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ public class ShieldPluginEnabledDisabledTests extends ShieldIntegTestCase {
|
||||||
protected Settings transportClientSettings() {
|
protected Settings transportClientSettings() {
|
||||||
return Settings.settingsBuilder()
|
return Settings.settingsBuilder()
|
||||||
.put(super.transportClientSettings())
|
.put(super.transportClientSettings())
|
||||||
.put(ShieldPlugin.ENABLED_SETTING_NAME, enabled)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME), enabled)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.shield;
|
||||||
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
@ -14,8 +15,9 @@ import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
import static org.hamcrest.Matchers.arrayContaining;
|
import static org.hamcrest.Matchers.arrayContaining;
|
||||||
|
|
||||||
public class ShieldPluginSettingsTests extends ESTestCase {
|
public class ShieldPluginSettingsTests extends ESTestCase {
|
||||||
private static final String TRIBE_T1_SHIELD_ENABLED = "tribe.t1." + ShieldPlugin.ENABLED_SETTING_NAME;
|
|
||||||
private static final String TRIBE_T2_SHIELD_ENABLED = "tribe.t2." + ShieldPlugin.ENABLED_SETTING_NAME;
|
private static final String TRIBE_T1_SHIELD_ENABLED = "tribe.t1." + XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME);
|
||||||
|
private static final String TRIBE_T2_SHIELD_ENABLED = "tribe.t2." + XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME);
|
||||||
|
|
||||||
public void testShieldIsMandatoryOnTribes() {
|
public void testShieldIsMandatoryOnTribes() {
|
||||||
Settings settings = Settings.builder().put("tribe.t1.cluster.name", "non_existing")
|
Settings settings = Settings.builder().put("tribe.t1.cluster.name", "non_existing")
|
||||||
|
@ -26,8 +28,8 @@ public class ShieldPluginSettingsTests extends ESTestCase {
|
||||||
Settings additionalSettings = shieldPlugin.additionalSettings();
|
Settings additionalSettings = shieldPlugin.additionalSettings();
|
||||||
|
|
||||||
|
|
||||||
assertThat(additionalSettings.getAsArray("tribe.t1.plugin.mandatory", null), arrayContaining(ShieldPlugin.NAME));
|
assertThat(additionalSettings.getAsArray("tribe.t1.plugin.mandatory", null), arrayContaining(XPackPlugin.NAME));
|
||||||
assertThat(additionalSettings.getAsArray("tribe.t2.plugin.mandatory", null), arrayContaining(ShieldPlugin.NAME));
|
assertThat(additionalSettings.getAsArray("tribe.t2.plugin.mandatory", null), arrayContaining(XPackPlugin.NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAdditionalMandatoryPluginsOnTribes() {
|
public void testAdditionalMandatoryPluginsOnTribes() {
|
||||||
|
@ -41,14 +43,14 @@ public class ShieldPluginSettingsTests extends ESTestCase {
|
||||||
Settings.builder().put(settings).put(shieldPlugin.additionalSettings()).build();
|
Settings.builder().put(settings).put(shieldPlugin.additionalSettings()).build();
|
||||||
fail("shield cannot change the value of a setting that is already defined, so a exception should be thrown");
|
fail("shield cannot change the value of a setting that is already defined, so a exception should be thrown");
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
assertThat(e.getMessage(), containsString("shield"));
|
assertThat(e.getMessage(), containsString(XPackPlugin.NAME));
|
||||||
assertThat(e.getMessage(), containsString("plugin.mandatory"));
|
assertThat(e.getMessage(), containsString("plugin.mandatory"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMandatoryPluginsOnTribesShieldAlreadyMandatory() {
|
public void testMandatoryPluginsOnTribesShieldAlreadyMandatory() {
|
||||||
Settings settings = Settings.builder().put("tribe.t1.cluster.name", "non_existing")
|
Settings settings = Settings.builder().put("tribe.t1.cluster.name", "non_existing")
|
||||||
.putArray("tribe.t1.plugin.mandatory", "test_plugin", ShieldPlugin.NAME).build();
|
.putArray("tribe.t1.plugin.mandatory", "test_plugin", XPackPlugin.NAME).build();
|
||||||
|
|
||||||
ShieldPlugin shieldPlugin = new ShieldPlugin(settings);
|
ShieldPlugin shieldPlugin = new ShieldPlugin(settings);
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ public class ShieldPluginSettingsTests extends ESTestCase {
|
||||||
assertThat(finalMandatoryPlugins, notNullValue());
|
assertThat(finalMandatoryPlugins, notNullValue());
|
||||||
assertThat(finalMandatoryPlugins.length, equalTo(2));
|
assertThat(finalMandatoryPlugins.length, equalTo(2));
|
||||||
assertThat(finalMandatoryPlugins[0], equalTo("test_plugin"));
|
assertThat(finalMandatoryPlugins[0], equalTo("test_plugin"));
|
||||||
assertThat(finalMandatoryPlugins[1], equalTo(ShieldPlugin.NAME));
|
assertThat(finalMandatoryPlugins[1], equalTo(XPackPlugin.NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testShieldIsEnabledByDefaultOnTribes() {
|
public void testShieldIsEnabledByDefaultOnTribes() {
|
||||||
|
@ -93,7 +95,7 @@ public class ShieldPluginSettingsTests extends ESTestCase {
|
||||||
Settings settings = Settings.builder().put("tribe.t1.cluster.name", "non_existing")
|
Settings settings = Settings.builder().put("tribe.t1.cluster.name", "non_existing")
|
||||||
.put(TRIBE_T1_SHIELD_ENABLED, false)
|
.put(TRIBE_T1_SHIELD_ENABLED, false)
|
||||||
.put("tribe.t2.cluster.name", "non_existing")
|
.put("tribe.t2.cluster.name", "non_existing")
|
||||||
.putArray("tribe.t1.plugin.mandatory", "test_plugin", ShieldPlugin.NAME).build();
|
.putArray("tribe.t1.plugin.mandatory", "test_plugin", XPackPlugin.NAME).build();
|
||||||
|
|
||||||
ShieldPlugin shieldPlugin = new ShieldPlugin(settings);
|
ShieldPlugin shieldPlugin = new ShieldPlugin(settings);
|
||||||
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.shield.audit.index;
|
|
||||||
|
|
||||||
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
|
||||||
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
|
|
||||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.shield.audit.logfile.LoggingAuditTrail;
|
|
||||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
|
||||||
import org.elasticsearch.test.ESIntegTestCase.Scope;
|
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.joda.time.DateTimeZone;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
|
|
||||||
//test is just too slow, please fix it to not be sleep-based
|
|
||||||
@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007")
|
|
||||||
@ClusterScope(scope = Scope.TEST, randomDynamicTemplates = false)
|
|
||||||
public class IndexAuditTrailEnabledTests extends ShieldIntegTestCase {
|
|
||||||
IndexNameResolver.Rollover rollover = randomFrom(IndexNameResolver.Rollover.values());
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Set<String> excludeTemplates() {
|
|
||||||
return Collections.singleton(IndexAuditTrail.INDEX_TEMPLATE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Settings nodeSettings(int nodeOrdinal) {
|
|
||||||
Settings.Builder builder = Settings.builder()
|
|
||||||
.put(super.nodeSettings(nodeOrdinal));
|
|
||||||
builder.put("shield.audit.enabled", true);
|
|
||||||
if (randomBoolean()) {
|
|
||||||
builder.putArray("shield.audit.outputs", LoggingAuditTrail.NAME, IndexAuditTrail.NAME);
|
|
||||||
} else {
|
|
||||||
builder.putArray("shield.audit.outputs", IndexAuditTrail.NAME);
|
|
||||||
}
|
|
||||||
builder.put(IndexAuditTrail.ROLLOVER_SETTING, rollover);
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeIndexDeletion() {
|
|
||||||
// For this test, this is a NO-OP because the index audit trail will continue to capture events and index after
|
|
||||||
// the tests have completed. The default implementation of this method expects that nothing is performing operations
|
|
||||||
// after the test has completed
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAuditTrailIndexAndTemplateExists() throws Exception {
|
|
||||||
awaitIndexTemplateCreation();
|
|
||||||
|
|
||||||
// Wait for the index to be created since we have our own startup
|
|
||||||
awaitAuditDocumentCreation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAuditTrailTemplateIsRecreatedAfterDelete() throws Exception {
|
|
||||||
// this is already "tested" by the test framework since we wipe the templates before and after, but lets be explicit about the
|
|
||||||
// behavior
|
|
||||||
awaitIndexTemplateCreation();
|
|
||||||
|
|
||||||
// delete the template
|
|
||||||
DeleteIndexTemplateResponse deleteResponse = client().admin().indices()
|
|
||||||
.prepareDeleteTemplate(IndexAuditTrail.INDEX_TEMPLATE_NAME).execute().actionGet();
|
|
||||||
assertThat(deleteResponse.isAcknowledged(), is(true));
|
|
||||||
awaitIndexTemplateCreation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void awaitAuditDocumentCreation() throws Exception {
|
|
||||||
final String indexName = IndexNameResolver.resolve(IndexAuditTrail.INDEX_NAME_PREFIX, DateTime.now(DateTimeZone.UTC), rollover);
|
|
||||||
boolean success = awaitBusy(() -> {
|
|
||||||
try {
|
|
||||||
SearchResponse searchResponse = client().prepareSearch(indexName).setSize(0).setTerminateAfter(1).execute().actionGet();
|
|
||||||
return searchResponse.getHits().totalHits() > 0;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
assertThat("no audit document exists!", success, is(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
void awaitIndexTemplateCreation() throws InterruptedException {
|
|
||||||
boolean found = awaitBusy(() -> {
|
|
||||||
GetIndexTemplatesResponse response = client().admin().indices()
|
|
||||||
.prepareGetTemplates(IndexAuditTrail.INDEX_TEMPLATE_NAME).execute().actionGet();
|
|
||||||
if (response.getIndexTemplates().size() > 0) {
|
|
||||||
for (IndexTemplateMetaData indexTemplateMetaData : response.getIndexTemplates()) {
|
|
||||||
if (IndexAuditTrail.INDEX_TEMPLATE_NAME.equals(indexTemplateMetaData.name())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
assertThat("index template [" + IndexAuditTrail.INDEX_TEMPLATE_NAME + "] was not created", found, is(true));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -42,6 +42,7 @@ import org.elasticsearch.transport.Transport;
|
||||||
import org.elasticsearch.transport.TransportInfo;
|
import org.elasticsearch.transport.TransportInfo;
|
||||||
import org.elasticsearch.transport.TransportMessage;
|
import org.elasticsearch.transport.TransportMessage;
|
||||||
import org.elasticsearch.transport.TransportRequest;
|
import org.elasticsearch.transport.TransportRequest;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
import org.joda.time.format.ISODateTimeFormat;
|
import org.joda.time.format.ISODateTimeFormat;
|
||||||
|
@ -166,18 +167,21 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase {
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
Settings.Builder builder = Settings.builder()
|
Settings.Builder builder = Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(ShieldPlugin.ENABLED_SETTING_NAME, useShield);
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME), useShield);
|
||||||
// For tests we forcefully configure Shield's custom query cache because the test framework randomizes the query
|
|
||||||
// cache impl,
|
// For tests we forcefully configure Shield's custom query cache because the test framework
|
||||||
// but if shield is disabled then we don't need to forcefully set the query cache
|
// randomizes the query cache impl but if shield is disabled then we don't need to forcefully
|
||||||
|
// set the query cache
|
||||||
if (useShield == false) {
|
if (useShield == false) {
|
||||||
builder.remove(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey());
|
builder.remove(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cluster2 = new InternalTestCluster("network", randomLong(), createTempDir(), numNodes, numNodes, cluster2Name,
|
cluster2 = new InternalTestCluster("network", randomLong(), createTempDir(), numNodes, numNodes, cluster2Name,
|
||||||
cluster2SettingsSource, 0, false, SECOND_CLUSTER_NODE_PREFIX, getMockPlugins(), Function.identity());
|
cluster2SettingsSource, 0, false, SECOND_CLUSTER_NODE_PREFIX, getMockPlugins(),
|
||||||
|
useShield ? getClientWrapper() : Function.identity());
|
||||||
cluster2.beforeTest(getRandom(), 0.5);
|
cluster2.beforeTest(getRandom(), 0.5);
|
||||||
remoteClient = cluster2.client();
|
remoteClient = cluster2.client();
|
||||||
|
|
||||||
|
@ -187,7 +191,7 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase {
|
||||||
|
|
||||||
Settings.Builder builder = Settings.builder()
|
Settings.Builder builder = Settings.builder()
|
||||||
.put(settings)
|
.put(settings)
|
||||||
.put(ShieldPlugin.ENABLED_SETTING_NAME, useShield)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME), useShield)
|
||||||
.put(remoteSettings(NetworkAddress.formatAddress(inet.address().getAddress()), inet.address().getPort(), cluster2Name))
|
.put(remoteSettings(NetworkAddress.formatAddress(inet.address().getAddress()), inet.address().getPort(), cluster2Name))
|
||||||
.put("shield.audit.index.client.shield.user", DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD);
|
.put("shield.audit.index.client.shield.user", DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
import org.elasticsearch.shield.authz.RoleDescriptor;
|
import org.elasticsearch.shield.authz.RoleDescriptor;
|
||||||
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
import org.elasticsearch.shield.authz.esnative.ESNativeRolesStore;
|
||||||
import org.elasticsearch.shield.authz.permission.Role;
|
import org.elasticsearch.shield.authz.permission.Role;
|
||||||
import org.elasticsearch.shield.client.ShieldClient;
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
import org.elasticsearch.test.ShieldSettingsSource;
|
import org.elasticsearch.test.ShieldSettingsSource;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
@ -43,7 +43,7 @@ import static org.hamcrest.Matchers.isOneOf;
|
||||||
public class ESNativeTests extends ShieldIntegTestCase {
|
public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
|
|
||||||
public void testDeletingNonexistingUserAndRole() throws Exception {
|
public void testDeletingNonexistingUserAndRole() throws Exception {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
DeleteUserResponse resp = c.prepareDeleteUser().user("joe").get();
|
DeleteUserResponse resp = c.prepareDeleteUser().user("joe").get();
|
||||||
assertFalse("user shouldn't be found", resp.found());
|
assertFalse("user shouldn't be found", resp.found());
|
||||||
DeleteRoleResponse resp2 = c.prepareDeleteRole().role("role").get();
|
DeleteRoleResponse resp2 = c.prepareDeleteRole().role("role").get();
|
||||||
|
@ -51,7 +51,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGettingUserThatDoesntExist() throws Exception {
|
public void testGettingUserThatDoesntExist() throws Exception {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
GetUsersResponse resp = c.prepareGetUsers().users("joe").get();
|
GetUsersResponse resp = c.prepareGetUsers().users("joe").get();
|
||||||
assertFalse("user should not exist", resp.isExists());
|
assertFalse("user should not exist", resp.isExists());
|
||||||
GetRolesResponse resp2 = c.prepareGetRoles().roles("role").get();
|
GetRolesResponse resp2 = c.prepareGetRoles().roles("role").get();
|
||||||
|
@ -59,7 +59,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAddAndGetUser() throws Exception {
|
public void testAddAndGetUser() throws Exception {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
logger.error("--> creating user");
|
logger.error("--> creating user");
|
||||||
c.prepareAddUser()
|
c.prepareAddUser()
|
||||||
.username("joe")
|
.username("joe")
|
||||||
|
@ -117,7 +117,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAddAndGetRole() throws Exception {
|
public void testAddAndGetRole() throws Exception {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
logger.error("--> creating role");
|
logger.error("--> creating role");
|
||||||
c.prepareAddRole()
|
c.prepareAddRole()
|
||||||
.name("test_role")
|
.name("test_role")
|
||||||
|
@ -171,7 +171,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAddUserAndRoleThenAuth() throws Exception {
|
public void testAddUserAndRoleThenAuth() throws Exception {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
logger.error("--> creating role");
|
logger.error("--> creating role");
|
||||||
c.prepareAddRole()
|
c.prepareAddRole()
|
||||||
.name("test_role")
|
.name("test_role")
|
||||||
|
@ -204,7 +204,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpdatingUserAndAuthentication() throws Exception {
|
public void testUpdatingUserAndAuthentication() throws Exception {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
logger.error("--> creating user");
|
logger.error("--> creating user");
|
||||||
c.prepareAddUser()
|
c.prepareAddUser()
|
||||||
.username("joe")
|
.username("joe")
|
||||||
|
@ -248,7 +248,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateDeleteAuthenticate() {
|
public void testCreateDeleteAuthenticate() {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
logger.error("--> creating user");
|
logger.error("--> creating user");
|
||||||
c.prepareAddUser()
|
c.prepareAddUser()
|
||||||
.username("joe")
|
.username("joe")
|
||||||
|
@ -285,7 +285,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
|
|
||||||
public void testCreateAndUpdateRole() {
|
public void testCreateAndUpdateRole() {
|
||||||
final boolean authenticate = randomBoolean();
|
final boolean authenticate = randomBoolean();
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
logger.error("--> creating role");
|
logger.error("--> creating role");
|
||||||
c.prepareAddRole()
|
c.prepareAddRole()
|
||||||
.name("test_role")
|
.name("test_role")
|
||||||
|
@ -340,7 +340,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticateWithDeletedRole() {
|
public void testAuthenticateWithDeletedRole() {
|
||||||
ShieldClient c = new ShieldClient(client());
|
SecurityClient c = securityClient();
|
||||||
logger.error("--> creating role");
|
logger.error("--> creating role");
|
||||||
c.prepareAddRole()
|
c.prepareAddRole()
|
||||||
.name("test_role")
|
.name("test_role")
|
||||||
|
@ -373,7 +373,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
||||||
@Before
|
@Before
|
||||||
public void ensureStoresStarted() throws Exception {
|
public void ensureStoresStarted() throws Exception {
|
||||||
// Clear the realm cache for all realms since we use a SUITE scoped cluster
|
// Clear the realm cache for all realms since we use a SUITE scoped cluster
|
||||||
ShieldClient client = new ShieldClient(client());
|
SecurityClient client = securityClient();
|
||||||
client.prepareClearRealmCache().get();
|
client.prepareClearRealmCache().get();
|
||||||
|
|
||||||
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
for (ESNativeUsersStore store : internalCluster().getInstances(ESNativeUsersStore.class)) {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.shield.authc.support;
|
package org.elasticsearch.shield.authc.support;
|
||||||
|
|
||||||
import org.apache.lucene.util.LuceneTestCase.BadApple;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.shield.User;
|
import org.elasticsearch.shield.User;
|
||||||
|
@ -25,8 +24,6 @@ import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.hamcrest.Matchers.sameInstance;
|
import static org.hamcrest.Matchers.sameInstance;
|
||||||
|
|
||||||
//test is just too slow, please fix it to not be sleep-based
|
|
||||||
@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007")
|
|
||||||
public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
||||||
private Settings globalSettings;
|
private Settings globalSettings;
|
||||||
|
|
||||||
|
@ -206,7 +203,9 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
||||||
};
|
};
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
final int numberOfThreads = randomIntBetween(8, 24);
|
final int numberOfProcessors = Runtime.getRuntime().availableProcessors();
|
||||||
|
final int numberOfThreads = scaledRandomIntBetween((numberOfProcessors + 1) / 2, numberOfProcessors * 3);
|
||||||
|
final int numberOfIterations = scaledRandomIntBetween(20, 100);
|
||||||
List<Thread> threads = new ArrayList<>();
|
List<Thread> threads = new ArrayList<>();
|
||||||
for (int i = 0; i < numberOfThreads; i++) {
|
for (int i = 0; i < numberOfThreads; i++) {
|
||||||
final boolean invalidPassword = randomBoolean();
|
final boolean invalidPassword = randomBoolean();
|
||||||
|
@ -215,9 +214,9 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
latch.await();
|
latch.await();
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < numberOfIterations; i++) {
|
||||||
User user = realm.authenticate(
|
UsernamePasswordToken token = new UsernamePasswordToken(username, invalidPassword ? randomPassword : password);
|
||||||
new UsernamePasswordToken(username, invalidPassword ? randomPassword : password));
|
User user = realm.authenticate(token);
|
||||||
if (invalidPassword && user != null) {
|
if (invalidPassword && user != null) {
|
||||||
throw new RuntimeException("invalid password led to an authenticated user: " + user.toString());
|
throw new RuntimeException("invalid password led to an authenticated user: " + user.toString());
|
||||||
} else if (invalidPassword == false && user == null) {
|
} else if (invalidPassword == false && user == null) {
|
||||||
|
|
|
@ -245,7 +245,7 @@ public class PrivilegeTests extends ESTestCase {
|
||||||
assertThat(predicate.test("whatever"), is(false));
|
assertThat(predicate.test("whatever"), is(false));
|
||||||
assertThat(predicate.test("cluster:admin/reroute"), is(true));
|
assertThat(predicate.test("cluster:admin/reroute"), is(true));
|
||||||
assertThat(predicate.test("cluster:admin/whatever"), is(false));
|
assertThat(predicate.test("cluster:admin/whatever"), is(false));
|
||||||
assertThat(predicate.test("indices:admin/mapping/put"), is(true));
|
assertThat(predicate.test("indices:admin/mapping/put"), is(false));
|
||||||
assertThat(predicate.test("indices:admin/mapping/whatever"), is(false));
|
assertThat(predicate.test("indices:admin/mapping/whatever"), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.elasticsearch.shield.authz.privilege.IndexPrivilege;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
import org.elasticsearch.threadpool.ThreadPool;
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -52,8 +53,9 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
|
|
||||||
public void testParseFile() throws Exception {
|
public void testParseFile() throws Exception {
|
||||||
Path path = getDataPath("roles.yml");
|
Path path = getDataPath("roles.yml");
|
||||||
Map<String, Role> roles = FileRolesStore.parseFile(path, logger,
|
Map<String, Role> roles = FileRolesStore.parseFile(path, logger, Settings.builder()
|
||||||
Settings.builder().put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, true).build());
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), true)
|
||||||
|
.build());
|
||||||
assertThat(roles, notNullValue());
|
assertThat(roles, notNullValue());
|
||||||
assertThat(roles.size(), is(10));
|
assertThat(roles.size(), is(10));
|
||||||
|
|
||||||
|
@ -208,8 +210,9 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
public void testParseFileWithFLSAndDLSDisabled() throws Exception {
|
public void testParseFileWithFLSAndDLSDisabled() throws Exception {
|
||||||
Path path = getDataPath("roles.yml");
|
Path path = getDataPath("roles.yml");
|
||||||
CapturingLogger logger = new CapturingLogger(CapturingLogger.Level.ERROR);
|
CapturingLogger logger = new CapturingLogger(CapturingLogger.Level.ERROR);
|
||||||
Map<String, Role> roles = FileRolesStore.parseFile(path,
|
Map<String, Role> roles = FileRolesStore.parseFile(path, logger, Settings.builder()
|
||||||
logger, Settings.builder().put(ShieldPlugin.DLS_FLS_ENABLED_SETTING, false).build());
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.DLS_FLS_FEATURE), false)
|
||||||
|
.build());
|
||||||
assertThat(roles, notNullValue());
|
assertThat(roles, notNullValue());
|
||||||
assertThat(roles.size(), is(7));
|
assertThat(roles.size(), is(7));
|
||||||
assertThat(roles.get("role_fields"), nullValue());
|
assertThat(roles.get("role_fields"), nullValue());
|
||||||
|
|
|
@ -251,17 +251,17 @@ public class ClientSSLServiceTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/2")
|
|
||||||
public void testThatSSLSocketFactoryHasProperCiphersAndProtocols() throws Exception {
|
public void testThatSSLSocketFactoryHasProperCiphersAndProtocols() throws Exception {
|
||||||
ClientSSLService sslService = createClientSSLService(settingsBuilder()
|
ClientSSLService sslService = createClientSSLService(settingsBuilder()
|
||||||
.put("shield.ssl.keystore.path", testclientStore)
|
.put("shield.ssl.keystore.path", testclientStore)
|
||||||
.put("shield.ssl.keystore.password", "testclient")
|
.put("shield.ssl.keystore.password", "testclient")
|
||||||
.build());
|
.build());
|
||||||
SSLSocketFactory factory = sslService.sslSocketFactory();
|
SSLSocketFactory factory = sslService.sslSocketFactory();
|
||||||
assertThat(factory.getDefaultCipherSuites(), is(sslService.ciphers()));
|
final String[] ciphers = sslService.supportedCiphers(factory.getSupportedCipherSuites(), sslService.ciphers());
|
||||||
|
assertThat(factory.getDefaultCipherSuites(), is(ciphers));
|
||||||
|
|
||||||
try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
|
try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
|
||||||
assertThat(socket.getEnabledCipherSuites(), is(sslService.ciphers()));
|
assertThat(socket.getEnabledCipherSuites(), is(ciphers));
|
||||||
assertThat(socket.getEnabledProtocols(), is(sslService.supportedProtocols()));
|
assertThat(socket.getEnabledProtocols(), is(sslService.supportedProtocols()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.hamcrest.Matchers.sameInstance;
|
import static org.hamcrest.Matchers.sameInstance;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
public class ServerSSLServiceTests extends ESTestCase {
|
public class ServerSSLServiceTests extends ESTestCase {
|
||||||
Path testnodeStore;
|
Path testnodeStore;
|
||||||
|
@ -223,17 +222,17 @@ public class ServerSSLServiceTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/2")
|
|
||||||
public void testThatSSLSocketFactoryHasProperCiphersAndProtocols() throws Exception {
|
public void testThatSSLSocketFactoryHasProperCiphersAndProtocols() throws Exception {
|
||||||
ServerSSLService sslService = new ServerSSLService(settingsBuilder()
|
ServerSSLService sslService = new ServerSSLService(settingsBuilder()
|
||||||
.put("shield.ssl.keystore.path", testnodeStore)
|
.put("shield.ssl.keystore.path", testnodeStore)
|
||||||
.put("shield.ssl.keystore.password", "testnode")
|
.put("shield.ssl.keystore.password", "testnode")
|
||||||
.build(), env);
|
.build(), env);
|
||||||
SSLSocketFactory factory = sslService.sslSocketFactory();
|
SSLSocketFactory factory = sslService.sslSocketFactory();
|
||||||
assertThat(factory.getDefaultCipherSuites(), is(sslService.ciphers()));
|
final String[] ciphers = sslService.supportedCiphers(factory.getSupportedCipherSuites(), sslService.ciphers());
|
||||||
|
assertThat(factory.getDefaultCipherSuites(), is(ciphers));
|
||||||
|
|
||||||
try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
|
try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
|
||||||
assertThat(socket.getEnabledCipherSuites(), is(sslService.ciphers()));
|
assertThat(socket.getEnabledCipherSuites(), is(ciphers));
|
||||||
assertThat(socket.getEnabledProtocols(), is(sslService.supportedProtocols()));
|
assertThat(socket.getEnabledProtocols(), is(sslService.supportedProtocols()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,11 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
import org.elasticsearch.shield.InternalClient;
|
import org.elasticsearch.shield.InternalClient;
|
||||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode;
|
import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode;
|
||||||
import org.elasticsearch.test.transport.AssertingLocalTransport;
|
import org.elasticsearch.test.transport.AssertingLocalTransport;
|
||||||
import org.elasticsearch.test.transport.MockTransportService;
|
import org.elasticsearch.test.transport.MockTransportService;
|
||||||
|
import org.elasticsearch.xpack.XPackClient;
|
||||||
import org.elasticsearch.xpack.XPackPlugin;
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -267,6 +269,7 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CustomShieldSettingsSource extends ShieldSettingsSource {
|
private class CustomShieldSettingsSource extends ShieldSettingsSource {
|
||||||
|
|
||||||
private CustomShieldSettingsSource(boolean sslTransportEnabled, Path configDir, Scope scope) {
|
private CustomShieldSettingsSource(boolean sslTransportEnabled, Path configDir, Scope scope) {
|
||||||
super(maxNumberOfNodes(), sslTransportEnabled, configDir, scope);
|
super(maxNumberOfNodes(), sslTransportEnabled, configDir, scope);
|
||||||
}
|
}
|
||||||
|
@ -339,4 +342,12 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase {
|
||||||
protected InternalClient internalClient(String node) {
|
protected InternalClient internalClient(String node) {
|
||||||
return internalCluster().getInstance(InternalClient.class, node);
|
return internalCluster().getInstance(InternalClient.class, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected SecurityClient securityClient() {
|
||||||
|
return securityClient(client());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SecurityClient securityClient(Client client) {
|
||||||
|
return randomBoolean() ? new XPackClient(client).security() : new SecurityClient(client);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.shield.ShieldPlugin;
|
import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.shield.transport.ShieldServerTransportService;
|
import org.elasticsearch.shield.transport.ShieldServerTransportService;
|
||||||
import org.elasticsearch.test.ShieldIntegTestCase;
|
import org.elasticsearch.test.ShieldIntegTestCase;
|
||||||
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ public class ShieldServerTransportServiceTests extends ShieldIntegTestCase {
|
||||||
protected Settings transportClientSettings() {
|
protected Settings transportClientSettings() {
|
||||||
return Settings.settingsBuilder()
|
return Settings.settingsBuilder()
|
||||||
.put(super.transportClientSettings())
|
.put(super.transportClientSettings())
|
||||||
.put(ShieldPlugin.ENABLED_SETTING_NAME, true)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
import org.elasticsearch.client.Client;
|
||||||
|
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||||
|
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||||
|
import org.elasticsearch.shield.client.SecurityClient;
|
||||||
|
import org.elasticsearch.watcher.client.WatcherClient;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
|
||||||
|
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class XPackClient {
|
||||||
|
|
||||||
|
private final Client client;
|
||||||
|
private final SecurityClient securityClient;
|
||||||
|
private final WatcherClient watcherClient;
|
||||||
|
|
||||||
|
public XPackClient(Client client) {
|
||||||
|
this.client = client;
|
||||||
|
this.securityClient = new SecurityClient(client);
|
||||||
|
this.watcherClient = new WatcherClient(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SecurityClient security() {
|
||||||
|
return securityClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WatcherClient watcher() {
|
||||||
|
return watcherClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XPackClient withHeaders(Map<String, String> headers) {
|
||||||
|
return new XPackClient(client.filterWithHeader(headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a client that will call xpack APIs on behalf of the given user.
|
||||||
|
*
|
||||||
|
* @param username The username of the user
|
||||||
|
* @param passwd The password of the user. This char array can be cleared after calling this method.
|
||||||
|
*/
|
||||||
|
public XPackClient withAuth(String username, char[] passwd) {
|
||||||
|
return withHeaders(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuthHeaderValue(username, new SecuredString(passwd))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,13 +7,13 @@ package org.elasticsearch.xpack;
|
||||||
|
|
||||||
import org.elasticsearch.SpecialPermission;
|
import org.elasticsearch.SpecialPermission;
|
||||||
import org.elasticsearch.action.ActionModule;
|
import org.elasticsearch.action.ActionModule;
|
||||||
|
import org.elasticsearch.client.Client;
|
||||||
import org.elasticsearch.common.component.LifecycleComponent;
|
import org.elasticsearch.common.component.LifecycleComponent;
|
||||||
import org.elasticsearch.common.inject.Module;
|
import org.elasticsearch.common.inject.Module;
|
||||||
import org.elasticsearch.common.logging.ESLogger;
|
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
|
||||||
import org.elasticsearch.common.network.NetworkModule;
|
import org.elasticsearch.common.network.NetworkModule;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.settings.SettingsModule;
|
import org.elasticsearch.common.settings.SettingsModule;
|
||||||
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.index.IndexModule;
|
import org.elasticsearch.index.IndexModule;
|
||||||
import org.elasticsearch.license.plugin.LicensePlugin;
|
import org.elasticsearch.license.plugin.LicensePlugin;
|
||||||
import org.elasticsearch.marvel.MarvelPlugin;
|
import org.elasticsearch.marvel.MarvelPlugin;
|
||||||
|
@ -22,6 +22,7 @@ import org.elasticsearch.script.ScriptModule;
|
||||||
import org.elasticsearch.shield.ShieldPlugin;
|
import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.watcher.WatcherPlugin;
|
import org.elasticsearch.watcher.WatcherPlugin;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -29,9 +30,7 @@ import java.util.Collection;
|
||||||
|
|
||||||
public class XPackPlugin extends Plugin {
|
public class XPackPlugin extends Plugin {
|
||||||
|
|
||||||
public static final String NAME = "x-pack";
|
public static final String NAME = "xpack";
|
||||||
|
|
||||||
private final static ESLogger logger = Loggers.getLogger(XPackPlugin.class);
|
|
||||||
|
|
||||||
// TODO: clean up this library to not ask for write access to all system properties!
|
// TODO: clean up this library to not ask for write access to all system properties!
|
||||||
static {
|
static {
|
||||||
|
@ -143,4 +142,30 @@ public class XPackPlugin extends Plugin {
|
||||||
watcherPlugin.onIndexModule(module);
|
watcherPlugin.onIndexModule(module);
|
||||||
marvelPlugin.onIndexModule(module);
|
marvelPlugin.onIndexModule(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean transportClientMode(Settings settings) {
|
||||||
|
return !"node".equals(settings.get(Client.CLIENT_TYPE_SETTING_S.getKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Path resolveConfigFile(Environment env, String name) {
|
||||||
|
return env.configFile().resolve(NAME).resolve(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A consistent way to enable disable features using the following setting:
|
||||||
|
*
|
||||||
|
* {@code "xpack.<feature>.enabled": true | false}
|
||||||
|
*
|
||||||
|
* Also supports the following setting as a fallback (for BWC with 1.x/2.x):
|
||||||
|
*
|
||||||
|
* {@code "<feature>.enabled": true | false}
|
||||||
|
*/
|
||||||
|
public static boolean featureEnabled(Settings settings, String featureName, boolean defaultValue) {
|
||||||
|
return settings.getAsBoolean(featureEnabledSetting(featureName),
|
||||||
|
settings.getAsBoolean(featureName + ".enabled", defaultValue)); // for bwc
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String featureEnabledSetting(String featureName) {
|
||||||
|
return NAME + "." + featureName + ".enabled";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,4 @@
|
||||||
- do:
|
- do:
|
||||||
nodes.info: {}
|
nodes.info: {}
|
||||||
|
|
||||||
- match: { nodes.$master.plugins.0.name: x-pack }
|
- match: { nodes.$master.plugins.0.name: xpack }
|
||||||
|
|
|
@ -76,7 +76,7 @@ REM JAVA_OPTS=%JAVA_OPTS% -XX:HeapDumpPath=$ES_HOME/logs/heapdump.hprof
|
||||||
|
|
||||||
REM Disables explicit GC
|
REM Disables explicit GC
|
||||||
set JAVA_OPTS=%JAVA_OPTS% -XX:+DisableExplicitGC
|
set JAVA_OPTS=%JAVA_OPTS% -XX:+DisableExplicitGC
|
||||||
set ES_CLASSPATH=%ES_CLASSPATH%;%ES_HOME%/lib/elasticsearch-1.4.0-SNAPSHOT.jar;%ES_HOME%/lib/*;%ES_HOME%/lib/sigar/*;%ES_HOME%/plugins/x-pack/*
|
set ES_CLASSPATH=%ES_CLASSPATH%;%ES_HOME%/lib/*;%ES_HOME%/lib/sigar/*;%ES_HOME%/plugins/xpack/*
|
||||||
set ES_PARAMS=-Des.path.home="%ES_HOME%"
|
set ES_PARAMS=-Des.path.home="%ES_HOME%"
|
||||||
|
|
||||||
SET HOSTNAME=%COMPUTERNAME%
|
SET HOSTNAME=%COMPUTERNAME%
|
|
@ -114,7 +114,7 @@ fi
|
||||||
export HOSTNAME=`hostname -s`
|
export HOSTNAME=`hostname -s`
|
||||||
|
|
||||||
# include watcher jars in classpath
|
# include watcher jars in classpath
|
||||||
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/x-pack/*"
|
ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/xpack/*"
|
||||||
|
|
||||||
cd "$ES_HOME" > /dev/null
|
cd "$ES_HOME" > /dev/null
|
||||||
$JAVA $ES_JAVA_OPTS -cp "$ES_CLASSPATH" org.elasticsearch.watcher.trigger.schedule.tool.CronEvalTool "$@" $properties
|
$JAVA $ES_JAVA_OPTS -cp "$ES_CLASSPATH" org.elasticsearch.watcher.trigger.schedule.tool.CronEvalTool "$@" $properties
|
|
@ -6,6 +6,7 @@
|
||||||
package org.elasticsearch.watcher;
|
package org.elasticsearch.watcher;
|
||||||
|
|
||||||
|
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.inject.AbstractModule;
|
import org.elasticsearch.common.inject.AbstractModule;
|
||||||
import org.elasticsearch.common.inject.multibindings.Multibinder;
|
import org.elasticsearch.common.inject.multibindings.Multibinder;
|
||||||
import org.elasticsearch.common.settings.Setting;
|
import org.elasticsearch.common.settings.Setting;
|
||||||
|
@ -14,10 +15,17 @@ import org.elasticsearch.watcher.support.WatcherIndexTemplateRegistry;
|
||||||
import org.elasticsearch.watcher.support.WatcherIndexTemplateRegistry.TemplateConfig;
|
import org.elasticsearch.watcher.support.WatcherIndexTemplateRegistry.TemplateConfig;
|
||||||
import org.elasticsearch.watcher.support.validation.WatcherSettingsValidation;
|
import org.elasticsearch.watcher.support.validation.WatcherSettingsValidation;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
|
||||||
public class WatcherModule extends AbstractModule {
|
public class WatcherModule extends AbstractModule {
|
||||||
|
|
||||||
public static final String HISTORY_TEMPLATE_NAME = "watch_history";
|
static final String PROPERTIES_FILE = "/watcher.properties";
|
||||||
|
static final String VERSION_FIELD = "watcher.template.version";
|
||||||
|
|
||||||
|
public static final String HISTORY_TEMPLATE_NAME = "watch_history_" + getHistoryIndexTemplateVersion();
|
||||||
public static final String TRIGGERED_TEMPLATE_NAME = "triggered_watches";
|
public static final String TRIGGERED_TEMPLATE_NAME = "triggered_watches";
|
||||||
public static final String WATCHES_TEMPLATE_NAME = "watches";
|
public static final String WATCHES_TEMPLATE_NAME = "watches";
|
||||||
public static final Setting<Settings> HISTORY_TEMPLATE_SETTING = Setting.groupSetting("watcher.history.index.", true,
|
public static final Setting<Settings> HISTORY_TEMPLATE_SETTING = Setting.groupSetting("watcher.history.index.", true,
|
||||||
|
@ -30,7 +38,7 @@ public class WatcherModule extends AbstractModule {
|
||||||
|
|
||||||
public final static TemplateConfig[] TEMPLATE_CONFIGS = new TemplateConfig[]{
|
public final static TemplateConfig[] TEMPLATE_CONFIGS = new TemplateConfig[]{
|
||||||
new TemplateConfig(TRIGGERED_TEMPLATE_NAME, TRIGGERED_TEMPLATE_SETTING),
|
new TemplateConfig(TRIGGERED_TEMPLATE_NAME, TRIGGERED_TEMPLATE_SETTING),
|
||||||
new TemplateConfig(HISTORY_TEMPLATE_NAME, HISTORY_TEMPLATE_SETTING),
|
new TemplateConfig(HISTORY_TEMPLATE_NAME, "watch_history", HISTORY_TEMPLATE_SETTING),
|
||||||
new TemplateConfig(WATCHES_TEMPLATE_NAME, WATCHES_TEMPLATE_SETTING)
|
new TemplateConfig(WATCHES_TEMPLATE_NAME, WATCHES_TEMPLATE_SETTING)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,4 +61,19 @@ public class WatcherModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final Integer getHistoryIndexTemplateVersion() {
|
||||||
|
try (InputStream is = WatcherModule.class.getResourceAsStream(PROPERTIES_FILE)) {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(is);
|
||||||
|
String version = properties.getProperty(VERSION_FIELD);
|
||||||
|
if (Strings.hasLength(version)) {
|
||||||
|
return Integer.parseInt(version);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IllegalArgumentException("failed to parse watcher template version");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalArgumentException("failed to load watcher template version");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.settings.SettingsModule;
|
import org.elasticsearch.common.settings.SettingsModule;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
import org.elasticsearch.script.ScriptModule;
|
import org.elasticsearch.script.ScriptModule;
|
||||||
|
import org.elasticsearch.shield.ShieldPlugin;
|
||||||
|
import org.elasticsearch.shield.authz.privilege.ClusterPrivilege;
|
||||||
import org.elasticsearch.watcher.actions.WatcherActionModule;
|
import org.elasticsearch.watcher.actions.WatcherActionModule;
|
||||||
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
import org.elasticsearch.watcher.actions.email.service.EmailService;
|
||||||
import org.elasticsearch.watcher.actions.email.service.InternalEmailService;
|
import org.elasticsearch.watcher.actions.email.service.InternalEmailService;
|
||||||
|
@ -50,8 +52,7 @@ import org.elasticsearch.watcher.rest.action.RestPutWatchAction;
|
||||||
import org.elasticsearch.watcher.rest.action.RestWatchServiceAction;
|
import org.elasticsearch.watcher.rest.action.RestWatchServiceAction;
|
||||||
import org.elasticsearch.watcher.rest.action.RestWatcherInfoAction;
|
import org.elasticsearch.watcher.rest.action.RestWatcherInfoAction;
|
||||||
import org.elasticsearch.watcher.rest.action.RestWatcherStatsAction;
|
import org.elasticsearch.watcher.rest.action.RestWatcherStatsAction;
|
||||||
import org.elasticsearch.watcher.shield.ShieldSecretService;
|
import org.elasticsearch.watcher.support.secret.SecretService;
|
||||||
import org.elasticsearch.watcher.shield.WatcherShieldModule;
|
|
||||||
import org.elasticsearch.watcher.support.WatcherIndexTemplateRegistry.TemplateConfig;
|
import org.elasticsearch.watcher.support.WatcherIndexTemplateRegistry.TemplateConfig;
|
||||||
import org.elasticsearch.watcher.support.clock.ClockModule;
|
import org.elasticsearch.watcher.support.clock.ClockModule;
|
||||||
import org.elasticsearch.watcher.support.http.HttpClient;
|
import org.elasticsearch.watcher.support.http.HttpClient;
|
||||||
|
@ -91,13 +92,19 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static org.elasticsearch.common.settings.Setting.Scope.CLUSTER;
|
||||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||||
|
|
||||||
public class WatcherPlugin extends Plugin {
|
public class WatcherPlugin extends Plugin {
|
||||||
|
|
||||||
public static final String NAME = "watcher";
|
public static final String NAME = "watcher";
|
||||||
public static final String ENABLED_SETTING = NAME + ".enabled";
|
public static final String ENABLED_SETTING = NAME + ".enabled";
|
||||||
|
public static final Setting<String> INDEX_WATCHER_VERSION_SETTING =
|
||||||
|
new Setting<>("index.watcher.plugin.version", "", Function.identity(), false, Setting.Scope.INDEX);
|
||||||
|
public static final Setting<String> INDEX_WATCHER_TEMPLATE_VERSION_SETTING =
|
||||||
|
new Setting<>("index.watcher.template.version", "", Function.identity(), false, Setting.Scope.INDEX);
|
||||||
|
|
||||||
private final static ESLogger logger = Loggers.getLogger(XPackPlugin.class);
|
private final static ESLogger logger = Loggers.getLogger(XPackPlugin.class);
|
||||||
|
|
||||||
|
@ -114,7 +121,14 @@ public class WatcherPlugin extends Plugin {
|
||||||
transportClient = "transport".equals(settings.get(Client.CLIENT_TYPE_SETTING_S.getKey()));
|
transportClient = "transport".equals(settings.get(Client.CLIENT_TYPE_SETTING_S.getKey()));
|
||||||
enabled = watcherEnabled(settings);
|
enabled = watcherEnabled(settings);
|
||||||
validAutoCreateIndex(settings);
|
validAutoCreateIndex(settings);
|
||||||
|
|
||||||
|
// adding the watcher privileges to shield
|
||||||
|
if (ShieldPlugin.enabled(settings)) {
|
||||||
|
registerClusterPrivilege("manage_watcher", "cluster:admin/watcher/*", "cluster:monitor/watcher/*");
|
||||||
|
registerClusterPrivilege("monitor_watcher", "cluster:monitor/watcher/*");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override public String name() {
|
@Override public String name() {
|
||||||
return NAME;
|
return NAME;
|
||||||
|
@ -146,7 +160,6 @@ public class WatcherPlugin extends Plugin {
|
||||||
new WatcherActionModule(),
|
new WatcherActionModule(),
|
||||||
new HistoryModule(),
|
new HistoryModule(),
|
||||||
new ExecutionModule(),
|
new ExecutionModule(),
|
||||||
new WatcherShieldModule(settings),
|
|
||||||
new SecretModule(settings));
|
new SecretModule(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,37 +206,41 @@ public class WatcherPlugin extends Plugin {
|
||||||
module.registerSetting(InternalEmailService.EMAIL_ACCOUNT_SETTING);
|
module.registerSetting(InternalEmailService.EMAIL_ACCOUNT_SETTING);
|
||||||
module.registerSetting(InternalHipChatService.HIPCHAT_ACCOUNT_SETTING);
|
module.registerSetting(InternalHipChatService.HIPCHAT_ACCOUNT_SETTING);
|
||||||
module.registerSetting(InternalPagerDutyService.PAGERDUTY_ACCOUNT_SETTING);
|
module.registerSetting(InternalPagerDutyService.PAGERDUTY_ACCOUNT_SETTING);
|
||||||
module.registerSetting(Setting.intSetting("watcher.execution.scroll.size", 0, false, Setting.Scope.CLUSTER));
|
module.registerSetting(INDEX_WATCHER_VERSION_SETTING);
|
||||||
module.registerSetting(Setting.intSetting("watcher.watch.scroll.size", 0, false, Setting.Scope.CLUSTER));
|
module.registerSetting(INDEX_WATCHER_TEMPLATE_VERSION_SETTING);
|
||||||
module.registerSetting(Setting.boolSetting("watcher.enabled", false, false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.intSetting("watcher.execution.scroll.size", 0, false, CLUSTER));
|
||||||
module.registerSetting(ShieldSecretService.ENCRYPT_SENSITIVE_DATA_SETTING);
|
module.registerSetting(Setting.intSetting("watcher.watch.scroll.size", 0, false, CLUSTER));
|
||||||
|
module.registerSetting(Setting.boolSetting("watcher.enabled", false, false, CLUSTER));
|
||||||
|
module.registerSetting(SecretService.Secure.ENCRYPT_SENSITIVE_DATA_SETTING);
|
||||||
|
|
||||||
// TODO add real settings for these
|
// TODO add real settings for these
|
||||||
module.registerSetting(Setting.simpleString("resource.reload.interval", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("resource.reload.interval", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("resource.reload.enabled", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("resource.reload.enabled", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("resource.reload.interval.low", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("resource.reload.interval.low", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("resource.reload.interval.medium", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("resource.reload.interval.medium", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.internal.ops.search.default_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.internal.ops.search.default_timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.internal.ops.bulk.default_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.internal.ops.bulk.default_timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.internal.ops.index.default_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.internal.ops.index.default_timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.execution.default_throttle_period", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.execution.default_throttle_period", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.http.default_read_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.http.default_read_timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.groupSetting("watcher.http.ssl.", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.groupSetting("watcher.http.ssl.", false, CLUSTER));
|
||||||
module.registerSetting(Setting.groupSetting("watcher.http.proxy.", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.groupSetting("watcher.http.proxy.", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.actions.index.default_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.actions.index.default_timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.index.rest.direct_access", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.index.rest.direct_access", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.trigger.schedule.engine", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.trigger.schedule.engine", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.input.search.default_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.input.search.default_timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.transform.search.default_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.transform.search.default_timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.trigger.schedule.ticker.tick_interval", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.trigger.schedule.ticker.tick_interval", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.execution.scroll.timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.execution.scroll.timeout", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.start_immediately", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.start_immediately", false, CLUSTER));
|
||||||
module.registerSetting(Setting.simpleString("watcher.http.default_connection_timeout", false, Setting.Scope.CLUSTER));
|
module.registerSetting(Setting.simpleString("watcher.http.default_connection_timeout", false, CLUSTER));
|
||||||
|
|
||||||
module.registerSettingsFilter("watcher.actions.email.service.account.*.smtp.password");
|
module.registerSettingsFilter("watcher.actions.email.service.account.*.smtp.password");
|
||||||
module.registerSettingsFilter("watcher.actions.slack.service.account.*.url");
|
module.registerSettingsFilter("watcher.actions.slack.service.account.*.url");
|
||||||
module.registerSettingsFilter("watcher.actions.pagerduty.service.account.*.url");
|
module.registerSettingsFilter("watcher.actions.pagerduty.service.account.*.url");
|
||||||
module.registerSettingsFilter("watcher.actions.pagerduty.service." + PagerDutyAccount.SERVICE_KEY_SETTING);
|
module.registerSettingsFilter("watcher.actions.pagerduty.service." + PagerDutyAccount.SERVICE_KEY_SETTING);
|
||||||
module.registerSettingsFilter("watcher.actions.pagerduty.service.account.*." + PagerDutyAccount.SERVICE_KEY_SETTING);
|
module.registerSettingsFilter("watcher.actions.pagerduty.service.account.*." +
|
||||||
|
PagerDutyAccount.SERVICE_KEY_SETTING);
|
||||||
module.registerSettingsFilter("watcher.actions.hipchat.service.account.*.auth_token");
|
module.registerSettingsFilter("watcher.actions.hipchat.service.account.*.auth_token");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,8 +282,9 @@ public class WatcherPlugin extends Plugin {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String errorMessage = LoggerMessageFormat.format("the [action.auto_create_index] setting value [{}] is too restrictive. disable " +
|
String errorMessage = LoggerMessageFormat.format("the [action.auto_create_index] setting value [{}] is too" +
|
||||||
"[action.auto_create_index] or set it to [.watches,.triggered_watches,.watch_history*]", (Object) settings);
|
" restrictive. disable [action.auto_create_index] or set it to " +
|
||||||
|
"[.watches,.triggered_watches,.watcher-history*]", (Object) settings);
|
||||||
if (Booleans.isExplicitFalse(value)) {
|
if (Booleans.isExplicitFalse(value)) {
|
||||||
throw new IllegalArgumentException(errorMessage);
|
throw new IllegalArgumentException(errorMessage);
|
||||||
}
|
}
|
||||||
|
@ -312,9 +330,22 @@ public class WatcherPlugin extends Plugin {
|
||||||
throw new IllegalArgumentException(errorMessage);
|
throw new IllegalArgumentException(errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.warn("the [action.auto_create_index] setting is configured to be restrictive [{}]. for the next 6 months daily history " +
|
logger.warn("the [action.auto_create_index] setting is configured to be restrictive [{}]. " +
|
||||||
"indices are allowed to be created, but please make sure that any future history indices after 6 months with the pattern " +
|
" for the next 6 months daily history indices are allowed to be created, but please make sure" +
|
||||||
"[.watch_history-YYYY.MM.dd] are allowed to be created", value);
|
" that any future history indices after 6 months with the pattern " +
|
||||||
|
"[.watcher-history-YYYY.MM.dd] are allowed to be created", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerClusterPrivilege(String name, String... patterns) {
|
||||||
|
try {
|
||||||
|
ClusterPrivilege.addCustom(name, patterns);
|
||||||
|
} catch (Exception se) {
|
||||||
|
logger.warn("could not register cluster privilege [{}]", name);
|
||||||
|
|
||||||
|
// we need to prevent bubbling the shield exception here for the tests. In the tests
|
||||||
|
// we create multiple nodes in the same jvm and since the custom cluster is a static binding
|
||||||
|
// multiple nodes will try to add the same privileges multiple times.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ public abstract class WatchExecutionContext {
|
||||||
public abstract boolean skipThrottling(String actionId);
|
public abstract boolean skipThrottling(String actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this execution should be recorded in the .watch_history index
|
* @return true if this execution should be recorded in the .watcher-history index
|
||||||
*/
|
*/
|
||||||
public abstract boolean recordExecution();
|
public abstract boolean recordExecution();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.index.engine.VersionConflictEngineException;
|
import org.elasticsearch.index.engine.VersionConflictEngineException;
|
||||||
|
import org.elasticsearch.watcher.WatcherModule;
|
||||||
import org.elasticsearch.watcher.execution.ExecutionState;
|
import org.elasticsearch.watcher.execution.ExecutionState;
|
||||||
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -30,7 +31,7 @@ import static org.elasticsearch.watcher.support.Exceptions.ioException;
|
||||||
*/
|
*/
|
||||||
public class HistoryStore extends AbstractComponent {
|
public class HistoryStore extends AbstractComponent {
|
||||||
|
|
||||||
public static final String INDEX_PREFIX = ".watch_history-";
|
public static final String INDEX_PREFIX = ".watcher-history-" + WatcherModule.getHistoryIndexTemplateVersion() + "-";
|
||||||
public static final String DOC_TYPE = "watch_record";
|
public static final String DOC_TYPE = "watch_record";
|
||||||
|
|
||||||
static final DateTimeFormatter indexTimeFormat = DateTimeFormat.forPattern("YYYY.MM.dd");
|
static final DateTimeFormatter indexTimeFormat = DateTimeFormat.forPattern("YYYY.MM.dd");
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.watcher.shield;
|
|
||||||
|
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
|
||||||
import org.elasticsearch.common.inject.Inject;
|
|
||||||
import org.elasticsearch.common.settings.Setting;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.shield.crypto.CryptoService;
|
|
||||||
import org.elasticsearch.watcher.support.secret.SecretService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ShieldSecretService extends AbstractComponent implements SecretService {
|
|
||||||
|
|
||||||
private final CryptoService cryptoService;
|
|
||||||
private final boolean encryptSensitiveData;
|
|
||||||
public static final Setting<Boolean> ENCRYPT_SENSITIVE_DATA_SETTING =
|
|
||||||
Setting.boolSetting("watcher.shield.encrypt_sensitive_data", false, false, Setting.Scope.CLUSTER);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ShieldSecretService(Settings settings, CryptoService cryptoService) {
|
|
||||||
super(settings);
|
|
||||||
this.encryptSensitiveData = ENCRYPT_SENSITIVE_DATA_SETTING.get(settings);
|
|
||||||
this.cryptoService = cryptoService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char[] encrypt(char[] text) {
|
|
||||||
return encryptSensitiveData ? cryptoService.encrypt(text) : text;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char[] decrypt(char[] text) {
|
|
||||||
return encryptSensitiveData ? cryptoService.decrypt(text) : text;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.watcher.shield;
|
|
||||||
|
|
||||||
import org.elasticsearch.common.inject.AbstractModule;
|
|
||||||
import org.elasticsearch.common.logging.ESLogger;
|
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.shield.ShieldPlugin;
|
|
||||||
import org.elasticsearch.shield.authz.privilege.ClusterPrivilege;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class WatcherShieldModule extends AbstractModule {
|
|
||||||
|
|
||||||
private final ESLogger logger;
|
|
||||||
|
|
||||||
public WatcherShieldModule(Settings settings) {
|
|
||||||
this.logger = Loggers.getLogger(WatcherShieldModule.class, settings);
|
|
||||||
if (ShieldPlugin.shieldEnabled(settings)) {
|
|
||||||
registerClusterPrivilege("manage_watcher", "cluster:admin/watcher/*", "cluster:monitor/watcher/*");
|
|
||||||
registerClusterPrivilege("monitor_watcher", "cluster:monitor/watcher/*");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerClusterPrivilege(String name, String... patterns) {
|
|
||||||
try {
|
|
||||||
ClusterPrivilege.addCustom(name, patterns);
|
|
||||||
} catch (Exception se) {
|
|
||||||
logger.warn("could not register cluster privilege [{}]", name);
|
|
||||||
|
|
||||||
// we need to prevent bubbling the shield exception here for the tests. In the tests
|
|
||||||
// we create multiple nodes in the same jvm and since the custom cluster is a static binding
|
|
||||||
// multiple nodes will try to add the same privileges multiple times.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -153,9 +153,9 @@ public class WatcherIndexTemplateRegistry extends AbstractComponent implements C
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try (InputStream is = WatchStore.class.getResourceAsStream("/" + config.getTemplateName() + ".json")) {
|
try (InputStream is = WatchStore.class.getResourceAsStream("/" + config.getFileName()+ ".json")) {
|
||||||
if (is == null) {
|
if (is == null) {
|
||||||
logger.error("Resource [/" + config.getTemplateName() + ".json] not found in classpath");
|
logger.error("Resource [/" + config.getFileName() + ".json] not found in classpath");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final byte[] template;
|
final byte[] template;
|
||||||
|
@ -184,13 +184,23 @@ public class WatcherIndexTemplateRegistry extends AbstractComponent implements C
|
||||||
public static class TemplateConfig {
|
public static class TemplateConfig {
|
||||||
|
|
||||||
private final String templateName;
|
private final String templateName;
|
||||||
|
private String fileName;
|
||||||
private final Setting<Settings> setting;
|
private final Setting<Settings> setting;
|
||||||
|
|
||||||
public TemplateConfig(String templateName, Setting<Settings> setting) {
|
public TemplateConfig(String templateName, Setting<Settings> setting) {
|
||||||
|
this(templateName, templateName, setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateConfig(String templateName, String fileName, Setting<Settings> setting) {
|
||||||
this.templateName = templateName;
|
this.templateName = templateName;
|
||||||
|
this.fileName = fileName;
|
||||||
this.setting = setting;
|
this.setting = setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTemplateName() {
|
public String getTemplateName() {
|
||||||
return templateName;
|
return templateName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ package org.elasticsearch.watcher.support.secret;
|
||||||
import org.elasticsearch.common.inject.AbstractModule;
|
import org.elasticsearch.common.inject.AbstractModule;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.shield.ShieldPlugin;
|
import org.elasticsearch.shield.ShieldPlugin;
|
||||||
import org.elasticsearch.watcher.shield.ShieldSecretService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -18,17 +17,16 @@ public class SecretModule extends AbstractModule {
|
||||||
private final boolean shieldEnabled;
|
private final boolean shieldEnabled;
|
||||||
|
|
||||||
public SecretModule(Settings settings) {
|
public SecretModule(Settings settings) {
|
||||||
shieldEnabled = ShieldPlugin.shieldEnabled(settings);
|
shieldEnabled = ShieldPlugin.enabled(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
if (shieldEnabled) {
|
if (shieldEnabled) {
|
||||||
bind(ShieldSecretService.class).asEagerSingleton();
|
bind(SecretService.Secure.class).asEagerSingleton();
|
||||||
bind(SecretService.class).to(ShieldSecretService.class);
|
bind(SecretService.class).to(SecretService.Secure.class);
|
||||||
} else {
|
} else {
|
||||||
bind(SecretService.PlainText.class).asEagerSingleton();
|
bind(SecretService.class).toInstance(SecretService.Insecure.INSTANCE);
|
||||||
bind(SecretService.class).to(SecretService.PlainText.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,12 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.watcher.support.secret;
|
package org.elasticsearch.watcher.support.secret;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.settings.Setting;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.shield.crypto.CryptoService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +20,12 @@ public interface SecretService {
|
||||||
|
|
||||||
char[] decrypt(char[] text);
|
char[] decrypt(char[] text);
|
||||||
|
|
||||||
class PlainText implements SecretService {
|
class Insecure implements SecretService {
|
||||||
|
|
||||||
|
public static final Insecure INSTANCE = new Insecure();
|
||||||
|
|
||||||
|
Insecure() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char[] encrypt(char[] text) {
|
public char[] encrypt(char[] text) {
|
||||||
|
@ -26,4 +37,31 @@ public interface SecretService {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Secure extends AbstractComponent implements SecretService {
|
||||||
|
|
||||||
|
private final CryptoService cryptoService;
|
||||||
|
private final boolean encryptSensitiveData;
|
||||||
|
public static final Setting<Boolean> ENCRYPT_SENSITIVE_DATA_SETTING =
|
||||||
|
Setting.boolSetting("watcher.shield.encrypt_sensitive_data", false, false, Setting.Scope.CLUSTER);
|
||||||
|
@Inject
|
||||||
|
public Secure(Settings settings, CryptoService cryptoService) {
|
||||||
|
super(settings);
|
||||||
|
this.encryptSensitiveData = ENCRYPT_SENSITIVE_DATA_SETTING.get(settings);
|
||||||
|
this.cryptoService = cryptoService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char[] encrypt(char[] text) {
|
||||||
|
return encryptSensitiveData ? cryptoService.encrypt(text) : text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char[] decrypt(char[] text) {
|
||||||
|
return encryptSensitiveData ? cryptoService.decrypt(text) : text;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,7 +257,7 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
||||||
* Such that the returned watch will potentially hide this sensitive data behind a "secret". A secret
|
* Such that the returned watch will potentially hide this sensitive data behind a "secret". A secret
|
||||||
* is an abstraction around sensitive data (text). There can be different implementations of how the
|
* is an abstraction around sensitive data (text). There can be different implementations of how the
|
||||||
* secret holds the data, depending on the wired up {@link SecretService}. When shield is installed, a
|
* secret holds the data, depending on the wired up {@link SecretService}. When shield is installed, a
|
||||||
* {@link org.elasticsearch.watcher.shield.ShieldSecretService} is used, that potentially encrypts the data
|
* {@link SecretService.Secure} is used, that potentially encrypts the data
|
||||||
* using Shield's configured system key.
|
* using Shield's configured system key.
|
||||||
*
|
*
|
||||||
* This method is only called once - when the user adds a new watch. From that moment on, all representations
|
* This method is only called once - when the user adds a new watch. From that moment on, all representations
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
{
|
{
|
||||||
"template": ".watch_history*",
|
"template": ".watcher-history-${watcher.template.version}*",
|
||||||
"order": 2147483647,
|
"order": 2147483647,
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"watcher.plugin.version": "${watcher.plugin.version}",
|
||||||
|
"watcher.template.version": "${watcher.template.version}",
|
||||||
"index.number_of_shards": 1,
|
"index.number_of_shards": 1,
|
||||||
"index.mapper.dynamic": false
|
"index.mapper.dynamic": false
|
||||||
},
|
},
|
||||||
|
@ -29,7 +31,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dynamic": "strict",
|
"dynamic": false,
|
||||||
"_all": {
|
"_all": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
watcher.template.version=${watcher.template.version}
|
|
@ -41,8 +41,10 @@ public class WatcherPluginDisableTests extends ESIntegTestCase {
|
||||||
return Settings.settingsBuilder()
|
return Settings.settingsBuilder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put(WatcherPlugin.ENABLED_SETTING, false)
|
.put(WatcherPlugin.ENABLED_SETTING, false)
|
||||||
|
|
||||||
// disable shield because of query cache check and authentication/authorization
|
// disable shield because of query cache check and authentication/authorization
|
||||||
.put(ShieldPlugin.ENABLED_SETTING_NAME, false)
|
.put(XPackPlugin.featureEnabledSetting(ShieldPlugin.NAME), false)
|
||||||
|
|
||||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue