You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by dd...@apache.org on 2013/11/01 17:56:25 UTC

svn commit: r1537986 - in /hbase/trunk: hbase-client/src/main/java/org/apache/hadoop/hbase/security/ hbase-server/src/test/java/org/apache/hadoop/hbase/security/

Author: ddas
Date: Fri Nov  1 16:56:24 2013
New Revision: 1537986

URL: http://svn.apache.org/r1537986
Log:
HBASE-8569. Improve coverage in package org.apache.hadoop.hbase.security. Contributed by Vadim Bondarev and  Andrey Klochkov

Added:
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/HBaseKerberosUtils.java
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUsersOperationsWithSecureHadoop.java
Modified:
    hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUser.java

Modified: hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java?rev=1537986&r1=1537985&r2=1537986&view=diff
==============================================================================
--- hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java (original)
+++ hbase/trunk/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java Fri Nov  1 16:56:24 2013
@@ -37,6 +37,7 @@ import javax.security.sasl.RealmChoiceCa
 import javax.security.sasl.Sasl;
 import javax.security.sasl.SaslClient;
 import javax.security.sasl.SaslException;
+
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.DataInputStream;
@@ -45,6 +46,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import com.google.common.annotations.VisibleForTesting;
+
 /**
  * A utility class that encapsulates SASL logic for RPC client.
  * Copied from <code>org.apache.hadoop.security</code>
@@ -72,9 +75,9 @@ public class HBaseSaslRpcClient {
       if (LOG.isDebugEnabled())
         LOG.debug("Creating SASL " + AuthMethod.DIGEST.getMechanismName()
             + " client to authenticate to service at " + token.getService());
-      saslClient = Sasl.createSaslClient(new String[] { AuthMethod.DIGEST
-          .getMechanismName() }, null, null, SaslUtil.SASL_DEFAULT_REALM,
-          SaslUtil.SASL_PROPS, new SaslClientCallbackHandler(token));
+      saslClient = createDigestSaslClient(
+          new String[] { AuthMethod.DIGEST.getMechanismName() },
+          SaslUtil.SASL_DEFAULT_REALM, new SaslClientCallbackHandler(token));
       break;
     case KERBEROS:
       if (LOG.isDebugEnabled()) {
@@ -93,9 +96,9 @@ public class HBaseSaslRpcClient {
           "Kerberos principal does not have the expected format: "
                 + serverPrincipal);
       }
-      saslClient = Sasl.createSaslClient(new String[] { AuthMethod.KERBEROS
-          .getMechanismName() }, null, names[0], names[1],
-          SaslUtil.SASL_PROPS, null);
+      saslClient = createKerberosSaslClient(
+          new String[] { AuthMethod.KERBEROS.getMechanismName() },
+          names[0], names[1]);
       break;
     default:
       throw new IOException("Unknown authentication method " + method);
@@ -104,6 +107,19 @@ public class HBaseSaslRpcClient {
       throw new IOException("Unable to find SASL client implementation");
   }
 
+  protected SaslClient createDigestSaslClient(String[] mechanismNames, 
+      String saslDefaultRealm, CallbackHandler saslClientCallbackHandler) 
+      throws IOException {
+    return Sasl.createSaslClient(mechanismNames, null, null, saslDefaultRealm,
+        SaslUtil.SASL_PROPS, saslClientCallbackHandler);
+  }
+
+  protected SaslClient createKerberosSaslClient(String[] mechanismNames,
+      String userFirstPart, String userSecondPart) throws IOException {
+    return Sasl.createSaslClient(mechanismNames, null, userFirstPart, 
+        userSecondPart, SaslUtil.SASL_PROPS, null);
+  }
+
   private static void readStatus(DataInputStream inStream) throws IOException {
     int status = inStream.readInt(); // read status
     if (status != SaslStatus.SUCCESS.state) {
@@ -234,7 +250,8 @@ public class HBaseSaslRpcClient {
     saslClient.dispose();
   }
 
-  private static class SaslClientCallbackHandler implements CallbackHandler {
+  @VisibleForTesting
+  static class SaslClientCallbackHandler implements CallbackHandler {
     private final String userName;
     private final char[] userPassword;
 

Added: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/HBaseKerberosUtils.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/HBaseKerberosUtils.java?rev=1537986&view=auto
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/HBaseKerberosUtils.java (added)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/HBaseKerberosUtils.java Fri Nov  1 16:56:24 2013
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.security;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeys;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+
+import com.google.common.base.Strings;
+
+class HBaseKerberosUtils {
+  public static final String KRB_PRINCIPAL = "hbase.regionserver.kerberos.principal";
+  public static final String KRB_KEYTAB_FILE = "hbase.regionserver.keytab.file";
+
+  static boolean isKerberosPropertySetted() {
+    String krbPrincipal = System.getProperty(KRB_PRINCIPAL);
+    String krbKeytab = System.getProperty(KRB_KEYTAB_FILE);
+    if (Strings.isNullOrEmpty(krbPrincipal) || Strings.isNullOrEmpty(krbKeytab)) {
+      return false;
+    }
+    return true;
+  }
+
+  static void setPrincipalForTesting(String principal) {
+    setSystemProperty(KRB_PRINCIPAL, principal);
+  }
+
+  static void setKeytabFileForTesting(String keytabFile) {
+    setSystemProperty(KRB_KEYTAB_FILE, keytabFile);
+  }
+
+  static void setSystemProperty(String propertyName, String propertyValue) {
+    System.setProperty(propertyName, propertyValue);
+  }
+
+  static String getKeytabFileForTesting() {
+    return System.getProperty(KRB_KEYTAB_FILE);
+  }
+
+  static String getPrincipalForTesting() {
+    return System.getProperty(KRB_PRINCIPAL);
+  }
+
+  static Configuration getConfigurationWoPrincipal() {
+    Configuration conf = HBaseConfiguration.create();
+    conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
+    conf.set("hbase.security.authentication", "kerberos");
+    conf.setBoolean("hbase.security.authorization", true);
+    return conf;
+  }
+
+  static Configuration getSecuredConfiguration() {
+    Configuration conf = HBaseConfiguration.create();
+    conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
+    conf.set("hbase.security.authentication", "kerberos");
+    conf.setBoolean("hbase.security.authorization", true);
+    conf.set(KRB_KEYTAB_FILE, System.getProperty(KRB_KEYTAB_FILE));
+    conf.set(KRB_PRINCIPAL, System.getProperty(KRB_PRINCIPAL));
+    return conf;
+  }
+}
\ No newline at end of file

Added: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java?rev=1537986&view=auto
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java (added)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java Fri Nov  1 16:56:24 2013
@@ -0,0 +1,283 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.security;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.RealmCallback;
+import javax.security.sasl.RealmChoiceCallback;
+import javax.security.sasl.SaslClient;
+
+import org.apache.hadoop.hbase.SmallTests;
+import org.apache.hadoop.hbase.security.HBaseSaslRpcClient.SaslClientCallbackHandler;
+import org.apache.hadoop.io.DataInputBuffer;
+import org.apache.hadoop.io.DataOutputBuffer;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.TokenIdentifier;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.Mockito;
+
+import com.google.common.base.Strings;
+
+@Category(SmallTests.class)
+public class TestHBaseSaslRpcClient {
+  
+  static {
+    System.setProperty("java.security.krb5.realm", "DOMAIN.COM");
+    System.setProperty("java.security.krb5.kdc", "DOMAIN.COM");
+  }
+  
+  static final String DEFAULT_USER_NAME = "principal";
+  static final String DEFAULT_USER_PASSWORD = "password";
+
+  private static final Logger LOG = Logger.getLogger(TestHBaseSaslRpcClient.class);
+
+  @BeforeClass
+  public static void before() {
+    Logger.getRootLogger().setLevel(Level.DEBUG);
+  }
+
+  @Test
+  public void testSaslClientCallbackHandler() throws UnsupportedCallbackException {
+    final Token<? extends TokenIdentifier> token = createTokenMock();
+    when(token.getIdentifier()).thenReturn(DEFAULT_USER_NAME.getBytes());
+    when(token.getPassword()).thenReturn(DEFAULT_USER_PASSWORD.getBytes());
+
+    final NameCallback nameCallback = mock(NameCallback.class);
+    final PasswordCallback passwordCallback = mock(PasswordCallback.class);
+    final RealmCallback realmCallback = mock(RealmCallback.class);
+    final RealmChoiceCallback realmChoiceCallback = mock(RealmChoiceCallback.class);
+
+    Callback[] callbackArray = {nameCallback, passwordCallback,
+        realmCallback, realmChoiceCallback};
+    final SaslClientCallbackHandler saslClCallbackHandler = new SaslClientCallbackHandler(token);
+    saslClCallbackHandler.handle(callbackArray);
+    verify(nameCallback).setName(anyString());
+    verify(realmCallback).setText(anyString());
+    verify(passwordCallback).setPassword(any(char[].class));
+  }
+
+  @Test
+  public void testSaslClientCallbackHandlerWithException() {
+    final Token<? extends TokenIdentifier> token = createTokenMock();
+    when(token.getIdentifier()).thenReturn(DEFAULT_USER_NAME.getBytes());
+    when(token.getPassword()).thenReturn(DEFAULT_USER_PASSWORD.getBytes());
+    final SaslClientCallbackHandler saslClCallbackHandler = new SaslClientCallbackHandler(token);
+    try {
+      saslClCallbackHandler.handle(new Callback[] { mock(TextOutputCallback.class) });
+    } catch (UnsupportedCallbackException expEx) {
+      //expected
+    } catch (Exception ex) {
+      fail("testSaslClientCallbackHandlerWithException error : " + ex.getMessage());
+    }
+  }
+
+  @Test
+  public void testHBaseSaslRpcClientCreation() throws Exception {
+    //creation kerberos principal check section
+    assertFalse(assertSuccessCreationKerberosPrincipal(null));
+    assertFalse(assertSuccessCreationKerberosPrincipal("DOMAIN.COM"));
+    assertFalse(assertSuccessCreationKerberosPrincipal("principal/DOMAIN.COM"));
+    assertTrue(assertSuccessCreationKerberosPrincipal("principal/localhost@DOMAIN.COM"));
+
+    //creation digest principal check section
+    assertFalse(assertSuccessCreationDigestPrincipal(null, null));
+    assertFalse(assertSuccessCreationDigestPrincipal("", ""));
+    assertFalse(assertSuccessCreationDigestPrincipal("", null));
+    assertFalse(assertSuccessCreationDigestPrincipal(null, ""));
+    assertTrue(assertSuccessCreationDigestPrincipal(DEFAULT_USER_NAME, DEFAULT_USER_PASSWORD));
+
+    //creation simple principal check section
+    assertFalse(assertSuccessCreationSimplePrincipal("", ""));
+    assertFalse(assertSuccessCreationSimplePrincipal(null, null));
+    assertFalse(assertSuccessCreationSimplePrincipal(DEFAULT_USER_NAME, DEFAULT_USER_PASSWORD));
+
+    //exceptions check section
+    assertTrue(assertIOExceptionThenSaslClientIsNull(DEFAULT_USER_NAME, DEFAULT_USER_PASSWORD));
+    assertTrue(assertIOExceptionWhenGetStreamsBeforeConnectCall(
+        DEFAULT_USER_NAME, DEFAULT_USER_PASSWORD));
+  }
+
+  @Test
+  public void testAuthMethodReadWrite() throws IOException {
+    DataInputBuffer in = new DataInputBuffer();
+    DataOutputBuffer out = new DataOutputBuffer();
+
+    assertAuthMethodRead(in, AuthMethod.SIMPLE);
+    assertAuthMethodRead(in, AuthMethod.KERBEROS);
+    assertAuthMethodRead(in, AuthMethod.DIGEST);
+
+    assertAuthMethodWrite(out, AuthMethod.SIMPLE);
+    assertAuthMethodWrite(out, AuthMethod.KERBEROS);
+    assertAuthMethodWrite(out, AuthMethod.DIGEST);
+  }
+
+  private void assertAuthMethodRead(DataInputBuffer in, AuthMethod authMethod)
+      throws IOException {
+    in.reset(new byte[] {authMethod.code}, 1);
+    assertEquals(authMethod, AuthMethod.read(in));
+  }
+
+  private void assertAuthMethodWrite(DataOutputBuffer out, AuthMethod authMethod)
+      throws IOException {
+    authMethod.write(out);
+    assertEquals(authMethod.code, out.getData()[0]);
+    out.reset();
+  }
+
+  private boolean assertIOExceptionWhenGetStreamsBeforeConnectCall(String principal,
+      String password) throws IOException {
+    boolean inState = false;
+    boolean outState = false;
+
+    HBaseSaslRpcClient rpcClient = new HBaseSaslRpcClient(AuthMethod.DIGEST, 
+        createTokenMockWithCredentials(principal, password), principal, false) {
+      @Override
+      public SaslClient createDigestSaslClient(String[] mechanismNames,
+          String saslDefaultRealm, CallbackHandler saslClientCallbackHandler)
+              throws IOException {
+        return Mockito.mock(SaslClient.class);
+      }
+
+      @Override
+      public SaslClient createKerberosSaslClient(String[] mechanismNames,
+          String userFirstPart, String userSecondPart) throws IOException {
+        return Mockito.mock(SaslClient.class);
+      }
+    };
+    
+    try {
+      rpcClient.getInputStream(Mockito.mock(InputStream.class));
+    } catch(IOException ex) {
+      //Sasl authentication exchange hasn't completed yet
+      inState = true;
+    }
+
+    try {
+      rpcClient.getOutputStream(Mockito.mock(OutputStream.class));
+    } catch(IOException ex) {
+      //Sasl authentication exchange hasn't completed yet
+      outState = true;
+    }
+
+    return inState && outState;
+  }
+
+  private boolean assertIOExceptionThenSaslClientIsNull(String principal, String password) {
+    try {
+      new HBaseSaslRpcClient(AuthMethod.DIGEST, 
+          createTokenMockWithCredentials(principal, password), principal, false) {
+        @Override
+        public SaslClient createDigestSaslClient(String[] mechanismNames,
+            String saslDefaultRealm, CallbackHandler saslClientCallbackHandler)
+                throws IOException {
+          return null;
+        }
+  
+        @Override
+        public SaslClient createKerberosSaslClient(String[] mechanismNames,
+            String userFirstPart, String userSecondPart) throws IOException {
+          return null;
+        }
+      };
+      return false;
+    } catch (IOException ex) {
+      return true;
+    }
+  }
+
+  private boolean assertSuccessCreationKerberosPrincipal(String principal) {
+    HBaseSaslRpcClient rpcClient = null;
+    try {
+      rpcClient = createSaslRpcClientForKerberos(principal);
+    } catch(Exception ex) {
+      LOG.error(ex.getMessage(), ex);
+    }
+    return rpcClient != null;
+  }
+
+  private boolean assertSuccessCreationDigestPrincipal(String principal, String password) {
+    HBaseSaslRpcClient rpcClient = null;
+    try {
+      rpcClient = new HBaseSaslRpcClient(AuthMethod.DIGEST, 
+          createTokenMockWithCredentials(principal, password), principal, false);
+    } catch(Exception ex) {
+      LOG.error(ex.getMessage(), ex);
+    }
+    return rpcClient != null;
+  }
+
+  private boolean assertSuccessCreationSimplePrincipal(String principal, String password) {
+    HBaseSaslRpcClient rpcClient = null;
+    try {
+      rpcClient = createSaslRpcClientSimple(principal, password);
+    } catch(Exception ex) {
+      LOG.error(ex.getMessage(), ex);
+    }
+    return rpcClient != null;
+  }
+
+  private HBaseSaslRpcClient createSaslRpcClientForKerberos(String principal)
+      throws IOException {
+    return new HBaseSaslRpcClient(AuthMethod.KERBEROS, createTokenMock(), principal, false);
+  }
+
+  private Token<? extends TokenIdentifier> createTokenMockWithCredentials(
+      String principal, String password)
+      throws IOException {
+    Token<? extends TokenIdentifier> token = createTokenMock();
+    if (!Strings.isNullOrEmpty(principal) && !Strings.isNullOrEmpty(password)) {
+      when(token.getIdentifier()).thenReturn(DEFAULT_USER_NAME.getBytes());
+      when(token.getPassword()).thenReturn(DEFAULT_USER_PASSWORD.getBytes());
+    }
+    return token;
+  }
+
+  private HBaseSaslRpcClient createSaslRpcClientSimple(String principal, String password)
+      throws IOException {
+    return new HBaseSaslRpcClient(AuthMethod.SIMPLE, createTokenMock(), principal, false);
+  }
+
+  @SuppressWarnings("unchecked")
+  private Token<? extends TokenIdentifier> createTokenMock() {
+    return mock(Token.class);
+  }
+}

Modified: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUser.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUser.java?rev=1537986&r1=1537985&r2=1537986&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUser.java (original)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUser.java Fri Nov  1 16:56:24 2013
@@ -18,19 +18,25 @@
  */
 package org.apache.hadoop.hbase.security;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeys;
 import org.apache.hadoop.hbase.HBaseConfiguration;
 import org.apache.hadoop.hbase.SmallTests;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import java.io.IOException;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
+import com.google.common.collect.ImmutableSet;
 
 @Category(SmallTests.class)
 public class TestUser {
@@ -75,7 +81,7 @@ public class TestUser {
     assertEquals("User name in runAs() should match", "testuser", username);
 
     // verify that nested contexts work
-    user2.runAs(new PrivilegedExceptionAction(){
+    user2.runAs(new PrivilegedExceptionAction<Object>(){
       public Object run() throws IOException, InterruptedException{
         String nestedName = user.runAs(action);
         assertEquals("Nest name should match nested user", "testuser", nestedName);
@@ -84,6 +90,22 @@ public class TestUser {
         return null;
       }
     });
+
+    username = user.runAs(new PrivilegedAction<String>(){
+      String result = null;
+      @Override
+      public String run() {
+        try {
+          return User.getCurrent().getName();
+        } catch (IOException e) {
+          result = "empty";
+        }
+        return result;
+      }
+    });
+
+    assertEquals("Current user within runAs() should match",
+        "testuser", username);
   }
 
   /**
@@ -106,5 +128,48 @@ public class TestUser {
     }
   }
 
-}
+  @Test
+  public void testUserGroupNames() throws Exception {
+    final String username = "testuser";
+    final ImmutableSet<String> singleGroups = ImmutableSet.of("group");
+    final Configuration conf = HBaseConfiguration.create();
+    User user = User.createUserForTesting(conf, username, singleGroups.toArray(new String[]{}));
+    assertUserGroup(user, singleGroups);
+
+    final ImmutableSet<String> multiGroups = ImmutableSet.of("group", "group1", "group2");
+    user = User.createUserForTesting(conf, username, multiGroups.toArray(new String[]{}));
+    assertUserGroup(user, multiGroups);
+  }
+
+  private void assertUserGroup(User user, ImmutableSet<String> groups) {
+    assertNotNull("GroupNames should be not null", user.getGroupNames());
+    assertTrue("UserGroupNames length should be == " + groups.size(),
+        user.getGroupNames().length == groups.size());
+
+    for (String group : user.getGroupNames()) {
+      assertTrue("groupName should be in set ", groups.contains(group));
+    }
+  }
+
+  @Test
+  public void testSecurityForNonSecureHadoop() {
+    assertFalse("Security should be disable in non-secure Hadoop",
+        User.isSecurityEnabled());
 
+    Configuration conf = HBaseConfiguration.create();
+    conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
+    conf.set(User.HBASE_SECURITY_CONF_KEY, "kerberos");
+    assertTrue("Security should be enabled", User.isHBaseSecurityEnabled(conf));
+
+    conf = HBaseConfiguration.create();
+    conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
+    assertFalse("HBase security should not be enabled if " 
+        + User.HBASE_SECURITY_CONF_KEY + " is not set accordingly",
+        User.isHBaseSecurityEnabled(conf));
+
+    conf = HBaseConfiguration.create();
+    conf.set(User.HBASE_SECURITY_CONF_KEY, "kerberos");
+    assertTrue("HBase security should be enabled regardless of underlying "
+        + "HDFS settings", User.isHBaseSecurityEnabled(conf));
+  }
+}

Added: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUsersOperationsWithSecureHadoop.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUsersOperationsWithSecureHadoop.java?rev=1537986&view=auto
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUsersOperationsWithSecureHadoop.java (added)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestUsersOperationsWithSecureHadoop.java Fri Nov  1 16:56:24 2013
@@ -0,0 +1,80 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.security;
+
+import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getConfigurationWoPrincipal;
+import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getKeytabFileForTesting;
+import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getPrincipalForTesting;
+import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getSecuredConfiguration;
+import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.isKerberosPropertySetted;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.IOException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.SmallTests;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category(SmallTests.class)
+public class TestUsersOperationsWithSecureHadoop {
+  /**
+   * test login with security enabled configuration
+   *
+   * To run this test, we must specify the following system properties:
+   * <p>
+   * <b> hbase.regionserver.kerberos.principal </b>
+   * <p>
+   * <b> hbase.regionserver.keytab.file </b>
+   *
+   * @throws IOException
+   */
+  @Test
+  public void testUserLoginInSecureHadoop() throws Exception {
+    UserGroupInformation defaultLogin = UserGroupInformation.getLoginUser();
+    Configuration conf = getConfigurationWoPrincipal();
+    User.login(conf, HBaseKerberosUtils.KRB_KEYTAB_FILE,
+        HBaseKerberosUtils.KRB_PRINCIPAL, "localhost");
+
+    UserGroupInformation failLogin = UserGroupInformation.getLoginUser();
+    assertTrue("ugi should be the same in case fail login",
+        defaultLogin.equals(failLogin));
+    
+    assumeTrue(isKerberosPropertySetted());
+
+    String nnKeyTab = getKeytabFileForTesting();
+    String dnPrincipal = getPrincipalForTesting();
+
+    assertNotNull("KerberosKeytab was not specified", nnKeyTab);
+    assertNotNull("KerberosPrincipal was not specified", dnPrincipal);
+
+    conf = getSecuredConfiguration();
+    UserGroupInformation.setConfiguration(conf);
+
+    User.login(conf, HBaseKerberosUtils.KRB_KEYTAB_FILE,
+        HBaseKerberosUtils.KRB_PRINCIPAL, "localhost");
+    UserGroupInformation successLogin = UserGroupInformation.getLoginUser();
+    assertFalse("ugi should be different in in case success login",
+       defaultLogin.equals(successLogin));
+  }
+}