1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.security.token;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.util.Properties;
26
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.fs.Path;
29 import org.apache.hadoop.hbase.HBaseTestingUtility;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.LocalHBaseCluster;
32 import org.apache.hadoop.hbase.TableName;
33 import org.apache.hadoop.hbase.client.Connection;
34 import org.apache.hadoop.hbase.client.ConnectionFactory;
35 import org.apache.hadoop.hbase.client.Table;
36 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
37 import org.apache.hadoop.hbase.http.ssl.KeyStoreTestUtil;
38 import org.apache.hadoop.hbase.ipc.AsyncRpcClient;
39 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
40 import org.apache.hadoop.hbase.ipc.RpcClient;
41 import org.apache.hadoop.hbase.ipc.RpcClientFactory;
42 import org.apache.hadoop.hbase.ipc.RpcClientImpl;
43 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
44 import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos;
45 import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos.GetAuthenticationTokenRequest;
46 import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos.WhoAmIRequest;
47 import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos.WhoAmIResponse;
48 import org.apache.hadoop.hbase.security.AccessDeniedException;
49 import org.apache.hadoop.hbase.security.HBaseKerberosUtils;
50 import org.apache.hadoop.hbase.testclassification.MediumTests;
51 import org.apache.hadoop.hbase.util.FSUtils;
52 import org.apache.hadoop.hdfs.DFSConfigKeys;
53 import org.apache.hadoop.http.HttpConfig;
54 import org.apache.hadoop.minikdc.MiniKdc;
55 import org.apache.hadoop.security.UserGroupInformation;
56 import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
57 import org.apache.hadoop.security.token.Token;
58 import org.apache.hadoop.security.token.TokenIdentifier;
59 import org.junit.AfterClass;
60 import org.junit.BeforeClass;
61 import org.junit.Test;
62 import org.junit.experimental.categories.Category;
63
64 import com.google.protobuf.ServiceException;
65
66 @Category(MediumTests.class)
67 public class TestGenerateDelegationToken {
68
69 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
70
71 private static LocalHBaseCluster CLUSTER;
72
73 private static final File KEYTAB_FILE = new File(TEST_UTIL.getDataTestDir("keytab").toUri()
74 .getPath());
75 private static MiniKdc KDC;
76
77 private static String HOST = "localhost";
78
79 private static String USERNAME;
80
81 private static String PRINCIPAL;
82
83 private static String HTTP_PRINCIPAL;
84
85 private static void setHdfsSecuredConfiguration(Configuration conf) throws Exception {
86
87 conf.set(DFSConfigKeys.DFS_NAMENODE_USER_NAME_KEY, PRINCIPAL + "@" + KDC.getRealm());
88 conf.set(DFSConfigKeys.DFS_NAMENODE_KEYTAB_FILE_KEY, KEYTAB_FILE.getAbsolutePath());
89 conf.set(DFSConfigKeys.DFS_DATANODE_USER_NAME_KEY, PRINCIPAL + "@" + KDC.getRealm());
90 conf.set(DFSConfigKeys.DFS_DATANODE_KEYTAB_FILE_KEY, KEYTAB_FILE.getAbsolutePath());
91 conf.set(DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY, HTTP_PRINCIPAL + "@"
92 + KDC.getRealm());
93 conf.setBoolean(DFSConfigKeys.DFS_BLOCK_ACCESS_TOKEN_ENABLE_KEY, true);
94 conf.set("dfs.http.policy", HttpConfig.Policy.HTTPS_ONLY.name());
95 conf.set(DFSConfigKeys.DFS_NAMENODE_HTTPS_ADDRESS_KEY, "localhost:0");
96 conf.set(DFSConfigKeys.DFS_DATANODE_HTTPS_ADDRESS_KEY, "localhost:0");
97
98 File keystoresDir = new File(TEST_UTIL.getDataTestDir("keystore").toUri().getPath());
99 keystoresDir.mkdirs();
100 String sslConfDir = KeyStoreTestUtil.getClasspathDir(TestGenerateDelegationToken.class);
101 KeyStoreTestUtil.setupSSLConfig(keystoresDir.getAbsolutePath(), sslConfDir, conf, false);
102
103 conf.setBoolean("ignore.secure.ports.for.testing", true);
104 }
105
106 @BeforeClass
107 public static void setUp() throws Exception {
108 Properties conf = MiniKdc.createConf();
109 conf.put(MiniKdc.DEBUG, true);
110 KDC = new MiniKdc(conf, new File(TEST_UTIL.getDataTestDir("kdc").toUri().getPath()));
111 KDC.start();
112 USERNAME = UserGroupInformation.getLoginUser().getShortUserName();
113 PRINCIPAL = USERNAME + "/" + HOST;
114 HTTP_PRINCIPAL = "HTTP/" + HOST;
115 KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL, HTTP_PRINCIPAL);
116 TEST_UTIL.startMiniZKCluster();
117
118 HBaseKerberosUtils.setKeytabFileForTesting(KEYTAB_FILE.getAbsolutePath());
119 HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
120 HBaseKerberosUtils.setSecuredConfiguration(TEST_UTIL.getConfiguration());
121 setHdfsSecuredConfiguration(TEST_UTIL.getConfiguration());
122 UserGroupInformation.setConfiguration(TEST_UTIL.getConfiguration());
123 TEST_UTIL.getConfiguration().setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
124 TokenProvider.class.getName());
125 TEST_UTIL.startMiniDFSCluster(1);
126 Path rootdir = TEST_UTIL.getDataTestDirOnTestFS("TestGenerateDelegationToken");
127 FSUtils.setRootDir(TEST_UTIL.getConfiguration(), rootdir);
128 CLUSTER = new LocalHBaseCluster(TEST_UTIL.getConfiguration(), 1);
129 CLUSTER.startup();
130 }
131
132 @AfterClass
133 public static void tearDown() throws Exception {
134 if (CLUSTER != null) {
135 CLUSTER.shutdown();
136 }
137 CLUSTER.join();
138 if (KDC != null) {
139 KDC.stop();
140 }
141 TEST_UTIL.shutdownMiniCluster();
142 }
143
144 private void testTokenAuth(Class<? extends RpcClient> rpcImplClass) throws IOException,
145 ServiceException {
146 TEST_UTIL.getConfiguration().set(RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY,
147 rpcImplClass.getName());
148 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
149 Table table = conn.getTable(TableName.META_TABLE_NAME)) {
150 CoprocessorRpcChannel rpcChannel = table.coprocessorService(HConstants.EMPTY_START_ROW);
151 AuthenticationProtos.AuthenticationService.BlockingInterface service =
152 AuthenticationProtos.AuthenticationService.newBlockingStub(rpcChannel);
153 WhoAmIResponse response = service.whoAmI(null, WhoAmIRequest.getDefaultInstance());
154 assertEquals(USERNAME, response.getUsername());
155 assertEquals(AuthenticationMethod.TOKEN.name(), response.getAuthMethod());
156 try {
157 service.getAuthenticationToken(null, GetAuthenticationTokenRequest.getDefaultInstance());
158 } catch (ServiceException e) {
159 AccessDeniedException exc = (AccessDeniedException) ProtobufUtil.getRemoteException(e);
160 assertTrue(exc.getMessage().contains(
161 "Token generation only allowed for Kerberos authenticated clients"));
162 }
163 }
164 }
165
166 @Test
167 public void test() throws Exception {
168 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
169 Token<? extends TokenIdentifier> token = TokenUtil.obtainToken(conn);
170 UserGroupInformation.getCurrentUser().addToken(token);
171 testTokenAuth(RpcClientImpl.class);
172 testTokenAuth(AsyncRpcClient.class);
173 }
174
175 }
176 }