1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.token;
20
21 import java.io.IOException;
22
23 import com.google.protobuf.RpcCallback;
24 import com.google.protobuf.RpcController;
25 import com.google.protobuf.Service;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.hbase.Coprocessor;
29 import org.apache.hadoop.hbase.CoprocessorEnvironment;
30 import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
31 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
32 import org.apache.hadoop.hbase.ipc.RpcServer;
33 import org.apache.hadoop.hbase.ipc.RequestContext;
34 import org.apache.hadoop.hbase.ipc.RpcServerInterface;
35 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
36 import org.apache.hadoop.hbase.protobuf.ResponseConverter;
37 import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos;
38 import org.apache.hadoop.hbase.security.AccessDeniedException;
39 import org.apache.hadoop.hbase.security.User;
40 import org.apache.hadoop.security.UserGroupInformation;
41 import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
42 import org.apache.hadoop.security.token.SecretManager;
43 import org.apache.hadoop.security.token.Token;
44
45
46
47
48
49 public class TokenProvider implements AuthenticationProtos.AuthenticationService.Interface,
50 Coprocessor, CoprocessorService {
51
52 private static Log LOG = LogFactory.getLog(TokenProvider.class);
53
54 private AuthenticationTokenSecretManager secretManager;
55
56
57 @Override
58 public void start(CoprocessorEnvironment env) {
59
60 if (env instanceof RegionCoprocessorEnvironment) {
61 RegionCoprocessorEnvironment regionEnv =
62 (RegionCoprocessorEnvironment)env;
63 RpcServerInterface server = regionEnv.getRegionServerServices().getRpcServer();
64 SecretManager<?> mgr = ((RpcServer)server).getSecretManager();
65 if (mgr instanceof AuthenticationTokenSecretManager) {
66 secretManager = (AuthenticationTokenSecretManager)mgr;
67 }
68 }
69 }
70
71 @Override
72 public void stop(CoprocessorEnvironment env) throws IOException {
73 }
74
75
76
77
78
79 private boolean isAllowedDelegationTokenOp(UserGroupInformation ugi) throws IOException {
80 AuthenticationMethod authMethod = ugi.getAuthenticationMethod();
81 if (authMethod == AuthenticationMethod.PROXY) {
82 authMethod = ugi.getRealUser().getAuthenticationMethod();
83 }
84 if (authMethod != AuthenticationMethod.KERBEROS
85 && authMethod != AuthenticationMethod.KERBEROS_SSL
86 && authMethod != AuthenticationMethod.CERTIFICATE) {
87 return false;
88 }
89 return true;
90 }
91
92
93
94 @Override
95 public Service getService() {
96 return AuthenticationProtos.AuthenticationService.newReflectiveService(this);
97 }
98
99 @Override
100 public void getAuthenticationToken(RpcController controller,
101 AuthenticationProtos.GetAuthenticationTokenRequest request,
102 RpcCallback<AuthenticationProtos.GetAuthenticationTokenResponse> done) {
103 AuthenticationProtos.GetAuthenticationTokenResponse.Builder response =
104 AuthenticationProtos.GetAuthenticationTokenResponse.newBuilder();
105
106 try {
107 if (secretManager == null) {
108 throw new IOException(
109 "No secret manager configured for token authentication");
110 }
111
112 User currentUser = RequestContext.getRequestUser();
113 UserGroupInformation ugi = null;
114 if (currentUser != null) {
115 ugi = currentUser.getUGI();
116 }
117 if (currentUser == null) {
118 throw new AccessDeniedException("No authenticated user for request!");
119 } else if (!isAllowedDelegationTokenOp(ugi)) {
120 LOG.warn("Token generation denied for user="+currentUser.getName()
121 +", authMethod="+ugi.getAuthenticationMethod());
122 throw new AccessDeniedException(
123 "Token generation only allowed for Kerberos authenticated clients");
124 }
125
126 Token<AuthenticationTokenIdentifier> token =
127 secretManager.generateToken(currentUser.getName());
128 response.setToken(ProtobufUtil.toToken(token)).build();
129 } catch (IOException ioe) {
130 ResponseConverter.setControllerException(controller, ioe);
131 }
132 done.run(response.build());
133 }
134
135 @Override
136 public void whoAmI(RpcController controller, AuthenticationProtos.WhoAmIRequest request,
137 RpcCallback<AuthenticationProtos.WhoAmIResponse> done) {
138 User requestUser = RequestContext.getRequestUser();
139 AuthenticationProtos.WhoAmIResponse.Builder response =
140 AuthenticationProtos.WhoAmIResponse.newBuilder();
141 if (requestUser != null) {
142 response.setUsername(requestUser.getShortName());
143 AuthenticationMethod method = requestUser.getUGI().getAuthenticationMethod();
144 if (method != null) {
145 response.setAuthMethod(method.name());
146 }
147 }
148 done.run(response.build());
149 }
150 }