Skip to content

Commit 1137557

Browse files
committed
HADOOP-11207. Enhanced common DelegationTokenAuthenticationHandler to support proxy-users on Delegation-token management operations. Contributed by Zhijie Shen.
1 parent 209b169 commit 1137557

File tree

5 files changed

+205
-28
lines changed

5 files changed

+205
-28
lines changed

hadoop-common-project/hadoop-common/CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,9 @@ Release 2.6.0 - UNRELEASED
597597
HADOOP-11181. Generalized o.a.h.s.t.d.DelegationTokenManager to handle all
598598
sub-classes of AbstractDelegationTokenIdentifier. (zjshen)
599599

600+
HADOOP-11207. Enhanced common DelegationTokenAuthenticationHandler to support
601+
proxy-users on Delegation-token management operations. (Zhijie Shen via
602+
vinodkv)
600603

601604
OPTIMIZATIONS
602605

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,19 +333,40 @@ public HttpURLConnection openConnection(URL url, Token token, String doAs)
333333
* supported.
334334
* @param token the authentication token being used for the user where the
335335
* Delegation token will be stored.
336+
* @param renewer the renewer user.
336337
* @return a delegation token.
337338
* @throws IOException if an IO error occurred.
338339
* @throws AuthenticationException if an authentication exception occurred.
339340
*/
340341
public org.apache.hadoop.security.token.Token<AbstractDelegationTokenIdentifier>
341342
getDelegationToken(URL url, Token token, String renewer)
342343
throws IOException, AuthenticationException {
344+
return getDelegationToken(url, token, renewer, null);
345+
}
346+
347+
/**
348+
* Requests a delegation token using the configured <code>Authenticator</code>
349+
* for authentication.
350+
*
351+
* @param url the URL to get the delegation token from. Only HTTP/S URLs are
352+
* supported.
353+
* @param token the authentication token being used for the user where the
354+
* Delegation token will be stored.
355+
* @param renewer the renewer user.
356+
* @param doAsUser the user to do as, which will be the token owner.
357+
* @return a delegation token.
358+
* @throws IOException if an IO error occurred.
359+
* @throws AuthenticationException if an authentication exception occurred.
360+
*/
361+
public org.apache.hadoop.security.token.Token<AbstractDelegationTokenIdentifier>
362+
getDelegationToken(URL url, Token token, String renewer, String doAsUser)
363+
throws IOException, AuthenticationException {
343364
Preconditions.checkNotNull(url, "url");
344365
Preconditions.checkNotNull(token, "token");
345366
try {
346367
token.delegationToken =
347368
((KerberosDelegationTokenAuthenticator) getAuthenticator()).
348-
getDelegationToken(url, token, renewer);
369+
getDelegationToken(url, token, renewer, doAsUser);
349370
return token.delegationToken;
350371
} catch (IOException ex) {
351372
token.delegationToken = null;
@@ -365,13 +386,29 @@ public HttpURLConnection openConnection(URL url, Token token, String doAs)
365386
*/
366387
public long renewDelegationToken(URL url, Token token)
367388
throws IOException, AuthenticationException {
389+
return renewDelegationToken(url, token, null);
390+
}
391+
392+
/**
393+
* Renews a delegation token from the server end-point using the
394+
* configured <code>Authenticator</code> for authentication.
395+
*
396+
* @param url the URL to renew the delegation token from. Only HTTP/S URLs are
397+
* supported.
398+
* @param token the authentication token with the Delegation Token to renew.
399+
* @param doAsUser the user to do as, which will be the token owner.
400+
* @throws IOException if an IO error occurred.
401+
* @throws AuthenticationException if an authentication exception occurred.
402+
*/
403+
public long renewDelegationToken(URL url, Token token, String doAsUser)
404+
throws IOException, AuthenticationException {
368405
Preconditions.checkNotNull(url, "url");
369406
Preconditions.checkNotNull(token, "token");
370407
Preconditions.checkNotNull(token.delegationToken,
371408
"No delegation token available");
372409
try {
373410
return ((KerberosDelegationTokenAuthenticator) getAuthenticator()).
374-
renewDelegationToken(url, token, token.delegationToken);
411+
renewDelegationToken(url, token, token.delegationToken, doAsUser);
375412
} catch (IOException ex) {
376413
token.delegationToken = null;
377414
throw ex;
@@ -389,13 +426,28 @@ public long renewDelegationToken(URL url, Token token)
389426
*/
390427
public void cancelDelegationToken(URL url, Token token)
391428
throws IOException {
429+
cancelDelegationToken(url, token, null);
430+
}
431+
432+
/**
433+
* Cancels a delegation token from the server end-point. It does not require
434+
* being authenticated by the configured <code>Authenticator</code>.
435+
*
436+
* @param url the URL to cancel the delegation token from. Only HTTP/S URLs
437+
* are supported.
438+
* @param token the authentication token with the Delegation Token to cancel.
439+
* @param doAsUser the user to do as, which will be the token owner.
440+
* @throws IOException if an IO error occurred.
441+
*/
442+
public void cancelDelegationToken(URL url, Token token, String doAsUser)
443+
throws IOException {
392444
Preconditions.checkNotNull(url, "url");
393445
Preconditions.checkNotNull(token, "token");
394446
Preconditions.checkNotNull(token.delegationToken,
395447
"No delegation token available");
396448
try {
397449
((KerberosDelegationTokenAuthenticator) getAuthenticator()).
398-
cancelDelegationToken(url, token, token.delegationToken);
450+
cancelDelegationToken(url, token, token.delegationToken, doAsUser);
399451
} finally {
400452
token.delegationToken = null;
401453
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,21 @@
1717
*/
1818
package org.apache.hadoop.security.token.delegation.web;
1919

20-
import com.google.common.annotations.VisibleForTesting;
20+
import java.io.IOException;
21+
import java.io.Writer;
22+
import java.text.MessageFormat;
23+
import java.util.HashMap;
24+
import java.util.HashSet;
25+
import java.util.LinkedHashMap;
26+
import java.util.Map;
27+
import java.util.Properties;
28+
import java.util.Set;
29+
30+
import javax.servlet.ServletException;
31+
import javax.servlet.http.HttpServletRequest;
32+
import javax.servlet.http.HttpServletResponse;
33+
import javax.ws.rs.core.MediaType;
34+
2135
import org.apache.hadoop.classification.InterfaceAudience;
2236
import org.apache.hadoop.classification.InterfaceStability;
2337
import org.apache.hadoop.conf.Configuration;
@@ -27,25 +41,15 @@
2741
import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
2842
import org.apache.hadoop.security.authentication.server.AuthenticationToken;
2943
import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
44+
import org.apache.hadoop.security.authorize.AuthorizationException;
45+
import org.apache.hadoop.security.authorize.ProxyUsers;
3046
import org.apache.hadoop.security.token.Token;
3147
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
3248
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
3349
import org.apache.hadoop.util.HttpExceptionUtils;
3450
import org.codehaus.jackson.map.ObjectMapper;
3551

36-
import javax.servlet.ServletException;
37-
import javax.servlet.http.HttpServletRequest;
38-
import javax.servlet.http.HttpServletResponse;
39-
import javax.ws.rs.core.MediaType;
40-
import java.io.IOException;
41-
import java.io.Writer;
42-
import java.text.MessageFormat;
43-
import java.util.HashMap;
44-
import java.util.HashSet;
45-
import java.util.LinkedHashMap;
46-
import java.util.Map;
47-
import java.util.Properties;
48-
import java.util.Set;
52+
import com.google.common.annotations.VisibleForTesting;
4953

5054
/**
5155
* An {@link AuthenticationHandler} that implements Kerberos SPNEGO mechanism
@@ -188,6 +192,19 @@ public boolean managementOperation(AuthenticationToken token,
188192
UserGroupInformation requestUgi = (token != null)
189193
? UserGroupInformation.createRemoteUser(token.getUserName())
190194
: null;
195+
// Create the proxy user if doAsUser exists
196+
String doAsUser = DelegationTokenAuthenticationFilter.getDoAs(request);
197+
if (requestUgi != null && doAsUser != null) {
198+
requestUgi = UserGroupInformation.createProxyUser(
199+
doAsUser, requestUgi);
200+
try {
201+
ProxyUsers.authorize(requestUgi, request.getRemoteHost());
202+
} catch (AuthorizationException ex) {
203+
HttpExceptionUtils.createServletExceptionResponse(response,
204+
HttpServletResponse.SC_FORBIDDEN, ex);
205+
return false;
206+
}
207+
}
191208
Map map = null;
192209
switch (dtOp) {
193210
case GETDELEGATIONTOKEN:

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,35 @@ public void authenticate(URL url, AuthenticatedURL.Token token)
136136
* supported.
137137
* @param token the authentication token being used for the user where the
138138
* Delegation token will be stored.
139+
* @param renewer the renewer user.
139140
* @throws IOException if an IO error occurred.
140141
* @throws AuthenticationException if an authentication exception occurred.
141142
*/
142143
public Token<AbstractDelegationTokenIdentifier> getDelegationToken(URL url,
143144
AuthenticatedURL.Token token, String renewer)
144145
throws IOException, AuthenticationException {
146+
return getDelegationToken(url, token, renewer, null);
147+
}
148+
149+
/**
150+
* Requests a delegation token using the configured <code>Authenticator</code>
151+
* for authentication.
152+
*
153+
* @param url the URL to get the delegation token from. Only HTTP/S URLs are
154+
* supported.
155+
* @param token the authentication token being used for the user where the
156+
* Delegation token will be stored.
157+
* @param renewer the renewer user.
158+
* @param doAsUser the user to do as, which will be the token owner.
159+
* @throws IOException if an IO error occurred.
160+
* @throws AuthenticationException if an authentication exception occurred.
161+
*/
162+
public Token<AbstractDelegationTokenIdentifier> getDelegationToken(URL url,
163+
AuthenticatedURL.Token token, String renewer, String doAsUser)
164+
throws IOException, AuthenticationException {
145165
Map json = doDelegationTokenOperation(url, token,
146-
DelegationTokenOperation.GETDELEGATIONTOKEN, renewer, null, true);
166+
DelegationTokenOperation.GETDELEGATIONTOKEN, renewer, null, true,
167+
doAsUser);
147168
json = (Map) json.get(DELEGATION_TOKEN_JSON);
148169
String tokenStr = (String) json.get(DELEGATION_TOKEN_URL_STRING_JSON);
149170
Token<AbstractDelegationTokenIdentifier> dToken =
@@ -169,8 +190,27 @@ public long renewDelegationToken(URL url,
169190
AuthenticatedURL.Token token,
170191
Token<AbstractDelegationTokenIdentifier> dToken)
171192
throws IOException, AuthenticationException {
193+
return renewDelegationToken(url, token, dToken, null);
194+
}
195+
196+
/**
197+
* Renews a delegation token from the server end-point using the
198+
* configured <code>Authenticator</code> for authentication.
199+
*
200+
* @param url the URL to renew the delegation token from. Only HTTP/S URLs are
201+
* supported.
202+
* @param token the authentication token with the Delegation Token to renew.
203+
* @param doAsUser the user to do as, which will be the token owner.
204+
* @throws IOException if an IO error occurred.
205+
* @throws AuthenticationException if an authentication exception occurred.
206+
*/
207+
public long renewDelegationToken(URL url,
208+
AuthenticatedURL.Token token,
209+
Token<AbstractDelegationTokenIdentifier> dToken, String doAsUser)
210+
throws IOException, AuthenticationException {
172211
Map json = doDelegationTokenOperation(url, token,
173-
DelegationTokenOperation.RENEWDELEGATIONTOKEN, null, dToken, true);
212+
DelegationTokenOperation.RENEWDELEGATIONTOKEN, null, dToken, true,
213+
doAsUser);
174214
return (Long) json.get(RENEW_DELEGATION_TOKEN_JSON);
175215
}
176216

@@ -187,17 +227,35 @@ public void cancelDelegationToken(URL url,
187227
AuthenticatedURL.Token token,
188228
Token<AbstractDelegationTokenIdentifier> dToken)
189229
throws IOException {
230+
cancelDelegationToken(url, token, dToken, null);
231+
}
232+
233+
/**
234+
* Cancels a delegation token from the server end-point. It does not require
235+
* being authenticated by the configured <code>Authenticator</code>.
236+
*
237+
* @param url the URL to cancel the delegation token from. Only HTTP/S URLs
238+
* are supported.
239+
* @param token the authentication token with the Delegation Token to cancel.
240+
* @param doAsUser the user to do as, which will be the token owner.
241+
* @throws IOException if an IO error occurred.
242+
*/
243+
public void cancelDelegationToken(URL url,
244+
AuthenticatedURL.Token token,
245+
Token<AbstractDelegationTokenIdentifier> dToken, String doAsUser)
246+
throws IOException {
190247
try {
191248
doDelegationTokenOperation(url, token,
192-
DelegationTokenOperation.CANCELDELEGATIONTOKEN, null, dToken, false);
249+
DelegationTokenOperation.CANCELDELEGATIONTOKEN, null, dToken, false,
250+
doAsUser);
193251
} catch (AuthenticationException ex) {
194252
throw new IOException("This should not happen: " + ex.getMessage(), ex);
195253
}
196254
}
197255

198256
private Map doDelegationTokenOperation(URL url,
199257
AuthenticatedURL.Token token, DelegationTokenOperation operation,
200-
String renewer, Token<?> dToken, boolean hasResponse)
258+
String renewer, Token<?> dToken, boolean hasResponse, String doAsUser)
201259
throws IOException, AuthenticationException {
202260
Map ret = null;
203261
Map<String, String> params = new HashMap<String, String>();
@@ -208,6 +266,11 @@ private Map doDelegationTokenOperation(URL url,
208266
if (dToken != null) {
209267
params.put(TOKEN_PARAM, dToken.encodeToUrlString());
210268
}
269+
// proxyuser
270+
if (doAsUser != null) {
271+
params.put(DelegationTokenAuthenticatedURL.DO_AS,
272+
URLEncoder.encode(doAsUser, "UTF-8"));
273+
}
211274
String urlStr = url.toExternalForm();
212275
StringBuilder sb = new StringBuilder(urlStr);
213276
String separator = (urlStr.contains("?")) ? "&" : "?";

0 commit comments

Comments
 (0)