You are viewing a plain text version of this content. The canonical link for it is here.
Posted to hdfs-commits@hadoop.apache.org by bo...@apache.org on 2010/01/26 20:34:08 UTC

svn commit: r903379 - in /hadoop/hdfs/trunk: ./ src/java/ src/java/org/apache/hadoop/hdfs/ src/java/org/apache/hadoop/hdfs/protocol/ src/java/org/apache/hadoop/hdfs/security/token/ src/java/org/apache/hadoop/hdfs/server/namenode/ src/test/hdfs/org/apac...

Author: boryas
Date: Tue Jan 26 19:34:06 2010
New Revision: 903379

URL: http://svn.apache.org/viewvc?rev=903379&view=rev
Log:
HDFS-899. Delegation Token Implementation

Added:
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationKey.java
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java
    hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/security/TestDelegationToken.java
Modified:
    hadoop/hdfs/trunk/CHANGES.txt
    hadoop/hdfs/trunk/src/java/hdfs-default.xml
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSClient.java
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSConfigKeys.java
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DistributedFileSystem.java
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/protocol/ClientProtocol.java
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
    hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java
    hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/TestDFSClientRetries.java

Modified: hadoop/hdfs/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/CHANGES.txt?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/CHANGES.txt (original)
+++ hadoop/hdfs/trunk/CHANGES.txt Tue Jan 26 19:34:06 2010
@@ -42,6 +42,10 @@
     COMPLETE state in response to getAdditionalBlock or completeFileInternal.
     (hairong)
 
+    HDFS-899. Delegation Token Implementation
+     and corresponding changes in Namenode and DFS Api to issue, 
+    renew and cancel delegation tokens. (jnp via boryas)
+
   OPTIMIZATIONS
 
   BUG FIXES

Modified: hadoop/hdfs/trunk/src/java/hdfs-default.xml
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/hdfs-default.xml?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/hdfs-default.xml (original)
+++ hadoop/hdfs/trunk/src/java/hdfs-default.xml Tue Jan 26 19:34:06 2010
@@ -481,4 +481,26 @@
   </description>
 </property>
 
+<property>
+  <name>dfs.namenode.delegation.key.update-interval</name>
+  <value>86400</value>
+  <description>The update frequency of master key for delegation tokens 
+       in the namenode.
+  </description>
+</property>
+
+<property>
+  <name>dfs.namenode.delegation.token.max-lifetime</name>
+  <value>604800</value>
+  <description>The maximum lifetime for which a delegation token is valid.
+  </description>
+</property>
+
+<property>
+  <name>dfs.namenode.delegation.token.renew-interval</name>
+  <value>86400</value>
+  <description>The frequency of renewal of delegation token.
+  </description>
+</property>
+
 </configuration>

Modified: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSClient.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSClient.java?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSClient.java (original)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSClient.java Tue Jan 26 19:34:06 2010
@@ -90,6 +90,7 @@
 import org.apache.hadoop.hdfs.protocol.DataTransferProtocol.PipelineAck;
 import org.apache.hadoop.hdfs.security.BlockAccessToken;
 import org.apache.hadoop.hdfs.security.InvalidAccessTokenException;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenIdentifier;
 import org.apache.hadoop.hdfs.server.common.HdfsConstants;
 import org.apache.hadoop.hdfs.server.common.UpgradeStatusReport;
 import org.apache.hadoop.hdfs.server.datanode.DataNode;
@@ -110,6 +111,9 @@
 import org.apache.hadoop.net.NodeBase;
 import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.UnixUserGroupInformation;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
 import org.apache.hadoop.util.Daemon;
 import org.apache.hadoop.util.DataChecksum;
 import org.apache.hadoop.util.Progressable;
@@ -348,6 +352,25 @@
     return serverDefaults;
   }
 
+  public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer)
+      throws IOException {
+    return namenode.getDelegationToken(renewer);
+  }
+
+  public Boolean renewDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws InvalidToken, IOException {
+    try {
+      return namenode.renewDelegationToken(token);
+    } catch (RemoteException re) {
+      throw re.unwrapRemoteException(InvalidToken.class);
+    }
+  }
+
+  public Boolean cancelDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws IOException {
+    return namenode.cancelDelegationToken(token);
+  }
+  
   /**
    * Report corrupt blocks that were discovered by the client.
    */

Modified: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSConfigKeys.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSConfigKeys.java?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSConfigKeys.java (original)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DFSConfigKeys.java Tue Jan 26 19:34:06 2010
@@ -88,6 +88,14 @@
   public static final String  DFS_NAMENODE_NAME_DIR_RESTORE_KEY = "dfs.namenode.name.dir.restore";
   public static final boolean DFS_NAMENODE_NAME_DIR_RESTORE_DEFAULT = false;
 
+  //Delegation token related keys
+  public static final String  DFS_NAMENODE_DELEGATION_KEY_UPDATE_INTERVAL_KEY = "dfs.namenode.delegation.key.update-interval";
+  public static final long    DFS_NAMENODE_DELEGATION_KEY_UPDATE_INTERVAL_DEFAULT = 86400;
+  public static final String  DFS_NAMENODE_DELEGATION_TOKEN_RENEW_INTERVAL_KEY = "dfs.namenode.delegation.token.renew-interval";
+  public static final long    DFS_NAMENODE_DELEGATION_TOKEN_RENEW_INTERVAL_DEFAULT = 86400;
+  public static final String  DFS_NAMENODE_DELEGATION_TOKEN_MAX_LIFETIME_KEY = "dfs.namenode.delegation.token.max-lifetime";
+  public static final long    DFS_NAMENODE_DELEGATION_TOKEN_MAX_LIFETIME_DEFAULT = 604800;
+
   //Following keys have no defaults
   public static final String  DFS_DATANODE_DATA_DIR_KEY = "dfs.datanode.data.dir";
   public static final String  DFS_NAMENODE_HTTPS_ADDRESS_KEY = "dfs.namenode.https-address";

Modified: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DistributedFileSystem.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DistributedFileSystem.java?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DistributedFileSystem.java (original)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/DistributedFileSystem.java Tue Jan 26 19:34:06 2010
@@ -31,11 +31,16 @@
 import org.apache.hadoop.hdfs.protocol.LocatedBlock;
 import org.apache.hadoop.hdfs.protocol.FSConstants.DatanodeReportType;
 import org.apache.hadoop.hdfs.protocol.FSConstants.UpgradeAction;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenIdentifier;
 import org.apache.hadoop.hdfs.server.common.UpgradeStatusReport;
 import org.apache.hadoop.hdfs.server.namenode.NameNode;
 import org.apache.hadoop.hdfs.DFSClient.DFSDataInputStream;
 import org.apache.hadoop.hdfs.DFSClient.DFSOutputStream;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.ipc.RemoteException;
 import org.apache.hadoop.security.AccessControlException;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
 import org.apache.hadoop.util.Progressable;
 import org.apache.hadoop.fs.Options;
 
@@ -599,5 +604,44 @@
     dfs.setTimes(getPathName(p), mtime, atime);
   }
   
+  /** 
+   * Delegation Token Operations
+   * These are DFS only operations.
+   */
   
+  /**
+   * Get a valid Delegation Token.
+   * 
+   * @param renewer Name of the designated renewer for the token
+   * @return Token<DelegationTokenIdentifier>
+   * @throws IOException
+   */
+  public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer)
+      throws IOException {
+    return dfs.getDelegationToken(renewer);
+  }
+
+  /**
+   * Renew an existing delegation token.
+   * 
+   * @param token delegation token obtained earlier
+   * @return True if renewed successfully else false
+   * @throws IOException
+   */
+  public Boolean renewDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws InvalidToken, IOException {
+    return dfs.renewDelegationToken(token);
+  }
+
+  /**
+   * Cancel an existing delegation token.
+   * 
+   * @param token delegation token
+   * @return True if canceled successfully else false
+   * @throws IOException
+   */
+  public Boolean cancelDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws IOException {
+    return dfs.cancelDelegationToken(token);
+  }
 }

Modified: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/protocol/ClientProtocol.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/protocol/ClientProtocol.java?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/protocol/ClientProtocol.java (original)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/protocol/ClientProtocol.java Tue Jan 26 19:34:06 2010
@@ -28,10 +28,13 @@
 import org.apache.hadoop.fs.Options;
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.hdfs.protocol.FSConstants.UpgradeAction;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenIdentifier;
 import org.apache.hadoop.hdfs.server.common.UpgradeStatusReport;
 import org.apache.hadoop.io.EnumSetWritable;
+import org.apache.hadoop.io.Text;
 import org.apache.hadoop.ipc.VersionedProtocol;
 import org.apache.hadoop.security.AccessControlException;
+import org.apache.hadoop.security.token.Token;
 
 /**********************************************************************
  * ClientProtocol is used by user code via 
@@ -46,9 +49,9 @@
    * Compared to the previous version the following changes have been introduced:
    * (Only the latest change is reflected.
    * The log of historical changes can be retrieved from the svn).
-   * 54: changed addBlock to include a list of excluded datanodes.
+   * 55: Adding Delegation Token related APIs
    */
-  public static final long versionID = 54L;
+  public static final long versionID = 55L;
   
   ///////////////////////////////////////
   // File contents
@@ -579,4 +582,33 @@
   public void updatePipeline(String clientName, Block oldBlock, 
       Block newBlock, DatanodeID[] newNodes)
   throws IOException;
+
+  /**
+   * Get a valid Delegation Token.
+   * 
+   * @param renewer the designated renewer for the token
+   * @return Token<DelegationTokenIdentifier>
+   * @throws IOException
+   */
+  public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer) throws IOException;
+
+  /**
+   * Renew an existing delegation token.
+   * 
+   * @param token delegation token obtained earlier
+   * @return True if renewed successfully else false
+   * @throws IOException
+   */
+  public Boolean renewDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws IOException;
+  
+  /**
+   * Cancel an existing delegation token.
+   * 
+   * @param token delegation token
+   * @return True if canceled successfully else false
+   * @throws IOException
+   */
+  public Boolean cancelDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws IOException;
 }

Added: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationKey.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationKey.java?rev=903379&view=auto
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationKey.java (added)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationKey.java Tue Jan 26 19:34:06 2010
@@ -0,0 +1,84 @@
+/**
+ * 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.hdfs.security.token;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import javax.crypto.SecretKey;
+
+import org.apache.hadoop.io.Writable;
+import org.apache.hadoop.io.WritableUtils;
+
+/**
+ * Key used for generating and verifying delegation tokens
+ */
+public class DelegationKey implements Writable {
+  private int keyId;
+  private long expiryDate;
+  private SecretKey key;
+
+  public DelegationKey() {
+    this(0, 0L, null);
+  }
+
+  public DelegationKey(int keyId, long expiryDate, SecretKey key) {
+    this.keyId = keyId;
+    this.expiryDate = expiryDate;
+    this.key = key;
+  }
+
+  public int getKeyId() {
+    return keyId;
+  }
+
+  public long getExpiryDate() {
+    return expiryDate;
+  }
+
+  public SecretKey getKey() {
+    return key;
+  }
+
+  public void setExpiryDate(long expiryDate) {
+    this.expiryDate = expiryDate;
+  }
+
+  /**
+   */
+  public void write(DataOutput out) throws IOException {
+    WritableUtils.writeVInt(out, keyId);
+    WritableUtils.writeVLong(out, expiryDate);
+    byte[] keyBytes = key.getEncoded();
+    WritableUtils.writeVInt(out, keyBytes.length);
+    out.write(keyBytes);
+  }
+
+  /**
+   */
+  public void readFields(DataInput in) throws IOException {
+    keyId = WritableUtils.readVInt(in);
+    expiryDate = WritableUtils.readVLong(in);
+    int len = WritableUtils.readVInt(in);
+    byte[] keyBytes = new byte[len];
+    in.readFully(keyBytes);
+    key = DelegationTokenSecretManager.createSecretKey(keyBytes);
+  }
+}

Added: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java?rev=903379&view=auto
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java (added)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java Tue Jan 26 19:34:06 2010
@@ -0,0 +1,146 @@
+/**
+ * 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.hdfs.security.token;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.io.Writable;
+import org.apache.hadoop.io.WritableFactories;
+import org.apache.hadoop.io.WritableFactory;
+import org.apache.hadoop.io.WritableUtils;
+import org.apache.hadoop.security.token.TokenIdentifier;
+
+public class DelegationTokenIdentifier extends TokenIdentifier {
+  static final Text KIND_NAME = new Text("HDFS_DELEGATION_TOKEN");
+
+  private Text owner;
+  private Text renewer;
+  private long issueDate;
+  private long maxDate;
+  private int sequenceNumber;
+  private int masterKeyId = 0;
+  
+  public DelegationTokenIdentifier() {
+    this(new Text(), new Text());
+  }
+  
+  public DelegationTokenIdentifier(Text owner, Text renewer) {
+    this.owner = owner;
+    this.renewer = renewer;
+    issueDate = 0;
+    maxDate = 0;
+  }
+
+  @Override
+  public Text getKind() {
+    return KIND_NAME;
+  }
+  
+  /**
+   * Get the username encoded in the token identifier
+   * 
+   * @return the username or owner
+   */
+  public Text getUsername() {
+    return owner;
+  }
+  
+  public Text getRenewer() {
+    return renewer;
+  }
+  
+  public void setIssueDate(long issueDate) {
+    this.issueDate = issueDate;
+  }
+  
+  public long getIssueDate() {
+    return issueDate;
+  }
+  
+  public void setMaxDate(long maxDate) {
+    this.maxDate = maxDate;
+  }
+  
+  public long getMaxDate() {
+    return maxDate;
+  }
+
+  public void setSequenceNumber(int seqNum) {
+    this.sequenceNumber = seqNum;
+  }
+  
+  public int getSequenceNumber() {
+    return sequenceNumber;
+  }
+
+  public void setMasterKeyId(int newId) {
+    masterKeyId = newId;
+  }
+
+  public int getMasterKeyId() {
+    return masterKeyId;
+  }
+
+  static boolean isEqual(Object a, Object b) {
+    return a == null ? b == null : a.equals(b);
+  }
+  
+  /** {@inheritDoc} */
+  public boolean equals(Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (obj instanceof DelegationTokenIdentifier) {
+      DelegationTokenIdentifier that = (DelegationTokenIdentifier) obj;
+      return this.sequenceNumber == that.sequenceNumber 
+          && this.issueDate == that.issueDate 
+          && this.maxDate == that.maxDate
+          && this.masterKeyId == that.masterKeyId
+          && isEqual(this.owner, that.owner) 
+          && isEqual(this.renewer, that.renewer);
+    }
+    return false;
+  }
+
+  /** {@inheritDoc} */
+  public int hashCode() {
+    return this.sequenceNumber;
+  }
+  
+  public void readFields(DataInput in) throws IOException {
+    owner.readFields(in);
+    renewer.readFields(in);
+    issueDate = WritableUtils.readVLong(in);
+    maxDate = WritableUtils.readVLong(in);
+    sequenceNumber = WritableUtils.readVInt(in);
+    masterKeyId = WritableUtils.readVInt(in);
+  }
+
+  public void write(DataOutput out) throws IOException {
+    owner.write(out);
+    renewer.write(out);
+    WritableUtils.writeVLong(out, issueDate);
+    WritableUtils.writeVLong(out, maxDate);
+    WritableUtils.writeVInt(out, sequenceNumber);
+    WritableUtils.writeVInt(out, masterKeyId);
+  }
+}

Added: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java?rev=903379&view=auto
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java (added)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java Tue Jan 26 19:34:06 2010
@@ -0,0 +1,352 @@
+/**
+ * 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.hdfs.security.token;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.crypto.SecretKey;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.SecretManager;
+import org.apache.hadoop.util.Daemon;
+import org.apache.hadoop.util.StringUtils;
+
+public class DelegationTokenSecretManager 
+   extends SecretManager<DelegationTokenIdentifier> {
+  private static final Log LOG = LogFactory
+      .getLog(DelegationTokenSecretManager.class);
+
+  /** 
+   * Cache of currently valid tokens, mapping from DelegationTokenIdentifier 
+   * to DelegationTokenInformation. Protected by its own lock.
+   */
+  private final Map<DelegationTokenIdentifier, DelegationTokenInformation> currentTokens 
+      = new HashMap<DelegationTokenIdentifier, DelegationTokenInformation>();
+  
+  /**
+   * Sequence number to create DelegationTokenIdentifier
+   */
+  private int delegationTokenSequenceNumber = 0;
+  
+  private final Map<Integer, DelegationKey> allKeys 
+      = new HashMap<Integer, DelegationKey>();
+  
+  /**
+   * Access to currentId and currentKey is protected by this object lock.
+   */
+  private int currentId = 0;
+  private DelegationKey currentKey;
+  
+  private long keyUpdateInterval;
+  private long tokenMaxLifetime;
+  private long tokenRemoverScanInterval;
+  private long tokenRenewInterval;
+  private Thread tokenRemoverThread;
+  private volatile boolean running;
+  
+
+  public DelegationTokenSecretManager(long delegationKeyUpdateInterval,
+      long delegationTokenMaxLifetime, long delegationTokenRenewInterval,
+      long delegationTokenRemoverScanInterval) {
+    this.keyUpdateInterval = delegationKeyUpdateInterval;
+    this.tokenMaxLifetime = delegationTokenMaxLifetime;
+    this.tokenRenewInterval = delegationTokenRenewInterval;
+    this.tokenRemoverScanInterval = delegationTokenRemoverScanInterval;
+  }
+  
+  /** should be called before this object is used */
+  public synchronized void startThreads() throws IOException {
+    updateCurrentKey();
+    running = true;
+    tokenRemoverThread = new Daemon(new ExpiredTokenRemover());
+    tokenRemoverThread.start();
+  }
+  
+  /** 
+   * Add a previously used master key to cache (when NN restarts), 
+   * should be called before activate().
+   * */
+  public synchronized void addKey(DelegationKey key) throws IOException {
+    if (running) // a safety check
+      throw new IOException("Can't add delegation key to a running SecretManager.");
+    if (key.getKeyId() > currentId) {
+      currentId = key.getKeyId();
+    }
+    allKeys.put(key.getKeyId(), key);
+  }
+
+  public synchronized DelegationKey[] getAllKeys() {
+    return allKeys.values().toArray(new DelegationKey[0]);
+  }
+  
+  /** Update the current master key */
+  private synchronized void updateCurrentKey() throws IOException {
+    LOG.info("Updating the current master key for generating delegation tokens");
+    /* Create a new currentKey with an estimated expiry date. */
+    currentId++;
+    currentKey = new DelegationKey(currentId, System.currentTimeMillis()
+        + keyUpdateInterval + tokenMaxLifetime, generateSecret());
+    allKeys.put(currentKey.getKeyId(), currentKey);
+  }
+  
+  /** Update the current master key for generating delegation tokens */
+  public synchronized void rollMasterKey() throws IOException {
+    removeExpiredKeys();
+    /* set final expiry date for retiring currentKey */
+    currentKey.setExpiryDate(System.currentTimeMillis() + tokenMaxLifetime);
+    /*
+     * currentKey might have been removed by removeExpiredKeys(), if
+     * updateMasterKey() isn't called at expected interval. Add it back to
+     * allKeys just in case.
+     */
+    allKeys.put(currentKey.getKeyId(), currentKey);
+    updateCurrentKey();
+  }
+
+  private synchronized void removeExpiredKeys() {
+    long now = System.currentTimeMillis();
+    for (Iterator<Map.Entry<Integer, DelegationKey>> it = allKeys.entrySet()
+        .iterator(); it.hasNext();) {
+      Map.Entry<Integer, DelegationKey> e = it.next();
+      if (e.getValue().getExpiryDate() < now) {
+        it.remove();
+      }
+    }
+  }
+  
+  @Override
+  protected byte[] createPassword(DelegationTokenIdentifier identifier) {
+    int sequenceNum;
+    int id;
+    DelegationKey key;
+    long now = System.currentTimeMillis();    
+    synchronized (this) {
+      id = currentId;
+      key = currentKey;
+      sequenceNum = ++delegationTokenSequenceNumber;
+    }
+    identifier.setIssueDate(now);
+    identifier.setMaxDate(now + tokenMaxLifetime);
+    identifier.setMasterKeyId(id);
+    identifier.setSequenceNumber(sequenceNum);
+    byte[] password = createPassword(identifier.getBytes(), key.getKey());
+    synchronized (currentTokens) {
+      currentTokens.put(identifier, new DelegationTokenInformation(now
+          + tokenRenewInterval, password));
+    }
+    return password;
+  }
+
+  @Override
+  public byte[] retrievePassword(DelegationTokenIdentifier identifier
+                                 ) throws InvalidToken {
+    DelegationTokenInformation info = null;
+    synchronized (currentTokens) {
+      info = currentTokens.get(identifier);
+    }
+    if (info == null) {
+      throw new InvalidToken("token is expired or doesn't exist");
+    }
+    long now = System.currentTimeMillis();
+    if (info.getRenewDate() < now) {
+      throw new InvalidToken("token is expired");
+    }
+    return info.getPassword();
+  }
+
+  /**
+   * Renew a delegation token. Canceled tokens are not renewed. Return true if
+   * the token is successfully renewed; false otherwise.
+   */
+  public Boolean renewToken(Token<DelegationTokenIdentifier> token,
+      String renewer) throws InvalidToken, IOException {
+    long now = System.currentTimeMillis();
+    ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier());
+    DataInputStream in = new DataInputStream(buf);
+    DelegationTokenIdentifier id = new DelegationTokenIdentifier();
+    id.readFields(in);
+    synchronized (currentTokens) {
+      if (currentTokens.get(id) == null) {
+        LOG.warn("Renewal request for unknown token");
+        return false;
+      }
+    }
+    if (id.getMaxDate() < now) {
+      LOG.warn("Client " + renewer + " tries to renew an expired token");
+      return false;
+    }
+    if (id.getRenewer() == null || !id.getRenewer().toString().equals(renewer)) {
+      LOG.warn("Client " + renewer + " tries to renew a token with "
+          + "renewer specified as " + id.getRenewer());
+      return false;
+    }
+    DelegationKey key = null;
+    synchronized (this) {
+      key = allKeys.get(id.getMasterKeyId());
+    }
+    if (key == null) {
+      LOG.warn("Unable to find master key for keyId=" + id.getMasterKeyId() 
+          + " from cache. Failed to renew an unexpired token with sequenceNumber=" 
+          + id.getSequenceNumber() + ", issued by this key");
+      return false;
+    }
+    byte[] password = createPassword(token.getIdentifier(), key.getKey());
+    if (!Arrays.equals(password, token.getPassword())) {
+      LOG.warn("Client " + renewer + " is trying to renew a token with wrong password");
+      return false;
+    }
+    DelegationTokenInformation info = new DelegationTokenInformation(
+        Math.min(id.getMaxDate(), now + tokenRenewInterval), password);
+    synchronized (currentTokens) {
+      currentTokens.put(id, info);
+    }
+    return true;
+  }
+  
+  /**
+   * Cancel a token by removing it from cache. Return true if 
+   * token exists in cache; false otherwise.
+   */
+  public Boolean cancelToken(Token<DelegationTokenIdentifier> token,
+      String canceller) throws IOException {
+    ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier());
+    DataInputStream in = new DataInputStream(buf);
+    DelegationTokenIdentifier id = new DelegationTokenIdentifier();
+    id.readFields(in);
+    if (id.getRenewer() == null) {
+      LOG.warn("Renewer is null: Invalid Identifier");
+      return false;
+    }
+    if (id.getUsername() == null) {
+      LOG.warn("owner is null: Invalid Identifier");
+      return false;
+    }
+    String owner = id.getUsername().toString();
+    String renewer = id.getRenewer().toString();
+    if (!canceller.equals(owner) && !canceller.equals(renewer)) {
+      LOG.warn(canceller + " is not authorized to cancel the token");
+      return false;
+    }
+    DelegationTokenInformation info = null;
+    synchronized (currentTokens) {
+      info = currentTokens.remove(id);
+    }
+    return info != null;
+  }
+  
+  /**
+   * Convert the byte[] to a secret key
+   * @param key the byte[] to create the secret key from
+   * @return the secret key
+   */
+  public static SecretKey createSecretKey(byte[] key) {
+    return SecretManager.createSecretKey(key);
+  }
+
+
+  /** Utility class to encapsulate a token's renew date and password. */
+  private static class DelegationTokenInformation {
+    long renewDate;
+    byte[] password;
+    DelegationTokenInformation(long renewDate, byte[] password) {
+      this.renewDate = renewDate;
+      this.password = password;
+    }
+    /** returns renew date */
+    long getRenewDate() {
+      return renewDate;
+    }
+    /** returns password */
+    byte[] getPassword() {
+      return password;
+    }
+  }
+  
+  /** Remove expired delegation tokens from cache */
+  private void removeExpiredToken() {
+    long now = System.currentTimeMillis();
+    synchronized (currentTokens) {
+      Iterator<DelegationTokenInformation> i = currentTokens.values().iterator();
+      while (i.hasNext()) {
+        long renewDate = i.next().getRenewDate();
+        if (now > renewDate) {
+          i.remove();
+        }
+      }
+    }
+  }
+
+  public synchronized void stopThreads() {
+    if (LOG.isDebugEnabled())
+      LOG.debug("Stopping expired delegation token remover thread");
+    running = false;
+    tokenRemoverThread.interrupt();
+    try {
+      tokenRemoverThread.join();
+    } catch (InterruptedException e) {
+    }
+  }
+  
+  private class ExpiredTokenRemover extends Thread {
+    private long lastMasterKeyUpdate;
+    private long lastTokenCacheCleanup;
+
+    public void run() {
+      LOG.info("Starting expired delegation token remover thread, "
+          + "tokenRemoverScanInterval=" + tokenRemoverScanInterval
+          / (60 * 1000) + " min(s)");
+      try {
+        while (running) {
+          long now = System.currentTimeMillis();
+          if (lastMasterKeyUpdate + keyUpdateInterval < now) {
+            try {
+              rollMasterKey();
+              lastMasterKeyUpdate = now;
+            } catch (IOException e) {
+              LOG.error("Master key updating failed. "
+                  + StringUtils.stringifyException(e));
+            }
+          }
+          if (lastTokenCacheCleanup + tokenRemoverScanInterval < now) {
+            removeExpiredToken();
+            lastTokenCacheCleanup = now;
+          }
+          Thread.sleep(5000); // 5 seconds
+        }
+      } catch (InterruptedException ie) {
+        LOG
+            .error("InterruptedExcpetion recieved for ExpiredTokenRemover thread "
+                + ie);
+      } catch (Throwable t) {
+        LOG.error("ExpiredTokenRemover thread received unexpected exception. "
+            + t);
+        Runtime.getRuntime().exit(-1);
+      }
+    }
+  }
+}

Modified: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java (original)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java Tue Jan 26 19:34:06 2010
@@ -36,6 +36,10 @@
 import org.apache.hadoop.security.PermissionChecker;
 import org.apache.hadoop.security.UnixUserGroupInformation;
 import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenIdentifier;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenSecretManager;
 import org.apache.hadoop.util.*;
 import org.apache.hadoop.metrics.util.MBeanUtil;
 import org.apache.hadoop.net.CachedDNSToSwitchMapping;
@@ -68,6 +72,7 @@
 import org.apache.hadoop.fs.permission.*;
 import org.apache.hadoop.ipc.Server;
 import org.apache.hadoop.io.IOUtils;
+import org.apache.hadoop.io.Text;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -145,6 +150,10 @@
   AccessTokenHandler accessTokenHandler;
   private long accessKeyUpdateInterval;
   private long accessTokenLifetime;
+  
+  // Scan interval is not configurable.
+  private final long DELEGATION_TOKEN_REMOVER_SCAN_INTERVAL = 3600000; // 1 hour
+  private DelegationTokenSecretManager dtSecretManager;
 
   //
   // Stores the correct file name hierarchy
@@ -256,6 +265,7 @@
     this.systemStart = now();
     this.blockManager = new BlockManager(this, conf);
     setConfigurationParameters(conf);
+    dtSecretManager = createDelegationTokenSecretManager(conf);
     this.registerMBean(conf); // register the MBean for the FSNamesystemStutus
     if(fsImage == null) {
       this.dir = new FSDirectory(this, conf);
@@ -276,6 +286,7 @@
       accessTokenHandler = new AccessTokenHandler(true,
           accessKeyUpdateInterval, accessTokenLifetime);
     }
+    dtSecretManager.startThreads();
   }
 
   /**
@@ -4309,5 +4320,47 @@
       }
     }
     return decommissioningNodes;
-  }  
+  }
+
+  /*
+   * Delegation Token
+   */
+   
+  private DelegationTokenSecretManager createDelegationTokenSecretManager(
+      Configuration conf) {
+    return new DelegationTokenSecretManager(conf.getLong(
+        DFSConfigKeys.DFS_NAMENODE_DELEGATION_KEY_UPDATE_INTERVAL_KEY,
+        DFSConfigKeys.DFS_NAMENODE_DELEGATION_KEY_UPDATE_INTERVAL_DEFAULT),
+        conf.getLong(
+            DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_MAX_LIFETIME_KEY,
+            DFSConfigKeys.DFS_NAMENODE_DELEGATION_KEY_UPDATE_INTERVAL_DEFAULT),
+        conf.getLong(
+            DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_RENEW_INTERVAL_KEY,
+            DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_MAX_LIFETIME_DEFAULT),
+        DELEGATION_TOKEN_REMOVER_SCAN_INTERVAL);
+  }
+
+  public DelegationTokenSecretManager getDelegationTokenSecretManager() {
+    return dtSecretManager;
+  }
+
+  public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer)
+      throws IOException {
+    String user = UserGroupInformation.getCurrentUGI().getUserName();
+    Text owner = new Text(user);
+    DelegationTokenIdentifier dtId = new DelegationTokenIdentifier(owner, renewer);
+    return new Token<DelegationTokenIdentifier>(dtId, dtSecretManager);
+  }
+
+  public Boolean renewDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws InvalidToken, IOException {
+    String renewer = UserGroupInformation.getCurrentUGI().getUserName();
+    return dtSecretManager.renewToken(token, renewer);
+  }
+
+  public Boolean cancelDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws IOException {
+    String canceller = UserGroupInformation.getCurrentUGI().getUserName();
+    return dtSecretManager.cancelToken(token, canceller);
+  }
 }

Modified: hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java (original)
+++ hadoop/hdfs/trunk/src/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java Tue Jan 26 19:34:06 2010
@@ -71,6 +71,7 @@
 import org.apache.hadoop.hdfs.HdfsConfiguration;
 import org.apache.hadoop.http.HttpServer;
 import org.apache.hadoop.io.EnumSetWritable;
+import org.apache.hadoop.io.Text;
 import org.apache.hadoop.ipc.RPC;
 import org.apache.hadoop.ipc.Server;
 import org.apache.hadoop.net.NetUtils;
@@ -84,6 +85,9 @@
 import org.apache.hadoop.security.authorize.PolicyProvider;
 import org.apache.hadoop.security.authorize.RefreshAuthorizationPolicyProtocol;
 import org.apache.hadoop.security.authorize.ServiceAuthorizationManager;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenIdentifier;
 import org.apache.hadoop.util.ReflectionUtils;
 import org.apache.hadoop.util.ServicePlugin;
 import org.apache.hadoop.util.StringUtils;
@@ -547,6 +551,22 @@
   /////////////////////////////////////////////////////
   // ClientProtocol
   /////////////////////////////////////////////////////
+  
+  public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer)
+      throws IOException {
+    return namesystem.getDelegationToken(renewer);
+  }
+
+  public Boolean renewDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws InvalidToken, IOException {
+    return namesystem.renewDelegationToken(token);
+  }
+
+  public Boolean cancelDelegationToken(Token<DelegationTokenIdentifier> token)
+      throws IOException {
+    return namesystem.cancelDelegationToken(token);
+  }
+  
   /** {@inheritDoc} */
   public LocatedBlocks   getBlockLocations(String src, 
                                           long offset, 

Modified: hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/TestDFSClientRetries.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/TestDFSClientRetries.java?rev=903379&r1=903378&r2=903379&view=diff
==============================================================================
--- hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/TestDFSClientRetries.java (original)
+++ hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/hdfs/TestDFSClientRetries.java Tue Jan 26 19:34:06 2010
@@ -31,11 +31,15 @@
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.hdfs.protocol.*;
 import org.apache.hadoop.hdfs.protocol.FSConstants.UpgradeAction;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenIdentifier;
 import org.apache.hadoop.hdfs.server.common.*;
 import org.apache.hadoop.hdfs.server.namenode.NotReplicatedYetException;
 import org.apache.hadoop.io.*;
 import org.apache.hadoop.ipc.RemoteException;
 import org.apache.hadoop.security.AccessControlException;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
 
 import junit.framework.TestCase;
 
@@ -185,6 +189,22 @@
 
     public void reportBadBlocks(LocatedBlock[] blocks) throws IOException {}
 
+    public Token<DelegationTokenIdentifier> getDelegationToken(Text renewer)
+        throws IOException {
+      return null;
+    }
+    
+    public Boolean renewDelegationToken(Token<DelegationTokenIdentifier> token)
+        throws InvalidToken, IOException {
+      return false;
+    }
+
+    public Boolean cancelDelegationToken(Token<DelegationTokenIdentifier> token)
+        throws IOException {
+      return false;
+    }
+    
+    
     @Deprecated
     public boolean rename(String src, String dst) throws IOException { return false; }
     

Added: hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/security/TestDelegationToken.java
URL: http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/security/TestDelegationToken.java?rev=903379&view=auto
==============================================================================
--- hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/security/TestDelegationToken.java (added)
+++ hadoop/hdfs/trunk/src/test/hdfs/org/apache/hadoop/security/TestDelegationToken.java Tue Jan 26 19:34:06 2010
@@ -0,0 +1,130 @@
+/**
+ * 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;
+
+
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+
+import junit.framework.Assert;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.hdfs.DFSConfigKeys;
+import org.apache.hadoop.hdfs.DistributedFileSystem;
+import org.apache.hadoop.hdfs.HdfsConfiguration;
+import org.apache.hadoop.hdfs.MiniDFSCluster;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenIdentifier;
+import org.apache.hadoop.hdfs.security.token.DelegationTokenSecretManager;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mortbay.log.Log;
+
+public class TestDelegationToken {
+  private MiniDFSCluster cluster;
+  Configuration config;
+  
+  @Before
+  public void setUp() throws Exception {
+    config = new HdfsConfiguration();
+    config.setLong(DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_MAX_LIFETIME_KEY, 10000);
+    config.setLong(DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_RENEW_INTERVAL_KEY, 5000);
+    FileSystem.setDefaultUri(config, "hdfs://localhost:" + "0");
+    cluster = new MiniDFSCluster(0, config, 1, true, true, true,  null, null, null, null);
+    cluster.waitActive();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if(cluster!=null) {
+      cluster.shutdown();
+    }
+  }
+
+  private Token<DelegationTokenIdentifier> generateDelegationToken(
+      String owner, String renewer) {
+    DelegationTokenSecretManager dtSecretManager = cluster.getNamesystem()
+        .getDelegationTokenSecretManager();
+    DelegationTokenIdentifier dtId = new DelegationTokenIdentifier(new Text(
+        owner), new Text(renewer));
+    return new Token<DelegationTokenIdentifier>(dtId, dtSecretManager);
+  }
+  
+  @Test
+  public void testDelegationTokenSecretManager() throws Exception {
+    DelegationTokenSecretManager dtSecretManager = cluster.getNamesystem()
+        .getDelegationTokenSecretManager();
+    Token<DelegationTokenIdentifier> token = generateDelegationToken(
+        "SomeUser", "JobTracker");
+    // Fake renewer should not be able to renew
+	  Assert.assertFalse(dtSecretManager.renewToken(token, "FakeRenewer"));
+	  Assert.assertTrue(dtSecretManager.renewToken(token, "JobTracker"));
+    DelegationTokenIdentifier identifier = new DelegationTokenIdentifier();
+    byte[] tokenId = token.getIdentifier();
+    identifier.readFields(new DataInputStream(
+             new ByteArrayInputStream(tokenId)));
+    Assert.assertTrue(null != dtSecretManager.retrievePassword(identifier));
+    Log.info("Sleep to expire the token");
+	  Thread.sleep(6000);
+	  //Token should be expired
+	  try {
+	    dtSecretManager.retrievePassword(identifier);
+	    //Should not come here
+	    Assert.fail("Token should have expired");
+	  } catch (InvalidToken e) {
+	    //Success
+	  }
+	  Assert.assertTrue(dtSecretManager.renewToken(token, "JobTracker"));
+	  Log.info("Sleep beyond the max lifetime");
+	  Thread.sleep(5000);
+	  Assert.assertFalse(dtSecretManager.renewToken(token, "JobTracker"));
+  }
+  
+  @Test 
+  public void testCancelDelegationToken() throws Exception {
+    DelegationTokenSecretManager dtSecretManager = cluster.getNamesystem()
+        .getDelegationTokenSecretManager();
+    Token<DelegationTokenIdentifier> token = generateDelegationToken(
+        "SomeUser", "JobTracker");
+    //Fake renewer should not be able to renew
+    Assert.assertFalse(dtSecretManager.cancelToken(token, "FakeCanceller"));
+    Assert.assertTrue(dtSecretManager.cancelToken(token, "JobTracker"));
+    Assert.assertFalse(dtSecretManager.renewToken(token, "JobTracker"));
+  }
+  
+  @Test
+  public void testDelegationTokenDFSApi() throws Exception {
+    DelegationTokenSecretManager dtSecretManager = cluster.getNamesystem().getDelegationTokenSecretManager();
+    DistributedFileSystem dfs = (DistributedFileSystem) cluster.getFileSystem();
+    Token<DelegationTokenIdentifier> token = dfs.getDelegationToken(new Text("JobTracker"));
+    DelegationTokenIdentifier identifier = new DelegationTokenIdentifier();
+    byte[] tokenId = token.getIdentifier();
+    identifier.readFields(new DataInputStream(
+             new ByteArrayInputStream(tokenId)));
+    Log.info("A valid token should have non-null password, and should be renewed successfully");
+    Assert.assertTrue(null != dtSecretManager.retrievePassword(identifier));
+    Assert.assertTrue(dtSecretManager.renewToken(token, "JobTracker"));
+  }
+  
+}