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

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 39154b915b HDDS-9529. Reauth to Vault after failed request (#5486)
39154b915b is described below

commit 39154b915b0e9fe446cf4d0827f0c1009a40c868
Author: Mikhail <[email protected]>
AuthorDate: Thu Oct 26 16:15:02 2023 +0300

    HDDS-9529. Reauth to Vault after failed request (#5486)
---
 .../ozone/s3/remote/vault/VaultS3SecretStore.java  | 68 +++++++++-------------
 .../s3/remote/vault/VaultS3SecretStoreTest.java    | 62 ++++++++------------
 2 files changed, 52 insertions(+), 78 deletions(-)

diff --git 
a/hadoop-ozone/s3-secret-store/src/main/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStore.java
 
b/hadoop-ozone/s3-secret-store/src/main/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStore.java
index ab4b13f634..892b86eaa7 100644
--- 
a/hadoop-ozone/s3-secret-store/src/main/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStore.java
+++ 
b/hadoop-ozone/s3-secret-store/src/main/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStore.java
@@ -21,7 +21,7 @@ import com.bettercloud.vault.SslConfig;
 import com.bettercloud.vault.Vault;
 import com.bettercloud.vault.VaultConfig;
 import com.bettercloud.vault.VaultException;
-import com.bettercloud.vault.response.LookupResponse;
+import com.bettercloud.vault.response.LogicalResponse;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.ozone.om.S3Batcher;
 import org.apache.hadoop.ozone.om.S3SecretStore;
@@ -32,10 +32,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
-import java.util.Collections;
 import java.util.Map;
-import java.util.Objects;
 
+import static java.util.Collections.singletonMap;
 import static 
org.apache.hadoop.ozone.s3.remote.S3SecretRemoteStoreConfigurationKeys.ADDRESS;
 import static 
org.apache.hadoop.ozone.s3.remote.S3SecretRemoteStoreConfigurationKeys.ENGINE_VER;
 import static 
org.apache.hadoop.ozone.s3.remote.S3SecretRemoteStoreConfigurationKeys.KEY_STORE_PASSWORD;
@@ -92,9 +91,8 @@ public class VaultS3SecretStore implements S3SecretStore {
   public void storeSecret(String kerberosId, S3SecretValue secret)
       throws IOException {
     try {
-      checkAuth();
-      vault.logical().write(secretPath + '/' + kerberosId,
-              Collections.singletonMap(kerberosId, secret.getAwsSecret()));
+      callWithReAuth(() -> vault.logical().write(secretPath + '/' + kerberosId,
+          singletonMap(kerberosId, secret.getAwsSecret())));
     } catch (VaultException e) {
       LOG.error("Failed to store secret", e);
       throw new IOException("Failed to store secret", e);
@@ -104,10 +102,9 @@ public class VaultS3SecretStore implements S3SecretStore {
   @Override
   public S3SecretValue getSecret(String kerberosID) throws IOException {
     try {
-      checkAuth();
-
-      Map<String, String> data = vault.logical()
-              .read(secretPath + '/' + kerberosID).getData();
+      Map<String, String> data = callWithReAuth(() -> vault.logical()
+          .read(secretPath + '/' + kerberosID))
+          .getData();
 
       if (data == null) {
         return null;
@@ -128,49 +125,34 @@ public class VaultS3SecretStore implements S3SecretStore {
   @Override
   public void revokeSecret(String kerberosId) throws IOException {
     try {
-      checkAuth();
-      vault.logical().delete(secretPath + '/' + kerberosId);
+      callWithReAuth(() -> vault.logical()
+          .delete(secretPath + '/' + kerberosId));
     } catch (VaultException e) {
       LOG.error("Failed to delete secret", e);
       throw new IOException("Failed to revoke secret", e);
     }
   }
 
-  private void checkAuth() throws VaultException {
-    try {
-      doCheck();
-    } catch (VaultException e) {
-      processEx(e, this::auth);
-      try {
-        doCheck();
-      } catch (VaultException ex) {
-        processEx(ex, () -> {
-          throw new VaultException("Failed to re-authenticate",
-              ex.getHttpStatusCode());
-        });
-      }
-    }
-  }
+  private LogicalResponse callWithReAuth(RestCall action)
+      throws VaultException {
+    LogicalResponse response = action.call();
+    int status = response.getRestResponse().getStatus();
+    if (isAuthFailed(status)) {
+      auth();
 
-  private void doCheck() throws VaultException {
-    LookupResponse lookupResponse = vault.auth().lookupSelf();
+      response = action.call();
+      status = response.getRestResponse().getStatus();
 
-    if (!Objects.equals(lookupResponse.getId(), config.getToken())) {
-      LOG.error("Lookup token is not the same as Vault client configuration.");
-      throw new VaultException("Failed to re-authenticate", 401);
+      if (isAuthFailed(status)) {
+        throw new VaultException("Failed to re-authenticate", status);
+      }
     }
-  }
 
-  private void processEx(VaultException e, Call callback)
-      throws VaultException {
-    int status = e.getHttpStatusCode();
-    if (status == 403 || status == 401) {
-      callback.run();
-    }
+    return response;
   }
 
-  private interface Call {
-    void run() throws VaultException;
+  private static boolean isAuthFailed(int status) {
+    return status == 403 || status == 401 || status == 400;
   }
 
   @Override
@@ -207,4 +189,8 @@ public class VaultS3SecretStore implements S3SecretStore {
   public static VaultS3SecretStoreBuilder builder() {
     return new VaultS3SecretStoreBuilder();
   }
+
+  private interface RestCall {
+    LogicalResponse call() throws VaultException;
+  }
 }
diff --git 
a/hadoop-ozone/s3-secret-store/src/test/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStoreTest.java
 
b/hadoop-ozone/s3-secret-store/src/test/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStoreTest.java
index a247c730b0..149a7fb6e8 100644
--- 
a/hadoop-ozone/s3-secret-store/src/test/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStoreTest.java
+++ 
b/hadoop-ozone/s3-secret-store/src/test/java/org/apache/hadoop/ozone/s3/remote/vault/VaultS3SecretStoreTest.java
@@ -20,10 +20,8 @@ package org.apache.hadoop.ozone.s3.remote.vault;
 
 import com.bettercloud.vault.Vault;
 import com.bettercloud.vault.VaultConfig;
-import com.bettercloud.vault.VaultException;
 import com.bettercloud.vault.api.Logical;
 import com.bettercloud.vault.response.LogicalResponse;
-import com.bettercloud.vault.response.LookupResponse;
 import com.bettercloud.vault.rest.RestResponse;
 import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
 import org.apache.hadoop.ozone.s3.remote.vault.auth.Auth;
@@ -48,7 +46,10 @@ import static org.mockito.Mockito.when;
  */
 public class VaultS3SecretStoreTest {
   private static final String TOKEN = "token";
-  private static final AtomicInteger FAIL_AUTH_COUNTER = new AtomicInteger(0);
+  private static final AtomicInteger AUTH_OPERATION_PROVIDER
+      = new AtomicInteger(0);
+  private static final AtomicInteger SUCCESS_OPERATION_LIMIT
+      = new AtomicInteger(0);
   private static final Map<String, Map<String, String>> STORE = new 
HashMap<>();
   private static VaultConfig config;
   private static VaultS3SecretStore s3SecretStore;
@@ -58,6 +59,10 @@ public class VaultS3SecretStoreTest {
     Vault vault = mock(Vault.class);
 
     Auth auth = config1 -> {
+      int newCounter = AUTH_OPERATION_PROVIDER.get();
+      if (newCounter > 0) {
+        SUCCESS_OPERATION_LIMIT.set(newCounter);
+      }
       config1.token(TOKEN);
       config = config1;
       return vault;
@@ -72,16 +77,18 @@ public class VaultS3SecretStoreTest {
         null);
 
     when(vault.logical()).thenReturn(new LogicalMock());
-    when(vault.auth()).thenReturn(new AuthMock());
   }
 
   @BeforeEach
   public void clean() {
+    AUTH_OPERATION_PROVIDER.set(0);
+    SUCCESS_OPERATION_LIMIT.set(0);
     STORE.clear();
   }
 
   @Test
   public void testReadWrite() throws IOException {
+    SUCCESS_OPERATION_LIMIT.set(2);
     S3SecretValue secret = new S3SecretValue("id", "value");
     s3SecretStore.storeSecret(
         "id",
@@ -92,30 +99,25 @@ public class VaultS3SecretStoreTest {
 
   @Test
   public void testReAuth() throws IOException {
+    SUCCESS_OPERATION_LIMIT.set(1);
+    AUTH_OPERATION_PROVIDER.set(1);
     S3SecretValue secret = new S3SecretValue("id", "value");
     s3SecretStore.storeSecret("id", secret);
 
-    FAIL_AUTH_COUNTER.set(1);
-
     assertEquals(secret, s3SecretStore.getSecret("id"));
 
-    FAIL_AUTH_COUNTER.set(1);
-
     assertDoesNotThrow(() -> s3SecretStore.revokeSecret("id"));
   }
 
   @Test
   public void testAuthFail() throws IOException {
+    SUCCESS_OPERATION_LIMIT.set(1);
     S3SecretValue secret = new S3SecretValue("id", "value");
     s3SecretStore.storeSecret("id", secret);
 
-    FAIL_AUTH_COUNTER.set(2);
-
     assertThrows(IOException.class,
         () -> s3SecretStore.getSecret("id"));
 
-    FAIL_AUTH_COUNTER.set(2);
-
     assertThrows(IOException.class,
         () -> s3SecretStore.revokeSecret("id"));
   }
@@ -127,48 +129,34 @@ public class VaultS3SecretStoreTest {
 
     @Override
     public LogicalResponse read(String path) {
+      if (SUCCESS_OPERATION_LIMIT.getAndDecrement() <= 0) {
+        return new LogicalResponseMock(path, 401);
+      }
+
       return new LogicalResponseMock(path);
     }
 
     @Override
     public LogicalResponse write(String path,
                                  Map<String, Object> nameValuePairs) {
+      if (SUCCESS_OPERATION_LIMIT.getAndDecrement() <= 0) {
+        return new LogicalResponseMock(path, 401);
+      }
+
       STORE.put(path, (Map) nameValuePairs);
       return new LogicalResponseMock(path);
     }
 
     @Override
     public LogicalResponse delete(String path) {
+      if (SUCCESS_OPERATION_LIMIT.getAndDecrement() <= 0) {
+        return new LogicalResponseMock(path, 401);
+      }
       STORE.remove(path);
       return new LogicalResponseMock(path);
     }
   }
 
-  private static class AuthMock extends com.bettercloud.vault.api.Auth {
-    AuthMock() {
-      super(config);
-    }
-
-    @Override
-    public LookupResponse lookupSelf() throws VaultException {
-      if (FAIL_AUTH_COUNTER.getAndDecrement() == 0) {
-        throw new VaultException("Fail", 401);
-      }
-      return new LookupResponseMock(200);
-    }
-  }
-
-  private static class LookupResponseMock extends LookupResponse {
-    LookupResponseMock(int code) {
-      super(new RestResponse(code, "application/json", new byte[0]), 1);
-    }
-
-    @Override
-    public String getId() {
-      return TOKEN;
-    }
-  }
-
   private static class LogicalResponseMock extends LogicalResponse {
     private final String key;
 


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

Reply via email to