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