accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From els...@apache.org
Subject [2/3] accumulo git commit: ACCUMULO-4135 Add impersonation configuration keys which don't put the principal in the key.
Date Sat, 06 Feb 2016 21:51:51 GMT
ACCUMULO-4135 Add impersonation configuration keys which don't put the principal in the key.

Apparently, Ambari has a very hard time handling configuration keys that have '/'
characters in them. As such, this breaks the impersonation config keys, as they
will near always have a '/' in them (e.g. primary/instance@REALM). This is sad.

This commit introduces an alternate strategy for specifying the same configuration
items but only using the values.

Closes apache/accumulo#67


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/e43e9273
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/e43e9273
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/e43e9273

Branch: refs/heads/master
Commit: e43e9273e5297f56b0cc51349ab9bdc25d6e956d
Parents: 81f1c7d
Author: Josh Elser <elserj@apache.org>
Authored: Sat Feb 6 16:40:03 2016 -0500
Committer: Josh Elser <elserj@apache.org>
Committed: Sat Feb 6 16:40:03 2016 -0500

----------------------------------------------------------------------
 .../org/apache/accumulo/core/conf/Property.java |   5 +
 docs/src/main/asciidoc/chapters/kerberos.txt    |  52 ++--
 .../server/security/UserImpersonation.java      |  97 ++++++-
 ...redentialsUpdatingInvocationHandlerTest.java |  55 ++--
 .../server/security/UserImpersonationTest.java  | 259 ++++++++++++++++++-
 5 files changed, 422 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/e43e9273/core/src/main/java/org/apache/accumulo/core/conf/Property.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/Property.java b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
index 559c460..28cc861 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/Property.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
@@ -158,8 +158,13 @@ public enum Property {
    */
   INSTANCE_RPC_SASL_ENABLED("instance.rpc.sasl.enabled", "false", PropertyType.BOOLEAN,
       "Configures Thrift RPCs to require SASL with GSSAPI which supports Kerberos authentication.
Mutually exclusive with SSL RPC configuration."),
+  @Deprecated
   INSTANCE_RPC_SASL_PROXYUSERS("instance.rpc.sasl.impersonation.", null, PropertyType.PREFIX,
       "Prefix that allows configuration of users that are allowed to impersonate other users"),
+  INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION("instance.rpc.sasl.allowed.user.impersonation",
"", PropertyType.STRING,
+      "One-line configuration property controlling what users are allowed to impersonate
other users"),
+  INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION("instance.rpc.sasl.allowed.host.impersonation",
"", PropertyType.STRING,
+      "One-line configuration property controlling the network locations (hostnames) that
are allowed to impersonate other users"),
 
   // general properties
   GENERAL_PREFIX("general.", null, PropertyType.PREFIX,

http://git-wip-us.apache.org/repos/asf/accumulo/blob/e43e9273/docs/src/main/asciidoc/chapters/kerberos.txt
----------------------------------------------------------------------
diff --git a/docs/src/main/asciidoc/chapters/kerberos.txt b/docs/src/main/asciidoc/chapters/kerberos.txt
index ca482b2..fec9277 100644
--- a/docs/src/main/asciidoc/chapters/kerberos.txt
+++ b/docs/src/main/asciidoc/chapters/kerberos.txt
@@ -35,7 +35,7 @@ Kerberos implements. In the Java programming language, the language itself
also
 GSSAPI which is leveraged by other applications, like Apache Hadoop and Apache Thrift.
 SASL, simple authentication and security layer, is a framework for authentication and
 and security over the network. SASL provides a number of mechanisms for authentication,
-one of which is GSSAPI. Thus, SASL provides the transport which authenticates 
+one of which is GSSAPI. Thus, SASL provides the transport which authenticates
 using GSSAPI that Kerberos implements.
 
 Kerberos is a very complicated software application and is deserving of much
@@ -269,29 +269,45 @@ it can only connect to Accumulo as itself. Impersonation, in this context,
refer
 of the proxy to authenticate to Accumulo as itself, but act on behalf of an Accumulo user.
 
 Accumulo supports basic impersonation of end-users by a third party via static rules in Accumulo's
-site configuration file.
+site configuration file. These two properties are semi-colon separated properties which are
aligned
+by index. This first element in the user impersonation property value matches the first element
+in the host impersonation property value, etc.
 
 ----
 <property>
-  <name>instance.rpc.sasl.impersonation.$PROXY_USER.users</name>
-  <value>*</value>
+  <name>instance.rpc.sasl.allowed.user.impersonation</name>
+  <value>$PROXY_USER:*</value>
 </property>
 
 <property>
-  <name>instance.rpc.sasl.impersonation.$PROXY_USER.hosts</name>
+  <name>instance.rpc.sasl.allowed.host.impersonation</name>
   <value>*</value>
 </property>
 ----
 
-The value +$PROXY_USER+ is the Kerberos principal of the server which is acting on behalf
of a user.
-Impersonation is enforced by the Kerberos principal and the host from which the RPC originated.
Both
-of the above properties expects values which are comma-separated lists. The value of each
user in the
-list should be the complete Kerberos principal of the user which the give +$PROXY_USER+ can
impersonate,
-and each value of the hosts list should be the FQDN of the machine which the +$PROXY_USER+
can submit
-requests from.
+Here, +$PROXY_USER+ can impersonate any user from any host.
+
+The following is an example of specifying a subset of users +$PROXY_USER+ can impersonate
and also
+limiting the hosts from which +$PROXY_USER+ can initiate requests from.
+
+----
+<property>
+  <name>instance.rpc.sasl.allowed.user.impersonation</name>
+  <value>$PROXY_USER:user1,user2;$PROXY_USER2:user2,user4</value>
+</property>
+
+<property>
+  <name>instance.rpc.sasl.allowed.host.impersonation</name>
+  <value>host1.domain.com,host2.domain.com;*</value>
+</property>
+----
+
+Here, +$PROXY_USER+ can impersonate user1 and user2 only from host1.domain.com or host2.domain.com.
++$PROXY_USER2+ can impersonate user2 and user4 from any host.
 
-Both the hosts and users configuration properties also accept a value of +*+ to denote that
any user or host
-is acceptable for +$PROXY_USER+.
+In these examples, the value +$PROXY_USER+ is the Kerberos principal of the server which
is acting on behalf of a user.
+Impersonation is enforced by the Kerberos principal and the host from which the RPC originated
(from the perspective
+of the Accumulo TabletServers/Masters). An asterisk (*) can be used to specify all users
or all hosts (depending on the context).
 
 ===== Delegation Tokens
 
@@ -299,7 +315,7 @@ Within Accumulo services, the primary task to implement delegation tokens
is the
 of a shared secret among all Accumulo tabletservers and the master. The secret key allows
for generation
 of delegation tokens for users and verification of delegation tokens presented by clients.
If a server
 process is unaware of the secret key used to create a delegation token, the client cannot
be authenticated.
-As ZooKeeper distribution is an asynchronous operation (typically on the order of seconds),
the 
+As ZooKeeper distribution is an asynchronous operation (typically on the order of seconds),
the
 value for `general.delegation.token.update.interval` should be on the order of hours to days
to reduce the
 likelihood of servers rejecting valid clients because the server did not yet see a new secret
key.
 
@@ -422,7 +438,7 @@ JVM to each YARN task is secure, even in multi-tenant instances.
 
 ==== Debugging
 
-*Q*: I have valid Kerberos credentials and a correct client configuration file but 
+*Q*: I have valid Kerberos credentials and a correct client configuration file but
 I still get errors like:
 
 ----
@@ -436,7 +452,7 @@ value, and ensure it matches the value reported by `klist`.
 ----
 $ echo $KRB5CCNAME
 
-$ klist 
+$ klist
 Ticket cache: FILE:/tmp/krb5cc_123
 Default principal: user@EXAMPLE.COM
 
@@ -462,7 +478,7 @@ diagnose some high-level configuration problem. Client applications can
add this
 hand to the command line and Accumulo server processes or applications started using the
`accumulo`
 script by adding the property to +ACCUMULO_GENERAL_OPTS+ in +$ACCUMULO_CONF_DIR/accumulo-env.sh+.
 
-Additionally, you can increase the log4j levels on +org.apache.hadoop.security+, which includes
the 
+Additionally, you can increase the log4j levels on +org.apache.hadoop.security+, which includes
the
 Hadoop +UserGroupInformation+ class, which will include some high-level debug statements.
This
 can be controlled in your client application, or using +$ACCUMULO_CONF_DIR/generic_logger.xml+
 
@@ -513,7 +529,7 @@ Caused by: KrbException: Identifier doesn't match expected value (906)
         ... 25 more
 ----
 
-or 
+or
 
 ----
 2015-01-12 14:47:29,440 [server.TThreadPoolServer] ERROR: Error occurred during processing
of message.

http://git-wip-us.apache.org/repos/asf/accumulo/blob/e43e9273/server/base/src/main/java/org/apache/accumulo/server/security/UserImpersonation.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/security/UserImpersonation.java
b/server/base/src/main/java/org/apache/accumulo/server/security/UserImpersonation.java
index 2a1fd00..97bc858 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/security/UserImpersonation.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/security/UserImpersonation.java
@@ -35,9 +35,12 @@ import org.slf4j.LoggerFactory;
  * When SASL is enabled, this parses properties from the site configuration to build up a
set of all users capable of impersonating another user, the users
  * which may be impersonated and the hosts in which the impersonator may issue requests from.
  *
- * <code>rpc_user=&gt;{allowed_accumulo_users=[...], allowed_client_hosts=[...]</code>
+ * <code>INSTANCE_RPC_SASL_PROXYUSERS=rpc_user={allowed_accumulo_users=[...], allowed_client_hosts=[...]</code>
+ * <code>INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION=rpc_user:user,user,user;...</code>
+ * <code>INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION=host,host:host...</code>
  *
- * @see Property#INSTANCE_RPC_SASL_PROXYUSERS
+ * @see Property#INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION
+ * @see Property#INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION
  */
 public class UserImpersonation {
 
@@ -170,11 +173,97 @@ public class UserImpersonation {
 
   private final Map<String,UsersWithHosts> proxyUsers;
 
+  @SuppressWarnings("deprecation")
   public UserImpersonation(AccumuloConfiguration conf) {
-    Map<String,String> entries = conf.getAllPropertiesWithPrefix(Property.INSTANCE_RPC_SASL_PROXYUSERS);
     proxyUsers = new HashMap<>();
+
+    // Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION is treated as the "new config
style" switch
+    final String userConfig = conf.get(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION);
+    if (!Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION.getDefaultValue().equals(userConfig))
{
+      String hostConfig = conf.get(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION);
+      parseOnelineConfiguration(userConfig, hostConfig);
+    } else {
+      // Otherwise, assume the old-style
+      parseMultiPropertyConfiguration(conf.getAllPropertiesWithPrefix(Property.INSTANCE_RPC_SASL_PROXYUSERS));
+    }
+  }
+
+  /**
+   * Parses the impersonation configuration for all users from a single property.
+   *
+   * @param userConfigString
+   *          Semi-colon separated list of {@code remoteUser:alloweduser,alloweduser,...}.
+   * @param hostConfigString
+   *          Semi-colon separated list of hosts.
+   */
+  private void parseOnelineConfiguration(String userConfigString, String hostConfigString)
{
+    // Pull out the config values, defaulting to at least one value
+    final String[] userConfigs;
+    if (userConfigString.trim().isEmpty()) {
+      userConfigs = new String[] {""};
+    } else {
+      userConfigs = StringUtils.split(userConfigString, ';');
+    }
+    final String[] hostConfigs;
+    if (hostConfigString.trim().isEmpty()) {
+      hostConfigs = new String[] {""};
+    } else {
+      hostConfigs = StringUtils.split(hostConfigString, ';');
+    }
+
+    if (userConfigs.length != hostConfigs.length) {
+      String msg = String.format("Should have equal number of user and host impersonation
elements in configuration. Got %d and %d elements, respectively.",
+          userConfigs.length, hostConfigs.length);
+      throw new IllegalArgumentException(msg);
+    }
+
+    for (int i = 0; i < userConfigs.length; i++) {
+      final String userConfig = userConfigs[i];
+      final String hostConfig = hostConfigs[i];
+
+      final String[] splitUserConfig = StringUtils.split(userConfig, ':');
+      if (2 != splitUserConfig.length) {
+        throw new IllegalArgumentException("Expect a single colon-separated pair, but found
'" + userConfig + "'");
+      }
+
+      final String remoteUser = splitUserConfig[0];
+      final String allowedImpersonationsForRemoteUser = splitUserConfig[1];
+      final UsersWithHosts usersWithHosts = new UsersWithHosts();
+
+      proxyUsers.put(remoteUser.trim(), usersWithHosts);
+
+      if (ALL.equals(allowedImpersonationsForRemoteUser)) {
+        usersWithHosts.setAcceptAllUsers(true);
+      } else {
+        String[] allowedUsers = StringUtils.split(allowedImpersonationsForRemoteUser, ",");
+        Set<String> usersSet = new HashSet<>();
+        usersSet.addAll(Arrays.asList(allowedUsers));
+        usersWithHosts.setUsers(usersSet);
+      }
+
+      if (ALL.equals(hostConfig)) {
+        usersWithHosts.setAcceptAllHosts(true);
+      } else {
+        String[] allowedHosts = StringUtils.split(hostConfig, ",");
+        Set<String> hostsSet = new HashSet<>();
+        hostsSet.addAll(Arrays.asList(allowedHosts));
+        usersWithHosts.setHosts(hostsSet);
+      }
+    }
+  }
+
+  /**
+   * Parses all properties that start with {@link Property#INSTANCE_RPC_SASL_PROXYUSERS}.
This approach was the original configuration method, but does not work
+   * with Ambari.
+   *
+   * @param configProperties
+   *          The relevant configuration properties for impersonation.
+   */
+  @SuppressWarnings("javadoc")
+  private void parseMultiPropertyConfiguration(Map<String,String> configProperties)
{
+    @SuppressWarnings("deprecation")
     final String configKey = Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey();
-    for (Entry<String,String> entry : entries.entrySet()) {
+    for (Entry<String,String> entry : configProperties.entrySet()) {
       String aclKey = entry.getKey().substring(configKey.length());
       int index = aclKey.lastIndexOf('.');
 

http://git-wip-us.apache.org/repos/asf/accumulo/blob/e43e9273/server/base/src/test/java/org/apache/accumulo/server/rpc/TCredentialsUpdatingInvocationHandlerTest.java
----------------------------------------------------------------------
diff --git a/server/base/src/test/java/org/apache/accumulo/server/rpc/TCredentialsUpdatingInvocationHandlerTest.java
b/server/base/src/test/java/org/apache/accumulo/server/rpc/TCredentialsUpdatingInvocationHandlerTest.java
index c2d182e..740acd9 100644
--- a/server/base/src/test/java/org/apache/accumulo/server/rpc/TCredentialsUpdatingInvocationHandlerTest.java
+++ b/server/base/src/test/java/org/apache/accumulo/server/rpc/TCredentialsUpdatingInvocationHandlerTest.java
@@ -17,6 +17,7 @@
 package org.apache.accumulo.server.rpc;
 
 import java.nio.ByteBuffer;
+import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -24,7 +25,9 @@ import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 import org.apache.accumulo.core.client.security.tokens.KerberosToken;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
 import org.apache.accumulo.core.conf.ConfigurationCopy;
+import org.apache.accumulo.core.conf.DefaultConfiguration;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.security.thrift.TCredentials;
 import org.junit.After;
@@ -32,14 +35,34 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.base.Predicate;
+
 public class TCredentialsUpdatingInvocationHandlerTest {
+  private static final DefaultConfiguration DEFAULT_CONFIG = DefaultConfiguration.getInstance();
 
   TCredentialsUpdatingInvocationHandler<Object> proxy;
-  ConfigurationCopy conf;
+  ConfigurationCopy cc;
+  AccumuloConfiguration conf;
 
   @Before
   public void setup() {
-    conf = new ConfigurationCopy();
+    cc = new ConfigurationCopy();
+    conf = new AccumuloConfiguration() {
+      @Override
+      public String get(Property property) {
+        String value = cc.get(property);
+        if (null == value) {
+          return DEFAULT_CONFIG.get(property);
+        }
+        return value;
+      }
+
+      @Override
+      public void getProperties(Map<String,String> props, Predicate<String> filter)
{
+        cc.getProperties(props, filter);
+      }
+    };
+
     proxy = new TCredentialsUpdatingInvocationHandler<Object>(new Object(), conf);
   }
 
@@ -97,8 +120,8 @@ public class TCredentialsUpdatingInvocationHandlerTest {
   @Test
   public void testAllowedAnyImpersonationForAnyUser() throws Exception {
     final String proxyServer = "proxy";
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", "*");
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", "*");
     proxy = new TCredentialsUpdatingInvocationHandler<Object>(new Object(), conf);
     TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0),
UUID.randomUUID().toString());
     UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
@@ -108,8 +131,8 @@ public class TCredentialsUpdatingInvocationHandlerTest {
   @Test
   public void testAllowedImpersonationForSpecificUsers() throws Exception {
     final String proxyServer = "proxy";
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", "client1,client2");
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", "client1,client2");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", "*");
     proxy = new TCredentialsUpdatingInvocationHandler<Object>(new Object(), conf);
     TCredentials tcreds = new TCredentials("client1", KerberosToken.class.getName(), ByteBuffer.allocate(0),
UUID.randomUUID().toString());
     UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
@@ -122,8 +145,8 @@ public class TCredentialsUpdatingInvocationHandlerTest {
   public void testDisallowedImpersonationForUser() throws Exception {
     final String proxyServer = "proxy";
     // let "otherproxy" impersonate, but not "proxy"
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy" + ".users", "*");
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy" + ".hosts", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy" + ".users", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy" + ".hosts", "*");
     proxy = new TCredentialsUpdatingInvocationHandler<Object>(new Object(), conf);
     TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0),
UUID.randomUUID().toString());
     UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
@@ -134,10 +157,10 @@ public class TCredentialsUpdatingInvocationHandlerTest {
   public void testDisallowedImpersonationForMultipleUsers() throws Exception {
     final String proxyServer = "proxy";
     // let "otherproxy" impersonate, but not "proxy"
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy1" + ".users", "*");
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy1" + ".hosts", "*");
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy2" + ".users", "client1,client2");
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy2" + ".hosts", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy1" + ".users", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy1" + ".hosts", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy2" + ".users", "client1,client2");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy2" + ".hosts", "*");
     proxy = new TCredentialsUpdatingInvocationHandler<Object>(new Object(), conf);
     TCredentials tcreds = new TCredentials("client1", KerberosToken.class.getName(), ByteBuffer.allocate(0),
UUID.randomUUID().toString());
     UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
@@ -147,8 +170,8 @@ public class TCredentialsUpdatingInvocationHandlerTest {
   @Test
   public void testAllowedImpersonationFromSpecificHost() throws Exception {
     final String proxyServer = "proxy", client = "client", host = "host.domain.com";
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", client);
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", host);
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", client);
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", host);
     proxy = new TCredentialsUpdatingInvocationHandler<Object>(new Object(), conf);
     TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0),
UUID.randomUUID().toString());
     UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
@@ -159,8 +182,8 @@ public class TCredentialsUpdatingInvocationHandlerTest {
   @Test(expected = ThriftSecurityException.class)
   public void testDisallowedImpersonationFromSpecificHost() throws Exception {
     final String proxyServer = "proxy", client = "client", host = "host.domain.com";
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", client);
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", host);
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", client);
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", host);
     proxy = new TCredentialsUpdatingInvocationHandler<Object>(new Object(), conf);
     TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0),
UUID.randomUUID().toString());
     UGIAssumingProcessor.rpcPrincipal.set(proxyServer);

http://git-wip-us.apache.org/repos/asf/accumulo/blob/e43e9273/server/base/src/test/java/org/apache/accumulo/server/security/UserImpersonationTest.java
----------------------------------------------------------------------
diff --git a/server/base/src/test/java/org/apache/accumulo/server/security/UserImpersonationTest.java
b/server/base/src/test/java/org/apache/accumulo/server/security/UserImpersonationTest.java
index 0f4159b..7422db4 100644
--- a/server/base/src/test/java/org/apache/accumulo/server/security/UserImpersonationTest.java
+++ b/server/base/src/test/java/org/apache/accumulo/server/security/UserImpersonationTest.java
@@ -24,8 +24,12 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
 
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
 import org.apache.accumulo.core.conf.ConfigurationCopy;
+import org.apache.accumulo.core.conf.DefaultConfiguration;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.server.security.UserImpersonation.AlwaysTrueSet;
 import org.apache.accumulo.server.security.UserImpersonation.UsersWithHosts;
@@ -33,17 +37,34 @@ import org.junit.Before;
 import org.junit.Test;
 
 import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
 
-/**
- *
- */
 public class UserImpersonationTest {
 
-  private ConfigurationCopy conf;
+  private ConfigurationCopy cc;
+  private AccumuloConfiguration conf;
 
   @Before
   public void setup() {
-    conf = new ConfigurationCopy(new HashMap<String,String>());
+    cc = new ConfigurationCopy(new HashMap<String,String>());
+    conf = new AccumuloConfiguration() {
+      DefaultConfiguration defaultConfig = DefaultConfiguration.getInstance();
+
+      @Override
+      public String get(Property property) {
+        String value = cc.get(property);
+        if (null == value) {
+          return defaultConfig.get(property);
+        }
+        return value;
+      }
+
+      @Override
+      public void getProperties(Map<String,String> props, Predicate<String> filter)
{
+        cc.getProperties(props, filter);
+      }
+    };
   }
 
   void setValidHosts(String user, String hosts) {
@@ -54,8 +75,24 @@ public class UserImpersonationTest {
     setUsersOrHosts(user, ".users", users);
   }
 
+  @SuppressWarnings("deprecation")
   void setUsersOrHosts(String user, String suffix, String value) {
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + user + suffix, value);
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + user + suffix, value);
+  }
+
+  void setValidHostsNewConfig(String user, String... hosts) {
+    cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION.getKey(), Joiner.on(';').join(hosts));
+  }
+
+  void setValidUsersNewConfig(Map<String,String> remoteToAllowedUsers) {
+    StringBuilder sb = new StringBuilder();
+    for (Entry<String,String> entry : remoteToAllowedUsers.entrySet()) {
+      if (sb.length() > 0) {
+        sb.append(";");
+      }
+      sb.append(entry.getKey()).append(":").append(entry.getValue());
+    }
+    cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, sb.toString());
   }
 
   @Test
@@ -76,6 +113,23 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testAnyUserAndHostsNewConfig() {
+    String server = "server";
+    setValidHostsNewConfig(server, "*");
+    setValidUsersNewConfig(ImmutableMap.of(server, "*"));
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+    assertNotNull(uwh);
+
+    assertTrue(uwh.acceptsAllHosts());
+    assertTrue(uwh.acceptsAllUsers());
+
+    assertEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+  }
+
+  @Test
   public void testNoHostByDefault() {
     String server = "server";
     setValidUsers(server, "*");
@@ -92,6 +146,22 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testNoHostByDefaultNewConfig() {
+    String server = "server";
+    setValidUsersNewConfig(ImmutableMap.of(server, "*"));
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+    assertNotNull(uwh);
+
+    assertFalse(uwh.acceptsAllHosts());
+    assertTrue(uwh.acceptsAllUsers());
+
+    assertNotEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+  }
+
+  @Test
   public void testNoUsersByDefault() {
     String server = "server";
     setValidHosts(server, "*");
@@ -108,6 +178,16 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testNoUsersByDefaultNewConfig() {
+    String server = "server";
+    setValidHostsNewConfig(server, "*");
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+    assertNull("Impersonation config should be drive by user element, not host", uwh);
+  }
+
+  @Test
   public void testSingleUserAndHost() {
     String server = "server", host = "single_host.domain.com", client = "single_client";
     setValidHosts(server, host);
@@ -131,6 +211,29 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testSingleUserAndHostNewConfig() {
+    String server = "server", host = "single_host.domain.com", client = "single_client";
+    setValidHostsNewConfig(server, host);
+    setValidUsersNewConfig(ImmutableMap.of(server, client));
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+    assertNotNull(uwh);
+
+    assertFalse(uwh.acceptsAllHosts());
+    assertFalse(uwh.acceptsAllUsers());
+
+    assertNotEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertNotEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+
+    assertTrue(uwh.getUsers().contains(client));
+    assertTrue(uwh.getHosts().contains(host));
+
+    assertFalse(uwh.getUsers().contains("some_other_user"));
+    assertFalse(uwh.getHosts().contains("other_host.domain.com"));
+  }
+
+  @Test
   public void testMultipleExplicitUsers() {
     String server = "server", client1 = "client1", client2 = "client2", client3 = "client3";
     setValidHosts(server, "*");
@@ -153,6 +256,28 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testMultipleExplicitUsersNewConfig() {
+    String server = "server", client1 = "client1", client2 = "client2", client3 = "client3";
+    setValidHostsNewConfig(server, "*");
+    setValidUsersNewConfig(ImmutableMap.of(server, Joiner.on(',').join(client1, client2,
client3)));
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+    assertNotNull(uwh);
+
+    assertTrue(uwh.acceptsAllHosts());
+    assertFalse(uwh.acceptsAllUsers());
+
+    assertEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertNotEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+
+    assertTrue(uwh.getUsers().contains(client1));
+    assertTrue(uwh.getUsers().contains(client2));
+    assertTrue(uwh.getUsers().contains(client3));
+    assertFalse(uwh.getUsers().contains("other_client"));
+  }
+
+  @Test
   public void testMultipleExplicitHosts() {
     String server = "server", host1 = "host1", host2 = "host2", host3 = "host3";
     setValidHosts(server, Joiner.on(',').join(host1, host2, host3));
@@ -175,6 +300,28 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testMultipleExplicitHostsNewConfig() {
+    String server = "server", host1 = "host1", host2 = "host2", host3 = "host3";
+    setValidHostsNewConfig(server, Joiner.on(',').join(host1, host2, host3));
+    setValidUsersNewConfig(ImmutableMap.of(server, "*"));
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+    assertNotNull(uwh);
+
+    assertFalse(uwh.acceptsAllHosts());
+    assertTrue(uwh.acceptsAllUsers());
+
+    assertNotEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+
+    assertTrue(uwh.getHosts().contains(host1));
+    assertTrue(uwh.getHosts().contains(host2));
+    assertTrue(uwh.getHosts().contains(host3));
+    assertFalse(uwh.getHosts().contains("other_host"));
+  }
+
+  @Test
   public void testMultipleExplicitUsersHosts() {
     String server = "server", host1 = "host1", host2 = "host2", host3 = "host3", client1
= "client1", client2 = "client2", client3 = "client3";
     setValidHosts(server, Joiner.on(',').join(host1, host2, host3));
@@ -202,6 +349,33 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testMultipleExplicitUsersHostsNewConfig() {
+    String server = "server", host1 = "host1", host2 = "host2", host3 = "host3", client1
= "client1", client2 = "client2", client3 = "client3";
+    setValidHostsNewConfig(server, Joiner.on(',').join(host1, host2, host3));
+    setValidUsersNewConfig(ImmutableMap.of(server, Joiner.on(',').join(client1, client2,
client3)));
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+    assertNotNull(uwh);
+
+    assertFalse(uwh.acceptsAllHosts());
+    assertFalse(uwh.acceptsAllUsers());
+
+    assertNotEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertNotEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+
+    assertTrue(uwh.getUsers().contains(client1));
+    assertTrue(uwh.getUsers().contains(client2));
+    assertTrue(uwh.getUsers().contains(client3));
+    assertFalse(uwh.getUsers().contains("other_client"));
+
+    assertTrue(uwh.getHosts().contains(host1));
+    assertTrue(uwh.getHosts().contains(host2));
+    assertTrue(uwh.getHosts().contains(host3));
+    assertFalse(uwh.getHosts().contains("other_host"));
+  }
+
+  @Test
   public void testMultipleAllowedImpersonators() {
     String server1 = "server1", server2 = "server2", host1 = "host1", host2 = "host2", host3
= "host3", client1 = "client1", client2 = "client2", client3 = "client3";
     // server1 can impersonate client1 and client2 from host1 or host2
@@ -255,10 +429,79 @@ public class UserImpersonationTest {
   }
 
   @Test
+  public void testMultipleAllowedImpersonatorsNewConfig() {
+    String server1 = "server1", server2 = "server2", host1 = "host1", host2 = "host2", host3
= "host3", client1 = "client1", client2 = "client2", client3 = "client3";
+    // server1 can impersonate client1 and client2 from host1 or host2
+    // server2 can impersonate only client3 from host3
+    setValidHostsNewConfig(server1, Joiner.on(',').join(host1, host2), host3);
+    setValidUsersNewConfig(ImmutableMap.of(server1, Joiner.on(',').join(client1, client2),
server2, client3));
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server1);
+    assertNotNull(uwh);
+
+    assertFalse(uwh.acceptsAllHosts());
+    assertFalse(uwh.acceptsAllUsers());
+
+    assertNotEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertNotEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+
+    assertTrue(uwh.getUsers().contains(client1));
+    assertTrue(uwh.getUsers().contains(client2));
+    assertFalse(uwh.getUsers().contains(client3));
+    assertFalse(uwh.getUsers().contains("other_client"));
+
+    assertTrue(uwh.getHosts().contains(host1));
+    assertTrue(uwh.getHosts().contains(host2));
+    assertFalse(uwh.getHosts().contains(host3));
+    assertFalse(uwh.getHosts().contains("other_host"));
+
+    uwh = impersonation.get(server2);
+    assertNotNull(uwh);
+
+    assertFalse(uwh.acceptsAllHosts());
+    assertFalse(uwh.acceptsAllUsers());
+
+    assertNotEquals(AlwaysTrueSet.class, uwh.getHosts().getClass());
+    assertNotEquals(AlwaysTrueSet.class, uwh.getUsers().getClass());
+
+    assertFalse(uwh.getUsers().contains(client1));
+    assertFalse(uwh.getUsers().contains(client2));
+    assertTrue(uwh.getUsers().contains(client3));
+    assertFalse(uwh.getUsers().contains("other_client"));
+
+    assertFalse(uwh.getHosts().contains(host1));
+    assertFalse(uwh.getHosts().contains(host2));
+    assertTrue(uwh.getHosts().contains(host3));
+    assertFalse(uwh.getHosts().contains("other_host"));
+
+    // client3 is not allowed to impersonate anyone
+    assertNull(impersonation.get(client3));
+  }
+
+  @SuppressWarnings("deprecation")
+  @Test
   public void testSingleUser() throws Exception {
     final String server = "server/hostname@EXAMPLE.COM", client = "client@EXAMPLE.COM";
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + server + ".users", client);
-    conf.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + server + ".hosts", "*");
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + server + ".users", client);
+    cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + server + ".hosts", "*");
+    UserImpersonation impersonation = new UserImpersonation(conf);
+
+    UsersWithHosts uwh = impersonation.get(server);
+
+    assertNotNull(uwh);
+
+    assertTrue(uwh.acceptsAllHosts());
+    assertFalse(uwh.acceptsAllUsers());
+
+    assertTrue(uwh.getUsers().contains(client));
+  }
+
+  @Test
+  public void testSingleUserNewConfig() throws Exception {
+    final String server = "server/hostname@EXAMPLE.COM", client = "client@EXAMPLE.COM";
+    cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, server + ":" + client);
+    cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION, "*");
     UserImpersonation impersonation = new UserImpersonation(conf);
 
     UsersWithHosts uwh = impersonation.get(server);


Mime
View raw message