From 81fe8e414748161f537e6902021d63928f8635f1 Mon Sep 17 00:00:00 2001 From: Steve Loughran Date: Thu, 30 Oct 2014 22:32:08 +0000 Subject: [PATCH] YARN-2677 registry punycoding of usernames doesn't fix all usernames to be DNS-valid (stevel) --- hadoop-yarn-project/CHANGES.txt | 3 ++ .../client/binding/RegistryUtils.java | 40 +++++++++++++++---- .../impl/zk/RegistryOperationsService.java | 4 +- .../binding/TestRegistryOperationUtils.java | 13 +++++- .../operations/TestRegistryOperations.java | 28 +++++++++++++ 5 files changed, 77 insertions(+), 11 deletions(-) diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index 0e066619732..56371142a2c 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -722,6 +722,9 @@ Release 2.6.0 - UNRELEASED YARN-2700 TestSecureRMRegistryOperations failing on windows: auth problems (stevel) + YARN-2677 registry punycoding of usernames doesn't fix all usernames to be + DNS-valid (stevel) + --- YARN-2598 GHS should show N/A instead of null for the inaccessible information diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/binding/RegistryUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/binding/RegistryUtils.java index 3b28a02a64b..8caf4002fee 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/binding/RegistryUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/binding/RegistryUtils.java @@ -44,6 +44,7 @@ import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; /** @@ -58,21 +59,46 @@ public class RegistryUtils { /** * Buld the user path -switches to the system path if the user is "". * It also cross-converts the username to ascii via punycode - * @param shortname username or "" + * @param username username or "" * @return the path to the user */ - public static String homePathForUser(String shortname) { - Preconditions.checkArgument(shortname != null, "null user"); + public static String homePathForUser(String username) { + Preconditions.checkArgument(username != null, "null user"); // catch recursion - if (shortname.startsWith(RegistryConstants.PATH_USERS)) { - return shortname; + if (username.startsWith(RegistryConstants.PATH_USERS)) { + return username; } - if (shortname.isEmpty()) { + if (username.isEmpty()) { return RegistryConstants.PATH_SYSTEM_SERVICES; } + + // convert username to registry name + String convertedName = convertUsername(username); + return RegistryPathUtils.join(RegistryConstants.PATH_USERS, - encodeForRegistry(shortname)); + encodeForRegistry(convertedName)); + } + + /** + * Convert the username to that which can be used for registry + * entries. Lower cases it, + * Strip the kerberos realm off a username if needed, and any "/" hostname + * entries + * @param username user + * @return the converted username + */ + public static String convertUsername(String username) { + String converted= username.toLowerCase(Locale.ENGLISH); + int atSymbol = converted.indexOf('@'); + if (atSymbol > 0) { + converted = converted.substring(0, atSymbol); + } + int slashSymbol = converted.indexOf('/'); + if (slashSymbol > 0) { + converted = converted.substring(0, slashSymbol); + } + return converted; } /** diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/RegistryOperationsService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/RegistryOperationsService.java index c54c205ce93..7c01bdf433e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/RegistryOperationsService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/RegistryOperationsService.java @@ -83,12 +83,12 @@ public class RegistryOperationsService extends CuratorService } /** - * Validate a path ... this includes checking that they are DNS-valid + * Validate a path * @param path path to validate * @throws InvalidPathnameException if a path is considered invalid */ protected void validatePath(String path) throws InvalidPathnameException { - RegistryPathUtils.validateElementsAsDNS(path); + // currently no checks are performed } @Override diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/client/binding/TestRegistryOperationUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/client/binding/TestRegistryOperationUtils.java index b86e3fe5e0f..b07d2ced64f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/client/binding/TestRegistryOperationUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/client/binding/TestRegistryOperationUtils.java @@ -38,10 +38,19 @@ public class TestRegistryOperationUtils extends Assert { public void testUsernameExtractionCurrentuser() throws Throwable { String whoami = RegistryUtils.getCurrentUsernameUnencoded(""); String ugiUser = UserGroupInformation.getCurrentUser().getShortUserName(); - assertEquals(ugiUser, whoami); - } + @Test + public void testShortenUsername() throws Throwable { + assertEquals("hbase", + RegistryUtils.convertUsername("hbase@HADOOP.APACHE.ORG")); + assertEquals("hbase", + RegistryUtils.convertUsername("hbase/localhost@HADOOP.APACHE.ORG")); + assertEquals("hbase", + RegistryUtils.convertUsername("hbase")); + assertEquals("hbase user", + RegistryUtils.convertUsername("hbase user")); + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/operations/TestRegistryOperations.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/operations/TestRegistryOperations.java index 1cfb02553eb..7a7f88cd51c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/operations/TestRegistryOperations.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/operations/TestRegistryOperations.java @@ -301,4 +301,32 @@ public class TestRegistryOperations extends AbstractRegistryTest { assertEquals(r1stat, stats.get("r1")); assertEquals(r2stat, stats.get("r2")); } + + + @Test + public void testComplexUsernames() throws Throwable { + operations.mknode("/users/user with spaces", true); + operations.mknode("/users/user-with_underscores", true); + operations.mknode("/users/000000", true); + operations.mknode("/users/-storm", true); + operations.mknode("/users/windows\\ user", true); + String home = RegistryUtils.homePathForUser("\u0413PA\u0414_3"); + operations.mknode(home, true); + operations.mknode( + RegistryUtils.servicePath(home, "service.class", "service 4_5"), + true); + + operations.mknode( + RegistryUtils.homePathForUser("hbase@HADOOP.APACHE.ORG"), + true); + operations.mknode( + RegistryUtils.homePathForUser("hbase/localhost@HADOOP.APACHE.ORG"), + true); + home = RegistryUtils.homePathForUser("ADMINISTRATOR/127.0.0.1"); + assertTrue("No 'administrator' in " + home, home.contains("administrator")); + operations.mknode( + home, + true); + + } }