Repository: sentry Updated Branches: refs/heads/master 383cfd3ca -> a11cf624d
SENTRY-1175: Improve usability of URI privileges when granting URIs (Hao Hao, Reviewed by: Sravya Tirukkovalur) Change-Id: I9f6f62b999afdc9d2e734b61065a1bf44d710bf1 Project: http://git-wip-us.apache.org/repos/asf/sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/a11cf624 Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/a11cf624 Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/a11cf624 Branch: refs/heads/master Commit: a11cf624d79f29adf8a6fe509271406003ffdde8 Parents: 383cfd3 Author: hahao <[email protected]> Authored: Fri Apr 22 21:47:41 2016 -0700 Committer: hahao <[email protected]> Committed: Fri Apr 22 21:47:41 2016 -0700 ---------------------------------------------------------------------- .../sentry/core/common/utils/PathUtils.java | 38 +++++++++++++++- .../apache/sentry/core/model/db/AccessURI.java | 7 ++- .../tests/e2e/hdfs/TestHDFSIntegration.java | 46 ++++++++++++++++++++ 3 files changed, 88 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/sentry/blob/a11cf624/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/PathUtils.java ---------------------------------------------------------------------- diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/PathUtils.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/PathUtils.java index c7002e0..d024032 100644 --- a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/PathUtils.java +++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/PathUtils.java @@ -17,11 +17,15 @@ package org.apache.sentry.core.common.utils; import java.io.File; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import com.google.common.annotations.VisibleForTesting; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.text.StrSubstitutor; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +36,12 @@ public class PathUtils { private static final Logger LOGGER = LoggerFactory.getLogger(PathUtils.class); private static String LOCAL_FILE_SCHEMA = "file"; private static String AUTHORITY_PREFIX = "://"; + private static final Configuration CONF = new Configuration(); + + @VisibleForTesting + public static Configuration getConfiguration() { + return CONF; + } /** * URI is a a special case. For URI's, /a implies /a/b. @@ -62,10 +72,31 @@ public class PathUtils { return false; } + /** + * Make fully qualified URI based on the default file system Scheme and Authority + * + * @param uriName The Uri name. + * @return Returns the fully qualified URI. + * @throws IOException + * @throws URISyntaxException + */ + private static URI makeFullQualifiedURI(String uriName) throws IOException, URISyntaxException { + Path uriPath = new Path(uriName); + + if (uriPath.isAbsoluteAndSchemeAuthorityNull()) { + + URI defaultUri = FileSystem.getDefaultUri(CONF); + uriPath = uriPath.makeQualified(defaultUri, uriPath); + return uriPath.toUri(); + } + + return new URI(uriName); + } + public static boolean impliesURI(String privilege, String request) { try { - URI privilegeURI = new URI(new StrSubstitutor(System.getProperties()).replace(privilege)); - URI requestURI = new URI(request); + URI privilegeURI = makeFullQualifiedURI(new StrSubstitutor(System.getProperties()).replace(privilege)); + URI requestURI = makeFullQualifiedURI(request); if (privilegeURI.getScheme() == null || privilegeURI.getPath() == null) { LOGGER.warn("Privilege URI " + request + " is not valid. Either no scheme or no path."); return false; @@ -78,6 +109,9 @@ public class PathUtils { } catch (URISyntaxException e) { LOGGER.warn("Request URI " + request + " is not a URI", e); return false; + } catch (IOException e) { + LOGGER.warn("Unable to get the configured filesystem implementation", e); + return false; } } http://git-wip-us.apache.org/repos/asf/sentry/blob/a11cf624/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java ---------------------------------------------------------------------- diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java index 600a82f..dd8104d 100644 --- a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java +++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/AccessURI.java @@ -33,17 +33,22 @@ public class AccessURI implements DBModelAuthorizable { */ public AccessURI(String uriName) { uriName = uriName == null ? "" : uriName; + + // Validating the URI format if (!uriName.equals(AccessConstants.ALL)) { Path uriPath = new Path(uriName); String schema = uriPath.toUri().getScheme(); if (StringUtils.isBlank(schema) || !uriPath.isAbsolute()) { throw new IllegalArgumentException("URI '" + uriName - + "' is invalid. Unsupport URI without schema or relative URI."); + + "' is invalid. Unsupported URI without schema or relative URI."); } + if (!uriName.startsWith(schema + AUTHORITY_PREFIX)) { throw new IllegalArgumentException("URI '" + uriName + "' is invalid."); } } + + // ALL(*) represents all URIs. this.uriName = uriName; } http://git-wip-us.apache.org/repos/asf/sentry/blob/a11cf624/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hdfs/TestHDFSIntegration.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hdfs/TestHDFSIntegration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hdfs/TestHDFSIntegration.java index d726176..99242d7 100644 --- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hdfs/TestHDFSIntegration.java +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hdfs/TestHDFSIntegration.java @@ -39,6 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import com.google.common.base.Preconditions; +import org.apache.sentry.core.common.utils.PathUtils; import org.junit.Assert; import org.apache.hadoop.conf.Configuration; @@ -1333,6 +1334,51 @@ public class TestHDFSIntegration { conn.close(); } + @Test + public void testURIsWithoutSchemeandAuthority() throws Throwable { + // In the local test environment, EXTERNAL_SENTRY_SERVICE is false, + // set the default URI scheme to be hdfs. + boolean testConfOff = new Boolean(System.getProperty(EXTERNAL_SENTRY_SERVICE, "false")); + if (!testConfOff) { + PathUtils.getConfiguration().set("fs.defaultFS", fsURI); + } + + String dbName= "db1"; + + tmpHDFSDir = new Path("/tmp/external"); + dbNames = new String[]{dbName}; + roles = new String[]{"admin_role", "db_role"}; + admin = StaticUserGroup.ADMIN1; + + Connection conn; + Statement stmt; + + conn = hiveServer2.createConnection("hive", "hive"); + stmt = conn.createStatement(); + + stmt.execute("create role admin_role"); + stmt.execute("grant all on server server1 to role admin_role"); + stmt.execute("grant role admin_role to group " + StaticUserGroup.ADMINGROUP); + + conn = hiveServer2.createConnection(StaticUserGroup.ADMIN1, StaticUserGroup.ADMIN1); + stmt = conn.createStatement(); + + stmt.execute("create database " + dbName); + stmt.execute("create role db_role"); + stmt.execute("grant create on database " + dbName +" to role db_role"); + stmt.execute("grant all on URI '/tmp/external' to role db_role"); + stmt.execute("grant role db_role to group " + StaticUserGroup.USERGROUP1); + + conn = hiveServer2.createConnection(StaticUserGroup.USER1_1, StaticUserGroup.USER1_1); + stmt = conn.createStatement(); + + stmt.execute("use " + dbName); + stmt.execute("create external table tab1 (s string) location '/tmp/external'"); + + stmt.close(); + conn.close(); + } + //SENTRY-884 @Test public void testAccessToTableDirectory() throws Throwable {
