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

[ozone] branch HDDS-4944 updated: HDDS-5645. Chroot S3 requests for a tenant to their corresponding volume. (#2697)

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

erose 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 7d63fe2  HDDS-5645. Chroot S3 requests for a tenant to their corresponding volume. (#2697)
7d63fe2 is described below

commit 7d63fe2d1f4d1b1608f755c8283f3f623c096fc3
Author: Ethan Rose <33...@users.noreply.github.com>
AuthorDate: Wed Oct 13 11:16:01 2021 -0700

    HDDS-5645. Chroot S3 requests for a tenant to their corresponding volume. (#2697)
---
 .../hadoop/hdds/scm/client/HddsClientUtils.java    |   5 +-
 .../java/org/apache/hadoop/ozone/OzoneConsts.java  |   5 -
 .../apache/hadoop/ozone/client/ObjectStore.java    |  38 +++--
 .../apache/hadoop/ozone/client/OzoneClient.java    |   7 +-
 .../hadoop/ozone/client/OzoneClientFactory.java    |  51 ++++--
 .../ozone/client/protocol/ClientProtocol.java      |   8 +
 .../apache/hadoop/ozone/client/rpc/RpcClient.java  |  10 ++
 .../main/java/org/apache/hadoop/ozone/OmUtils.java |   1 +
 .../hadoop/ozone/om/multitenant/AccessPolicy.java  |  11 +-
 .../multitenant/MultiTenantAccessAuthorizer.java   |  23 +--
 .../MultiTenantAccessAuthorizerDummyPlugin.java    |  98 ++++++-----
 .../MultiTenantAccessAuthorizerRangerPlugin.java   |  36 ++--
 ...incipal.java => OzoneTenantGroupPrincipal.java} |  65 ++++---
 .../ozone/om/multitenant/RangerAccessPolicy.java   |  25 +--
 .../OzoneMultiTenantPrincipalImpl.java             |  77 ---------
 .../ozone/om/protocol/OzoneManagerProtocol.java    |   3 +
 ...OzoneManagerProtocolClientSideTranslatorPB.java |  15 ++
 .../client/rpc/TestOzoneRpcClientAbstract.java     |   6 +-
 ...estMultiTenantAccessAuthorizerRangerPlugin.java |  96 +++++------
 .../om/multitenant/TestMultiTenantVolume.java      | 157 +++++++++++++++++
 .../src/main/proto/OmClientProtocol.proto          |  23 ++-
 .../hadoop/ozone/om/OMMultiTenantManager.java      |  76 +++++----
 .../hadoop/ozone/om/OMMultiTenantManagerImpl.java  | 186 ++++++++++-----------
 .../org/apache/hadoop/ozone/om/OzoneManager.java   |  27 ++-
 .../s3/tenant/OMAssignUserToTenantRequest.java     |  13 +-
 .../protocolPB/OzoneManagerRequestHandler.java     |  15 ++
 .../hadoop/ozone/s3/OzoneClientProducer.java       |  11 +-
 .../hadoop/ozone/s3/endpoint/EndpointBase.java     |  11 +-
 .../hadoop/ozone/s3/endpoint/ObjectEndpoint.java   |  23 +--
 .../hadoop/ozone/client/ObjectStoreStub.java       |  10 +-
 .../hadoop/ozone/client/OzoneBucketStub.java       |  27 ++-
 .../s3/endpoint/TestMultipartUploadWithCopy.java   |   6 +-
 .../hadoop/ozone/s3/endpoint/TestObjectHead.java   |   6 +-
 .../ozone/s3/endpoint/TestPermissionCheck.java     |  17 +-
 34 files changed, 694 insertions(+), 494 deletions(-)

diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java
index 6b74adb..ff52a01 100644
--- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java
+++ b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/client/HddsClientUtils.java
@@ -235,11 +235,12 @@ public final class HddsClientUtils {
   }
 
   /**
-   * Returns the s3VolumeName configured in ConfigurationSource.
+   * Returns the default S3 Volume name configured in ConfigurationSource,
+   * which will be used for S3 buckets that are not part of a tenant.
    * @param conf Configuration object
    * @return s3 volume name
    */
-  public static String getS3VolumeName(ConfigurationSource conf) {
+  public static String getDefaultS3VolumeName(ConfigurationSource conf) {
     return conf.get(OzoneConfigKeys.OZONE_S3_VOLUME_NAME,
             OzoneConfigKeys.OZONE_S3_VOLUME_NAME_DEFAULT);
   }
diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
index 22e8fab..371885a 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
@@ -342,11 +342,6 @@ public final class OzoneConsts {
   public static final String DEFAULT_TENANT_POLICY_ID_SUFFIX = "-default";
   public static final String DEFAULT_TENANT_USER_GROUP_SUFFIX = "-users";
 
-  public static final String DEFAULT_TENANT_GROUP_ALL_ADMINS =
-      "GroupTenantAllAdmins";
-  public static final String DEFAULT_TENANT_GROUP_ALL_USERS =
-      "GroupTenantAllUsers";
-
   // For OM metrics saving to a file
   public static final String OM_METRICS_FILE = "omMetrics";
   public static final String OM_METRICS_TEMP_FILE = OM_METRICS_FILE + ".tmp";
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java
index 81b5101..acc18b7 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java
@@ -60,8 +60,9 @@ public class ObjectStore {
    * Cache size to be used for listVolume calls.
    */
   private int listCacheSize;
-
-  private String s3VolumeName;
+  private final String defaultS3Volume;
+  // TODO: Using for now for multitenancy but remove when HDDS-4440 is merged.
+  private final String accessID;
 
   /**
    * Creates an instance of ObjectStore.
@@ -69,17 +70,24 @@ public class ObjectStore {
    * @param proxy ClientProtocol proxy.
    */
   public ObjectStore(ConfigurationSource conf, ClientProtocol proxy) {
+    this(conf, proxy, null);
+  }
+
+  public ObjectStore(ConfigurationSource conf, ClientProtocol proxy,
+      String accessID) {
     this.proxy = TracingUtil.createProxy(proxy, ClientProtocol.class, conf);
     this.listCacheSize = HddsClientUtils.getListCacheSize(conf);
-    this.s3VolumeName = HddsClientUtils.getS3VolumeName(conf);
+    defaultS3Volume = HddsClientUtils.getDefaultS3VolumeName(conf);
+    this.accessID = accessID;
   }
 
   @VisibleForTesting
   protected ObjectStore() {
     // For the unit test
     OzoneConfiguration conf = new OzoneConfiguration();
-    this.s3VolumeName = HddsClientUtils.getS3VolumeName(conf);
     proxy = null;
+    defaultS3Volume = HddsClientUtils.getDefaultS3VolumeName(conf);
+    this.accessID = null;
   }
 
   @VisibleForTesting
@@ -87,10 +95,6 @@ public class ObjectStore {
     return proxy;
   }
 
-  public String getS3VolumeName() {
-    return s3VolumeName;
-  }
-
   /**
    * Creates the volume with default values.
    * @param volumeName Name of the volume to be created.
@@ -119,12 +123,12 @@ public class ObjectStore {
    */
   public void createS3Bucket(String bucketName) throws
       IOException {
-    OzoneVolume volume = getVolume(s3VolumeName);
+    OzoneVolume volume = getS3Volume();
     volume.createBucket(bucketName);
   }
 
   public OzoneBucket getS3Bucket(String bucketName) throws IOException {
-    return getVolume(s3VolumeName).getBucket(bucketName);
+    return getS3Volume().getBucket(bucketName);
   }
 
   /**
@@ -134,7 +138,7 @@ public class ObjectStore {
    */
   public void deleteS3Bucket(String bucketName) throws IOException {
     try {
-      OzoneVolume volume = getVolume(s3VolumeName);
+      OzoneVolume volume = getS3Volume();
       volume.deleteBucket(bucketName);
     } catch (OMException ex) {
       if (ex.getResult() == OMException.ResultCodes.VOLUME_NOT_FOUND) {
@@ -145,7 +149,6 @@ public class ObjectStore {
     }
   }
 
-
   /**
    * Returns the volume information.
    * @param volumeName Name of the volume.
@@ -153,8 +156,15 @@ public class ObjectStore {
    * @throws IOException
    */
   public OzoneVolume getVolume(String volumeName) throws IOException {
-    OzoneVolume volume = proxy.getVolumeDetails(volumeName);
-    return volume;
+    return proxy.getVolumeDetails(volumeName);
+  }
+
+  public OzoneVolume getS3Volume() throws IOException {
+    if (accessID == null)  {
+      return proxy.getVolumeDetails(defaultS3Volume);
+    } else {
+      return proxy.getS3VolumeDetails(accessID);
+    }
   }
 
   public S3SecretValue getS3Secret(String kerberosID) throws IOException {
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java
index 493315e..bb97ebc 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClient.java
@@ -84,8 +84,13 @@ public class OzoneClient implements Closeable {
    * @param proxy ClientProtocol proxy instance
    */
   public OzoneClient(ConfigurationSource conf, ClientProtocol proxy) {
+    this(conf, proxy, null);
+  }
+
+  public OzoneClient(ConfigurationSource conf, ClientProtocol proxy,
+      String accessID) {
     this.proxy = proxy;
-    this.objectStore = new ObjectStore(conf, this.proxy);
+    this.objectStore = new ObjectStore(conf, this.proxy, accessID);
     this.conf = conf;
   }
 
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java
index 9bf3973..a0cddc3 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneClientFactory.java
@@ -107,10 +107,16 @@ public final class OzoneClientFactory {
    */
   public static OzoneClient getRpcClient(String omServiceId,
       ConfigurationSource config) throws IOException {
+    return getRpcClient(getClientProtocol(config, omServiceId), config, null);
+  }
+
+  public static OzoneClient getRpcClient(String omServiceId,
+      ConfigurationSource config, String accessID) throws IOException {
     Preconditions.checkNotNull(omServiceId);
     Preconditions.checkNotNull(config);
     if (OmUtils.isOmHAServiceId(config, omServiceId)) {
-      return getRpcClient(getClientProtocol(config, omServiceId), config);
+      return getRpcClient(getClientProtocol(config, omServiceId), config,
+          accessID);
     } else {
       throw new IOException("Service ID specified " +
           "does not match with " + OZONE_OM_SERVICE_IDS_KEY + " defined in " +
@@ -119,18 +125,8 @@ public final class OzoneClientFactory {
     }
   }
 
-  /**
-   * Returns an OzoneClient which will use RPC protocol.
-   *
-   * @param config
-   *        used for OzoneClient creation
-   *
-   * @return OzoneClient
-   *
-   * @throws IOException
-   */
-  public static OzoneClient getRpcClient(ConfigurationSource config)
-      throws IOException {
+  public static OzoneClient getRpcClient(ConfigurationSource config,
+        String accessID) throws IOException {
     Preconditions.checkNotNull(config);
 
     // Doing this explicitly so that when service ids are defined in the
@@ -144,13 +140,29 @@ public final class OzoneClientFactory {
           " defined in the configuration. Use the method getRpcClient which " +
           "takes serviceID and configuration as param");
     } else if (serviceIds.length == 1) {
-      return getRpcClient(getClientProtocol(config, serviceIds[0]), config);
+      return getRpcClient(getClientProtocol(config, serviceIds[0]), config,
+          accessID);
     } else {
-      return getRpcClient(getClientProtocol(config), config);
+      return getRpcClient(getClientProtocol(config), config, accessID);
     }
   }
 
   /**
+   * Returns an OzoneClient which will use RPC protocol.
+   *
+   * @param config
+   *        used for OzoneClient creation
+   *
+   * @return OzoneClient
+   *
+   * @throws IOException
+   */
+  public static OzoneClient getRpcClient(ConfigurationSource config)
+      throws IOException {
+    return getRpcClient(config, null);
+  }
+
+  /**
    * Creates OzoneClient with the given ClientProtocol and Configuration.
    *
    * @param clientProtocol
@@ -160,8 +172,13 @@ public final class OzoneClientFactory {
    *        Configuration to be used for OzoneClient creation
    */
   private static OzoneClient getRpcClient(ClientProtocol clientProtocol,
-                                       ConfigurationSource config) {
-    return new OzoneClient(config, clientProtocol);
+      ConfigurationSource config) {
+    return new OzoneClient(config, clientProtocol, null);
+  }
+
+  private static OzoneClient getRpcClient(ClientProtocol clientProtocol,
+      ConfigurationSource config, String accessID) {
+    return new OzoneClient(config, clientProtocol, accessID);
   }
 
   /**
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
index 33dfa3b..69938aa 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
@@ -119,6 +119,14 @@ public interface ClientProtocol {
       throws IOException;
 
   /**
+   * @param accessID
+   * @return The {@link OzoneVolume} that should be used to for this S3
+   * request based on its access ID.
+   * @throws IOException
+   */
+  OzoneVolume getS3VolumeDetails(String accessID) throws IOException;
+
+  /**
    * Checks if a Volume exists and the user with a role specified has access
    * to the Volume.
    * @param volumeName Name of the Volume
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
index 3b2e572..146db37 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
@@ -377,6 +377,16 @@ public class RpcClient implements ClientProtocol {
       throws IOException {
     verifyVolumeName(volumeName);
     OmVolumeArgs volume = ozoneManagerClient.getVolumeInfo(volumeName);
+    return buildOzoneVolume(volume);
+  }
+
+  @Override
+  public OzoneVolume getS3VolumeDetails(String accessID) throws IOException {
+    OmVolumeArgs volume = ozoneManagerClient.getS3Volume(accessID);
+    return buildOzoneVolume(volume);
+  }
+
+  private OzoneVolume buildOzoneVolume(OmVolumeArgs volume) {
     return new OzoneVolume(
         conf,
         this,
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
index 8502744..e9255a3 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
@@ -265,6 +265,7 @@ public final class OmUtils {
     case ListMultipartUploads:
     case FinalizeUpgradeProgress:
     case PrepareStatus:
+    case GetS3Volume:
     case TenantGetUserInfo:
       return true;
     case CreateVolume:
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/AccessPolicy.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/AccessPolicy.java
index 346a848..1eac2ea 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/AccessPolicy.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/AccessPolicy.java
@@ -17,6 +17,7 @@
 package org.apache.hadoop.ozone.om.multitenant;
 
 import java.io.IOException;
+import java.security.Principal;
 import java.util.List;
 
 import org.apache.hadoop.hdds.annotation.InterfaceAudience;
@@ -54,11 +55,11 @@ public interface AccessPolicy {
    */
   class AccessPolicyElem {
     private OzoneObj object;
-    private OzoneMultiTenantPrincipal principal;
+    private Principal principal;
     private ACLType aclType;
     private AccessGrantType grantType;
 
-    public AccessPolicyElem(OzoneObj obj, OzoneMultiTenantPrincipal id,
+    public AccessPolicyElem(OzoneObj obj, Principal id,
                      ACLType acl, AccessGrantType grant) {
       object = obj;
       principal = id;
@@ -70,7 +71,7 @@ public interface AccessPolicy {
       return object;
     }
 
-    public OzoneMultiTenantPrincipal getPrincipal() {
+    public Principal getPrincipal() {
       return principal;
     }
 
@@ -122,11 +123,11 @@ public interface AccessPolicy {
   AccessPolicyType getAccessPolicyType();
 
   void addAccessPolicyElem(OzoneObj object,
-                           OzoneMultiTenantPrincipal principal, ACLType acl,
+                           Principal principal, ACLType acl,
                            AccessGrantType grant) throws IOException;
 
   void removeAccessPolicyElem(OzoneObj object,
-                              OzoneMultiTenantPrincipal principal,
+                              Principal principal,
                               ACLType acl, AccessGrantType grant)
       throws IOException;
 
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizer.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizer.java
index e8d66ea..5f0a9fd 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizer.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizer.java
@@ -27,6 +27,7 @@ import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;
 import org.apache.hadoop.ozone.security.acl.IOzoneObj;
 import org.apache.hadoop.ozone.security.acl.RequestContext;
+import org.apache.http.auth.BasicUserPrincipal;
 
 
 /**
@@ -59,7 +60,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * MultiTenantGateKeeperplugin Implementation. E.g. a Ranger
    * based Implementation can return some ID thats relevant for it.
    */
-  String createUser(OzoneMultiTenantPrincipal principal,
+  String createUser(BasicUserPrincipal principal,
                     List<String> groupIDs) throws Exception;
 
   /**
@@ -67,14 +68,14 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @return Unique userID maintained by the authorizer plugin.
    * @throws Exception
    */
-  String getUserId(OzoneMultiTenantPrincipal principal) throws Exception;
+  String getUserId(BasicUserPrincipal principal) throws Exception;
 
   /**
    * @param principal
    * @return Unique groupID maintained by the authorizer plugin.
    * @throws Exception
    */
-  String getGroupId(OzoneMultiTenantPrincipal principal)
+  String getGroupId(OzoneTenantGroupPrincipal principal)
       throws Exception;
 
   /**
@@ -92,7 +93,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * MultiTenantGateKeeper plugin Implementation e.g. corresponding ID on the
    * Ranger end for a ranger based implementation .
    */
-  String createGroup(OzoneMultiTenantPrincipal group) throws Exception;
+  String createGroup(OzoneTenantGroupPrincipal group) throws Exception;
 
   /**
    * Delete the group groupID in MultiTenantGateKeeper plugin.
@@ -137,7 +138,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @param aclType
    */
   void grantAccess(BucketNameSpace bucketNameSpace,
-                   OzoneMultiTenantPrincipal user, ACLType aclType);
+                   BasicUserPrincipal user, ACLType aclType);
 
   /**
    * Revoke from user aclType access from bucketNameSpace.
@@ -146,7 +147,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @param aclType
    */
   void revokeAccess(BucketNameSpace bucketNameSpace,
-                    OzoneMultiTenantPrincipal user, ACLType aclType);
+                    BasicUserPrincipal user, ACLType aclType);
 
   /**
    * Grant user aclType access to accountNameSpace.
@@ -155,7 +156,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @param aclType
    */
   void grantAccess(AccountNameSpace accountNameSpace,
-                   OzoneMultiTenantPrincipal user,
+                   BasicUserPrincipal user,
                    ACLType aclType);
 
   /**
@@ -165,7 +166,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @param aclType
    */
   void revokeAccess(AccountNameSpace accountNameSpace,
-                    OzoneMultiTenantPrincipal user, ACLType aclType);
+                    BasicUserPrincipal user, ACLType aclType);
 
   /**
    * Return all bucketnamespace accesses granted to user.
@@ -173,7 +174,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @return list of access
    */
   List<Pair<BucketNameSpace, ACLType>> getAllBucketNameSpaceAccesses(
-      OzoneMultiTenantPrincipal user);
+      BasicUserPrincipal user);
 
   /**
    * Checks if the user has access to bucketNameSpace.
@@ -182,7 +183,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @return true if access is granted, false otherwise.
    */
   boolean checkAccess(BucketNameSpace bucketNameSpace,
-                      OzoneMultiTenantPrincipal user);
+                      BasicUserPrincipal user);
 
   /**
    * Checks if the user has access to accountNameSpace.
@@ -191,7 +192,7 @@ public interface MultiTenantAccessAuthorizer extends IAccessAuthorizer {
    * @return true if access is granted, false otherwise.
    */
   boolean checkAccess(AccountNameSpace accountNameSpace,
-                      OzoneMultiTenantPrincipal user);
+                      BasicUserPrincipal user);
 
   /**
    * Check access for given ozoneObject. Access for the object would be
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerDummyPlugin.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerDummyPlugin.java
index 8ab532d..3f23a42 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerDummyPlugin.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerDummyPlugin.java
@@ -22,6 +22,7 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.security.acl.IOzoneObj;
 import org.apache.hadoop.ozone.security.acl.RequestContext;
+import org.apache.http.auth.BasicUserPrincipal;
 
 import java.io.IOException;
 import java.util.List;
@@ -35,97 +36,112 @@ public class MultiTenantAccessAuthorizerDummyPlugin implements
 
   @Override
   public void init(Configuration configuration) throws IOException {
+
   }
 
   @Override
   public void shutdown() throws Exception {
+
   }
 
   @Override
-  public void grantAccess(BucketNameSpace bucketNameSpace,
-                          OzoneMultiTenantPrincipal user, ACLType aclType) {
+  public String createUser(BasicUserPrincipal principal, List<String> groupIDs)
+      throws Exception {
+    return null;
   }
 
   @Override
-  public void revokeAccess(BucketNameSpace bucketNameSpace,
-                           OzoneMultiTenantPrincipal user, ACLType aclType) {
+  public String getUserId(BasicUserPrincipal principal) throws Exception {
+    return null;
   }
 
   @Override
-  public void grantAccess(AccountNameSpace accountNameSpace,
-                          OzoneMultiTenantPrincipal user, ACLType aclType) {
+  public String getGroupId(OzoneTenantGroupPrincipal principal)
+      throws Exception {
+    return null;
   }
 
   @Override
-  public void revokeAccess(AccountNameSpace accountNameSpace,
-                           OzoneMultiTenantPrincipal user, ACLType aclType) {
-  }
+  public void deleteUser(String opaqueUserID) throws IOException {
 
-  public List<Pair<BucketNameSpace, ACLType>>
-      getAllBucketNameSpaceAccesses(OzoneMultiTenantPrincipal user) {
-    return null;
   }
 
   @Override
-  public boolean checkAccess(BucketNameSpace bucketNameSpace,
-                             OzoneMultiTenantPrincipal user) {
-    return true;
+  public String createGroup(OzoneTenantGroupPrincipal group) throws Exception {
+    return null;
   }
 
   @Override
-  public boolean checkAccess(AccountNameSpace accountNameSpace,
-                             OzoneMultiTenantPrincipal user) {
-    return true;
+  public void deleteGroup(String groupID) throws IOException {
+
   }
 
   @Override
-  public boolean checkAccess(IOzoneObj ozoneObject, RequestContext context)
-      throws OMException {
-    return true;
+  public String createAccessPolicy(AccessPolicy policy) throws Exception {
+    return null;
   }
 
   @Override
-  public String getGroupId(OzoneMultiTenantPrincipal principal)
+  public AccessPolicy getAccessPolicyByName(String policyName)
       throws Exception {
-    return "dummyGroupId";
+    return null;
   }
 
   @Override
-  public String getUserId(OzoneMultiTenantPrincipal principal)
-      throws Exception {
-    return "dummyUserId";
+  public void deletePolicybyId(String policyId) throws IOException {
+
   }
 
-  public String createUser(OzoneMultiTenantPrincipal principal,
-                           List<String> groupIDs)
-      throws Exception {
-    return "dummyCreateUser";
+  @Override
+  public void deletePolicybyName(String policyName) throws Exception {
+
   }
 
-  public String createGroup(OzoneMultiTenantPrincipal group) throws Exception {
-    return "dummyCreateGroup";
+  @Override
+  public void grantAccess(BucketNameSpace bucketNameSpace,
+      BasicUserPrincipal user, ACLType aclType) {
+
   }
 
-  public String createAccessPolicy(AccessPolicy policy) throws Exception {
-    return "dummyCreateAccessPolicy";
+  @Override
+  public void revokeAccess(BucketNameSpace bucketNameSpace,
+      BasicUserPrincipal user, ACLType aclType) {
+
   }
 
-  public AccessPolicy getAccessPolicyByName(String policyName)
-      throws Exception {
-    return new RangerAccessPolicy(policyName);
+  @Override
+  public void grantAccess(AccountNameSpace accountNameSpace,
+      BasicUserPrincipal user, ACLType aclType) {
+
   }
 
-  public void deleteUser(String userId) throws IOException {
+  @Override
+  public void revokeAccess(AccountNameSpace accountNameSpace,
+      BasicUserPrincipal user, ACLType aclType) {
+
   }
 
-  public void deleteGroup(String groupId) throws IOException {
+  @Override
+  public List<Pair<BucketNameSpace, ACLType>> getAllBucketNameSpaceAccesses(
+      BasicUserPrincipal user) {
+    return null;
   }
 
   @Override
-  public void deletePolicybyName(String policyName) throws Exception {
+  public boolean checkAccess(BucketNameSpace bucketNameSpace,
+      BasicUserPrincipal user) {
+    return false;
   }
 
-  public void deletePolicybyId(String policyId) throws IOException {
+  @Override
+  public boolean checkAccess(AccountNameSpace accountNameSpace,
+      BasicUserPrincipal user) {
+    return false;
   }
 
+  @Override
+  public boolean checkAccess(IOzoneObj ozoneObject, RequestContext context)
+      throws OMException {
+    return false;
+  }
 }
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerRangerPlugin.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerRangerPlugin.java
index 86c44f6..94a31dd 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerRangerPlugin.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessAuthorizerRangerPlugin.java
@@ -63,6 +63,7 @@ import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.security.acl.IOzoneObj;
 import org.apache.hadoop.ozone.security.acl.RequestContext;
 import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.http.auth.BasicUserPrincipal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -158,44 +159,44 @@ public class MultiTenantAccessAuthorizerRangerPlugin implements
 
   @Override
   public void grantAccess(BucketNameSpace bucketNameSpace,
-                          OzoneMultiTenantPrincipal user, ACLType aclType) {
+                          BasicUserPrincipal user, ACLType aclType) {
     // TBD
   }
 
   @Override
   public void revokeAccess(BucketNameSpace bucketNameSpace,
-                           OzoneMultiTenantPrincipal user, ACLType aclType) {
+                           BasicUserPrincipal user, ACLType aclType) {
     // TBD
   }
 
   @Override
   public void grantAccess(AccountNameSpace accountNameSpace,
-                          OzoneMultiTenantPrincipal user, ACLType aclType) {
+                          BasicUserPrincipal user, ACLType aclType) {
     // TBD
   }
 
   @Override
   public void revokeAccess(AccountNameSpace accountNameSpace,
-                           OzoneMultiTenantPrincipal user, ACLType aclType) {
+                           BasicUserPrincipal user, ACLType aclType) {
     // TBD
   }
 
   public List<Pair<BucketNameSpace, ACLType>>
-      getAllBucketNameSpaceAccesses(OzoneMultiTenantPrincipal user) {
+      getAllBucketNameSpaceAccesses(BasicUserPrincipal user) {
     // TBD
     return null;
   }
 
   @Override
   public boolean checkAccess(BucketNameSpace bucketNameSpace,
-                             OzoneMultiTenantPrincipal user) {
+                             BasicUserPrincipal user) {
     // TBD
     return true;
   }
 
   @Override
   public boolean checkAccess(AccountNameSpace accountNameSpace,
-                             OzoneMultiTenantPrincipal user) {
+                             BasicUserPrincipal user) {
     // TBD
     return true;
   }
@@ -222,11 +223,11 @@ public class MultiTenantAccessAuthorizerRangerPlugin implements
   }
 
   @Override
-  public String getGroupId(OzoneMultiTenantPrincipal principal)
+  public String getGroupId(OzoneTenantGroupPrincipal principal)
       throws Exception {
     String rangerAdminUrl =
         rangerHttpsAddress + OZONE_OM_RANGER_ADMIN_GET_GROUP_HTTP_ENDPOINT +
-            principal.getFullMultiTenantPrincipalID();
+            principal.getName();
 
     HttpsURLConnection conn = makeHttpsGetCall(rangerAdminUrl,
         "GET", false);
@@ -238,7 +239,7 @@ public class MultiTenantAccessAuthorizerRangerPlugin implements
       int numIndex = info.size();
       for (int i = 0; i < numIndex; ++i) {
         if (info.get(i).getAsJsonObject().get("name").getAsString()
-            .equals(principal.getFullMultiTenantPrincipalID())) {
+            .equals(principal.getName())) {
           groupIDCreated =
               info.get(i).getAsJsonObject().get("id").getAsString();
           break;
@@ -253,11 +254,11 @@ public class MultiTenantAccessAuthorizerRangerPlugin implements
   }
 
   @Override
-  public String getUserId(OzoneMultiTenantPrincipal principal)
+  public String getUserId(BasicUserPrincipal principal)
       throws Exception {
     String rangerAdminUrl =
         rangerHttpsAddress + OZONE_OM_RANGER_ADMIN_GET_USER_HTTP_ENDPOINT +
-        principal.getFullMultiTenantPrincipalID();
+        principal.getName();
 
     HttpsURLConnection conn = makeHttpsGetCall(rangerAdminUrl,
         "GET", false);
@@ -269,7 +270,7 @@ public class MultiTenantAccessAuthorizerRangerPlugin implements
       int numIndex = userinfo.size();
       for (int i = 0; i < numIndex; ++i) {
         if (userinfo.get(i).getAsJsonObject().get("name").getAsString()
-            .equals(principal.getFullMultiTenantPrincipalID())) {
+            .equals(principal.getName())) {
           userIDCreated =
               userinfo.get(i).getAsJsonObject().get("id").getAsString();
           break;
@@ -283,14 +284,14 @@ public class MultiTenantAccessAuthorizerRangerPlugin implements
     return userIDCreated;
   }
 
-  public String createUser(OzoneMultiTenantPrincipal principal,
+  public String createUser(BasicUserPrincipal principal,
                            List<String> groupIDs)
       throws Exception {
     String rangerAdminUrl =
         rangerHttpsAddress + OZONE_OM_RANGER_ADMIN_CREATE_USER_HTTP_ENDPOINT;
 
     String jsonCreateUserString = getCreateUserJsonString(
-        principal.getFullMultiTenantPrincipalID(), groupIDs);
+        principal.getName(), groupIDs);
 
     HttpsURLConnection conn = makeHttpsPostCall(rangerAdminUrl,
         jsonCreateUserString, "POST", false);
@@ -315,12 +316,11 @@ public class MultiTenantAccessAuthorizerRangerPlugin implements
   }
 
 
-  public String createGroup(OzoneMultiTenantPrincipal group) throws Exception {
+  public String createGroup(OzoneTenantGroupPrincipal group) throws Exception {
     String rangerAdminUrl =
         rangerHttpsAddress + OZONE_OM_RANGER_ADMIN_CREATE_GROUP_HTTP_ENDPOINT;
 
-    String jsonCreateGroupString = getCreateGroupJsonString(
-        group.getFullMultiTenantPrincipalID());
+    String jsonCreateGroupString = getCreateGroupJsonString(group.toString());
 
     HttpsURLConnection conn = makeHttpsPostCall(rangerAdminUrl,
         jsonCreateGroupString,
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/OzoneMultiTenantPrincipal.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/OzoneTenantGroupPrincipal.java
similarity index 50%
rename from hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/OzoneMultiTenantPrincipal.java
rename to hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/OzoneTenantGroupPrincipal.java
index eb399ed..c264ad7 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/OzoneMultiTenantPrincipal.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/OzoneTenantGroupPrincipal.java
@@ -17,45 +17,40 @@
  */
 package org.apache.hadoop.ozone.om.multitenant;
 
+import org.apache.hadoop.ozone.OzoneConsts;
 import java.security.Principal;
 
 /**
- * OzoneMultiTenantPrincipal interface.
+ * Used to identify a tenant's group in Ranger.
  */
-public interface OzoneMultiTenantPrincipal {
-
-  /**
-   * Two types of Ozone principal.
-   */
-  enum OzonePrincipalType{USER_PRINCIPAL, GROUP_PRINCIPAL};
-
-  /**
-   * @return Principal(access-id) representing the multiTenantUser including
-   * any Tenant AccountNameSpace qualification.
-   */
-  Principal getPrincipal();
-
-  /**
-   * @return full String ID of the MultiTenantPrincipal
-   */
-  String getFullMultiTenantPrincipalID();
-
-  /**
-   * @return plain TenantID part
-   */
-  String getTenantID();
-
-  /**
-   * @return plain userID part
-   */
-  String getUserID();
-
-  /**
-   *
-   * @return Whether this principal represents a User or a group.
-   */
-  OzonePrincipalType getUserPrincipalType();
+public final class OzoneTenantGroupPrincipal implements Principal {
+  private final String tenantID;
+  private final String groupName;
+
+  public static OzoneTenantGroupPrincipal newUserGroup(String tenantID) {
+    return new OzoneTenantGroupPrincipal(tenantID, "GroupTenantAllUsers");
+  }
+
+  public static OzoneTenantGroupPrincipal newAdminGroup(String tenantID) {
+    return new OzoneTenantGroupPrincipal(tenantID, "GroupTenantAllAdmins");
+  }
+
+  private OzoneTenantGroupPrincipal(String tenantID, String groupName) {
+    this.tenantID = tenantID;
+    this.groupName = groupName;
+  }
+
+  public String getTenantID() {
+    return tenantID;
+  }
+
+  @Override
+  public String toString() {
+    return getName();
+  }
 
   @Override
-  String toString();
+  public String getName() {
+    return tenantID + OzoneConsts.TENANT_NAME_USER_NAME_DELIMITER + groupName;
+  }
 }
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerAccessPolicy.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerAccessPolicy.java
index f2ca425..113bd99 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerAccessPolicy.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerAccessPolicy.java
@@ -22,6 +22,7 @@ import org.apache.hadoop.ozone.security.acl.OzoneObj;
 import com.google.gson.JsonObject;
 
 import java.io.IOException;
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -29,7 +30,6 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import static org.apache.hadoop.ozone.om.multitenant.AccessPolicy.AccessPolicyType.RANGER_POLICY;
-import static org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal.OzonePrincipalType.GROUP_PRINCIPAL;
 
 /**
  * This is used for Ozone tenant access policy control.
@@ -81,7 +81,7 @@ public class RangerAccessPolicy implements AccessPolicy {
 
   @Override
   public void addAccessPolicyElem(OzoneObj object,
-                                  OzoneMultiTenantPrincipal principal,
+                                  Principal principal,
                                   ACLType acl, AccessGrantType grant)
       throws IOException {
     if (accessObject == null) {
@@ -91,17 +91,17 @@ public class RangerAccessPolicy implements AccessPolicy {
           "RangerAccessPolicy supports only one object per" + " policy");
     }
     AccessPolicyElem elem = new AccessPolicyElem(object, principal, acl, grant);
-    if (!policyMap.containsKey(principal.toString())) {
+    if (!policyMap.containsKey(principal.getName())) {
       List<AccessPolicyElem> elemList = new ArrayList<>();
       elemList.add(elem);
-      policyMap.put(principal.toString(), elemList);
+      policyMap.put(principal.getName(), elemList);
       return;
     }
-    List<AccessPolicyElem> elemList = policyMap.get(principal.toString());
+    List<AccessPolicyElem> elemList = policyMap.get(principal.getName());
     for (AccessPolicyElem e : elemList) {
       if (e.getAclType() == acl) {
         throw new IOException(
-            "RangerAccessPolicy: Principal " + principal.toString()
+            "RangerAccessPolicy: Principal " + principal.getName()
                 + " already exists with access " + acl);
       }
     }
@@ -118,8 +118,10 @@ public class RangerAccessPolicy implements AccessPolicy {
     return list;
   }
 
-  @Override public void removeAccessPolicyElem(OzoneObj object,
-      OzoneMultiTenantPrincipal principal, ACLType acl, AccessGrantType grant)
+  @Override
+  public void removeAccessPolicyElem(OzoneObj object,
+                                     Principal principal, ACLType acl,
+                                     AccessGrantType grant)
       throws IOException {
     if (accessObject == null) {
       throw new IOException("removeAccessPolicyElem: Invalid Arguments.");
@@ -127,11 +129,11 @@ public class RangerAccessPolicy implements AccessPolicy {
       throw new IOException(
           "removeAccessPolicyElem:  Object not found." + object.toString());
     }
-    if (!policyMap.containsKey(principal.toString())) {
+    if (!policyMap.containsKey(principal.getName())) {
       throw new IOException(
           "removeAccessPolicyElem:  Principal not found." + object.toString());
     }
-    List<AccessPolicyElem> elemList = policyMap.get(principal.toString());
+    List<AccessPolicyElem> elemList = policyMap.get(principal.getName());
     for (AccessPolicyElem e : elemList) {
       if (e.getAclType() == acl) {
         elemList.remove(e);
@@ -190,8 +192,7 @@ public class RangerAccessPolicy implements AccessPolicy {
         continue;
       }
       policyItems.append("{");
-      if (list.get(0).getPrincipal().getUserPrincipalType()
-          == GROUP_PRINCIPAL) {
+      if (list.get(0).getPrincipal() instanceof OzoneTenantGroupPrincipal) {
         policyItems.append("\"groups\":[\"" + mapElem.getKey() + "\"],");
       } else {
         policyItems.append("\"users\":[\"" + mapElem.getKey() + "\"],");
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenantImpl/OzoneMultiTenantPrincipalImpl.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenantImpl/OzoneMultiTenantPrincipalImpl.java
deleted file mode 100644
index 03e49f6..0000000
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/multitenantImpl/OzoneMultiTenantPrincipalImpl.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.hadoop.ozone.om.multitenantImpl;
-
-import static org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal.OzonePrincipalType.USER_PRINCIPAL;
-
-import java.security.Principal;
-
-import org.apache.hadoop.ozone.OzoneConsts;
-import org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal;
-import org.apache.http.auth.BasicUserPrincipal;
-
-/**
- * Implements OzoneMultiTenantPrincipal.
- */
-public class OzoneMultiTenantPrincipalImpl
-    implements OzoneMultiTenantPrincipal {
-
-  // TODO: This separator should come from Ozone Config.
-  private static final String TENANT_ID_SEPARATOR =
-      OzoneConsts.TENANT_NAME_USER_NAME_DELIMITER;
-  private OzonePrincipalType  principalType = USER_PRINCIPAL;
-  private Principal principalUserIDPart;
-  private Principal principalTenantIDPart;
-
-  public OzoneMultiTenantPrincipalImpl(Principal tenant, Principal user,
-      OzonePrincipalType type) {
-    principalTenantIDPart = tenant;
-    principalUserIDPart = user;
-    principalType = type;
-  }
-
-  @Override
-  public String getFullMultiTenantPrincipalID() {
-    return getTenantID() + TENANT_ID_SEPARATOR + getUserID();
-  }
-
-  @Override
-  public Principal getPrincipal() {
-    return new BasicUserPrincipal(getFullMultiTenantPrincipalID());
-  }
-
-  @Override
-  public String getTenantID() {
-    return principalTenantIDPart.getName();
-  }
-
-  @Override
-  public String getUserID() {
-    return principalUserIDPart.getName();
-  }
-
-  @Override
-  public OzonePrincipalType getUserPrincipalType() {
-    return principalType;
-  }
-
-  @Override
-  public String toString() {
-    return getFullMultiTenantPrincipalID();
-  }
-}
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
index ceae46b..ae5f276 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
@@ -475,6 +475,9 @@ public interface OzoneManagerProtocol
   S3SecretValue assignUserToTenant(String username, String tenantName,
       String accessId) throws IOException;
 
+  OmVolumeArgs getS3Volume(String accessID) throws IOException;
+
+  // TODO: modify, delete
   /**
    * Get tenant info for a user.
    * @param userPrincipal Kerberos principal of a user.
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
index 2b82c4b..94b1c9b 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
@@ -941,6 +941,21 @@ public final class OzoneManagerProtocolClientSideTranslatorPB
     return TenantUserInfoValue.fromProtobuf(resp.getTenantUserInfo());
   }
 
+  @Override
+  public OmVolumeArgs getS3Volume(String accessID) throws IOException {
+    final GetS3VolumeRequest request = GetS3VolumeRequest.newBuilder()
+        .setAccessID(accessID)
+        .build();
+    final OMRequest omRequest = createOMRequest(Type.GetS3Volume)
+        .setGetS3VolumeRequest(request)
+        .build();
+    final OMResponse omResponse = submitRequest(omRequest);
+    final GetS3VolumeResponse resp = handleError(omResponse)
+        .getGetS3VolumeResponse();
+
+    return OmVolumeArgs.getFromProtobuf(resp.getVolumeInfo());
+  }
+
   /**
    * Return the proxy object underlying this protocol translator.
    *
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java
index f2fc945..93fdac4 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java
@@ -266,7 +266,8 @@ public abstract class TestOzoneRpcClientAbstract {
 
   @Test
   public void testDefaultS3GVolumeExists() throws Exception {
-    String s3VolumeName = HddsClientUtils.getS3VolumeName(cluster.getConf());
+    String s3VolumeName =
+        HddsClientUtils.getDefaultS3VolumeName(cluster.getConf());
     OzoneVolume ozoneVolume = store.getVolume(s3VolumeName);
     Assert.assertEquals(ozoneVolume.getName(), s3VolumeName);
     OMMetadataManager omMetadataManager =
@@ -3586,7 +3587,8 @@ public abstract class TestOzoneRpcClientAbstract {
   @Test
   public void testSetS3VolumeAcl() throws Exception {
     OzoneObj s3vVolume = new OzoneObjInfo.Builder()
-        .setVolumeName(HddsClientUtils.getS3VolumeName(cluster.getConf()))
+        .setVolumeName(
+            HddsClientUtils.getDefaultS3VolumeName(cluster.getConf()))
         .setResType(OzoneObj.ResourceType.VOLUME)
         .setStoreType(OzoneObj.StoreType.OZONE)
         .build();
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantAccessAuthorizerRangerPlugin.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantAccessAuthorizerRangerPlugin.java
index 065a434..aa28900 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantAccessAuthorizerRangerPlugin.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantAccessAuthorizerRangerPlugin.java
@@ -20,8 +20,6 @@ import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_RANGER_HTTPS_ADMI
 import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_RANGER_HTTPS_ADMIN_API_USER;
 import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_RANGER_HTTPS_ADDRESS_KEY;
 import static org.apache.hadoop.ozone.om.multitenant.AccessPolicy.AccessGrantType.ALLOW;
-import static org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal.OzonePrincipalType.GROUP_PRINCIPAL;
-import static org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal.OzonePrincipalType.USER_PRINCIPAL;
 import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.CREATE;
 import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.LIST;
 import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.NONE;
@@ -37,7 +35,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
-import org.apache.hadoop.ozone.om.multitenantImpl.OzoneMultiTenantPrincipalImpl;
 import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType;
 import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
 import org.apache.http.auth.BasicUserPrincipal;
@@ -102,31 +99,31 @@ public class TestMultiTenantAccessAuthorizerRangerPlugin {
     omm.init(conf);
 
     try {
-      OzoneMultiTenantPrincipal group1Principal = getTestPrincipal("tenant1",
-          "groupTestAdmin", GROUP_PRINCIPAL);
-      OzoneMultiTenantPrincipal group2Principal = getTestPrincipal("tenant1",
-          "groupTestUsers", GROUP_PRINCIPAL);
+      OzoneTenantGroupPrincipal group1Principal =
+          OzoneTenantGroupPrincipal.newAdminGroup("tenant1");
+      OzoneTenantGroupPrincipal group2Principal =
+          OzoneTenantGroupPrincipal.newUserGroup("tenant1");
       groupIdsCreated.add(omm.createGroup(group1Principal));
       groupIdsCreated.add(omm.createGroup(group2Principal));
 
-      OzoneMultiTenantPrincipal userPrincipal =
-          getTestPrincipal("tenant1", "user1Test", USER_PRINCIPAL);
+      BasicUserPrincipal userPrincipal =
+          new BasicUserPrincipal("user1Test");
       usersIdsCreated.add(omm.createUser(userPrincipal, groupIdsCreated));
 
       AccessPolicy tenant1VolumeAccessPolicy = createVolumeAccessPolicy(
-          "vol1", "tenant1", "Users");
+          "vol1", "tenant1");
       policyIdsCreated.add(omm.createAccessPolicy(tenant1VolumeAccessPolicy));
 
       AccessPolicy tenant1BucketCreatePolicy = allowCreateBucketPolicy(
-          "vol1", "tenant1", "Users");
+          "vol1", "tenant1");
       policyIdsCreated.add(omm.createAccessPolicy(tenant1BucketCreatePolicy));
 
       AccessPolicy tenant1BucketAccessPolicy = allowAccessBucketPolicy(
-          "vol1", "tenant1", "Users", "bucket1");
+          "vol1", "bucket1", "tenant1");
       policyIdsCreated.add(omm.createAccessPolicy(tenant1BucketAccessPolicy));
 
       AccessPolicy tenant1KeyAccessPolicy = allowAccessKeyPolicy(
-          "vol1", "tenant1", "Users", "bucket1");
+          "vol1", "bucket1", "tenant1");
       policyIdsCreated.add(omm.createAccessPolicy(tenant1KeyAccessPolicy));
 
     } catch (Exception e) {
@@ -148,7 +145,7 @@ public class TestMultiTenantAccessAuthorizerRangerPlugin {
   @Ignore("TODO:Requires (mocked) Ranger endpoint")
   public void testMultiTenantAccessAuthorizerRangerPluginWithoutIds()
       throws Exception {
-    OzoneMultiTenantPrincipal userPrincipal = null;
+    BasicUserPrincipal userPrincipal = null;
     simulateOzoneSiteXmlConfig();
     final MultiTenantAccessAuthorizer omm =
         new MultiTenantAccessAuthorizerRangerPlugin();
@@ -156,36 +153,35 @@ public class TestMultiTenantAccessAuthorizerRangerPlugin {
 
     try {
       Assert.assertTrue(policyIdsCreated.size() == 0);
-      OzoneMultiTenantPrincipal group1Principal = getTestPrincipal("tenant1",
-          "groupTestAdmin", GROUP_PRINCIPAL);
-      OzoneMultiTenantPrincipal group2Principal = getTestPrincipal("tenant1",
-          "groupTestUsers", GROUP_PRINCIPAL);
+      OzoneTenantGroupPrincipal group1Principal =
+          OzoneTenantGroupPrincipal.newAdminGroup("tenant1");
+      OzoneTenantGroupPrincipal group2Principal =
+          OzoneTenantGroupPrincipal.newUserGroup("tenant1");
       omm.createGroup(group1Principal);
       groupIdsCreated.add(omm.getGroupId(group1Principal));
       omm.createGroup(group2Principal);
       groupIdsCreated.add(omm.getGroupId(group2Principal));
 
-      userPrincipal =
-          getTestPrincipal("tenant1", "user1Test", USER_PRINCIPAL);
+      userPrincipal = new BasicUserPrincipal("user1Test");
       omm.createUser(userPrincipal, groupIdsCreated);
 
       AccessPolicy tenant1VolumeAccessPolicy = createVolumeAccessPolicy(
-          "vol1", "tenant1", "Users");
+          "vol1", "tenant1");
       omm.createAccessPolicy(tenant1VolumeAccessPolicy);
       policyIdsCreated.add(tenant1VolumeAccessPolicy.getPolicyName());
 
       AccessPolicy tenant1BucketCreatePolicy = allowCreateBucketPolicy(
-          "vol1", "tenant1", "Users");
+          "vol1", "tenant1");
       omm.createAccessPolicy(tenant1BucketCreatePolicy);
       policyIdsCreated.add(tenant1BucketCreatePolicy.getPolicyName());
 
       AccessPolicy tenant1BucketAccessPolicy = allowAccessBucketPolicy(
-          "vol1", "tenant1", "Users", "bucket1");
+          "vol1", "bucket1", "tenant1");
       omm.createAccessPolicy(tenant1BucketAccessPolicy);
       policyIdsCreated.add(tenant1BucketAccessPolicy.getPolicyName());
 
       AccessPolicy tenant1KeyAccessPolicy = allowAccessKeyPolicy(
-          "vol1", "tenant1", "Users", "bucket1");
+          "vol1", "bucket1", "tenant1");
       omm.createAccessPolicy(tenant1KeyAccessPolicy);
       policyIdsCreated.add(tenant1KeyAccessPolicy.getPolicyName());
 
@@ -203,23 +199,15 @@ public class TestMultiTenantAccessAuthorizerRangerPlugin {
     }
   }
 
-  private OzoneMultiTenantPrincipal getTestPrincipal(String tenant, String id,
-      OzoneMultiTenantPrincipal.OzonePrincipalType type) {
-    OzoneMultiTenantPrincipal principal = new OzoneMultiTenantPrincipalImpl(
-        new BasicUserPrincipal(tenant),
-        new BasicUserPrincipal(id), type);
-    return principal;
-  }
-
-  private AccessPolicy createVolumeAccessPolicy(String vol, String tenant,
-                                        String group) throws IOException {
+  private AccessPolicy createVolumeAccessPolicy(String vol, String tenant)
+      throws IOException {
+    OzoneTenantGroupPrincipal principal =
+        OzoneTenantGroupPrincipal.newUserGroup(tenant);
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "VolumeAccess" + vol + "Policy");
+        principal.getName() + "VolumeAccess" + vol + "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(VOLUME).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName("").setKeyName("").build();
-    OzoneMultiTenantPrincipal principal = getTestPrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, READ, ALLOW);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, LIST, ALLOW);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal,
@@ -227,29 +215,29 @@ public class TestMultiTenantAccessAuthorizerRangerPlugin {
     return tenantVolumeAccessPolicy;
   }
 
-  private AccessPolicy allowCreateBucketPolicy(String vol, String tenant,
-                                       String group) throws IOException {
+  private AccessPolicy allowCreateBucketPolicy(String vol, String tenant)
+      throws IOException {
+    OzoneTenantGroupPrincipal principal =
+        OzoneTenantGroupPrincipal.newUserGroup(tenant);
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "AllowBucketCreate" + vol + "Policy");
+        principal.getName() + "AllowBucketCreate" + vol + "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(BUCKET).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName("*").setKeyName("").build();
-    OzoneMultiTenantPrincipal principal = getTestPrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, CREATE, ALLOW);
     return tenantVolumeAccessPolicy;
   }
 
-  private AccessPolicy allowAccessBucketPolicy(String vol, String tenant,
-                                       String group, String bucketName)
-      throws IOException {
+  private AccessPolicy allowAccessBucketPolicy(String vol, String bucketName,
+      String tenant) throws IOException {
+    OzoneTenantGroupPrincipal principal =
+        OzoneTenantGroupPrincipal.newUserGroup(tenant);
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "AllowBucketAccess" + vol + bucketName + "Policy");
+        principal.getName() + "AllowBucketAccess" + vol + bucketName +
+            "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(BUCKET).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName(bucketName).setKeyName("*").build();
-    OzoneMultiTenantPrincipal principal = getTestPrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     for (ACLType acl :ACLType.values()) {
       if (acl != NONE) {
         tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, acl,
@@ -259,16 +247,16 @@ public class TestMultiTenantAccessAuthorizerRangerPlugin {
     return tenantVolumeAccessPolicy;
   }
 
-  private AccessPolicy allowAccessKeyPolicy(String vol, String tenant,
-                                    String group, String bucketName)
-      throws IOException {
+  private AccessPolicy allowAccessKeyPolicy(String vol, String bucketName,
+      String tenant) throws IOException {
+    OzoneTenantGroupPrincipal principal =
+        OzoneTenantGroupPrincipal.newUserGroup(tenant);
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "AllowBucketKeyAccess" + vol + bucketName + "Policy");
+        principal.getName() + "AllowBucketKeyAccess" + vol + bucketName +
+            "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(KEY).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName(bucketName).setKeyName("*").build();
-    OzoneMultiTenantPrincipal principal = getTestPrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     for (ACLType acl :ACLType.values()) {
       if (acl != NONE) {
         tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, acl,
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantVolume.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantVolume.java
new file mode 100644
index 0000000..2bca0aa
--- /dev/null
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantVolume.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.ozone.om.multitenant;
+
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
+import org.apache.hadoop.ozone.MiniOzoneCluster;
+import org.apache.hadoop.ozone.MiniOzoneClusterProvider;
+import org.apache.hadoop.ozone.client.ObjectStore;
+import org.apache.hadoop.ozone.client.OzoneBucket;
+import org.apache.hadoop.ozone.client.OzoneVolume;
+import org.apache.hadoop.ozone.client.rpc.RpcClient;
+import org.apache.hadoop.ozone.om.OMMultiTenantManagerImpl;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+
+import java.util.UUID;
+
+/**
+ * Tests that S3 requests for a tenant are directed to that tenant's volume,
+ * and that users not belonging to a tenant are directed to the default S3
+ * volume.
+ */
+public class TestMultiTenantVolume {
+  private static MiniOzoneClusterProvider clusterProvider;
+  private MiniOzoneCluster cluster;
+  private static String s3VolumeName;
+
+  @BeforeClass
+  public static void initClusterProvider() {
+    OzoneConfiguration conf = new OzoneConfiguration();
+    conf.setBoolean(
+        OMMultiTenantManagerImpl.OZONE_OM_TENANT_DEV_SKIP_RANGER, true);
+    MiniOzoneCluster.Builder builder = MiniOzoneCluster.newBuilder(conf)
+        .withoutDatanodes();
+    clusterProvider = new MiniOzoneClusterProvider(conf, builder, 2);
+    s3VolumeName = HddsClientUtils.getDefaultS3VolumeName(conf);
+  }
+
+  @Before
+  public void setup() throws Exception {
+    cluster = clusterProvider.provide();
+  }
+
+  @After
+  public void teardown() throws Exception {
+    clusterProvider.destroy(cluster);
+  }
+
+  @AfterAll
+  public static void shutdownClusterProvider() throws Exception {
+    clusterProvider.shutdown();
+  }
+
+  @Test
+  public void testDefaultS3Volume() throws Exception {
+    final String bucketName = "bucket";
+
+    // Default client not belonging to a tenant should end up in the S3 volume.
+    ObjectStore store = cluster.getClient().getObjectStore();
+    Assert.assertEquals(s3VolumeName, store.getS3Volume().getName());
+
+    // Create bucket.
+    store.createS3Bucket(bucketName);
+    Assert.assertEquals(s3VolumeName,
+        store.getS3Bucket(bucketName).getVolumeName());
+
+    // Delete bucket.
+    store.deleteS3Bucket(bucketName);
+    assertS3BucketNotFound(store, bucketName);
+  }
+
+  @Test
+  public void testS3TenantVolume() throws Exception {
+    final String tenant = "tenant";
+    final String principal = "username";
+    final String bucketName = "bucket";
+    final String accessID = UUID.randomUUID().toString();
+
+    ObjectStore store = getStoreForAccessID(accessID);
+    store.createTenant(tenant);
+    store.assignUserToTenant(principal, tenant, accessID);
+
+    // S3 volume pointed to by the store should be for the tenant.
+    Assert.assertEquals(tenant, store.getS3Volume().getName());
+
+    // Create bucket in the tenant volume.
+    store.createS3Bucket(bucketName);
+    OzoneBucket bucket = store.getS3Bucket(bucketName);
+    Assert.assertEquals(tenant, bucket.getVolumeName());
+
+    // A different user should not see bucket, since they will be directed to
+    // the s3 volume.
+    ObjectStore store2 = getStoreForAccessID(UUID.randomUUID().toString());
+    assertS3BucketNotFound(store2, bucketName);
+
+    // Delete bucket.
+    store.deleteS3Bucket(bucketName);
+    assertS3BucketNotFound(store, bucketName);
+  }
+
+  /**
+   * Checks that the bucket is not found using
+   * {@link ObjectStore#getS3Bucket} and the designated S3 volume pointed to
+   * by the ObjectStore.
+   */
+  private void assertS3BucketNotFound(ObjectStore store, String bucketName)
+      throws Exception {
+    try {
+      store.getS3Bucket(bucketName);
+    } catch(OMException ex) {
+      if (ex.getResult() != OMException.ResultCodes.BUCKET_NOT_FOUND) {
+        throw ex;
+      }
+    }
+
+    try {
+      OzoneVolume volume = store.getS3Volume();
+      volume.getBucket(bucketName);
+    } catch(OMException ex) {
+      if (ex.getResult() != OMException.ResultCodes.BUCKET_NOT_FOUND) {
+        throw ex;
+      }
+    }
+  }
+
+  private ObjectStore getStoreForAccessID(String accessID) throws Exception {
+    // Cluster provider will modify our provided configuration. We must use
+    // this version to build the client.
+    OzoneConfiguration conf = cluster.getOzoneManager().getConfiguration();
+    // Manually construct an object store instead of using the cluster
+    // provided one so we can specify the access ID.
+    // TODO: Update after HDDS-4440 is merged and this is not necessary.
+    return new ObjectStore(conf, new RpcClient(conf, null),
+        accessID);
+  }
+}
diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 916427a..296b4ca 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -110,6 +110,7 @@ enum Type {
   TenantGetUserInfo = 98;
   AssignUserToTenant = 99;
   RevokeUserAccessToTenant = 100;
+  GetS3Volume = 101;
 }
 
 message OMRequest {
@@ -193,13 +194,14 @@ message OMRequest {
 
   optional PurgePathsRequest                purgePathsRequest              = 94;
 
-  optional CreateTenantRequest              CreateTenantRequest            = 95;
-  optional ModifyTenantRequest              ModifyTenantRequest            = 96;
-  optional DeleteTenantRequest              DeleteTenantRequest            = 97;
+  optional CreateTenantRequest              createTenantRequest            = 95;
+  optional ModifyTenantRequest              modifyTenantRequest            = 96;
+  optional DeleteTenantRequest              deleteTenantRequest            = 97;
 
   optional TenantGetUserInfoRequest         TenantGetUserInfoRequest       = 98;
   optional AssignUserToTenantRequest        AssignUserToTenantRequest      = 99;
   optional RevokeUserAccessToTenantRequest  RevokeUserAccessToTenantRequest = 100;
+  optional GetS3VolumeRequest               getS3VolumeRequest             = 101;
 }
 
 message OMResponse {
@@ -278,13 +280,14 @@ message OMResponse {
   optional PurgePathsResponse                 purgePathsResponse           = 93;
 
   // Skipped 94 to align with OMRequest
-  optional CreateTenantResponse              CreateTenantResponse          = 95;
-  optional ModifyTenantResponse              ModifyTenantResponse          = 96;
-  optional DeleteTenantResponse              DeleteTenantResponse          = 97;
+  optional CreateTenantResponse              createTenantResponse          = 95;
+  optional ModifyTenantResponse              modifyTenantResponse          = 96;
+  optional DeleteTenantResponse              deleteTenantResponse          = 97;
 
   optional TenantGetUserInfoResponse         TenantGetUserInfoResponse     = 98;
   optional AssignUserToTenantResponse        AssignUserToTenantResponse    = 99;
   optional RevokeUserAccessToTenantResponse  RevokeUserAccessToTenantResponse = 100;
+  optional GetS3VolumeResponse               getS3VolumeResponse           = 101;
 }
 
 enum Status {
@@ -1410,6 +1413,10 @@ message RevokeUserAccessToTenantRequest {
     optional string tenantName = 2;
 }
 
+message GetS3VolumeRequest {
+  optional string accessID = 1;
+}
+
 message CreateTenantResponse {
     optional bool success = 1;
 }
@@ -1431,6 +1438,10 @@ message RevokeUserAccessToTenantResponse {
     optional bool success = 1;
 }
 
+message GetS3VolumeResponse {
+  optional VolumeInfo volumeInfo = 1;
+}
+
 /**
   This will be used internally by OM to replicate S3 Secret across quorum of
   OM's.
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 ccae7f9..6621417 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
@@ -24,8 +24,8 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.ozone.om.multitenant.AccessPolicy;
 import org.apache.hadoop.ozone.om.multitenant.AccountNameSpace;
 import org.apache.hadoop.ozone.om.multitenant.BucketNameSpace;
-import org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal;
 import org.apache.hadoop.ozone.om.multitenant.Tenant;
+import org.apache.http.auth.BasicUserPrincipal;
 
 /**
  * OM MultiTenant manager interface.
@@ -111,23 +111,23 @@ public interface OMMultiTenantManager {
 
   /**
    * Creates a new user that exists for S3 API access to Ozone.
-   * TODO: FIX the description.
    * @param tenantName
-   * @param userName
+   * @param principal
+   * @param accessID
    * @return Unique UserID.
    * @throws IOException if there is any error condition detected.
    */
-  String assignUserToTenant(String tenantName, String userName);
+  String assignUserToTenant(BasicUserPrincipal principal, String tenantName,
+                            String accessID);
 
   /**
    * Given a user, destroys all state associated with that user.
    * This is different from deactivateUser().
-   * @param tenantName
-   @ @param userName
+   * @param accessID
    * @return
    * @throws IOException
    */
-  void destroyUser(String tenantName, String userName);
+  void destroyUser(String accessID);
 
 
   /**
@@ -137,99 +137,101 @@ public interface OMMultiTenantManager {
 
   /**
    * Given a user, return their S3-Secret Key.
-   * @param user
+   * @param accessID
    * @return S3 secret Key
    */
-  String getUserSecret(OzoneMultiTenantPrincipal user) throws IOException;
+  String getUserSecret(String accessID) throws IOException;
 
   /**
-   * Generates a new S3 secret key for the user. They can obtain the newly
-   * generated secret with getUserSecret();
-   * @param user
+   * Modify the groups that a user belongs to.
+   * @param accessID
+   * @param groupsAdded
+   * @param groupsRemoved
+   * @throws IOException
    */
-  void modifyUser(OzoneMultiTenantPrincipal user, List<String> groupsAdded,
+  void modifyUser(String accessID, List<String> groupsAdded,
                   List<String> groupsRemoved) throws IOException;
 
   /**
    * Given a user, deactivate them. We will need a recon command/job to cleanup
    * any data owned by this user (ReconMultiTenantManager).
-   * @param user
+   * @param accessID
    */
-  void deactivateUser(OzoneMultiTenantPrincipal user) throws IOException;
+  void deactivateUser(String accessID) throws IOException;
 
   /**
-   * List all the users that belong to this Tenant.
+   * List all the access IDs of all users that belong to this Tenant.
    * @param tenantID
    * @return List of users
    */
-  List<OzoneMultiTenantPrincipal> listAllUsers(String tenantID)
+  List<String> listAllAccessIDs(String tenantID)
       throws IOException;
 
   /**
-   * Given a user return Tenant.
-   * @param user
-   * @return Tenant
+   * Given an access ID return its corresponding tenant.
+   * @param accessID
+   * @return String tenant name
    */
-  Tenant getUserTenantInfo(OzoneMultiTenantPrincipal user) throws IOException;
+  String getTenantForAccessID(String accessID) throws IOException;
 
   /**
    * Given a user, make him an admin of the corresponding Tenant.
-   * @param user
+   * @param accessID
    */
-  void assignTenantAdminRole(OzoneMultiTenantPrincipal user) throws IOException;
+  void assignTenantAdminRole(String accessID) throws IOException;
 
   /**
-   * Given a user, make him an admin of the corresponding Tenant.
+   * Given a user, remove him as admin of the corresponding Tenant.
    */
-  void revokeTenantAdmin(OzoneMultiTenantPrincipal user) throws IOException;
+  void revokeTenantAdmin(String accessID) throws IOException;
 
   /**
    * List all the Admin users that belong to this Tenant.
    * @param tenantID
    * @return List of users
    */
-  List<OzoneMultiTenantPrincipal> listAllTenantAdmin(String tenantID)
+  List<String> listAllTenantAdmin(String tenantID)
       throws IOException;
 
   /**
    * grant given user access to the given BucketNameSpace.
-   * @param user
+   * @param accessID
    * @param bucketNameSpace
    */
-  void grantAccess(OzoneMultiTenantPrincipal user,
+  void grantAccess(String accessID,
                    BucketNameSpace bucketNameSpace) throws IOException;
 
   /**
-   * grant given user access to the given BucketNameSpace.
-   * @param user
+   * grant given user access to the given Bucket.
+   * @param accessID
    * @param bucketNameSpace
    */
-  void grantBucketAccess(OzoneMultiTenantPrincipal user,
+  void grantBucketAccess(String accessID,
                    BucketNameSpace bucketNameSpace, String bucketName)
       throws IOException;
 
   /**
    * revoke user access from the given BucketNameSpace.
-   * @param user
+   * @param accessID
    * @param bucketNameSpace
    */
-  void revokeAccess(OzoneMultiTenantPrincipal user,
+  void revokeAccess(String accessID,
                     BucketNameSpace bucketNameSpace) throws IOException;
 
   /**
    * grant given user access to the given AccountNameSpace.
-   * @param user
+   * @param accessID
    * @param accountNameSpace
    */
-  void grantAccess(OzoneMultiTenantPrincipal user,
+  void grantAccess(String accessID,
                    AccountNameSpace accountNameSpace) throws IOException;
 
   /**
    * revoke user access from the given AccountNameSpace.
-   * @param user
+   * @param accessID
    * @param accountNameSpace
    */
-  void revokeAccess(OzoneMultiTenantPrincipal user,
+  void revokeAccess(String accessID,
                     AccountNameSpace accountNameSpace) throws IOException;
 
   /**
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 a444bb8..d7265dc 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
@@ -17,11 +17,7 @@
  */
 package org.apache.hadoop.ozone.om;
 
-import static org.apache.hadoop.ozone.OzoneConsts.DEFAULT_TENANT_GROUP_ALL_ADMINS;
-import static org.apache.hadoop.ozone.OzoneConsts.DEFAULT_TENANT_GROUP_ALL_USERS;
 import static org.apache.hadoop.ozone.om.multitenant.AccessPolicy.AccessGrantType.ALLOW;
-import static org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal.OzonePrincipalType.GROUP_PRINCIPAL;
-import static org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal.OzonePrincipalType.USER_PRINCIPAL;
 import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.CREATE;
 import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.LIST;
 import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.NONE;
@@ -38,8 +34,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.ozone.om.helpers.OmDBAccessIdInfo;
@@ -50,10 +48,9 @@ import org.apache.hadoop.ozone.om.multitenant.CephCompatibleTenantImpl;
 import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessAuthorizer;
 import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessAuthorizerDummyPlugin;
 import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessAuthorizerRangerPlugin;
-import org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal;
+import org.apache.hadoop.ozone.om.multitenant.OzoneTenantGroupPrincipal;
 import org.apache.hadoop.ozone.om.multitenant.RangerAccessPolicy;
 import org.apache.hadoop.ozone.om.multitenant.Tenant;
-import org.apache.hadoop.ozone.om.multitenantImpl.OzoneMultiTenantPrincipalImpl;
 import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType;
 import org.apache.hadoop.ozone.security.acl.OzoneObj;
 import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
@@ -78,9 +75,9 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
   private final boolean devSkipRanger;
 
   private MultiTenantAccessAuthorizer authorizer;
-  private OMMetadataManager omMetadataManager;
-  private OzoneConfiguration conf;
-  private ReentrantReadWriteLock controlPathLock;
+  private final OMMetadataManager omMetadataManager;
+  private final OzoneConfiguration conf;
+  private final ReentrantReadWriteLock controlPathLock;
 
   // The following Mappings maintain all of the multi-tenancy states.
   // These mappings needs to have their persistent counterpart in OM tables.
@@ -89,13 +86,13 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
   // module a clean separation from the rest of the OM.
 
   // key : tenantName, value : TenantInfo
-  private Map<String, Tenant> inMemoryTenantNameToTenantInfoMap;
+  private final Map<String, Tenant> inMemoryTenantNameToTenantInfoMap;
 
   // This Mapping maintains all policies for all tenants
   //   key = tenantName
   //   value = list of all PolicyNames for this tenant in authorizor-plugin
   // Typical Usage : find out all the bucket/user policies for a tenant.
-  private Map<String, List<String>> inMemoryTenantToPolicyNameListMap;
+  private final Map<String, List<String>> inMemoryTenantToPolicyNameListMap;
 
   // This Mapping maintains all groups for all tenants
   //   key = tenantName
@@ -112,17 +109,22 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
   //      access the volume created for Tenant_XYZ.
   //      2) If user creates an access policy for a bucket, all the users
   //      that would have same access to the bucket can go in the same group.
-  private Map<String, List<String>> inMemoryTenantToTenantGroups;
+  private final Map<String, List<String>> inMemoryTenantToTenantGroups;
 
   // Mapping for user-access-id to TenantName
   // Typical usage: given a user-access-id find out which tenant
-  private Map<String, String> inMemoryUserNameToTenantNameMap;
+  private final Map<String, String> inMemoryAccessIDToTenantNameMap;
 
   // Mapping from user-access-id to all the groups that they belong to.
   // Typical usage: Adding a user or modify user, provide a list of groups
   //          that they would belong to. Note that groupIDs are opaque to OM.
   //          This may make sense just to the authorizer-plugin.
-  private Map<String, List<String>> inMemoryUserNameToListOfGroupsMap;
+  private final Map<String, List<String>> inMemoryAccessIDToListOfGroupsMap;
+
+  // Used for testing (where there's no ranger instance) to inject a mock
+  // authorizer. Use the normal Ranger plugin by default.
+  private static Supplier<MultiTenantAccessAuthorizer> authorizerSupplier =
+      MultiTenantAccessAuthorizerRangerPlugin::new;
 
 
   OMMultiTenantManagerImpl(OMMetadataManager mgr, OzoneConfiguration conf)
@@ -131,8 +133,8 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
     inMemoryTenantNameToTenantInfoMap = new ConcurrentHashMap<>();
     inMemoryTenantToPolicyNameListMap = new ConcurrentHashMap<>();
     inMemoryTenantToTenantGroups = new ConcurrentHashMap<>();
-    inMemoryUserNameToTenantNameMap = new ConcurrentHashMap<>();
-    inMemoryUserNameToListOfGroupsMap = new ConcurrentHashMap<>();
+    inMemoryAccessIDToTenantNameMap = new ConcurrentHashMap<>();
+    inMemoryAccessIDToListOfGroupsMap = new ConcurrentHashMap<>();
 
     controlPathLock = new ReentrantReadWriteLock();
     omMetadataManager = mgr;
@@ -141,6 +143,12 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
     start(conf);
   }
 
+  @VisibleForTesting
+  public static void setAuthorizerSupplier(
+      Supplier<MultiTenantAccessAuthorizer> authSupplier) {
+    authorizerSupplier = authSupplier;
+  }
+
   @Override
   public void start(OzoneConfiguration configuration) throws IOException {
     if (devSkipRanger) {
@@ -207,21 +215,19 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
       // TODO : Make it an idempotent operation. If any ranger state creation
       //  fails because it already exists, Ignore it.
 
-      OzoneMultiTenantPrincipal groupTenantAllUsers = getOzonePrincipal(
-          tenantID, DEFAULT_TENANT_GROUP_ALL_USERS, GROUP_PRINCIPAL);
-      String groupTenantAllUsersID =
-          authorizer.createGroup(groupTenantAllUsers);
-      tenant.addTenantAccessGroup(groupTenantAllUsersID);
+      OzoneTenantGroupPrincipal allTenantUsers =
+          OzoneTenantGroupPrincipal.newUserGroup(tenantID);
+      String allTenantUsersGroupID = authorizer.createGroup(allTenantUsers);
+      tenant.addTenantAccessGroup(allTenantUsersGroupID);
 
-      OzoneMultiTenantPrincipal groupTenantAllAdmins = getOzonePrincipal(
-          tenantID, DEFAULT_TENANT_GROUP_ALL_ADMINS, GROUP_PRINCIPAL);
-      String groupTenantAllAdminsID =
-          authorizer.createGroup(groupTenantAllAdmins);
-      tenant.addTenantAccessGroup(groupTenantAllAdminsID);
+      OzoneTenantGroupPrincipal allTenantAdmins =
+          OzoneTenantGroupPrincipal.newAdminGroup(tenantID);
+      String allTenantAdminsGroupID = authorizer.createGroup(allTenantAdmins);
+      tenant.addTenantAccessGroup(allTenantAdminsGroupID);
 
       List<String> allTenantGroups = new ArrayList<>();
-      allTenantGroups.add(groupTenantAllAdmins.getFullMultiTenantPrincipalID());
-      allTenantGroups.add(groupTenantAllUsers.getFullMultiTenantPrincipalID());
+      allTenantGroups.add(allTenantUsers.toString());
+      allTenantGroups.add(allTenantAdmins.toString());
       inMemoryTenantToTenantGroups.put(tenantID, allTenantGroups);
 
       BucketNameSpace bucketNameSpace = tenant.getTenantBucketNameSpace();
@@ -229,14 +235,14 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
         String volumeName = volume.getVolumeName();
         // Allow Volume List access
         AccessPolicy tenantVolumeAccessPolicy = createVolumeAccessPolicy(
-            volumeName, tenantID, groupTenantAllUsers.getUserID());
+            volumeName, allTenantUsers);
         tenantVolumeAccessPolicy.setPolicyID(
             authorizer.createAccessPolicy(tenantVolumeAccessPolicy));
         tenant.addTenantAccessPolicy(tenantVolumeAccessPolicy);
 
         // Allow Bucket Create within Volume
         AccessPolicy tenantBucketCreatePolicy = allowCreateBucketPolicy(
-            volumeName, tenantID, groupTenantAllUsers.getUserID());
+            volumeName, allTenantUsers);
         tenantBucketCreatePolicy.setPolicyID(
             authorizer.createAccessPolicy(tenantBucketCreatePolicy));
         tenant.addTenantAccessPolicy(tenantBucketCreatePolicy);
@@ -321,39 +327,36 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
    *      We can do all of this as part of holding a coarse lock and synchronize
    *      these control path operations.
    *
+   * @param principal
    * @param tenantName
-   * @param userName
+   * @param accessID
    * @return Tenant, or null on error
    */
   @Override
-  public String assignUserToTenant(String tenantName, String userName) {
+  public String assignUserToTenant(BasicUserPrincipal principal,
+      String tenantName, String accessID) {
     try {
       controlPathLock.writeLock().lock();
       Tenant tenant = getTenantInfo(tenantName);
       if (tenant == null) {
-        LOG.error("Tenant doesn't exist");
+        LOG.error("Cannot assign user to tenant {} that doesn't exist",
+            tenantName);
         return null;
       }
-      final OzoneMultiTenantPrincipal userPrincipal =
-          new OzoneMultiTenantPrincipalImpl(new BasicUserPrincipal(tenantName),
-              new BasicUserPrincipal(userName), USER_PRINCIPAL);
-
-      final OzoneMultiTenantPrincipal groupTenantAllUsers = getOzonePrincipal(
-          tenantName, DEFAULT_TENANT_GROUP_ALL_USERS, GROUP_PRINCIPAL);
+      final OzoneTenantGroupPrincipal groupTenantAllUsers =
+          OzoneTenantGroupPrincipal.newUserGroup(tenantName);
       String idGroupTenantAllUsers = authorizer.getGroupId(groupTenantAllUsers);
       List<String> userGroupIDs = new ArrayList<>();
       userGroupIDs.add(idGroupTenantAllUsers);
 
-      String userID = authorizer.createUser(userPrincipal, userGroupIDs);
+      String userID = authorizer.createUser(principal, userGroupIDs);
 
-      inMemoryUserNameToTenantNameMap.put(
-          userPrincipal.getFullMultiTenantPrincipalID(), tenantName);
-      inMemoryUserNameToListOfGroupsMap.put(
-          userPrincipal.getFullMultiTenantPrincipalID(), userGroupIDs);
+      inMemoryAccessIDToTenantNameMap.put(accessID, tenantName);
+      inMemoryAccessIDToListOfGroupsMap.put(accessID, userGroupIDs);
 
       return userID;
     } catch (Exception e) {
-      destroyUser(tenantName, userName);
+      destroyUser(accessID);
       LOG.error(e.getMessage());
       return null;
     } finally {
@@ -362,24 +365,20 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
   }
 
   @Override
-  public void destroyUser(String tenantName, String userName) {
+  public void destroyUser(String accessID) {
     try {
       controlPathLock.writeLock().lock();
-      final Tenant tenant = getTenantInfo(tenantName);
-      if (tenant == null) {
+      String tenantName = getTenantForAccessID(accessID);
+      if (tenantName == null) {
         LOG.error("Tenant doesn't exist");
         return;
       }
-      final OzoneMultiTenantPrincipal userPrincipal =
-          new OzoneMultiTenantPrincipalImpl(new BasicUserPrincipal(tenantName),
-              new BasicUserPrincipal(userName), USER_PRINCIPAL);
-      final String userID = authorizer.getUserId(userPrincipal);
-      authorizer.deleteUser(userID);
-
-      inMemoryUserNameToTenantNameMap.remove(
-          userPrincipal.getFullMultiTenantPrincipalID());
-      inMemoryUserNameToListOfGroupsMap.remove(
-          userPrincipal.getFullMultiTenantPrincipalID());
+      // TODO: Determine how to replace this code.
+//      final String userID = authorizer.getUserId(userPrincipal);
+//      authorizer.deleteUser(userID);
+
+      inMemoryAccessIDToTenantNameMap.remove(accessID);
+      inMemoryAccessIDToListOfGroupsMap.remove(accessID);
     } catch (Exception e) {
       LOG.error(e.getMessage());
     } finally {
@@ -409,80 +408,79 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
   }
 
   @Override
-  public String getUserSecret(OzoneMultiTenantPrincipal user)
+  public String getUserSecret(String accessID)
       throws IOException {
     return "";
   }
 
   @Override
-  public void modifyUser(OzoneMultiTenantPrincipal user,
+  public void modifyUser(String accessID,
                          List<String> groupsAdded,
                          List<String> groupsRemoved) throws IOException {
 
   }
 
   @Override
-  public void deactivateUser(OzoneMultiTenantPrincipal user)
+  public void deactivateUser(String accessID)
       throws IOException {
 
   }
 
   @Override
-  public List<OzoneMultiTenantPrincipal> listAllUsers(String tenantID)
+  public List<String> listAllAccessIDs(String tenantID)
       throws IOException {
     return null;
   }
 
   @Override
-  public Tenant getUserTenantInfo(OzoneMultiTenantPrincipal user)
-      throws IOException {
-    return null;
+  public String getTenantForAccessID(String accessID) {
+    return inMemoryAccessIDToTenantNameMap.getOrDefault(accessID, null);
   }
 
   @Override
-  public void assignTenantAdminRole(OzoneMultiTenantPrincipal user)
+  public void assignTenantAdminRole(String accessID)
       throws IOException {
 
   }
 
   @Override
-  public void revokeTenantAdmin(OzoneMultiTenantPrincipal user)
+  public void revokeTenantAdmin(String accessID)
       throws IOException {
 
   }
 
   @Override
-  public List<OzoneMultiTenantPrincipal> listAllTenantAdmin(String tenantID)
+  public List<String> listAllTenantAdmin(String tenantID)
       throws IOException {
     return null;
   }
 
   @Override
-  public void grantAccess(OzoneMultiTenantPrincipal user,
+  public void grantAccess(String accessID,
       BucketNameSpace bucketNameSpace) throws IOException {
 
   }
 
   @Override
-  public void grantBucketAccess(OzoneMultiTenantPrincipal user,
+  public void grantBucketAccess(String accessID,
       BucketNameSpace bucketNameSpace, String bucketName) throws IOException {
 
   }
 
   @Override
-  public void revokeAccess(OzoneMultiTenantPrincipal user,
+  public void revokeAccess(String accessID,
       BucketNameSpace bucketNameSpace) throws IOException {
 
   }
 
   @Override
-  public void grantAccess(OzoneMultiTenantPrincipal user,
+  public void grantAccess(String accessID,
       AccountNameSpace accountNameSpace) throws IOException {
 
   }
 
   @Override
-  public void revokeAccess(OzoneMultiTenantPrincipal user,
+  public void revokeAccess(String accessID,
       AccountNameSpace accountNameSpace) throws IOException {
 
   }
@@ -511,23 +509,13 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
 
   }
 
-  private OzoneMultiTenantPrincipal getOzonePrincipal(String tenant, String id,
-      OzoneMultiTenantPrincipal.OzonePrincipalType type) {
-    OzoneMultiTenantPrincipal principal = new OzoneMultiTenantPrincipalImpl(
-        new BasicUserPrincipal(tenant),
-        new BasicUserPrincipal(id), type);
-    return principal;
-  }
-
-  private AccessPolicy createVolumeAccessPolicy(String vol, String tenant,
-      String group) throws IOException {
+  private AccessPolicy createVolumeAccessPolicy(String vol,
+      OzoneTenantGroupPrincipal principal) throws IOException {
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "VolumeAccess" + vol + "Policy");
+        principal.getName() + "VolumeAccess" + vol + "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(VOLUME).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName("").setKeyName("").build();
-    OzoneMultiTenantPrincipal principal = getOzonePrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, READ, ALLOW);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, LIST, ALLOW);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal,
@@ -535,28 +523,25 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
     return tenantVolumeAccessPolicy;
   }
 
-  private AccessPolicy allowCreateBucketPolicy(String vol, String tenant,
-      String group) throws IOException {
+  private AccessPolicy allowCreateBucketPolicy(String vol,
+      OzoneTenantGroupPrincipal principal) throws IOException {
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "AllowBucketCreate" + vol + "Policy");
+        principal.getName() + "AllowBucketCreate" + vol + "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(BUCKET).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName("*").setKeyName("").build();
-    OzoneMultiTenantPrincipal principal = getOzonePrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, CREATE, ALLOW);
     return tenantVolumeAccessPolicy;
   }
 
-  private AccessPolicy allowAccessBucketPolicy(String vol, String tenant,
-      String group, String bucketName) throws IOException {
+  private AccessPolicy allowAccessBucketPolicy(String vol, String bucketName,
+      OzoneTenantGroupPrincipal principal) throws IOException {
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "AllowBucketAccess" + vol + bucketName + "Policy");
+        principal.getName() + "AllowBucketAccess" + vol + bucketName +
+            "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(BUCKET).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName(bucketName).setKeyName("*").build();
-    OzoneMultiTenantPrincipal principal = getOzonePrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     for (ACLType acl : ACLType.values()) {
       if (acl != NONE) {
         tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, acl,
@@ -566,15 +551,14 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
     return tenantVolumeAccessPolicy;
   }
 
-  private AccessPolicy allowAccessKeyPolicy(String vol, String tenant,
-      String group, String bucketName) throws IOException {
+  private AccessPolicy allowAccessKeyPolicy(String vol, String bucketName,
+      OzoneTenantGroupPrincipal principal) throws IOException {
     AccessPolicy tenantVolumeAccessPolicy = new RangerAccessPolicy(
-        tenant + group + "AllowBucketKeyAccess" + vol + bucketName + "Policy");
+        principal.getName() + "AllowBucketKeyAccess" + vol + bucketName +
+            "Policy");
     OzoneObjInfo obj = OzoneObjInfo.Builder.newBuilder()
         .setResType(KEY).setStoreType(OZONE).setVolumeName(vol)
         .setBucketName(bucketName).setKeyName("*").build();
-    OzoneMultiTenantPrincipal principal = getOzonePrincipal(tenant, group,
-        GROUP_PRINCIPAL);
     for (ACLType acl :ACLType.values()) {
       if (acl != NONE) {
         tenantVolumeAccessPolicy.addAccessPolicyElem(obj, principal, acl,
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 0d1bb0d..cddcb0d 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
@@ -3139,6 +3139,31 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
   }
 
   @Override
+  public OmVolumeArgs getS3Volume(String accessID) throws IOException {
+    String tenantName = multiTenantManagr.getTenantForAccessID(accessID);
+    if (tenantName == null) {
+      // If the user is not associated with a tenant, they will use the
+      // default s3 volume.
+      String defaultS3volume =
+          HddsClientUtils.getDefaultS3VolumeName(configuration);
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("No tenant found for access ID {}. Directing " +
+            "requests to default s3 volume {}.", accessID, defaultS3volume);
+      }
+      return getVolumeInfo(defaultS3volume);
+    } else {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Get S3 volume request for access ID {} belonging to tenant" +
+            " {} is directed to the volume {}.", accessID, tenantName,
+            tenantName);
+      }
+      // This call performs acl checks and checks volume existence.
+      return getVolumeInfo(tenantName);
+    }
+  }
+
+  @Override
   /**
    * {@inheritDoc}
    */
@@ -4164,7 +4189,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
    * @throws IOException
    */
   private void addS3GVolumeToDB() throws IOException {
-    String s3VolumeName = HddsClientUtils.getS3VolumeName(configuration);
+    String s3VolumeName = HddsClientUtils.getDefaultS3VolumeName(configuration);
     String dbVolumeKey = metadataManager.getVolumeKey(s3VolumeName);
 
     if (!s3VolumeName.equals(OzoneConfigKeys.OZONE_S3_VOLUME_NAME_DEFAULT)) {
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMAssignUserToTenantRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMAssignUserToTenantRequest.java
index 5f2f489..8359ace 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMAssignUserToTenantRequest.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMAssignUserToTenantRequest.java
@@ -31,7 +31,6 @@ import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.om.helpers.OmDBAccessIdInfo;
 import org.apache.hadoop.ozone.om.helpers.OmDBKerberosPrincipalInfo;
 import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
-import org.apache.hadoop.ozone.om.multitenant.OzoneMultiTenantPrincipal;
 import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper;
 import org.apache.hadoop.ozone.om.request.OMClientRequest;
 import org.apache.hadoop.ozone.om.request.util.OmResponseUtil;
@@ -43,6 +42,7 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMReque
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Secret;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest;
+import org.apache.http.auth.BasicUserPrincipal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -169,7 +169,6 @@ public class OMAssignUserToTenantRequest extends OMClientRequest {
 
     boolean acquiredVolumeLock = false;
     boolean acquiredS3SecretLock = false;
-    OzoneMultiTenantPrincipal tenantPrincipal = null;
     Map<String, String> auditMap = new HashMap<>();
     OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
 
@@ -234,8 +233,11 @@ public class OMAssignUserToTenantRequest extends OMClientRequest {
       // TODO: Is userId from MultiTenantManager still useful?
       // TODO: Move this to preExecute as well.
       userId = ozoneManager.getMultiTenantManager()
-          .assignUserToTenant(tenantName, accessId);
-      LOG.debug("userId = {}", userId);
+          .assignUserToTenant(new BasicUserPrincipal(principal), tenantName,
+              accessId);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("userId for assign user to tenant request = {}", userId);
+      }
 
       // Add to tenantAccessIdTable
       final OmDBAccessIdInfo omDBAccessIdInfo = new OmDBAccessIdInfo.Builder()
@@ -285,8 +287,7 @@ public class OMAssignUserToTenantRequest extends OMClientRequest {
           s3SecretValue, principal, defaultGroupName, roleName,
           accessId, omDBAccessIdInfo, omDBKerberosPrincipalInfo);
     } catch (IOException ex) {
-      ozoneManager.getMultiTenantManager().destroyUser(
-          tenantName, accessId);
+      ozoneManager.getMultiTenantManager().destroyUser(accessId);
       exception = ex;
       // Set response success flag to false
       omResponse.setAssignUserToTenantResponse(
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java
index b3ead46..ad313d9 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java
@@ -80,6 +80,8 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRespo
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareStatusResponse;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServiceListRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServiceListResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeRequest;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeResponse;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantGetUserInfoRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantGetUserInfoResponse;
@@ -224,6 +226,11 @@ public class OzoneManagerRequestHandler implements RequestHandler {
         PrepareStatusResponse prepareStatusResponse = getPrepareStatus();
         responseBuilder.setPrepareStatusResponse(prepareStatusResponse);
         break;
+      case GetS3Volume:
+        GetS3VolumeResponse s3VolumeResponse =
+            getS3Volume(request.getGetS3VolumeRequest());
+        responseBuilder.setGetS3VolumeResponse(s3VolumeResponse);
+        break;
       case TenantGetUserInfo:
         TenantGetUserInfoResponse getUserInfoResponse = tenantGetUserInfo(
             request.getTenantGetUserInfoRequest());
@@ -680,6 +687,14 @@ public class OzoneManagerRequestHandler implements RequestHandler {
         .setCurrentTxnIndex(prepareState.getIndex()).build();
   }
 
+  private GetS3VolumeResponse getS3Volume(GetS3VolumeRequest request)
+      throws IOException {
+    OmVolumeArgs s3VolArgs = impl.getS3Volume(request.getAccessID());
+    return GetS3VolumeResponse.newBuilder()
+        .setVolumeInfo(s3VolArgs.getProtobuf())
+        .build();
+  }
+
   public OzoneManager getOzoneManager() {
     return impl;
   }
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java
index 83809c3..95c2825 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/OzoneClientProducer.java
@@ -130,7 +130,9 @@ public class OzoneClientProducer {
       }
       ozoneClient =
           remoteUser.doAs((PrivilegedExceptionAction<OzoneClient>) () -> {
-            return createOzoneClient();
+            // TODO: Once HDDS-4440 is merged, access ID should be passed
+            //  through the OM transport.
+            return createOzoneClient(awsAccessId);
           });
     } catch (OS3Exception ex) {
       if (LOG.isDebugEnabled()) {
@@ -149,14 +151,13 @@ public class OzoneClientProducer {
   }
 
   @NotNull
-  @VisibleForTesting
-  OzoneClient createOzoneClient() throws IOException {
+  private OzoneClient createOzoneClient(String accessID) throws IOException {
     if (omServiceID == null) {
-      return OzoneClientFactory.getRpcClient(ozoneConfiguration);
+      return OzoneClientFactory.getRpcClient(ozoneConfiguration, accessID);
     } else {
       // As in HA case, we need to pass om service ID.
       return OzoneClientFactory.getRpcClient(omServiceID,
-          ozoneConfiguration);
+          ozoneConfiguration, accessID);
     }
   }
 
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
index 137b8ea..48fdfd1 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.function.Function;
 
-import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
 import org.apache.hadoop.ozone.client.OzoneBucket;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneVolume;
@@ -76,9 +75,7 @@ public class EndpointBase {
   }
 
   protected OzoneVolume getVolume() throws IOException {
-    String s3VolumeName = HddsClientUtils.getS3VolumeName(
-        client.getConfiguration());
-    return client.getObjectStore().getVolume(s3VolumeName);
+    return client.getObjectStore().getS3Volume();
   }
 
   /**
@@ -109,7 +106,7 @@ public class EndpointBase {
    * @param s3BucketName - S3 Bucket Name.
    * @throws  IOException in case the bucket cannot be deleted.
    */
-  public void deleteS3Bucket(String s3BucketName)
+  protected void deleteS3Bucket(String s3BucketName)
       throws IOException, OS3Exception {
     try {
       client.getObjectStore().deleteS3Bucket(s3BucketName);
@@ -130,7 +127,7 @@ public class EndpointBase {
    * @param prefix Bucket prefix to match
    * @return {@code Iterator<OzoneBucket>}
    */
-  public Iterator<? extends OzoneBucket> listS3Buckets(String prefix)
+  protected Iterator<? extends OzoneBucket> listS3Buckets(String prefix)
       throws IOException, OS3Exception {
     return iterateBuckets(volume -> volume.listBuckets(prefix));
   }
@@ -145,7 +142,7 @@ public class EndpointBase {
    * @param previousBucket Buckets are listed after this bucket
    * @return {@code Iterator<OzoneBucket>}
    */
-  public Iterator<? extends OzoneBucket> listS3Buckets(String prefix,
+  protected Iterator<? extends OzoneBucket> listS3Buckets(String prefix,
       String previousBucket) throws IOException, OS3Exception {
     return iterateBuckets(volume -> volume.listBuckets(prefix, previousBucket));
   }
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
index 03636c3..4e25478 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
@@ -51,6 +51,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.hadoop.hdds.client.ReplicationConfig;
 import org.apache.hadoop.hdds.client.ReplicationFactor;
 import org.apache.hadoop.hdds.client.ReplicationType;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
@@ -176,14 +177,15 @@ public class ObjectEndpoint extends EndpointBase {
         s3StorageType = toS3StorageType(storageType);
         storageTypeDefault = false;
       }
-      ReplicationType replicationType = s3StorageType.getType();
-      ReplicationFactor replicationFactor = s3StorageType.getFactor();
+      ReplicationConfig replicationConfig =
+          ReplicationConfig.fromTypeAndFactor(s3StorageType.getType(),
+              s3StorageType.getFactor());
 
       if (copyHeader != null) {
         //Copy object, as copy source available.
         CopyObjectResponse copyObjectResponse = copyObject(
-            copyHeader, bucketName, keyPath, replicationType,
-            replicationFactor, storageTypeDefault);
+            copyHeader, bucketName, keyPath, replicationConfig,
+            storageTypeDefault);
         return Response.status(Status.OK).entity(copyObjectResponse).header(
             "Connection", "close").build();
       }
@@ -191,8 +193,8 @@ public class ObjectEndpoint extends EndpointBase {
       // Normal put object
       OzoneBucket bucket = getBucket(bucketName);
 
-      output = bucket.createKey(keyPath, length, replicationType,
-          replicationFactor, new HashMap<>());
+      output = bucket.createKey(keyPath, length, replicationConfig,
+          new HashMap<>());
 
       if ("STREAMING-AWS4-HMAC-SHA256-PAYLOAD"
           .equals(headers.getHeaderString("x-amz-content-sha256"))) {
@@ -483,7 +485,9 @@ public class ObjectEndpoint extends EndpointBase {
       ReplicationFactor replicationFactor = s3StorageType.getFactor();
 
       OmMultipartInfo multipartInfo = ozoneBucket
-          .initiateMultipartUpload(key, replicationType, replicationFactor);
+          .initiateMultipartUpload(key,
+              ReplicationConfig.fromTypeAndFactor(replicationType,
+              replicationFactor));
 
       MultipartUploadInitiateResponse multipartUploadInitiateResponse = new
           MultipartUploadInitiateResponse();
@@ -730,8 +734,7 @@ public class ObjectEndpoint extends EndpointBase {
   private CopyObjectResponse copyObject(String copyHeader,
                                         String destBucket,
                                         String destkey,
-                                        ReplicationType replicationType,
-                                        ReplicationFactor replicationFactor,
+                                        ReplicationConfig replicationConfig,
                                         boolean storageTypeDefault)
       throws OS3Exception, IOException {
 
@@ -780,7 +783,7 @@ public class ObjectEndpoint extends EndpointBase {
       sourceInputStream = sourceOzoneBucket.readKey(sourceKey);
 
       destOutputStream = destOzoneBucket.createKey(destkey, sourceKeyLen,
-          replicationType, replicationFactor, new HashMap<>());
+          replicationConfig, new HashMap<>());
 
       IOUtils.copy(sourceInputStream, destOutputStream);
 
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java
index 74ebf4e..5591ff6 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java
@@ -121,10 +121,18 @@ public class ObjectStoreStub extends ObjectStore {
   }
 
   @Override
+  public OzoneVolume getS3Volume() throws IOException {
+    // Always return default S3 volume. This class will not be used for
+    // multitenant testing.
+    String volumeName = HddsClientUtils.getDefaultS3VolumeName(conf);
+    return getVolume(volumeName);
+  }
+
+  @Override
   public void createS3Bucket(String s3BucketName) throws
       IOException {
     if (!bucketEmptyStatus.containsKey(s3BucketName)) {
-      String volumeName = HddsClientUtils.getS3VolumeName(conf);
+      String volumeName = HddsClientUtils.getDefaultS3VolumeName(conf);
       bucketEmptyStatus.put(s3BucketName, true);
       if (!volumes.containsKey(volumeName)) {
         createVolume(volumeName);
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneBucketStub.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneBucketStub.java
index cf0d4c3..3a3e3a9 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneBucketStub.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneBucketStub.java
@@ -87,16 +87,15 @@ public class OzoneBucketStub extends OzoneBucket {
 
   @Override
   public OzoneOutputStream createKey(String key, long size) throws IOException {
-    return createKey(key, size, ReplicationType.STAND_ALONE,
-        ReplicationFactor.ONE, new HashMap<>());
+    return createKey(key, size,
+        ReplicationConfig.fromTypeAndFactor(ReplicationType.STAND_ALONE,
+        ReplicationFactor.ONE), new HashMap<>());
   }
 
   @Override
   public OzoneOutputStream createKey(String key, long size,
-                                     ReplicationType type,
-                                     ReplicationFactor factor,
-                                     Map<String, String> metadata)
-      throws IOException {
+                                     ReplicationConfig replicationConfig,
+                                     Map<String, String> keyMetadata) {
     ByteArrayOutputStream byteArrayOutputStream =
         new ByteArrayOutputStream((int) size) {
           @Override
@@ -109,8 +108,7 @@ public class OzoneBucketStub extends OzoneBucket {
                 size,
                 System.currentTimeMillis(),
                 System.currentTimeMillis(),
-                new ArrayList<>(), type, metadata, null,
-                factor.getValue()
+                new ArrayList<>(), replicationConfig, metadata, null
             ));
             super.close();
           }
@@ -186,8 +184,7 @@ public class OzoneBucketStub extends OzoneBucket {
 
   @Override
   public OmMultipartInfo initiateMultipartUpload(String keyName,
-                                                 ReplicationType type,
-                                                 ReplicationFactor factor)
+                                                 ReplicationConfig config)
       throws IOException {
     String uploadID = UUID.randomUUID().toString();
     multipartUploadIdMap.put(keyName, uploadID);
@@ -277,8 +274,9 @@ public class OzoneBucketStub extends OzoneBucket {
     List<PartInfo> partInfoList = new ArrayList<>();
 
     if (partList.get(key) == null) {
-      return new OzoneMultipartUploadPartListParts(ReplicationType.RATIS,
-          ReplicationFactor.ONE, 0, false);
+      return new OzoneMultipartUploadPartListParts(ReplicationConfig
+          .fromTypeAndFactor(ReplicationType.RATIS, ReplicationFactor.ONE),
+          0, false);
     } else {
       Map<Integer, Part> partMap = partList.get(key);
       Iterator<Map.Entry<Integer, Part>> partIterator =
@@ -307,8 +305,9 @@ public class OzoneBucketStub extends OzoneBucket {
       }
 
       OzoneMultipartUploadPartListParts ozoneMultipartUploadPartListParts =
-          new OzoneMultipartUploadPartListParts(ReplicationType.RATIS,
-              ReplicationFactor.ONE,
+          new OzoneMultipartUploadPartListParts(
+              ReplicationConfig.fromTypeAndFactor(ReplicationType.RATIS,
+                  ReplicationFactor.ONE),
               nextPartNumberMarker, truncated);
       ozoneMultipartUploadPartListParts.addAllParts(partInfoList);
 
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestMultipartUploadWithCopy.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestMultipartUploadWithCopy.java
index 29f6dcf..5d7e0b9 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestMultipartUploadWithCopy.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestMultipartUploadWithCopy.java
@@ -32,6 +32,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Scanner;
 
+import org.apache.hadoop.hdds.client.ReplicationConfig;
 import org.apache.hadoop.hdds.client.ReplicationFactor;
 import org.apache.hadoop.hdds.client.ReplicationType;
 import org.apache.hadoop.ozone.OzoneConsts;
@@ -84,8 +85,9 @@ public class TestMultipartUploadWithCopy {
 
     byte[] keyContent = EXISTING_KEY_CONTENT.getBytes(UTF_8);
     try (OutputStream stream = bucket
-        .createKey(EXISTING_KEY, keyContent.length, ReplicationType.RATIS,
-            ReplicationFactor.THREE, new HashMap<>())) {
+        .createKey(EXISTING_KEY, keyContent.length,
+            ReplicationConfig.fromTypeAndFactor(ReplicationType.RATIS,
+            ReplicationFactor.THREE), new HashMap<>())) {
       stream.write(keyContent);
     }
 
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectHead.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectHead.java
index a1b4fb1..bec92af 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectHead.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectHead.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import java.time.format.DateTimeFormatter;
 import java.util.HashMap;
 
+import org.apache.hadoop.hdds.client.ReplicationConfig;
 import org.apache.hadoop.hdds.client.ReplicationFactor;
 import org.apache.hadoop.hdds.client.ReplicationType;
 import org.apache.hadoop.ozone.client.OzoneBucket;
@@ -67,8 +68,9 @@ public class TestObjectHead {
     //GIVEN
     String value = RandomStringUtils.randomAlphanumeric(32);
     OzoneOutputStream out = bucket.createKey("key1",
-        value.getBytes(UTF_8).length, ReplicationType.STAND_ALONE,
-        ReplicationFactor.ONE, new HashMap<>());
+        value.getBytes(UTF_8).length,
+        ReplicationConfig.fromTypeAndFactor(ReplicationType.STAND_ALONE,
+        ReplicationFactor.ONE), new HashMap<>());
     out.write(value.getBytes(UTF_8));
     out.close();
 
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java
index 81b0718..b27c94f 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java
@@ -79,7 +79,7 @@ public class TestPermissionCheck {
    */
   @Test
   public void testListS3Buckets() throws IOException {
-    doThrow(exception).when(objectStore).getVolume(anyString());
+    doThrow(exception).when(objectStore).getS3Volume();
     RootEndpoint rootEndpoint = new RootEndpoint();
     rootEndpoint.setClient(client);
 
@@ -196,7 +196,7 @@ public class TestPermissionCheck {
 
   @Test
   public void testGetAcl() throws Exception {
-    Mockito.when(objectStore.getVolume(anyString())).thenReturn(volume);
+    Mockito.when(objectStore.getS3Volume()).thenReturn(volume);
     Mockito.when(objectStore.getS3Bucket(anyString())).thenReturn(bucket);
     doThrow(exception).when(bucket).getAcls();
 
@@ -212,15 +212,15 @@ public class TestPermissionCheck {
     try {
       bucketEndpoint.get("bucketName", null, null, null, 1000,
           null, null, null, null, null, "acl", null);
-    } catch (Exception e) {
-      Assert.assertTrue(e instanceof OS3Exception &&
-          ((OS3Exception)e).getHttpCode() == HTTP_FORBIDDEN);
+      Assert.fail("Expected OS3Exception with FORBIDDEN http code.");
+    } catch (OS3Exception e) {
+      Assert.assertEquals(HTTP_FORBIDDEN, e.getHttpCode());
     }
   }
 
   @Test
   public void testSetAcl() throws Exception {
-    Mockito.when(objectStore.getVolume(anyString())).thenReturn(volume);
+    Mockito.when(objectStore.getS3Volume()).thenReturn(volume);
     Mockito.when(objectStore.getS3Bucket(anyString())).thenReturn(bucket);
     doThrow(exception).when(bucket).addAcl(any());
 
@@ -267,7 +267,8 @@ public class TestPermissionCheck {
   public void testPutKey() throws IOException {
     Mockito.when(objectStore.getS3Bucket(anyString())).thenReturn(bucket);
     doThrow(exception).when(bucket)
-        .createKey(anyString(), anyLong(), any(), any(), any());
+        .createKey(anyString(), anyLong(), any(), any());
+
     ObjectEndpoint objectEndpoint = new ObjectEndpoint();
     objectEndpoint.setClient(client);
     objectEndpoint.setHeaders(headers);
@@ -302,7 +303,7 @@ public class TestPermissionCheck {
   public void testMultiUploadKey() throws IOException {
     Mockito.when(objectStore.getS3Bucket(anyString())).thenReturn(bucket);
     doThrow(exception).when(bucket)
-        .initiateMultipartUpload(anyString(), any(), any());
+        .initiateMultipartUpload(anyString(), any());
     ObjectEndpoint objectEndpoint = new ObjectEndpoint();
     objectEndpoint.setClient(client);
     objectEndpoint.setHeaders(headers);

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