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

avijayan pushed a commit to branch HDDS-4944
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/HDDS-4944 by this push:
     new e5fb5b0  HDDS-5476. [Multi-Tenant] Support Ozone s3 authentication 
with arbitrary accessId that is not same as the kerberos ID (#2635)
e5fb5b0 is described below

commit e5fb5b02eb528d8cc9a6724cdad76e5271aaee1a
Author: avijayanhwx <[email protected]>
AuthorDate: Wed Sep 22 13:58:43 2021 -0700

    HDDS-5476. [Multi-Tenant] Support Ozone s3 authentication with arbitrary 
accessId that is not same as the kerberos ID (#2635)
---
 .../ozone/security/OzoneTokenIdentifier.java       | 37 +++++++++++++++++++---
 .../hadoop/ozone/om/OMMultiTenantManager.java      |  6 ++++
 .../hadoop/ozone/om/OMMultiTenantManagerImpl.java  | 24 ++++++++++++++
 .../org/apache/hadoop/ozone/om/OzoneManager.java   |  1 +
 .../OzoneDelegationTokenSecretManager.java         | 18 ++++++++++-
 .../ozone/security/TestOzoneTokenIdentifier.java   | 18 +++++++++++
 6 files changed, 99 insertions(+), 5 deletions(-)

diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneTokenIdentifier.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneTokenIdentifier.java
index 01fcaf8..a62dd15 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneTokenIdentifier.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneTokenIdentifier.java
@@ -23,6 +23,7 @@ import java.io.DataOutput;
 import java.io.IOException;
 import java.time.Instant;
 import java.util.Arrays;
+import java.util.function.UnaryOperator;
 
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.hadoop.hdds.annotation.InterfaceAudience;
@@ -33,7 +34,10 @@ import org.apache.hadoop.io.Text;
 import org.apache.hadoop.io.WritableUtils;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMTokenProto;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMTokenProto.Type;
+import org.apache.hadoop.security.UserGroupInformation;
 import 
org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMTokenProto.Type.S3AUTHINFO;
 
@@ -46,6 +50,9 @@ import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.
 public class OzoneTokenIdentifier extends
     AbstractDelegationTokenIdentifier {
 
+  private static final Logger LOG =
+      LoggerFactory.getLogger(OzoneTokenIdentifier.class);
+
   public static final Text KIND_NAME = new Text("OzoneToken");
   private String omCertSerialId;
   private Type tokenType;
@@ -54,6 +61,10 @@ public class OzoneTokenIdentifier extends
   private String strToSign;
   private String omServiceId;
 
+  // Function to convert an arbitrary accessId to the kerberos user that owns
+  // the accessId.
+  private UnaryOperator<String> getUserForAccessId;
+
   /**
    * Create an empty delegation token identifier.
    */
@@ -107,10 +118,24 @@ public class OzoneTokenIdentifier extends
     return buf.getData();
   }
 
-  /** Instead of relying on proto deserialization, this
-   *  provides  explicit deserialization for OzoneTokenIdentifier.
-   * @return byte[]
-   */
+  @Override
+  public UserGroupInformation getUser() {
+    if (getUserForAccessId != null && tokenType.equals(S3AUTHINFO)) {
+      // Should have been passed as accessId
+      String tokenUser = getOwner().toString();
+      String actualUserName = getUserForAccessId.apply(tokenUser);
+      if (actualUserName != null) {
+        LOG.debug("S3 Token user for {} : {}", tokenUser, actualUserName);
+        return UserGroupInformation.createRemoteUser(actualUserName);
+      }
+    }
+    return super.getUser();
+  }
+
+    /** Instead of relying on proto deserialization, this
+     *  provides  explicit deserialization for OzoneTokenIdentifier.
+     * @return byte[]
+     */
   public OzoneTokenIdentifier fromUniqueSerializedKey(byte[] rawData)
       throws IOException {
     DataInputBuffer in = new DataInputBuffer();
@@ -368,6 +393,10 @@ public class OzoneTokenIdentifier extends
     this.strToSign = strToSign;
   }
 
+  public void setGetUserForAccessId(UnaryOperator<String> func) {
+    this.getUserForAccessId = func;
+  }
+
   @Override
   public String toString() {
     StringBuilder buffer = new StringBuilder();
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManager.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManager.java
index d9eacdf..ccae7f9 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManager.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManager.java
@@ -129,6 +129,12 @@ public interface OMMultiTenantManager {
    */
   void destroyUser(String tenantName, String userName);
 
+
+  /**
+   * Given an accessId, return kerberos user name for the tenant user.
+   */
+  String getUserNameGivenAccessId(String accessId);
+
   /**
    * Given a user, return their S3-Secret Key.
    * @param user
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java
index a9e0962..8237214 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java
@@ -42,6 +42,7 @@ import java.util.stream.Collectors;
 
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.om.helpers.OmDBAccessIdInfo;
 import org.apache.hadoop.ozone.om.multitenant.AccessPolicy;
 import org.apache.hadoop.ozone.om.multitenant.AccountNameSpace;
 import org.apache.hadoop.ozone.om.multitenant.BucketNameSpace;
@@ -59,6 +60,8 @@ import org.apache.http.auth.BasicUserPrincipal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Preconditions;
+
 /**
  * Implements OMMultiTenantManager.
  */
@@ -369,6 +372,27 @@ public class OMMultiTenantManagerImpl implements 
OMMultiTenantManager {
   }
 
   @Override
+  public String getUserNameGivenAccessId(String accessId) {
+    Preconditions.checkNotNull(accessId);
+    try {
+      controlPathLock.readLock().lock();
+      OmDBAccessIdInfo omDBAccessIdInfo =
+          omMetadataManager.getTenantAccessIdTable().get(accessId);
+      if (omDBAccessIdInfo != null) {
+        String userName = omDBAccessIdInfo.getKerberosPrincipal();
+        LOG.debug("Username for accessId {} = {}", accessId, userName);
+        return userName;
+      }
+    } catch (IOException ioEx) {
+      LOG.error("Unexpected error while obtaining DB Access Info for {}",
+          accessId, ioEx);
+    } finally {
+      controlPathLock.readLock().unlock();
+    }
+    return null;
+  }
+
+  @Override
   public String getUserSecret(OzoneMultiTenantPrincipal user)
       throws IOException {
     return "";
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 af85efb..bf4e3ee 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
@@ -802,6 +802,7 @@ public final class OzoneManager extends 
ServiceRuntimeInfoImpl
         .setS3SecretManager(s3SecretManager)
         .setCertificateClient(certClient)
         .setOmServiceId(omNodeDetails.getServiceId())
+        .setOMMultiTenantManager(multiTenantManagr)
         .build();
   }
 
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java
index 5d34f6a..a433e10 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java
@@ -36,6 +36,7 @@ import 
org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient
 import org.apache.hadoop.hdds.security.x509.exceptions.CertificateException;
 import org.apache.hadoop.io.Text;
 import org.apache.hadoop.ozone.om.OMConfigKeys;
+import org.apache.hadoop.ozone.om.OMMultiTenantManager;
 import org.apache.hadoop.ozone.om.S3SecretManager;
 import org.apache.hadoop.ozone.om.S3SecretManagerImpl;
 import org.apache.hadoop.ozone.om.exceptions.OMException;
@@ -71,6 +72,7 @@ public class OzoneDelegationTokenSecretManager
   private final long tokenRemoverScanInterval;
   private String omCertificateSerialId;
   private String omServiceId;
+  private OMMultiTenantManager multiTenantManager;
 
   /**
    * If the delegation token update thread holds this lock, it will not get
@@ -97,6 +99,7 @@ public class OzoneDelegationTokenSecretManager
     isRatisEnabled = b.ozoneConf.getBoolean(
         OMConfigKeys.OZONE_OM_RATIS_ENABLE_KEY,
         OMConfigKeys.OZONE_OM_RATIS_ENABLE_DEFAULT);
+    this.multiTenantManager = b.omMultiTenantManager;
     loadTokenSecretState(store.loadState());
 
   }
@@ -111,6 +114,7 @@ public class OzoneDelegationTokenSecretManager
     private long tokenRemoverScanInterval;
     private Text service;
     private S3SecretManager s3SecretManager;
+    private OMMultiTenantManager omMultiTenantManager;
     private CertificateClient certClient;
     private String omServiceId;
 
@@ -157,11 +161,23 @@ public class OzoneDelegationTokenSecretManager
       this.omServiceId = serviceId;
       return this;
     }
+
+    public Builder setOMMultiTenantManager(OMMultiTenantManager
+                                               multiTenantManager) {
+      this.omMultiTenantManager = multiTenantManager;
+      return this;
+    }
+
   }
 
   @Override
   public OzoneTokenIdentifier createIdentifier() {
-    return OzoneTokenIdentifier.newInstance();
+    OzoneTokenIdentifier tokenId = OzoneTokenIdentifier.newInstance();
+    if (multiTenantManager != null) {
+      tokenId.setGetUserForAccessId(
+          multiTenantManager::getUserNameGivenAccessId);
+    }
+    return tokenId;
   }
 
   /**
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneTokenIdentifier.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneTokenIdentifier.java
index 48ed205..2ac8d4c 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneTokenIdentifier.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneTokenIdentifier.java
@@ -17,6 +17,8 @@
  */
 package org.apache.hadoop.ozone.security;
 
+import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMTokenProto.Type.S3AUTHINFO;
+
 import javax.crypto.KeyGenerator;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
@@ -346,4 +348,20 @@ public class TestOzoneTokenIdentifier {
     Assert.assertEquals("Deserialize Serialized Token should equal.",
         idWrite, idRead);
   }
+
+  @Test
+  public void testGetUserFromAccessIdInToken() {
+    OzoneTokenIdentifier id = getIdentifierInst();
+    Assert.assertEquals("User1", id.getUser().getUserName());
+
+    id.setTokenType(S3AUTHINFO);
+    Assert.assertEquals("User1", id.getUser().getUserName());
+
+    id.setGetUserForAccessId(s -> "modified-" + s);
+    Assert.assertEquals("modified-User1", id.getUser().getUserName());
+
+    id.setGetUserForAccessId(s -> null);
+    Assert.assertEquals("User1", id.getUser().getUserName());
+
+  }
 }
\ No newline at end of file

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

Reply via email to