Repository: incubator-hawq Updated Branches: refs/heads/master d6dd24fd3 -> e889fc6d7
HAWQ-1422. Resolve user groups using Hadoop config (closes #1220) Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/e889fc6d Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/e889fc6d Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/e889fc6d Branch: refs/heads/master Commit: e889fc6d731e268733cf5fd22aaedc548f5d050c Parents: d6dd24f Author: Alexander Denissov <adenis...@pivotal.io> Authored: Thu Apr 13 14:13:52 2017 -0700 Committer: Alexander Denissov <adenis...@pivotal.io> Committed: Wed Apr 19 09:49:59 2017 -0700 ---------------------------------------------------------------------- .../integration/service/tests/DatabaseTest.java | 4 +- .../integration/service/tests/FunctionTest.java | 4 +- .../integration/service/tests/LanguageTest.java | 4 +- .../integration/service/tests/ProtocolTest.java | 4 +- .../integration/service/tests/SchemaTest.java | 4 +- .../integration/service/tests/SequenceTest.java | 4 +- .../integration/service/tests/TableTest.java | 4 +- .../service/tests/TablespaceTest.java | 4 +- .../service/tests/common/ServiceTestBase.java | 1 + .../tests/common/SimpleResourceTestBase.java | 18 +++++++- .../authorization/RangerHawqAuthorizer.java | 25 ++++++++++- .../authorization/RangerHawqAuthorizerTest.java | 47 +++++++++++++++++--- .../service/src/test/resources/log4j.properties | 2 +- 13 files changed, 98 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java index 1e6557f..4c6678f 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/DatabaseTest.java @@ -49,12 +49,12 @@ public class DatabaseTest extends SimpleResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(database, TEST_DB) .resource(schema, STAR) .resource(table, STAR) - .groupAccess(PUBLIC_GROUP, SPECIAL_PRIVILEGES) + .groupAccess(group, SPECIAL_PRIVILEGES) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java index ecdb67b..f514667 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/FunctionTest.java @@ -84,12 +84,12 @@ public class FunctionTest extends ComplexResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(database, TEST_DB) .resource(schema, TEST_SCHEMA) .resource(function, TEST_FUNCTION) - .groupAccess(PUBLIC_GROUP, privileges) + .groupAccess(group, privileges) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java index d39a595..1c68fd5 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/LanguageTest.java @@ -78,11 +78,11 @@ public class LanguageTest extends ComplexResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(database, TEST_DB) .resource(language, TEST_LANGUAGE) - .groupAccess(PUBLIC_GROUP, privileges) + .groupAccess(group, privileges) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java index e67a0d3..2b2463e 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/ProtocolTest.java @@ -44,10 +44,10 @@ public class ProtocolTest extends SimpleResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(protocol, TEST_PROTOCOL) - .groupAccess(PUBLIC_GROUP, privileges) + .groupAccess(group, privileges) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SchemaTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SchemaTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SchemaTest.java index b3dff37..d9cc96d 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SchemaTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SchemaTest.java @@ -83,12 +83,12 @@ public class SchemaTest extends ComplexResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(database, TEST_DB) .resource(schema, TEST_SCHEMA) .resource(table, STAR) - .groupAccess(PUBLIC_GROUP, SPECIAL_PRIVILEGES) + .groupAccess(group, SPECIAL_PRIVILEGES) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SequenceTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SequenceTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SequenceTest.java index 5add94c..447cdda 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SequenceTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/SequenceTest.java @@ -85,12 +85,12 @@ public class SequenceTest extends ComplexResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(database, TEST_DB) .resource(schema, TEST_SCHEMA) .resource(sequence, TEST_SEQUENCE) - .groupAccess(PUBLIC_GROUP, privileges) + .groupAccess(group, privileges) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TableTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TableTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TableTest.java index 742b91c..9a617b3 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TableTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TableTest.java @@ -84,12 +84,12 @@ public class TableTest extends ComplexResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(database, TEST_DB) .resource(schema, TEST_SCHEMA) .resource(table, TEST_TABLE) - .groupAccess(PUBLIC_GROUP, privileges) + .groupAccess(group, privileges) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java index f8834b5..3c432ff 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/TablespaceTest.java @@ -44,10 +44,10 @@ public class TablespaceTest extends SimpleResourceTestBase { } @Override - protected Policy getResourceGroupPolicy() { + protected Policy getResourceGroupPolicy(String group) { Policy policy = policyBuilder .resource(tablespace, TEST_TABLESPACE) - .groupAccess(PUBLIC_GROUP, privileges) + .groupAccess(group, privileges) .build(); return policy; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/ServiceTestBase.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/ServiceTestBase.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/ServiceTestBase.java index 21c654c..cf7f9ce 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/ServiceTestBase.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/ServiceTestBase.java @@ -42,6 +42,7 @@ public abstract class ServiceTestBase { public final TestName testName = new TestName(); protected static final String PUBLIC_GROUP = "public"; + protected static final String TEST_GROUP = "test"; protected static final String GPADMIN_USER = "gpadmin"; protected static final String TEST_USER = "maria_dev"; protected static final String UNKNOWN = "unknown"; http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/SimpleResourceTestBase.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/SimpleResourceTestBase.java b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/SimpleResourceTestBase.java index 8bd18e8..c07c006 100644 --- a/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/SimpleResourceTestBase.java +++ b/ranger-plugin/integration/service/src/test/java/org/apache/hawq/ranger/integration/service/tests/common/SimpleResourceTestBase.java @@ -64,7 +64,7 @@ public abstract class SimpleResourceTestBase extends ServiceTestBase { @Test public void testSpecificResourcePublicGroupPolicy() throws IOException { - Policy policy = getResourceGroupPolicy(); + Policy policy = getResourceGroupPolicy(PUBLIC_GROUP); createPolicy(policy); checkUserHasResourceAccess(TEST_USER, specificResource, privileges); // user NOT in the policy --> has access to the specific resource @@ -76,6 +76,20 @@ public abstract class SimpleResourceTestBase extends ServiceTestBase { assertFalse(hasAccess(TEST_USER, specificResource, privileges)); } + @Test + public void testSpecificResourceUserGroupPolicy() throws IOException { + Policy policy = getResourceGroupPolicy(TEST_GROUP); + createPolicy(policy); + checkUserHasResourceAccess(TEST_USER, specificResource, privileges); + // user NOT in the group --> has NO access to the specific resource + assertFalse(hasAccess(UNKNOWN, specificResource, privileges)); + // user IN the group --> has NO access to the unknown resource + assertFalse(hasAccess(TEST_USER, unknownResource, privileges)); + // test that user doesn't have access if policy is deleted + deletePolicy(policy); + assertFalse(hasAccess(TEST_USER, specificResource, privileges)); + } + protected void checkResourceUserPolicy(Policy policy) throws IOException { createPolicy(policy); boolean policyDeleted = false; @@ -110,5 +124,5 @@ public abstract class SimpleResourceTestBase extends ServiceTestBase { } abstract protected Policy getResourceUserPolicy(); - abstract protected Policy getResourceGroupPolicy(); + abstract protected Policy getResourceGroupPolicy(String group); } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java index 6fa67ab..d33a9d0 100644 --- a/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java +++ b/ranger-plugin/service/src/main/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizer.java @@ -24,11 +24,13 @@ import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.hawq.ranger.authorization.model.AuthorizationRequest; import org.apache.hawq.ranger.authorization.model.AuthorizationResponse; import org.apache.hawq.ranger.authorization.model.HawqPrivilege; import org.apache.hawq.ranger.authorization.model.HawqResource; import org.apache.hawq.ranger.authorization.model.ResourceAccess; +import org.apache.ranger.audit.provider.MiscUtil; import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler; import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl; import org.apache.ranger.plugin.policyengine.RangerAccessResource; @@ -117,12 +119,12 @@ public class RangerHawqAuthorizer implements HawqAuthorizer { for (Map.Entry<HawqResource, String> resourceEntry : resourceAccess.getResource().entrySet()) { rangerResource.setValue(resourceEntry.getKey().name(), resourceEntry.getValue()); } + // determine user groups + Set<String> userGroups = getUserGroups(user); boolean accessAllowed = true; // iterate over all privileges requested for (HawqPrivilege privilege : resourceAccess.getPrivileges()) { - // TODO not clear how we will get user groups -- Kerberos case ? - Set<String> userGroups = Collections.emptySet(); boolean privilegeAuthorized = authorizeResourcePrivilege(rangerResource, privilege.name(), user, userGroups, clientIp, context); // ALL model of evaluation -- all privileges must be authorized for access to be allowed if (!privilegeAuthorized) { @@ -244,6 +246,25 @@ public class RangerHawqAuthorizer implements HawqAuthorizer { } } + /** + * Returns a set of groups the user belongs to + * @param user user name + * @return set of groups for the user + */ + private Set<String> getUserGroups(String user) { + String[] userGroups = null; + try { + UserGroupInformation ugi = UserGroupInformation.createRemoteUser(user); + userGroups = ugi.getGroupNames(); + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Determined user=%s belongs to groups=%s", user, Arrays.toString(userGroups))); + } + } catch (Throwable e) { + LOG.warn("Failed to determine groups for user=" + user, e); + } + return userGroups == null ? Collections.<String>emptySet() : new HashSet<String>(Arrays.asList(userGroups)); + } + /** http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java index 0a439db..db9b540 100644 --- a/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java +++ b/ranger-plugin/service/src/test/java/org/apache/hawq/ranger/authorization/RangerHawqAuthorizerTest.java @@ -17,6 +17,8 @@ package org.apache.hawq.ranger.authorization; +import org.apache.commons.collections.CollectionUtils; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.hawq.ranger.authorization.model.AuthorizationRequest; import org.apache.hawq.ranger.authorization.model.AuthorizationResponse; import org.apache.hawq.ranger.authorization.model.HawqPrivilege; @@ -32,11 +34,11 @@ import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.internal.util.collections.Sets; import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertNotNull; @@ -45,8 +47,8 @@ import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) +@RunWith(PowerMockRunner.class) +@PrepareForTest(UserGroupInformation.class) public class RangerHawqAuthorizerTest { private static final Integer TEST_REQUEST_ID = 1; @@ -140,6 +142,24 @@ public class RangerHawqAuthorizerTest { testRequest(TEST_RESOURCE_REQUEST_USAGE_SCHEMA, TEST_RESOURCE_RESPONSE_USAGE_SCHEMA); } + @Test + public void testAuthorize_allAllowed_group() throws Exception { + UserGroupInformation mockUgi = mock(UserGroupInformation.class); + when(mockUgi.getGroupNames()).thenReturn(new String[]{"foo", "bar"}); + PowerMockito.mockStatic(UserGroupInformation.class); + when(UserGroupInformation.createRemoteUser(TEST_USER)).thenReturn(mockUgi); + when(mockRangerPlugin.isAccessAllowed(argThat(new UGIMatcher(TEST_USER, "foo", "bar")))).thenReturn(mockRangerAccessResult); + when(mockRangerAccessResult.getIsAllowed()).thenReturn(true); + testRequest(TEST_RESOURCE_REQUEST, TEST_RESOURCE_RESPONSE_ALL_TRUE); + } + + @Test + public void testAuthorize_allAllowed_noGroup() throws Exception { + when(mockRangerPlugin.isAccessAllowed(argThat(new UGIMatcher(TEST_USER, null)))).thenReturn(mockRangerAccessResult); + when(mockRangerAccessResult.getIsAllowed()).thenReturn(true); + testRequest(TEST_RESOURCE_REQUEST, TEST_RESOURCE_RESPONSE_ALL_TRUE); + } + /* ----- VALIDATION TESTS ----- */ @Test(expected=IllegalArgumentException.class) @@ -322,4 +342,19 @@ public class RangerHawqAuthorizerTest { } }; + private class UGIMatcher extends ArgumentMatcher<RangerAccessRequest> { + private String user; + private Set<String> groups; + public UGIMatcher(String user, String... groups) { + this.user = user; + this.groups = groups == null ? Collections.<String>emptySet() : Sets.newSet(groups); + } + @Override + public boolean matches(Object request) { + return request == null ? false : + user.equals(((RangerAccessRequest) request).getUser()) && + CollectionUtils.isEqualCollection(groups, (((RangerAccessRequest) request).getUserGroups())); + } + }; + } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e889fc6d/ranger-plugin/service/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/ranger-plugin/service/src/test/resources/log4j.properties b/ranger-plugin/service/src/test/resources/log4j.properties index b9888df..4631547 100644 --- a/ranger-plugin/service/src/test/resources/log4j.properties +++ b/ranger-plugin/service/src/test/resources/log4j.properties @@ -39,4 +39,4 @@ log4j.appender.devnull=org.apache.log4j.varia.NullAppender log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.target=System.err log4j.appender.console.layout=org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n \ No newline at end of file +log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n