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