Add config to allow setting up custom unsecured paths for druid nodes. (#5614)

* Add config to allow setting up custom unsecured paths for druid nodes.

* return all resources for Unsecured paths

* review comment - Add test

* fix tests

* fix test
This commit is contained in:
Nishant Bangarwa 2018-04-12 05:40:07 +05:30 committed by Jonathan Wei
parent afa75e04b7
commit e6efd75a3d
23 changed files with 131 additions and 29 deletions

View File

@ -9,6 +9,7 @@ layout: doc_page
|`druid.auth.authenticationChain`|JSON List of Strings|List of Authenticator type names|["allowAll"]|no|
|`druid.escalator.type`|String|Type of the Escalator that should be used for internal Druid communications. This Escalator must use an authentication scheme that is supported by an Authenticator in `druid.auth.authenticationChain`.|"noop"|no|
|`druid.auth.authorizers`|JSON List of Strings|List of Authorizer type names |["allowAll"]|no|
|`druid.auth.unsecuredPaths`| List of Strings|List of paths for which security checks will not be performed. All requests to these paths will be allowed.|[]|no|
## Enabling Authentication/Authorization

View File

@ -126,7 +126,7 @@ public class OverlordResourceTest
public void expectAuthorizationTokenCheck()
{
AuthenticationResult authenticationResult = new AuthenticationResult("druid", "druid", null);
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(authenticationResult)

View File

@ -128,6 +128,7 @@ public class OverlordTest
public void setUp() throws Exception
{
req = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)

View File

@ -113,6 +113,7 @@ public class SupervisorResourceTest extends EasyMockSupport
EasyMock.expect(taskMaster.getSupervisorManager()).andReturn(Optional.of(supervisorManager));
EasyMock.expect(supervisorManager.createOrUpdateAndStartSupervisor(spec)).andReturn(true);
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -162,6 +163,7 @@ public class SupervisorResourceTest extends EasyMockSupport
EasyMock.expect(supervisorManager.getSupervisorIds()).andReturn(supervisorIds).atLeastOnce();
EasyMock.expect(supervisorManager.getSupervisorSpec("id1")).andReturn(Optional.of(spec1));
EasyMock.expect(supervisorManager.getSupervisorSpec("id2")).andReturn(Optional.of(spec2));
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -345,6 +347,7 @@ public class SupervisorResourceTest extends EasyMockSupport
SupervisorSpec spec2 = new TestSupervisorSpec("id2", null, Arrays.asList("datasource2"));
EasyMock.expect(supervisorManager.getSupervisorSpec("id1")).andReturn(Optional.of(spec1)).atLeastOnce();
EasyMock.expect(supervisorManager.getSupervisorSpec("id2")).andReturn(Optional.of(spec2)).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -457,6 +460,7 @@ public class SupervisorResourceTest extends EasyMockSupport
SupervisorSpec spec2 = new TestSupervisorSpec("id2", null, Arrays.asList("datasource2"));
EasyMock.expect(supervisorManager.getSupervisorSpec("id1")).andReturn(Optional.of(spec1)).atLeastOnce();
EasyMock.expect(supervisorManager.getSupervisorSpec("id2")).andReturn(Optional.of(spec2)).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("wronguser", "druid", null)
@ -547,6 +551,7 @@ public class SupervisorResourceTest extends EasyMockSupport
EasyMock.expect(taskMaster.getSupervisorManager()).andReturn(Optional.of(supervisorManager)).times(3);
EasyMock.expect(supervisorManager.getSupervisorHistory()).andReturn(history).times(3);
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -644,6 +649,7 @@ public class SupervisorResourceTest extends EasyMockSupport
EasyMock.expect(taskMaster.getSupervisorManager()).andReturn(Optional.of(supervisorManager)).times(4);
EasyMock.expect(supervisorManager.getSupervisorHistory()).andReturn(history).times(4);
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("notdruid", "druid", null)

View File

@ -28,6 +28,7 @@ command=java
-Ddruid.escalator.authorizerName=basic
-Ddruid.auth.authorizers="[\"basic\"]"
-Ddruid.auth.authorizer.basic.type=basic
-Ddruid.auth.unsecuredPaths="[\"/druid/coordinator/v1/loadqueue\"]"
-cp /shared/docker/lib/*
io.druid.cli.Main server coordinator
redirect_stderr=true

View File

@ -100,6 +100,11 @@ public class ITBasicAuthConfigurationTest
httpClient
);
final HttpClient unsecuredClient = httpClient;
// check that we are allowed to access unsecured path without credentials.
checkUnsecuredCoordinatorLoadQueuePath(unsecuredClient);
// check that admin works
checkNodeAccess(adminClient);
@ -221,6 +226,11 @@ public class ITBasicAuthConfigurationTest
testAvaticaAuthFailure(routerUrl);
}
private void checkUnsecuredCoordinatorLoadQueuePath(HttpClient client)
{
makeRequest(client, HttpMethod.GET, config.getCoordinatorUrl() + "/druid/coordinator/v1/loadqueue", null);
}
private void testAvaticaQuery(String url)
{
LOG.info("URL: " + url);

View File

@ -22,7 +22,9 @@ package io.druid.server.security;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class AuthConfig
{
@ -36,21 +38,25 @@ public class AuthConfig
*/
public static final String DRUID_AUTHORIZATION_CHECKED = "Druid-Authorization-Checked";
public static final String DRUID_ALLOW_UNSECURED_PATH = "Druid-Allow-Unsecured-Path";
public static final String ALLOW_ALL_NAME = "allowAll";
public AuthConfig()
{
this(null, null);
this(null, null, null);
}
@JsonCreator
public AuthConfig(
@JsonProperty("authenticatorChain") List<String> authenticationChain,
@JsonProperty("authorizers") List<String> authorizers
@JsonProperty("authorizers") List<String> authorizers,
@JsonProperty("unsecuredPaths") List<String> unsecuredPaths
)
{
this.authenticatorChain = authenticationChain;
this.authorizers = authorizers;
this.unsecuredPaths = unsecuredPaths == null ? Collections.emptyList() : unsecuredPaths;
}
@JsonProperty
@ -59,6 +65,9 @@ public class AuthConfig
@JsonProperty
private List<String> authorizers;
@JsonProperty
private final List<String> unsecuredPaths;
public List<String> getAuthenticatorChain()
{
return authenticatorChain;
@ -69,12 +78,18 @@ public class AuthConfig
return authorizers;
}
public List<String> getUnsecuredPaths()
{
return unsecuredPaths;
}
@Override
public String toString()
{
return "AuthConfig{" +
"authenticatorChain='" + authenticatorChain + '\'' +
", authorizers='" + authorizers + '\'' +
", unsecuredPaths='" + unsecuredPaths + '\'' +
'}';
}
@ -87,23 +102,15 @@ public class AuthConfig
if (o == null || getClass() != o.getClass()) {
return false;
}
AuthConfig that = (AuthConfig) o;
if (getAuthenticatorChain() != null
? !getAuthenticatorChain().equals(that.getAuthenticatorChain())
: that.getAuthenticatorChain() != null) {
return false;
}
return getAuthorizers() != null ? getAuthorizers().equals(that.getAuthorizers()) : that.getAuthorizers() == null;
return Objects.equals(authenticatorChain, that.authenticatorChain) &&
Objects.equals(authorizers, that.authorizers) &&
Objects.equals(unsecuredPaths, that.unsecuredPaths);
}
@Override
public int hashCode()
{
int result = getAuthenticatorChain() != null ? getAuthenticatorChain().hashCode() : 0;
result = 31 * result + (getAuthorizers() != null ? getAuthorizers().hashCode() : 0);
return result;
return Objects.hash(authenticatorChain, authorizers, unsecuredPaths);
}
}

View File

@ -155,6 +155,10 @@ public class AuthorizationUtils
final AuthorizerMapper authorizerMapper
)
{
if (request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH) != null) {
return Access.OK;
}
if (request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED) != null) {
throw new ISE("Request already had authorization check.");
}
@ -201,6 +205,10 @@ public class AuthorizationUtils
final AuthorizerMapper authorizerMapper
)
{
if (request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH) != null) {
return resources;
}
if (request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED) != null) {
throw new ISE("Request already had authorization check.");
}
@ -309,6 +317,11 @@ public class AuthorizationUtils
final AuthorizerMapper authorizerMapper
)
{
if (request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH) != null) {
return unfilteredResources;
}
if (request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED) != null) {
throw new ISE("Request already had authorization check.");
}

View File

@ -76,8 +76,10 @@ public class SecuritySanityCheckFilter implements Filter
// make sure the original request isn't trying to fake the auth token checks
Boolean authInfoChecked = (Boolean) request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED);
Boolean allowUnsecured = (Boolean) request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH);
AuthenticationResult result = (AuthenticationResult) request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT);
if (authInfoChecked != null || result != null) {
if (authInfoChecked != null || result != null || allowUnsecured != null) {
sendJsonError(httpResponse, Response.SC_FORBIDDEN, unauthorizedMessage, out);
out.close();
return;

View File

@ -53,6 +53,7 @@ public class UnsecuredResourceFilter implements Filter
// 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_ALLOW_UNSECURED_PATH, true);
filterChain.doFilter(servletRequest, servletResponse);
}

View File

@ -144,6 +144,7 @@ public class EventReceiverFirehoseTest
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(AllowAllAuthenticator.ALLOW_ALL_RESULT)
.anyTimes();
@ -246,6 +247,7 @@ public class EventReceiverFirehoseTest
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(AllowAllAuthenticator.ALLOW_ALL_RESULT)
.anyTimes();
@ -265,6 +267,7 @@ public class EventReceiverFirehoseTest
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(AllowAllAuthenticator.ALLOW_ALL_RESULT)
.anyTimes();
@ -403,6 +406,7 @@ public class EventReceiverFirehoseTest
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(AllowAllAuthenticator.ALLOW_ALL_RESULT)
.anyTimes();

View File

@ -170,6 +170,7 @@ public class QueryResourceTest
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(authenticationResult)
@ -206,6 +207,7 @@ public class QueryResourceTest
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(authenticationResult)
@ -247,13 +249,13 @@ public class QueryResourceTest
new DefaultGenericQueryMetricsFactory(jsonMapper),
new NoopServiceEmitter(),
testRequestLogger,
new AuthConfig(null, null),
new AuthConfig(),
authMapper
),
jsonMapper,
jsonMapper,
queryManager,
new AuthConfig(null, null),
new AuthConfig(),
authMapper,
new DefaultGenericQueryMetricsFactory(jsonMapper)
);
@ -301,6 +303,7 @@ public class QueryResourceTest
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(authenticationResult)
@ -354,13 +357,13 @@ public class QueryResourceTest
new DefaultGenericQueryMetricsFactory(jsonMapper),
new NoopServiceEmitter(),
testRequestLogger,
new AuthConfig(null, null),
new AuthConfig(),
authMapper
),
jsonMapper,
jsonMapper,
queryManager,
new AuthConfig(null, null),
new AuthConfig(),
authMapper,
new DefaultGenericQueryMetricsFactory(jsonMapper)
);
@ -426,6 +429,8 @@ public class QueryResourceTest
.andReturn(null)
.anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(testServletRequest.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
.andReturn(authenticationResult)
.anyTimes();
@ -475,13 +480,13 @@ public class QueryResourceTest
new DefaultGenericQueryMetricsFactory(jsonMapper),
new NoopServiceEmitter(),
testRequestLogger,
new AuthConfig(null, null),
new AuthConfig(),
authMapper
),
jsonMapper,
jsonMapper,
queryManager,
new AuthConfig(null, null),
new AuthConfig(),
authMapper,
new DefaultGenericQueryMetricsFactory(jsonMapper)
);

View File

@ -128,6 +128,7 @@ public class DatasourcesResourceTest
EasyMock.expect(inventoryView.getInventory()).andReturn(
ImmutableList.of(server)
).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -142,6 +143,7 @@ public class DatasourcesResourceTest
EasyMock.expect(inventoryView.getInventory()).andReturn(
ImmutableList.of(server)
).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -184,6 +186,7 @@ public class DatasourcesResourceTest
ImmutableList.of(listDataSources.get(0), listDataSources.get(1))
).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
authenticationResult
@ -200,6 +203,7 @@ public class DatasourcesResourceTest
ImmutableList.of(listDataSources.get(0), listDataSources.get(1))
).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
authenticationResult
@ -236,7 +240,7 @@ public class DatasourcesResourceTest
inventoryView,
null,
null,
new AuthConfig(null, null),
new AuthConfig(),
authMapper
);
Response response = datasourcesResource.getQueryableDataSources("full", null, request);
@ -277,6 +281,7 @@ public class DatasourcesResourceTest
EasyMock.expect(inventoryView.getInventory()).andReturn(
ImmutableList.of(server)
).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)

View File

@ -108,6 +108,7 @@ public class IntervalsResourceTest
EasyMock.expect(inventoryView.getInventory()).andReturn(
ImmutableList.of(server)
).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -145,6 +146,7 @@ public class IntervalsResourceTest
EasyMock.expect(inventoryView.getInventory()).andReturn(
ImmutableList.of(server)
).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -176,6 +178,7 @@ public class IntervalsResourceTest
EasyMock.expect(inventoryView.getInventory()).andReturn(
ImmutableList.of(server)
).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)
@ -209,6 +212,7 @@ public class IntervalsResourceTest
EasyMock.expect(inventoryView.getInventory()).andReturn(
ImmutableList.of(server)
).atLeastOnce();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(
new AuthenticationResult("druid", "druid", null)

View File

@ -110,6 +110,7 @@ public class ResourceFilterTestHelper
)
).anyTimes();
EasyMock.expect(request.getMethod()).andReturn(requestMethod).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).anyTimes();
AuthenticationResult authenticationResult = new AuthenticationResult("druid", "druid", null);
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT))
@ -182,7 +183,7 @@ public class ResourceFilterTestHelper
for (Key<?> key : mockableKeys) {
binder.bind((Key<Object>) key).toInstance(EasyMock.createNiceMock(key.getTypeLiteral().getRawType()));
}
binder.bind(AuthConfig.class).toInstance(new AuthConfig(null, null));
binder.bind(AuthConfig.class).toInstance(new AuthConfig());
}
}
);

View File

@ -41,6 +41,7 @@ public class SecuritySanityCheckFilterTest
FilterChain filterChain = EasyMock.createStrictMock(FilterChain.class);
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).once();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(null).once();
filterChain.doFilter(req, resp);
EasyMock.expectLastCall().once();
@ -61,6 +62,7 @@ public class SecuritySanityCheckFilterTest
AuthenticationResult authenticationResult = new AuthenticationResult("does-not-belong", "does-not-belong", null);
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(true).once();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(authenticationResult).once();
EasyMock.expect(resp.getOutputStream()).andReturn(outputStream).once();
resp.setStatus(403);

View File

@ -97,7 +97,9 @@ public class CliMiddleManager extends ServerRunnable
binder.bind(WorkerCuratorCoordinator.class).in(ManageLifecycle.class);
LifecycleModule.register(binder, WorkerTaskMonitor.class);
binder.bind(JettyServerInitializer.class).toInstance(new MiddleManagerJettyServerInitializer());
binder.bind(JettyServerInitializer.class)
.to(MiddleManagerJettyServerInitializer.class)
.in(LazySingleton.class);
Jerseys.addResource(binder, WorkerResource.class);
Jerseys.addResource(binder, TaskManagementResource.class);

View File

@ -22,6 +22,7 @@ package io.druid.cli;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
@ -91,6 +92,7 @@ import io.druid.server.http.RedirectFilter;
import io.druid.server.http.RedirectInfo;
import io.druid.server.initialization.jetty.JettyServerInitUtils;
import io.druid.server.initialization.jetty.JettyServerInitializer;
import io.druid.server.security.AuthConfig;
import io.druid.server.security.AuthenticationUtils;
import io.druid.server.security.Authenticator;
import io.druid.server.security.AuthenticatorMapper;
@ -194,7 +196,9 @@ public class CliOverlord extends ServerRunnable
if (standalone) {
binder.bind(RedirectFilter.class).in(LazySingleton.class);
binder.bind(RedirectInfo.class).to(OverlordRedirectInfo.class).in(LazySingleton.class);
binder.bind(JettyServerInitializer.class).toInstance(new OverlordJettyServerInitializer());
binder.bind(JettyServerInitializer.class)
.to(OverlordJettyServerInitializer.class)
.in(LazySingleton.class);
}
Jerseys.addResource(binder, OverlordResource.class);
@ -302,6 +306,14 @@ public class CliOverlord extends ServerRunnable
*/
private static class OverlordJettyServerInitializer implements JettyServerInitializer
{
private final AuthConfig authConfig;
@Inject
OverlordJettyServerInitializer(AuthConfig authConfig)
{
this.authConfig = authConfig;
}
@Override
public void initialize(Server server, Injector injector)
{
@ -330,6 +342,7 @@ public class CliOverlord extends ServerRunnable
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
AuthenticationUtils.addNoopAuthorizationFilters(root, authConfig.getUnsecuredPaths());
authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);

View File

@ -71,12 +71,14 @@ class CoordinatorJettyServerInitializer implements JettyServerInitializer
private final DruidCoordinatorConfig config;
private final boolean beOverlord;
private final AuthConfig authConfig;
@Inject
CoordinatorJettyServerInitializer(DruidCoordinatorConfig config, Properties properties)
CoordinatorJettyServerInitializer(DruidCoordinatorConfig config, Properties properties, AuthConfig authConfig)
{
this.config = config;
this.beOverlord = CliCoordinator.isOverlord(properties);
this.authConfig = authConfig;
}
@Override
@ -117,6 +119,7 @@ class CoordinatorJettyServerInitializer implements JettyServerInitializer
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
AuthenticationUtils.addNoopAuthorizationFilters(root, authConfig.getUnsecuredPaths());
if (beOverlord) {
AuthenticationUtils.addNoopAuthorizationFilters(root, CliOverlord.UNSECURED_PATHS);

View File

@ -21,6 +21,7 @@ package io.druid.cli;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.servlet.GuiceFilter;
@ -52,6 +53,14 @@ class MiddleManagerJettyServerInitializer implements JettyServerInitializer
"/status/health"
);
private final AuthConfig authConfig;
@Inject
public MiddleManagerJettyServerInitializer(AuthConfig authConfig)
{
this.authConfig = authConfig;
}
@Override
public void initialize(Server server, Injector injector)
{
@ -67,6 +76,7 @@ class MiddleManagerJettyServerInitializer implements JettyServerInitializer
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
AuthenticationUtils.addNoopAuthorizationFilters(root, authConfig.getUnsecuredPaths());
authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);

View File

@ -33,6 +33,7 @@ import io.druid.server.initialization.ServerConfig;
import io.druid.server.initialization.jetty.JettyServerInitUtils;
import io.druid.server.initialization.jetty.JettyServerInitializer;
import io.druid.server.initialization.jetty.LimitRequestsFilter;
import io.druid.server.security.AuthConfig;
import io.druid.server.security.AuthenticationUtils;
import io.druid.server.security.Authenticator;
import io.druid.server.security.AuthenticatorMapper;
@ -61,11 +62,14 @@ public class QueryJettyServerInitializer implements JettyServerInitializer
private final ServerConfig serverConfig;
private final AuthConfig authConfig;
@Inject
public QueryJettyServerInitializer(Set<Handler> extensionHandlers, ServerConfig serverConfig)
public QueryJettyServerInitializer(Set<Handler> extensionHandlers, ServerConfig serverConfig, AuthConfig authConfig)
{
this.extensionHandlers = ImmutableList.copyOf(extensionHandlers);
this.serverConfig = serverConfig;
this.authConfig = authConfig;
}
@Override
@ -96,6 +100,7 @@ public class QueryJettyServerInitializer implements JettyServerInitializer
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
AuthenticationUtils.addNoopAuthorizationFilters(root, authConfig.getUnsecuredPaths());
authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);

View File

@ -34,6 +34,7 @@ import io.druid.server.initialization.jetty.JettyServerInitUtils;
import io.druid.server.initialization.jetty.JettyServerInitializer;
import io.druid.server.router.ManagementProxyConfig;
import io.druid.server.router.Router;
import io.druid.server.security.AuthConfig;
import io.druid.server.security.AuthenticationUtils;
import io.druid.server.security.Authenticator;
import io.druid.server.security.AuthenticatorMapper;
@ -63,6 +64,7 @@ public class RouterJettyServerInitializer implements JettyServerInitializer
private final ManagementProxyConfig managementProxyConfig;
private final AsyncQueryForwardingServlet asyncQueryForwardingServlet;
private final AsyncManagementForwardingServlet asyncManagementForwardingServlet;
private final AuthConfig authConfig;
@Inject
public RouterJettyServerInitializer(
@ -70,7 +72,8 @@ public class RouterJettyServerInitializer implements JettyServerInitializer
@Global DruidHttpClientConfig globalHttpClientConfig,
ManagementProxyConfig managementProxyConfig,
AsyncQueryForwardingServlet asyncQueryForwardingServlet,
AsyncManagementForwardingServlet asyncManagementForwardingServlet
AsyncManagementForwardingServlet asyncManagementForwardingServlet,
AuthConfig authConfig
)
{
this.routerHttpClientConfig = routerHttpClientConfig;
@ -78,6 +81,7 @@ public class RouterJettyServerInitializer implements JettyServerInitializer
this.managementProxyConfig = managementProxyConfig;
this.asyncQueryForwardingServlet = asyncQueryForwardingServlet;
this.asyncManagementForwardingServlet = asyncManagementForwardingServlet;
this.authConfig = authConfig;
}
@Override
@ -105,6 +109,7 @@ public class RouterJettyServerInitializer implements JettyServerInitializer
// perform no-op authorization for these resources
AuthenticationUtils.addNoopAuthorizationFilters(root, UNSECURED_PATHS);
AuthenticationUtils.addNoopAuthorizationFilters(root, authConfig.getUnsecuredPaths());
final List<Authenticator> authenticators = authenticatorMapper.getAuthenticatorChain();
AuthenticationUtils.addAuthenticationFilterChain(root, authenticators);

View File

@ -86,6 +86,7 @@ public class SqlResourceTest extends CalciteTestBase
final DruidOperatorTable operatorTable = CalciteTests.createOperatorTable();
final ExprMacroTable macroTable = CalciteTests.createExprMacroTable();
req = EasyMock.createStrictMock(HttpServletRequest.class);
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED))
.andReturn(null)
.anyTimes();