Copilot commented on code in PR #16553:
URL: https://github.com/apache/pinot/pull/16553#discussion_r2263866318


##########
pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3PinotFS.java:
##########
@@ -702,6 +740,28 @@ public void copyToLocalFile(URI srcUri, File dstFile)
     _s3Client.getObject(getObjectRequest, ResponseTransformer.toFile(dstFile));
   }
 
+  @Override
+  public void copyToLocalFile(URI srcUri, File dstFile)
+      throws Exception {
+    try {
+      LOGGER.info("Copy {} to local {}", srcUri, dstFile.getAbsolutePath());
+      copyToLocalFileInternal(srcUri, dstFile);
+    } catch (Exception e) {
+      LOGGER.warn("Caught exception during S3 copy, attempting to refresh 
credentials and retry");
+
+      logAwsCredentials("BEFORE refresh");
+      initOrRefreshS3Client();
+      logAwsCredentials("AFTER refresh");
+
+      try {
+        copyToLocalFileInternal(srcUri, dstFile);
+      } catch (Exception retryException) {
+        throw new Exception("Unexpected exception during S3 copy to local file 
after credential refresh",
+            retryException);
+      }

Review Comment:
   The retry logic catches all exceptions and assumes they are 
credential-related. Consider checking the exception type to ensure credential 
refresh is only attempted for authentication/authorization failures, not for 
network issues or other unrelated errors.
   ```suggestion
         // Only attempt credential refresh and retry for S3Exception with 
401/403 status code
         if (e instanceof S3Exception) {
           int statusCode = ((S3Exception) e).statusCode();
           if (statusCode == 401 || statusCode == 403) {
             LOGGER.warn("Caught S3 authentication/authorization exception 
({}), attempting to refresh credentials and retry", statusCode);
   
             logAwsCredentials("BEFORE refresh");
             initOrRefreshS3Client();
             logAwsCredentials("AFTER refresh");
   
             try {
               copyToLocalFileInternal(srcUri, dstFile);
             } catch (Exception retryException) {
               throw new Exception("Unexpected exception during S3 copy to 
local file after credential refresh",
                   retryException);
             }
             return;
           }
         }
         // For all other exceptions, rethrow
         throw e;
   ```



##########
pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3PinotFS.java:
##########
@@ -690,10 +696,42 @@ private void visitFiles(URI fileUri, boolean recursive, 
Consumer<S3Object> objec
     }
   }
 
-  @Override
-  public void copyToLocalFile(URI srcUri, File dstFile)
+  private static String maskKey(String key) {
+    if (key == null || key.length() <= 6) {
+      return "***";
+    }
+    int maskLength = key.length() - 6;
+    StringBuilder sb = new StringBuilder();
+    sb.append(key, 0, 3);
+    for (int i = 0; i < maskLength; i++) {
+      sb.append("*");
+    }
+    sb.append(key, key.length() - 3, key.length());
+    return sb.toString();
+  }
+
+  private void logAwsCredentials(String when) {
+    AwsCredentials credentials = getAwsCredentials();
+    if (credentials != null) {
+      LOGGER.warn("S3 credentials {} - Access Key: {}", when, 
maskKey(credentials.accessKeyId()));
+      LOGGER.warn("S3 credentials {} - Secret Key: {}", when, 
maskKey(credentials.secretAccessKey()));
+    } else {
+      LOGGER.warn("S3 credentials {} - Unable to retrieve AWS credentials 
(access key & secret key unavailable)", when);

Review Comment:
   Logging AWS credentials (even masked) at WARN level could expose sensitive 
information in logs. Consider using DEBUG level or removing credential logging 
entirely for production environments.
   ```suggestion
         LOGGER.debug("S3 credentials {} - Access Key: {}", when, 
maskKey(credentials.accessKeyId()));
         LOGGER.debug("S3 credentials {} - Secret Key: {}", when, 
maskKey(credentials.secretAccessKey()));
       } else {
         LOGGER.debug("S3 credentials {} - Unable to retrieve AWS credentials 
(access key & secret key unavailable)", when);
   ```



##########
pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3PinotFS.java:
##########
@@ -690,10 +696,42 @@ private void visitFiles(URI fileUri, boolean recursive, 
Consumer<S3Object> objec
     }
   }
 
-  @Override
-  public void copyToLocalFile(URI srcUri, File dstFile)
+  private static String maskKey(String key) {
+    if (key == null || key.length() <= 6) {
+      return "***";
+    }
+    int maskLength = key.length() - 6;
+    StringBuilder sb = new StringBuilder();
+    sb.append(key, 0, 3);
+    for (int i = 0; i < maskLength; i++) {
+      sb.append("*");
+    }
+    sb.append(key, key.length() - 3, key.length());
+    return sb.toString();
+  }
+
+  private void logAwsCredentials(String when) {
+    AwsCredentials credentials = getAwsCredentials();
+    if (credentials != null) {
+      LOGGER.warn("S3 credentials {} - Access Key: {}", when, 
maskKey(credentials.accessKeyId()));
+      LOGGER.warn("S3 credentials {} - Secret Key: {}", when, 
maskKey(credentials.secretAccessKey()));
+    } else {
+      LOGGER.warn("S3 credentials {} - Unable to retrieve AWS credentials 
(access key & secret key unavailable)", when);
+    }
+  }
+
+  public AwsCredentials getAwsCredentials() {
+    Object provider = 
_s3Client.serviceClientConfiguration().credentialsProvider();
+    if (provider instanceof AwsCredentialsProvider) {
+      return ((AwsCredentialsProvider) provider).resolveCredentials();
+    } else {
+      throw new IllegalStateException("S3 client credentialsProvider is not an 
AwsCredentialsProvider: "
+          + (provider != null ? provider.getClass().getName() : "null"));

Review Comment:
   The getAwsCredentials method throws an IllegalStateException when the 
credentials provider is not the expected type. This could cause the credential 
refresh to fail unexpectedly. Consider returning null or handling this case 
more gracefully to avoid breaking the retry mechanism.
   ```suggestion
         LOGGER.warn("S3 client credentialsProvider is not an 
AwsCredentialsProvider: {}",
             (provider != null ? provider.getClass().getName() : "null"));
         return null;
   ```



##########
pinot-plugins/pinot-file-system/pinot-s3/src/main/java/org/apache/pinot/plugin/filesystem/S3PinotFS.java:
##########
@@ -702,6 +740,28 @@ public void copyToLocalFile(URI srcUri, File dstFile)
     _s3Client.getObject(getObjectRequest, ResponseTransformer.toFile(dstFile));
   }
 
+  @Override
+  public void copyToLocalFile(URI srcUri, File dstFile)
+      throws Exception {
+    try {
+      LOGGER.info("Copy {} to local {}", srcUri, dstFile.getAbsolutePath());
+      copyToLocalFileInternal(srcUri, dstFile);
+    } catch (Exception e) {
+      LOGGER.warn("Caught exception during S3 copy, attempting to refresh 
credentials and retry");
+
+      logAwsCredentials("BEFORE refresh");
+      initOrRefreshS3Client();
+      logAwsCredentials("AFTER refresh");
+
+      try {
+        copyToLocalFileInternal(srcUri, dstFile);
+      } catch (Exception retryException) {
+        throw new Exception("Unexpected exception during S3 copy to local file 
after credential refresh",

Review Comment:
   The error message 'Unexpected exception during S3 copy to local file after 
credential refresh' is generic and doesn't provide context about the original 
failure. Include information about both the original exception and the retry 
exception to aid in debugging.
   ```suggestion
           throw new Exception(
               "Unexpected exception during S3 copy to local file after 
credential refresh. "
                   + "Original exception: " + e.getClass().getName() + ": " + 
e.getMessage() + "; "
                   + "Retry exception: " + retryException.getClass().getName() 
+ ": " + retryException.getMessage(),
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to