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