Skip to content

Commit 4157d1e

Browse files
subrat.mishrabrfrn169
authored andcommitted
HBASE-22116 Added keytab and principal support for HttpDoAsClient.
Signed-off-by: Toshihiro Suzuki <brfrn169@gmail.com>
1 parent 302a9ce commit 4157d1e

File tree

1 file changed

+78
-27
lines changed

1 file changed

+78
-27
lines changed

hbase-examples/src/main/java/org/apache/hadoop/hbase/thrift/HttpDoAsClient.java

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,24 @@
1818
*/
1919
package org.apache.hadoop.hbase.thrift;
2020

21+
import java.io.File;
2122
import java.nio.ByteBuffer;
2223
import java.nio.charset.CharacterCodingException;
2324
import java.nio.charset.Charset;
2425
import java.nio.charset.CharsetDecoder;
26+
import java.security.Principal;
2527
import java.security.PrivilegedExceptionAction;
2628
import java.util.ArrayList;
2729
import java.util.Base64;
2830
import java.util.HashMap;
31+
import java.util.HashSet;
2932
import java.util.List;
3033
import java.util.Map;
34+
import java.util.Set;
3135
import java.util.SortedMap;
3236
import java.util.TreeMap;
3337
import javax.security.auth.Subject;
38+
import javax.security.auth.kerberos.KerberosPrincipal;
3439
import javax.security.auth.login.AppConfigurationEntry;
3540
import javax.security.auth.login.Configuration;
3641
import javax.security.auth.login.LoginContext;
@@ -68,11 +73,13 @@ public class HttpDoAsClient {
6873
private static boolean secure = false;
6974
static protected String doAsUser = null;
7075
static protected String principal = null;
76+
static protected String keyTab = null;
7177

7278
public static void main(String[] args) throws Exception {
73-
if (args.length < 3 || args.length > 4) {
79+
if (args.length < 3 || args.length > 6) {
7480
System.out.println("Invalid arguments!");
75-
System.out.println("Usage: HttpDoAsClient host port doAsUserName [security=true]");
81+
System.out.println(
82+
"Usage: HttpDoAsClient host port doAsUserName [security=true] [principal] [keytab]");
7683
System.exit(-1);
7784
}
7885

@@ -81,7 +88,16 @@ public static void main(String[] args) throws Exception {
8188
doAsUser = args[2];
8289
if (args.length > 3) {
8390
secure = Boolean.parseBoolean(args[3]);
84-
principal = getSubject().getPrincipals().iterator().next().getName();
91+
if (args.length > 4) {
92+
principal = args[4];
93+
keyTab = args[5];
94+
if (!new File(keyTab).exists()) {
95+
System.err.printf("ERROR: KeyTab File %s not found %n", keyTab);
96+
System.exit(-1);
97+
}
98+
} else {
99+
principal = getSubject().getPrincipals().iterator().next().getName();
100+
}
85101
}
86102

87103
final HttpDoAsClient client = new HttpDoAsClient();
@@ -252,31 +268,66 @@ static Subject getSubject() throws Exception {
252268
* To authenticate the DemoClient, kinit should be invoked ahead.
253269
* Here we try to get the Kerberos credential from the ticket cache.
254270
*/
255-
LoginContext context = new LoginContext("", new Subject(), null,
256-
new Configuration() {
257-
@Override
258-
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
259-
Map<String, String> options = new HashMap<>();
260-
options.put("useKeyTab", "false");
261-
options.put("storeKey", "false");
262-
options.put("doNotPrompt", "true");
263-
options.put("useTicketCache", "true");
264-
options.put("renewTGT", "true");
265-
options.put("refreshKrb5Config", "true");
266-
options.put("isInitiator", "true");
267-
String ticketCache = System.getenv("KRB5CCNAME");
268-
if (ticketCache != null) {
269-
options.put("ticketCache", ticketCache);
270-
}
271-
options.put("debug", "true");
272-
273-
return new AppConfigurationEntry[]{
274-
new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
275-
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
276-
options)};
277-
}
278-
});
271+
LoginContext context;
272+
273+
if (keyTab != null) {
274+
// To authenticate the HttpDoAsClient using principal and keyTab
275+
Set<Principal> principals = new HashSet<>();
276+
principals.add(new KerberosPrincipal(principal));
277+
Subject subject =
278+
new Subject(false, principals, new HashSet<>(), new HashSet<>());
279+
280+
context = new LoginContext("", subject, null, new KerberosConfiguration(principal, keyTab));
281+
} else {
282+
/*
283+
* To authenticate the HttpDoAsClient, kinit should be invoked ahead. Here we try to
284+
* get the Kerberos credential from the ticket cache.
285+
*/
286+
context = new LoginContext("", new Subject(), null, new KerberosConfiguration());
287+
}
279288
context.login();
280289
return context.getSubject();
281290
}
291+
292+
private static class KerberosConfiguration extends Configuration {
293+
private String principal;
294+
private String keyTab;
295+
296+
public KerberosConfiguration() {
297+
// Empty constructor will have no principal or keyTab values
298+
}
299+
300+
public KerberosConfiguration(String principal, String keyTab) {
301+
this.principal = principal;
302+
this.keyTab = keyTab;
303+
}
304+
305+
@Override
306+
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
307+
Map<String, String> options = new HashMap<>();
308+
if (principal != null && keyTab != null) {
309+
options.put("principal", principal);
310+
options.put("keyTab", keyTab);
311+
options.put("useKeyTab", "true");
312+
options.put("storeKey", "true");
313+
} else {
314+
options.put("useKeyTab", "false");
315+
options.put("storeKey", "false");
316+
}
317+
options.put("doNotPrompt", "true");
318+
options.put("useTicketCache", "true");
319+
options.put("renewTGT", "true");
320+
options.put("refreshKrb5Config", "true");
321+
options.put("isInitiator", "true");
322+
String ticketCache = System.getenv("KRB5CCNAME");
323+
if (ticketCache != null) {
324+
options.put("ticketCache", ticketCache);
325+
}
326+
options.put("debug", "true");
327+
328+
return new AppConfigurationEntry[] {
329+
new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
330+
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) };
331+
}
332+
}
282333
}

0 commit comments

Comments
 (0)