View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.security;
20  
21  import java.io.IOException;
22  import java.security.PrivilegedAction;
23  import java.security.PrivilegedExceptionAction;
24  
25  import org.apache.commons.lang.SystemUtils;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.fs.CommonConfigurationKeys;
30  import org.apache.hadoop.hbase.HBaseConfiguration;
31  import org.apache.hadoop.hbase.testclassification.SmallTests;
32  import org.apache.hadoop.security.UserGroupInformation;
33  import org.junit.Test;
34  import org.junit.experimental.categories.Category;
35  
36  import com.google.common.collect.ImmutableSet;
37  
38  import static org.junit.Assert.*;
39  
40  @Category(SmallTests.class)
41  public class TestUser {
42    private static final Log LOG = LogFactory.getLog(TestUser.class);
43  
44    @Test
45    public void testCreateUserForTestingGroupCache() throws Exception {
46      Configuration conf = HBaseConfiguration.create();
47      User uCreated = User.createUserForTesting(conf, "group_user", new String[] { "MYGROUP" });
48      UserProvider up = UserProvider.instantiate(conf);
49      User uProvided = up.create(UserGroupInformation.createRemoteUser("group_user"));
50      assertArrayEquals(uCreated.getGroupNames(), uProvided.getGroupNames());
51  
52    }
53  
54    @Test
55    public void testCacheGetGroups() throws Exception {
56      Configuration conf = HBaseConfiguration.create();
57      UserProvider up = UserProvider.instantiate(conf);
58  
59      // VERY unlikely that this user will exist on the box.
60      // This should mean the user has no groups.
61      String nonUser = "kklvfnvhdhcenfnniilggljhdecjhidkle";
62  
63      // Create two UGI's for this username
64      UserGroupInformation ugiOne = UserGroupInformation.createRemoteUser(nonUser);
65      UserGroupInformation ugiTwo = UserGroupInformation.createRemoteUser(nonUser);
66  
67      // Now try and get the user twice.
68      User uOne = up.create(ugiOne);
69      User uTwo = up.create(ugiTwo);
70  
71      // Make sure that we didn't break groups and everything worked well.
72      assertArrayEquals(uOne.getGroupNames(),uTwo.getGroupNames());
73  
74      // Check that they are referentially equal.
75      // Since getting a group for a users that doesn't exist creates a new string array
76      // the only way that they should be referentially equal is if the cache worked and
77      // made sure we didn't go to hadoop's script twice.
78      assertTrue(uOne.getGroupNames() == uTwo.getGroupNames());
79      assertEquals(0, ugiOne.getGroupNames().length);
80    }
81  
82    @Test
83    public void testCacheGetGroupsRoot() throws Exception {
84      // Windows users don't have a root user.
85      // However pretty much every other *NIX os will have root.
86      if (!SystemUtils.IS_OS_WINDOWS) {
87        Configuration conf = HBaseConfiguration.create();
88        UserProvider up = UserProvider.instantiate(conf);
89  
90  
91        String rootUserName = "root";
92  
93        // Create two UGI's for this username
94        UserGroupInformation ugiOne = UserGroupInformation.createRemoteUser(rootUserName);
95        UserGroupInformation ugiTwo = UserGroupInformation.createRemoteUser(rootUserName);
96  
97        // Now try and get the user twice.
98        User uOne = up.create(ugiOne);
99        User uTwo = up.create(ugiTwo);
100 
101       // Make sure that we didn't break groups and everything worked well.
102       assertArrayEquals(uOne.getGroupNames(),uTwo.getGroupNames());
103       String[] groupNames = ugiOne.getGroupNames();
104       assertTrue(groupNames.length > 0);
105     }
106   }
107 
108 
109   @Test
110   public void testBasicAttributes() throws Exception {
111     Configuration conf = HBaseConfiguration.create();
112     User user = User.createUserForTesting(conf, "simple", new String[]{"foo"});
113     assertEquals("Username should match", "simple", user.getName());
114     assertEquals("Short username should match", "simple", user.getShortName());
115     // don't test shortening of kerberos names because regular Hadoop doesn't support them
116   }
117 
118   @Test
119   public void testRunAs() throws Exception {
120     Configuration conf = HBaseConfiguration.create();
121     final User user = User.createUserForTesting(conf, "testuser", new String[]{"foo"});
122     final PrivilegedExceptionAction<String> action = new PrivilegedExceptionAction<String>(){
123       public String run() throws IOException {
124           User u = User.getCurrent();
125           return u.getName();
126       }
127     };
128 
129     String username = user.runAs(action);
130     assertEquals("Current user within runAs() should match",
131         "testuser", username);
132 
133     // ensure the next run is correctly set
134     User user2 = User.createUserForTesting(conf, "testuser2", new String[]{"foo"});
135     String username2 = user2.runAs(action);
136     assertEquals("Second username should match second user",
137         "testuser2", username2);
138 
139     // check the exception version
140     username = user.runAs(new PrivilegedExceptionAction<String>(){
141       public String run() throws Exception {
142         return User.getCurrent().getName();
143       }
144     });
145     assertEquals("User name in runAs() should match", "testuser", username);
146 
147     // verify that nested contexts work
148     user2.runAs(new PrivilegedExceptionAction<Object>(){
149       public Object run() throws IOException, InterruptedException{
150         String nestedName = user.runAs(action);
151         assertEquals("Nest name should match nested user", "testuser", nestedName);
152         assertEquals("Current name should match current user",
153             "testuser2", User.getCurrent().getName());
154         return null;
155       }
156     });
157 
158     username = user.runAs(new PrivilegedAction<String>(){
159       String result = null;
160       @Override
161       public String run() {
162         try {
163           return User.getCurrent().getName();
164         } catch (IOException e) {
165           result = "empty";
166         }
167         return result;
168       }
169     });
170 
171     assertEquals("Current user within runAs() should match",
172         "testuser", username);
173   }
174 
175   /**
176    * Make sure that we're returning a result for the current user.
177    * Previously getCurrent() was returning null if not initialized on
178    * non-secure Hadoop variants.
179    */
180   @Test
181   public void testGetCurrent() throws Exception {
182     User user1 = User.getCurrent();
183     assertNotNull(user1.ugi);
184     LOG.debug("User1 is "+user1.getName());
185 
186     for (int i =0 ; i< 100; i++) {
187       User u = User.getCurrent();
188       assertNotNull(u);
189       assertEquals(user1.getName(), u.getName());
190       assertEquals(user1, u);
191       assertEquals(user1.hashCode(), u.hashCode());
192     }
193   }
194 
195   @Test
196   public void testUserGroupNames() throws Exception {
197     final String username = "testuser";
198     final ImmutableSet<String> singleGroups = ImmutableSet.of("group");
199     final Configuration conf = HBaseConfiguration.create();
200     User user = User.createUserForTesting(conf, username,
201         singleGroups.toArray(new String[singleGroups.size()]));
202     assertUserGroup(user, singleGroups);
203 
204     final ImmutableSet<String> multiGroups = ImmutableSet.of("group", "group1", "group2");
205     user = User.createUserForTesting(conf, username,
206         multiGroups.toArray(new String[multiGroups.size()]));
207     assertUserGroup(user, multiGroups);
208   }
209 
210   private void assertUserGroup(User user, ImmutableSet<String> groups) {
211     assertNotNull("GroupNames should be not null", user.getGroupNames());
212     assertTrue("UserGroupNames length should be == " + groups.size(),
213         user.getGroupNames().length == groups.size());
214 
215     for (String group : user.getGroupNames()) {
216       assertTrue("groupName should be in set ", groups.contains(group));
217     }
218   }
219 
220   @Test
221   public void testSecurityForNonSecureHadoop() {
222     assertFalse("Security should be disable in non-secure Hadoop",
223         User.isSecurityEnabled());
224 
225     Configuration conf = HBaseConfiguration.create();
226     conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
227     conf.set(User.HBASE_SECURITY_CONF_KEY, "kerberos");
228     assertTrue("Security should be enabled", User.isHBaseSecurityEnabled(conf));
229 
230     conf = HBaseConfiguration.create();
231     conf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
232     assertFalse("HBase security should not be enabled if " 
233         + User.HBASE_SECURITY_CONF_KEY + " is not set accordingly",
234         User.isHBaseSecurityEnabled(conf));
235 
236     conf = HBaseConfiguration.create();
237     conf.set(User.HBASE_SECURITY_CONF_KEY, "kerberos");
238     assertTrue("HBase security should be enabled regardless of underlying "
239         + "HDFS settings", User.isHBaseSecurityEnabled(conf));
240   }
241 }