You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by si...@apache.org on 2021/11/20 02:29:40 UTC

[ozone] branch HDDS-4944 updated: HDDS-5972. [Multi-Tenant] Implement SetSecret: `ozone tenant user setsecret` and `ozone s3 setsecret` (#2845)

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

siyao 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 19116fe  HDDS-5972. [Multi-Tenant] Implement SetSecret: `ozone tenant user setsecret` and `ozone s3 setsecret` (#2845)
19116fe is described below

commit 19116fe1f14a779505147bf5687dbd6239dbd800
Author: Siyao Meng <50...@users.noreply.github.com>
AuthorDate: Fri Nov 19 18:29:19 2021 -0800

    HDDS-5972. [Multi-Tenant] Implement SetSecret: `ozone tenant user setsecret` and `ozone s3 setsecret` (#2845)
---
 .../java/org/apache/hadoop/ozone/OzoneConsts.java  |   3 +
 .../apache/hadoop/ozone/client/ObjectStore.java    |  12 ++
 .../ozone/client/protocol/ClientProtocol.java      |  10 +
 .../apache/hadoop/ozone/client/rpc/RpcClient.java  |  12 ++
 .../main/java/org/apache/hadoop/ozone/OmUtils.java |   1 +
 .../org/apache/hadoop/ozone/audit/OMAction.java    |   1 +
 .../hadoop/ozone/om/helpers/OmDBAccessIdInfo.java  |  32 +--
 .../hadoop/ozone/om/helpers/OmDBTenantInfo.java    |  22 +-
 .../hadoop/ozone/om/helpers/OmTenantArgs.java      |  11 +-
 .../hadoop/ozone/om/helpers/OmTenantUserArgs.java  |  12 +-
 .../hadoop/ozone/om/helpers/S3SecretValue.java     |   1 +
 .../hadoop/ozone/om/helpers/TenantUserList.java    |  19 +-
 .../ozone/om/protocol/OzoneManagerProtocol.java    |  10 +
 ...OzoneManagerProtocolClientSideTranslatorPB.java |  25 ++-
 .../smoketest/security/ozone-secure-tenant.robot   |  32 ++-
 .../smoketest/security/ozone-secure-token.robot    |   1 +
 .../hadoop/ozone/TestSecureOzoneCluster.java       |  17 +-
 .../hadoop/ozone/shell/TestOzoneTenantShell.java   | 122 +++++++++++
 .../src/main/proto/OmClientProtocol.proto          |  17 +-
 .../hadoop/ozone/om/OMMultiTenantManagerImpl.java  |   6 +-
 .../org/apache/hadoop/ozone/om/OzoneManager.java   |  25 ++-
 .../om/ratis/utils/OzoneManagerRatisUtils.java     |   3 +
 .../om/request/s3/security/OMSetSecretRequest.java | 233 +++++++++++++++++++++
 .../om/request/s3/security/S3GetSecretRequest.java |   4 +-
 .../s3/tenant/OMTenantAssignAdminRequest.java      |   4 +-
 .../request/s3/tenant/OMTenantCreateRequest.java   |  45 ++--
 .../request/s3/tenant/OMTenantRequestHelper.java   |  56 ++++-
 .../s3/tenant/OMTenantRevokeAdminRequest.java      |  26 ++-
 .../tenant/OMTenantRevokeUserAccessIdRequest.java  |   2 +-
 .../response/s3/security/OMSetSecretResponse.java  |  89 ++++++++
 .../response/s3/tenant/OMTenantCreateResponse.java |   2 +-
 .../s3/security/TestS3GetSecretRequest.java        |   4 +-
 .../hadoop/ozone/shell/s3/GetS3SecretHandler.java  |   7 +-
 .../org/apache/hadoop/ozone/shell/s3/S3Shell.java  |   1 +
 ...3SecretHandler.java => SetS3SecretHandler.java} |  29 +--
 .../shell/tenant/TenantAssignAdminHandler.java     |   8 +-
 .../tenant/TenantAssignUserAccessIdHandler.java    |  12 +-
 .../ozone/shell/tenant/TenantGetSecretHandler.java |  10 +-
 .../ozone/shell/tenant/TenantListUsersHandler.java |   8 +-
 .../shell/tenant/TenantRevokeAdminHandler.java     |   8 +-
 .../ozone/shell/tenant/TenantSetSecretHandler.java |  43 +++-
 41 files changed, 824 insertions(+), 161 deletions(-)

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 36f5e52..7bc326a 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
@@ -323,6 +323,7 @@ public final class OzoneConsts {
   public static final String MAX_PARTS = "maxParts";
   public static final String S3_BUCKET = "s3Bucket";
   public static final String S3_GETSECRET_USER = "S3GetSecretUser";
+  public static final String S3_SETSECRET_USER = "S3SetSecretUser";
   public static final String S3_REVOKESECRET_USER = "S3RevokeSecretUser";
   public static final String RENAMED_KEYS_MAP = "renamedKeysMap";
   public static final String UNRENAMED_KEYS_MAP = "unRenamedKeysMap";
@@ -374,6 +375,8 @@ public final class OzoneConsts {
   public static final int S3_BUCKET_MIN_LENGTH = 3;
   public static final int S3_BUCKET_MAX_LENGTH = 64;
 
+  public static final int S3_SECRET_KEY_MIN_LENGTH = 8;
+
   //GDPR
   public static final String GDPR_FLAG = "gdprEnabled";
   public static final String GDPR_ALGORITHM_NAME = "AES";
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 5119cb3..2639208 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
@@ -178,6 +178,18 @@ public class ObjectStore {
     return proxy.getS3Secret(kerberosID, createIfNotExist);
   }
 
+  /**
+   * Set secretKey for accessId.
+   * @param accessId
+   * @param secretKey
+   * @return S3SecretValue <accessId, secretKey> pair
+   * @throws IOException
+   */
+  public S3SecretValue setS3Secret(String accessId, String secretKey)
+          throws IOException {
+    return proxy.setS3Secret(accessId, secretKey);
+  }
+
   public void revokeS3Secret(String kerberosID) throws IOException {
     proxy.revokeS3Secret(kerberosID);
   }
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 5f94abd..5d2a420 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
@@ -571,6 +571,16 @@ public interface ClientProtocol {
           throws IOException;
 
   /**
+   * Set secret key of a given accessId.
+   * @param accessId
+   * @param secretKey
+   * @return S3SecretValue
+   * @throws IOException
+   */
+  S3SecretValue setS3Secret(String accessId, String secretKey)
+      throws IOException;
+
+  /**
    * Revoke S3 Secret of given kerberos user.
    * @param kerberosID
    * @throws IOException
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 bba1e5e..7e81ba4 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
@@ -644,6 +644,18 @@ public class RpcClient implements ClientProtocol {
   /**
    * {@inheritDoc}
    */
+  public S3SecretValue setS3Secret(String accessId, String secretKey)
+          throws IOException {
+    Preconditions.checkArgument(Strings.isNotBlank(accessId),
+            "accessId cannot be null or empty.");
+    Preconditions.checkArgument(Strings.isNotBlank(secretKey),
+            "secretKey cannot be null or empty.");
+    return ozoneManagerClient.setS3Secret(accessId, secretKey);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public void revokeS3Secret(String kerberosID) throws IOException {
     Preconditions.checkArgument(Strings.isNotBlank(kerberosID),
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 a24e770..047878f 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
@@ -302,6 +302,7 @@ public final class OmUtils {
     case Prepare:
     case CancelPrepare:
     case DeleteOpenKeys:
+    case SetS3Secret:
     case RevokeS3Secret:
     case PurgePaths:
     case CreateTenant:
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
index c95f74d..6f83395 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
@@ -71,6 +71,7 @@ public enum OMAction implements AuditAction {
   LIST_STATUS,
 
   GET_S3_SECRET,
+  SET_S3_SECRET,
   REVOKE_S3_SECRET,
 
   CREATE_TENANT,
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBAccessIdInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBAccessIdInfo.java
index 69b4404..7488603 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBAccessIdInfo.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBAccessIdInfo.java
@@ -29,13 +29,13 @@ public final class OmDBAccessIdInfo {
    */
   private final String tenantId;
   /**
-   * Kerberos principal this accessId belongs to.
+   * User principal this accessId belongs to.
    */
-  private final String kerberosPrincipal;
+  private final String userPrincipal;
   /**
-   * Shared secret of the accessId.
+   * Corresponding secret key for the accessId.
    */
-  private final String sharedSecret;
+  private final String secretKey;
   /**
    * Whether this accessId is an administrator of the tenant.
    */
@@ -50,11 +50,11 @@ public final class OmDBAccessIdInfo {
   public static final String SERIALIZATION_SPLIT_KEY = ";";
 
   public OmDBAccessIdInfo(String tenantId,
-      String kerberosPrincipal, String sharedSecret,
-      boolean isAdmin, boolean isDelegatedAdmin) {
+                          String userPrincipal, String secretKey,
+                          boolean isAdmin, boolean isDelegatedAdmin) {
     this.tenantId = tenantId;
-    this.kerberosPrincipal = kerberosPrincipal;
-    this.sharedSecret = sharedSecret;
+    this.userPrincipal = userPrincipal;
+    this.secretKey = secretKey;
     this.isAdmin = isAdmin;
     this.isDelegatedAdmin = isDelegatedAdmin;
   }
@@ -65,8 +65,8 @@ public final class OmDBAccessIdInfo {
         "Incorrect accessIdInfoString");
 
     tenantId = tInfo[0];
-    kerberosPrincipal = tInfo[1];
-    sharedSecret = tInfo[2];
+    userPrincipal = tInfo[1];
+    secretKey = tInfo[2];
     if (tInfo.length == 5) {
       isAdmin = Boolean.parseBoolean(tInfo[3]);
       isDelegatedAdmin = Boolean.parseBoolean(tInfo[4]);
@@ -83,8 +83,8 @@ public final class OmDBAccessIdInfo {
   private String serialize() {
     final StringBuilder sb = new StringBuilder();
     sb.append(tenantId);
-    sb.append(SERIALIZATION_SPLIT_KEY).append(kerberosPrincipal);
-    sb.append(SERIALIZATION_SPLIT_KEY).append(sharedSecret);
+    sb.append(SERIALIZATION_SPLIT_KEY).append(userPrincipal);
+    sb.append(SERIALIZATION_SPLIT_KEY).append(secretKey);
     sb.append(SERIALIZATION_SPLIT_KEY).append(isAdmin);
     sb.append(SERIALIZATION_SPLIT_KEY).append(isDelegatedAdmin);
     return sb.toString();
@@ -106,12 +106,12 @@ public final class OmDBAccessIdInfo {
     return new OmDBAccessIdInfo(tInfo);
   }
 
-  public String getKerberosPrincipal() {
-    return kerberosPrincipal;
+  public String getUserPrincipal() {
+    return userPrincipal;
   }
 
-  public String getSharedSecret() {
-    return sharedSecret;
+  public String getSecretKey() {
+    return secretKey;
   }
 
   public boolean getIsAdmin() {
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBTenantInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBTenantInfo.java
index 2af2cae..302d403 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBTenantInfo.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDBTenantInfo.java
@@ -27,7 +27,7 @@ public final class OmDBTenantInfo {
   /**
    * Name of the tenant.
    */
-  private final String tenantName;
+  private final String tenantId;
   /**
    * Name of the tenant's bucket namespace.
    */
@@ -47,10 +47,10 @@ public final class OmDBTenantInfo {
   // Implies above names should NOT contain the split key.
   public static final String TENANT_INFO_SPLIT_KEY = ";";
 
-  public OmDBTenantInfo(String tenantName,
+  public OmDBTenantInfo(String tenantId,
       String bucketNamespaceName, String accountNamespaceName,
       String userPolicyGroupName, String bucketPolicyGroupName) {
-    this.tenantName = tenantName;
+    this.tenantId = tenantId;
     this.bucketNamespaceName = bucketNamespaceName;
     this.accountNamespaceName = accountNamespaceName;
     this.userPolicyGroupName = userPolicyGroupName;
@@ -62,20 +62,20 @@ public final class OmDBTenantInfo {
     Preconditions.checkState(tInfo.length == 5,
         "Incorrect tenantInfoString");
 
-    tenantName = tInfo[0];
+    tenantId = tInfo[0];
     bucketNamespaceName = tInfo[1];
     accountNamespaceName = tInfo[2];
     userPolicyGroupName = tInfo[3];
     bucketPolicyGroupName = tInfo[4];
   }
 
-  public String getTenantName() {
-    return tenantName;
+  public String getTenantId() {
+    return tenantId;
   }
 
   private String generateTenantInfo() {
     StringBuilder sb = new StringBuilder();
-    sb.append(tenantName).append(TENANT_INFO_SPLIT_KEY);
+    sb.append(tenantId).append(TENANT_INFO_SPLIT_KEY);
     sb.append(bucketNamespaceName).append(TENANT_INFO_SPLIT_KEY);
     sb.append(accountNamespaceName).append(TENANT_INFO_SPLIT_KEY);
     sb.append(userPolicyGroupName).append(TENANT_INFO_SPLIT_KEY);
@@ -122,7 +122,7 @@ public final class OmDBTenantInfo {
    */
   @SuppressWarnings("checkstyle:hiddenfield")
   public static final class Builder {
-    private String tenantName;
+    private String tenantId;
     private String bucketNamespaceName;
     private String accountNamespaceName;
     private String userPolicyGroupName;
@@ -131,8 +131,8 @@ public final class OmDBTenantInfo {
     private Builder() {
     }
 
-    public Builder setTenantName(String tenantName) {
-      this.tenantName = tenantName;
+    public Builder setTenantId(String tenantId) {
+      this.tenantId = tenantId;
       return this;
     }
 
@@ -157,7 +157,7 @@ public final class OmDBTenantInfo {
     }
 
     public OmDBTenantInfo build() {
-      return new OmDBTenantInfo(tenantName, bucketNamespaceName,
+      return new OmDBTenantInfo(tenantId, bucketNamespaceName,
           accountNamespaceName, userPolicyGroupName, bucketPolicyGroupName);
     }
   }
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantArgs.java
index 5a59af5..8c500d2 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantArgs.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantArgs.java
@@ -22,13 +22,14 @@ package org.apache.hadoop.ozone.om.helpers;
  * This class is used for storing Ozone tenant arguments.
  */
 public class OmTenantArgs {
-  private final String tenantName;
+  /* Tenant name */
+  private final String tenantId;
 
-  public OmTenantArgs(String tenantName) {
-    this.tenantName = tenantName;
+  public OmTenantArgs(String tenantId) {
+    this.tenantId = tenantId;
   }
 
-  public String getTenantName() {
-    return tenantName;
+  public String getTenantId() {
+    return tenantId;
   }
 }
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantUserArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantUserArgs.java
index 0d52f4b..83b1652 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantUserArgs.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmTenantUserArgs.java
@@ -19,22 +19,22 @@
 package org.apache.hadoop.ozone.om.helpers;
 
 /**
- * This class is used for storing tenant user arguments.
+ * This class is used for storing tenant user arguments. Unused for now.
  */
 public class OmTenantUserArgs {
   private final String tenantUsername;
-  private final String tenantName;
+  private final String tenantId;
 
-  public OmTenantUserArgs(String tenantUsername, String tenantName) {
+  public OmTenantUserArgs(String tenantUsername, String tenantId) {
     this.tenantUsername = tenantUsername;
-    this.tenantName = tenantName;
+    this.tenantId = tenantId;
   }
 
   public String getTenantUsername() {
     return tenantUsername;
   }
 
-  public String getTenantName() {
-    return tenantName;
+  public String getTenantId() {
+    return tenantId;
   }
 }
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/S3SecretValue.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/S3SecretValue.java
index 5f65114..aa5839d 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/S3SecretValue.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/S3SecretValue.java
@@ -25,6 +25,7 @@ import java.util.Objects;
  * S3Secret to be saved in database.
  */
 public class S3SecretValue {
+  // TODO: This field should be renamed to accessId for generalization.
   private String kerberosID;
   private String awsSecret;
 
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/TenantUserList.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/TenantUserList.java
index acdaa7f..62f6a77 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/TenantUserList.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/TenantUserList.java
@@ -30,19 +30,18 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantU
  */
 public class TenantUserList {
 
-  private final String tenantName;
+  private final String tenantId;
 
   private final List<TenantUserAccessId> userAccessIds;
-
-
-  public TenantUserList(String tenantName,
+  
+  public TenantUserList(String tenantId,
                         List<TenantUserAccessId> userAccessIds) {
-    this.tenantName = tenantName;
+    this.tenantId = tenantId;
     this.userAccessIds = userAccessIds;
   }
 
-  public String getTenantName() {
-    return tenantName;
+  public String getTenantId() {
+    return tenantId;
   }
 
   public List<TenantUserAccessId> getUserAccessIds() {
@@ -56,7 +55,7 @@ public class TenantUserList {
 
   @Override
   public String toString() {
-    return "tenantName=" + tenantName +
+    return "tenantId=" + tenantId +
         "\nuserAccessIds=" + userAccessIds;
   }
 
@@ -69,12 +68,12 @@ public class TenantUserList {
       return false;
     }
     TenantUserList that = (TenantUserList) o;
-    return tenantName.equals(that.tenantName) &&
+    return tenantId.equals(that.tenantId) &&
         userAccessIds.equals(that.userAccessIds);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(tenantName, userAccessIds);
+    return Objects.hash(tenantId, userAccessIds);
   }
 }
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 fddeec2..63c1000 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
@@ -462,6 +462,16 @@ public interface OzoneManagerProtocol
           throws IOException;
 
   /**
+   * Set secret key for accessId.
+   * @param accessId
+   * @param secretKey
+   * @return S3SecretValue
+   * @throws IOException
+   */
+  S3SecretValue setS3Secret(String accessId, String secretKey)
+      throws IOException;
+
+  /**
    * Revokes s3Secret of given kerberos user.
    * @param kerberosID
    * @throws IOException
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 85b528f..97e3c2f 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
@@ -895,6 +895,27 @@ public final class OzoneManagerProtocolClientSideTranslatorPB
   }
 
   @Override
+  public S3SecretValue setS3Secret(String accessId, String secretKey)
+          throws IOException {
+    final SetS3SecretRequest request = SetS3SecretRequest.newBuilder()
+        .setAccessId(accessId)
+        .setSecretKey(secretKey)
+        .build();
+    OMRequest omRequest = createOMRequest(Type.SetS3Secret)
+        .setSetS3SecretRequest(request)
+        .build();
+    final SetS3SecretResponse resp = handleError(submitRequest(omRequest))
+        .getSetS3SecretResponse();
+
+    final S3Secret accessIdSecretKeyPair = S3Secret.newBuilder()
+        .setKerberosID(resp.getAccessId())
+        .setAwsSecret(resp.getSecretKey())
+        .build();
+
+    return S3SecretValue.fromProtobuf(accessIdSecretKeyPair);
+  }
+
+  @Override
   public void revokeS3Secret(String kerberosID) throws IOException {
     RevokeS3SecretRequest request = RevokeS3SecretRequest.newBuilder()
             .setKerberosID(kerberosID)
@@ -930,12 +951,12 @@ public final class OzoneManagerProtocolClientSideTranslatorPB
    */
   @Override
   public S3SecretValue tenantAssignUserAccessId(
-      String username, String tenantName, String accessId) throws IOException {
+      String username, String tenantId, String accessId) throws IOException {
 
     final TenantAssignUserAccessIdRequest request =
         TenantAssignUserAccessIdRequest.newBuilder()
         .setTenantUsername(username)
-        .setTenantName(tenantName)
+        .setTenantName(tenantId)
         .setAccessId(accessId)
         .build();
     final OMRequest omRequest = createOMRequest(Type.TenantAssignUserAccessId)
diff --git a/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-tenant.robot b/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-tenant.robot
index 82e80e7..3ad8c10 100644
--- a/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-tenant.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-tenant.robot
@@ -30,9 +30,9 @@ Init Ranger MockServer
                         Should contain   ${output}         {}
 
 *** Test Cases ***
-Secure Tenant Create Tenant Success
-#    Run Keyword   Kinit test user     testuser     testuser.keytab
+Secure Tenant Create Tenant Success with Cluster Admin
     Run Keyword         Init Ranger MockServer
+    Run Keyword   Kinit test user     testuser     testuser.keytab
     ${output} =         Execute          ozone tenant create tenantone
                         Should contain   ${output}         Created tenant 'tenantone'
 
@@ -44,7 +44,31 @@ Secure Tenant GetUserInfo Success
     ${output} =         Execute          ozone tenant user info bob
                         Should contain   ${output}         Tenant 'tenantone' with accessId 'tenantone$bob'
 
+Secure Tenant SetSecret Success with Cluster Admin
+    ${output} =         Execute          ozone tenant user setsecret 'tenantone$bob' --secret=somesecret1 --export
+                        Should contain   ${output}         export AWS_SECRET_ACCESS_KEY='somesecret1'
+
+Secure Tenant SetSecret Failure For Invalid Secret Input 1
+    ${rc}  ${output} =  Run And Return Rc And Output  ozone tenant user setsecret 'tenantone$bob' --secret='' --export
+                        Should contain   ${output}         secretKey cannot be null or empty.
+
+Secure Tenant SetSecret Failure For Invalid Secret Input 2
+    ${rc}  ${output} =  Run And Return Rc And Output  ozone tenant user setsecret 'tenantone$bob' --secret=short --export
+                        Should contain   ${output}         Secret key length should be at least 8 characters
+
+Secure Tenant GetSecret Success
+    ${output} =         Execute          ozone tenant user getsecret 'tenantone$bob' --export
+                        Should contain   ${output}         export AWS_SECRET_ACCESS_KEY='somesecret1'
+
 Secure Tenant Assign User Failure
-    ${rc}  ${result} =  Run And Return Rc And Output  ozone tenant user assign bob --tenant=thistenantdoesnotexist
-                        Should contain   ${result}         Tenant 'thistenantdoesnotexist' doesn't exist
+    ${rc}  ${output} =  Run And Return Rc And Output  ozone tenant user assign bob --tenant=thistenantdoesnotexist
+                        Should contain   ${output}         Tenant 'thistenantdoesnotexist' doesn't exist
+
+Secure Tenant Create Tenant Failure with Regular (non-admin) user
+    Run Keyword   Kinit test user     testuser2    testuser2.keytab
+    ${rc}  ${output} =  Run And Return Rc And Output  ozone tenant create tenanttwo
+                        Should contain   ${output}         Failed to create tenant 'tenanttwo': User 'testuser2/scm@EXAMPLE.COM' is not an Ozone admin.
 
+Secure Tenant SetSecret Failure with Regular (non-admin) user
+    ${rc}  ${output} =  Run And Return Rc And Output  ozone tenant user set-secret 'tenantone$bob' --secret=somesecret2 --export
+                        Should contain   ${output}         Permission denied. Requested accessId
diff --git a/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-token.robot b/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-token.robot
index a84d2ef..fad6d35 100644
--- a/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-token.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/security/ozone-secure-token.robot
@@ -23,6 +23,7 @@ Test Timeout        5 minutes
 
 *** Keywords ***
 Get and use Token in Secure Cluster
+    Run Keyword   Kinit test user     testuser     testuser.keytab
     Execute                      ozone sh token get -t /tmp/ozone.token
     File Should Not Be Empty     /tmp/ozone.token
     Execute                      kdestroy
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
index d5cc358..095b956 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
@@ -616,7 +616,7 @@ public final class TestSecureOzoneCluster {
   }
 
   @Test
-  public void testGetS3SecretAndRevokeS3Secret() throws Exception {
+  public void testGetSetRevokeS3Secret() throws Exception {
 
     // Setup secure OM for start
     setupOm(conf);
@@ -647,6 +647,15 @@ public final class TestSecureOzoneCluster {
       // Revoke the existing secret
       omClient.revokeS3Secret(username);
 
+      // Set secret should fail since the accessId is revoked
+      final String secretKeySet = "somesecret1";
+      try {
+        omClient.setS3Secret(username, secretKeySet);
+      } catch (OMException omEx) {
+        assertEquals(OMException.ResultCodes.ACCESSID_NOT_FOUND,
+            omEx.getResult());
+      }
+
       // Get a new secret
       S3SecretValue attempt3 = omClient.getS3Secret(username);
 
@@ -656,6 +665,12 @@ public final class TestSecureOzoneCluster {
       // accessKey is still the same because it is derived from username
       assertEquals(attempt3.getAwsAccessKey(), attempt2.getAwsAccessKey());
 
+      // Admin can set secret for any user
+      omClient.setS3Secret(username, secretKeySet);
+      assertEquals(secretKeySet, omClient.getS3Secret(username).getAwsSecret());
+      // Clean up
+      omClient.revokeS3Secret(username);
+
       // Admin can get and revoke other users' secrets
       // omClient's ugi is current user, which is added as an OM admin
       omClient.getS3Secret("HADOOP/ALICE");
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java
index c37e048..cacd212 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneTenantShell.java
@@ -33,6 +33,7 @@ import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessAuthorizerRangerP
 import org.apache.hadoop.ozone.om.request.s3.tenant.OMAssignUserToTenantRequest;
 import org.apache.hadoop.ozone.om.request.s3.tenant.OMTenantCreateRequest;
 import org.apache.hadoop.ozone.shell.tenant.TenantShell;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.ozone.test.GenericTestUtils;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -52,6 +53,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
+import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
 import java.util.List;
 import java.util.UUID;
@@ -591,4 +593,124 @@ public class TestOzoneTenantShell {
 
     // TODO: Clean up: remove tenant when tenant remove CLI is implemented
   }
+
+  @Test
+  public void testTenantSetSecret() throws IOException, InterruptedException {
+
+    final String tenantName = "tenant-test-set-secret";
+
+    // Create test tenant
+    executeHA(tenantShell, new String[] {"create", tenantName});
+    checkOutput(out, "Created tenant '" + tenantName + "'.\n", true);
+    checkOutput(err, "", true);
+
+    // Set secret for non-existent accessId. Expect failure
+    executeHA(tenantShell, new String[] {
+        "user", "set-secret", tenantName + "$alice", "--secret=somesecret0"});
+    checkOutput(out, "", true);
+    checkOutput(err, "AccessId '" + tenantName + "$alice' doesn't exist\n",
+        true);
+
+    // Assign a user to the tenant so that we have an accessId entry
+    executeHA(tenantShell, new String[] {
+        "user", "assign", "alice", "--tenant=" + tenantName});
+    checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" +
+        "export AWS_SECRET_ACCESS_KEY='", false);
+    checkOutput(err, "Assigned 'alice' to '" + tenantName + "'" +
+        " with accessId '" + tenantName + "$alice'.\n", true);
+
+    // Set secret as OM admin should succeed
+    executeHA(tenantShell, new String[] {
+        "user", "setsecret", tenantName + "$alice",
+        "--secret=somesecret1", "--export"});
+    checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" +
+        "export AWS_SECRET_ACCESS_KEY='somesecret1'\n", true);
+    checkOutput(err, "", true);
+
+    // Set empty secret key should fail
+    executeHA(tenantShell, new String[] {
+        "user", "setsecret", tenantName + "$alice",
+        "--secret=short", "--export"});
+    checkOutput(out, "", true);
+    checkOutput(err, "", true);
+    // Note: Exception thrown from OM to the client stderr is somehow not
+    //  captured in err, but is printed to the console output.
+
+    // Get secret should still give the previous secret key
+    executeHA(tenantShell, new String[] {
+        "user", "getsecret", tenantName + "$alice"});
+    checkOutput(out, "somesecret1", false);
+    checkOutput(err, "", true);
+
+    // Set secret as alice should succeed
+    final UserGroupInformation ugiAlice = UserGroupInformation
+        .createUserForTesting("alice",  new String[] {"usergroup"});
+
+    ugiAlice.doAs((PrivilegedExceptionAction<Void>) () -> {
+      executeHA(tenantShell, new String[] {
+          "user", "setsecret", tenantName + "$alice",
+          "--secret=somesecret2", "--export"});
+      checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" +
+          "export AWS_SECRET_ACCESS_KEY='somesecret2'\n", true);
+      checkOutput(err, "", true);
+      return null;
+    });
+
+    // Set secret as bob should fail
+    executeHA(tenantShell, new String[] {
+        "user", "assign", "bob", "--tenant=" + tenantName});
+    checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$bob'\n" +
+        "export AWS_SECRET_ACCESS_KEY='", false);
+    checkOutput(err, "Assigned 'bob' to '" + tenantName + "'" +
+        " with accessId '" + tenantName + "$bob'.\n", true);
+
+    final UserGroupInformation ugiBob = UserGroupInformation
+        .createUserForTesting("bob",  new String[] {"usergroup"});
+
+    ugiBob.doAs((PrivilegedExceptionAction<Void>) () -> {
+      executeHA(tenantShell, new String[] {
+          "user", "setsecret", tenantName + "$alice",
+          "--secret=somesecret2", "--export"});
+      checkOutput(out, "", true);
+      checkOutput(err, "", true);
+      // Note: Exception thrown from OM to the client stderr is somehow not
+      //  captured in err, but is printed to the console output.
+      return null;
+    });
+
+    // Once we make bob an admin of this tenant, set secret should succeed
+    executeHA(tenantShell, new String[] {"user", "assign-admin",
+        tenantName + "$" + ugiBob.getShortUserName(),
+        "--tenant=" + tenantName, "--delegated=true"});
+    checkOutput(out, "", true);
+    checkOutput(err, "Assigned admin", false);
+
+    ugiBob.doAs((PrivilegedExceptionAction<Void>) () -> {
+      executeHA(tenantShell, new String[] {
+          "user", "setsecret", tenantName + "$alice",
+          "--secret=somesecret2", "--export"});
+      checkOutput(out, "export AWS_ACCESS_KEY_ID='" + tenantName + "$alice'\n" +
+          "export AWS_SECRET_ACCESS_KEY='somesecret2'\n", true);
+      checkOutput(err, "", true);
+      return null;
+    });
+
+    // Clean up
+    executeHA(tenantShell, new String[] {"user", "revoke-admin",
+        tenantName + "$" + ugiBob.getShortUserName()});
+    checkOutput(out, "", true);
+    checkOutput(err, "Revoked admin", false);
+
+    executeHA(tenantShell, new String[] {
+        "user", "revoke", tenantName + "$bob"});
+    checkOutput(out, "", true);
+    checkOutput(err, "Revoked accessId", false);
+
+    executeHA(tenantShell, new String[] {
+        "user", "revoke", tenantName + "$alice"});
+    checkOutput(out, "", true);
+    checkOutput(err, "Revoked accessId", false);
+
+    // TODO: Clean up: remove tenant when tenant remove CLI is implemented
+  }
 }
diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 87ae19f..b0ff9a9 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -117,6 +117,8 @@ enum Type {
 
   GetS3Volume = 104;
   TenantListUser = 105;
+
+  SetS3Secret = 106;
 }
 
 message OMRequest {
@@ -213,7 +215,9 @@ message OMRequest {
   optional TenantRevokeAdminRequest         TenantRevokeAdminRequest       = 102;
 
   optional GetS3VolumeRequest               getS3VolumeRequest             = 104;
-  optional TenantListUserRequest            tenantListUserRequest         = 105;
+  optional TenantListUserRequest            tenantListUserRequest          = 105;
+
+  optional SetS3SecretRequest               SetS3SecretRequest             = 106;
 }
 
 message OMResponse {
@@ -306,6 +310,8 @@ message OMResponse {
 
   optional GetS3VolumeResponse               getS3VolumeResponse           = 104;
   optional TenantListUserResponse            tenantListUserResponse        = 105;
+
+  optional SetS3SecretResponse               SetS3SecretResponse           = 106;
 }
 
 enum Status {
@@ -1383,13 +1389,14 @@ message GetS3SecretResponse {
     required S3Secret s3Secret = 2;
 }
 
-message SetSecretRequest {
+message SetS3SecretRequest {
     optional string accessId = 1;
-    optional string secret = 2;
+    optional string secretKey = 2;
 }
 
-message SetSecretResponse {
-    optional bool success = 1;
+message SetS3SecretResponse {
+    optional string accessId = 1;
+    optional string secretKey = 2;
 }
 
 message TenantInfo {
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 1ffd6b4..c9aa568 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
@@ -307,7 +307,7 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
         return;
       }
       tenantCache.get(tenantName).getTenantUsers()
-          .remove(new ImmutablePair<>(omDBAccessIdInfo.getKerberosPrincipal(),
+          .remove(new ImmutablePair<>(omDBAccessIdInfo.getUserPrincipal(),
               accessID));
       // TODO: Determine how to replace this code.
 //      final String userID = authorizer.getUserId(userPrincipal);
@@ -327,7 +327,7 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
       OmDBAccessIdInfo omDBAccessIdInfo =
           omMetadataManager.getTenantAccessIdTable().get(accessId);
       if (omDBAccessIdInfo != null) {
-        String userName = omDBAccessIdInfo.getKerberosPrincipal();
+        String userName = omDBAccessIdInfo.getUserPrincipal();
         LOG.debug("Username for accessId {} = {}", accessId, userName);
         return userName;
       }
@@ -599,7 +599,7 @@ public class OMMultiTenantManagerImpl implements OMMultiTenantManager {
         String accessId = next.getKey();
         OmDBAccessIdInfo value = next.getValue();
         String tenantId = value.getTenantId();
-        String user = value.getKerberosPrincipal();
+        String user = value.getUserPrincipal();
 
         CachedTenantInfo cachedTenantInfo = tenantCache
             .computeIfAbsent(tenantId, k -> new CachedTenantInfo(tenantId));
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 9be641a..e8b1ea0 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
@@ -3150,9 +3150,9 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
     while (iterator.hasNext()) {
       final Table.KeyValue<String, OmDBTenantInfo> dbEntry = iterator.next();
       final OmDBTenantInfo omDBTenantInfo = dbEntry.getValue();
-      assert(dbEntry.getKey().equals(omDBTenantInfo.getTenantName()));
+      assert(dbEntry.getKey().equals(omDBTenantInfo.getTenantId()));
       tenantInfoList.add(TenantInfo.newBuilder()
-          .setTenantName(omDBTenantInfo.getTenantName())
+          .setTenantName(omDBTenantInfo.getTenantId())
           .setBucketNamespaceName(omDBTenantInfo.getBucketNamespaceName())
           .setAccountNamespaceName(omDBTenantInfo.getAccountNamespaceName())
           .setUserPolicyGroupName(omDBTenantInfo.getUserPolicyGroupName())
@@ -3200,7 +3200,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
               accessId);
           throw new NullPointerException("accessIdInfo is null");
         }
-        assert(accessIdInfo.getKerberosPrincipal().equals(userPrincipal));
+        assert(accessIdInfo.getUserPrincipal().equals(userPrincipal));
         accessIdInfoList.add(TenantAccessIdInfo.newBuilder()
             .setAccessId(accessId)
             .setTenantName(accessIdInfo.getTenantId())
@@ -3258,16 +3258,16 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
   @Override
   public OmVolumeArgs getS3Volume(String accessID) throws IOException {
 
-    String tenantName;
+    String tenantId;
     try {
-      tenantName = multiTenantManagr.getTenantForAccessID(accessID);
+      tenantId = multiTenantManagr.getTenantForAccessID(accessID);
       if (LOG.isDebugEnabled()) {
         LOG.debug("Get S3 volume request for access ID {} belonging to tenant" +
-                " {} is directed to the volume {}.", accessID, tenantName,
-            tenantName);
+                " {} is directed to the volume {}.", accessID, tenantId,
+            tenantId);  // TODO: Get volume name from DB. Do not assume the same
       }
       // This call performs acl checks and checks volume existence.
-      return getVolumeInfo(tenantName);
+      return getVolumeInfo(tenantId);
 
     } catch (OMException ex) {
       if (ex.getResult().equals(INVALID_ACCESSID)) {
@@ -3287,9 +3287,12 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
   }
 
   @Override
-  /**
-   * {@inheritDoc}
-   */
+  public S3SecretValue setS3Secret(String accessId, String secretKey) {
+    throw new UnsupportedOperationException("OzoneManager does not require " +
+            "this to be implemented. As write requests use a new approach");
+  }
+
+  @Override
   public void revokeS3Secret(String kerberosID) {
     throw new UnsupportedOperationException("OzoneManager does not require " +
             "this to be implemented. As write requests use a new approach");
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
index eb28310..0ce987b 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
@@ -77,6 +77,7 @@ import org.apache.hadoop.ozone.om.request.s3.multipart.S3MultipartUploadCommitPa
 import org.apache.hadoop.ozone.om.request.s3.multipart.S3MultipartUploadCommitPartRequestWithFSO;
 import org.apache.hadoop.ozone.om.request.s3.multipart.S3MultipartUploadCompleteRequest;
 import org.apache.hadoop.ozone.om.request.s3.multipart.S3MultipartUploadCompleteRequestWithFSO;
+import org.apache.hadoop.ozone.om.request.s3.security.OMSetSecretRequest;
 import org.apache.hadoop.ozone.om.request.s3.security.S3GetSecretRequest;
 import org.apache.hadoop.ozone.om.request.s3.security.S3RevokeSecretRequest;
 import org.apache.hadoop.ozone.om.request.s3.tenant.OMAssignUserToTenantRequest;
@@ -257,6 +258,8 @@ public final class OzoneManagerRatisUtils {
       return new OMPrepareRequest(omRequest);
     case CancelPrepare:
       return new OMCancelPrepareRequest(omRequest);
+    case SetS3Secret:
+      return new OMSetSecretRequest(omRequest);
     case RevokeS3Secret:
       return new S3RevokeSecretRequest(omRequest);
     case CreateTenant:
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/OMSetSecretRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/OMSetSecretRequest.java
new file mode 100644
index 0000000..d183015
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/OMSetSecretRequest.java
@@ -0,0 +1,233 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.request.s3.security;
+
+import com.google.common.base.Optional;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
+import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
+import org.apache.hadoop.ipc.ProtobufRpcEngine;
+import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.audit.OMAction;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.helpers.OmDBAccessIdInfo;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
+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;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.om.response.s3.security.OMSetSecretResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.*;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.S3_SECRET_LOCK;
+import static org.apache.hadoop.ozone.om.request.s3.tenant.OMTenantRequestHelper.isUserAccessIdPrincipalOrTenantAdmin;
+
+/**
+ * Handles SetSecret request.
+ */
+public class OMSetSecretRequest extends OMClientRequest {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(OMSetSecretRequest.class);
+
+  public OMSetSecretRequest(OMRequest omRequest) {
+    super(omRequest);
+  }
+
+  @Override
+  public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
+    final OMMetadataManager omMetadataManager =
+        ozoneManager.getMetadataManager();
+
+    final SetS3SecretRequest request =
+        getOmRequest().getSetS3SecretRequest();
+
+    final String accessId = request.getAccessId();
+
+    // First check accessId existence
+    final OmDBAccessIdInfo accessIdInfo = omMetadataManager
+        .getTenantAccessIdTable().get(accessId);
+
+    if (accessIdInfo == null) {
+      // Check (old) S3SecretTable
+      if (omMetadataManager.getS3SecretTable().get(accessId) == null) {
+        throw new OMException("accessId '" + accessId + "' not found.",
+            OMException.ResultCodes.ACCESSID_NOT_FOUND);
+      }
+    }
+
+    // Secret should not be empty
+    final String secretKey = request.getSecretKey();
+    if (StringUtils.isEmpty(secretKey)) {
+      throw new OMException("Secret key should not be empty",
+              OMException.ResultCodes.INVALID_REQUEST);
+    }
+
+    if (secretKey.length() < OzoneConsts.S3_SECRET_KEY_MIN_LENGTH) {
+      throw new OMException("Secret key length should be at least " +
+          OzoneConsts.S3_SECRET_KEY_MIN_LENGTH + " characters",
+          OMException.ResultCodes.INVALID_REQUEST);
+    }
+
+    // TODO: Check if secretKey matches other requirements? e.g. combination
+
+    final UserGroupInformation ugi = ProtobufRpcEngine.Server.getRemoteUser();
+    final String username = ugi.getUserName();
+
+    // Permission check. To pass the check, any one of the following conditions
+    // shall be satisfied:
+    // 1. username matches accessId exactly
+    // 2. user is an OM admin
+    // 3. user is assigned to a tenant under this accessId
+    // 4. user is an admin of the tenant where the accessId is assigned
+
+    if (!username.equals(accessId) && !ozoneManager.isAdmin(ugi)) {
+      // Attempt to retrieve tenant info using the accessId
+      if (!isUserAccessIdPrincipalOrTenantAdmin(ozoneManager, accessId, ugi)) {
+        throw new OMException("Permission denied. Requested accessId '" +
+                accessId + "' and user doesn't satisfy any of:\n" +
+                "1) accessId match current username: '" + username + "';\n" +
+                "2) is an OM admin;\n" +
+                "3) user is assigned to a tenant under this accessId;\n" +
+                "4) user is an admin of the tenant where the accessId is " +
+                "assigned", OMException.ResultCodes.PERMISSION_DENIED);
+      }
+    }
+
+    return getOmRequest();
+  }
+
+  @Override
+  public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
+      long transactionLogIndex,
+      OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) {
+
+    OMClientResponse omClientResponse = null;
+    OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(
+        getOmRequest());
+    boolean acquiredLock = false;
+    IOException exception = null;
+    OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
+
+    final SetS3SecretRequest request = getOmRequest().getSetS3SecretRequest();
+    final String accessId = request.getAccessId();
+    final String secretKey = request.getSecretKey();
+
+    try {
+      acquiredLock = omMetadataManager.getLock().acquireWriteLock(
+          S3_SECRET_LOCK, accessId);
+
+      // Intentionally set to final so they can only be set once.
+      final S3SecretValue newS3SecretValue;
+      final OmDBAccessIdInfo newDBAccessIdInfo;
+
+      // Get accessId entry from multi-tenant TenantAccessIdTable
+      final OmDBAccessIdInfo omDBAccessIdInfo =
+          omMetadataManager.getTenantAccessIdTable().get(accessId);
+
+      // Check accessId existence in TenantAccessIdTable
+      if (omDBAccessIdInfo == null) {
+        // accessId doesn't exist in TenantAccessIdTable, check S3SecretTable
+        if (omMetadataManager.getS3SecretTable().get(accessId) == null) {
+          throw new OMException("accessId '" + accessId + "' not found.",
+              OMException.ResultCodes.ACCESSID_NOT_FOUND);
+        }
+
+        // accessId found in S3SecretTable. Update S3SecretTable
+        LOG.debug("Updating S3SecretTable cache entry");
+        // Update S3SecretTable cache entry in this case
+        newS3SecretValue = new S3SecretValue(accessId, secretKey);
+        newDBAccessIdInfo = null;
+
+        omMetadataManager.getS3SecretTable().addCacheEntry(
+            new CacheKey<>(accessId),
+            new CacheValue<>(Optional.of(newS3SecretValue),
+                transactionLogIndex));
+
+      } else {
+
+        // Update TenantAccessIdTable
+        // Build new OmDBAccessIdInfo with updated secret
+        LOG.debug("Updating TenantAccessIdTable cache entry");
+        newS3SecretValue = null;
+        newDBAccessIdInfo = new OmDBAccessIdInfo.Builder()
+            .setTenantId(omDBAccessIdInfo.getTenantId())
+            .setKerberosPrincipal(omDBAccessIdInfo.getUserPrincipal())
+            .setSharedSecret(secretKey)
+            .setIsAdmin(omDBAccessIdInfo.getIsAdmin())
+            .setIsDelegatedAdmin(omDBAccessIdInfo.getIsDelegatedAdmin())
+            .build();
+
+        // Update TenantAccessIdTable cache entry
+        omMetadataManager.getTenantAccessIdTable().addCacheEntry(
+            new CacheKey<>(accessId),
+            new CacheValue<>(Optional.of(newDBAccessIdInfo),
+                transactionLogIndex));
+      }
+
+      // Compose response
+      final SetS3SecretResponse.Builder setSecretResponse =
+          SetS3SecretResponse.newBuilder()
+              .setAccessId(accessId)
+              .setSecretKey(secretKey);
+
+      omClientResponse = new OMSetSecretResponse(accessId,
+          newDBAccessIdInfo, newS3SecretValue,
+          omResponse.setSetS3SecretResponse(setSecretResponse).build());
+
+    } catch (IOException ex) {
+      exception = ex;
+      omClientResponse = new OMSetSecretResponse(
+          createErrorOMResponse(omResponse, ex));
+    } finally {
+      addResponseToDoubleBuffer(transactionLogIndex, omClientResponse,
+          ozoneManagerDoubleBufferHelper);
+      if (acquiredLock) {
+        omMetadataManager.getLock().releaseWriteLock(S3_SECRET_LOCK,
+            accessId);
+      }
+    }
+
+    final Map<String, String> auditMap = new HashMap<>();
+    auditMap.put(OzoneConsts.S3_SETSECRET_USER, accessId);
+
+    // audit log
+    auditLog(ozoneManager.getAuditLogger(), buildAuditMessage(
+        OMAction.SET_S3_SECRET, auditMap,
+        exception, getOmRequest().getUserInfo()));
+
+    if (exception == null) {
+      LOG.debug("Success: SetSecret for accessKey '{}'", accessId);
+    } else {
+      LOG.error("Failed to SetSecret for accessKey '{}': {}",
+          accessId, exception);
+    }
+    return omClientResponse;
+  }
+
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/S3GetSecretRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/S3GetSecretRequest.java
index 9cb03c1..9e737c4 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/S3GetSecretRequest.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/S3GetSecretRequest.java
@@ -181,6 +181,8 @@ public class S3GetSecretRequest extends OMClientRequest {
                     new CacheKey<>(accessId),
                     new CacheValue<>(Optional.of(assignS3SecretValue),
                             transactionLogIndex));
+            // TODO: Put accessId entry straight to TenantAccessIdTable
+            //  later when we deprecate the S3SecretTable.
           } else {
             assignS3SecretValue = null;
           }
@@ -191,7 +193,7 @@ public class S3GetSecretRequest extends OMClientRequest {
         }
       } else {
         // Found in TenantAccessIdTable.
-        awsSecret = omDBAccessIdInfo.getSharedSecret();
+        awsSecret = omDBAccessIdInfo.getSecretKey();
         assignS3SecretValue = null;
       }
 
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantAssignAdminRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantAssignAdminRequest.java
index b99426c..9e04d55 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantAssignAdminRequest.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantAssignAdminRequest.java
@@ -185,8 +185,8 @@ public class OMTenantAssignAdminRequest extends OMClientRequest {
       final OmDBAccessIdInfo newOmDBAccessIdInfo =
           new OmDBAccessIdInfo.Builder()
           .setTenantId(oldAccessIdInfo.getTenantId())
-          .setKerberosPrincipal(oldAccessIdInfo.getKerberosPrincipal())
-          .setSharedSecret(oldAccessIdInfo.getSharedSecret())
+          .setKerberosPrincipal(oldAccessIdInfo.getUserPrincipal())
+          .setSharedSecret(oldAccessIdInfo.getSecretKey())
           .setIsAdmin(true)
           .setIsDelegatedAdmin(delegated)
           .build();
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantCreateRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantCreateRequest.java
index d1c8283..d0c0de4 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantCreateRequest.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantCreateRequest.java
@@ -111,22 +111,22 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
   @Override
   public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
     final CreateTenantRequest request = getOmRequest().getCreateTenantRequest();
-    final String tenantName = request.getTenantName();
+    final String tenantId = request.getTenantName();
 
     // Check Ozone admin privilege
     OMTenantRequestHelper.checkAdmin(ozoneManager);
 
-    // Check tenantName validity
-    if (tenantName.contains(OzoneConsts.TENANT_NAME_USER_NAME_DELIMITER)) {
-      throw new OMException("Invalid tenant name " + tenantName +
+    // Check tenantId validity
+    if (tenantId.contains(OzoneConsts.TENANT_NAME_USER_NAME_DELIMITER)) {
+      throw new OMException("Invalid tenant name " + tenantId +
           ". Tenant name should not contain delimiter.",
           OMException.ResultCodes.INVALID_VOLUME_NAME);
     }
 
     // Check tenant existence in tenantStateTable
     if (ozoneManager.getMetadataManager().getTenantStateTable()
-        .isExist(tenantName)) {
-      LOG.debug("tenant: {} already exists", tenantName);
+        .isExist(tenantId)) {
+      LOG.debug("tenant: {} already exists", tenantId);
       throw new OMException("Tenant already exists",
           TENANT_ALREADY_EXISTS);
     }
@@ -141,7 +141,10 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
     // A caveat is that this assumes OM's auth_to_local is the same as
     //  the client's. Maybe move this logic to the client and pass VolumeArgs?
     final String owner = ugi.getShortUserName();
-    final String volumeName = tenantName;  // TODO: Configurable
+    final String volumeName = tenantId;  // TODO: Configurable
+    // Validate volume name
+    OmUtils.validateVolumeName(volumeName);
+    // TODO: Refactor this and OMVolumeCreateRequest to improve maintainability.
     final VolumeInfo volumeInfo = VolumeInfo.newBuilder()
         .setVolume(volumeName)
         .setAdminName(owner)
@@ -162,7 +165,7 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
     // If we fail after pre-execute. handleRequestFailure() callback
     // would clean up any state maintained by the getMultiTenantManager.
     tenantInContext = ozoneManager.getMultiTenantManager()
-        .createTenantAccessInAuthorizer(tenantName);
+        .createTenantAccessInAuthorizer(tenantId);
 
     // Get the tenant default policy, pass this along
     final String tenantDefaultPolicies = tenantInContext
@@ -174,7 +177,7 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
         .setCreateTenantRequest(
             CreateTenantRequest.newBuilder()
                 .setTenantDefaultPolicyName(tenantDefaultPolicies)
-                .setTenantName(tenantName))
+                .setTenantName(tenantId))
         .setCreateVolumeRequest(
             CreateVolumeRequest.newBuilder().setVolumeInfo(updatedVolumeInfo))
         .setUserInfo(getUserInfo())
@@ -218,7 +221,7 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
     Map<String, String> auditMap = new HashMap<>();
     OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
     CreateTenantRequest request = getOmRequest().getCreateTenantRequest();
-    final String tenantName = request.getTenantName();
+    final String tenantId = request.getTenantName();
     final VolumeInfo volumeInfo =
         getOmRequest().getCreateVolumeRequest().getVolumeInfo();
     final String volumeName = volumeInfo.getVolume();
@@ -233,7 +236,7 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
       if (ozoneManager.getAclsEnabled()) {
         checkAcls(ozoneManager, OzoneObj.ResourceType.VOLUME,
             OzoneObj.StoreType.OZONE, IAccessAuthorizer.ACLType.CREATE,
-            tenantName, null, null);
+            tenantId, null, null);
       }
 
       acquiredVolumeLock = omMetadataManager.getLock().acquireWriteLock(
@@ -244,23 +247,23 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
         throw new OMException("Volume already exists", VOLUME_ALREADY_EXISTS);
       }
       // Check tenant existence in tenantStateTable
-      if (omMetadataManager.getTenantStateTable().isExist(tenantName)) {
-        LOG.debug("tenant: {} already exists", tenantName);
+      if (omMetadataManager.getTenantStateTable().isExist(tenantId)) {
+        LOG.debug("tenant: {} already exists", tenantId);
         throw new OMException("Tenant already exists", TENANT_ALREADY_EXISTS);
       }
 
       // Add to tenantStateTable. Redundant assignment for clarity
-      final String bucketNamespaceName = tenantName;
+      final String bucketNamespaceName = tenantId;
       final String accountNamespaceName = volumeName;
       final String userPolicyGroupName =
-          tenantName + OzoneConsts.DEFAULT_TENANT_USER_POLICY_SUFFIX;
+          tenantId + OzoneConsts.DEFAULT_TENANT_USER_POLICY_SUFFIX;
       final String bucketPolicyGroupName =
-          tenantName + OzoneConsts.DEFAULT_TENANT_BUCKET_POLICY_SUFFIX;
+          tenantId + OzoneConsts.DEFAULT_TENANT_BUCKET_POLICY_SUFFIX;
       final OmDBTenantInfo omDBTenantInfo = new OmDBTenantInfo(
-          tenantName, bucketNamespaceName, accountNamespaceName,
+          tenantId, bucketNamespaceName, accountNamespaceName,
           userPolicyGroupName, bucketPolicyGroupName);
       omMetadataManager.getTenantStateTable().addCacheEntry(
-          new CacheKey<>(tenantName),
+          new CacheKey<>(tenantId),
           new CacheValue<>(Optional.of(omDBTenantInfo), transactionLogIndex));
 
       // Add to tenantPolicyTable
@@ -340,17 +343,17 @@ public class OMTenantCreateRequest extends OMVolumeRequest {
     }
 
     // Perform audit logging
-    auditMap.put(OzoneConsts.TENANT, tenantName);
+    auditMap.put(OzoneConsts.TENANT, tenantId);
     // Note auditMap contains volume creation info
     auditLog(ozoneManager.getAuditLogger(),
         buildAuditMessage(OMAction.CREATE_TENANT, auditMap, exception,
             getOmRequest().getUserInfo()));
 
     if (exception == null) {
-      LOG.info("Created tenant '{}' and volume '{}'", tenantName, volumeName);
+      LOG.info("Created tenant '{}' and volume '{}'", tenantId, volumeName);
       // TODO: omMetrics.incNumTenants()
     } else {
-      LOG.error("Failed to create tenant '{}'", tenantName, exception);
+      LOG.error("Failed to create tenant '{}'", tenantId, exception);
       // TODO: omMetrics.incNumTenantCreateFails()
     }
     return omClientResponse;
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRequestHelper.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRequestHelper.java
index 9b03762..190861f 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRequestHelper.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRequestHelper.java
@@ -119,25 +119,67 @@ public final class OMTenantRequestHelper {
     return volumeName;
   }
 
-  static String getTenantNameFromAccessId(OMMetadataManager omMetadataManager,
-      String accessId) throws IOException {
+  public static String getTenantNameFromAccessId(
+      OMMetadataManager omMetadataManager, String accessId) throws IOException {
 
     final OmDBAccessIdInfo accessIdInfo = omMetadataManager
         .getTenantAccessIdTable().get(accessId);
 
     if (accessIdInfo == null) {
-      throw new OMException("OmDBAccessIdInfo entry is missing for accessId '" +
-          accessId + "'.", OMException.ResultCodes.METADATA_ERROR);
+      throw new OMException("OmDBAccessIdInfo is missing for accessId '" +
+          accessId + "' in DB.", OMException.ResultCodes.METADATA_ERROR);
     }
 
-    final String tenantName = accessIdInfo.getTenantId();
+    final String tenantId = accessIdInfo.getTenantId();
 
-    if (StringUtils.isEmpty(tenantName)) {
+    if (StringUtils.isEmpty(tenantId)) {
       throw new OMException("tenantId field is null or empty for accessId '" +
           accessId + "'.", OMException.ResultCodes.METADATA_ERROR);
     }
 
-    return tenantName;
+    return tenantId;
+  }
+
+  public static boolean isUserAccessIdPrincipalOrTenantAdmin(
+          OzoneManager ozoneManager, String accessId,
+          UserGroupInformation ugi) throws IOException {
+
+    final OmDBAccessIdInfo accessIdInfo = ozoneManager.getMetadataManager()
+            .getTenantAccessIdTable().get(accessId);
+
+    if (accessIdInfo == null) {
+      // Doesn't have the accessId entry in TenantAccessIdTable.
+      // Probably came from `ozone s3 getsecret` with older OM.
+      return false;
+    }
+
+    final String tenantName = accessIdInfo.getTenantId();
+    // Sanity check
+    if (tenantName == null) {
+      throw new OMException("Unexpected error: OmDBAccessIdInfo " +
+              "tenantId field should not have been null",
+              OMException.ResultCodes.METADATA_ERROR);
+    }
+
+    final String accessIdPrincipal = accessIdInfo.getUserPrincipal();
+    // Sanity check
+    if (accessIdPrincipal == null) {
+      throw new OMException("Unexpected error: OmDBAccessIdInfo " +
+              "kerberosPrincipal field should not have been null",
+              OMException.ResultCodes.METADATA_ERROR);
+    }
+
+    // Check if ugi matches the holder of the accessId
+    if (ugi.getShortUserName().equals(accessIdPrincipal)) {
+      return true;
+    }
+
+    // Check if ugi is an admin of this tenant
+    if (ozoneManager.isTenantAdmin(ugi, tenantName, true)) {
+      return true;
+    }
+
+    return false;
   }
 
 }
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeAdminRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeAdminRequest.java
index b725e34..d441a54 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeAdminRequest.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeAdminRequest.java
@@ -72,16 +72,16 @@ public class OMTenantRevokeAdminRequest extends OMClientRequest {
         getOmRequest().getTenantRevokeAdminRequest();
 
     final String accessId = request.getAccessId();
-    String tenantName = request.getTenantName();
+    String tenantId = request.getTenantName();
 
-    // If tenantName is not provided, figure it out from the table
-    if (StringUtils.isEmpty(tenantName)) {
-      tenantName = OMTenantRequestHelper.getTenantNameFromAccessId(
+    // If tenant name is not specified, try figuring it out from accessId.
+    if (StringUtils.isEmpty(tenantId)) {
+      tenantId = OMTenantRequestHelper.getTenantNameFromAccessId(
           ozoneManager.getMetadataManager(), accessId);
     }
 
     // Caller should be an Ozone admin or this tenant's delegated admin
-    OMTenantRequestHelper.checkTenantAdmin(ozoneManager, tenantName);
+    OMTenantRequestHelper.checkTenantAdmin(ozoneManager, tenantId);
 
     // TODO: Check tenant existence?
 
@@ -94,9 +94,9 @@ public class OMTenantRevokeAdminRequest extends OMClientRequest {
     }
 
     // Check if accessId is assigned to the tenant
-    if (!accessIdInfo.getTenantId().equals(tenantName)) {
+    if (!accessIdInfo.getTenantId().equals(tenantId)) {
       throw new OMException("accessId '" + accessId +
-          "' must be assigned to tenant '" + tenantName + "' first.",
+          "' must be assigned to tenant '" + tenantId + "' first.",
           OMException.ResultCodes.INVALID_TENANT_NAME);
     }
 
@@ -106,7 +106,13 @@ public class OMTenantRevokeAdminRequest extends OMClientRequest {
 
     final OMRequest.Builder omRequestBuilder = getOmRequest().toBuilder()
         .setUserInfo(getUserInfo())
-        .setTenantRevokeAdminRequest(request)
+        .setTenantRevokeAdminRequest(
+                // Regenerate request just in case tenantId is not provided
+                //  by the client
+                TenantRevokeAdminRequest.newBuilder()
+                        .setTenantName(tenantId)
+                        .setAccessId(request.getAccessId())
+                        .build())
         .setCmdType(getOmRequest().getCmdType())
         .setClientId(getOmRequest().getClientId());
 
@@ -159,8 +165,8 @@ public class OMTenantRevokeAdminRequest extends OMClientRequest {
       final OmDBAccessIdInfo newOmDBAccessIdInfo =
           new OmDBAccessIdInfo.Builder()
           .setTenantId(oldAccessIdInfo.getTenantId())
-          .setKerberosPrincipal(oldAccessIdInfo.getKerberosPrincipal())
-          .setSharedSecret(oldAccessIdInfo.getSharedSecret())
+          .setKerberosPrincipal(oldAccessIdInfo.getUserPrincipal())
+          .setSharedSecret(oldAccessIdInfo.getSecretKey())
           .setIsAdmin(false)
           .setIsDelegatedAdmin(false)
           .build();
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeUserAccessIdRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeUserAccessIdRequest.java
index 9c16297..28808a3 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeUserAccessIdRequest.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantRevokeUserAccessIdRequest.java
@@ -173,7 +173,7 @@ public class OMTenantRevokeUserAccessIdRequest extends OMClientRequest {
       OmDBAccessIdInfo omDBAccessIdInfo =
           omMetadataManager.getTenantAccessIdTable().get(accessId);
       assert(omDBAccessIdInfo != null);
-      userPrincipal = omDBAccessIdInfo.getKerberosPrincipal();
+      userPrincipal = omDBAccessIdInfo.getUserPrincipal();
       assert(userPrincipal != null);
       OmDBKerberosPrincipalInfo principalInfo = omMetadataManager
           .getPrincipalToAccessIdsTable().getIfExist(userPrincipal);
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/security/OMSetSecretResponse.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/security/OMSetSecretResponse.java
new file mode 100644
index 0000000..7d60f26
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/security/OMSetSecretResponse.java
@@ -0,0 +1,89 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.response.s3.security;
+
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
+import org.apache.hadoop.ozone.om.helpers.OmDBAccessIdInfo;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
+import org.apache.hadoop.ozone.om.response.CleanupTableInfo;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.io.IOException;
+
+import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.S3_SECRET_TABLE;
+import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.TENANT_ACCESS_ID_TABLE;
+
+/**
+ * Response for SetSecret request.
+ */
+@CleanupTableInfo(cleanupTables = {S3_SECRET_TABLE, TENANT_ACCESS_ID_TABLE})
+public class OMSetSecretResponse extends OMClientResponse {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(OMSetSecretResponse.class);
+
+  private String accessId;
+  private OmDBAccessIdInfo dbAccessIdInfo;
+  private S3SecretValue s3SecretValue;
+
+  public OMSetSecretResponse(@Nullable String accessId,
+                             @Nullable OmDBAccessIdInfo dbAccessIdInfo,
+                             @Nullable S3SecretValue s3SecretValue,
+                             @Nonnull OMResponse omResponse) {
+    super(omResponse);
+    this.accessId = accessId;
+    this.dbAccessIdInfo = dbAccessIdInfo;
+    this.s3SecretValue = s3SecretValue;
+  }
+
+  /**
+   * For when the request is not successful.
+   * For a successful request, the other constructor should be used.
+   */
+  public OMSetSecretResponse(@Nonnull OMResponse omResponse) {
+    super(omResponse);
+    checkStatusNotOK();
+  }
+
+  @Override
+  public void addToDBBatch(OMMetadataManager omMetadataManager,
+      BatchOperation batchOperation) throws IOException {
+
+    assert(getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK);
+
+    if (dbAccessIdInfo != null) {
+      LOG.debug("Updating TenantAccessIdTable");
+      omMetadataManager.getTenantAccessIdTable().putWithBatch(batchOperation,
+          accessId, dbAccessIdInfo);
+    }
+
+    if (s3SecretValue != null) {
+      LOG.debug("Updating TenantAccessIdTable");
+      omMetadataManager.getS3SecretTable().putWithBatch(batchOperation,
+          accessId, s3SecretValue);
+    }
+  }
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/tenant/OMTenantCreateResponse.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/tenant/OMTenantCreateResponse.java
index 99905d6..3fa2485 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/tenant/OMTenantCreateResponse.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/tenant/OMTenantCreateResponse.java
@@ -79,7 +79,7 @@ public class OMTenantCreateResponse extends OMClientResponse {
   public void addToDBBatch(OMMetadataManager omMetadataManager,
       BatchOperation batchOperation) throws IOException {
 
-    final String tenantName = omTenantInfo.getTenantName();
+    final String tenantName = omTenantInfo.getTenantId();
     omMetadataManager.getTenantStateTable().putWithBatch(
         batchOperation, tenantName, omTenantInfo);
 
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java
index cdc1132..5fe57ff 100644
--- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java
@@ -348,7 +348,7 @@ public class TestS3GetSecretRequest {
     // Check response
     Assert.assertTrue(omTenantCreateResponse.getOMResponse().getSuccess());
     Assert.assertEquals(TENANT_NAME,
-        omTenantCreateResponse.getOmDBTenantInfo().getTenantName());
+        omTenantCreateResponse.getOmDBTenantInfo().getTenantId());
 
 
     // 2. AssignUserToTenantRequest: Assign "bob@EXAMPLE.COM" to "finance".
@@ -419,6 +419,6 @@ public class TestS3GetSecretRequest {
     final S3Secret s3Secret = getS3SecretResponse.getS3Secret();
     Assert.assertEquals(ACCESS_ID_BOB, s3Secret.getKerberosID());
     Assert.assertEquals(
-        omDBAccessIdInfo.getSharedSecret(), s3Secret.getAwsSecret());
+        omDBAccessIdInfo.getSecretKey(), s3Secret.getAwsSecret());
   }
 }
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/GetS3SecretHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/GetS3SecretHandler.java
index aa4d893..e1dc534 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/GetS3SecretHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/GetS3SecretHandler.java
@@ -30,13 +30,12 @@ import picocli.CommandLine.Option;
 /**
  * Executes getsecret calls.
  */
-@Command(name = "getsecret",
-    description = "Returns s3 secret for current user")
+@Command(name = "getsecret", aliases = "get-secret",
+    description = "Returns S3 secret for a user")
 public class GetS3SecretHandler extends S3Handler {
 
   @Option(names = "-u",
-      description = "Specify the user to perform the operation on "
-          + "(Admins only)'")
+      description = "Specify the user (accessId). Requires admin privilege'")
   private String username;
 
   @Option(names = "-e",
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/S3Shell.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/S3Shell.java
index d85b0e9..13f59c4 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/S3Shell.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/S3Shell.java
@@ -31,6 +31,7 @@ import picocli.CommandLine.Command;
     description = "Shell for S3 specific operations",
     subcommands = {
         GetS3SecretHandler.class,
+        SetS3SecretHandler.class,
         RevokeS3SecretHandler.class
     })
 public class S3Shell extends Shell {
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/GetS3SecretHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/SetS3SecretHandler.java
similarity index 73%
copy from hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/GetS3SecretHandler.java
copy to hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/SetS3SecretHandler.java
index aa4d893..1045876f 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/GetS3SecretHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/s3/SetS3SecretHandler.java
@@ -17,31 +17,35 @@
  */
 package org.apache.hadoop.ozone.shell.s3;
 
-import java.io.IOException;
-
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.shell.OzoneAddress;
 import org.apache.hadoop.security.UserGroupInformation;
-
+import picocli.CommandLine;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Option;
 
+import java.io.IOException;
+
 /**
- * Executes getsecret calls.
+ * ozone s3 setsecret.
  */
-@Command(name = "getsecret",
-    description = "Returns s3 secret for current user")
-public class GetS3SecretHandler extends S3Handler {
+@Command(name = "setsecret", aliases = "set-secret",
+    description = "Set s3 secret for current user")
+public class SetS3SecretHandler extends S3Handler {
 
   @Option(names = "-u",
       description = "Specify the user to perform the operation on "
           + "(Admins only)'")
   private String username;
 
+  @CommandLine.Option(names = {"-s", "--secret", "--secretKey"},
+      description = "Secret key", required = true)
+  private String secretKey;
+
   @Option(names = "-e",
       description = "Print out variables together with 'export' prefix, to "
-          + "use it from 'eval $(ozone s3 getsecret)'")
+          + "use it from 'eval $(ozone s3 setsecret)'")
   private boolean export;
 
   @Override
@@ -56,14 +60,15 @@ public class GetS3SecretHandler extends S3Handler {
       username = UserGroupInformation.getCurrentUser().getUserName();
     }
 
-    final S3SecretValue secret = client.getObjectStore().getS3Secret(username);
+    final S3SecretValue accessIdSecretKeyPair =
+        client.getObjectStore().setS3Secret(username, secretKey);
     if (export) {
       out().println("export AWS_ACCESS_KEY_ID='" +
-          secret.getAwsAccessKey() + "'");
+          accessIdSecretKeyPair.getAwsAccessKey() + "'");
       out().println("export AWS_SECRET_ACCESS_KEY='" +
-          secret.getAwsSecret() + "'");
+          accessIdSecretKeyPair.getAwsSecret() + "'");
     } else {
-      out().println(secret);
+      out().println(accessIdSecretKeyPair);
     }
   }
 
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignAdminHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignAdminHandler.java
index 3e2c659..1e05e32 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignAdminHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignAdminHandler.java
@@ -47,7 +47,7 @@ public class TenantAssignAdminHandler extends TenantHandler {
 
   @CommandLine.Option(names = {"-t", "--tenant"},
       description = "Tenant name")
-  private String tenantName;
+  private String tenantId;
 
   @CommandLine.Option(names = {"-d", "--delegated"}, defaultValue = "true",
       description = "Make delegated admin")
@@ -59,13 +59,13 @@ public class TenantAssignAdminHandler extends TenantHandler {
 
     for (final String accessId : accessIds) {
       try {
-        objStore.tenantAssignAdmin(accessId, tenantName, delegated);
+        objStore.tenantAssignAdmin(accessId, tenantId, delegated);
         // TODO: Make tenantAssignAdmin return accessId, tenantName, user later.
         err().println("Assigned admin to '" + accessId +
-            (tenantName != null ? "' in tenant '" + tenantName + "'" : ""));
+            (tenantId != null ? "' in tenant '" + tenantId + "'" : ""));
       } catch (IOException e) {
         err().println("Failed to assign admin to '" + accessId +
-            (tenantName != null ? "' in tenant '" + tenantName + "'" : "") +
+            (tenantId != null ? "' in tenant '" + tenantId + "'" : "") +
             ": " + e.getMessage());
         if (e instanceof OMException) {
           final OMException omEx = (OMException) e;
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignUserAccessIdHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignUserAccessIdHandler.java
index 75bf672..2fe0f3e 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignUserAccessIdHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantAssignUserAccessIdHandler.java
@@ -47,7 +47,7 @@ public class TenantAssignUserAccessIdHandler extends TenantHandler {
 
   @CommandLine.Option(names = {"-t", "--tenant"},
       description = "Tenant name", required = true)
-  private String tenantName;
+  private String tenantId;
 
   @CommandLine.Option(names = {"-a", "--access-id", "--accessId"},
       description = "(Optional) Specify the accessId for user in this tenant. "
@@ -59,8 +59,8 @@ public class TenantAssignUserAccessIdHandler extends TenantHandler {
   //  `s3 getsecret` and leak the secret if an admin isn't careful.
   private String accessId;
 
-  private String getDefaultAccessId(String principal) {
-    return tenantName + TENANT_NAME_USER_NAME_DELIMITER + principal;
+  private String getDefaultAccessId(String userPrincipal) {
+    return tenantId + TENANT_NAME_USER_NAME_DELIMITER + userPrincipal;
   }
 
   @Override
@@ -83,8 +83,8 @@ public class TenantAssignUserAccessIdHandler extends TenantHandler {
           accessId = getDefaultAccessId(principal);
         }
         final S3SecretValue resp =
-            objStore.tenantAssignUserAccessId(principal, tenantName, accessId);
-        err().println("Assigned '" + principal + "' to '" + tenantName +
+            objStore.tenantAssignUserAccessId(principal, tenantId, accessId);
+        err().println("Assigned '" + principal + "' to '" + tenantId +
             "' with accessId '" + accessId + "'.");
         out().println("export AWS_ACCESS_KEY_ID='" +
             resp.getAwsAccessKey() + "'");
@@ -92,7 +92,7 @@ public class TenantAssignUserAccessIdHandler extends TenantHandler {
             resp.getAwsSecret() + "'");
       } catch (IOException e) {
         err().println("Failed to assign '" + principal + "' to '" +
-            tenantName + "': " + e.getMessage());
+            tenantId + "': " + e.getMessage());
         if (e instanceof OMException) {
           final OMException omException = (OMException) e;
           if (omException.getResult().equals(
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantGetSecretHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantGetSecretHandler.java
index dcbc0e3..e1a6f15 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantGetSecretHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantGetSecretHandler.java
@@ -43,7 +43,7 @@ public class TenantGetSecretHandler extends TenantHandler {
   @CommandLine.Parameters(description = "List of accessIds", arity = "1..")
   private List<String> accessIds = new ArrayList<>();
 
-  @CommandLine.Option(names = "-e",
+  @CommandLine.Option(names = {"-e", "--export"},
       description = "Print out variables together with 'export' prefix")
   private boolean export;
 
@@ -55,15 +55,15 @@ public class TenantGetSecretHandler extends TenantHandler {
     for (final String accessId : accessIds) {
 
       try {
-        final S3SecretValue secret =
+        final S3SecretValue accessIdSecretKeyPair =
             objectStore.getS3Secret(accessId, false);
         if (export) {
           out().println("export AWS_ACCESS_KEY_ID='" +
-              secret.getAwsAccessKey() + "'");
+              accessIdSecretKeyPair.getAwsAccessKey() + "'");
           out().println("export AWS_SECRET_ACCESS_KEY='" +
-              secret.getAwsSecret() + "'");
+              accessIdSecretKeyPair.getAwsSecret() + "'");
         } else {
-          out().println(secret);
+          out().println(accessIdSecretKeyPair);
         }
       } catch (OMException omEx) {
         if (omEx.getResult().equals(ACCESSID_NOT_FOUND)) {
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantListUsersHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantListUsersHandler.java
index 458a458..abe52e9 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantListUsersHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantListUsersHandler.java
@@ -42,7 +42,7 @@ public class TenantListUsersHandler extends S3Handler {
 
   @CommandLine.Option(names = {"-t", "--tenant"},
       description = "Tenant name")
-  private String tenantName;
+  private String tenantId;
 
   @CommandLine.Option(names = {"-p", "--prefix"},
       description = "Filter users with this prefix.")
@@ -52,19 +52,19 @@ public class TenantListUsersHandler extends S3Handler {
   protected void execute(OzoneClient client, OzoneAddress address) {
     final ObjectStore objStore = client.getObjectStore();
 
-    if (StringUtils.isEmpty(tenantName)) {
+    if (StringUtils.isEmpty(tenantId)) {
       err().println("Please specify a tenant name with -t.");
       return;
     }
     try {
       TenantUserList usersInTenant =
-          objStore.listUsersInTenant(tenantName, prefix);
+          objStore.listUsersInTenant(tenantId, prefix);
       for (TenantUserAccessId accessIdInfo : usersInTenant.getUserAccessIds()) {
         out().println("- User '" + accessIdInfo.getUser() +
             "' with accessId '" + accessIdInfo.getAccessId() + "'");
       }
     } catch (IOException e) {
-      err().println("Failed to Get Users in tenant '" + tenantName
+      err().println("Failed to Get Users in tenant '" + tenantId
           + "': " + e.getMessage());
     }
   }
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantRevokeAdminHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantRevokeAdminHandler.java
index dec27c2..d318c06 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantRevokeAdminHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantRevokeAdminHandler.java
@@ -42,7 +42,7 @@ public class TenantRevokeAdminHandler extends TenantHandler {
 
   @CommandLine.Option(names = {"-t", "--tenant"},
       description = "Tenant name")
-  private String tenantName;
+  private String tenantId;
 
   @Override
   protected void execute(OzoneClient client, OzoneAddress address) {
@@ -51,12 +51,12 @@ public class TenantRevokeAdminHandler extends TenantHandler {
     for (final String accessId : accessIds) {
       try {
         // TODO: Make tenantRevokeAdmin return accessId, tenantName, user later.
-        objStore.tenantRevokeAdmin(accessId, tenantName);
+        objStore.tenantRevokeAdmin(accessId, tenantId);
         err().println("Revoked admin role of '" + accessId +
-            (tenantName != null ? "' from tenant '" + tenantName + "'" : ""));
+            (tenantId != null ? "' from tenant '" + tenantId + "'" : ""));
       } catch (IOException e) {
         err().println("Failed to revoke admin role of '" + accessId +
-            (tenantName != null ? "' from tenant '" + tenantName + "'" : "") +
+            (tenantId != null ? "' from tenant '" + tenantId + "'" : "") +
             ": " + e.getMessage());
         if (e instanceof OMException) {
           final OMException omEx = (OMException) e;
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantSetSecretHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantSetSecretHandler.java
index 9ca6133..b1b6b49 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantSetSecretHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/tenant/TenantSetSecretHandler.java
@@ -17,10 +17,17 @@
  */
 package org.apache.hadoop.ozone.shell.tenant;
 
+import org.apache.hadoop.ozone.client.ObjectStore;
 import org.apache.hadoop.ozone.client.OzoneClient;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.shell.OzoneAddress;
 import picocli.CommandLine;
 
+import java.io.IOException;
+
+import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.ACCESSID_NOT_FOUND;
+
 /**
  * ozone tenant user set-secret.
  */
@@ -32,9 +39,39 @@ public class TenantSetSecretHandler extends TenantHandler {
   @CommandLine.Parameters(description = "AccessId", arity = "1")
   private String accessId;
 
+  @CommandLine.Option(names = {"-s", "--secret"},
+          description = "Secret key", required = true)
+  private String secretKey;
+
+  @CommandLine.Option(names = {"-e", "--export"},
+          description = "Print out variables together with 'export' prefix")
+  private boolean export;
+
   @Override
-  protected void execute(OzoneClient client, OzoneAddress address) {
-//    final ObjectStore objectStore = client.getObjectStore();
+  protected void execute(OzoneClient client, OzoneAddress address)
+          throws IOException {
+
+    final ObjectStore objectStore = client.getObjectStore();
+
+    try {
+      final S3SecretValue accessIdSecretKeyPair =
+              objectStore.setS3Secret(accessId, secretKey);
+      if (export) {
+        out().println("export AWS_ACCESS_KEY_ID='" +
+                accessIdSecretKeyPair.getAwsAccessKey() + "'");
+        out().println("export AWS_SECRET_ACCESS_KEY='" +
+                accessIdSecretKeyPair.getAwsSecret() + "'");
+      } else {
+        out().println(accessIdSecretKeyPair);
+      }
+    } catch (OMException omEx) {
+      if (omEx.getResult().equals(ACCESSID_NOT_FOUND)) {
+        // Print to stderr here in order not to contaminate stdout just in
+        // case -e is specified.
+        err().println("AccessId '" + accessId + "' doesn't exist");
+      } else {
+        throw omEx;
+      }
+    }
   }
 }
-

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