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