Test: remove KnownActionsTests (elastic/x-pack-elasticsearch#3133)

This commit removes the KnownActionsTests as it no longer serves the intended purpose of catching
actions/handlers added to elasticsearch that security needs to be aware of. Today, it is common
for this test to break the build and as a mechanical response developers just add to the actions
or handlers file to get the build green again.

Relates elastic/x-pack-elasticsearch#1489

Original commit: elastic/x-pack-elasticsearch@0bdb5341f5
This commit is contained in:
Jay Modi 2017-11-28 08:06:36 -07:00 committed by GitHub
parent c7fea95476
commit fa33f45cfb
4 changed files with 22 additions and 548 deletions

View File

@ -1,227 +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.transport;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.Version;
import org.elasticsearch.action.Action;
import org.elasticsearch.common.io.FileSystemUtils;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.reindex.ReindexPlugin;
import org.elasticsearch.license.Licensing;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.discovery.TestZenDiscovery;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.deprecation.Deprecation;
import org.junit.BeforeClass;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static java.util.Collections.unmodifiableSet;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
@ClusterScope(numClientNodes = 0, supportsDedicatedMasters = false, numDataNodes = 1)
public class KnownActionsTests extends SecurityIntegTestCase {
private static Set<String> knownActions;
private static Set<String> knownHandlers;
private static Set<String> codeActions;
@Override
protected Collection<Class<? extends Plugin>> getMockPlugins() {
Collection<Class<? extends Plugin>> mockPlugins = super.getMockPlugins();
// no handler wrapping here we check the requestHandlers below and this plugin wraps it
return mockPlugins.stream().filter(p -> p != AssertingTransportInterceptor.TestPlugin.class).collect(Collectors.toList());
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
.put(TestZenDiscovery.USE_MOCK_PINGS.getKey(), false).build();
}
@BeforeClass
public static void init() throws Exception {
knownActions = loadKnownActions();
knownHandlers = loadKnownHandlers();
codeActions = loadCodeActions();
}
public void testAllTransportHandlersAreKnown() {
TransportService transportService = internalCluster().getDataNodeInstance(TransportService.class);
for (String handler : transportService.requestHandlers.keySet()) {
if (!knownActions.contains(handler)) {
assertThat("elasticsearch core transport handler [" + handler + "] is unknown to security", knownHandlers,
hasItem(handler));
}
}
}
public void testAllCodeActionsAreKnown() throws Exception {
for (String action : codeActions) {
assertThat("classpath action [" + action + "] is unknown to security", knownActions, hasItem(action));
}
}
public void testAllKnownActionsAreValid() {
for (String knownAction : knownActions) {
assertThat("security known action [" + knownAction + "] is not among the classpath actions", codeActions,
hasItems(knownAction));
}
}
public void testAllKnownTransportHandlersAreValid() {
TransportService transportService = internalCluster().getDataNodeInstance(TransportService.class);
for (String knownHandler : knownHandlers) {
assertThat("security known handler [" + knownHandler + "] is unknown to core", transportService.requestHandlers.keySet(),
hasItems(knownHandler));
}
}
public static Set<String> loadKnownActions() {
return readSetFromResource("actions");
}
public static Set<String> loadKnownHandlers() {
return readSetFromResource("handlers");
}
private static Set<String> readSetFromResource(String resource) {
Set<String> knownActions = new HashSet<>();
try (InputStream input = KnownActionsTests.class.getResourceAsStream(resource)) {
Streams.readAllLines(input, action -> knownActions.add(action));
} catch (IOException ioe) {
throw new IllegalStateException("could not load known " + resource, ioe);
}
return unmodifiableSet(knownActions);
}
private static Set<String> loadCodeActions() throws IOException, ReflectiveOperationException, URISyntaxException {
Set<String> actions = new HashSet<>();
// loading es core actions in org.elasticsearch package
loadActions(collectSubClasses(Action.class, Version.class), actions);
// loading all xpack top level actions in org.elasticsearch.xpack package
loadActions(collectSubClasses(Action.class, XPackPlugin.class), actions);
// also loading all actions from the licensing plugin in org.elasticsearch.license package
loadActions(collectSubClasses(Action.class, Licensing.class), actions);
// also load stuff from Reindex in org.elasticsearch.index.reindex package
loadActions(collectSubClasses(Action.class, ReindexPlugin.class), actions);
// also load stuff from Deprecation in org.elasticsearch.deprecation
loadActions(collectSubClasses(Action.class, Deprecation.class), actions);
return unmodifiableSet(actions);
}
private static void loadActions(Collection<Class<?>> clazzes, Set<String> actions) throws ReflectiveOperationException {
for (Class<?> clazz : clazzes) {
if (!Modifier.isAbstract(clazz.getModifiers())) {
Field field = null;
try {
field = clazz.getField("INSTANCE");
} catch (NoSuchFieldException nsfe) {
fail("every action should have a static field called INSTANCE, missing in " + clazz.getName());
}
assertThat("every action should have a static field called INSTANCE, present but not static in " + clazz.getName(),
Modifier.isStatic(field.getModifiers()), is(true));
actions.add(((Action) field.get(null)).name());
}
}
}
/**
* finds all subclasses extending {@code subClass}, recursively from the package and codesource of {@code prototype}
*/
private static Collection<Class<?>> collectSubClasses(Class<?> subClass, Class<?> prototype) throws IOException,
ReflectiveOperationException, URISyntaxException {
URL codeLocation = prototype.getProtectionDomain().getCodeSource().getLocation();
final FileSystem fileSystem;
final Path root;
if (codeLocation.toURI().toString().endsWith(".jar")) {
try {
// hack around a bug in the zipfilesystem implementation before java 9,
// its checkWritable was incorrect and it won't work without write permissions.
// if we add the permission, it will open jars r/w, which is too scary! so copy to a safe r-w location.
Path tmp = createTempFile(null, ".jar");
try (InputStream in = FileSystemUtils.openFileURLStream(codeLocation)) {
Files.copy(in, tmp, StandardCopyOption.REPLACE_EXISTING);
}
fileSystem = FileSystems.newFileSystem(new URI("jar:" + tmp.toUri()), Collections.<String,Object>emptyMap());
root = fileSystem.getPath("/");
} catch (URISyntaxException e) {
throw new IOException("couldn't open zipfilesystem: ", e);
}
} else {
fileSystem = null;
root = PathUtils.get(codeLocation.toURI());
}
ClassLoader loader = prototype.getClassLoader();
List<Class<?>> clazzes = new ArrayList<>();
try {
collectClassesForPackage(subClass, root, loader, prototype.getPackage().getName(), clazzes);
} finally {
IOUtils.close(fileSystem);
}
return clazzes;
}
private static void collectClassesForPackage(Class<?> subclass, Path root, ClassLoader cld, String pckgname, List<Class<?>> classes)
throws IOException, ReflectiveOperationException {
String pathName = pckgname.replace('.', '/');
Path directory = root.resolve(pathName);
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
for (Path file : stream) {
if (Files.isDirectory(file)) {
// recurse
String subPackage = pckgname + "." + file.getFileName().toString();
// remove trailing / or whatever
if (subPackage.endsWith(root.getFileSystem().getSeparator())) {
subPackage = subPackage.substring(0, subPackage.length() - root.getFileSystem().getSeparator().length());
}
collectClassesForPackage(subclass, root, cld, subPackage, classes);
}
String fname = file.getFileName().toString();
if (fname.endsWith(".class")) {
String clazzName = fname.substring(0, fname.length() - 6);
Class<?> clazz = Class.forName(pckgname + '.' + clazzName, false, cld);
// Don't run static initializers, as we won't use most of them.
// Java will do that automatically once accessed/instantiated.
if (subclass.isAssignableFrom(clazz)) {
classes.add(clazz);
}
}
}
}
}
}

View File

@ -10,37 +10,40 @@ import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
import org.elasticsearch.action.search.ClearScrollAction;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.transport.KnownActionsTests;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.CoreMatchers.equalTo;
public class SecurityActionMapperTests extends ESTestCase {
public void testThatAllOrdinaryActionsRemainTheSame() {
List<String> actions = new ArrayList<>();
actions.addAll(KnownActionsTests.loadKnownActions());
actions.addAll(KnownActionsTests.loadKnownHandlers());
SecurityActionMapper securityActionMapper = new SecurityActionMapper();
int iterations = randomIntBetween(10, 100);
for (int i = 0; i < iterations; i++) {
String randomAction;
do {
if (randomBoolean()) {
randomAction = randomFrom(actions);
} else {
randomAction = randomAlphaOfLength(randomIntBetween(1, 30));
}
} while (randomAction.equals(ClearScrollAction.NAME) ||
StringBuilder actionNameBuilder = new StringBuilder();
if (randomBoolean()) {
actionNameBuilder.append("indices:");
if (randomBoolean()) {
actionNameBuilder.append("data/");
actionNameBuilder.append(randomBoolean() ? "read" : "write");
actionNameBuilder.append("/");
actionNameBuilder.append(randomAlphaOfLengthBetween(2, 12));
} else {
actionNameBuilder.append(randomBoolean() ? "admin" : "monitor");
actionNameBuilder.append("/");
actionNameBuilder.append(randomAlphaOfLengthBetween(2, 12));
}
} else {
actionNameBuilder.append("cluster:");
actionNameBuilder.append(randomBoolean() ? "admin" : "monitor");
actionNameBuilder.append("/");
actionNameBuilder.append(randomAlphaOfLengthBetween(2, 12));
}
String randomAction = actionNameBuilder.toString();
assumeFalse("Random action is one of the known mapped values: " + randomAction, randomAction.equals(ClearScrollAction.NAME) ||
randomAction.equals(AnalyzeAction.NAME) ||
randomAction.equals(AnalyzeAction.NAME + "[s]"));
assertThat(securityActionMapper.action(randomAction, null), equalTo(randomAction));
}
assertThat(securityActionMapper.action(randomAction, null), equalTo(randomAction));
}
public void testClearScroll() {

View File

@ -1,164 +0,0 @@
cluster:admin/repository/delete
cluster:admin/repository/get
cluster:admin/repository/put
cluster:admin/repository/verify
cluster:admin/reroute
cluster:admin/settings/update
cluster:admin/snapshot/create
cluster:admin/snapshot/delete
cluster:admin/snapshot/get
cluster:admin/snapshot/restore
cluster:admin/snapshot/status
cluster:admin/tasks/cancel
cluster:monitor/allocation/explain
cluster:monitor/health
cluster:monitor/main
cluster:monitor/nodes/hot_threads
cluster:monitor/nodes/info
cluster:monitor/nodes/stats
cluster:monitor/nodes/usage
cluster:monitor/remote/info
cluster:monitor/state
cluster:monitor/stats
cluster:monitor/task
cluster:monitor/task/get
cluster:monitor/tasks/lists
indices:admin/aliases
indices:admin/aliases/exists
indices:admin/aliases/get
indices:admin/analyze
indices:admin/cache/clear
indices:admin/close
indices:admin/create
indices:admin/delete
indices:admin/get
indices:admin/exists
indices:admin/flush
indices:admin/synced_flush
indices:admin/forcemerge
indices:admin/mapping/put
indices:admin/mappings/fields/get
indices:admin/mappings/get
indices:admin/open
indices:admin/refresh
indices:admin/settings/update
indices:admin/shards/search_shards
indices:admin/shrink
indices:admin/resize
indices:admin/rollover
indices:admin/template/delete
indices:admin/template/get
indices:admin/template/put
indices:admin/types/exists
indices:admin/upgrade
indices:admin/validate/query
indices:monitor/recovery
indices:monitor/segments
indices:monitor/settings/get
indices:monitor/shard_stores
indices:monitor/stats
indices:monitor/upgrade
indices:data/read/explain
indices:data/read/field_caps
indices:data/read/get
indices:data/read/xpack/graph/explore
indices:data/read/mget
indices:data/read/msearch
indices:data/read/mtv
cluster:admin/script/get
indices:data/read/scroll
indices:data/read/scroll/clear
indices:data/read/search
indices:data/read/tv
indices:data/write/bulk
indices:data/write/delete
indices:data/write/index
cluster:admin/script/delete
cluster:admin/script/put
indices:data/write/update
cluster:monitor/xpack/info
cluster:monitor/xpack/usage
cluster:monitor/xpack/license/get
cluster:admin/xpack/license/delete
cluster:admin/xpack/license/put
cluster:admin/xpack/monitoring/bulk
cluster:admin/xpack/security/realm/cache/clear
cluster:admin/xpack/security/roles/cache/clear
cluster:admin/xpack/security/user/authenticate
cluster:admin/xpack/security/user/change_password
cluster:admin/xpack/security/user/put
cluster:admin/xpack/security/user/delete
cluster:admin/xpack/security/user/get
cluster:admin/xpack/security/user/set_enabled
cluster:admin/xpack/security/user/has_privileges
cluster:admin/xpack/security/role/put
cluster:admin/xpack/security/role/delete
cluster:admin/xpack/security/role/get
cluster:admin/xpack/security/role_mapping/put
cluster:admin/xpack/security/role_mapping/delete
cluster:admin/xpack/security/role_mapping/get
cluster:admin/xpack/security/token/create
cluster:admin/xpack/security/token/invalidate
cluster:admin/xpack/watcher/service
cluster:admin/xpack/watcher/watch/delete
cluster:admin/xpack/watcher/watch/execute
cluster:admin/xpack/watcher/watch/put
cluster:admin/xpack/watcher/watch/ack
cluster:admin/xpack/watcher/watch/activate
cluster:monitor/xpack/watcher/watch/get
cluster:monitor/xpack/watcher/stats/dist
internal:indices/admin/upgrade
cluster:admin/ingest/pipeline/delete
cluster:admin/ingest/pipeline/get
cluster:admin/ingest/pipeline/put
cluster:admin/ingest/pipeline/simulate
cluster:admin/xpack/ml/filters/get
cluster:monitor/xpack/ml/job/results/categories/get
cluster:monitor/xpack/ml/job/stats/get
cluster:monitor/xpack/ml/job/results/buckets/get
cluster:monitor/xpack/ml/job/results/overall_buckets/get
cluster:monitor/xpack/ml/job/model_snapshots/get
cluster:monitor/xpack/ml/job/results/records/get
cluster:monitor/xpack/ml/job/results/influencers/get
cluster:internal/xpack/ml/datafeed/isolate
cluster:admin/xpack/ml/datafeeds/preview
cluster:admin/xpack/ml/datafeeds/put
cluster:admin/xpack/ml/datafeeds/update
cluster:admin/xpack/ml/job/model_snapshots/delete
cluster:admin/xpack/ml/job/validate/detector
cluster:admin/xpack/ml/job/validate
cluster:admin/xpack/ml/job/delete
cluster:admin/xpack/ml/job/model_snapshots/revert
cluster:admin/xpack/ml/datafeeds/delete
cluster:admin/xpack/ml/job/data/post
cluster:admin/xpack/ml/job/close
cluster:internal/xpack/ml/job/kill/process
cluster:admin/xpack/ml/filters/put
cluster:admin/xpack/ml/job/put
cluster:monitor/xpack/ml/job/get
cluster:monitor/xpack/ml/datafeeds/get
cluster:admin/xpack/ml/job/model_snapshots/update
cluster:admin/xpack/ml/job/flush
cluster:admin/xpack/ml/filters/delete
cluster:monitor/xpack/ml/datafeeds/stats/get
cluster:admin/xpack/ml/datafeed/stop
cluster:admin/xpack/ml/datafeed/start
cluster:admin/xpack/ml/job/open
cluster:admin/xpack/ml/job/update
cluster:internal/xpack/ml/job/update/process
cluster:admin/xpack/ml/delete_expired_data
cluster:admin/persistent/start
cluster:admin/persistent/completion
cluster:admin/persistent/update_status
cluster:admin/persistent/remove
cluster:internal/xpack/ml/job/finalize_job_execution
cluster:admin/xpack/upgrade/info
cluster:admin/xpack/upgrade
cluster:admin/reindex/rethrottle
indices:data/write/update/byquery
indices:data/write/delete/byquery
indices:data/write/reindex
cluster:admin/xpack/deprecation/info
cluster:admin/xpack/ml/job/forecast
cluster:admin/xpack/license/start_trial
cluster:admin/xpack/license/trial_status

View File

@ -1,138 +0,0 @@
cluster:admin/snapshot/status[nodes]
cluster:admin/snapshot/status[nodes][n]
cluster:admin/tasks/cancel[n]
cluster:monitor/allocation/explain
cluster:monitor/main
cluster:monitor/nodes/hot_threads[n]
cluster:monitor/nodes/info[n]
cluster:monitor/nodes/liveness
cluster:monitor/nodes/stats[n]
cluster:monitor/nodes/usage[n]
cluster:monitor/stats[n]
cluster:monitor/tasks/lists[n]
cluster:admin/xpack/security/realm/cache/clear
cluster:admin/xpack/security/realm/cache/clear[n]
cluster:admin/xpack/security/roles/cache/clear
cluster:admin/xpack/security/roles/cache/clear[n]
cluster:admin/xpack/security/role/put
cluster:admin/xpack/security/role/delete
cluster:admin/xpack/security/role/get
cluster:admin/xpack/security/user/authenticate
cluster:admin/xpack/security/user/change_password
cluster:admin/xpack/security/user/put
cluster:admin/xpack/security/user/delete
cluster:admin/xpack/security/user/get
cluster:admin/xpack/security/user/set_enabled
cluster:admin/xpack/security/token/create
cluster:admin/xpack/security/token/invalidate
indices:admin/analyze[s]
indices:admin/cache/clear[n]
indices:admin/forcemerge[n]
indices:admin/flush[s]
indices:admin/flush[s][p]
indices:admin/flush[s][r]
indices:admin/synced_flush
indices:admin/mappings/fields/get[index]
indices:admin/mappings/fields/get[index][s]
indices:admin/refresh[s]
indices:admin/refresh[s][p]
indices:admin/refresh[s][r]
indices:admin/seq_no/global_checkpoint_sync
indices:admin/seq_no/global_checkpoint_sync[p]
indices:admin/seq_no/global_checkpoint_sync[r]
indices:admin/upgrade
indices:admin/upgrade[n]
indices:admin/validate/query[s]
indices:data/read/explain[s]
indices:data/read/field_caps[index]
indices:data/read/field_caps[index][s]
indices:data/read/get[s]
indices:data/read/xpack/graph/explore
indices:data/read/mget[shard][s]
indices:data/read/mtv[shard][s]
indices:data/read/search[clear_scroll_contexts]
indices:data/read/search[free_context/scroll]
indices:data/read/search[free_context]
indices:data/read/search[phase/dfs]
indices:data/read/search[phase/fetch/id/scroll]
indices:data/read/search[phase/fetch/id]
indices:data/read/search[phase/query+fetch/scroll]
indices:data/read/search[phase/query/id]
indices:data/read/search[phase/query/scroll]
indices:data/read/search[phase/query]
indices:data/read/search[can_match]
internal:transport/proxy/indices:data/read/search[clear_scroll_contexts]
internal:transport/proxy/indices:data/read/search[free_context/scroll]
internal:transport/proxy/indices:data/read/search[free_context]
internal:transport/proxy/indices:data/read/search[phase/dfs]
internal:transport/proxy/indices:data/read/search[phase/fetch/id/scroll]
internal:transport/proxy/indices:data/read/search[phase/fetch/id]
internal:transport/proxy/indices:data/read/search[phase/query+fetch/scroll]
internal:transport/proxy/indices:data/read/search[phase/query/id]
internal:transport/proxy/indices:data/read/search[phase/query/scroll]
internal:transport/proxy/indices:data/read/search[phase/query]
internal:transport/proxy/indices:data/read/search[can_match]
indices:data/read/tv[s]
indices:data/write/bulk[s]
indices:data/write/bulk[s][p]
indices:data/write/bulk[s][r]
indices:data/write/delete
indices:data/write/delete[p]
indices:data/write/delete[r]
indices:data/write/index
indices:data/write/index[p]
indices:data/write/index[r]
indices:data/write/update[s]
indices:monitor/recovery[n]
indices:monitor/segments[n]
indices:monitor/shard_stores
indices:monitor/stats[n]
indices:monitor/upgrade[n]
indices:monitor/upgrade
internal:admin/tasks/ban
internal:cluster/node/mapping/refresh
internal:cluster/nodes/indices/shard/store
internal:cluster/nodes/indices/shard/store[n]
internal:cluster/shard/failure
internal:cluster/shard/started
internal:cluster/snapshot/update_snapshot_status
internal:discovery/zen/fd/master_ping
internal:discovery/zen/fd/ping
internal:discovery/zen/join
internal:discovery/zen/join/validate
internal:discovery/zen/leave
internal:discovery/zen/publish/send
internal:discovery/zen/publish/commit
internal:discovery/zen/rejoin
internal:discovery/zen/unicast
internal:gateway/local/allocate_dangled
internal:gateway/local/meta_state
internal:gateway/local/meta_state[n]
internal:gateway/local/started_shards
internal:gateway/local/started_shards[n]
internal:index/seq_no/resync
internal:index/seq_no/resync[p]
internal:index/seq_no/resync[r]
internal:index/shard/exists
internal:index/shard/recovery/clean_files
internal:index/shard/recovery/file_chunk
internal:index/shard/recovery/filesInfo
internal:index/shard/recovery/finalize
internal:index/shard/recovery/prepare_translog
internal:index/shard/recovery/wait_clusterstate
internal:index/shard/recovery/start_recovery
internal:index/shard/recovery/translog_ops
internal:index/shard/recovery/translog_ops
internal:index/shard/recovery/handoff_primary_context
internal:indices/admin/upgrade
internal:indices/flush/synced/in_flight
internal:indices/flush/synced/pre
internal:indices/flush/synced/sync
internal:admin/repository/verify
internal:transport/handshake
cluster:admin/reindex/rethrottle[n]
cluster:admin/xpack/upgrade
indices:data/write/update/byquery
indices:data/write/delete/byquery
indices:data/write/reindex
cluster:admin/xpack/deprecation/info