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 static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getKeytabFileForTesting;
22  import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getPrincipalForTesting;
23  import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getSecuredConfiguration;
24  import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.isKerberosPropertySetted;
25  import static org.junit.Assert.assertEquals;
26  import static org.junit.Assert.assertNotSame;
27  import static org.junit.Assert.assertSame;
28  import static org.junit.Assume.assumeTrue;
29  
30  import java.io.IOException;
31  import java.net.InetSocketAddress;
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  import org.apache.hadoop.conf.Configuration;
36  import org.apache.hadoop.fs.CommonConfigurationKeys;
37  import org.apache.hadoop.hbase.HConstants;
38  import org.apache.hadoop.hbase.ServerName;
39  import org.apache.hadoop.hbase.ipc.FifoRpcScheduler;
40  import org.apache.hadoop.hbase.ipc.RpcClient;
41  import org.apache.hadoop.hbase.ipc.RpcServer;
42  import org.apache.hadoop.hbase.ipc.RpcServerInterface;
43  import org.apache.hadoop.hbase.ipc.TestDelayedRpc.TestDelayedImplementation;
44  import org.apache.hadoop.hbase.ipc.TestDelayedRpc.TestThread;
45  import org.apache.hadoop.hbase.ipc.protobuf.generated.TestDelayedRpcProtos;
46  import org.apache.hadoop.hbase.testclassification.SmallTests;
47  import org.apache.hadoop.security.UserGroupInformation;
48  import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
49  import org.junit.Test;
50  import org.junit.experimental.categories.Category;
51  import org.mockito.Mockito;
52  
53  import com.google.common.collect.Lists;
54  import com.google.protobuf.BlockingRpcChannel;
55  import com.google.protobuf.BlockingService;
56  
57  @Category(SmallTests.class)
58  public class TestSecureRPC {
59    public static RpcServerInterface rpcServer;
60    /**
61     * To run this test, we must specify the following system properties:
62     *<p>
63     * <b> hbase.regionserver.kerberos.principal </b>
64     * <p>
65     * <b> hbase.regionserver.keytab.file </b>
66     */
67    @Test
68    public void testRpcCallWithEnabledKerberosSaslAuth()
69        throws Exception {
70      assumeTrue(isKerberosPropertySetted());
71      String krbKeytab = getKeytabFileForTesting();
72      String krbPrincipal = getPrincipalForTesting();
73  
74      UserGroupInformation ugi = loginKerberosPrincipal(krbKeytab, krbPrincipal);
75      UserGroupInformation ugi2 = UserGroupInformation.getCurrentUser();
76  
77      // check that the login user is okay:
78      assertSame(ugi, ugi2);
79      assertEquals(AuthenticationMethod.KERBEROS, ugi.getAuthenticationMethod());
80      assertEquals(krbPrincipal, ugi.getUserName());
81  
82      Configuration clientConf = getSecuredConfiguration();
83      callRpcService(User.create(ugi2), clientConf, false);
84    }
85  
86    private UserGroupInformation loginKerberosPrincipal(String krbKeytab, String krbPrincipal)
87        throws Exception {
88      Configuration cnf = new Configuration();
89      cnf.set(CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
90      UserGroupInformation.setConfiguration(cnf);
91      UserGroupInformation.loginUserFromKeytab(krbPrincipal, krbKeytab);
92      return UserGroupInformation.getLoginUser();
93    }
94  
95    private void callRpcService(User clientUser, Configuration clientConf,
96        boolean allowInsecureFallback) throws Exception {
97   
98      Configuration conf = getSecuredConfiguration();
99      conf.setBoolean(RpcServer.FALLBACK_TO_INSECURE_CLIENT_AUTH, allowInsecureFallback);
100 
101     SecurityInfo securityInfoMock = Mockito.mock(SecurityInfo.class);
102     Mockito.when(securityInfoMock.getServerPrincipal())
103       .thenReturn(HBaseKerberosUtils.KRB_PRINCIPAL);
104     SecurityInfo.addInfo("TestDelayedService", securityInfoMock);
105 
106     boolean delayReturnValue = false;
107     InetSocketAddress isa = new InetSocketAddress("localhost", 0);
108     TestDelayedImplementation instance = new TestDelayedImplementation(delayReturnValue);
109     BlockingService service =
110         TestDelayedRpcProtos.TestDelayedService.newReflectiveBlockingService(instance);
111 
112     rpcServer = new RpcServer(null, "testSecuredDelayedRpc",
113         Lists.newArrayList(new RpcServer.BlockingServiceAndInterface(service, null)),
114           isa, conf, new FifoRpcScheduler(conf, 1));
115     rpcServer.start();
116     RpcClient rpcClient = new RpcClient(clientConf, HConstants.DEFAULT_CLUSTER_ID.toString());
117     try {
118       InetSocketAddress address = rpcServer.getListenerAddress();
119       if (address == null) {
120         throw new IOException("Listener channel is closed");
121       }
122       BlockingRpcChannel channel = rpcClient.createBlockingRpcChannel(
123           ServerName.valueOf(address.getHostName(), address.getPort(),
124           System.currentTimeMillis()), clientUser, 1000);
125       TestDelayedRpcProtos.TestDelayedService.BlockingInterface stub =
126         TestDelayedRpcProtos.TestDelayedService.newBlockingStub(channel);
127       List<Integer> results = new ArrayList<Integer>();
128       TestThread th1 = new TestThread(stub, true, results);
129       th1.start();
130       Thread.sleep(100);
131       th1.join();
132 
133       assertEquals(0xDEADBEEF, results.get(0).intValue());
134     } finally {
135       rpcClient.stop();
136     }
137   }
138 
139   @Test
140   public void testRpcFallbackToSimpleAuth() throws Exception {
141     assumeTrue(isKerberosPropertySetted());
142     String krbKeytab = getKeytabFileForTesting();
143     String krbPrincipal = getPrincipalForTesting();
144 
145     UserGroupInformation ugi = loginKerberosPrincipal(krbKeytab, krbPrincipal);
146     assertEquals(AuthenticationMethod.KERBEROS, ugi.getAuthenticationMethod());
147     assertEquals(krbPrincipal, ugi.getUserName());
148 
149     String clientUsername = "testuser";
150     UserGroupInformation clientUgi = UserGroupInformation.createUserForTesting(clientUsername,
151         new String[]{clientUsername});
152 
153     // check that the client user is insecure
154     assertNotSame(ugi, clientUgi);
155     assertEquals(AuthenticationMethod.SIMPLE, clientUgi.getAuthenticationMethod());
156     assertEquals(clientUsername, clientUgi.getUserName());
157 
158     Configuration clientConf = new Configuration();
159     clientConf.set(User.HBASE_SECURITY_CONF_KEY, "simple");
160     callRpcService(User.create(clientUgi), clientConf, true);
161   }
162 }