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 om...@apache.org on 2011/03/04 04:43:51 UTC
svn commit: r1077128 - in
/hadoop/common/branches/branch-0.20-security-patches/src: hdfs/
hdfs/org/apache/hadoop/hdfs/ hdfs/org/apache/hadoop/hdfs/protocol/
hdfs/org/apache/hadoop/hdfs/security/token/
hdfs/org/apache/hadoop/hdfs/server/namenode/ test/o...
Author: omalley
Date: Fri Mar 4 03:43:51 2011
New Revision: 1077128
URL: http://svn.apache.org/viewvc?rev=1077128&view=rev
Log:
commit 3ce2f82e3b4391b5f96c9915d98e40b365ecd9a2
Author: Jitendra Nath Pandey <ji...@yahoo-inc.com>
Date: Tue Jan 26 23:40:06 2010 -0800
HDFS-899 from https://issues.apache.org/jira/secure/attachment/12431529/HDFS-899-0_20.2.patch
+++ b/YAHOO-CHANGES.txt
+ HDFS-899. Delegation Token Implementation. (Jitendra Nath Pandey)
+
Added:
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationKey.java
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java
hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/security/TestDelegationToken.java
Modified:
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/hdfs-default.xml
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DFSClient.java
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DistributedFileSystem.java
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/protocol/ClientProtocol.java
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/NameNode.java
hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/hdfs/TestDFSClientRetries.java
Modified: hadoop/common/branches/branch-0.20-security-patches/src/hdfs/hdfs-default.xml
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/hdfs-default.xml?rev=1077128&r1=1077127&r2=1077128&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/hdfs-default.xml (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/hdfs-default.xml Fri Mar 4 03:43:51 2011
@@ -386,4 +386,26 @@ creations/deletions), or "all".</descrip
</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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DFSClient.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DFSClient.java?rev=1077128&r1=1077127&r2=1077128&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DFSClient.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DFSClient.java Fri Mar 4 03:43:51 2011
@@ -31,6 +31,7 @@ import org.apache.hadoop.hdfs.Distribute
import org.apache.hadoop.hdfs.protocol.*;
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;
@@ -38,6 +39,10 @@ import org.apache.hadoop.hdfs.server.nam
import org.apache.hadoop.hdfs.server.namenode.NotReplicatedYetException;
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.*;
import org.apache.commons.logging.*;
@@ -262,6 +267,25 @@ public class DFSClient implements FSCons
}
}
+ 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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DistributedFileSystem.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DistributedFileSystem.java?rev=1077128&r1=1077127&r2=1077128&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DistributedFileSystem.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/DistributedFileSystem.java Fri Mar 4 03:43:51 2011
@@ -30,10 +30,15 @@ import org.apache.hadoop.hdfs.protocol.B
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.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;
@@ -484,5 +489,44 @@ public class DistributedFileSystem exten
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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/protocol/ClientProtocol.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/protocol/ClientProtocol.java?rev=1077128&r1=1077127&r2=1077128&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/protocol/ClientProtocol.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/protocol/ClientProtocol.java Fri Mar 4 03:43:51 2011
@@ -22,10 +22,13 @@ import java.io.*;
import org.apache.hadoop.ipc.VersionedProtocol;
import org.apache.hadoop.security.AccessControlException;
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.fs.permission.*;
import org.apache.hadoop.fs.ContentSummary;
import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.security.token.Token;
/**********************************************************************
* ClientProtocol is used by user code via
@@ -40,9 +43,9 @@ public interface ClientProtocol extends
* 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).
- * 42: All LocatedBlock objects contain access tokens
+ * 43: Adding Delegation Token related APIs
*/
- public static final long versionID = 42L;
+ public static final long versionID = 43L;
///////////////////////////////////////
// File contents
@@ -474,4 +477,33 @@ public interface ClientProtocol extends
* by this call.
*/
public void setTimes(String src, long mtime, long atime) 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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationKey.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationKey.java?rev=1077128&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationKey.java (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationKey.java Fri Mar 4 03:43:51 2011
@@ -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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java?rev=1077128&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenIdentifier.java Fri Mar 4 03:43:51 2011
@@ -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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java?rev=1077128&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/security/token/DelegationTokenSecretManager.java Fri Mar 4 03:43:51 2011
@@ -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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java?rev=1077128&r1=1077127&r2=1077128&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java Fri Mar 4 03:43:51 2011
@@ -35,6 +35,10 @@ import org.apache.hadoop.hdfs.security.E
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;
@@ -57,6 +61,7 @@ import org.apache.hadoop.fs.Path;
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;
@@ -137,6 +142,10 @@ public class FSNamesystem implements FSC
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;
volatile long pendingReplicationBlocksCount = 0L;
volatile long corruptReplicaBlocksCount = 0L;
@@ -303,6 +312,7 @@ public class FSNamesystem implements FSC
close();
throw e;
}
+ dtSecretManager.startThreads();
}
/**
@@ -311,6 +321,7 @@ public class FSNamesystem implements FSC
private void initialize(NameNode nn, Configuration conf) throws IOException {
this.systemStart = now();
setConfigurationParameters(conf);
+ dtSecretManager = createDelegationTokenSecretManager(conf);
this.nameNodeAddress = nn.getNameNodeAddress();
this.registerMBean(conf); // register the MBean for the FSNamesystemStutus
@@ -4875,4 +4886,43 @@ public class FSNamesystem implements FSC
}
return decommissioningNodes;
}
+
+ /*
+ * Delegation Token
+ */
+
+ private DelegationTokenSecretManager createDelegationTokenSecretManager(
+ Configuration conf) {
+ return new DelegationTokenSecretManager(conf.getLong(
+ "dfs.namenode.delegation.key.update-interval", 86400),
+ conf.getLong(
+ "dfs.namenode.delegation.token.max-lifetime", 604800),
+ conf.getLong(
+ "dfs.namenode.delegation.token.renew-interval", 86400),
+ 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/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/NameNode.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/NameNode.java?rev=1077128&r1=1077127&r2=1077128&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/NameNode.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/hdfs/org/apache/hadoop/hdfs/server/namenode/NameNode.java Fri Mar 4 03:43:51 2011
@@ -42,6 +42,7 @@ import org.apache.hadoop.hdfs.server.pro
import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
import org.apache.hadoop.hdfs.server.protocol.UpgradeCommand;
import org.apache.hadoop.http.HttpServer;
+import org.apache.hadoop.io.Text;
import org.apache.hadoop.ipc.*;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.util.ReflectionUtils;
@@ -57,6 +58,9 @@ import org.apache.hadoop.security.author
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 java.io.*;
import java.net.*;
@@ -346,6 +350,22 @@ public class NameNode implements ClientP
/////////////////////////////////////////////////////
// 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/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/hdfs/TestDFSClientRetries.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/hdfs/TestDFSClientRetries.java?rev=1077128&r1=1077127&r2=1077128&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/hdfs/TestDFSClientRetries.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/hdfs/TestDFSClientRetries.java Fri Mar 4 03:43:51 2011
@@ -28,11 +28,15 @@ import org.apache.hadoop.fs.*;
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;
@@ -213,6 +217,20 @@ public class TestDFSClientRetries extend
public void setTimes(String src, long mtime, long atime) 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;
+ }
}
public void testNotYetReplicatedErrors() throws IOException
Added: hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/security/TestDelegationToken.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/security/TestDelegationToken.java?rev=1077128&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/security/TestDelegationToken.java (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/security/TestDelegationToken.java Fri Mar 4 03:43:51 2011
@@ -0,0 +1,131 @@
+/**
+ * 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.DistributedFileSystem;
+import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
+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;
+ FSNamesystem nameSystem;
+ Configuration config;
+
+ @Before
+ public void setUp() throws Exception {
+ config = new Configuration();
+ config.setLong("dfs.namenode.delegation.token.max-lifetime", 10000);
+ config.setLong("dfs.namenode.delegation.token.renew-interval", 5000);
+ FileSystem.setDefaultUri(config, "hdfs://localhost:" + "0");
+ cluster = new MiniDFSCluster(0, config, 1, true, true, true, null, null, null, null);
+ cluster.waitActive();
+ nameSystem = cluster.getNameNode().namesystem;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if(cluster!=null) {
+ cluster.shutdown();
+ }
+ }
+
+ private Token<DelegationTokenIdentifier> generateDelegationToken(
+ String owner, String renewer) {
+ DelegationTokenSecretManager dtSecretManager =
+ nameSystem.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 =
+ nameSystem.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 =
+ nameSystem.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 = nameSystem.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"));
+ }
+
+}