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

aengineer pushed a commit to branch HDDS-4
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/HDDS-4 by this push:
     new 1f78b04  HDDS-938. Add Client APIs for using S3 Auth interface. 
Contributed by  Dinesh Chitlangia.
1f78b04 is described below

commit 1f78b04ff3aaec175b1379474ceaaf2788199b16
Author: Anu Engineer <[email protected]>
AuthorDate: Fri Jan 4 10:04:17 2019 -0800

    HDDS-938. Add Client APIs for using S3 Auth interface.
    Contributed by  Dinesh Chitlangia.
---
 .../java/org/apache/hadoop/ozone/OzoneConsts.java  |  1 +
 .../apache/hadoop/ozone/client/ObjectStore.java    |  5 ++
 .../ozone/client/protocol/ClientProtocol.java      |  9 +++
 .../hadoop/ozone/client/rest/RestClient.java       |  7 ++
 .../apache/hadoop/ozone/client/rpc/RpcClient.java  | 15 ++++
 .../main/java/org/apache/hadoop/ozone/OmUtils.java | 26 +++++++
 .../apache/hadoop/ozone/om/OzoneManagerLock.java   | 24 ++++++-
 .../hadoop/ozone/om/helpers/S3SecretValue.java     | 84 ++++++++++++++++++++++
 .../ozone/om/protocol/OzoneManagerProtocol.java    |  8 +++
 ...OzoneManagerProtocolClientSideTranslatorPB.java | 23 ++++++
 .../src/main/proto/OzoneManagerProtocol.proto      | 17 +++++
 .../ozone/client/rpc/TestOzoneRpcClient.java       | 18 +++++
 .../org/apache/hadoop/ozone/om/OzoneManager.java   | 11 +++
 .../apache/hadoop/ozone/om/S3SecretManager.java    | 30 ++++++++
 .../hadoop/ozone/om/S3SecretManagerImpl.java       | 82 +++++++++++++++++++++
 .../hadoop/ozone/om/exceptions/OMException.java    |  3 +-
 ...OzoneManagerProtocolServerSideTranslatorPB.java | 19 +++++
 17 files changed, 380 insertions(+), 2 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 dad3bfe..a73fce9 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
@@ -86,6 +86,7 @@ public final class OzoneConsts {
   public static final String CONTAINER_ROOT_PREFIX = "repository";
 
   public static final String FILE_HASH = "SHA-256";
+  public static final String MD5_HASH = "MD5";
   public final static String CHUNK_OVERWRITE = "OverWriteRequested";
 
   public static final int CHUNK_SIZE = 1 * 1024 * 1024; // 1 MB
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 353996b..4d5f6d9 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
@@ -28,6 +28,7 @@ import java.util.Objects;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
 import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.security.UserGroupInformation;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -155,6 +156,10 @@ public class ObjectStore {
     return volume;
   }
 
+  public S3SecretValue getS3Secret(String kerberosID) throws IOException {
+    return proxy.getS3Secret(kerberosID);
+  }
+
   /**
    * Returns Iterator to iterate over all buckets for a user.
    * The result can be restricted using bucket prefix, will return all
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 2fe302e..ef7fa59 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
@@ -31,6 +31,8 @@ import org.apache.hadoop.ozone.client.io.OzoneOutputStream;
 
 import java.io.IOException;
 import java.util.List;
+
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
 import org.apache.hadoop.security.KerberosInfo;
 import org.apache.hadoop.security.token.Token;
@@ -420,4 +422,11 @@ public interface ClientProtocol {
   void cancelDelegationToken(Token<OzoneTokenIdentifier> token)
       throws IOException;
 
+  /**
+   * returns S3 Secret given kerberos user.
+   * @param kerberosID
+   * @return S3SecretValue
+   * @throws IOException
+   */
+  S3SecretValue getS3Secret(String kerberosID) throws IOException;
 }
diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java
index 6e2841d..377092b 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rest/RestClient.java
@@ -43,6 +43,7 @@ import 
org.apache.hadoop.ozone.client.rest.response.BucketInfo;
 import org.apache.hadoop.ozone.client.rest.response.KeyInfoDetails;
 import org.apache.hadoop.ozone.client.rest.response.VolumeInfo;
 import org.apache.hadoop.ozone.om.OMConfigKeys;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServicePort;
 import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
@@ -709,6 +710,12 @@ public class RestClient implements ClientProtocol {
   }
 
   @Override
+  public S3SecretValue getS3Secret(String kerberosID) throws IOException {
+    throw new UnsupportedOperationException("Ozone REST protocol does not " +
+        "support this operation.");
+  }
+
+  @Override
   public OzoneInputStream getKey(
       String volumeName, String bucketName, String keyName)
       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 f6b68c4..ee7c571 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
@@ -51,6 +51,7 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
 import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
 import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
 import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
 import 
org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolClientSideTranslatorPB;
 import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolPB;
@@ -446,6 +447,20 @@ public class RpcClient implements ClientProtocol {
     ozoneManagerClient.cancelDelegationToken(token);
   }
 
+  /**
+   * Returns s3 secret given a kerberos user.
+   * @param kerberosID
+   * @return S3SecretValue
+   * @throws IOException
+   */
+  @Override
+  public S3SecretValue getS3Secret(String kerberosID) throws IOException {
+    Preconditions.checkArgument(Strings.isNotBlank(kerberosID),
+        "kerberosID cannot be null or empty.");
+
+    return ozoneManagerClient.getS3Secret(kerberosID);
+  }
+
   @Override
   public void setBucketVersioning(
       String volumeName, String bucketName, Boolean versioning)
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 e7ed84f..2aae700 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
@@ -18,10 +18,15 @@
 package org.apache.hadoop.ozone;
 
 import java.io.File;
+import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.Collection;
 import java.util.Optional;
 
+import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdds.HddsConfigKeys;
 import org.apache.hadoop.hdds.server.ServerUtils;
@@ -140,4 +145,25 @@ public final class OmUtils {
         OMConfigKeys.OZONE_OM_DB_DIRS, HddsConfigKeys.OZONE_METADATA_DIRS);
     return ServerUtils.getOzoneMetaDirPath(conf);
   }
+
+  public static byte[] getMD5Digest(String input) throws IOException {
+    try {
+      MessageDigest md = MessageDigest.getInstance(OzoneConsts.MD5_HASH);
+      return md.digest(input.getBytes(StandardCharsets.UTF_8));
+    } catch (NoSuchAlgorithmException ex) {
+      throw new IOException("Error creating an instance of MD5 digest.\n" +
+          "This could possibly indicate a faulty JRE");
+    }
+  }
+
+  public static byte[] getSHADigest() throws IOException {
+    try {
+      MessageDigest sha = MessageDigest.getInstance(OzoneConsts.FILE_HASH);
+      return sha.digest(RandomStringUtils.random(32)
+          .getBytes(StandardCharsets.UTF_8));
+    } catch (NoSuchAlgorithmException ex) {
+      throw new IOException("Error creating an instance of SHA-256 digest.\n" +
+          "This could possibly indicate a faulty JRE");
+    }
+  }
 }
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerLock.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerLock.java
index c5ce9e2..0e36898 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerLock.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OzoneManagerLock.java
@@ -67,6 +67,7 @@ public final class OzoneManagerLock {
   private static final String VOLUME_LOCK = "volumeLock";
   private static final String BUCKET_LOCK = "bucketLock";
   private static final String S3_BUCKET_LOCK = "s3BucketLock";
+  private static final String S3_SECRET_LOCK = "s3SecretetLock";
 
   private final LockManager<String> manager;
 
@@ -76,7 +77,8 @@ public final class OzoneManagerLock {
           () -> ImmutableMap.of(
               VOLUME_LOCK, new AtomicInteger(0),
               BUCKET_LOCK, new AtomicInteger(0),
-              S3_BUCKET_LOCK, new AtomicInteger(0)
+              S3_BUCKET_LOCK, new AtomicInteger(0),
+              S3_SECRET_LOCK, new AtomicInteger(0)
           )
       );
 
@@ -219,4 +221,24 @@ public final class OzoneManagerLock {
   private boolean hasAnyS3Lock() {
     return myLocks.get().get(S3_BUCKET_LOCK).get() != 0;
   }
+
+  public void acquireS3SecretLock(String awsAccessId) {
+    if (hasAnyS3SecretLock()) {
+      throw new RuntimeException(
+          "Thread '" + Thread.currentThread().getName() +
+              "' cannot acquire S3 Secret lock while holding S3 " +
+              "awsAccessKey lock(s).");
+    }
+    manager.lock(awsAccessId);
+    myLocks.get().get(S3_SECRET_LOCK).incrementAndGet();
+  }
+
+  private boolean hasAnyS3SecretLock() {
+    return myLocks.get().get(S3_SECRET_LOCK).get() != 0;
+  }
+
+  public void releaseS3SecretLock(String awsAccessId) {
+    manager.unlock(awsAccessId);
+    myLocks.get().get(S3_SECRET_LOCK).decrementAndGet();
+  }
 }
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
new file mode 100644
index 0000000..8b050a7
--- /dev/null
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/S3SecretValue.java
@@ -0,0 +1,84 @@
+/**
+ * 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.helpers;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.hadoop.ozone.OmUtils;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+
+import java.io.IOException;
+
+/**
+ * S3Secret to be saved in database.
+ */
+public class S3SecretValue {
+  private String kerberosID;
+  private String awsSecret;
+  private String awsAccessKey;
+
+  public S3SecretValue(String kerberosID, String awsSecret) throws IOException 
{
+    this.kerberosID = kerberosID;
+    this.awsSecret = awsSecret;
+    this.awsAccessKey =
+        DigestUtils.md5Hex(OmUtils.getMD5Digest(kerberosID));
+  }
+
+  public String getKerberosID() {
+    return kerberosID;
+  }
+
+  public void setKerberosID(String kerberosID) {
+    this.kerberosID = kerberosID;
+  }
+
+  public String getAwsSecret() {
+    return awsSecret;
+  }
+
+  public void setAwsSecret(String awsSecret) {
+    this.awsSecret = awsSecret;
+  }
+
+  public String getAwsAccessKey() {
+    return awsAccessKey;
+  }
+
+  public void setAwsAccessKey(String awsAccessKey) {
+    this.awsAccessKey = awsAccessKey;
+  }
+
+  public static S3SecretValue fromProtobuf(
+      OzoneManagerProtocolProtos.S3Secret s3Secret) throws IOException {
+    return new S3SecretValue(s3Secret.getKerberosID(), 
s3Secret.getAwsSecret());
+  }
+
+  public OzoneManagerProtocolProtos.S3Secret getProtobuf() {
+    return OzoneManagerProtocolProtos.S3Secret.newBuilder()
+        .setAwsSecret(this.awsSecret)
+        .setKerberosID(this.kerberosID)
+        .build();
+  }
+
+  @Override
+  public String toString() {
+    return "S3SecretValue{" +
+        "kerberosID='" + kerberosID + '\'' +
+        ", awsSecret='" + awsSecret + '\'' +
+        '}';
+  }
+}
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 06933d2..fc48d0e 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
@@ -25,6 +25,7 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
 import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
 import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
 import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneAclInfo;
 
@@ -308,5 +309,12 @@ public interface OzoneManagerProtocol  extends 
OzoneManagerSecurityProtocol {
                                    String bucketPrefix, int maxNumOfBuckets)
       throws IOException;
 
+  /**
+   * Gets s3Secret for given kerberos user.
+   * @param kerberosID
+   * @return S3SecretValue
+   * @throws IOException
+   */
+  S3SecretValue getS3Secret(String 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 85ae4a8..ca2e2fa 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
@@ -33,8 +33,10 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
 import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
 import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
 import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
 import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
 import org.apache.hadoop.ozone.protocol.proto
     .OzoneManagerProtocolProtos.AllocateBlockRequest;
 import org.apache.hadoop.ozone.protocol.proto
@@ -883,6 +885,27 @@ public final class 
OzoneManagerProtocolClientSideTranslatorPB
     }
   }
 
+  @Override
+  public S3SecretValue getS3Secret(String kerberosID) throws IOException {
+    OzoneManagerProtocolProtos.S3SecretRequest request  =
+        OzoneManagerProtocolProtos.S3SecretRequest.newBuilder()
+        .setKerberosID(kerberosID)
+        .build();
+    final OzoneManagerProtocolProtos.S3SecretResponse resp;
+    try {
+      resp = rpcProxy.getS3Secret(NULL_RPC_CONTROLLER, request);
+    } catch (ServiceException e) {
+      throw ProtobufHelper.getRemoteException(e);
+    }
+
+    if(resp.getStatus() != Status.OK) {
+      throw new IOException("Fetch S3 Secret failed, error: " +
+          resp.getStatus());
+    } else {
+      return S3SecretValue.fromProtobuf(resp.getS3Secret());
+    }
+  }
+
   /**
    * Return the proxy object underlying this protocol translator.
    *
diff --git a/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto 
b/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto
index 39d709d..5ce6117 100644
--- a/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto
+++ b/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto
@@ -61,6 +61,7 @@ enum Status {
     SCM_VERSION_MISMATCH_ERROR = 21;
     S3_BUCKET_NOT_FOUND = 22;
     S3_BUCKET_ALREADY_EXISTS = 23;
+    S3_SECRET_NOT_FOUND = 24;
 }
 
 
@@ -426,6 +427,19 @@ message S3ListBucketsResponse {
     repeated BucketInfo bucketInfo = 2;
 }
 
+message S3Secret {
+    required string kerberosID = 1;
+    required string awsSecret = 2;
+}
+
+message S3SecretRequest {
+    required string kerberosID = 1;
+}
+
+message S3SecretResponse {
+    required Status status = 1;
+    required S3Secret s3Secret = 2;
+}
 
 /**
  The OM service that takes care of Ozone namespace.
@@ -580,4 +594,7 @@ service OzoneManagerService {
 
     rpc listS3Buckets(S3ListBucketsRequest)
     returns(S3ListBucketsResponse);
+
+    rpc getS3Secret(S3SecretRequest)
+    returns(S3SecretResponse);
 }
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClient.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClient.java
index 485845c..b2b97f5 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClient.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClient.java
@@ -56,6 +56,7 @@ import org.apache.hadoop.ozone.client.rest.OzoneException;
 import org.apache.hadoop.hdds.scm.ScmConfigKeys;
 import org.apache.hadoop.hdds.scm.protocolPB.
     StorageContainerLocationProtocolClientSideTranslatorPB;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.test.GenericTestUtils;
 import org.apache.hadoop.util.Time;
 import org.junit.AfterClass;
@@ -1258,6 +1259,23 @@ public class TestOzoneRpcClient {
     }
   }
 
+  @Test
+  public void testGetS3Secret() throws IOException {
+    //Creates a secret since it does not exist
+    S3SecretValue firstAttempt = store.getS3Secret("HADOOP/JOHNDOE");
+
+    //Fetches the secret from db since it was created in previous step
+    S3SecretValue secondAttempt = store.getS3Secret("HADOOP/JOHNDOE");
+
+    //secret fetched on both attempts must be same
+    Assert.assertTrue(firstAttempt.getAwsSecret()
+        .equals(secondAttempt.getAwsSecret()));
+
+    //access key fetched on both attempts must be same
+    Assert.assertTrue(firstAttempt.getAwsAccessKey()
+        .equals(secondAttempt.getAwsAccessKey()));
+  }
+
   /**
    * Close OzoneClient and shutdown MiniOzoneCluster.
    */
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 cc458d7..b954762 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
@@ -50,6 +50,7 @@ import org.apache.hadoop.ipc.Client;
 import org.apache.hadoop.ipc.ProtobufRpcEngine;
 import org.apache.hadoop.ipc.RPC;
 import org.apache.hadoop.ozone.OzoneSecurityUtil;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.security.OzoneSecurityException;
 import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
 import org.apache.hadoop.security.AccessControlException;
@@ -187,6 +188,7 @@ public final class OzoneManager extends 
ServiceRuntimeInfoImpl
   private final Runnable shutdownHook;
   private final File omMetaDir;
   private final SecurityConfig secConfig;
+  private final S3SecretManager s3SecretManager;
 
   private OzoneManager(OzoneConfiguration conf) throws IOException {
     Preconditions.checkNotNull(conf);
@@ -245,6 +247,7 @@ public final class OzoneManager extends 
ServiceRuntimeInfoImpl
         volumeManager, bucketManager);
     keyManager = new KeyManagerImpl(scmBlockClient, metadataManager,
         configuration, omStorage.getOmId(), blockTokenMgr);
+    s3SecretManager = new S3SecretManagerImpl(configuration, metadataManager);
 
     shutdownHook = () -> {
       saveOmMetrics();
@@ -1655,6 +1658,14 @@ public final class OzoneManager extends 
ServiceRuntimeInfoImpl
   /**
    * {@inheritDoc}
    */
+  public S3SecretValue getS3Secret(String kerberosID) throws IOException{
+    return s3SecretManager.getS3Secret(kerberosID);
+  }
+
+  @Override
+  /**
+   * {@inheritDoc}
+   */
   public String getOzoneBucketMapping(String s3BucketName)
       throws IOException {
     return s3BucketManager.getOzoneBucketMapping(s3BucketName);
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/S3SecretManager.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/S3SecretManager.java
new file mode 100644
index 0000000..4c87274
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/S3SecretManager.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.hadoop.ozone.om;
+
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
+
+import java.io.IOException;
+/**
+ * Interface to manager s3 secret.
+ */
+public interface S3SecretManager {
+
+  S3SecretValue getS3Secret(String kerberosID) throws IOException;
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/S3SecretManagerImpl.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/S3SecretManagerImpl.java
new file mode 100644
index 0000000..902130d
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/S3SecretManagerImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.hadoop.ozone.om;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.OmUtils;
+import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.logging.log4j.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+/**
+ * S3 Secret manager.
+ */
+public class S3SecretManagerImpl implements S3SecretManager {
+  private static final Logger LOG =
+      LoggerFactory.getLogger(S3SecretManagerImpl.class);
+
+  /**
+   * OMMetadataManager is used for accessing OM MetadataDB and ReadWriteLock.
+   */
+  private final OMMetadataManager omMetadataManager;
+  private final OzoneConfiguration configuration;
+
+  /**
+   * Constructs S3SecretManager.
+   *
+   * @param omMetadataManager
+   */
+  public S3SecretManagerImpl(OzoneConfiguration configuration,
+      OMMetadataManager omMetadataManager) {
+    this.configuration = configuration;
+    this.omMetadataManager = omMetadataManager;
+  }
+
+  @Override
+  public S3SecretValue getS3Secret(String kerberosID) throws IOException {
+    Preconditions.checkArgument(Strings.isNotBlank(kerberosID),
+        "kerberosID cannot be null or empty.");
+    byte[] awsAccessKey = OmUtils.getMD5Digest(kerberosID);
+    S3SecretValue result = null;
+    omMetadataManager.getLock().acquireS3SecretLock(kerberosID);
+    try {
+      byte[] s3Secret =
+          omMetadataManager.getS3SecretTable().get(awsAccessKey);
+      if(s3Secret == null) {
+        byte[] secret = OmUtils.getSHADigest();
+        result = new S3SecretValue(kerberosID, DigestUtils.sha256Hex(secret));
+        omMetadataManager.getS3SecretTable()
+            .put(awsAccessKey, result.getProtobuf().toByteArray());
+      } else {
+        result = S3SecretValue.fromProtobuf(
+            OzoneManagerProtocolProtos.S3Secret.parseFrom(s3Secret));
+      }
+      result.setAwsAccessKey(DigestUtils.md5Hex(awsAccessKey));
+    } finally {
+      omMetadataManager.getLock().releaseS3SecretLock(kerberosID);
+    }
+    return result;
+  }
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
index 3292adf..a1a3fbd 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
@@ -115,6 +115,7 @@ public class OMException extends IOException {
     SCM_VERSION_MISMATCH_ERROR,
     SCM_IN_CHILL_MODE,
     S3_BUCKET_ALREADY_EXISTS,
-    S3_BUCKET_NOT_FOUND
+    S3_BUCKET_NOT_FOUND,
+    S3_SECRET_NOT_FOUND
   }
 }
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
index e2536d3..112cecb 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
@@ -31,6 +31,7 @@ import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
 import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
 import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
 import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolPB;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
     .AllocateBlockRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
@@ -199,6 +200,8 @@ public class OzoneManagerProtocolServerSideTranslatorPB 
implements
         return Status.S3_BUCKET_ALREADY_EXISTS;
       case S3_BUCKET_NOT_FOUND:
         return Status.S3_BUCKET_NOT_FOUND;
+      case S3_SECRET_NOT_FOUND:
+        return Status.S3_SECRET_NOT_FOUND;
       default:
         return Status.INTERNAL_ERROR;
       }
@@ -662,6 +665,22 @@ public class OzoneManagerProtocolServerSideTranslatorPB 
implements
   }
 
   @Override
+  public OzoneManagerProtocolProtos.S3SecretResponse getS3Secret(
+      RpcController controller,
+      OzoneManagerProtocolProtos.S3SecretRequest request)
+      throws ServiceException {
+    OzoneManagerProtocolProtos.S3SecretResponse.Builder resp =
+        OzoneManagerProtocolProtos.S3SecretResponse.newBuilder();
+    try {
+      
resp.setS3Secret(impl.getS3Secret(request.getKerberosID()).getProtobuf());
+      resp.setStatus(Status.OK);
+    } catch (IOException e) {
+      resp.setStatus(exceptionToResponseStatus(e));
+    }
+    return resp.build();
+  }
+
+  @Override
   public GetDelegationTokenResponseProto getDelegationToken(
       RpcController controller, GetDelegationTokenRequestProto request)
       throws ServiceException {


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

Reply via email to