diff --git a/server/src/main/java/io/druid/server/http/DatasourcesResource.java b/server/src/main/java/io/druid/server/http/DatasourcesResource.java index 52988a448bb..8ce337485ba 100644 --- a/server/src/main/java/io/druid/server/http/DatasourcesResource.java +++ b/server/src/main/java/io/druid/server/http/DatasourcesResource.java @@ -43,7 +43,6 @@ import io.druid.metadata.MetadataSegmentManager; import io.druid.query.TableDataSource; import io.druid.server.http.security.DatasourceResourceFilter; import io.druid.server.security.AuthConfig; -import io.druid.server.security.AuthenticationResult; import io.druid.server.security.AuthorizerMapper; import io.druid.timeline.DataSegment; import io.druid.timeline.TimelineLookup; @@ -110,9 +109,9 @@ public class DatasourcesResource { Response.ResponseBuilder builder = Response.ok(); final Set datasources = InventoryViewUtils.getSecuredDataSources( + req, serverInventoryView, - authorizerMapper, - (AuthenticationResult) req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT) + authorizerMapper ); if (full != null) { diff --git a/server/src/main/java/io/druid/server/http/IntervalsResource.java b/server/src/main/java/io/druid/server/http/IntervalsResource.java index 4a90237e671..2181e9cb6f7 100644 --- a/server/src/main/java/io/druid/server/http/IntervalsResource.java +++ b/server/src/main/java/io/druid/server/http/IntervalsResource.java @@ -27,7 +27,6 @@ import io.druid.java.util.common.Intervals; import io.druid.java.util.common.MapUtils; import io.druid.java.util.common.guava.Comparators; import io.druid.server.security.AuthConfig; -import io.druid.server.security.AuthenticationResult; import io.druid.server.security.AuthorizerMapper; import io.druid.timeline.DataSegment; import org.joda.time.Interval; @@ -72,9 +71,9 @@ public class IntervalsResource { final Comparator comparator = Comparators.inverse(Comparators.intervalsByStartThenEnd()); final Set datasources = InventoryViewUtils.getSecuredDataSources( + req, serverInventoryView, - authorizerMapper, - (AuthenticationResult) req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT) + authorizerMapper ); final Map>> retVal = Maps.newTreeMap(comparator); @@ -104,9 +103,9 @@ public class IntervalsResource { final Interval theInterval = Intervals.of(interval.replace("_", "/")); final Set datasources = InventoryViewUtils.getSecuredDataSources( + req, serverInventoryView, - authorizerMapper, - (AuthenticationResult) req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT) + authorizerMapper ); final Comparator comparator = Comparators.inverse(Comparators.intervalsByStartThenEnd()); diff --git a/server/src/main/java/io/druid/server/http/InventoryViewUtils.java b/server/src/main/java/io/druid/server/http/InventoryViewUtils.java index e6db453e6c3..dc7cb5e9736 100644 --- a/server/src/main/java/io/druid/server/http/InventoryViewUtils.java +++ b/server/src/main/java/io/druid/server/http/InventoryViewUtils.java @@ -20,7 +20,6 @@ package io.druid.server.http; import com.google.common.base.Function; -import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -30,18 +29,11 @@ import io.druid.client.DruidDataSource; import io.druid.client.DruidServer; import io.druid.client.InventoryView; import io.druid.java.util.common.ISE; -import io.druid.java.util.common.Pair; -import io.druid.server.security.Access; -import io.druid.server.security.Action; -import io.druid.server.security.AuthenticationResult; -import io.druid.server.security.Authorizer; +import io.druid.server.security.AuthorizationUtils; import io.druid.server.security.AuthorizerMapper; -import io.druid.server.security.Resource; -import io.druid.server.security.ResourceType; +import javax.servlet.http.HttpServletRequest; import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -81,42 +73,26 @@ public class InventoryViewUtils } public static Set getSecuredDataSources( + HttpServletRequest request, InventoryView inventoryView, - final AuthorizerMapper authorizerMapper, - final AuthenticationResult authenticationResult + final AuthorizerMapper authorizerMapper ) { if (authorizerMapper == null) { throw new ISE("No authorization mapper found"); } - final Authorizer authorizer = authorizerMapper.getAuthorizer(authenticationResult.getAuthorizerName()); - if (authorizer == null) { - throw new ISE("Invalid to call a secured method with null Authorizer!!"); - } else { - final Map, Access> resourceAccessMap = new HashMap<>(); - return ImmutableSet.copyOf( - Iterables.filter( - getDataSources(inventoryView), - new Predicate() - { - @Override - public boolean apply(DruidDataSource input) - { - Resource resource = new Resource(input.getName(), ResourceType.DATASOURCE); - Action action = Action.READ; - Pair key = new Pair<>(resource, action); - if (resourceAccessMap.containsKey(key)) { - return resourceAccessMap.get(key).isAllowed(); - } else { - Access access = authorizer.authorize(authenticationResult, key.lhs, key.rhs); - resourceAccessMap.put(key, access); - return access.isAllowed(); - } - } - } - ) - ); - } + return ImmutableSet.copyOf( + AuthorizationUtils.filterAuthorizedResources( + request, + getDataSources(inventoryView), + datasource -> { + return Lists.newArrayList( + AuthorizationUtils.DATASOURCE_READ_RA_GENERATOR.apply(datasource.getName()) + ); + }, + authorizerMapper + ) + ); } } diff --git a/server/src/test/java/io/druid/server/http/DatasourcesResourceTest.java b/server/src/test/java/io/druid/server/http/DatasourcesResourceTest.java index 3b98960b8e1..90f5519c076 100644 --- a/server/src/test/java/io/druid/server/http/DatasourcesResourceTest.java +++ b/server/src/test/java/io/druid/server/http/DatasourcesResourceTest.java @@ -118,15 +118,34 @@ public class DatasourcesResourceTest @Test public void testGetFullQueryableDataSources() throws Exception { + // first request EasyMock.expect(server.getDataSources()).andReturn( ImmutableList.of(listDataSources.get(0), listDataSources.get(1)) - ).atLeastOnce(); + ).once(); EasyMock.expect(inventoryView.getInventory()).andReturn( ImmutableList.of(server) - ).atLeastOnce(); + ).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") - ).atLeastOnce(); + new AuthenticationResult("druid", "druid") + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); + + // second request + EasyMock.expect(server.getDataSources()).andReturn( + ImmutableList.of(listDataSources.get(0), listDataSources.get(1)) + ).once(); + EasyMock.expect(inventoryView.getInventory()).andReturn( + ImmutableList.of(server) + ).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") + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); + EasyMock.replay(inventoryView, server, request); DatasourcesResource datasourcesResource = new DatasourcesResource( inventoryView, @@ -155,18 +174,37 @@ public class DatasourcesResourceTest @Test public void testSecuredGetFullQueryableDataSources() throws Exception { - AuthenticationResult authenticationResult = new AuthenticationResult("druid", "druid"); - - EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)) - .andReturn(authenticationResult) - .anyTimes(); + // first request EasyMock.expect(server.getDataSources()).andReturn( - ImmutableList.of(listDataSources.get(0), listDataSources.get(1)) - ).atLeastOnce(); + ImmutableList.of(listDataSources.get(0), listDataSources.get(1)) + ).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") + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); EasyMock.expect(inventoryView.getInventory()).andReturn( ImmutableList.of(server) - ).atLeastOnce(); + ).once(); + + // second request + EasyMock.expect(server.getDataSources()).andReturn( + ImmutableList.of(listDataSources.get(0), listDataSources.get(1)) + ).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") + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); + + EasyMock.expect(inventoryView.getInventory()).andReturn( + ImmutableList.of(server) + ).once(); EasyMock.replay(inventoryView, server, request); AuthorizerMapper authMapper = new AuthorizerMapper(null) { @@ -232,9 +270,12 @@ public class DatasourcesResourceTest EasyMock.expect(inventoryView.getInventory()).andReturn( ImmutableList.of(server) ).atLeastOnce(); + EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once(); EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn( new AuthenticationResult("druid", "druid") - ).atLeastOnce(); + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); EasyMock.replay(inventoryView, server, request); DatasourcesResource datasourcesResource = new DatasourcesResource( diff --git a/server/src/test/java/io/druid/server/http/IntervalsResourceTest.java b/server/src/test/java/io/druid/server/http/IntervalsResourceTest.java index c6d8eff10be..b91acb598a7 100644 --- a/server/src/test/java/io/druid/server/http/IntervalsResourceTest.java +++ b/server/src/test/java/io/druid/server/http/IntervalsResourceTest.java @@ -108,9 +108,12 @@ public class IntervalsResourceTest EasyMock.expect(inventoryView.getInventory()).andReturn( ImmutableList.of(server) ).atLeastOnce(); + EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once(); EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn( new AuthenticationResult("druid", "druid") - ).atLeastOnce(); + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); EasyMock.replay(inventoryView, request); List expectedIntervals = new ArrayList<>(); @@ -142,9 +145,12 @@ public class IntervalsResourceTest EasyMock.expect(inventoryView.getInventory()).andReturn( ImmutableList.of(server) ).atLeastOnce(); + EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once(); EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn( new AuthenticationResult("druid", "druid") - ).atLeastOnce(); + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); EasyMock.replay(inventoryView, request); List expectedIntervals = new ArrayList<>(); @@ -170,9 +176,12 @@ public class IntervalsResourceTest EasyMock.expect(inventoryView.getInventory()).andReturn( ImmutableList.of(server) ).atLeastOnce(); + EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once(); EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn( new AuthenticationResult("druid", "druid") - ).atLeastOnce(); + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); EasyMock.replay(inventoryView, request); List expectedIntervals = new ArrayList<>(); @@ -200,9 +209,12 @@ public class IntervalsResourceTest EasyMock.expect(inventoryView.getInventory()).andReturn( ImmutableList.of(server) ).atLeastOnce(); + EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).once(); EasyMock.expect(request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn( new AuthenticationResult("druid", "druid") - ).atLeastOnce(); + ).once(); + request.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true); + EasyMock.expectLastCall().times(1); EasyMock.replay(inventoryView, request); IntervalsResource intervalsResource = new IntervalsResource(