You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by bh...@apache.org on 2021/11/01 18:58:12 UTC

[ozone] branch master updated: HDDS-5885. OM Auth Validate for read requests and handle non ratis enabled code. (#2779)

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

bharat 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 5c76856  HDDS-5885. OM Auth Validate for read requests and handle non ratis enabled code. (#2779)
5c76856 is described below

commit 5c76856e68599a50cbf2fc4d57fed8ac84332f3d
Author: Bharat Viswanadham <bh...@apache.org>
AuthorDate: Mon Nov 1 11:57:46 2021 -0700

    HDDS-5885. OM Auth Validate for read requests and handle non ratis enabled code. (#2779)
---
 .../ozone/client/rpc/TestSecureOzoneRpcClient.java | 39 +++++++++++++++++--
 .../org/apache/hadoop/ozone/om/OzoneManager.java   | 30 ++++++++++++++-
 ...OzoneManagerProtocolServerSideTranslatorPB.java | 45 ++++++++++++++++++----
 .../hadoop/ozone/security/S3SecurityUtil.java      | 26 ++++++-------
 4 files changed, 115 insertions(+), 25 deletions(-)

diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java
index f27184a..4886110 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java
@@ -46,6 +46,7 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
 import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateVolumeRequest;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoVolumeRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Authentication;
@@ -241,7 +242,7 @@ public class TestSecureOzoneRpcClient extends TestOzoneRpcClient {
     cluster.getOzoneManager().getMetadataManager().getS3SecretTable().put(
         accessKey, new S3SecretValue(accessKey, secret));
 
-    OMRequest omRequest = OMRequest.newBuilder()
+    OMRequest writeRequest = OMRequest.newBuilder()
         .setCmdType(OzoneManagerProtocolProtos.Type.CreateVolume)
         .setVersion(CURRENT_VERSION)
         .setClientId(UUID.randomUUID().toString())
@@ -257,18 +258,50 @@ public class TestSecureOzoneRpcClient extends TestOzoneRpcClient {
     GenericTestUtils.waitFor(() -> cluster.getOzoneManager().isLeaderReady(),
         100, 120000);
     OMResponse omResponse = cluster.getOzoneManager().getOmServerProtocol()
-        .submitRequest(null, omRequest);
+        .submitRequest(null, writeRequest);
 
+    // Verify response.
     Assert.assertTrue(omResponse.getStatus() == Status.OK);
 
+    // Read Request
+    OMRequest readRequest = OMRequest.newBuilder()
+        .setCmdType(OzoneManagerProtocolProtos.Type.InfoVolume)
+        .setVersion(CURRENT_VERSION)
+        .setClientId(UUID.randomUUID().toString())
+        .setInfoVolumeRequest(InfoVolumeRequest.newBuilder()
+            .setVolumeName(volumeName).build())
+        .setS3Authentication(S3Authentication.newBuilder()
+            .setAccessId(accessKey)
+            .setSignature(signature).setStringToSign(strToSign))
+        .build();
+
+    omResponse = cluster.getOzoneManager().getOmServerProtocol()
+        .submitRequest(null, readRequest);
+
+    // Verify response.
+    Assert.assertTrue(omResponse.getStatus() == Status.OK);
+
+    VolumeInfo volumeInfo = omResponse.getInfoVolumeResponse().getVolumeInfo();
+    Assert.assertNotNull(volumeInfo);
+    Assert.assertEquals(volumeName, volumeInfo.getVolume());
+    Assert.assertEquals(accessKey, volumeInfo.getAdminName());
+    Assert.assertEquals(accessKey, volumeInfo.getOwnerName());
 
     // Override secret to S3Secret table with some dummy value
     cluster.getOzoneManager().getMetadataManager().getS3SecretTable().put(
         accessKey, new S3SecretValue(accessKey, "dummy"));
+
+    // Write request with invalid credentials.
     omResponse = cluster.getOzoneManager().getOmServerProtocol()
-        .submitRequest(null, omRequest);
+        .submitRequest(null, writeRequest);
     Assert.assertTrue(omResponse.getStatus() == Status.INVALID_TOKEN);
 
+  // Read request with invalid credentials.
+    omResponse = cluster.getOzoneManager().getOmServerProtocol()
+        .submitRequest(null, readRequest);
+    Assert.assertTrue(omResponse.getStatus() == Status.INVALID_TOKEN);
+
+
   }
 
   private boolean verifyRatisReplication(String volumeName, String bucketName,
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 0750b30..b52b3b1 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -143,6 +143,7 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DBUpdatesRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Authentication;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServicePort;
 import org.apache.hadoop.ozone.protocolPB.OMInterServiceProtocolServerSideImpl;
 import org.apache.hadoop.ozone.storage.proto.OzoneManagerStorageProtos.PersistedUserVolumeInfo;
@@ -270,6 +271,11 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
 
   private static final String OM_DAEMON = "om";
 
+  // This is set for read requests when OMRequest has S3Authentication set,
+  // and it is reset when read request is processed.
+  private static final ThreadLocal<S3Authentication> S3_AUTH =
+      new ThreadLocal<>();
+
   private static boolean securityEnabled = false;
   private OzoneDelegationTokenSecretManager delegationTokenMgr;
   private OzoneBlockTokenSecretManager blockTokenMgr;
@@ -541,6 +547,20 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
   }
 
   /**
+   * Set the {@link S3Authentication} for the current rpc handler thread.
+   */
+  public static void setS3Auth(S3Authentication val) {
+    S3_AUTH.set(val);
+  }
+
+  /**
+   * Returns the {@link S3Authentication} for the current rpc handler thread.
+   */
+  public static S3Authentication getS3Auth() {
+    return S3_AUTH.get();
+  }
+
+  /**
    * This method is used to set selected instance variables in this class from
    * the passed in config. This allows these variable to be reset when the OM
    * instance is restarted (normally from a test mini-cluster). Note, not all
@@ -1989,8 +2009,16 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
   private void checkAcls(ResourceType resType, StoreType store,
       ACLType acl, String vol, String bucket, String key)
       throws IOException {
-    UserGroupInformation user = ProtobufRpcEngine.Server.getRemoteUser();
+    UserGroupInformation user;
+    if (getS3Auth() != null) {
+      user = UserGroupInformation.createRemoteUser(
+          getS3Auth().getAccessId());
+    } else {
+      user = ProtobufRpcEngine.Server.getRemoteUser();
+    }
+
     InetAddress remoteIp = ProtobufRpcEngine.Server.getRemoteIp();
+
     checkAcls(resType, store, acl, vol, bucket, key,
         user != null ? user : getRemoteUser(),
         remoteIp != null ? remoteIp : omRpcAddress.getAddress(),
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
index 905ca67..7946f65 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
@@ -128,17 +128,36 @@ public class OzoneManagerProtocolServerSideTranslatorPB implements
   private OMResponse processRequest(OMRequest request) throws
       ServiceException {
     if (isRatisEnabled) {
+      boolean s3Auth = false;
+      try {
+        // If Request has S3Authentication validate S3 credentials
+        // if current OM is leader and then proceed with processing the request.
+        if (request.hasS3Authentication()) {
+          s3Auth = true;
+          checkLeaderStatus();
+          S3SecurityUtil.validateS3Credential(request, ozoneManager);
+        }
+      } catch (IOException ex) {
+        // If validate credentials fail return error OM Response.
+        return createErrorResponse(request, ex);
+      }
       // Check if the request is a read only request
       if (OmUtils.isReadOnly(request)) {
-        return submitReadRequestToOM(request);
-      } else {
-        checkLeaderStatus();
         try {
-          // If Request has S3Authentication validate S3 credentials and
-          // then proceed with processing the request.
           if (request.hasS3Authentication()) {
-            S3SecurityUtil.validateS3Credential(request, ozoneManager);
+            ozoneManager.setS3Auth(request.getS3Authentication());
           }
+          return submitReadRequestToOM(request);
+        } finally {
+          ozoneManager.setS3Auth(null);
+        }
+      } else {
+        // To validate credentials we have already verified leader status.
+        // This will skip of checking leader status again if request has S3Auth.
+        if (!s3Auth) {
+          checkLeaderStatus();
+        }
+        try {
           OMClientRequest omClientRequest =
               createClientRequest(request, ozoneManager);
           request = omClientRequest.preExecute(ozoneManager);
@@ -215,8 +234,20 @@ public class OzoneManagerProtocolServerSideTranslatorPB implements
     OMClientResponse omClientResponse = null;
     long index = 0L;
     try {
+      // If Request has S3Authentication validate S3 credentials and
+      // then proceed with processing the request.
+      if (request.hasS3Authentication()) {
+        S3SecurityUtil.validateS3Credential(request, ozoneManager);
+      }
       if (OmUtils.isReadOnly(request)) {
-        return handler.handleReadRequest(request);
+        try {
+          if (request.hasS3Authentication()) {
+            ozoneManager.setS3Auth(request.getS3Authentication());
+          }
+          return handler.handleReadRequest(request);
+        } finally {
+          ozoneManager.setS3Auth(null);
+        }
       } else {
         OMClientRequest omClientRequest =
             createClientRequest(request, ozoneManager);
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java
index b9e2a05..377eec8 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java
@@ -50,20 +50,18 @@ public final class S3SecurityUtil {
   public static void validateS3Credential(OMRequest omRequest,
       OzoneManager ozoneManager) throws OMException {
     if (ozoneManager.isSecurityEnabled()) {
-      if (omRequest.hasS3Authentication()) {
-        OzoneTokenIdentifier s3Token = constructS3Token(omRequest);
-        try {
-          // authenticate user with signature verification through
-          // delegationTokenMgr validateToken via retrievePassword
-          ozoneManager.getDelegationTokenMgr().retrievePassword(s3Token);
-        } catch (SecretManager.InvalidToken e) {
-          // TODO: Just check are we okay to log enitre token in failure case.
-          OzoneManagerProtocolServerSideTranslatorPB.getLog().error(
-              "signatures do NOT match for S3 identifier:{}", s3Token, e);
-          throw new OMException("User " + s3Token.getAwsAccessId()
-              + " request authorization failure: signatures do NOT match",
-              INVALID_TOKEN);
-        }
+      OzoneTokenIdentifier s3Token = constructS3Token(omRequest);
+      try {
+        // authenticate user with signature verification through
+        // delegationTokenMgr validateToken via retrievePassword
+        ozoneManager.getDelegationTokenMgr().retrievePassword(s3Token);
+      } catch (SecretManager.InvalidToken e) {
+        // TODO: Just check are we okay to log enitre token in failure case.
+        OzoneManagerProtocolServerSideTranslatorPB.getLog().error(
+            "signatures do NOT match for S3 identifier:{}", s3Token, e);
+        throw new OMException("User " + s3Token.getAwsAccessId()
+            + " request authorization failure: signatures do NOT match",
+            INVALID_TOKEN);
       }
     }
   }

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org