diff --git a/elasticsearch-transport-client/src/test/java/org/elasticsearch/xpack/client/PreBuiltXPackTransportClientTests.java b/elasticsearch-transport-client/src/test/java/org/elasticsearch/xpack/client/PreBuiltXPackTransportClientTests.java index cbff866c37c..9dfd86fb306 100644 --- a/elasticsearch-transport-client/src/test/java/org/elasticsearch/xpack/client/PreBuiltXPackTransportClientTests.java +++ b/elasticsearch-transport-client/src/test/java/org/elasticsearch/xpack/client/PreBuiltXPackTransportClientTests.java @@ -22,12 +22,10 @@ public class PreBuiltXPackTransportClientTests extends RandomizedTest { @Test public void testPluginInstalled() { - // TODO: remove when Netty 4.1.6 is upgraded to Netty 4.1.7 including https://github.com/netty/netty/pull/6068 - assumeFalse(Constants.JRE_IS_MINIMUM_JAVA9); try (TransportClient client = new PreBuiltXPackTransportClient(Settings.EMPTY)) { Settings settings = client.settings(); assertEquals(Security.NAME4, NetworkModule.TRANSPORT_TYPE_SETTING.get(settings)); } } -} +} \ No newline at end of file diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/XPackPlugin.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/XPackPlugin.java index 8ebb0158c50..dca131d78bc 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/XPackPlugin.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/XPackPlugin.java @@ -40,7 +40,6 @@ import org.elasticsearch.plugins.ScriptPlugin; import org.elasticsearch.rest.RestHandler; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.threadpool.ExecutorBuilder; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.Transport; @@ -96,7 +95,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.time.Clock; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -221,7 +219,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I @Override public Collection createComponents(Client client, ClusterService clusterService, ThreadPool threadPool, ResourceWatcherService resourceWatcherService, ScriptService scriptService, - SearchRequestParsers searchRequestParsers, NamedXContentRegistry xContentRegistry) { + NamedXContentRegistry xContentRegistry) { List components = new ArrayList<>(); components.add(sslService); @@ -255,7 +253,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I httpTemplateParser, scriptService, httpAuthRegistry); components.addAll(notificationComponents); - components.addAll(watcher.createComponents(getClock(), scriptService, internalClient, searchRequestParsers, licenseState, + components.addAll(watcher.createComponents(getClock(), scriptService, internalClient, licenseState, httpClient, httpTemplateParser, threadPool, clusterService, security.getCryptoService(), xContentRegistry, components)); diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/common/http/HttpProxy.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/common/http/HttpProxy.java index 7c72158d678..74fbf95c778 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/common/http/HttpProxy.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/common/http/HttpProxy.java @@ -7,7 +7,6 @@ package org.elasticsearch.xpack.common.http; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/graph/rest/action/RestGraphAction.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/graph/rest/action/RestGraphAction.java index b2b594eadd6..b9e5e0e466a 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/graph/rest/action/RestGraphAction.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/graph/rest/action/RestGraphAction.java @@ -87,7 +87,7 @@ public class RestGraphAction extends XPackRestHandler { Hop currentHop = graphRequest.createNextHop(null); try (XContentParser parser = request.contentOrSourceParamParser()) { - QueryParseContext context = new QueryParseContext(parser, parseFieldMatcher); + QueryParseContext context = new QueryParseContext(parser); XContentParser.Token token = parser.nextToken(); @@ -115,7 +115,7 @@ public class RestGraphAction extends XPackRestHandler { if (token == XContentParser.Token.START_ARRAY) { if (VERTICES_FIELD.match(fieldName)) { - parseVertices(parser, context, currentHop, graphRequest); + parseVertices(parser, currentHop); } } else if (token == XContentParser.Token.START_OBJECT) { if (QUERY_FIELD.match(fieldName)) { @@ -135,12 +135,10 @@ public class RestGraphAction extends XPackRestHandler { } else { throw new ElasticsearchParseException("Illegal property in graph definition " + fieldName, token.name()); } - } - } - private void parseVertices(XContentParser parser, QueryParseContext context, Hop currentHop, GraphExploreRequest graphRequest) + private void parseVertices(XContentParser parser, Hop currentHop) throws IOException { XContentParser.Token token; @@ -324,7 +322,6 @@ public class RestGraphAction extends XPackRestHandler { } else { throw new ElasticsearchParseException("Unknown object property: [" + fieldName + "]"); } - } } } diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java index 135addf1c5b..ed14720087f 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java @@ -91,7 +91,7 @@ public class Exporters extends AbstractLifecycleComponent implements Iterable state = new AtomicReference<>(State.INITIALIZED); private final AtomicBoolean installingSomething = new AtomicBoolean(false); + private final AtomicBoolean waitedForSetup = new AtomicBoolean(false); public LocalExporter(Exporter.Config config, InternalClient client, ClusterService clusterService, CleanerService cleanerService) { @@ -122,6 +123,7 @@ public class LocalExporter extends Exporter implements ClusterStateListener, Cle public void doClose() { if (state.getAndSet(State.TERMINATED) != State.TERMINATED) { logger.trace("stopped"); + // we also remove the listener in resolveBulk after we get to RUNNING, but it's okay to double-remove clusterService.removeListener(this); cleanerService.remove(this); } @@ -143,17 +145,31 @@ public class LocalExporter extends Exporter implements ClusterStateListener, Cle final Map templates = StreamSupport.stream(new ResolversRegistry(Settings.EMPTY).spliterator(), false) .collect(Collectors.toMap(MonitoringIndexNameResolver::templateName, MonitoringIndexNameResolver::template, (a, b) -> a)); - // if this is not the master, we just need to make sure the master has set things up + boolean setup = true; + + // elected master node needs to setup templates; non-master nodes need to wait for it to be setup if (clusterService.state().nodes().isLocalNodeElectedMaster()) { - if (setupIfElectedMaster(clusterState, templates) == false) { - return null; - } + setup = setupIfElectedMaster(clusterState, templates); } else if (setupIfNotElectedMaster(clusterState, templates.keySet()) == false) { + // the first pass will be false so that we don't bother users if the master took one-go to setup + if (waitedForSetup.getAndSet(true)) { + logger.info("waiting for elected master node [{}] to setup local exporter [{}] (does it have x-pack installed?)", + clusterService.state().nodes().getMasterNode(), config.name()); + } + + setup = false; + } + + // any failure/delay to setup the local exporter stops it until the next pass (10s by default) + if (setup == false) { return null; } if (state.compareAndSet(State.INITIALIZED, State.RUNNING)) { logger.debug("started"); + + // we no longer need to receive cluster state updates + clusterService.removeListener(this); } return new LocalBulk(name(), logger, client, resolvers, config.settings().getAsBoolean(USE_INGEST_PIPELINE_SETTING, true)); diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/notification/email/attachment/ReportingAttachmentParser.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/notification/email/attachment/ReportingAttachmentParser.java index b713d670ca4..fbfe9effb32 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/notification/email/attachment/ReportingAttachmentParser.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/notification/email/attachment/ReportingAttachmentParser.java @@ -8,8 +8,6 @@ package org.elasticsearch.xpack.notification.email.attachment; import org.apache.logging.log4j.Logger; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.ParseFieldMatcher; -import org.elasticsearch.common.ParseFieldMatcherSupplier; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.logging.LoggerMessageFormat; @@ -49,10 +47,9 @@ public class ReportingAttachmentParser implements EmailAttachmentParser RETRIES_SETTING = Setting.intSetting("xpack.notification.reporting.retries", 40, 0, Setting.Property.NodeScope); - private static final ObjectParser PARSER = new ObjectParser<>("reporting_attachment"); - private static final ObjectParser PAYLOAD_PARSER = + private static final ObjectParser PARSER = new ObjectParser<>("reporting_attachment"); + private static final ObjectParser PAYLOAD_PARSER = new ObjectParser<>("reporting_attachment_kibana_payload", true, null); - private static final ParseFieldMatcherSupplier STRICT_PARSING = () -> ParseFieldMatcher.STRICT; static { PARSER.declareInt(Builder::retries, new ParseField("retries")); @@ -88,7 +85,7 @@ public class ReportingAttachmentParser implements EmailAttachmentParser {}; + final ThreadContext.StoredContext toRestore = threadContext.newStoredContext(); final ActionListener signingListener = new ContextPreservingActionListener<>(threadContext, toRestore, ActionListener.wrap(r -> { try { @@ -127,7 +122,9 @@ public class SecurityActionFilter extends AbstractComponent implements ActionFil } }); } else { - applyInternal(action, request, authenticatedListener); + try (ThreadContext.StoredContext ignore = threadContext.newStoredContext()) { + applyInternal(action, request, authenticatedListener); + } } } catch (Exception e) { listener.onFailure(e); diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java index 2688823acff..16b83dfa646 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java @@ -11,12 +11,9 @@ import org.elasticsearch.xpack.security.authz.IndicesAndAliasesResolver; import org.elasticsearch.xpack.security.authz.permission.FieldPermissions; import java.util.Collections; -import java.util.HashSet; import java.util.Map; import java.util.Set; -import static java.util.Collections.unmodifiableSet; - /** * Encapsulates the field and document permissions per concrete index based on the current request. */ diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/ssl/CertificateTool.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/ssl/CertificateTool.java index 37538c22740..2843d40b692 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/ssl/CertificateTool.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/ssl/CertificateTool.java @@ -7,7 +7,6 @@ package org.elasticsearch.xpack.ssl; import joptsimple.OptionSet; import joptsimple.OptionSpec; - import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; @@ -19,11 +18,8 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.cli.EnvironmentAwareCommand; import org.elasticsearch.cli.Terminal; import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.ParseFieldMatcher; -import org.elasticsearch.common.ParseFieldMatcherSupplier; import org.elasticsearch.common.Strings; import org.elasticsearch.common.network.InetAddresses; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.NamedXContentRegistry; @@ -31,9 +27,9 @@ import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.env.Environment; -import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.xpack.XPackPlugin; +import javax.security.auth.x500.X500Principal; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -62,8 +58,6 @@ import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import javax.security.auth.x500.X500Principal; - /** * CLI tool to make generation of certificates or certificate requests easier for users */ @@ -80,9 +74,9 @@ public class CertificateTool extends EnvironmentAwareCommand { Pattern.compile("[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1," + MAX_FILENAME_LENGTH + "}"); private static final int DEFAULT_KEY_SIZE = 2048; - private static final ObjectParser, CertInfoParseContext> PARSER = new ObjectParser<>("certgen"); + private static final ObjectParser, Void> PARSER = new ObjectParser<>("certgen"); static { - ConstructingObjectParser instanceParser = + ConstructingObjectParser instanceParser = new ConstructingObjectParser<>("instances", a -> new CertificateInformation((String) a[0], (String) (a[1] == null ? a[0] : a[1]), (List) a[2], (List) a[3])); @@ -248,7 +242,7 @@ public class CertificateTool extends EnvironmentAwareCommand { try (Reader reader = Files.newBufferedReader(file)) { // EMPTY is safe here because we never use namedObject XContentParser xContentParser = XContentType.YAML.xContent().createParser(NamedXContentRegistry.EMPTY, reader); - return PARSER.parse(xContentParser, new ArrayList<>(), new CertInfoParseContext()); + return PARSER.parse(xContentParser, new ArrayList<>(), null); } } @@ -632,20 +626,6 @@ public class CertificateTool extends EnvironmentAwareCommand { } } - private static class CertInfoParseContext implements ParseFieldMatcherSupplier { - - private final ParseFieldMatcher parseFieldMatcher; - - CertInfoParseContext() { - this.parseFieldMatcher = ParseFieldMatcher.EMPTY; - } - - @Override - public ParseFieldMatcher getParseFieldMatcher() { - return parseFieldMatcher; - } - } - private interface Writer { void write(ZipOutputStream zipOutputStream, JcaPEMWriter pemWriter) throws Exception; } diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java index 65d5c564eaf..6a262cee8c1 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java @@ -32,7 +32,6 @@ import org.elasticsearch.plugins.ScriptPlugin; import org.elasticsearch.rest.RestHandler; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.threadpool.ExecutorBuilder; import org.elasticsearch.threadpool.FixedExecutorBuilder; import org.elasticsearch.threadpool.ThreadPool; @@ -219,7 +218,7 @@ public class Watcher implements ActionPlugin, ScriptPlugin { } public Collection createComponents(Clock clock, ScriptService scriptService, InternalClient internalClient, - SearchRequestParsers searchRequestParsers, XPackLicenseState licenseState, + XPackLicenseState licenseState, HttpClient httpClient, HttpRequestTemplate.Parser httpTemplateParser, ThreadPool threadPool, ClusterService clusterService, CryptoService cryptoService, NamedXContentRegistry xContentRegistry, Collection components) { @@ -237,8 +236,7 @@ public class Watcher implements ActionPlugin, ScriptPlugin { final ConditionRegistry conditionRegistry = new ConditionRegistry(Collections.unmodifiableMap(parsers), clock); final Map transformFactories = new HashMap<>(); transformFactories.put(ScriptTransform.TYPE, new ScriptTransformFactory(settings, scriptService)); - transformFactories.put(SearchTransform.TYPE, new SearchTransformFactory(settings, internalClient, searchRequestParsers, - xContentRegistry, scriptService)); + transformFactories.put(SearchTransform.TYPE, new SearchTransformFactory(settings, internalClient, xContentRegistry, scriptService)); final TransformRegistry transformRegistry = new TransformRegistry(settings, Collections.unmodifiableMap(transformFactories)); final Map actionFactoryMap = new HashMap<>(); @@ -261,7 +259,7 @@ public class Watcher implements ActionPlugin, ScriptPlugin { final Map inputFactories = new HashMap<>(); inputFactories.put(SearchInput.TYPE, - new SearchInputFactory(settings, internalClient, searchRequestParsers, xContentRegistry, scriptService)); + new SearchInputFactory(settings, internalClient, xContentRegistry, scriptService)); inputFactories.put(SimpleInput.TYPE, new SimpleInputFactory(settings)); inputFactories.put(HttpInput.TYPE, new HttpInputFactory(settings, httpClient, templateEngine, httpTemplateParser)); inputFactories.put(NoneInput.TYPE, new NoneInputFactory(settings)); @@ -294,7 +292,7 @@ public class Watcher implements ActionPlugin, ScriptPlugin { final TriggeredWatchStore triggeredWatchStore = new TriggeredWatchStore(settings, watcherClientProxy, triggeredWatchParser); final WatcherSearchTemplateService watcherSearchTemplateService = - new WatcherSearchTemplateService(settings, scriptService, searchRequestParsers, xContentRegistry); + new WatcherSearchTemplateService(settings, scriptService, xContentRegistry); final WatchExecutor watchExecutor = getWatchExecutor(threadPool); final Watch.Parser watchParser = new Watch.Parser(settings, triggerService, registry, inputRegistry, cryptoService, clock); diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/input/search/SearchInputFactory.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/input/search/SearchInputFactory.java index a2941e6a9a8..4a11bd9b027 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/input/search/SearchInputFactory.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/input/search/SearchInputFactory.java @@ -11,7 +11,6 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.watcher.input.InputFactory; import org.elasticsearch.xpack.watcher.input.simple.ExecutableSimpleInput; @@ -25,17 +24,17 @@ public class SearchInputFactory extends InputFactory 0) { try (XContentParser parser = XContentFactory.xContent(source).createParser(xContentRegistry, source)) { - sourceBuilder.parseXContent(new QueryParseContext(parser, parseFieldMatcher)); + sourceBuilder.parseXContent(new QueryParseContext(parser)); searchRequest.source(sourceBuilder); } } diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/transform/search/SearchTransformFactory.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/transform/search/SearchTransformFactory.java index e4ef8ffc035..8e4c9da90a9 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/transform/search/SearchTransformFactory.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/watcher/transform/search/SearchTransformFactory.java @@ -11,7 +11,6 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy; import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService; @@ -24,17 +23,17 @@ public class SearchTransformFactory extends TransformFactory addedNodes) { + public void connectToNodes(Iterable discoveryNodes) { // skip } @Override - public void disconnectFromNodes(List removedNodes) { + public void disconnectFromNodesExcept(Iterable nodesToKeep) { // skip } }); diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterTemplateTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterTemplateTests.java index 96be1c1e5c8..21e0be18fa8 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterTemplateTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterTemplateTests.java @@ -185,9 +185,6 @@ public class LocalExporterTemplateTests extends MonitoringIntegTestCase { .endObject() .startObject("mappings") .startObject("_default_") - .startObject("_all") - .field("enabled", false) - .endObject() .field("date_detection", false) .startObject("properties") .startObject("cluster_uuid") diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilterTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilterTests.java index 8b1c095a431..a0c67677381 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilterTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilterTests.java @@ -5,6 +5,7 @@ */ package org.elasticsearch.xpack.security.action.filter; +import org.apache.lucene.util.SetOnce; import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRequest; @@ -60,6 +61,7 @@ public class SecurityActionFilterTests extends ESTestCase { private AuditTrailService auditTrail; private XPackLicenseState licenseState; private SecurityActionFilter filter; + private ThreadContext threadContext; private boolean failDestructiveOperations; @Before @@ -72,14 +74,17 @@ public class SecurityActionFilterTests extends ESTestCase { when(licenseState.isAuthAllowed()).thenReturn(true); when(licenseState.isStatsAndHealthAllowed()).thenReturn(true); ThreadPool threadPool = mock(ThreadPool.class); - when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY)); + threadContext = new ThreadContext(Settings.EMPTY); + when(threadPool.getThreadContext()).thenReturn(threadContext); failDestructiveOperations = randomBoolean(); Settings settings = Settings.builder() .put(DestructiveOperations.REQUIRES_NAME_SETTING.getKey(), failDestructiveOperations).build(); DestructiveOperations destructiveOperations = new DestructiveOperations(settings, new ClusterSettings(settings, Collections.singleton(DestructiveOperations.REQUIRES_NAME_SETTING))); + + SecurityContext securityContext = new SecurityContext(settings, threadContext, cryptoService); filter = new SecurityActionFilter(Settings.EMPTY, authcService, authzService, cryptoService, auditTrail, - licenseState, new HashSet<>(), threadPool, mock(SecurityContext.class), destructiveOperations); + licenseState, new HashSet<>(), threadPool, securityContext, destructiveOperations); } public void testApply() throws Exception { @@ -108,6 +113,81 @@ public class SecurityActionFilterTests extends ESTestCase { verify(chain).proceed(eq(task), eq("_action"), eq(request), isA(ContextPreservingActionListener.class)); } + public void testApplyRestoresThreadContext() throws Exception { + ActionRequest request = mock(ActionRequest.class); + ActionListener listener = mock(ActionListener.class); + ActionFilterChain chain = mock(ActionFilterChain.class); + Task task = mock(Task.class); + User user = new User("username", "r1", "r2"); + Authentication authentication = new Authentication(user, new RealmRef("test", "test", "foo"), null); + doAnswer((i) -> { + ActionListener callback = + (ActionListener) i.getArguments()[3]; + assertNull(threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + threadContext.putTransient(Authentication.AUTHENTICATION_KEY, authentication); + callback.onResponse(authentication); + return Void.TYPE; + }).when(authcService).authenticate(eq("_action"), eq(request), eq(SystemUser.INSTANCE), any(ActionListener.class)); + final Role empty = Role.EMPTY; + doAnswer((i) -> { + ActionListener callback = + (ActionListener) i.getArguments()[1]; + assertEquals(authentication, threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + callback.onResponse(empty); + return Void.TYPE; + }).when(authzService).roles(any(User.class), any(ActionListener.class)); + doReturn(request).when(spy(filter)).unsign(user, "_action", request); + assertNull(threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + + filter.apply(task, "_action", request, listener, chain); + + assertNull(threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + verify(authzService).authorize(authentication, "_action", request, empty, null); + verify(chain).proceed(eq(task), eq("_action"), eq(request), isA(ContextPreservingActionListener.class)); + } + + public void testApplyAsSystemUser() throws Exception { + ActionRequest request = mock(ActionRequest.class); + ActionListener listener = mock(ActionListener.class); + User user = new User("username", "r1", "r2"); + Authentication authentication = new Authentication(user, new RealmRef("test", "test", "foo"), null); + SetOnce authenticationSetOnce = new SetOnce<>(); + ActionFilterChain chain = (task, action, request1, listener1) -> { + authenticationSetOnce.set(threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + }; + Task task = mock(Task.class); + final boolean hasExistingAuthentication = randomBoolean(); + final String action = "internal:foo"; + if (hasExistingAuthentication) { + threadContext.putTransient(Authentication.AUTHENTICATION_KEY, authentication); + threadContext.putTransient(AuthorizationService.ORIGINATING_ACTION_KEY, "indices:foo"); + } else { + assertNull(threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + } + doAnswer((i) -> { + ActionListener callback = + (ActionListener) i.getArguments()[3]; + callback.onResponse(threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + return Void.TYPE; + }).when(authcService).authenticate(eq(action), eq(request), eq(SystemUser.INSTANCE), any(ActionListener.class)); + doReturn(request).when(spy(filter)).unsign(user, action, request); + doAnswer((i) -> { + String text = (String) i.getArguments()[0]; + return text; + }).when(cryptoService).sign(any(String.class)); + + filter.apply(task, action, request, listener, chain); + + if (hasExistingAuthentication) { + assertEquals(authentication, threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + } else { + assertNull(threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); + } + assertNotNull(authenticationSetOnce.get()); + assertNotEquals(authentication, authenticationSetOnce.get()); + assertEquals(SystemUser.INSTANCE, authenticationSetOnce.get().getUser()); + } + public void testApplyDestructiveOperations() throws Exception { ActionRequest request = new MockIndicesRequest( IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()), diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/throttler/ActionThrottleTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/throttler/ActionThrottleTests.java index 950b7b59692..4213195a009 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/throttler/ActionThrottleTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/throttler/ActionThrottleTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.watcher.actions.throttler; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.xpack.common.http.HttpMethod; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.common.text.TextTemplate; @@ -40,8 +41,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; +import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.indexAction; import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.loggingAction; -import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.webhookAction; import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; @@ -287,8 +288,21 @@ public class ActionThrottleTests extends AbstractWatcherIntegrationTestCase { }, 20, TimeUnit.SECONDS); } - @AwaitsFix(bugUrl = "https://github.com/elastic/x-pack/issues/4561") public void testFailingActionDoesGetThrottled() throws Exception { + // create a mapping with a wrong @timestamp field, so that the index action of the watch below will fail + String mapping = XContentFactory.jsonBuilder() + .startObject() + .startObject("bar") + .startObject("properties") + .startObject("@timestamp") + .field("type", "integer") + .endObject() + .endObject() + .endObject() + .endObject().string(); + + client().admin().indices().prepareCreate("foo").addMapping("bar", mapping).get(); + TimeValue throttlePeriod = new TimeValue(60, TimeUnit.MINUTES); watcherClient().preparePutWatch("_id").setSource(watchBuilder() @@ -296,8 +310,7 @@ public class ActionThrottleTests extends AbstractWatcherIntegrationTestCase { new IntervalSchedule.Interval(60, IntervalSchedule.Interval.Unit.MINUTES)))) .defaultThrottlePeriod(throttlePeriod) .addAction("logging", loggingAction("test out")) - // no DNS resolution here please - .addAction("failing_hook", webhookAction(HttpRequestTemplate.builder("http://127.0.0.1/foobar", 80)))) + .addAction("failing_hook", indexAction("foo", "bar").setExecutionTimeField("@timestamp"))) .get(); refresh(Watch.INDEX); diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchInputTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchInputTests.java index 81f7d3ffdbd..af1a9ba5b6e 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchInputTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchInputTests.java @@ -17,7 +17,6 @@ import org.elasticsearch.plugins.ScriptPlugin; import org.elasticsearch.script.MockMustacheScriptEngine; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; @@ -144,9 +143,8 @@ public class SearchInputTests extends ESIntegTestCase { XContentParser parser = createParser(builder); parser.nextToken(); - SearchRequestParsers searchParsers = new SearchRequestParsers(); SearchInputFactory factory = new SearchInputFactory(Settings.EMPTY, WatcherClientProxy.of(client()), - searchParsers, xContentRegistry(), scriptService()); + xContentRegistry(), scriptService()); SearchInput searchInput = factory.parseInput("_id", parser); assertEquals(SearchInput.TYPE, searchInput.type()); @@ -157,7 +155,6 @@ public class SearchInputTests extends ESIntegTestCase { String master = internalCluster().getMasterName(); return new WatcherSearchTemplateService(internalCluster().clusterService(master).getSettings(), internalCluster().getInstance(ScriptService.class, master), - internalCluster().getInstance(SearchRequestParsers.class, master), internalCluster().getInstance(NamedXContentRegistry.class, master) ); } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchTransformTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchTransformTests.java index 378fd43555a..ada4eb09c1e 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchTransformTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/SearchTransformTests.java @@ -21,7 +21,6 @@ import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptType; -import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; @@ -212,9 +211,8 @@ public class SearchTransformTests extends ESIntegTestCase { XContentParser parser = createParser(builder); parser.nextToken(); - SearchRequestParsers searchRequestParsers = internalCluster().getInstance(SearchRequestParsers.class); SearchTransformFactory transformFactory = new SearchTransformFactory(Settings.EMPTY, WatcherClientProxy.of(client()), - searchRequestParsers, xContentRegistry(), scriptService()); + xContentRegistry(), scriptService()); ExecutableSearchTransform executable = transformFactory.parseExecutable("_id", parser); assertThat(executable, notNullValue()); @@ -284,7 +282,6 @@ public class SearchTransformTests extends ESIntegTestCase { String master = internalCluster().getMasterName(); return new WatcherSearchTemplateService(internalCluster().clusterService(master).getSettings(), internalCluster().getInstance(ScriptService.class, master), - internalCluster().getInstance(SearchRequestParsers.class, master), xContentRegistry() ); } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java index 415f85123e2..537f420b96a 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java @@ -23,7 +23,6 @@ import org.elasticsearch.index.query.ScriptQueryBuilder; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.common.http.HttpClient; import org.elasticsearch.xpack.common.http.HttpMethod; @@ -288,9 +287,7 @@ public class WatchTests extends ESTestCase { ActionRegistry actionRegistry = registry(Collections.emptyList(), conditionRegistry, transformRegistry); Watch.Parser watchParser = new Watch.Parser(settings, triggerService, actionRegistry, inputRegistry, null, Clock.systemUTC()); - SearchRequestParsers searchParsers = new SearchRequestParsers(); - WatcherSearchTemplateService searchTemplateService = new WatcherSearchTemplateService(settings, scriptService, searchParsers, - xContentRegistry()); + WatcherSearchTemplateService searchTemplateService = new WatcherSearchTemplateService(settings, scriptService, xContentRegistry()); XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); @@ -409,8 +406,7 @@ public class WatchTests extends ESTestCase { Map parsers = new HashMap<>(); switch (inputType) { case SearchInput.TYPE: - SearchRequestParsers searchParsers = new SearchRequestParsers(); - parsers.put(SearchInput.TYPE, new SearchInputFactory(settings, client, searchParsers, xContentRegistry(), scriptService)); + parsers.put(SearchInput.TYPE, new SearchInputFactory(settings, client, xContentRegistry(), scriptService)); return new InputRegistry(Settings.EMPTY, parsers); default: parsers.put(SimpleInput.TYPE, new SimpleInputFactory(settings)); @@ -457,10 +453,9 @@ public class WatchTests extends ESTestCase { } private TransformRegistry transformRegistry() { - SearchRequestParsers searchParsers = new SearchRequestParsers(); Map factories = new HashMap<>(); factories.put(ScriptTransform.TYPE, new ScriptTransformFactory(settings, scriptService)); - factories.put(SearchTransform.TYPE, new SearchTransformFactory(settings, client, searchParsers, xContentRegistry(), scriptService)); + factories.put(SearchTransform.TYPE, new SearchTransformFactory(settings, client, xContentRegistry(), scriptService)); return new TransformRegistry(Settings.EMPTY, unmodifiableMap(factories)); } diff --git a/elasticsearch/src/test/resources/indices/bwc/x-pack-5.1.2.zip b/elasticsearch/src/test/resources/indices/bwc/x-pack-5.1.2.zip new file mode 100644 index 00000000000..aaafdfebf3d Binary files /dev/null and b/elasticsearch/src/test/resources/indices/bwc/x-pack-5.1.2.zip differ