This is an automated email from the ASF dual-hosted git repository.

swagle pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 355096b  HDDS-5236. Require block token for more operations (#2254)
355096b is described below

commit 355096b9c218a90d01307b7b8782c469300b94bf
Author: Doroszlai, Attila <[email protected]>
AuthorDate: Mon May 24 22:49:25 2021 +0200

    HDDS-5236. Require block token for more operations (#2254)
    
    * Require block token for all chunk/block operations
    
    * Addendum: implement getBlockID; add tests
    
    * No block token for ListBlock (unsupported operation anyway), as it has no 
block ID
    
    * Test for more block/chunk operations
    
    * Require container token for ListBlock, but not for ListContainer
    
    * Do not require...Token for unsupported operations
---
 .../java/org/apache/hadoop/hdds/HddsUtils.java     |  82 +++++++++++------
 .../ozone/container/ContainerTestHelper.java       | 101 ++++++++++++++++-----
 .../hdds/security/token/BlockTokenVerifier.java    |  39 ++++----
 .../security/token/CompositeTokenVerifier.java     |   4 +-
 .../security/token/ContainerTokenVerifier.java     |   4 +-
 .../hdds/security/token/NoopTokenVerifier.java     |   6 +-
 .../security/token/ShortLivedTokenVerifier.java    |   9 +-
 .../hadoop/hdds/security/token/TokenVerifier.java  |  11 ++-
 .../server/TestSecureContainerServer.java          |  71 +++++++++++----
 9 files changed, 219 insertions(+), 108 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java
index e03e928..6e701d5 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsUtils.java
@@ -41,7 +41,7 @@ import org.apache.hadoop.hdds.client.BlockID;
 import org.apache.hadoop.hdds.conf.ConfigurationException;
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProtoOrBuilder;
 import org.apache.hadoop.hdds.scm.ScmConfigKeys;
 import org.apache.hadoop.hdds.scm.ha.SCMHAUtils;
 import org.apache.hadoop.hdds.scm.ha.SCMNodeInfo;
@@ -354,7 +354,7 @@ public final class HddsUtils {
    * @return True if its readOnly , false otherwise.
    */
   public static boolean isReadOnly(
-      ContainerProtos.ContainerCommandRequestProto proto) {
+      ContainerCommandRequestProtoOrBuilder proto) {
     switch (proto.getCmdType()) {
     case ReadContainer:
     case ReadChunk:
@@ -394,12 +394,15 @@ public final class HddsUtils {
   public static boolean requireBlockToken(
       ContainerProtos.Type cmdType) {
     switch (cmdType) {
-    case ReadChunk:
+    case DeleteBlock:
+    case DeleteChunk:
     case GetBlock:
-    case WriteChunk:
+    case GetCommittedBlockLength:
+    case GetSmallFile:
     case PutBlock:
     case PutSmallFile:
-    case GetSmallFile:
+    case ReadChunk:
+    case WriteChunk:
       return true;
     default:
       return false;
@@ -412,7 +415,6 @@ public final class HddsUtils {
     case CloseContainer:
     case CreateContainer:
     case DeleteContainer:
-    case ListContainer:
     case ReadContainer:
     case UpdateContainer:
       return true;
@@ -426,44 +428,66 @@ public final class HddsUtils {
    * @param msg container command
    * @return block ID.
    */
-  public static BlockID getBlockID(ContainerCommandRequestProto msg) {
+  public static BlockID getBlockID(ContainerCommandRequestProtoOrBuilder msg) {
+    ContainerProtos.DatanodeBlockID blockID = null;
     switch (msg.getCmdType()) {
-    case ReadChunk:
-      if (msg.hasReadChunk()) {
-        return BlockID.getFromProtobuf(msg.getReadChunk().getBlockID());
+    case DeleteBlock:
+      if (msg.hasDeleteBlock()) {
+        blockID = msg.getDeleteBlock().getBlockID();
       }
-      return null;
+      break;
+    case DeleteChunk:
+      if (msg.hasDeleteChunk()) {
+        blockID = msg.getDeleteChunk().getBlockID();
+      }
+      break;
     case GetBlock:
       if (msg.hasGetBlock()) {
-        return BlockID.getFromProtobuf(msg.getGetBlock().getBlockID());
+        blockID = msg.getGetBlock().getBlockID();
       }
-      return null;
-    case WriteChunk:
-      if (msg.hasWriteChunk()) {
-        return BlockID.getFromProtobuf(msg.getWriteChunk().getBlockID());
+      break;
+    case GetCommittedBlockLength:
+      if (msg.hasGetCommittedBlockLength()) {
+        blockID = msg.getGetCommittedBlockLength().getBlockID();
       }
-      return null;
+      break;
+    case GetSmallFile:
+      if (msg.hasGetSmallFile()) {
+        blockID = msg.getGetSmallFile().getBlock().getBlockID();
+      }
+      break;
+    case ListChunk:
+      if (msg.hasListChunk()) {
+        blockID = msg.getListChunk().getBlockID();
+      }
+      break;
     case PutBlock:
       if (msg.hasPutBlock()) {
-        return BlockID.getFromProtobuf(msg.getPutBlock().getBlockData()
-            .getBlockID());
+        blockID = msg.getPutBlock().getBlockData().getBlockID();
       }
-      return null;
+      break;
     case PutSmallFile:
       if (msg.hasPutSmallFile()) {
-        return BlockID.getFromProtobuf(msg.getPutSmallFile().getBlock()
-            .getBlockData().getBlockID());
+        blockID = msg.getPutSmallFile().getBlock().getBlockData().getBlockID();
       }
-      return null;
-    case GetSmallFile:
-      if (msg.hasGetSmallFile()) {
-        return BlockID.getFromProtobuf(msg.getGetSmallFile().getBlock()
-            .getBlockID());
+      break;
+    case ReadChunk:
+      if (msg.hasReadChunk()) {
+        blockID = msg.getReadChunk().getBlockID();
       }
-      return null;
+      break;
+    case WriteChunk:
+      if (msg.hasWriteChunk()) {
+        blockID = msg.getWriteChunk().getBlockID();
+      }
+      break;
     default:
-      return null;
+      break;
     }
+
+    return blockID != null
+        ? BlockID.getFromProtobuf(blockID)
+        : null;
   }
 
   /**
diff --git 
a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/container/ContainerTestHelper.java
 
b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/container/ContainerTestHelper.java
index 4c344ab..5e4a8dc 100644
--- 
a/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/container/ContainerTestHelper.java
+++ 
b/hadoop-hdds/common/src/test/java/org/apache/hadoop/ozone/container/ContainerTestHelper.java
@@ -33,6 +33,7 @@ import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ChecksumTy
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto.Builder;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandResponseProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.DatanodeBlockID;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.KeyValue;
 import org.apache.hadoop.hdds.scm.pipeline.MockPipeline;
 import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
@@ -135,6 +136,17 @@ public final class ContainerTestHelper {
   public static ContainerCommandRequestProto getWriteChunkRequest(
       Pipeline pipeline, BlockID blockID, int datalen, int seq, String token)
       throws IOException {
+    Builder builder = newWriteChunkRequestBuilder(pipeline, blockID, datalen,
+        seq);
+    if (!Strings.isNullOrEmpty(token)) {
+      builder.setEncodedToken(token);
+    }
+    return builder.build();
+  }
+
+  public static Builder newWriteChunkRequestBuilder(
+      Pipeline pipeline, BlockID blockID, int datalen, int seq)
+      throws IOException {
     LOG.trace("writeChunk {} (blockID={}) to pipeline={}",
         datalen, blockID, pipeline);
     ContainerProtos.WriteChunkRequestProto.Builder writeRequest =
@@ -156,11 +168,8 @@ public final class ContainerTestHelper {
     request.setContainerID(blockID.getContainerID());
     request.setWriteChunk(writeRequest);
     request.setDatanodeUuid(pipeline.getFirstNode().getUuidString());
-    if (!Strings.isNullOrEmpty(token)) {
-      request.setEncodedToken(token);
-    }
 
-    return request.build();
+    return request;
   }
 
   /**
@@ -225,19 +234,25 @@ public final class ContainerTestHelper {
    * Returns a read Request.
    *
    * @param pipeline pipeline.
-   * @param request writeChunkRequest.
+   * @param writeChunk writeChunkRequest.
    * @return Request.
    */
   public static ContainerCommandRequestProto getReadChunkRequest(
-      Pipeline pipeline, ContainerProtos.WriteChunkRequestProto request)
+      Pipeline pipeline, ContainerProtos.WriteChunkRequestProto writeChunk)
+      throws IOException {
+    return newReadChunkRequestBuilder(pipeline, writeChunk).build();
+  }
+
+  public static Builder newReadChunkRequestBuilder(Pipeline pipeline,
+      ContainerProtos.WriteChunkRequestProtoOrBuilder writeChunk)
       throws IOException {
     LOG.trace("readChunk blockID={} from pipeline={}",
-        request.getBlockID(), pipeline);
+        writeChunk.getBlockID(), pipeline);
 
     ContainerProtos.ReadChunkRequestProto.Builder readRequest =
         ContainerProtos.ReadChunkRequestProto.newBuilder();
-    readRequest.setBlockID(request.getBlockID());
-    readRequest.setChunkData(request.getChunkData());
+    readRequest.setBlockID(writeChunk.getBlockID());
+    readRequest.setChunkData(writeChunk.getChunkData());
     readRequest.setReadChunkVersion(ContainerProtos.ReadChunkVersion.V1);
 
     Builder newRequest =
@@ -246,7 +261,7 @@ public final class ContainerTestHelper {
     newRequest.setContainerID(readRequest.getBlockID().getContainerID());
     newRequest.setReadChunk(readRequest);
     newRequest.setDatanodeUuid(pipeline.getFirstNode().getUuidString());
-    return newRequest.build();
+    return newRequest;
   }
 
   /**
@@ -259,6 +274,12 @@ public final class ContainerTestHelper {
   public static ContainerCommandRequestProto getDeleteChunkRequest(
       Pipeline pipeline, ContainerProtos.WriteChunkRequestProto writeRequest)
       throws IOException {
+    return newDeleteChunkRequestBuilder(pipeline, writeRequest).build();
+  }
+
+  public static Builder newDeleteChunkRequestBuilder(Pipeline pipeline,
+      ContainerProtos.WriteChunkRequestProtoOrBuilder writeRequest)
+      throws IOException {
     LOG.trace("deleteChunk blockID={} from pipeline={}",
         writeRequest.getBlockID(), pipeline);
 
@@ -275,7 +296,7 @@ public final class ContainerTestHelper {
     request.setContainerID(writeRequest.getBlockID().getContainerID());
     request.setDeleteChunk(deleteRequest);
     request.setDatanodeUuid(pipeline.getFirstNode().getUuidString());
-    return request.build();
+    return request;
   }
 
   /**
@@ -404,8 +425,18 @@ public final class ContainerTestHelper {
       Pipeline pipeline, String token,
       ContainerProtos.WriteChunkRequestProto writeRequest)
       throws IOException {
-    LOG.trace("putBlock: {} to pipeline={} with token {}",
-        writeRequest.getBlockID(), pipeline, token);
+    Builder builder = newPutBlockRequestBuilder(pipeline, writeRequest);
+    if (!Strings.isNullOrEmpty(token)) {
+      builder.setEncodedToken(token);
+    }
+    return builder.build();
+  }
+
+  public static Builder newPutBlockRequestBuilder(Pipeline pipeline,
+      ContainerProtos.WriteChunkRequestProtoOrBuilder writeRequest)
+      throws IOException {
+    LOG.trace("putBlock: {} to pipeline={}",
+        writeRequest.getBlockID(), pipeline);
 
     ContainerProtos.PutBlockRequestProto.Builder putRequest =
         ContainerProtos.PutBlockRequestProto.newBuilder();
@@ -424,10 +455,7 @@ public final class ContainerTestHelper {
     request.setContainerID(blockData.getContainerID());
     request.setPutBlock(putRequest);
     request.setDatanodeUuid(pipeline.getFirstNode().getUuidString());
-    if (!Strings.isNullOrEmpty(token)) {
-      request.setEncodedToken(token);
-    }
-    return request.build();
+    return request;
   }
 
   /**
@@ -440,9 +468,13 @@ public final class ContainerTestHelper {
   public static ContainerCommandRequestProto getBlockRequest(
       Pipeline pipeline, ContainerProtos.PutBlockRequestProto putBlockRequest)
       throws IOException {
-    ContainerProtos.DatanodeBlockID blockID =
-        putBlockRequest.getBlockData().getBlockID();
-    LOG.trace("getKey: blockID={}", blockID);
+    return newGetBlockRequestBuilder(pipeline, putBlockRequest).build();
+  }
+
+  public static Builder newGetBlockRequestBuilder(
+      Pipeline pipeline, ContainerProtos.PutBlockRequestProtoOrBuilder 
putBlock)
+      throws IOException {
+    DatanodeBlockID blockID = putBlock.getBlockData().getBlockID();
 
     ContainerProtos.GetBlockRequestProto.Builder getRequest =
         ContainerProtos.GetBlockRequestProto.newBuilder();
@@ -454,7 +486,7 @@ public final class ContainerTestHelper {
     request.setContainerID(blockID.getContainerID());
     request.setGetBlock(getRequest);
     request.setDatanodeUuid(pipeline.getFirstNode().getUuidString());
-    return request.build();
+    return request;
   }
 
   /**
@@ -478,8 +510,13 @@ public final class ContainerTestHelper {
   public static ContainerCommandRequestProto getDeleteBlockRequest(
       Pipeline pipeline, ContainerProtos.PutBlockRequestProto putBlockRequest)
       throws IOException {
-    ContainerProtos.DatanodeBlockID blockID = putBlockRequest.getBlockData()
-        .getBlockID();
+    return newDeleteBlockRequestBuilder(pipeline, putBlockRequest).build();
+  }
+
+  public static Builder newDeleteBlockRequestBuilder(Pipeline pipeline,
+      ContainerProtos.PutBlockRequestProtoOrBuilder putBlockRequest)
+      throws IOException {
+    DatanodeBlockID blockID = putBlockRequest.getBlockData().getBlockID();
     LOG.trace("deleteBlock: name={}", blockID);
     ContainerProtos.DeleteBlockRequestProto.Builder delRequest =
         ContainerProtos.DeleteBlockRequestProto.newBuilder();
@@ -490,7 +527,23 @@ public final class ContainerTestHelper {
     request.setContainerID(blockID.getContainerID());
     request.setDeleteBlock(delRequest);
     request.setDatanodeUuid(pipeline.getFirstNode().getUuidString());
-    return request.build();
+    return request;
+  }
+
+  public static Builder newGetCommittedBlockLengthBuilder(Pipeline pipeline,
+      ContainerProtos.PutBlockRequestProtoOrBuilder putBlock)
+      throws IOException {
+    DatanodeBlockID blockID = putBlock.getBlockData().getBlockID();
+
+    ContainerProtos.GetCommittedBlockLengthRequestProto.Builder req =
+        ContainerProtos.GetCommittedBlockLengthRequestProto.newBuilder()
+            .setBlockID(blockID);
+
+    return ContainerCommandRequestProto.newBuilder()
+        .setCmdType(ContainerProtos.Type.GetCommittedBlockLength)
+        .setContainerID(blockID.getContainerID())
+        .setDatanodeUuid(pipeline.getFirstNode().getUuidString())
+        .setGetCommittedBlockLength(req);
   }
 
   /**
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/BlockTokenVerifier.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/BlockTokenVerifier.java
index a43cd2c..092a059 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/BlockTokenVerifier.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/BlockTokenVerifier.java
@@ -23,17 +23,15 @@ import org.apache.hadoop.hdds.HddsUtils;
 import org.apache.hadoop.hdds.client.BlockID;
 import org.apache.hadoop.hdds.client.ContainerBlockID;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProtoOrBuilder;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
 import org.apache.hadoop.hdds.security.x509.SecurityConfig;
 import 
org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
 
-import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.GetBlock;
-import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.GetSmallFile;
-import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.PutBlock;
-import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.PutSmallFile;
-import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.ReadChunk;
-import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.WriteChunk;
+import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.DeleteBlock;
+import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.DeleteChunk;
+import static 
org.apache.hadoop.hdds.protocol.proto.HddsProtos.BlockTokenSecretProto.AccessModeProto.DELETE;
 import static 
org.apache.hadoop.hdds.protocol.proto.HddsProtos.BlockTokenSecretProto.AccessModeProto.READ;
 import static 
org.apache.hadoop.hdds.protocol.proto.HddsProtos.BlockTokenSecretProto.AccessModeProto.WRITE;
 
@@ -68,7 +66,7 @@ public class BlockTokenVerifier extends
   }
 
   @Override
-  protected Object getService(ContainerCommandRequestProto cmd) {
+  protected Object getService(ContainerCommandRequestProtoOrBuilder cmd) {
     BlockID blockID = HddsUtils.getBlockID(cmd);
     Preconditions.checkNotNull(blockID,
         "no blockID in %s command", cmd.getCmdType());
@@ -77,21 +75,20 @@ public class BlockTokenVerifier extends
 
   @Override
   protected void verify(OzoneBlockTokenIdentifier tokenId,
-      ContainerCommandRequestProto cmd) throws SCMSecurityException {
+      ContainerCommandRequestProtoOrBuilder cmd) throws SCMSecurityException {
 
-    ContainerProtos.Type type = cmd.getCmdType();
-    if (type == ReadChunk || type == GetBlock || type == GetSmallFile) {
-      if (!tokenId.getAccessModes().contains(READ)) {
-        throw new BlockTokenException("Block token with " + 
tokenId.getService()
-            + " doesn't have READ permission");
-      }
-    } else if (type == WriteChunk || type == PutBlock || type == PutSmallFile) 
{
-      if (!tokenId.getAccessModes().contains(WRITE)) {
-        throw new BlockTokenException("Block token with " + 
tokenId.getService()
-            + " doesn't have WRITE permission");
-      }
+    HddsProtos.BlockTokenSecretProto.AccessModeProto accessMode;
+    if (HddsUtils.isReadOnly(cmd)) {
+      accessMode = READ;
+    } else if (cmd.getCmdType() == DeleteBlock ||
+        cmd.getCmdType() == DeleteChunk) {
+      accessMode = DELETE;
     } else {
-      throw new BlockTokenException("Block token does not support " + cmd);
+      accessMode = WRITE;
+    }
+    if (!tokenId.getAccessModes().contains(accessMode)) {
+      throw new BlockTokenException("Block token with " + tokenId.getService()
+          + " doesn't have " + accessMode + " permission");
     }
   }
 }
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/CompositeTokenVerifier.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/CompositeTokenVerifier.java
index ce10c25..750bb76 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/CompositeTokenVerifier.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/CompositeTokenVerifier.java
@@ -17,7 +17,7 @@
  */
 package org.apache.hadoop.hdds.security.token;
 
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProtoOrBuilder;
 import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
 import org.apache.hadoop.security.token.Token;
 
@@ -37,7 +37,7 @@ public class CompositeTokenVerifier implements TokenVerifier {
 
   @Override
   public void verify(String user, Token<?> token,
-      ContainerCommandRequestProto cmd) throws SCMSecurityException {
+      ContainerCommandRequestProtoOrBuilder cmd) throws SCMSecurityException {
 
     for (TokenVerifier verifier : delegates) {
       verifier.verify(user, token, cmd);
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ContainerTokenVerifier.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ContainerTokenVerifier.java
index 806a9ae..941160a 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ContainerTokenVerifier.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ContainerTokenVerifier.java
@@ -19,7 +19,7 @@ package org.apache.hadoop.hdds.security.token;
 
 import org.apache.hadoop.hdds.HddsUtils;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProtoOrBuilder;
 import org.apache.hadoop.hdds.scm.container.ContainerID;
 import org.apache.hadoop.hdds.security.x509.SecurityConfig;
 import 
org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
@@ -45,7 +45,7 @@ public class ContainerTokenVerifier extends
   }
 
   @Override
-  protected Object getService(ContainerCommandRequestProto cmd) {
+  protected Object getService(ContainerCommandRequestProtoOrBuilder cmd) {
     return ContainerID.valueOf(cmd.getContainerID());
   }
 }
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/NoopTokenVerifier.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/NoopTokenVerifier.java
index b86b906..084b42e 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/NoopTokenVerifier.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/NoopTokenVerifier.java
@@ -17,7 +17,7 @@
  */
 package org.apache.hadoop.hdds.security.token;
 
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProtoOrBuilder;
 import org.apache.hadoop.security.token.Token;
 
 /** No-op verifier, used when block token is disabled in config. */
@@ -25,12 +25,12 @@ public class NoopTokenVerifier implements TokenVerifier {
 
   @Override
   public void verify(String user, Token<?> token,
-      ContainerCommandRequestProto cmd) {
+      ContainerCommandRequestProtoOrBuilder cmd) {
     // no-op
   }
 
   @Override // to avoid "failed to find token"
-  public void verify(ContainerCommandRequestProto cmd, String user,
+  public void verify(ContainerCommandRequestProtoOrBuilder cmd, String user,
       String encodedToken) {
     // no-op
   }
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ShortLivedTokenVerifier.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ShortLivedTokenVerifier.java
index dc89d0b..92b643e 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ShortLivedTokenVerifier.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/ShortLivedTokenVerifier.java
@@ -18,7 +18,7 @@
 package org.apache.hadoop.hdds.security.token;
 
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProtoOrBuilder;
 import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
 import org.apache.hadoop.hdds.security.x509.SecurityConfig;
 import 
org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
@@ -58,17 +58,18 @@ public abstract class
   protected abstract T createTokenIdentifier();
 
   /** Extract info on "service" being accessed by {@code cmd}. */
-  protected abstract Object getService(ContainerCommandRequestProto cmd);
+  protected abstract Object getService(
+      ContainerCommandRequestProtoOrBuilder cmd);
 
   /** Hook for further verification. */
-  protected void verify(T tokenId, ContainerCommandRequestProto cmd)
+  protected void verify(T tokenId, ContainerCommandRequestProtoOrBuilder cmd)
       throws SCMSecurityException {
     // NOP
   }
 
   @Override
   public void verify(String user, Token<?> token,
-      ContainerCommandRequestProto cmd) throws SCMSecurityException {
+      ContainerCommandRequestProtoOrBuilder cmd) throws SCMSecurityException {
 
     if (!isTokenRequired(cmd.getCmdType())) {
       return;
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/TokenVerifier.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/TokenVerifier.java
index b2a5ae5..dbf79d5 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/TokenVerifier.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/security/token/TokenVerifier.java
@@ -21,7 +21,7 @@ package org.apache.hadoop.hdds.security.token;
 import com.google.common.base.Strings;
 import org.apache.hadoop.hdds.annotation.InterfaceAudience;
 import org.apache.hadoop.hdds.annotation.InterfaceStability;
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
+import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProtoOrBuilder;
 import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
 import org.apache.hadoop.hdds.security.x509.SecurityConfig;
 import 
org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
@@ -47,12 +47,13 @@ public interface TokenVerifier {
    * @param cmd container command
    * @throws SCMSecurityException if token verification fails.
    */
-  void verify(String user, Token<?> token, ContainerCommandRequestProto cmd)
+  void verify(String user, Token<?> token,
+      ContainerCommandRequestProtoOrBuilder cmd)
       throws SCMSecurityException;
 
-  /** Same as {@link #verify(String, Token, ContainerCommandRequestProto)}, but
-   * with encoded token. */
-  default void verify(ContainerCommandRequestProto cmd, String user,
+  /** Same as {@link #verify(String, Token,
+   * ContainerCommandRequestProtoOrBuilder)}, but with encoded token. */
+  default void verify(ContainerCommandRequestProtoOrBuilder cmd, String user,
       String encodedToken) throws SCMSecurityException {
 
     if (Strings.isNullOrEmpty(encodedToken)) {
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/server/TestSecureContainerServer.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/server/TestSecureContainerServer.java
index 4db4050..92df53f 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/server/TestSecureContainerServer.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/server/TestSecureContainerServer.java
@@ -72,22 +72,28 @@ import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.test.GenericTestUtils;
 
 import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_BLOCK_TOKEN_ENABLED;
+import static org.apache.hadoop.hdds.HddsUtils.isReadOnly;
 import static 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.SUCCESS;
 import static org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_KEY;
 import static 
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SECURITY_ENABLED_KEY;
 import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.getCreateContainerRequest;
-import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.getPutBlockRequest;
 import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.getTestBlockID;
 import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.getTestContainerID;
-import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.getWriteChunkRequest;
+import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.newDeleteBlockRequestBuilder;
+import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.newDeleteChunkRequestBuilder;
+import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.newGetBlockRequestBuilder;
+import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.newGetCommittedBlockLengthBuilder;
+import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.newPutBlockRequestBuilder;
+import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.newReadChunkRequestBuilder;
+import static 
org.apache.hadoop.ozone.container.ContainerTestHelper.newWriteChunkRequestBuilder;
 
 import com.google.common.collect.Maps;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.RandomUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.hadoop.test.LambdaTestUtils;
 import org.apache.ratis.rpc.RpcType;
+
 import static org.apache.ratis.rpc.SupportedRpcType.GRPC;
 import org.apache.ratis.util.function.CheckedBiConsumer;
 import org.junit.After;
@@ -96,6 +102,8 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -253,45 +261,72 @@ public class TestSecureContainerServer {
       ContainerProtocolCalls.createContainer(client, containerID,
           getToken(ContainerID.valueOf(containerID)));
 
-      // Test 1: Test putBlock failure without block token.
-      assertFailsTokenVerification(client, getPutBlockRequest(pipeline, null,
-          getWriteChunkRequest(pipeline, blockID, 1024, 
null).getWriteChunk()));
-
-      // Test 2: Test putBlock succeeded with valid block token.
       Token<OzoneBlockTokenIdentifier> token =
           blockTokenSecretManager.generateToken(blockID,
-          EnumSet.allOf(AccessModeProto.class), RandomUtils.nextLong());
+              EnumSet.allOf(AccessModeProto.class), RandomUtils.nextLong());
+      String encodedToken = token.encodeToUrlString();
+
+      ContainerCommandRequestProto.Builder writeChunk =
+          newWriteChunkRequestBuilder(pipeline, blockID, 1024, 0);
+      assertRequiresToken(client, encodedToken, writeChunk);
+
+      ContainerCommandRequestProto.Builder putBlock =
+          newPutBlockRequestBuilder(pipeline, writeChunk.getWriteChunk());
+      assertRequiresToken(client, encodedToken, putBlock);
+
+      ContainerCommandRequestProto.Builder readChunk =
+          newReadChunkRequestBuilder(pipeline, writeChunk.getWriteChunk());
+      assertRequiresToken(client, encodedToken, readChunk);
+
+      ContainerCommandRequestProto.Builder getBlock =
+          newGetBlockRequestBuilder(pipeline, putBlock.getPutBlock());
+      assertRequiresToken(client, encodedToken, getBlock);
 
-      ContainerCommandRequestProto writeChunkRequest = getWriteChunkRequest(
-          pipeline, blockID, 1024, token.encodeToUrlString());
-      assertSucceeds(client, writeChunkRequest);
+      ContainerCommandRequestProto.Builder getCommittedBlockLength =
+          newGetCommittedBlockLengthBuilder(pipeline, putBlock.getPutBlock());
+      assertRequiresToken(client, encodedToken, getCommittedBlockLength);
 
-      assertSucceeds(client, getPutBlockRequest(pipeline,
-          token.encodeToUrlString(), writeChunkRequest.getWriteChunk()));
+      ContainerCommandRequestProto.Builder deleteChunk =
+          newDeleteChunkRequestBuilder(pipeline, writeChunk.getWriteChunk());
+      assertRequiresToken(client, encodedToken, deleteChunk);
+
+      ContainerCommandRequestProto.Builder deleteBlock =
+          newDeleteBlockRequestBuilder(pipeline, putBlock.getPutBlock());
+      assertRequiresToken(client, encodedToken, deleteBlock);
     } finally {
       stopServer.accept(pipeline);
       servers.forEach(XceiverServerSpi::stop);
     }
   }
 
-  private static ContainerCommandRequestProto assertSucceeds(
+  private static void assertRequiresToken(XceiverClientSpi client,
+      String encodedToken, ContainerCommandRequestProto.Builder requestBuilder)
+      throws Exception {
+
+    requestBuilder.setEncodedToken("");
+    assertFailsTokenVerification(client, requestBuilder.build());
+
+    requestBuilder.setEncodedToken(encodedToken);
+    assertSucceeds(client, requestBuilder.build());
+  }
+
+  private static void assertSucceeds(
       XceiverClientSpi client, ContainerCommandRequestProto req)
       throws IOException {
     ContainerCommandResponseProto response = client.sendCommand(req);
     assertEquals(SUCCESS, response.getResult());
-    return req;
   }
 
   private static void assertFailsTokenVerification(XceiverClientSpi client,
       ContainerCommandRequestProto request) throws Exception {
-    if (client instanceof XceiverClientGrpc) {
+    if (client instanceof XceiverClientGrpc || isReadOnly(request)) {
       ContainerCommandResponseProto response = client.sendCommand(request);
       assertNotEquals(response.getResult(), ContainerProtos.Result.SUCCESS);
       String msg = response.getMessage();
       assertTrue(msg, msg.contains("token verification failed"));
     } else {
       assertRootCauseMessage("token verification failed",
-          LambdaTestUtils.intercept(IOException.class, () ->
+          Assert.assertThrows(IOException.class, () ->
               client.sendCommand(request)));
     }
   }

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to