You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by ad...@apache.org on 2021/10/11 07:00:03 UTC

[ozone] branch HDDS-4440-s3-performance updated: HDDS-5780. Support s3 authentication on a per request basis (#2721)

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

adoroszlai pushed a commit to branch HDDS-4440-s3-performance
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/HDDS-4440-s3-performance by this push:
     new b0f41d6  HDDS-5780. Support s3 authentication on a per request basis (#2721)
b0f41d6 is described below

commit b0f41d67da7cdec7aabdb71de8b005cc879280bc
Author: Neil Joshi <ne...@gmail.com>
AuthorDate: Mon Oct 11 00:59:50 2021 -0600

    HDDS-5780. Support s3 authentication on a per request basis (#2721)
---
 .../ozone/om/protocolPB/GrpcOmTransport.java       | 39 +++++++++
 .../hadoop/ozone/om/GrpcOzoneManagerServer.java    | 24 ++++--
 .../org/apache/hadoop/ozone/om/OzoneManager.java   |  7 +-
 .../hadoop/ozone/om/OzoneManagerServiceGrpc.java   | 95 ++++++++++++++++++----
 .../ozone/om/TestGrpcOzoneManagerServer.java       |  6 +-
 5 files changed, 142 insertions(+), 29 deletions(-)

diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/GrpcOmTransport.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/GrpcOmTransport.java
index 752f29e..22d49a9 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/GrpcOmTransport.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/GrpcOmTransport.java
@@ -17,7 +17,11 @@
  */
 package org.apache.hadoop.ozone.om.protocolPB;
 
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
 import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -27,8 +31,14 @@ import org.apache.hadoop.hdds.conf.ConfigGroup;
 import org.apache.hadoop.hdds.conf.ConfigTag;
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.io.Text;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
+import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.TokenIdentifier;
 import org.apache.hadoop.security.UserGroupInformation;
 
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerServiceGrpc;
@@ -45,6 +55,8 @@ import static org.apache.hadoop.ozone.om.OMConfigKeys
 import static org.apache.hadoop.ozone.om.OMConfigKeys
     .OZONE_OM_GRPC_MAXIMUM_RESPONSE_LENGTH_DEFAULT;
 import static org.apache.hadoop.hdds.HddsUtils.getHostNameFromConfigKeys;
+import static org.apache.hadoop.ozone.protocol.proto
+    .OzoneManagerProtocolProtos.OMTokenProto.Type.S3AUTHINFO;
 
 /**
  * Grpc transport for grpc between s3g and om.
@@ -98,6 +110,33 @@ public class GrpcOmTransport implements OmTransport {
 
   @Override
   public OMResponse submitRequest(OMRequest payload) throws IOException {
+    UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
+
+    final Collection<Token<? extends TokenIdentifier>> tokenS3Requests =
+        ugi.getTokens();
+    if (tokenS3Requests.size() > 1) {
+      throw new OMException(ResultCodes.INVALID_TOKEN);
+    }
+    Iterator<Token<? extends TokenIdentifier>> tokenit =
+        tokenS3Requests.iterator();
+    if (tokenit.hasNext()) {
+      OzoneTokenIdentifier oti = OzoneTokenIdentifier.newInstance();
+      oti.readFields(new DataInputStream(
+          new ByteArrayInputStream(tokenit.next().getIdentifier())));
+      if (oti.getTokenType().equals(S3AUTHINFO)) {
+        payload = OMRequest.newBuilder(payload)
+            .setS3Authentication(
+                OzoneManagerProtocolProtos
+                    .S3Authentication.newBuilder()
+                    .setSignature(oti.getSignature())
+                    .setStringToSign(oti.getStrToSign())
+                    .setAccessId(oti.getAwsAccessId()))
+            .setUserInfo(OzoneManagerProtocolProtos
+                .UserInfo.newBuilder()
+                .setUserName(ugi.getUserName()).build())
+            .build();
+      }
+    }
     return client.submitRequest(payload);
   }
 
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/GrpcOzoneManagerServer.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/GrpcOzoneManagerServer.java
index d82024a..60942f9 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/GrpcOzoneManagerServer.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/GrpcOzoneManagerServer.java
@@ -23,8 +23,10 @@ import java.util.concurrent.TimeUnit;
 import org.apache.hadoop.hdds.conf.Config;
 import org.apache.hadoop.hdds.conf.ConfigGroup;
 import org.apache.hadoop.hdds.conf.ConfigTag;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.protocolPB.OzoneManagerProtocolServerSideTranslatorPB;
+import org.apache.hadoop.ozone.security.OzoneDelegationTokenSecretManager;
 import io.grpc.Server;
 import io.grpc.netty.NettyServerBuilder;
 import org.slf4j.Logger;
@@ -40,17 +42,27 @@ public class GrpcOzoneManagerServer {
   private Server server;
   private int port = 8981;
 
-  public GrpcOzoneManagerServer(GrpcOzoneManagerServerConfig omServerConfig,
+  public GrpcOzoneManagerServer(OzoneConfiguration config,
                                 OzoneManagerProtocolServerSideTranslatorPB
-                                    omTranslator) {
-    this.port = omServerConfig.getPort();
-    init(omTranslator);
+                                    omTranslator,
+                                OzoneDelegationTokenSecretManager
+                                    delegationTokenMgr) {
+    this.port = config.getObject(
+        GrpcOzoneManagerServerConfig.class).
+        getPort();
+    init(omTranslator,
+        delegationTokenMgr,
+        config);
   }
 
-  public void init(OzoneManagerProtocolServerSideTranslatorPB omTranslator) {
+  public void init(OzoneManagerProtocolServerSideTranslatorPB omTranslator,
+                   OzoneDelegationTokenSecretManager delegationTokenMgr,
+                   OzoneConfiguration omServerConfig) {
     NettyServerBuilder nettyServerBuilder = NettyServerBuilder.forPort(port)
         .maxInboundMessageSize(OzoneConsts.OZONE_SCM_CHUNK_MAX_SIZE)
-        .addService(new OzoneManagerServiceGrpc(omTranslator));
+        .addService(new OzoneManagerServiceGrpc(omTranslator,
+            delegationTokenMgr,
+            omServerConfig));
 
     server = nettyServerBuilder.build();
   }
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 1dd402d..29688ba 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
@@ -111,7 +111,6 @@ import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
 import org.apache.hadoop.ozone.om.exceptions.OMLeaderNotReadyException;
 import org.apache.hadoop.ozone.om.exceptions.OMNotLeaderException;
-import org.apache.hadoop.ozone.om.GrpcOzoneManagerServer.GrpcOzoneManagerServerConfig;
 import org.apache.hadoop.ozone.om.ha.OMHANodeDetails;
 import org.apache.hadoop.ozone.om.helpers.OMNodeDetails;
 import org.apache.hadoop.ozone.om.helpers.DBUpdates;
@@ -1023,9 +1022,9 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
    */
   private GrpcOzoneManagerServer startGrpcServer(OzoneConfiguration conf)
           throws IOException {
-    return new GrpcOzoneManagerServer(conf.getObject(
-            GrpcOzoneManagerServerConfig.class),
-            this.omServerProtocol);
+    return new GrpcOzoneManagerServer(conf,
+            this.omServerProtocol,
+            this.delegationTokenMgr);
   }
 
   private static boolean isOzoneSecurityEnabled() {
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerServiceGrpc.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerServiceGrpc.java
index 95b9285..a23f7ef 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerServiceGrpc.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerServiceGrpc.java
@@ -18,22 +18,35 @@
 package org.apache.hadoop.ozone.om;
 
 import com.google.protobuf.RpcController;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.security.x509.SecurityConfig;
+import org.apache.hadoop.io.Text;
 import org.apache.hadoop.ipc.ClientId;
 import org.apache.hadoop.ipc.RPC;
 import org.apache.hadoop.ipc.Server;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerRatisUtils;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerServiceGrpc.OzoneManagerServiceImplBase;
 import org.apache.hadoop.ozone.protocolPB.OzoneManagerProtocolServerSideTranslatorPB;
 import org.apache.hadoop.ozone.protocol.proto
+    .OzoneManagerProtocolProtos.S3Authentication;
+import org.apache.hadoop.ozone.protocol.proto
     .OzoneManagerProtocolProtos.OMRequest;
 import org.apache.hadoop.ozone.protocol.proto
     .OzoneManagerProtocolProtos.OMResponse;
+import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
+import org.apache.hadoop.ozone.security.OzoneDelegationTokenSecretManager;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import static org.apache.hadoop.ozone.protocol.proto
+    .OzoneManagerProtocolProtos.OMTokenProto.Type.S3AUTHINFO;
+
 /**
  * Grpc Service for handling S3 gateway OzoneManagerProtocol client requests.
  */
@@ -45,10 +58,16 @@ public class OzoneManagerServiceGrpc extends OzoneManagerServiceImplBase {
    */
   private static final RpcController NULL_RPC_CONTROLLER = null;
   private OzoneManagerProtocolServerSideTranslatorPB omTranslator;
+  private OzoneDelegationTokenSecretManager delegationTokenMgr;
+  private final SecurityConfig secConfig;
 
   OzoneManagerServiceGrpc(
-      OzoneManagerProtocolServerSideTranslatorPB omTranslator) {
+      OzoneManagerProtocolServerSideTranslatorPB omTranslator,
+      OzoneDelegationTokenSecretManager delegationTokenMgr,
+      OzoneConfiguration configuration) {
     this.omTranslator = omTranslator;
+    this.delegationTokenMgr = delegationTokenMgr;
+    this.secConfig = new SecurityConfig(configuration);
   }
 
   @Override
@@ -60,22 +79,66 @@ public class OzoneManagerServiceGrpc extends OzoneManagerServiceImplBase {
         request.getCmdType().name());
     AtomicInteger callCount = new AtomicInteger(0);
     OMResponse omResponse;
+
+    if (secConfig.isSecurityEnabled()) {
+      if (request.hasS3Authentication()) {
+        S3Authentication auth = request.getS3Authentication();
+        OzoneTokenIdentifier identifier = new OzoneTokenIdentifier();
+        identifier.setTokenType(S3AUTHINFO);
+        identifier.setStrToSign(auth.getStringToSign());
+        identifier.setSignature(auth.getSignature());
+        identifier.setAwsAccessId(auth.getAccessId());
+        identifier.setOwner(new Text(auth.getAccessId()));
+        try {
+          // authenticate user with signature verification through
+          // delegationTokenMgr validateToken via retrievePassword
+          delegationTokenMgr.retrievePassword(identifier);
+        } catch (Throwable e) {
+          LOG.error("signatures do NOT match for S3 identifier:{}",
+              identifier, e);
+          responseObserver.onNext(
+              createErrorResponse(request,
+                  new OMException("User " + request.getUserInfo()
+                      .getUserName() +
+                      " request authorization failure: " +
+                      "signatures do NOT match",
+                      OMException.ResultCodes.S3_SECRET_NOT_FOUND)));
+          responseObserver.onCompleted();
+          return;
+        }
+      }
+    }
+
+    org.apache.hadoop.ipc.Server.getCurCall().set(new Server.Call(1,
+        callCount.incrementAndGet(),
+        null,
+        null,
+        RPC.RpcKind.RPC_PROTOCOL_BUFFER,
+        ClientId.getClientId()));
+    // TODO: currently require setting the Server class for each request
+    // with thread context (Server.Call()) that includes retries
+    // and importantly random ClientId.  This is currently necessary for
+    // Om Ratis Server to create createWriteRaftClientRequest.
+    // Look to remove Server class requirement for issuing ratis transactions
+    // for OMRequests.  Test through successful ratis-enabled OMRequest
+    // handling without dependency on hadoop IPC based Server.
     try {
-      org.apache.hadoop.ipc.Server.getCurCall().set(new Server.Call(1,
-          callCount.incrementAndGet(),
-          null,
-          null,
-          RPC.RpcKind.RPC_PROTOCOL_BUFFER,
-          ClientId.getClientId()));
-      // TODO: currently require setting the Server class for each request
-      // with thread context (Server.Call()) that includes retries
-      // and importantly random ClientId.  This is currently necessary for
-      // Om Ratis Server to create createWriteRaftClientRequest.
-      // Look to remove Server class requirement for issuing ratis transactions
-      // for OMRequests.  Test through successful ratis-enabled OMRequest 
-      // handling without dependency on hadoop IPC based Server.
-      omResponse = this.omTranslator.
-          submitRequest(NULL_RPC_CONTROLLER, request);
+      omResponse =
+          UserGroupInformation.getCurrentUser().doAs(
+              (PrivilegedExceptionAction<OMResponse>) () -> {
+                try {
+                  return this.omTranslator.
+                      submitRequest(NULL_RPC_CONTROLLER, request);
+                } catch (Throwable se) {
+                  Throwable e = se.getCause();
+                  if (e == null) {
+                    throw new IOException(se);
+                  } else {
+                    throw e instanceof IOException ?
+                        (IOException) e : new IOException(se);
+                  }
+                }
+              });
     } catch (Throwable e) {
       omResponse = createErrorResponse(
           request,
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestGrpcOzoneManagerServer.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestGrpcOzoneManagerServer.java
index 46155ae..b75a651 100644
--- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestGrpcOzoneManagerServer.java
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestGrpcOzoneManagerServer.java
@@ -47,9 +47,9 @@ public class TestGrpcOzoneManagerServer {
     ozoneManager = Mockito.mock(OzoneManager.class);
     omServerProtocol = ozoneManager.getOmServerProtocol();
 
-    server = new GrpcOzoneManagerServer(conf.getObject(
-            GrpcOzoneManagerServer.GrpcOzoneManagerServerConfig.class),
-        omServerProtocol);
+    server = new GrpcOzoneManagerServer(conf,
+        omServerProtocol,
+        ozoneManager.getDelegationTokenMgr());
 
     try {
       server.start();

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