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