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