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 ji...@apache.org on 2013/10/11 23:49:02 UTC
svn commit: r1531436 - in
/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop:
ipc/ security/ security/token/ security/token/delegation/
Author: jing9
Date: Fri Oct 11 21:49:01 2013
New Revision: 1531436
URL: http://svn.apache.org/r1531436
Log:
HDFS-5322. HDFS delegation token not found in cache errors seen on secure HA clusters. Contributed by Jing Zhao.
Modified:
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcServer.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/SecretManager.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java?rev=1531436&r1=1531435&r2=1531436&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java Fri Oct 11 21:49:01 2013
@@ -1295,6 +1295,29 @@ public abstract class Server {
}
}
+ private Throwable getCauseForInvalidToken(IOException e) {
+ Throwable cause = e;
+ while (cause != null) {
+ if (cause instanceof RetriableException) {
+ return (RetriableException) cause;
+ } else if (cause instanceof StandbyException) {
+ return (StandbyException) cause;
+ } else if (cause instanceof InvalidToken) {
+ // FIXME: hadoop method signatures are restricting the SASL
+ // callbacks to only returning InvalidToken, but some services
+ // need to throw other exceptions (ex. NN + StandyException),
+ // so for now we'll tunnel the real exceptions via an
+ // InvalidToken's cause which normally is not set
+ if (cause.getCause() != null) {
+ cause = cause.getCause();
+ }
+ return cause;
+ }
+ cause = cause.getCause();
+ }
+ return e;
+ }
+
private void saslProcess(RpcSaslProto saslMessage)
throws WrappedRpcServerException, IOException, InterruptedException {
if (saslContextEstablished) {
@@ -1307,29 +1330,11 @@ public abstract class Server {
try {
saslResponse = processSaslMessage(saslMessage);
} catch (IOException e) {
- IOException sendToClient = e;
- Throwable cause = e;
- while (cause != null) {
- if (cause instanceof InvalidToken) {
- // FIXME: hadoop method signatures are restricting the SASL
- // callbacks to only returning InvalidToken, but some services
- // need to throw other exceptions (ex. NN + StandyException),
- // so for now we'll tunnel the real exceptions via an
- // InvalidToken's cause which normally is not set
- if (cause.getCause() != null) {
- cause = cause.getCause();
- }
- sendToClient = (IOException) cause;
- break;
- }
- cause = cause.getCause();
- }
rpcMetrics.incrAuthenticationFailures();
- String clientIP = this.toString();
// attempting user could be null
- AUDITLOG.warn(AUTH_FAILED_FOR + clientIP + ":" + attemptingUser +
- " (" + e.getLocalizedMessage() + ")");
- throw sendToClient;
+ AUDITLOG.warn(AUTH_FAILED_FOR + this.toString() + ":"
+ + attemptingUser + " (" + e.getLocalizedMessage() + ")");
+ throw (IOException) getCauseForInvalidToken(e);
}
if (saslServer != null && saslServer.isComplete()) {
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcServer.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcServer.java?rev=1531436&r1=1531435&r2=1531436&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcServer.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcServer.java Fri Oct 11 21:49:01 2013
@@ -45,11 +45,13 @@ import org.apache.commons.logging.LogFac
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.ipc.RetriableException;
import org.apache.hadoop.ipc.Server;
import org.apache.hadoop.ipc.Server.Connection;
+import org.apache.hadoop.ipc.StandbyException;
import org.apache.hadoop.security.token.SecretManager;
-import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.security.token.SecretManager.InvalidToken;
+import org.apache.hadoop.security.token.TokenIdentifier;
/**
* A utility class for dealing with SASL on RPC server
@@ -267,13 +269,15 @@ public class SaslRpcServer {
this.connection = connection;
}
- private char[] getPassword(TokenIdentifier tokenid) throws InvalidToken {
- return encodePassword(secretManager.retrievePassword(tokenid));
+ private char[] getPassword(TokenIdentifier tokenid) throws InvalidToken,
+ StandbyException, RetriableException, IOException {
+ return encodePassword(secretManager.retriableRetrievePassword(tokenid));
}
@Override
public void handle(Callback[] callbacks) throws InvalidToken,
- UnsupportedCallbackException {
+ UnsupportedCallbackException, StandbyException, RetriableException,
+ IOException {
NameCallback nc = null;
PasswordCallback pc = null;
AuthorizeCallback ac = null;
@@ -292,7 +296,8 @@ public class SaslRpcServer {
}
}
if (pc != null) {
- TokenIdentifier tokenIdentifier = getIdentifier(nc.getDefaultName(), secretManager);
+ TokenIdentifier tokenIdentifier = getIdentifier(nc.getDefaultName(),
+ secretManager);
char[] password = getPassword(tokenIdentifier);
UserGroupInformation user = null;
user = tokenIdentifier.getUser(); // may throw exception
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/SecretManager.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/SecretManager.java?rev=1531436&r1=1531435&r2=1531436&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/SecretManager.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/SecretManager.java Fri Oct 11 21:49:01 2013
@@ -29,6 +29,7 @@ import javax.crypto.spec.SecretKeySpec;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.ipc.RetriableException;
import org.apache.hadoop.ipc.StandbyException;
@@ -66,7 +67,29 @@ public abstract class SecretManager<T ex
* @return the password to use
* @throws InvalidToken the token was invalid
*/
- public abstract byte[] retrievePassword(T identifier) throws InvalidToken;
+ public abstract byte[] retrievePassword(T identifier)
+ throws InvalidToken;
+
+ /**
+ * The same functionality with {@link #retrievePassword}, except that this
+ * method can throw a {@link RetriableException} or a {@link StandbyException}
+ * to indicate that client can retry/failover the same operation because of
+ * temporary issue on the server side.
+ *
+ * @param identifier the identifier to validate
+ * @return the password to use
+ * @throws InvalidToken the token was invalid
+ * @throws StandbyException the server is in standby state, the client can
+ * try other servers
+ * @throws RetriableException the token was invalid, and the server thinks
+ * this may be a temporary issue and suggests the client to retry
+ * @throws IOException to allow future exceptions to be added without breaking
+ * compatibility
+ */
+ public byte[] retriableRetrievePassword(T identifier)
+ throws InvalidToken, StandbyException, RetriableException, IOException {
+ return retrievePassword(identifier);
+ }
/**
* Create an empty token identifier.
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java?rev=1531436&r1=1531435&r2=1531436&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java Fri Oct 11 21:49:01 2013
@@ -289,20 +289,30 @@ extends AbstractDelegationTokenIdentifie
+ tokenRenewInterval, password, getTrackingIdIfEnabled(identifier)));
return password;
}
-
- @Override
- public synchronized byte[] retrievePassword(TokenIdent identifier)
+
+ /**
+ * Find the DelegationTokenInformation for the given token id, and verify that
+ * if the token is expired. Note that this method should be called with
+ * acquiring the secret manager's monitor.
+ */
+ protected DelegationTokenInformation checkToken(TokenIdent identifier)
throws InvalidToken {
+ assert Thread.holdsLock(this);
DelegationTokenInformation info = currentTokens.get(identifier);
if (info == null) {
throw new InvalidToken("token (" + identifier.toString()
+ ") can't be found in cache");
}
- long now = Time.now();
- if (info.getRenewDate() < now) {
+ if (info.getRenewDate() < Time.now()) {
throw new InvalidToken("token (" + identifier.toString() + ") is expired");
}
- return info.getPassword();
+ return info;
+ }
+
+ @Override
+ public synchronized byte[] retrievePassword(TokenIdent identifier)
+ throws InvalidToken {
+ return checkToken(identifier).getPassword();
}
protected String getTrackingIdIfEnabled(TokenIdent ident) {