Add unsecured /health endpoint, remove auth checks from isLeader (#5087)

* Add unsecured /health endpoint, remove auth checks from isLeader

* PR comments
This commit is contained in:
Jonathan Wei 2017-11-15 12:41:30 -08:00 committed by Himanshu
parent 7722401cb3
commit af44d1142b
9 changed files with 74 additions and 9 deletions

View File

@ -179,9 +179,11 @@ public class OverlordResource
return Response.ok(taskMaster.getCurrentLeader()).build(); return Response.ok(taskMaster.getCurrentLeader()).build();
} }
/**
* This is an unsecured endpoint, defined as such in UNSECURED_PATHS in CliOverlord
*/
@GET @GET
@Path("/isLeader") @Path("/isLeader")
@ResourceFilters(StateResourceFilter.class)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response isLeader() public Response isLeader()
{ {

View File

@ -38,16 +38,28 @@ import java.util.List;
/** /**
*/ */
@Path("/status") @Path("/status")
@ResourceFilters(StateResourceFilter.class)
public class StatusResource public class StatusResource
{ {
@GET @GET
@ResourceFilters(StateResourceFilter.class)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Status doGet() public Status doGet()
{ {
return new Status(Initialization.getLoadedImplementations(DruidModule.class)); return new Status(Initialization.getLoadedImplementations(DruidModule.class));
} }
/**
* This is an unsecured endpoint, defined as such in UNSECURED_PATHS in the service initiailization files
* (e.g. CliOverlord, CoordinatorJettyServerInitializer)
*/
@GET
@Path("/health")
@Produces(MediaType.APPLICATION_JSON)
public boolean getHealth()
{
return true;
}
public static class Status public static class Status
{ {
final String version; final String version;

View File

@ -41,7 +41,6 @@ import java.util.Map;
/** /**
*/ */
@Path("/druid/coordinator/v1") @Path("/druid/coordinator/v1")
@ResourceFilters(StateResourceFilter.class)
public class CoordinatorResource public class CoordinatorResource
{ {
private final DruidCoordinator coordinator; private final DruidCoordinator coordinator;
@ -56,12 +55,16 @@ public class CoordinatorResource
@GET @GET
@Path("/leader") @Path("/leader")
@ResourceFilters(StateResourceFilter.class)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response getLeader() public Response getLeader()
{ {
return Response.ok(coordinator.getCurrentLeader()).build(); return Response.ok(coordinator.getCurrentLeader()).build();
} }
/**
* This is an unsecured endpoint, defined as such in UNSECURED_PATHS in CoordinatorJettyServerInitializer
*/
@GET @GET
@Path("/isLeader") @Path("/isLeader")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ -78,6 +81,7 @@ public class CoordinatorResource
@GET @GET
@Path("/loadstatus") @Path("/loadstatus")
@ResourceFilters(StateResourceFilter.class)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response getLoadStatus( public Response getLoadStatus(
@QueryParam("simple") String simple, @QueryParam("simple") String simple,
@ -96,6 +100,7 @@ public class CoordinatorResource
@GET @GET
@Path("/loadqueue") @Path("/loadqueue")
@ResourceFilters(StateResourceFilter.class)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response getLoadQueue( public Response getLoadQueue(
@QueryParam("simple") String simple, @QueryParam("simple") String simple,

View File

@ -27,6 +27,10 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import java.io.IOException; import java.io.IOException;
/**
* Sets necessary request attributes for requests sent to endpoints that don't need authentication or
* authorization checks. This Filter is placed before all Authenticators in the filter chain.
*/
public class UnsecuredResourceFilter implements Filter public class UnsecuredResourceFilter implements Filter
{ {
@Override @Override
@ -40,6 +44,14 @@ public class UnsecuredResourceFilter implements Filter
ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain
) throws IOException, ServletException ) throws IOException, ServletException
{ {
// PreResponseAuthorizationCheckFilter checks that this attribute is set,
// but the value doesn't matter since we skip authorization checks for requests that go through this filter
servletRequest.setAttribute(
AuthConfig.DRUID_AUTHENTICATION_RESULT,
new AuthenticationResult(AuthConfig.ALLOW_ALL_NAME, AuthConfig.ALLOW_ALL_NAME, null)
);
// This request will not go to an Authorizer, so we need to set this for PreResponseAuthorizationCheckFilter
servletRequest.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); servletRequest.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true);
filterChain.doFilter(servletRequest, servletResponse); filterChain.doFilter(servletRequest, servletResponse);
} }

View File

@ -121,7 +121,9 @@ public class CliOverlord extends ServerRunnable
"/console.html", "/console.html",
"/old-console/*", "/old-console/*",
"/images/*", "/images/*",
"/js/*" "/js/*",
"/druid/indexer/v1/isLeader",
"/status/health"
); );
public CliOverlord() public CliOverlord()
@ -320,13 +322,15 @@ public class CliOverlord extends ServerRunnable
List<Authenticator> authenticators = null; List<Authenticator> authenticators = null;
AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper); AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper);
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
authenticators = authenticatorMapper.getAuthenticatorChain(); authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators); AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);
JettyServerInitUtils.addExtensionFilters(root, injector); JettyServerInitUtils.addExtensionFilters(root, injector);
// perform no-op authorization for these static resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
// Check that requests were authorized before sending responses // Check that requests were authorized before sending responses
AuthenticationUtils.addPreResponseAuthorizationCheckFilter( AuthenticationUtils.addPreResponseAuthorizationCheckFilter(

View File

@ -62,7 +62,9 @@ class CoordinatorJettyServerInitializer implements JettyServerInitializer
"/fonts/*", "/fonts/*",
"/old-console/*", "/old-console/*",
"/coordinator/false", "/coordinator/false",
"/overlord/false" "/overlord/false",
"/status/health",
"/druid/coordinator/v1/isLeader"
); );
private static Logger log = new Logger(CoordinatorJettyServerInitializer.class); private static Logger log = new Logger(CoordinatorJettyServerInitializer.class);
@ -112,13 +114,15 @@ class CoordinatorJettyServerInitializer implements JettyServerInitializer
List<Authenticator> authenticators = null; List<Authenticator> authenticators = null;
AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper); AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper);
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
authenticators = authenticatorMapper.getAuthenticatorChain(); authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators); AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);
JettyServerInitUtils.addExtensionFilters(root, injector); JettyServerInitUtils.addExtensionFilters(root, injector);
// perform no-op authorization for these static resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
// Check that requests were authorized before sending responses // Check that requests were authorized before sending responses
AuthenticationUtils.addPreResponseAuthorizationCheckFilter( AuthenticationUtils.addPreResponseAuthorizationCheckFilter(

View File

@ -20,6 +20,7 @@
package io.druid.cli; package io.druid.cli;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.servlet.GuiceFilter; import com.google.inject.servlet.GuiceFilter;
@ -47,6 +48,10 @@ class MiddleManagerJettyServerInitializer implements JettyServerInitializer
{ {
private static Logger log = new Logger(MiddleManagerJettyServerInitializer.class); private static Logger log = new Logger(MiddleManagerJettyServerInitializer.class);
private static List<String> UNSECURED_PATHS = Lists.newArrayList(
"/status/health"
);
@Override @Override
public void initialize(Server server, Injector injector) public void initialize(Server server, Injector injector)
{ {
@ -59,6 +64,10 @@ class MiddleManagerJettyServerInitializer implements JettyServerInitializer
List<Authenticator> authenticators = null; List<Authenticator> authenticators = null;
AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper); AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper);
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
authenticators = authenticatorMapper.getAuthenticatorChain(); authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators); AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);

View File

@ -22,6 +22,7 @@ package io.druid.cli;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
@ -51,6 +52,9 @@ import java.util.Set;
public class QueryJettyServerInitializer implements JettyServerInitializer public class QueryJettyServerInitializer implements JettyServerInitializer
{ {
private static final Logger log = new Logger(QueryJettyServerInitializer.class); private static final Logger log = new Logger(QueryJettyServerInitializer.class);
private static List<String> UNSECURED_PATHS = Lists.newArrayList(
"/status/health"
);
private final List<Handler> extensionHandlers; private final List<Handler> extensionHandlers;
@ -88,6 +92,10 @@ public class QueryJettyServerInitializer implements JettyServerInitializer
List<Authenticator> authenticators = null; List<Authenticator> authenticators = null;
AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper); AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper);
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
authenticators = authenticatorMapper.getAuthenticatorChain(); authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators); AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);

View File

@ -20,6 +20,7 @@
package io.druid.cli; package io.druid.cli;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
@ -50,6 +51,10 @@ public class RouterJettyServerInitializer implements JettyServerInitializer
{ {
private static Logger log = new Logger(RouterJettyServerInitializer.class); private static Logger log = new Logger(RouterJettyServerInitializer.class);
private static List<String> UNSECURED_PATHS = Lists.newArrayList(
"/status/health"
);
private final AsyncQueryForwardingServlet asyncQueryForwardingServlet; private final AsyncQueryForwardingServlet asyncQueryForwardingServlet;
private final DruidHttpClientConfig httpClientConfig; private final DruidHttpClientConfig httpClientConfig;
@ -88,6 +93,10 @@ public class RouterJettyServerInitializer implements JettyServerInitializer
List<Authenticator> authenticators = null; List<Authenticator> authenticators = null;
AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper); AuthenticationUtils.addSecuritySanityCheckFilter(root, jsonMapper);
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
authenticators = authenticatorMapper.getAuthenticatorChain(); authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators); AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);