mirror of https://github.com/apache/druid.git
Router: Authorize permissionless internal requests. (#16419)
* Router: Authorize permissionless internal requests. Router-internal requests like /proxy/enabled and errors for invalid requests should not require permissions, but they still need to be authorized in order to satisfy the PreResponseAuthorizationCheckFilter. This patch adds authorization checks that do not require any particular permissions. * Fix tests.
This commit is contained in:
parent
1040a29bc5
commit
717e634156
|
@ -32,6 +32,8 @@ import org.apache.druid.guice.http.DruidHttpClientConfig;
|
||||||
import org.apache.druid.java.util.common.StringUtils;
|
import org.apache.druid.java.util.common.StringUtils;
|
||||||
import org.apache.druid.server.initialization.jetty.StandardResponseHeaderFilterHolder;
|
import org.apache.druid.server.initialization.jetty.StandardResponseHeaderFilterHolder;
|
||||||
import org.apache.druid.server.security.AuthConfig;
|
import org.apache.druid.server.security.AuthConfig;
|
||||||
|
import org.apache.druid.server.security.AuthorizationUtils;
|
||||||
|
import org.apache.druid.server.security.AuthorizerMapper;
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.api.Response;
|
import org.eclipse.jetty.client.api.Response;
|
||||||
|
@ -41,6 +43,7 @@ import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
||||||
|
@ -71,6 +74,7 @@ public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
||||||
private final DruidHttpClientConfig httpClientConfig;
|
private final DruidHttpClientConfig httpClientConfig;
|
||||||
private final DruidLeaderSelector coordLeaderSelector;
|
private final DruidLeaderSelector coordLeaderSelector;
|
||||||
private final DruidLeaderSelector overlordLeaderSelector;
|
private final DruidLeaderSelector overlordLeaderSelector;
|
||||||
|
private final AuthorizerMapper authorizerMapper;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AsyncManagementForwardingServlet(
|
public AsyncManagementForwardingServlet(
|
||||||
|
@ -78,7 +82,8 @@ public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
||||||
@Global Provider<HttpClient> httpClientProvider,
|
@Global Provider<HttpClient> httpClientProvider,
|
||||||
@Global DruidHttpClientConfig httpClientConfig,
|
@Global DruidHttpClientConfig httpClientConfig,
|
||||||
@Coordinator DruidLeaderSelector coordLeaderSelector,
|
@Coordinator DruidLeaderSelector coordLeaderSelector,
|
||||||
@IndexingService DruidLeaderSelector overlordLeaderSelector
|
@IndexingService DruidLeaderSelector overlordLeaderSelector,
|
||||||
|
AuthorizerMapper authorizerMapper
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.jsonMapper = jsonMapper;
|
this.jsonMapper = jsonMapper;
|
||||||
|
@ -86,6 +91,7 @@ public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
||||||
this.httpClientConfig = httpClientConfig;
|
this.httpClientConfig = httpClientConfig;
|
||||||
this.coordLeaderSelector = coordLeaderSelector;
|
this.coordLeaderSelector = coordLeaderSelector;
|
||||||
this.overlordLeaderSelector = overlordLeaderSelector;
|
this.overlordLeaderSelector = overlordLeaderSelector;
|
||||||
|
this.authorizerMapper = authorizerMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -110,9 +116,11 @@ public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
||||||
request.getRequestURI().substring(ARBITRARY_OVERLORD_BASE_PATH.length())
|
request.getRequestURI().substring(ARBITRARY_OVERLORD_BASE_PATH.length())
|
||||||
);
|
);
|
||||||
} else if (ENABLED_PATH.equals(requestURI)) {
|
} else if (ENABLED_PATH.equals(requestURI)) {
|
||||||
|
authorizeNoPermissionsNeeded(request);
|
||||||
handleEnabledRequest(response);
|
handleEnabledRequest(response);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
authorizeNoPermissionsNeeded(request);
|
||||||
handleInvalidRequest(
|
handleInvalidRequest(
|
||||||
response,
|
response,
|
||||||
StringUtils.format("Unsupported proxy destination[%s]", request.getRequestURI()),
|
StringUtils.format("Unsupported proxy destination[%s]", request.getRequestURI()),
|
||||||
|
@ -122,6 +130,7 @@ public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentLeader == null) {
|
if (currentLeader == null) {
|
||||||
|
authorizeNoPermissionsNeeded(request);
|
||||||
handleInvalidRequest(
|
handleInvalidRequest(
|
||||||
response,
|
response,
|
||||||
StringUtils.format(
|
StringUtils.format(
|
||||||
|
@ -191,6 +200,14 @@ public class AsyncManagementForwardingServlet extends AsyncProxyServlet
|
||||||
super.onServerResponseHeaders(clientRequest, proxyResponse, serverResponse);
|
super.onServerResponseHeaders(clientRequest, proxyResponse, serverResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorizes router-internal requests that do not require any permissions. (But do require an authenticated user.)
|
||||||
|
*/
|
||||||
|
private void authorizeNoPermissionsNeeded(HttpServletRequest request)
|
||||||
|
{
|
||||||
|
AuthorizationUtils.authorizeAllResourceActions(request, Collections.emptyList(), authorizerMapper);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleInvalidRequest(HttpServletResponse response, String errorMessage, int statusCode) throws IOException
|
private void handleInvalidRequest(HttpServletResponse response, String errorMessage, int statusCode) throws IOException
|
||||||
{
|
{
|
||||||
if (!response.isCommitted()) {
|
if (!response.isCommitted()) {
|
||||||
|
|
|
@ -39,6 +39,10 @@ import org.apache.druid.server.initialization.BaseJettyTest;
|
||||||
import org.apache.druid.server.initialization.ServerConfig;
|
import org.apache.druid.server.initialization.ServerConfig;
|
||||||
import org.apache.druid.server.initialization.jetty.JettyServerInitUtils;
|
import org.apache.druid.server.initialization.jetty.JettyServerInitUtils;
|
||||||
import org.apache.druid.server.initialization.jetty.JettyServerInitializer;
|
import org.apache.druid.server.initialization.jetty.JettyServerInitializer;
|
||||||
|
import org.apache.druid.server.security.AllowAllAuthenticator;
|
||||||
|
import org.apache.druid.server.security.AllowAllAuthorizer;
|
||||||
|
import org.apache.druid.server.security.AuthenticationUtils;
|
||||||
|
import org.apache.druid.server.security.AuthorizerMapper;
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
|
@ -321,7 +325,7 @@ public class AsyncManagementForwardingServletTest extends BaseJettyTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProxyEnebledCheck() throws Exception
|
public void testProxyEnabledCheck() throws Exception
|
||||||
{
|
{
|
||||||
HttpURLConnection connection = ((HttpURLConnection)
|
HttpURLConnection connection = ((HttpURLConnection)
|
||||||
new URL(StringUtils.format("http://localhost:%d/proxy/enabled", port)).openConnection());
|
new URL(StringUtils.format("http://localhost:%d/proxy/enabled", port)).openConnection());
|
||||||
|
@ -491,7 +495,8 @@ public class AsyncManagementForwardingServletTest extends BaseJettyTest
|
||||||
injector.getProvider(HttpClient.class),
|
injector.getProvider(HttpClient.class),
|
||||||
injector.getInstance(DruidHttpClientConfig.class),
|
injector.getInstance(DruidHttpClientConfig.class),
|
||||||
coordinatorLeaderSelector,
|
coordinatorLeaderSelector,
|
||||||
overlordLeaderSelector
|
overlordLeaderSelector,
|
||||||
|
new AuthorizerMapper(ImmutableMap.of("allowAll", new AllowAllAuthorizer()))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -502,6 +507,7 @@ public class AsyncManagementForwardingServletTest extends BaseJettyTest
|
||||||
root.addServlet(holder, "/druid/indexer/*");
|
root.addServlet(holder, "/druid/indexer/*");
|
||||||
root.addServlet(holder, "/proxy/*");
|
root.addServlet(holder, "/proxy/*");
|
||||||
|
|
||||||
|
AuthenticationUtils.addAuthenticationFilterChain(root, ImmutableList.of(new AllowAllAuthenticator()));
|
||||||
JettyServerInitUtils.addExtensionFilters(root, injector);
|
JettyServerInitUtils.addExtensionFilters(root, injector);
|
||||||
|
|
||||||
final HandlerList handlerList = new HandlerList();
|
final HandlerList handlerList = new HandlerList();
|
||||||
|
|
Loading…
Reference in New Issue