1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.fail;
24
25 import java.io.File;
26 import java.io.IOException;
27 import java.lang.reflect.InvocationTargetException;
28 import java.lang.reflect.Method;
29 import java.util.List;
30
31 import com.google.common.collect.ImmutableMap;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.hbase.testclassification.SmallTests;
36 import org.junit.AfterClass;
37 import org.junit.Test;
38 import org.junit.experimental.categories.Category;
39
40 @Category(SmallTests.class)
41 public class TestHBaseConfiguration {
42
43 private static final Log LOG = LogFactory.getLog(TestHBaseConfiguration.class);
44
45 private static HBaseCommonTestingUtility UTIL = new HBaseCommonTestingUtility();
46
47 @AfterClass
48 public static void tearDown() throws IOException {
49 UTIL.cleanupTestDir();
50 }
51
52 @Test
53 public void testGetIntDeprecated() {
54 int VAL = 1, VAL2 = 2;
55 String NAME = "foo";
56 String DEPRECATED_NAME = "foo.deprecated";
57
58 Configuration conf = HBaseConfiguration.create();
59 conf.setInt(NAME, VAL);
60 assertEquals(VAL, HBaseConfiguration.getInt(conf, NAME, DEPRECATED_NAME, 0));
61
62 conf = HBaseConfiguration.create();
63 conf.setInt(DEPRECATED_NAME, VAL);
64 assertEquals(VAL, HBaseConfiguration.getInt(conf, NAME, DEPRECATED_NAME, 0));
65
66 conf = HBaseConfiguration.create();
67 conf.setInt(DEPRECATED_NAME, VAL);
68 conf.setInt(NAME, VAL);
69 assertEquals(VAL, HBaseConfiguration.getInt(conf, NAME, DEPRECATED_NAME, 0));
70
71 conf = HBaseConfiguration.create();
72 conf.setInt(DEPRECATED_NAME, VAL);
73 conf.setInt(NAME, VAL2);
74 assertEquals(VAL, HBaseConfiguration.getInt(conf, NAME, DEPRECATED_NAME, 0));
75 }
76
77 @Test
78 public void testSubset() throws Exception {
79 Configuration conf = HBaseConfiguration.create();
80
81
82 String prefix = "hbase.mapred.output.";
83 conf.set("hbase.security.authentication", "kerberos");
84 conf.set("hbase.regionserver.kerberos.principal", "hbasesource");
85 HBaseConfiguration.setWithPrefix(conf, prefix,
86 ImmutableMap.of(
87 "hbase.regionserver.kerberos.principal", "hbasedest",
88 "", "shouldbemissing")
89 .entrySet());
90
91 Configuration subsetConf = HBaseConfiguration.subset(conf, prefix);
92 assertNull(subsetConf.get(prefix + "hbase.regionserver.kerberos.principal"));
93 assertEquals("hbasedest", subsetConf.get("hbase.regionserver.kerberos.principal"));
94 assertNull(subsetConf.get("hbase.security.authentication"));
95 assertNull(subsetConf.get(""));
96
97 Configuration mergedConf = HBaseConfiguration.create(conf);
98 HBaseConfiguration.merge(mergedConf, subsetConf);
99
100 assertEquals("hbasedest", mergedConf.get("hbase.regionserver.kerberos.principal"));
101 assertEquals("kerberos", mergedConf.get("hbase.security.authentication"));
102 assertEquals("shouldbemissing", mergedConf.get(prefix));
103 }
104
105 @Test
106 public void testGetPassword() throws Exception {
107 Configuration conf = HBaseConfiguration.create();
108 conf.set(ReflectiveCredentialProviderClient.CREDENTIAL_PROVIDER_PATH, "jceks://file"
109 + new File(UTIL.getDataTestDir().toUri().getPath(), "foo.jks").getCanonicalPath());
110 ReflectiveCredentialProviderClient client = new ReflectiveCredentialProviderClient();
111 if (client.isHadoopCredentialProviderAvailable()) {
112 char[] keyPass = { 'k', 'e', 'y', 'p', 'a', 's', 's' };
113 char[] storePass = { 's', 't', 'o', 'r', 'e', 'p', 'a', 's', 's' };
114 client.createEntry(conf, "ssl.keypass.alias", keyPass);
115 client.createEntry(conf, "ssl.storepass.alias", storePass);
116
117 String keypass = HBaseConfiguration.getPassword(conf, "ssl.keypass.alias", null);
118 assertEquals(keypass, new String(keyPass));
119
120 String storepass = HBaseConfiguration.getPassword(conf, "ssl.storepass.alias", null);
121 assertEquals(storepass, new String(storePass));
122 }
123 }
124
125 private static class ReflectiveCredentialProviderClient {
126 public static final String HADOOP_CRED_PROVIDER_FACTORY_CLASS_NAME =
127 "org.apache.hadoop.security.alias.JavaKeyStoreProvider$Factory";
128 public static final String
129 HADOOP_CRED_PROVIDER_FACTORY_GET_PROVIDERS_METHOD_NAME = "getProviders";
130
131 public static final String HADOOP_CRED_PROVIDER_CLASS_NAME =
132 "org.apache.hadoop.security.alias.CredentialProvider";
133 public static final String
134 HADOOP_CRED_PROVIDER_GET_CREDENTIAL_ENTRY_METHOD_NAME =
135 "getCredentialEntry";
136 public static final String
137 HADOOP_CRED_PROVIDER_GET_ALIASES_METHOD_NAME = "getAliases";
138 public static final String
139 HADOOP_CRED_PROVIDER_CREATE_CREDENTIAL_ENTRY_METHOD_NAME =
140 "createCredentialEntry";
141 public static final String HADOOP_CRED_PROVIDER_FLUSH_METHOD_NAME = "flush";
142
143 public static final String HADOOP_CRED_ENTRY_CLASS_NAME =
144 "org.apache.hadoop.security.alias.CredentialProvider$CredentialEntry";
145 public static final String HADOOP_CRED_ENTRY_GET_CREDENTIAL_METHOD_NAME =
146 "getCredential";
147
148 public static final String CREDENTIAL_PROVIDER_PATH =
149 "hadoop.security.credential.provider.path";
150
151 private static Object hadoopCredProviderFactory = null;
152 private static Method getProvidersMethod = null;
153 private static Method getAliasesMethod = null;
154 private static Method getCredentialEntryMethod = null;
155 private static Method getCredentialMethod = null;
156 private static Method createCredentialEntryMethod = null;
157 private static Method flushMethod = null;
158 private static Boolean hadoopClassesAvailable = null;
159
160
161
162
163
164
165
166
167
168 private boolean isHadoopCredentialProviderAvailable() {
169 if (null != hadoopClassesAvailable) {
170
171 if (hadoopClassesAvailable && null != getProvidersMethod
172 && null != hadoopCredProviderFactory
173 && null != getCredentialEntryMethod && null != getCredentialMethod) {
174 return true;
175 } else {
176
177 return false;
178 }
179 }
180
181 hadoopClassesAvailable = false;
182
183
184 Class<?> hadoopCredProviderFactoryClz = null;
185 try {
186 hadoopCredProviderFactoryClz = Class
187 .forName(HADOOP_CRED_PROVIDER_FACTORY_CLASS_NAME);
188 } catch (ClassNotFoundException e) {
189 return false;
190 }
191
192 try {
193 hadoopCredProviderFactory = hadoopCredProviderFactoryClz.newInstance();
194 } catch (InstantiationException e) {
195 return false;
196 } catch (IllegalAccessException e) {
197 return false;
198 }
199
200 try {
201 getProvidersMethod = loadMethod(hadoopCredProviderFactoryClz,
202 HADOOP_CRED_PROVIDER_FACTORY_GET_PROVIDERS_METHOD_NAME,
203 Configuration.class);
204
205 Class<?> hadoopCredProviderClz = null;
206 hadoopCredProviderClz = Class.forName(HADOOP_CRED_PROVIDER_CLASS_NAME);
207 getCredentialEntryMethod = loadMethod(hadoopCredProviderClz,
208 HADOOP_CRED_PROVIDER_GET_CREDENTIAL_ENTRY_METHOD_NAME, String.class);
209
210 getAliasesMethod = loadMethod(hadoopCredProviderClz,
211 HADOOP_CRED_PROVIDER_GET_ALIASES_METHOD_NAME);
212
213 createCredentialEntryMethod = loadMethod(hadoopCredProviderClz,
214 HADOOP_CRED_PROVIDER_CREATE_CREDENTIAL_ENTRY_METHOD_NAME,
215 String.class, char[].class);
216
217 flushMethod = loadMethod(hadoopCredProviderClz,
218 HADOOP_CRED_PROVIDER_FLUSH_METHOD_NAME);
219
220
221 Class<?> hadoopCredentialEntryClz = null;
222 try {
223 hadoopCredentialEntryClz = Class
224 .forName(HADOOP_CRED_ENTRY_CLASS_NAME);
225 } catch (ClassNotFoundException e) {
226 LOG.error("Failed to load class:" + e);
227 return false;
228 }
229
230 getCredentialMethod = loadMethod(hadoopCredentialEntryClz,
231 HADOOP_CRED_ENTRY_GET_CREDENTIAL_METHOD_NAME);
232 } catch (Exception e1) {
233 return false;
234 }
235
236 hadoopClassesAvailable = true;
237 LOG.info("Credential provider classes have been" +
238 " loaded and initialized successfully through reflection.");
239 return true;
240
241 }
242
243 private Method loadMethod(Class<?> clz, String name, Class<?>... classes)
244 throws Exception {
245 Method method = null;
246 try {
247 method = clz.getMethod(name, classes);
248 } catch (SecurityException e) {
249 fail("security exception caught for: " + name + " in " +
250 clz.getCanonicalName());
251 throw e;
252 } catch (NoSuchMethodException e) {
253 LOG.error("Failed to load the " + name + ": " + e);
254 fail("no such method: " + name + " in " + clz.getCanonicalName());
255 throw e;
256 }
257 return method;
258 }
259
260
261
262
263
264
265
266
267 @SuppressWarnings("unchecked")
268 protected List<Object> getCredentialProviders(Configuration conf) {
269
270 Object providersObj = null;
271 try {
272 providersObj = getProvidersMethod.invoke(hadoopCredProviderFactory,
273 conf);
274 } catch (IllegalArgumentException e) {
275 LOG.error("Failed to invoke: " + getProvidersMethod.getName() +
276 ": " + e);
277 return null;
278 } catch (IllegalAccessException e) {
279 LOG.error("Failed to invoke: " + getProvidersMethod.getName() +
280 ": " + e);
281 return null;
282 } catch (InvocationTargetException e) {
283 LOG.error("Failed to invoke: " + getProvidersMethod.getName() +
284 ": " + e);
285 return null;
286 }
287
288
289 try {
290 return (List<Object>) providersObj;
291 } catch (ClassCastException e) {
292 return null;
293 }
294 }
295
296
297
298
299
300
301
302
303
304
305
306
307 public void createEntry(Configuration conf, String name, char[] credential)
308 throws Exception {
309
310 if (!isHadoopCredentialProviderAvailable()) {
311 return;
312 }
313
314 List<Object> providers = getCredentialProviders(conf);
315 if (null == providers) {
316 throw new IOException("Could not fetch any CredentialProviders, " +
317 "is the implementation available?");
318 }
319
320 Object provider = providers.get(0);
321 createEntryInProvider(provider, name, credential);
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337 private void createEntryInProvider(Object credentialProvider,
338 String name, char[] credential) throws Exception {
339
340 if (!isHadoopCredentialProviderAvailable()) {
341 return;
342 }
343
344 try {
345 createCredentialEntryMethod.invoke(credentialProvider, name, credential);
346 } catch (IllegalArgumentException e) {
347 return;
348 } catch (IllegalAccessException e) {
349 return;
350 } catch (InvocationTargetException e) {
351 return;
352 }
353
354 try {
355 flushMethod.invoke(credentialProvider);
356 } catch (IllegalArgumentException e) {
357 throw e;
358 } catch (IllegalAccessException e) {
359 throw e;
360 } catch (InvocationTargetException e) {
361 throw e;
362 }
363 }
364 }
365 }