Skip to content

Commit 0feba43

Browse files
committed
HDFS-14305. Fix serial number calculation in BlockTokenSecretManager to avoid token key ID overlap between NameNodes. Contributed by He Xiaoqiao.
1 parent 3a8118b commit 0feba43

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/security/token/block/BlockTokenSecretManager.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ public class BlockTokenSecretManager extends
6363

6464
public static final Token<BlockTokenIdentifier> DUMMY_TOKEN = new Token<BlockTokenIdentifier>();
6565

66+
/**
67+
* In order to prevent serial No. of different NameNode from overlapping,
68+
* Using 6 bits (identify 64=2^6 namenodes, and presuppose that no scenario
69+
* where deploy more than 64 namenodes (include ANN, SBN, Observers, etc.)
70+
* in one namespace) to identify index of NameNode, and the remainder 26 bits
71+
* auto-incr to change the serial No.
72+
*/
73+
@VisibleForTesting
74+
public static final int NUM_VALID_BITS = 26;
75+
private static final int LOW_MASK = (1 << NUM_VALID_BITS) - 1;
76+
6677
private final boolean isMaster;
6778

6879
/**
@@ -79,8 +90,8 @@ public class BlockTokenSecretManager extends
7990
private String blockPoolId;
8091
private final String encryptionAlgorithm;
8192

82-
private final int intRange;
83-
private final int nnRangeStart;
93+
private final int nnIndex;
94+
8495
private final boolean useProto;
8596

8697
private final SecureRandom nonceGenerator = new SecureRandom();
@@ -129,8 +140,7 @@ public BlockTokenSecretManager(long keyUpdateInterval,
129140
private BlockTokenSecretManager(boolean isMaster, long keyUpdateInterval,
130141
long tokenLifetime, String blockPoolId, String encryptionAlgorithm,
131142
int nnIndex, int numNNs, boolean useProto) {
132-
this.intRange = Integer.MAX_VALUE / numNNs;
133-
this.nnRangeStart = intRange * nnIndex;
143+
this.nnIndex = nnIndex;
134144
this.isMaster = isMaster;
135145
this.keyUpdateInterval = keyUpdateInterval;
136146
this.tokenLifetime = tokenLifetime;
@@ -144,8 +154,7 @@ private BlockTokenSecretManager(boolean isMaster, long keyUpdateInterval,
144154

145155
@VisibleForTesting
146156
public synchronized void setSerialNo(int serialNo) {
147-
// we mod the serial number by the range and then add that times the index
148-
this.serialNo = (serialNo % intRange) + (nnRangeStart);
157+
this.serialNo = (serialNo & LOW_MASK) | (nnIndex << NUM_VALID_BITS);
149158
}
150159

151160
public void setBlockPoolId(String blockPoolId) {

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestFailoverWithBlockTokensEnabled.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,36 @@ private void setAndCheckSerialNumber(int serialNumber, BlockTokenSecretManager..
116116
}
117117
}
118118
}
119-
119+
120+
@Test
121+
public void testSerialNumberMaskMatchIndex() {
122+
BlockTokenSecretManager btsm1 = cluster.getNamesystem(0).getBlockManager()
123+
.getBlockTokenSecretManager();
124+
BlockTokenSecretManager btsm2 = cluster.getNamesystem(1).getBlockManager()
125+
.getBlockTokenSecretManager();
126+
BlockTokenSecretManager btsm3 = cluster.getNamesystem(2).getBlockManager()
127+
.getBlockTokenSecretManager();
128+
int[] testSet = {0, Integer.MAX_VALUE, Integer.MIN_VALUE,
129+
Integer.MAX_VALUE / 2, Integer.MIN_VALUE / 2,
130+
Integer.MAX_VALUE / 3, Integer.MIN_VALUE / 3};
131+
for (int i = 0; i < testSet.length; i++) {
132+
setAndCheckHighBitsSerialNumber(testSet[i], btsm1, 0);
133+
setAndCheckHighBitsSerialNumber(testSet[i], btsm2, 1);
134+
setAndCheckHighBitsSerialNumber(testSet[i], btsm3, 2);
135+
}
136+
}
137+
138+
/**
139+
* Check mask of serial number if equal to index of NameNode.
140+
*/
141+
private void setAndCheckHighBitsSerialNumber(int serialNumber,
142+
BlockTokenSecretManager btsm, int nnIndex) {
143+
btsm.setSerialNo(serialNumber);
144+
int serialNo = btsm.getSerialNoForTesting();
145+
int index = serialNo >> BlockTokenSecretManager.NUM_VALID_BITS;
146+
assertEquals(index, nnIndex);
147+
}
148+
120149
@Test
121150
public void ensureInvalidBlockTokensAreRejected() throws IOException,
122151
URISyntaxException {

0 commit comments

Comments
 (0)