瀏覽代碼

Move RestWrapper to interceptor.RestInterceptor (#86784)

Chris Hegarty 3 年之前
父節點
當前提交
95c81c8837

+ 20 - 17
server/src/main/java/org/elasticsearch/action/ActionModule.java

@@ -271,6 +271,7 @@ import org.elasticsearch.persistent.StartPersistentTaskAction;
 import org.elasticsearch.persistent.UpdatePersistentTaskStatusAction;
 import org.elasticsearch.plugins.ActionPlugin;
 import org.elasticsearch.plugins.ActionPlugin.ActionHandler;
+import org.elasticsearch.plugins.interceptor.RestInterceptorActionPlugin;
 import org.elasticsearch.rest.RestController;
 import org.elasticsearch.rest.RestHandler;
 import org.elasticsearch.rest.RestHeaderDefinition;
@@ -477,24 +478,26 @@ public class ActionModule extends AbstractModule {
                 new RestHeaderDefinition(Task.X_ELASTIC_PRODUCT_ORIGIN_HTTP_HEADER, false)
             )
         ).collect(Collectors.toSet());
-        UnaryOperator<RestHandler> restWrapper = null;
+        UnaryOperator<RestHandler> restInterceptor = null;
         for (ActionPlugin plugin : actionPlugins) {
-            UnaryOperator<RestHandler> newRestWrapper = plugin.getRestHandlerWrapper(threadPool.getThreadContext());
-            if (newRestWrapper != null) {
-                logger.debug("Using REST wrapper from plugin " + plugin.getClass().getName());
-                if (plugin.getClass().getCanonicalName() == null
-                    || plugin.getClass().getCanonicalName().startsWith("org.elasticsearch.xpack") == false) {
-                    throw new IllegalArgumentException(
-                        "The "
-                            + plugin.getClass().getName()
-                            + " plugin tried to install a custom REST "
-                            + "wrapper. This functionality is not available anymore."
-                    );
+            if (plugin instanceof RestInterceptorActionPlugin riplugin) {
+                UnaryOperator<RestHandler> newRestInterceptor = riplugin.getRestHandlerInterceptor(threadPool.getThreadContext());
+                if (newRestInterceptor != null) {
+                    logger.debug("Using REST interceptor from plugin " + plugin.getClass().getName());
+                    if (plugin.getClass().getCanonicalName() == null
+                        || plugin.getClass().getCanonicalName().startsWith("org.elasticsearch.xpack") == false) {
+                        throw new IllegalArgumentException(
+                            "The "
+                                + plugin.getClass().getName()
+                                + " plugin tried to install a custom REST "
+                                + "interceptor. This functionality is not available anymore."
+                        );
+                    }
+                    if (restInterceptor != null) {
+                        throw new IllegalArgumentException("Cannot have more than one plugin implementing a REST interceptor");
+                    }
+                    restInterceptor = newRestInterceptor;
                 }
-                if (restWrapper != null) {
-                    throw new IllegalArgumentException("Cannot have more than one plugin implementing a REST wrapper");
-                }
-                restWrapper = newRestWrapper;
             }
         }
         mappingRequestValidators = new RequestValidators<>(
@@ -504,7 +507,7 @@ public class ActionModule extends AbstractModule {
             actionPlugins.stream().flatMap(p -> p.indicesAliasesRequestValidators().stream()).toList()
         );
 
-        restController = new RestController(headers, restWrapper, nodeClient, circuitBreakerService, usageService);
+        restController = new RestController(headers, restInterceptor, nodeClient, circuitBreakerService, usageService);
     }
 
     public Map<String, ActionHandler<?, ?>> getActions() {

+ 0 - 27
server/src/main/java/org/elasticsearch/plugins/ActionPlugin.java

@@ -22,7 +22,6 @@ import org.elasticsearch.common.settings.ClusterSettings;
 import org.elasticsearch.common.settings.IndexScopedSettings;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.settings.SettingsFilter;
-import org.elasticsearch.common.util.concurrent.ThreadContext;
 import org.elasticsearch.rest.RestController;
 import org.elasticsearch.rest.RestHandler;
 import org.elasticsearch.rest.RestHeaderDefinition;
@@ -32,7 +31,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.function.Supplier;
-import java.util.function.UnaryOperator;
 
 /**
  * An additional extension point for {@link Plugin}s that extends Elasticsearch's scripting functionality. Implement it like this:
@@ -98,31 +96,6 @@ public interface ActionPlugin {
         return Collections.emptyList();
     }
 
-    /**
-     * Returns a function used to wrap each rest request before handling the request.
-     * The returned {@link UnaryOperator} is called for every incoming rest request and receives
-     * the original rest handler as it's input. This allows adding arbitrary functionality around
-     * rest request handlers to do for instance logging or authentication.
-     * A simple example of how to only allow GET request is here:
-     * <pre>
-     * {@code
-     *    UnaryOperator<RestHandler> getRestHandlerWrapper(ThreadContext threadContext) {
-     *      return originalHandler -> (RestHandler) (request, channel, client) -> {
-     *        if (request.method() != Method.GET) {
-     *          throw new IllegalStateException("only GET requests are allowed");
-     *        }
-     *        originalHandler.handleRequest(request, channel, client);
-     *      };
-     *    }
-     * }
-     * </pre>
-     *
-     * Note: Only one installed plugin may implement a rest wrapper.
-     */
-    default UnaryOperator<RestHandler> getRestHandlerWrapper(ThreadContext threadContext) {
-        return null;
-    }
-
     final class ActionHandler<Request extends ActionRequest, Response extends ActionResponse> {
         private final ActionType<Response> action;
         private final Class<? extends TransportAction<Request, Response>> transportAction;

+ 44 - 0
server/src/main/java/org/elasticsearch/plugins/interceptor/RestInterceptorActionPlugin.java

@@ -0,0 +1,44 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.plugins.interceptor;
+
+import org.elasticsearch.common.util.concurrent.ThreadContext;
+import org.elasticsearch.plugins.ActionPlugin;
+import org.elasticsearch.rest.RestHandler;
+
+import java.util.function.UnaryOperator;
+
+/**
+ * An action plugin that intercepts incoming the REST requests.
+ */
+public interface RestInterceptorActionPlugin extends ActionPlugin {
+
+    /**
+     * Returns a function used to intercept each rest request before handling the request.
+     * The returned {@link UnaryOperator} is called for every incoming rest request and receives
+     * the original rest handler as it's input. This allows adding arbitrary functionality around
+     * rest request handlers to do for instance logging or authentication.
+     * A simple example of how to only allow GET request is here:
+     * <pre>
+     * {@code
+     *    UnaryOperator<RestHandler> getRestHandlerInterceptor(ThreadContext threadContext) {
+     *      return originalHandler -> (RestHandler) (request, channel, client) -> {
+     *        if (request.method() != Method.GET) {
+     *          throw new IllegalStateException("only GET requests are allowed");
+     *        }
+     *        originalHandler.handleRequest(request, channel, client);
+     *      };
+     *    }
+     * }
+     * </pre>
+     *
+     * Note: Only one installed plugin may implement a rest interceptor.
+     */
+    UnaryOperator<RestHandler> getRestHandlerInterceptor(ThreadContext threadContext);
+}

+ 4 - 3
server/src/test/java/org/elasticsearch/action/ActionModuleTests.java

@@ -24,6 +24,7 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
 import org.elasticsearch.indices.TestIndexNameExpressionResolver;
 import org.elasticsearch.plugins.ActionPlugin;
 import org.elasticsearch.plugins.ActionPlugin.ActionHandler;
+import org.elasticsearch.plugins.interceptor.RestInterceptorActionPlugin;
 import org.elasticsearch.rest.RestChannel;
 import org.elasticsearch.rest.RestController;
 import org.elasticsearch.rest.RestHandler;
@@ -271,7 +272,7 @@ public class ActionModuleTests extends ESTestCase {
                 e.getMessage(),
                 Matchers.equalTo(
                     "The org.elasticsearch.action.ActionModuleTests$SecPlugin plugin tried to "
-                        + "install a custom REST wrapper. This functionality is not available anymore."
+                        + "install a custom REST interceptor. This functionality is not available anymore."
                 )
             );
         } finally {
@@ -289,9 +290,9 @@ public class ActionModuleTests extends ESTestCase {
         public void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception {}
     }
 
-    class SecPlugin implements ActionPlugin {
+    class SecPlugin implements ActionPlugin, RestInterceptorActionPlugin {
         @Override
-        public UnaryOperator<RestHandler> getRestHandlerWrapper(ThreadContext threadContext) {
+        public UnaryOperator<RestHandler> getRestHandlerInterceptor(ThreadContext threadContext) {
             return UnaryOperator.identity();
         }
     };

+ 7 - 3
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/LocalStateCompositeXPackPlugin.java

@@ -76,6 +76,7 @@ import org.elasticsearch.plugins.ScriptPlugin;
 import org.elasticsearch.plugins.SearchPlugin;
 import org.elasticsearch.plugins.ShutdownAwarePlugin;
 import org.elasticsearch.plugins.SystemIndexPlugin;
+import org.elasticsearch.plugins.interceptor.RestInterceptorActionPlugin;
 import org.elasticsearch.repositories.RepositoriesService;
 import org.elasticsearch.repositories.Repository;
 import org.elasticsearch.rest.RestController;
@@ -130,7 +131,8 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin
         IndexStorePlugin,
         SystemIndexPlugin,
         SearchPlugin,
-        ShutdownAwarePlugin {
+        ShutdownAwarePlugin,
+        RestInterceptorActionPlugin {
 
     private XPackLicenseState licenseState;
     private SSLService sslService;
@@ -430,11 +432,13 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin
     }
 
     @Override
-    public UnaryOperator<RestHandler> getRestHandlerWrapper(ThreadContext threadContext) {
+    public UnaryOperator<RestHandler> getRestHandlerInterceptor(ThreadContext threadContext) {
 
         // There can be only one.
         List<UnaryOperator<RestHandler>> items = filterPlugins(ActionPlugin.class).stream()
-            .map(p -> p.getRestHandlerWrapper(threadContext))
+            .filter(RestInterceptorActionPlugin.class::isInstance)
+            .map(RestInterceptorActionPlugin.class::cast)
+            .map(p -> p.getRestHandlerInterceptor(threadContext))
             .filter(Objects::nonNull)
             .collect(Collectors.toList());
 

+ 4 - 2
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java

@@ -65,6 +65,7 @@ import org.elasticsearch.plugins.NetworkPlugin;
 import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.plugins.SearchPlugin;
 import org.elasticsearch.plugins.SystemIndexPlugin;
+import org.elasticsearch.plugins.interceptor.RestInterceptorActionPlugin;
 import org.elasticsearch.repositories.RepositoriesService;
 import org.elasticsearch.rest.RestController;
 import org.elasticsearch.rest.RestHandler;
@@ -366,7 +367,8 @@ public class Security extends Plugin
         DiscoveryPlugin,
         MapperPlugin,
         ExtensiblePlugin,
-        SearchPlugin {
+        SearchPlugin,
+        RestInterceptorActionPlugin {
 
     public static final String SECURITY_CRYPTO_THREAD_POOL_NAME = XPackField.SECURITY + "-crypto";
 
@@ -1528,7 +1530,7 @@ public class Security extends Plugin
     }
 
     @Override
-    public UnaryOperator<RestHandler> getRestHandlerWrapper(ThreadContext threadContext) {
+    public UnaryOperator<RestHandler> getRestHandlerInterceptor(ThreadContext threadContext) {
         final boolean extractClientCertificate;
         if (enabled && HTTP_SSL_ENABLED.get(settings)) {
             final SslConfiguration httpSSLConfig = getSslService().getHttpTransportSSLConfiguration();

+ 7 - 7
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java

@@ -651,7 +651,7 @@ public class SecurityTests extends ESTestCase {
         }
     }
 
-    public void testSecurityPluginInstallsRestHandlerWrapperEvenIfSecurityIsDisabled() throws IllegalAccessException {
+    public void testSecurityPluginInstallsRestHandlerInterceptorEvenIfSecurityIsDisabled() throws IllegalAccessException {
         Settings settings = Settings.builder().put("xpack.security.enabled", false).put("path.home", createTempDir()).build();
         SettingsModule settingsModule = new SettingsModule(Settings.EMPTY);
         ThreadPool threadPool = new TestThreadPool(getTestName());
@@ -659,7 +659,7 @@ public class SecurityTests extends ESTestCase {
         try {
             UsageService usageService = new UsageService();
             Security security = new Security(settings);
-            assertTrue(security.getRestHandlerWrapper(threadPool.getThreadContext()) != null);
+            assertTrue(security.getRestHandlerInterceptor(threadPool.getThreadContext()) != null);
 
         } finally {
             threadPool.shutdown();
@@ -667,7 +667,7 @@ public class SecurityTests extends ESTestCase {
 
     }
 
-    public void testSecurityRestHandlerWrapperCanBeInstalled() throws IllegalAccessException {
+    public void testSecurityRestHandlerInterceptorCanBeInstalled() throws IllegalAccessException {
         final Logger amLogger = LogManager.getLogger(ActionModule.class);
         Loggers.setLevel(amLogger, Level.DEBUG);
         final MockLogAppender appender = new MockLogAppender();
@@ -682,14 +682,14 @@ public class SecurityTests extends ESTestCase {
             UsageService usageService = new UsageService();
             Security security = new Security(settings);
 
-            // Verify Security rest wrapper is about to be installed
-            // We will throw later if another wrapper is already installed
+            // Verify Security rest interceptor is about to be installed
+            // We will throw later if another interceptor is already installed
             appender.addExpectation(
                 new MockLogAppender.SeenEventExpectation(
-                    "Security rest wrapper",
+                    "Security rest interceptor",
                     ActionModule.class.getName(),
                     Level.DEBUG,
-                    "Using REST wrapper from plugin org.elasticsearch.xpack.security.Security"
+                    "Using REST interceptor from plugin org.elasticsearch.xpack.security.Security"
                 )
             );