You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by tu...@apache.org on 2014/08/08 06:58:59 UTC
svn commit: r1616672 [1/2] - in /hadoop/common/trunk/hadoop-common-project:
hadoop-auth/
hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/
hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/
hadoop-auth...
Author: tucu
Date: Fri Aug 8 04:58:58 2014
New Revision: 1616672
URL: http://svn.apache.org/r1616672
Log:
HADOOP-10771. Refactor HTTP delegation support out of httpfs to common, PART 2. (tucu)
Added:
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticationHandler.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticator.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/PseudoDelegationTokenAuthenticationHandler.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/ServletUtils.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestWebDelegationToken.java
Modified:
hadoop/common/trunk/hadoop-common-project/hadoop-auth/pom.xml
hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/AuthenticatedURL.java
hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java
hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java
hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestAuthenticatedURL.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/pom.xml
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationFilter.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenIdentifier.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/PseudoDelegationTokenAuthenticator.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestDelegationTokenAuthenticationHandlerWithMocks.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestDelegationTokenManager.java
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-auth/pom.xml
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-auth/pom.xml?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-auth/pom.xml (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-auth/pom.xml Fri Aug 8 04:58:58 2014
@@ -144,6 +144,15 @@
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
+ <id>prepare-jar</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>prepare-test-jar</id>
+ <phase>prepare-package</phase>
<goals>
<goal>test-jar</goal>
</goals>
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/AuthenticatedURL.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/AuthenticatedURL.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/AuthenticatedURL.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/AuthenticatedURL.java Fri Aug 8 04:58:58 2014
@@ -120,32 +120,6 @@ public class AuthenticatedURL {
return token;
}
- /**
- * Return the hashcode for the token.
- *
- * @return the hashcode for the token.
- */
- @Override
- public int hashCode() {
- return (token != null) ? token.hashCode() : 0;
- }
-
- /**
- * Return if two token instances are equal.
- *
- * @param o the other token instance.
- *
- * @return if this instance and the other instance are equal.
- */
- @Override
- public boolean equals(Object o) {
- boolean eq = false;
- if (o instanceof Token) {
- Token other = (Token) o;
- eq = (token == null && other.token == null) || (token != null && this.token.equals(other.token));
- }
- return eq;
- }
}
private static Class<? extends Authenticator> DEFAULT_AUTHENTICATOR = KerberosAuthenticator.class;
@@ -209,6 +183,16 @@ public class AuthenticatedURL {
}
/**
+ * Returns the {@link Authenticator} instance used by the
+ * <code>AuthenticatedURL</code>.
+ *
+ * @return the {@link Authenticator} instance
+ */
+ protected Authenticator getAuthenticator() {
+ return authenticator;
+ }
+
+ /**
* Returns an authenticated {@link HttpURLConnection}.
*
* @param url the URL to connect to. Only HTTP/S URLs are supported.
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java Fri Aug 8 04:58:58 2014
@@ -142,12 +142,31 @@ public class KerberosAuthenticationHandl
*/
public static final String NAME_RULES = TYPE + ".name.rules";
+ private String type;
private String keytab;
private GSSManager gssManager;
private Subject serverSubject = new Subject();
private List<LoginContext> loginContexts = new ArrayList<LoginContext>();
/**
+ * Creates a Kerberos SPNEGO authentication handler with the default
+ * auth-token type, <code>kerberos</code>.
+ */
+ public KerberosAuthenticationHandler() {
+ this(TYPE);
+ }
+
+ /**
+ * Creates a Kerberos SPNEGO authentication handler with a custom auth-token
+ * type.
+ *
+ * @param type auth-token type.
+ */
+ public KerberosAuthenticationHandler(String type) {
+ this.type = type;
+ }
+
+ /**
* Initializes the authentication handler instance.
* <p/>
* It creates a Kerberos context using the principal and keytab specified in the configuration.
@@ -249,7 +268,7 @@ public class KerberosAuthenticationHandl
*/
@Override
public String getType() {
- return TYPE;
+ return type;
}
/**
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java Fri Aug 8 04:58:58 2014
@@ -55,6 +55,25 @@ public class PseudoAuthenticationHandler
private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
private boolean acceptAnonymous;
+ private String type;
+
+ /**
+ * Creates a Hadoop pseudo authentication handler with the default auth-token
+ * type, <code>simple</code>.
+ */
+ public PseudoAuthenticationHandler() {
+ this(TYPE);
+ }
+
+ /**
+ * Creates a Hadoop pseudo authentication handler with a custom auth-token
+ * type.
+ *
+ * @param type auth-token type.
+ */
+ public PseudoAuthenticationHandler(String type) {
+ this.type = type;
+ }
/**
* Initializes the authentication handler instance.
@@ -96,7 +115,7 @@ public class PseudoAuthenticationHandler
*/
@Override
public String getType() {
- return TYPE;
+ return type;
}
/**
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestAuthenticatedURL.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestAuthenticatedURL.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestAuthenticatedURL.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestAuthenticatedURL.java Fri Aug 8 04:58:58 2014
@@ -33,36 +33,6 @@ public class TestAuthenticatedURL {
token = new AuthenticatedURL.Token("foo");
Assert.assertTrue(token.isSet());
Assert.assertEquals("foo", token.toString());
-
- AuthenticatedURL.Token token1 = new AuthenticatedURL.Token();
- AuthenticatedURL.Token token2 = new AuthenticatedURL.Token();
- Assert.assertEquals(token1.hashCode(), token2.hashCode());
- Assert.assertTrue(token1.equals(token2));
-
- token1 = new AuthenticatedURL.Token();
- token2 = new AuthenticatedURL.Token("foo");
- Assert.assertNotSame(token1.hashCode(), token2.hashCode());
- Assert.assertFalse(token1.equals(token2));
-
- token1 = new AuthenticatedURL.Token("foo");
- token2 = new AuthenticatedURL.Token();
- Assert.assertNotSame(token1.hashCode(), token2.hashCode());
- Assert.assertFalse(token1.equals(token2));
-
- token1 = new AuthenticatedURL.Token("foo");
- token2 = new AuthenticatedURL.Token("foo");
- Assert.assertEquals(token1.hashCode(), token2.hashCode());
- Assert.assertTrue(token1.equals(token2));
-
- token1 = new AuthenticatedURL.Token("bar");
- token2 = new AuthenticatedURL.Token("foo");
- Assert.assertNotSame(token1.hashCode(), token2.hashCode());
- Assert.assertFalse(token1.equals(token2));
-
- token1 = new AuthenticatedURL.Token("foo");
- token2 = new AuthenticatedURL.Token("bar");
- Assert.assertNotSame(token1.hashCode(), token2.hashCode());
- Assert.assertFalse(token1.equals(token2));
}
@Test
@@ -137,4 +107,12 @@ public class TestAuthenticatedURL {
Mockito.verify(connConf).configure(Mockito.<HttpURLConnection>any());
}
+ @Test
+ public void testGetAuthenticator() throws Exception {
+ Authenticator authenticator = Mockito.mock(Authenticator.class);
+
+ AuthenticatedURL aURL = new AuthenticatedURL(authenticator);
+ Assert.assertEquals(authenticator, aURL.getAuthenticator());
+ }
+
}
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/pom.xml
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/pom.xml?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/pom.xml (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/pom.xml Fri Aug 8 04:58:58 2014
@@ -204,6 +204,17 @@
<scope>compile</scope>
</dependency>
<dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-auth</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-minikdc</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
</dependency>
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java?rev=1616672&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java Fri Aug 8 04:58:58 2014
@@ -0,0 +1,330 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.security.token.delegation.web;
+
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.security.Credentials;
+import org.apache.hadoop.security.SecurityUtil;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.hadoop.security.authentication.client.ConnectionConfigurator;
+import org.apache.hadoop.security.token.TokenIdentifier;
+import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The <code>DelegationTokenAuthenticatedURL</code> is a
+ * {@link AuthenticatedURL} sub-class with built-in Hadoop Delegation Token
+ * functionality.
+ * <p/>
+ * The authentication mechanisms supported by default are Hadoop Simple
+ * authentication (also known as pseudo authentication) and Kerberos SPNEGO
+ * authentication.
+ * <p/>
+ * Additional authentication mechanisms can be supported via {@link
+ * DelegationTokenAuthenticator} implementations.
+ * <p/>
+ * The default {@link DelegationTokenAuthenticator} is the {@link
+ * KerberosDelegationTokenAuthenticator} class which supports
+ * automatic fallback from Kerberos SPNEGO to Hadoop Simple authentication via
+ * the {@link PseudoDelegationTokenAuthenticator} class.
+ * <p/>
+ * <code>AuthenticatedURL</code> instances are not thread-safe.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Unstable
+public class DelegationTokenAuthenticatedURL extends AuthenticatedURL {
+
+ /**
+ * Client side authentication token that handles Delegation Tokens.
+ */
+ @InterfaceAudience.Public
+ @InterfaceStability.Unstable
+ public static class Token extends AuthenticatedURL.Token {
+ private
+ org.apache.hadoop.security.token.Token<AbstractDelegationTokenIdentifier>
+ delegationToken;
+
+ org.apache.hadoop.security.token.Token<AbstractDelegationTokenIdentifier>
+ getDelegationToken() {
+ return delegationToken;
+ }
+
+ }
+
+ private static Class<? extends DelegationTokenAuthenticator>
+ DEFAULT_AUTHENTICATOR = KerberosDelegationTokenAuthenticator.class;
+
+ /**
+ * Sets the default {@link DelegationTokenAuthenticator} class to use when an
+ * {@link DelegationTokenAuthenticatedURL} instance is created without
+ * specifying one.
+ *
+ * The default class is {@link KerberosDelegationTokenAuthenticator}
+ *
+ * @param authenticator the authenticator class to use as default.
+ */
+ public static void setDefaultDelegationTokenAuthenticator(
+ Class<? extends DelegationTokenAuthenticator> authenticator) {
+ DEFAULT_AUTHENTICATOR = authenticator;
+ }
+
+ /**
+ * Returns the default {@link DelegationTokenAuthenticator} class to use when
+ * an {@link DelegationTokenAuthenticatedURL} instance is created without
+ * specifying one.
+ * <p/>
+ * The default class is {@link KerberosDelegationTokenAuthenticator}
+ *
+ * @return the delegation token authenticator class to use as default.
+ */
+ public static Class<? extends DelegationTokenAuthenticator>
+ getDefaultDelegationTokenAuthenticator() {
+ return DEFAULT_AUTHENTICATOR;
+ }
+
+ private static DelegationTokenAuthenticator
+ obtainDelegationTokenAuthenticator(DelegationTokenAuthenticator dta) {
+ try {
+ return (dta != null) ? dta : DEFAULT_AUTHENTICATOR.newInstance();
+ } catch (Exception ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ /**
+ * Creates an <code>DelegationTokenAuthenticatedURL</code>.
+ * <p/>
+ * An instance of the default {@link DelegationTokenAuthenticator} will be
+ * used.
+ */
+ public DelegationTokenAuthenticatedURL() {
+ this(null, null);
+ }
+
+ /**
+ * Creates an <code>DelegationTokenAuthenticatedURL</code>.
+ *
+ * @param authenticator the {@link DelegationTokenAuthenticator} instance to
+ * use, if <code>null</code> the default one will be used.
+ */
+ public DelegationTokenAuthenticatedURL(
+ DelegationTokenAuthenticator authenticator) {
+ this(authenticator, null);
+ }
+
+ /**
+ * Creates an <code>DelegationTokenAuthenticatedURL</code> using the default
+ * {@link DelegationTokenAuthenticator} class.
+ *
+ * @param connConfigurator a connection configurator.
+ */
+ public DelegationTokenAuthenticatedURL(
+ ConnectionConfigurator connConfigurator) {
+ this(null, connConfigurator);
+ }
+
+ /**
+ * Creates an <code>DelegationTokenAuthenticatedURL</code>.
+ *
+ * @param authenticator the {@link DelegationTokenAuthenticator} instance to
+ * use, if <code>null</code> the default one will be used.
+ * @param connConfigurator a connection configurator.
+ */
+ public DelegationTokenAuthenticatedURL(
+ DelegationTokenAuthenticator authenticator,
+ ConnectionConfigurator connConfigurator) {
+ super(obtainDelegationTokenAuthenticator(authenticator), connConfigurator);
+ }
+
+ /**
+ * Returns an authenticated {@link HttpURLConnection}, it uses a Delegation
+ * Token only if the given auth token is an instance of {@link Token} and
+ * it contains a Delegation Token, otherwise use the configured
+ * {@link DelegationTokenAuthenticator} to authenticate the connection.
+ *
+ * @param url the URL to connect to. Only HTTP/S URLs are supported.
+ * @param token the authentication token being used for the user.
+ * @return an authenticated {@link HttpURLConnection}.
+ * @throws IOException if an IO error occurred.
+ * @throws AuthenticationException if an authentication exception occurred.
+ */
+ @Override
+ public HttpURLConnection openConnection(URL url, AuthenticatedURL.Token token)
+ throws IOException, AuthenticationException {
+ return (token instanceof Token) ? openConnection(url, (Token) token)
+ : super.openConnection(url ,token);
+ }
+
+ /**
+ * Returns an authenticated {@link HttpURLConnection}. If the Delegation
+ * Token is present, it will be used taking precedence over the configured
+ * <code>Authenticator</code>.
+ *
+ * @param url the URL to connect to. Only HTTP/S URLs are supported.
+ * @param token the authentication token being used for the user.
+ * @return an authenticated {@link HttpURLConnection}.
+ * @throws IOException if an IO error occurred.
+ * @throws AuthenticationException if an authentication exception occurred.
+ */
+ public HttpURLConnection openConnection(URL url, Token token)
+ throws IOException, AuthenticationException {
+ return openConnection(url, token, null);
+ }
+
+ private URL augmentURL(URL url, Map<String, String> params)
+ throws IOException {
+ if (params != null && params.size() > 0) {
+ String urlStr = url.toExternalForm();
+ StringBuilder sb = new StringBuilder(urlStr);
+ String separator = (urlStr.contains("?")) ? "&" : "?";
+ for (Map.Entry<String, String> param : params.entrySet()) {
+ sb.append(separator).append(param.getKey()).append("=").append(
+ param.getValue());
+ separator = "&";
+ }
+ url = new URL(sb.toString());
+ }
+ return url;
+ }
+
+ /**
+ * Returns an authenticated {@link HttpURLConnection}. If the Delegation
+ * Token is present, it will be used taking precedence over the configured
+ * <code>Authenticator</code>. If the <code>doAs</code> parameter is not NULL,
+ * the request will be done on behalf of the specified <code>doAs</code> user.
+ *
+ * @param url the URL to connect to. Only HTTP/S URLs are supported.
+ * @param token the authentication token being used for the user.
+ * @param doAs user to do the the request on behalf of, if NULL the request is
+ * as self.
+ * @return an authenticated {@link HttpURLConnection}.
+ * @throws IOException if an IO error occurred.
+ * @throws AuthenticationException if an authentication exception occurred.
+ */
+ public HttpURLConnection openConnection(URL url, Token token, String doAs)
+ throws IOException, AuthenticationException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(token, "token");
+ Map<String, String> extraParams = new HashMap<String, String>();
+
+ // delegation token
+ Credentials creds = UserGroupInformation.getCurrentUser().getCredentials();
+ if (!creds.getAllTokens().isEmpty()) {
+ InetSocketAddress serviceAddr = new InetSocketAddress(url.getHost(),
+ url.getPort());
+ Text service = SecurityUtil.buildTokenService(serviceAddr);
+ org.apache.hadoop.security.token.Token<? extends TokenIdentifier> dt =
+ creds.getToken(service);
+ if (dt != null) {
+ extraParams.put(KerberosDelegationTokenAuthenticator.DELEGATION_PARAM,
+ dt.encodeToUrlString());
+ }
+ }
+
+ url = augmentURL(url, extraParams);
+ return super.openConnection(url, token);
+ }
+
+ /**
+ * Requests a delegation token using the configured <code>Authenticator</code>
+ * for authentication.
+ *
+ * @param url the URL to get the delegation token from. Only HTTP/S URLs are
+ * supported.
+ * @param token the authentication token being used for the user where the
+ * Delegation token will be stored.
+ * @return a delegation token.
+ * @throws IOException if an IO error occurred.
+ * @throws AuthenticationException if an authentication exception occurred.
+ */
+ public org.apache.hadoop.security.token.Token<AbstractDelegationTokenIdentifier>
+ getDelegationToken(URL url, Token token, String renewer)
+ throws IOException, AuthenticationException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(token, "token");
+ try {
+ token.delegationToken =
+ ((KerberosDelegationTokenAuthenticator) getAuthenticator()).
+ getDelegationToken(url, token, renewer);
+ return token.delegationToken;
+ } catch (IOException ex) {
+ token.delegationToken = null;
+ throw ex;
+ }
+ }
+
+ /**
+ * Renews a delegation token from the server end-point using the
+ * configured <code>Authenticator</code> for authentication.
+ *
+ * @param url the URL to renew the delegation token from. Only HTTP/S URLs are
+ * supported.
+ * @param token the authentication token with the Delegation Token to renew.
+ * @throws IOException if an IO error occurred.
+ * @throws AuthenticationException if an authentication exception occurred.
+ */
+ public long renewDelegationToken(URL url, Token token)
+ throws IOException, AuthenticationException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(token, "token");
+ Preconditions.checkNotNull(token.delegationToken,
+ "No delegation token available");
+ try {
+ return ((KerberosDelegationTokenAuthenticator) getAuthenticator()).
+ renewDelegationToken(url, token, token.delegationToken);
+ } catch (IOException ex) {
+ token.delegationToken = null;
+ throw ex;
+ }
+ }
+
+ /**
+ * Cancels a delegation token from the server end-point. It does not require
+ * being authenticated by the configured <code>Authenticator</code>.
+ *
+ * @param url the URL to cancel the delegation token from. Only HTTP/S URLs
+ * are supported.
+ * @param token the authentication token with the Delegation Token to cancel.
+ * @throws IOException if an IO error occurred.
+ */
+ public void cancelDelegationToken(URL url, Token token)
+ throws IOException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(token, "token");
+ Preconditions.checkNotNull(token.delegationToken,
+ "No delegation token available");
+ try {
+ ((KerberosDelegationTokenAuthenticator) getAuthenticator()).
+ cancelDelegationToken(url, token, token.delegationToken);
+ } finally {
+ token.delegationToken = null;
+ }
+ }
+
+}
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationFilter.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationFilter.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationFilter.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationFilter.java Fri Aug 8 04:58:58 2014
@@ -15,79 +15,88 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.hadoop.fs.http.server;
+package org.apache.hadoop.security.token.delegation.web;
import org.apache.hadoop.classification.InterfaceAudience;
-import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
+import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
+import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
+import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
+import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
+
import javax.servlet.FilterConfig;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Map;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
import java.util.Properties;
/**
- * Subclass of hadoop-auth <code>AuthenticationFilter</code> that obtains its configuration
- * from HttpFSServer's server configuration.
+ * The <code>DelegationTokenAuthenticationFilter</code> filter is a
+ * {@link AuthenticationFilter} with Hadoop Delegation Token support.
+ * <p/>
+ * By default it uses it own instance of the {@link
+ * AbstractDelegationTokenSecretManager}. For situations where an external
+ * <code>AbstractDelegationTokenSecretManager</code> is required (i.e. one that
+ * shares the secret with <code>AbstractDelegationTokenSecretManager</code>
+ * instance running in other services), the external
+ * <code>AbstractDelegationTokenSecretManager</code> must be set as an
+ * attribute in the {@link ServletContext} of the web application using the
+ * {@link #DELEGATION_TOKEN_SECRET_MANAGER_ATTR} attribute name (
+ * 'hadoop.http.delegation-token-secret-manager').
*/
@InterfaceAudience.Private
-public class HttpFSAuthenticationFilter extends AuthenticationFilter {
- private static final String CONF_PREFIX = "httpfs.authentication.";
-
- private static final String SIGNATURE_SECRET_FILE = SIGNATURE_SECRET + ".file";
+@InterfaceStability.Evolving
+public class DelegationTokenAuthenticationFilter
+ extends AuthenticationFilter {
/**
- * Returns the hadoop-auth configuration from HttpFSServer's configuration.
+ * Sets an external <code>DelegationTokenSecretManager</code> instance to
+ * manage creation and verification of Delegation Tokens.
* <p/>
- * It returns all HttpFSServer's configuration properties prefixed with
- * <code>httpfs.authentication</code>. The <code>httpfs.authentication</code>
- * prefix is removed from the returned property names.
+ * This is useful for use cases where secrets must be shared across multiple
+ * services.
+ */
+
+ public static final String DELEGATION_TOKEN_SECRET_MANAGER_ATTR =
+ "hadoop.http.delegation-token-secret-manager";
+
+ /**
+ * It delegates to
+ * {@link AuthenticationFilter#getConfiguration(String, FilterConfig)} and
+ * then overrides the {@link AuthenticationHandler} to use if authentication
+ * type is set to <code>simple</code> or <code>kerberos</code> in order to use
+ * the corresponding implementation with delegation token support.
*
* @param configPrefix parameter not used.
* @param filterConfig parameter not used.
- *
- * @return hadoop-auth configuration read from HttpFSServer's configuration.
+ * @return hadoop-auth de-prefixed configuration for the filter and handler.
*/
@Override
- protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) {
- Properties props = new Properties();
- Configuration conf = HttpFSServerWebApp.get().getConfig();
-
- props.setProperty(AuthenticationFilter.COOKIE_PATH, "/");
- for (Map.Entry<String, String> entry : conf) {
- String name = entry.getKey();
- if (name.startsWith(CONF_PREFIX)) {
- String value = conf.get(name);
- name = name.substring(CONF_PREFIX.length());
- props.setProperty(name, value);
- }
- }
-
- if (props.getProperty(AUTH_TYPE).equals("kerberos")) {
+ protected Properties getConfiguration(String configPrefix,
+ FilterConfig filterConfig) throws ServletException {
+ Properties props = super.getConfiguration(configPrefix, filterConfig);
+ String authType = props.getProperty(AUTH_TYPE);
+ if (authType.equals(PseudoAuthenticationHandler.TYPE)) {
props.setProperty(AUTH_TYPE,
- HttpFSKerberosAuthenticationHandler.class.getName());
- }
-
- String signatureSecretFile = props.getProperty(SIGNATURE_SECRET_FILE, null);
- if (signatureSecretFile == null) {
- throw new RuntimeException("Undefined property: " + SIGNATURE_SECRET_FILE);
- }
-
- try {
- StringBuilder secret = new StringBuilder();
- Reader reader = new FileReader(signatureSecretFile);
- int c = reader.read();
- while (c > -1) {
- secret.append((char)c);
- c = reader.read();
- }
- reader.close();
- props.setProperty(AuthenticationFilter.SIGNATURE_SECRET, secret.toString());
- } catch (IOException ex) {
- throw new RuntimeException("Could not read HttpFS signature secret file: " + signatureSecretFile);
+ PseudoDelegationTokenAuthenticationHandler.class.getName());
+ } else if (authType.equals(KerberosAuthenticationHandler.TYPE)) {
+ props.setProperty(AUTH_TYPE,
+ KerberosDelegationTokenAuthenticationHandler.class.getName());
}
return props;
}
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ super.init(filterConfig);
+ AbstractDelegationTokenSecretManager dtSecretManager =
+ (AbstractDelegationTokenSecretManager) filterConfig.getServletContext().
+ getAttribute(DELEGATION_TOKEN_SECRET_MANAGER_ATTR);
+ if (dtSecretManager != null && getAuthenticationHandler()
+ instanceof DelegationTokenAuthenticationHandler) {
+ DelegationTokenAuthenticationHandler handler =
+ (DelegationTokenAuthenticationHandler) getAuthenticationHandler();
+ handler.setExternalDelegationTokenSecretManager(dtSecretManager);
+ }
+ }
}
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java Fri Aug 8 04:58:58 2014
@@ -15,22 +15,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.hadoop.fs.http.server;
+package org.apache.hadoop.security.token.delegation.web;
+import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.classification.InterfaceAudience;
-import org.apache.hadoop.fs.http.client.HttpFSFileSystem;
-import org.apache.hadoop.fs.http.client.HttpFSKerberosAuthenticator;
-import org.apache.hadoop.fs.http.client.HttpFSKerberosAuthenticator.DelegationTokenOperation;
-import org.apache.hadoop.lib.service.DelegationTokenIdentifier;
-import org.apache.hadoop.lib.service.DelegationTokenManager;
-import org.apache.hadoop.lib.service.DelegationTokenManagerException;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
import org.apache.hadoop.security.authentication.server.AuthenticationToken;
import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
import org.apache.hadoop.security.token.Token;
-import org.json.simple.JSONObject;
+import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
+import org.codehaus.jackson.map.ObjectMapper;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
@@ -41,41 +42,136 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
/**
- * Server side <code>AuthenticationHandler</code> that authenticates requests
- * using the incoming delegation token as a 'delegation' query string parameter.
+ * An {@link AuthenticationHandler} that implements Kerberos SPNEGO mechanism
+ * for HTTP and supports Delegation Token functionality.
* <p/>
- * If not delegation token is present in the request it delegates to the
- * {@link KerberosAuthenticationHandler}
+ * In addition to the wrapped {@link AuthenticationHandler} configuration
+ * properties, this handler supports the following properties prefixed
+ * with the type of the wrapped <code>AuthenticationHandler</code>:
+ * <ul>
+ * <li>delegation-token.token-kind: the token kind for generated tokens
+ * (no default, required property).</li>
+ * <li>delegation-token.update-interval.sec: secret manager master key
+ * update interval in seconds (default 1 day).</li>
+ * <li>delegation-token.max-lifetime.sec: maximum life of a delegation
+ * token in seconds (default 7 days).</li>
+ * <li>delegation-token.renewal-interval.sec: renewal interval for
+ * delegation tokens in seconds (default 1 day).</li>
+ * <li>delegation-token.removal-scan-interval.sec: delegation tokens
+ * removal scan interval in seconds (default 1 hour).</li>
+ * </ul>
+ *
*/
@InterfaceAudience.Private
-public class HttpFSKerberosAuthenticationHandler
- extends KerberosAuthenticationHandler {
+@InterfaceStability.Evolving
+public abstract class DelegationTokenAuthenticationHandler
+ implements AuthenticationHandler {
- static final Set<String> DELEGATION_TOKEN_OPS =
- new HashSet<String>();
+ protected static final String TYPE_POSTFIX = "-dt";
+
+ public static final String PREFIX = "delegation-token.";
+
+ public static final String TOKEN_KIND = PREFIX + "token-kind.sec";
+
+ public static final String UPDATE_INTERVAL = PREFIX + "update-interval.sec";
+ public static final long UPDATE_INTERVAL_DEFAULT = 24 * 60 * 60;
+
+ public static final String MAX_LIFETIME = PREFIX + "max-lifetime.sec";
+ public static final long MAX_LIFETIME_DEFAULT = 7 * 24 * 60 * 60;
+
+ public static final String RENEW_INTERVAL = PREFIX + "renew-interval.sec";
+ public static final long RENEW_INTERVAL_DEFAULT = 24 * 60 * 60;
+
+ public static final String REMOVAL_SCAN_INTERVAL = PREFIX +
+ "removal-scan-interval.sec";
+ public static final long REMOVAL_SCAN_INTERVAL_DEFAULT = 60 * 60;
+
+ private static final Set<String> DELEGATION_TOKEN_OPS = new HashSet<String>();
static {
- DELEGATION_TOKEN_OPS.add(
- DelegationTokenOperation.GETDELEGATIONTOKEN.toString());
- DELEGATION_TOKEN_OPS.add(
- DelegationTokenOperation.RENEWDELEGATIONTOKEN.toString());
- DELEGATION_TOKEN_OPS.add(
- DelegationTokenOperation.CANCELDELEGATIONTOKEN.toString());
+ DELEGATION_TOKEN_OPS.add(KerberosDelegationTokenAuthenticator.
+ DelegationTokenOperation.GETDELEGATIONTOKEN.toString());
+ DELEGATION_TOKEN_OPS.add(KerberosDelegationTokenAuthenticator.
+ DelegationTokenOperation.RENEWDELEGATIONTOKEN.toString());
+ DELEGATION_TOKEN_OPS.add(KerberosDelegationTokenAuthenticator.
+ DelegationTokenOperation.CANCELDELEGATIONTOKEN.toString());
+ }
+
+ private AuthenticationHandler authHandler;
+ private DelegationTokenManager tokenManager;
+ private String authType;
+
+ public DelegationTokenAuthenticationHandler(AuthenticationHandler handler) {
+ authHandler = handler;
+ authType = handler.getType();
+ }
+
+ @VisibleForTesting
+ DelegationTokenManager getTokenManager() {
+ return tokenManager;
}
- public static final String TYPE = "kerberos-dt";
+ @Override
+ public void init(Properties config) throws ServletException {
+ authHandler.init(config);
+ initTokenManager(config);
+ }
/**
- * Returns authentication type of the handler.
+ * Sets an external <code>DelegationTokenSecretManager</code> instance to
+ * manage creation and verification of Delegation Tokens.
+ * <p/>
+ * This is useful for use cases where secrets must be shared across multiple
+ * services.
*
- * @return <code>delegationtoken-kerberos</code>
+ * @param secretManager a <code>DelegationTokenSecretManager</code> instance
*/
+ public void setExternalDelegationTokenSecretManager(
+ AbstractDelegationTokenSecretManager secretManager) {
+ tokenManager.setExternalDelegationTokenSecretManager(secretManager);
+ }
+
+ @VisibleForTesting
+ @SuppressWarnings("unchecked")
+ public void initTokenManager(Properties config) {
+ String configPrefix = authHandler.getType() + ".";
+ Configuration conf = new Configuration(false);
+ for (Map.Entry entry : config.entrySet()) {
+ conf.set((String) entry.getKey(), (String) entry.getValue());
+ }
+ String tokenKind = conf.get(TOKEN_KIND);
+ if (tokenKind == null) {
+ throw new IllegalArgumentException(
+ "The configuration does not define the token kind");
+ }
+ tokenKind = tokenKind.trim();
+ long updateInterval = conf.getLong(configPrefix + UPDATE_INTERVAL,
+ UPDATE_INTERVAL_DEFAULT);
+ long maxLifeTime = conf.getLong(configPrefix + MAX_LIFETIME,
+ MAX_LIFETIME_DEFAULT);
+ long renewInterval = conf.getLong(configPrefix + RENEW_INTERVAL,
+ RENEW_INTERVAL_DEFAULT);
+ long removalScanInterval = conf.getLong(
+ configPrefix + REMOVAL_SCAN_INTERVAL, REMOVAL_SCAN_INTERVAL_DEFAULT);
+ tokenManager = new DelegationTokenManager(new Text(tokenKind),
+ updateInterval * 1000, maxLifeTime * 1000, renewInterval * 1000,
+ removalScanInterval * 1000);
+ tokenManager.init();
+ }
+
+ @Override
+ public void destroy() {
+ tokenManager.destroy();
+ authHandler.destroy();
+ }
+
@Override
public String getType() {
- return TYPE;
+ return authType;
}
private static final String ENTER = System.getProperty("line.separator");
@@ -84,87 +180,118 @@ public class HttpFSKerberosAuthenticatio
@SuppressWarnings("unchecked")
public boolean managementOperation(AuthenticationToken token,
HttpServletRequest request, HttpServletResponse response)
- throws IOException, AuthenticationException {
+ throws IOException, AuthenticationException {
boolean requestContinues = true;
- String op = request.getParameter(HttpFSFileSystem.OP_PARAM);
+ String op = ServletUtils.getParameter(request,
+ KerberosDelegationTokenAuthenticator.OP_PARAM);
op = (op != null) ? op.toUpperCase() : null;
if (DELEGATION_TOKEN_OPS.contains(op) &&
!request.getMethod().equals("OPTIONS")) {
- DelegationTokenOperation dtOp =
- DelegationTokenOperation.valueOf(op);
+ KerberosDelegationTokenAuthenticator.DelegationTokenOperation dtOp =
+ KerberosDelegationTokenAuthenticator.
+ DelegationTokenOperation.valueOf(op);
if (dtOp.getHttpMethod().equals(request.getMethod())) {
+ boolean doManagement;
if (dtOp.requiresKerberosCredentials() && token == null) {
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
- MessageFormat.format(
- "Operation [{0}] requires SPNEGO authentication established",
- dtOp));
- requestContinues = false;
+ token = authenticate(request, response);
+ if (token == null) {
+ requestContinues = false;
+ doManagement = false;
+ } else {
+ doManagement = true;
+ }
} else {
- DelegationTokenManager tokenManager =
- HttpFSServerWebApp.get().get(DelegationTokenManager.class);
- try {
- Map map = null;
- switch (dtOp) {
- case GETDELEGATIONTOKEN:
- String renewerParam =
- request.getParameter(HttpFSKerberosAuthenticator.RENEWER_PARAM);
- if (renewerParam == null) {
- renewerParam = token.getUserName();
- }
- Token<?> dToken = tokenManager.createToken(
- UserGroupInformation.getCurrentUser(), renewerParam);
+ doManagement = true;
+ }
+ if (doManagement) {
+ UserGroupInformation requestUgi = (token != null)
+ ? UserGroupInformation.createRemoteUser(token.getUserName())
+ : null;
+ Map map = null;
+ switch (dtOp) {
+ case GETDELEGATIONTOKEN:
+ if (requestUgi == null) {
+ throw new IllegalStateException("request UGI cannot be NULL");
+ }
+ String renewer = ServletUtils.getParameter(request,
+ KerberosDelegationTokenAuthenticator.RENEWER_PARAM);
+ try {
+ Token<?> dToken = tokenManager.createToken(requestUgi, renewer);
map = delegationTokenToJSON(dToken);
- break;
- case RENEWDELEGATIONTOKEN:
- case CANCELDELEGATIONTOKEN:
- String tokenParam =
- request.getParameter(HttpFSKerberosAuthenticator.TOKEN_PARAM);
- if (tokenParam == null) {
- response.sendError(HttpServletResponse.SC_BAD_REQUEST,
+ } catch (IOException ex) {
+ throw new AuthenticationException(ex.toString(), ex);
+ }
+ break;
+ case RENEWDELEGATIONTOKEN:
+ if (requestUgi == null) {
+ throw new IllegalStateException("request UGI cannot be NULL");
+ }
+ String tokenToRenew = ServletUtils.getParameter(request,
+ KerberosDelegationTokenAuthenticator.TOKEN_PARAM);
+ if (tokenToRenew == null) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST,
MessageFormat.format(
- "Operation [{0}] requires the parameter [{1}]",
- dtOp, HttpFSKerberosAuthenticator.TOKEN_PARAM));
+ "Operation [{0}] requires the parameter [{1}]", dtOp,
+ KerberosDelegationTokenAuthenticator.TOKEN_PARAM)
+ );
+ requestContinues = false;
+ } else {
+ Token<DelegationTokenIdentifier> dt =
+ new Token<DelegationTokenIdentifier>();
+ try {
+ dt.decodeFromUrlString(tokenToRenew);
+ long expirationTime = tokenManager.renewToken(dt,
+ requestUgi.getShortUserName());
+ map = new HashMap();
+ map.put("long", expirationTime);
+ } catch (IOException ex) {
+ throw new AuthenticationException(ex.toString(), ex);
+ }
+ }
+ break;
+ case CANCELDELEGATIONTOKEN:
+ String tokenToCancel = ServletUtils.getParameter(request,
+ KerberosDelegationTokenAuthenticator.TOKEN_PARAM);
+ if (tokenToCancel == null) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST,
+ MessageFormat.format(
+ "Operation [{0}] requires the parameter [{1}]", dtOp,
+ KerberosDelegationTokenAuthenticator.TOKEN_PARAM)
+ );
+ requestContinues = false;
+ } else {
+ Token<DelegationTokenIdentifier> dt =
+ new Token<DelegationTokenIdentifier>();
+ try {
+ dt.decodeFromUrlString(tokenToCancel);
+ tokenManager.cancelToken(dt, (requestUgi != null)
+ ? requestUgi.getShortUserName() : null);
+ } catch (IOException ex) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND,
+ "Invalid delegation token, cannot cancel");
requestContinues = false;
- } else {
- if (dtOp == DelegationTokenOperation.CANCELDELEGATIONTOKEN) {
- Token<DelegationTokenIdentifier> dt =
- new Token<DelegationTokenIdentifier>();
- dt.decodeFromUrlString(tokenParam);
- tokenManager.cancelToken(dt,
- UserGroupInformation.getCurrentUser().getUserName());
- } else {
- Token<DelegationTokenIdentifier> dt =
- new Token<DelegationTokenIdentifier>();
- dt.decodeFromUrlString(tokenParam);
- long expirationTime =
- tokenManager.renewToken(dt, token.getUserName());
- map = new HashMap();
- map.put("long", expirationTime);
- }
}
- break;
- }
- if (requestContinues) {
- response.setStatus(HttpServletResponse.SC_OK);
- if (map != null) {
- response.setContentType(MediaType.APPLICATION_JSON);
- Writer writer = response.getWriter();
- JSONObject.writeJSONString(map, writer);
- writer.write(ENTER);
- writer.flush();
-
}
- requestContinues = false;
+ break;
+ }
+ if (requestContinues) {
+ response.setStatus(HttpServletResponse.SC_OK);
+ if (map != null) {
+ response.setContentType(MediaType.APPLICATION_JSON);
+ Writer writer = response.getWriter();
+ ObjectMapper jsonMapper = new ObjectMapper();
+ jsonMapper.writeValue(writer, map);
+ writer.write(ENTER);
+ writer.flush();
}
- } catch (DelegationTokenManagerException ex) {
- throw new AuthenticationException(ex.toString(), ex);
+ requestContinues = false;
}
}
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
- MessageFormat.format(
- "Wrong HTTP method [{0}] for operation [{1}], it should be [{2}]",
- request.getMethod(), dtOp, dtOp.getHttpMethod()));
+ MessageFormat.format(
+ "Wrong HTTP method [{0}] for operation [{1}], it should be " +
+ "[{2}]", request.getMethod(), dtOp, dtOp.getHttpMethod()));
requestContinues = false;
}
}
@@ -174,13 +301,15 @@ public class HttpFSKerberosAuthenticatio
@SuppressWarnings("unchecked")
private static Map delegationTokenToJSON(Token token) throws IOException {
Map json = new LinkedHashMap();
- json.put(HttpFSKerberosAuthenticator.DELEGATION_TOKEN_URL_STRING_JSON,
- token.encodeToUrlString());
+ json.put(
+ KerberosDelegationTokenAuthenticator.DELEGATION_TOKEN_URL_STRING_JSON,
+ token.encodeToUrlString());
Map response = new LinkedHashMap();
- response.put(HttpFSKerberosAuthenticator.DELEGATION_TOKEN_JSON, json);
+ response.put(KerberosDelegationTokenAuthenticator.DELEGATION_TOKEN_JSON,
+ json);
return response;
}
-
+
/**
* Authenticates a request looking for the <code>delegation</code>
* query-string parameter and verifying it is a valid token. If there is not
@@ -190,41 +319,37 @@ public class HttpFSKerberosAuthenticatio
*
* @param request the HTTP client request.
* @param response the HTTP client response.
- *
* @return the authentication token for the authenticated request.
* @throws IOException thrown if an IO error occurred.
* @throws AuthenticationException thrown if the authentication failed.
*/
@Override
public AuthenticationToken authenticate(HttpServletRequest request,
- HttpServletResponse response)
- throws IOException, AuthenticationException {
+ HttpServletResponse response)
+ throws IOException, AuthenticationException {
AuthenticationToken token;
- String delegationParam =
- request.getParameter(HttpFSKerberosAuthenticator.DELEGATION_PARAM);
+ String delegationParam = ServletUtils.getParameter(request,
+ KerberosDelegationTokenAuthenticator.DELEGATION_PARAM);
if (delegationParam != null) {
try {
Token<DelegationTokenIdentifier> dt =
- new Token<DelegationTokenIdentifier>();
+ new Token<DelegationTokenIdentifier>();
dt.decodeFromUrlString(delegationParam);
- DelegationTokenManager tokenManager =
- HttpFSServerWebApp.get().get(DelegationTokenManager.class);
UserGroupInformation ugi = tokenManager.verifyToken(dt);
final String shortName = ugi.getShortUserName();
// creating a ephemeral token
token = new AuthenticationToken(shortName, ugi.getUserName(),
- getType());
+ getType());
token.setExpires(0);
} catch (Throwable ex) {
throw new AuthenticationException("Could not verify DelegationToken, " +
- ex.toString(), ex);
+ ex.toString(), ex);
}
} else {
- token = super.authenticate(request, response);
+ token = authHandler.authenticate(request, response);
}
return token;
}
-
}
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java Fri Aug 8 04:58:58 2014
@@ -15,49 +15,47 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.hadoop.fs.http.client;
-
+package org.apache.hadoop.security.token.delegation.web;
import org.apache.hadoop.classification.InterfaceAudience;
-import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.authentication.client.Authenticator;
-import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
+import org.apache.hadoop.security.authentication.client.ConnectionConfigurator;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
-import org.json.simple.JSONObject;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
-import java.net.URI;
import java.net.URL;
+import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
- * A <code>KerberosAuthenticator</code> subclass that fallback to
- * {@link HttpFSPseudoAuthenticator}.
+ * {@link Authenticator} wrapper that enhances an {@link Authenticator} with
+ * Delegation Token support.
*/
-@InterfaceAudience.Private
-public class HttpFSKerberosAuthenticator extends KerberosAuthenticator {
-
- /**
- * Returns the fallback authenticator if the server does not use
- * Kerberos SPNEGO HTTP authentication.
- *
- * @return a {@link HttpFSPseudoAuthenticator} instance.
- */
- @Override
- protected Authenticator getFallBackAuthenticator() {
- return new HttpFSPseudoAuthenticator();
- }
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public abstract class DelegationTokenAuthenticator implements Authenticator {
+ private static Logger LOG =
+ LoggerFactory.getLogger(DelegationTokenAuthenticator.class);
+
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final String APPLICATION_JSON_MIME = "application/json";
private static final String HTTP_GET = "GET";
private static final String HTTP_PUT = "PUT";
+ public static final String OP_PARAM = "op";
+
public static final String DELEGATION_PARAM = "delegation";
public static final String TOKEN_PARAM = "token";
public static final String RENEWER_PARAM = "renewer";
@@ -78,7 +76,7 @@ public class HttpFSKerberosAuthenticator
private boolean requiresKerberosCredentials;
private DelegationTokenOperation(String httpMethod,
- boolean requiresKerberosCredentials) {
+ boolean requiresKerberosCredentials) {
this.httpMethod = httpMethod;
this.requiresKerberosCredentials = requiresKerberosCredentials;
}
@@ -90,98 +88,162 @@ public class HttpFSKerberosAuthenticator
public boolean requiresKerberosCredentials() {
return requiresKerberosCredentials;
}
+ }
+
+ private Authenticator authenticator;
+ public DelegationTokenAuthenticator(Authenticator authenticator) {
+ this.authenticator = authenticator;
}
- public static void injectDelegationToken(Map<String, String> params,
- Token<?> dtToken)
- throws IOException {
- if (dtToken != null) {
- params.put(DELEGATION_PARAM, dtToken.encodeToUrlString());
- }
+ @Override
+ public void setConnectionConfigurator(ConnectionConfigurator configurator) {
+ authenticator.setConnectionConfigurator(configurator);
}
private boolean hasDelegationToken(URL url) {
- return url.getQuery().contains(DELEGATION_PARAM + "=");
+ String queryStr = url.getQuery();
+ return (queryStr != null) && queryStr.contains(DELEGATION_PARAM + "=");
}
@Override
public void authenticate(URL url, AuthenticatedURL.Token token)
- throws IOException, AuthenticationException {
+ throws IOException, AuthenticationException {
if (!hasDelegationToken(url)) {
- super.authenticate(url, token);
+ authenticator.authenticate(url, token);
}
}
- public static final String OP_PARAM = "op";
-
- public static Token<?> getDelegationToken(URI fsURI,
- InetSocketAddress httpFSAddr, AuthenticatedURL.Token token,
- String renewer) throws IOException {
- DelegationTokenOperation op =
- DelegationTokenOperation.GETDELEGATIONTOKEN;
- Map<String, String> params = new HashMap<String, String>();
- params.put(OP_PARAM, op.toString());
- params.put(RENEWER_PARAM,renewer);
- URL url = HttpFSUtils.createURL(new Path(fsURI), params);
- AuthenticatedURL aUrl =
- new AuthenticatedURL(new HttpFSKerberosAuthenticator());
- try {
- HttpURLConnection conn = aUrl.openConnection(url, token);
- conn.setRequestMethod(op.getHttpMethod());
- HttpFSUtils.validateResponse(conn, HttpURLConnection.HTTP_OK);
- JSONObject json = (JSONObject) ((JSONObject)
- HttpFSUtils.jsonParse(conn)).get(DELEGATION_TOKEN_JSON);
- String tokenStr = (String)
- json.get(DELEGATION_TOKEN_URL_STRING_JSON);
- Token<AbstractDelegationTokenIdentifier> dToken =
+ /**
+ * Requests a delegation token using the configured <code>Authenticator</code>
+ * for authentication.
+ *
+ * @param url the URL to get the delegation token from. Only HTTP/S URLs are
+ * supported.
+ * @param token the authentication token being used for the user where the
+ * Delegation token will be stored.
+ * @throws IOException if an IO error occurred.
+ * @throws AuthenticationException if an authentication exception occurred.
+ */
+ public Token<AbstractDelegationTokenIdentifier> getDelegationToken(URL url,
+ AuthenticatedURL.Token token, String renewer)
+ throws IOException, AuthenticationException {
+ Map json = doDelegationTokenOperation(url, token,
+ DelegationTokenOperation.GETDELEGATIONTOKEN, renewer, null, true);
+ json = (Map) json.get(DELEGATION_TOKEN_JSON);
+ String tokenStr = (String) json.get(DELEGATION_TOKEN_URL_STRING_JSON);
+ Token<AbstractDelegationTokenIdentifier> dToken =
new Token<AbstractDelegationTokenIdentifier>();
- dToken.decodeFromUrlString(tokenStr);
- SecurityUtil.setTokenService(dToken, httpFSAddr);
- return dToken;
- } catch (AuthenticationException ex) {
- throw new IOException(ex.toString(), ex);
- }
+ dToken.decodeFromUrlString(tokenStr);
+ InetSocketAddress service = new InetSocketAddress(url.getHost(),
+ url.getPort());
+ SecurityUtil.setTokenService(dToken, service);
+ return dToken;
}
- public static long renewDelegationToken(URI fsURI,
- AuthenticatedURL.Token token, Token<?> dToken) throws IOException {
- Map<String, String> params = new HashMap<String, String>();
- params.put(OP_PARAM,
- DelegationTokenOperation.RENEWDELEGATIONTOKEN.toString());
- params.put(TOKEN_PARAM, dToken.encodeToUrlString());
- URL url = HttpFSUtils.createURL(new Path(fsURI), params);
- AuthenticatedURL aUrl =
- new AuthenticatedURL(new HttpFSKerberosAuthenticator());
+ /**
+ * Renews a delegation token from the server end-point using the
+ * configured <code>Authenticator</code> for authentication.
+ *
+ * @param url the URL to renew the delegation token from. Only HTTP/S URLs are
+ * supported.
+ * @param token the authentication token with the Delegation Token to renew.
+ * @throws IOException if an IO error occurred.
+ * @throws AuthenticationException if an authentication exception occurred.
+ */
+ public long renewDelegationToken(URL url,
+ AuthenticatedURL.Token token,
+ Token<AbstractDelegationTokenIdentifier> dToken)
+ throws IOException, AuthenticationException {
+ Map json = doDelegationTokenOperation(url, token,
+ DelegationTokenOperation.RENEWDELEGATIONTOKEN, null, dToken, true);
+ return (Long) json.get(RENEW_DELEGATION_TOKEN_JSON);
+ }
+
+ /**
+ * Cancels a delegation token from the server end-point. It does not require
+ * being authenticated by the configured <code>Authenticator</code>.
+ *
+ * @param url the URL to cancel the delegation token from. Only HTTP/S URLs
+ * are supported.
+ * @param token the authentication token with the Delegation Token to cancel.
+ * @throws IOException if an IO error occurred.
+ */
+ public void cancelDelegationToken(URL url,
+ AuthenticatedURL.Token token,
+ Token<AbstractDelegationTokenIdentifier> dToken)
+ throws IOException {
try {
- HttpURLConnection conn = aUrl.openConnection(url, token);
- conn.setRequestMethod(
- DelegationTokenOperation.RENEWDELEGATIONTOKEN.getHttpMethod());
- HttpFSUtils.validateResponse(conn, HttpURLConnection.HTTP_OK);
- JSONObject json = (JSONObject) ((JSONObject)
- HttpFSUtils.jsonParse(conn)).get(DELEGATION_TOKEN_JSON);
- return (Long)(json.get(RENEW_DELEGATION_TOKEN_JSON));
+ doDelegationTokenOperation(url, token,
+ DelegationTokenOperation.CANCELDELEGATIONTOKEN, null, dToken, false);
} catch (AuthenticationException ex) {
- throw new IOException(ex.toString(), ex);
+ throw new IOException("This should not happen: " + ex.getMessage(), ex);
}
}
- public static void cancelDelegationToken(URI fsURI,
- AuthenticatedURL.Token token, Token<?> dToken) throws IOException {
+ private Map doDelegationTokenOperation(URL url,
+ AuthenticatedURL.Token token, DelegationTokenOperation operation,
+ String renewer, Token<?> dToken, boolean hasResponse)
+ throws IOException, AuthenticationException {
+ Map ret = null;
Map<String, String> params = new HashMap<String, String>();
- params.put(OP_PARAM,
- DelegationTokenOperation.CANCELDELEGATIONTOKEN.toString());
- params.put(TOKEN_PARAM, dToken.encodeToUrlString());
- URL url = HttpFSUtils.createURL(new Path(fsURI), params);
- AuthenticatedURL aUrl =
- new AuthenticatedURL(new HttpFSKerberosAuthenticator());
- try {
- HttpURLConnection conn = aUrl.openConnection(url, token);
- conn.setRequestMethod(
- DelegationTokenOperation.CANCELDELEGATIONTOKEN.getHttpMethod());
- HttpFSUtils.validateResponse(conn, HttpURLConnection.HTTP_OK);
- } catch (AuthenticationException ex) {
- throw new IOException(ex.toString(), ex);
+ params.put(OP_PARAM, operation.toString());
+ if (renewer != null) {
+ params.put(RENEWER_PARAM, renewer);
+ }
+ if (dToken != null) {
+ params.put(TOKEN_PARAM, dToken.encodeToUrlString());
+ }
+ String urlStr = url.toExternalForm();
+ StringBuilder sb = new StringBuilder(urlStr);
+ String separator = (urlStr.contains("?")) ? "&" : "?";
+ for (Map.Entry<String, String> entry : params.entrySet()) {
+ sb.append(separator).append(entry.getKey()).append("=").
+ append(URLEncoder.encode(entry.getValue(), "UTF8"));
+ separator = "&";
+ }
+ url = new URL(sb.toString());
+ AuthenticatedURL aUrl = new AuthenticatedURL(this);
+ HttpURLConnection conn = aUrl.openConnection(url, token);
+ conn.setRequestMethod(operation.getHttpMethod());
+ validateResponse(conn, HttpURLConnection.HTTP_OK);
+ if (hasResponse) {
+ String contentType = conn.getHeaderField(CONTENT_TYPE);
+ contentType = (contentType != null) ? contentType.toLowerCase()
+ : null;
+ if (contentType != null &&
+ contentType.contains(APPLICATION_JSON_MIME)) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ret = mapper.readValue(conn.getInputStream(), Map.class);
+ } catch (Exception ex) {
+ throw new AuthenticationException(String.format(
+ "'%s' did not handle the '%s' delegation token operation: %s",
+ url.getAuthority(), operation, ex.getMessage()), ex);
+ }
+ } else {
+ throw new AuthenticationException(String.format("'%s' did not " +
+ "respond with JSON to the '%s' delegation token operation",
+ url.getAuthority(), operation));
+ }
+ }
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void validateResponse(HttpURLConnection conn, int expected)
+ throws IOException {
+ int status = conn.getResponseCode();
+ if (status != expected) {
+ try {
+ conn.getInputStream().close();
+ } catch (IOException ex) {
+ //NOP
+ }
+ String msg = String.format("HTTP status, expected [%d], got [%d]: %s",
+ expected, status, conn.getResponseMessage());
+ LOG.debug(msg);
+ throw new IOException(msg);
}
}
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenIdentifier.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenIdentifier.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenIdentifier.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenIdentifier.java Fri Aug 8 04:58:58 2014
@@ -15,21 +15,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.hadoop.lib.service;
+package org.apache.hadoop.security.token.delegation.web;
import org.apache.hadoop.classification.InterfaceAudience;
-import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
+import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
/**
- * HttpFS <code>DelegationTokenIdentifier</code> implementation.
+ * Concrete delegation token identifier used by {@link DelegationTokenManager},
+ * {@link KerberosDelegationTokenAuthenticationHandler} and
+ * {@link DelegationTokenAuthenticationFilter}.
*/
@InterfaceAudience.Private
+@InterfaceStability.Evolving
public class DelegationTokenIdentifier
- extends AbstractDelegationTokenIdentifier {
+ extends AbstractDelegationTokenIdentifier {
- private Text kind = WebHdfsFileSystem.TOKEN_KIND;
+ private Text kind;
public DelegationTokenIdentifier(Text kind) {
this.kind = kind;
@@ -50,8 +53,8 @@ public class DelegationTokenIdentifier
}
/**
- * Returns the kind, <code>TOKEN_KIND</code>.
- * @return returns <code>TOKEN_KIND</code>.
+ * Return the delegation token kind
+ * @return returns the delegation token kind
*/
@Override
public Text getKind() {
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java?rev=1616672&r1=1616671&r2=1616672&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java Fri Aug 8 04:58:58 2014
@@ -15,20 +15,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.hadoop.lib.service.security;
+package org.apache.hadoop.security.token.delegation.web;
import org.apache.hadoop.classification.InterfaceAudience;
-import org.apache.hadoop.fs.http.server.HttpFSServerWebApp;
-import org.apache.hadoop.hdfs.web.SWebHdfsFileSystem;
-import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
+import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.io.Text;
-import org.apache.hadoop.lib.server.BaseService;
-import org.apache.hadoop.lib.server.ServerException;
-import org.apache.hadoop.lib.server.ServiceException;
-import org.apache.hadoop.lib.service.DelegationTokenIdentifier;
-import org.apache.hadoop.lib.service.DelegationTokenManager;
-import org.apache.hadoop.lib.service.DelegationTokenManagerException;
-import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
@@ -38,88 +29,89 @@ import java.io.DataInputStream;
import java.io.IOException;
/**
- * DelegationTokenManager service implementation.
+ * Delegation Token Manager used by the
+ * {@link KerberosDelegationTokenAuthenticationHandler}.
+ *
*/
@InterfaceAudience.Private
-public class DelegationTokenManagerService extends BaseService
- implements DelegationTokenManager {
+@InterfaceStability.Evolving
+class DelegationTokenManager {
- private static final String PREFIX = "delegation.token.manager";
-
- private static final String UPDATE_INTERVAL = "update.interval";
+ private static class DelegationTokenSecretManager
+ extends AbstractDelegationTokenSecretManager<DelegationTokenIdentifier> {
- private static final String MAX_LIFETIME = "max.lifetime";
+ private Text tokenKind;
- private static final String RENEW_INTERVAL = "renew.interval";
+ public DelegationTokenSecretManager(Text tokenKind,
+ long delegationKeyUpdateInterval,
+ long delegationTokenMaxLifetime,
+ long delegationTokenRenewInterval,
+ long delegationTokenRemoverScanInterval) {
+ super(delegationKeyUpdateInterval, delegationTokenMaxLifetime,
+ delegationTokenRenewInterval, delegationTokenRemoverScanInterval);
+ this.tokenKind = tokenKind;
+ }
- private static final long HOUR = 60 * 60 * 1000;
- private static final long DAY = 24 * HOUR;
+ @Override
+ public DelegationTokenIdentifier createIdentifier() {
+ return new DelegationTokenIdentifier(tokenKind);
+ }
- DelegationTokenSecretManager secretManager = null;
+ }
+ private AbstractDelegationTokenSecretManager secretManager = null;
+ private boolean managedSecretManager;
private Text tokenKind;
- public DelegationTokenManagerService() {
- super(PREFIX);
+ public DelegationTokenManager(Text tokenKind,
+ long delegationKeyUpdateInterval,
+ long delegationTokenMaxLifetime,
+ long delegationTokenRenewInterval,
+ long delegationTokenRemoverScanInterval) {
+ this.secretManager = new DelegationTokenSecretManager(tokenKind,
+ delegationKeyUpdateInterval, delegationTokenMaxLifetime,
+ delegationTokenRenewInterval, delegationTokenRemoverScanInterval);
+ this.tokenKind = tokenKind;
+ managedSecretManager = true;
}
/**
- * Initializes the service.
- *
- * @throws ServiceException thrown if the service could not be initialized.
- */
- @Override
- protected void init() throws ServiceException {
-
- long updateInterval = getServiceConfig().getLong(UPDATE_INTERVAL, DAY);
- long maxLifetime = getServiceConfig().getLong(MAX_LIFETIME, 7 * DAY);
- long renewInterval = getServiceConfig().getLong(RENEW_INTERVAL, DAY);
- tokenKind = (HttpFSServerWebApp.get().isSslEnabled())
- ? SWebHdfsFileSystem.TOKEN_KIND : WebHdfsFileSystem.TOKEN_KIND;
- secretManager = new DelegationTokenSecretManager(tokenKind, updateInterval,
- maxLifetime,
- renewInterval, HOUR);
- try {
- secretManager.startThreads();
- } catch (IOException ex) {
- throw new ServiceException(ServiceException.ERROR.S12,
- DelegationTokenManager.class.getSimpleName(),
- ex.toString(), ex);
+ * Sets an external <code>DelegationTokenSecretManager</code> instance to
+ * manage creation and verification of Delegation Tokens.
+ * <p/>
+ * This is useful for use cases where secrets must be shared across multiple
+ * services.
+ *
+ * @param secretManager a <code>DelegationTokenSecretManager</code> instance
+ */
+ public void setExternalDelegationTokenSecretManager(
+ AbstractDelegationTokenSecretManager secretManager) {
+ this.secretManager.stopThreads();
+ this.secretManager = secretManager;
+ this.tokenKind = secretManager.createIdentifier().getKind();
+ managedSecretManager = false;
+ }
+
+ public void init() {
+ if (managedSecretManager) {
+ try {
+ secretManager.startThreads();
+ } catch (IOException ex) {
+ throw new RuntimeException("Could not start " +
+ secretManager.getClass() + ": " + ex.toString(), ex);
+ }
}
}
- /**
- * Destroys the service.
- */
- @Override
public void destroy() {
- secretManager.stopThreads();
- super.destroy();
- }
-
- /**
- * Returns the service interface.
- *
- * @return the service interface.
- */
- @Override
- public Class getInterface() {
- return DelegationTokenManager.class;
+ if (managedSecretManager) {
+ secretManager.stopThreads();
+ }
}
- /**
- * Creates a delegation token.
- *
- * @param ugi UGI creating the token.
- * @param renewer token renewer.
- * @return new delegation token.
- * @throws DelegationTokenManagerException thrown if the token could not be
- * created.
- */
- @Override
+ @SuppressWarnings("unchecked")
public Token<DelegationTokenIdentifier> createToken(UserGroupInformation ugi,
- String renewer)
- throws DelegationTokenManagerException {
+ String renewer) {
renewer = (renewer == null) ? ugi.getShortUserName() : renewer;
String user = ugi.getUserName();
Text owner = new Text(user);
@@ -127,116 +119,35 @@ public class DelegationTokenManagerServi
if (ugi.getRealUser() != null) {
realUser = new Text(ugi.getRealUser().getUserName());
}
- DelegationTokenIdentifier tokenIdentifier =
- new DelegationTokenIdentifier(tokenKind, owner, new Text(renewer), realUser);
- Token<DelegationTokenIdentifier> token =
- new Token<DelegationTokenIdentifier>(tokenIdentifier, secretManager);
- try {
- SecurityUtil.setTokenService(token,
- HttpFSServerWebApp.get().getAuthority());
- } catch (ServerException ex) {
- throw new DelegationTokenManagerException(
- DelegationTokenManagerException.ERROR.DT04, ex.toString(), ex);
- }
- return token;
+ DelegationTokenIdentifier tokenIdentifier = new DelegationTokenIdentifier(
+ tokenKind, owner, new Text(renewer), realUser);
+ return new Token<DelegationTokenIdentifier>(tokenIdentifier, secretManager);
}
- /**
- * Renews a delegation token.
- *
- * @param token delegation token to renew.
- * @param renewer token renewer.
- * @return epoc expiration time.
- * @throws DelegationTokenManagerException thrown if the token could not be
- * renewed.
- */
- @Override
+ @SuppressWarnings("unchecked")
public long renewToken(Token<DelegationTokenIdentifier> token, String renewer)
- throws DelegationTokenManagerException {
- try {
- return secretManager.renewToken(token, renewer);
- } catch (IOException ex) {
- throw new DelegationTokenManagerException(
- DelegationTokenManagerException.ERROR.DT02, ex.toString(), ex);
- }
+ throws IOException {
+ return secretManager.renewToken(token, renewer);
}
- /**
- * Cancels a delegation token.
- *
- * @param token delegation token to cancel.
- * @param canceler token canceler.
- * @throws DelegationTokenManagerException thrown if the token could not be
- * canceled.
- */
- @Override
+ @SuppressWarnings("unchecked")
public void cancelToken(Token<DelegationTokenIdentifier> token,
- String canceler)
- throws DelegationTokenManagerException {
- try {
- secretManager.cancelToken(token, canceler);
- } catch (IOException ex) {
- throw new DelegationTokenManagerException(
- DelegationTokenManagerException.ERROR.DT03, ex.toString(), ex);
- }
+ String canceler) throws IOException {
+ canceler = (canceler != null) ? canceler :
+ verifyToken(token).getShortUserName();
+ secretManager.cancelToken(token, canceler);
}
- /**
- * Verifies a delegation token.
- *
- * @param token delegation token to verify.
- * @return the UGI for the token.
- * @throws DelegationTokenManagerException thrown if the token could not be
- * verified.
- */
- @Override
- public UserGroupInformation verifyToken(Token<DelegationTokenIdentifier> token)
- throws DelegationTokenManagerException {
+ @SuppressWarnings("unchecked")
+ public UserGroupInformation verifyToken(Token<DelegationTokenIdentifier>
+ token) throws IOException {
ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier());
DataInputStream dis = new DataInputStream(buf);
DelegationTokenIdentifier id = new DelegationTokenIdentifier(tokenKind);
- try {
- id.readFields(dis);
- dis.close();
- secretManager.verifyToken(id, token.getPassword());
- } catch (Exception ex) {
- throw new DelegationTokenManagerException(
- DelegationTokenManagerException.ERROR.DT01, ex.toString(), ex);
- }
+ id.readFields(dis);
+ dis.close();
+ secretManager.verifyToken(id, token.getPassword());
return id.getUser();
}
- private static class DelegationTokenSecretManager
- extends AbstractDelegationTokenSecretManager<DelegationTokenIdentifier> {
-
- private Text tokenKind;
-
- /**
- * Create a secret manager
- *
- * @param delegationKeyUpdateInterval the number of seconds for rolling new
- * secret keys.
- * @param delegationTokenMaxLifetime the maximum lifetime of the delegation
- * tokens
- * @param delegationTokenRenewInterval how often the tokens must be renewed
- * @param delegationTokenRemoverScanInterval how often the tokens are
- * scanned
- * for expired tokens
- */
- public DelegationTokenSecretManager(Text tokenKind, long delegationKeyUpdateInterval,
- long delegationTokenMaxLifetime,
- long delegationTokenRenewInterval,
- long delegationTokenRemoverScanInterval) {
- super(delegationKeyUpdateInterval, delegationTokenMaxLifetime,
- delegationTokenRenewInterval, delegationTokenRemoverScanInterval);
- this.tokenKind = tokenKind;
- }
-
- @Override
- public DelegationTokenIdentifier createIdentifier() {
- return new DelegationTokenIdentifier(tokenKind);
- }
-
- }
-
}
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticationHandler.java?rev=1616672&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticationHandler.java (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticationHandler.java Fri Aug 8 04:58:58 2014
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.security.token.delegation.web;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
+import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
+
+/**
+ * An {@link AuthenticationHandler} that implements Kerberos SPNEGO mechanism
+ * for HTTP and supports Delegation Token functionality.
+ * <p/>
+ * In addition to the {@link KerberosAuthenticationHandler} configuration
+ * properties, this handler supports:
+ * <ul>
+ * <li>kerberos.delegation-token.token-kind: the token kind for generated tokens
+ * (no default, required property).</li>
+ * <li>kerberos.delegation-token.update-interval.sec: secret manager master key
+ * update interval in seconds (default 1 day).</li>
+ * <li>kerberos.delegation-token.max-lifetime.sec: maximum life of a delegation
+ * token in seconds (default 7 days).</li>
+ * <li>kerberos.delegation-token.renewal-interval.sec: renewal interval for
+ * delegation tokens in seconds (default 1 day).</li>
+ * <li>kerberos.delegation-token.removal-scan-interval.sec: delegation tokens
+ * removal scan interval in seconds (default 1 hour).</li>
+ * </ul>
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Evolving
+public class KerberosDelegationTokenAuthenticationHandler
+ extends DelegationTokenAuthenticationHandler {
+
+ public KerberosDelegationTokenAuthenticationHandler() {
+ super(new KerberosAuthenticationHandler(KerberosAuthenticationHandler.TYPE +
+ TYPE_POSTFIX));
+ }
+
+}
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticator.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticator.java?rev=1616672&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticator.java (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/KerberosDelegationTokenAuthenticator.java Fri Aug 8 04:58:58 2014
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.security.token.delegation.web;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.security.authentication.client.Authenticator;
+import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
+
+/**
+ * The <code>KerberosDelegationTokenAuthenticator</code> provides support for
+ * Kerberos SPNEGO authentication mechanism and support for Hadoop Delegation
+ * Token operations.
+ * <p/>
+ * It falls back to the {@link PseudoDelegationTokenAuthenticator} if the HTTP
+ * endpoint does not trigger a SPNEGO authentication
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public class KerberosDelegationTokenAuthenticator
+ extends DelegationTokenAuthenticator {
+
+ public KerberosDelegationTokenAuthenticator() {
+ super(new KerberosAuthenticator() {
+ @Override
+ protected Authenticator getFallBackAuthenticator() {
+ return new PseudoDelegationTokenAuthenticator();
+ }
+ });
+ }
+}