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.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.Coprocessor;
30 import org.apache.hadoop.hbase.CoprocessorEnvironment;
31 import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
32 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
33 import org.apache.hadoop.hbase.ipc.RpcServer;
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 @InterfaceAudience.Private
50 public class TokenProvider implements AuthenticationProtos.AuthenticationService.Interface,
51 Coprocessor, CoprocessorService {
52
53 private static final Log LOG = LogFactory.getLog(TokenProvider.class);
54
55 private AuthenticationTokenSecretManager secretManager;
56
57
58 @Override
59 public void start(CoprocessorEnvironment env) {
60
61 if (env instanceof RegionCoprocessorEnvironment) {
62 RegionCoprocessorEnvironment regionEnv =
63 (RegionCoprocessorEnvironment)env;
64 RpcServerInterface server = regionEnv.getRegionServerServices().getRpcServer();
65 SecretManager<?> mgr = ((RpcServer)server).getSecretManager();
66 if (mgr instanceof AuthenticationTokenSecretManager) {
67 secretManager = (AuthenticationTokenSecretManager)mgr;
68 }
69 }
70 }
71
72 @Override
73 public void stop(CoprocessorEnvironment env) throws IOException {
74 }
75
76
77
78
79
80 private boolean isAllowedDelegationTokenOp(UserGroupInformation ugi) throws IOException {
81 AuthenticationMethod authMethod = ugi.getAuthenticationMethod();
82 if (authMethod == AuthenticationMethod.PROXY) {
83 authMethod = ugi.getRealUser().getAuthenticationMethod();
84 }
85 if (authMethod != AuthenticationMethod.KERBEROS
86 && authMethod != AuthenticationMethod.KERBEROS_SSL
87 && authMethod != AuthenticationMethod.CERTIFICATE) {
88 return false;
89 }
90 return true;
91 }
92
93
94
95 @Override
96 public Service getService() {
97 return AuthenticationProtos.AuthenticationService.newReflectiveService(this);
98 }
99
100 @Override
101 public void getAuthenticationToken(RpcController controller,
102 AuthenticationProtos.GetAuthenticationTokenRequest request,
103 RpcCallback<AuthenticationProtos.GetAuthenticationTokenResponse> done) {
104 AuthenticationProtos.GetAuthenticationTokenResponse.Builder response =
105 AuthenticationProtos.GetAuthenticationTokenResponse.newBuilder();
106
107 try {
108 if (secretManager == null) {
109 throw new IOException(
110 "No secret manager configured for token authentication");
111 }
112
113 User currentUser = RpcServer.getRequestUser();
114 UserGroupInformation ugi = null;
115 if (currentUser != null) {
116 ugi = currentUser.getUGI();
117 }
118 if (currentUser == null) {
119 throw new AccessDeniedException("No authenticated user for request!");
120 } else if (!isAllowedDelegationTokenOp(ugi)) {
121 LOG.warn("Token generation denied for user="+currentUser.getName()
122 +", authMethod="+ugi.getAuthenticationMethod());
123 throw new AccessDeniedException(
124 "Token generation only allowed for Kerberos authenticated clients");
125 }
126
127 Token<AuthenticationTokenIdentifier> token =
128 secretManager.generateToken(currentUser.getName());
129 response.setToken(ProtobufUtil.toToken(token)).build();
130 } catch (IOException ioe) {
131 ResponseConverter.setControllerException(controller, ioe);
132 }
133 done.run(response.build());
134 }
135
136 @Override
137 public void whoAmI(RpcController controller, AuthenticationProtos.WhoAmIRequest request,
138 RpcCallback<AuthenticationProtos.WhoAmIResponse> done) {
139 User requestUser = RpcServer.getRequestUser();
140 AuthenticationProtos.WhoAmIResponse.Builder response =
141 AuthenticationProtos.WhoAmIResponse.newBuilder();
142 if (requestUser != null) {
143 response.setUsername(requestUser.getShortName());
144 AuthenticationMethod method = requestUser.getUGI().getAuthenticationMethod();
145 if (method != null) {
146 response.setAuthMethod(method.name());
147 }
148 }
149 done.run(response.build());
150 }
151 }