[ 
https://issues.apache.org/jira/browse/HADOOP-19736?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18039287#comment-18039287
 ] 

ASF GitHub Bot commented on HADOOP-19736:
-----------------------------------------

manika137 commented on code in PR #8051:
URL: https://github.com/apache/hadoop/pull/8051#discussion_r2540494549


##########
hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAzureBlobFileSystemUserBoundSAS.java:
##########
@@ -0,0 +1,432 @@
+/**
+ * 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.fs.azurebfs;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.AccessDeniedException;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import org.apache.hadoop.fs.FSDataInputStream;
+import org.apache.hadoop.fs.FSDataOutputStream;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys;
+import org.apache.hadoop.fs.azurebfs.contracts.services.ListResultEntrySchema;
+import org.apache.hadoop.fs.azurebfs.extensions.MockInvalidSASTokenProvider;
+import org.apache.hadoop.fs.azurebfs.extensions.MockUserBoundSASTokenProvider;
+import org.apache.hadoop.fs.azurebfs.extensions.SASTokenProvider;
+import org.apache.hadoop.fs.azurebfs.oauth2.AccessTokenProvider;
+import org.apache.hadoop.fs.azurebfs.oauth2.AzureADToken;
+import org.apache.hadoop.fs.azurebfs.services.AbfsBlobClient;
+import org.apache.hadoop.fs.azurebfs.services.AbfsClient;
+import org.apache.hadoop.fs.azurebfs.services.AbfsRestOperation;
+import org.apache.hadoop.fs.azurebfs.services.AuthType;
+
+import static 
org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeys.FS_AZURE_ACCOUNT_OAUTH_CLIENT_ID;
+import static 
org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeys.FS_AZURE_ACCOUNT_OAUTH_CLIENT_SECRET;
+import static 
org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeys.FS_AZURE_SAS_TOKEN_PROVIDER_TYPE;
+import static 
org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_BLOB_FS_CHECKACCESS_TEST_CLIENT_ID;
+import static 
org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_BLOB_FS_CHECKACCESS_TEST_CLIENT_SECRET;
+import static 
org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_BLOB_FS_CHECKACCESS_TEST_USER_GUID;
+import static 
org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_BLOB_FS_CLIENT_SERVICE_PRINCIPAL_OBJECT_ID;
+import static 
org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_TEST_APP_SERVICE_PRINCIPAL_TENANT_ID;
+import static 
org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_TEST_END_USER_OBJECT_ID;
+import static 
org.apache.hadoop.fs.azurebfs.constants.TestConfigurationKeys.FS_AZURE_TEST_END_USER_TENANT_ID;
+import static org.apache.hadoop.test.LambdaTestUtils.intercept;
+import static org.assertj.core.api.Assumptions.assumeThat;
+
+/**
+ * Integration tests for AzureBlobFileSystem using User-Bound SAS and OAuth.
+ * Covers scenarios for token provider configuration, SAS token validity, and 
basic file operations.
+ */
+public class ITestAzureBlobFileSystemUserBoundSAS
+    extends AbstractAbfsIntegrationTest {
+
+  private static Path testPath = new Path("/test.txt");
+
+  private static final String TEST_OBJECT_ID = "123456789";
+
+  private static final String INVALID_OAUTH_TOKEN_VALUE = 
"InvalidOAuthTokenValue";
+
+  /**
+   * Constructor. Ensures tests run with SharedKey authentication.
+   * @throws Exception if auth type is not SharedKey
+   */
+  protected ITestAzureBlobFileSystemUserBoundSAS() throws Exception {
+    assumeThat(this.getAuthType()).isEqualTo(AuthType.SharedKey);
+  }
+
+  /**
+   * Sets up the test environment and configures the AbfsConfiguration for 
user-bound SAS tests.
+   * @throws Exception if setup fails
+   */
+  @BeforeEach
+  @Override
+  public void setup() throws Exception {
+    AbfsConfiguration abfsConfig = this.getConfiguration();
+    String accountName = getAccountName();
+
+    Boolean isHNSEnabled = abfsConfig.getBoolean(
+        TestConfigurationKeys.FS_AZURE_TEST_NAMESPACE_ENABLED_ACCOUNT, false);
+
+    if (!isHNSEnabled) {
+      assumeBlobServiceType();
+    }
+
+    createFilesystemForUserBoundSASTests();
+    super.setup();
+
+    // Set all required configs on the raw configuration
+    abfsConfig.set(
+        FS_AZURE_BLOB_FS_CLIENT_SERVICE_PRINCIPAL_OBJECT_ID + "." + 
accountName,
+        abfsConfig.get(FS_AZURE_BLOB_FS_CHECKACCESS_TEST_USER_GUID));
+    abfsConfig.set(FS_AZURE_BLOB_FS_CLIENT_SERVICE_PRINCIPAL_OBJECT_ID,
+        abfsConfig.get(FS_AZURE_BLOB_FS_CHECKACCESS_TEST_USER_GUID));
+    abfsConfig.set(FS_AZURE_ACCOUNT_OAUTH_CLIENT_ID + "." + accountName,
+        abfsConfig.get(FS_AZURE_BLOB_FS_CHECKACCESS_TEST_CLIENT_ID));
+    abfsConfig.set(FS_AZURE_ACCOUNT_OAUTH_CLIENT_ID,
+        abfsConfig.get(FS_AZURE_BLOB_FS_CHECKACCESS_TEST_CLIENT_ID));
+    abfsConfig.set(FS_AZURE_ACCOUNT_OAUTH_CLIENT_SECRET + "." + accountName,
+        abfsConfig.get(FS_AZURE_BLOB_FS_CHECKACCESS_TEST_CLIENT_SECRET));
+    abfsConfig.set(FS_AZURE_ACCOUNT_OAUTH_CLIENT_SECRET,
+        abfsConfig.get(FS_AZURE_BLOB_FS_CHECKACCESS_TEST_CLIENT_SECRET));
+    abfsConfig.set(FS_AZURE_TEST_END_USER_TENANT_ID,
+        abfsConfig.get(FS_AZURE_TEST_APP_SERVICE_PRINCIPAL_TENANT_ID));
+    abfsConfig.set(FS_AZURE_TEST_END_USER_OBJECT_ID,
+        abfsConfig.get(FS_AZURE_BLOB_FS_CHECKACCESS_TEST_USER_GUID));
+    abfsConfig.set(FS_AZURE_SAS_TOKEN_PROVIDER_TYPE,
+        MockUserBoundSASTokenProvider.class.getName());
+  }
+
+
+  /**
+   * Injects a mock AccessTokenProvider into the AbfsClient of the given 
filesystem.
+   * @param fs AzureBlobFileSystem instance
+   * @param mockProvider AccessTokenProvider to inject
+   * @throws Exception if reflection fails
+   */
+  private void injectMockTokenProvider(AzureBlobFileSystem fs,
+      AccessTokenProvider mockProvider) throws Exception {
+    Field abfsStoreField = AzureBlobFileSystem.class.getDeclaredField(
+        "abfsStore");
+    abfsStoreField.setAccessible(true);
+    AzureBlobFileSystemStore store
+        = (AzureBlobFileSystemStore) abfsStoreField.get(fs);
+
+    Field abfsClientField = AzureBlobFileSystemStore.class.getDeclaredField(
+        "client");
+    abfsClientField.setAccessible(true);
+    AbfsClient client = (AbfsClient) abfsClientField.get(store);
+
+    Field tokenProviderField = AbfsClient.class.getDeclaredField(
+        "tokenProvider");
+    tokenProviderField.setAccessible(true);
+    tokenProviderField.set(client, mockProvider);
+  }
+
+  /**
+   * Helper to create a new AzureBlobFileSystem instance for tests.
+   * @return AzureBlobFileSystem instance
+   * @throws RuntimeException if creation fails
+   */
+  private AzureBlobFileSystem createTestFileSystem() throws RuntimeException {
+    try {
+      return (AzureBlobFileSystem) FileSystem.newInstance(
+          getRawConfiguration());
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Test that file creation fails when the end user object ID does not match 
the service principal object ID.
+   * @throws Exception if test fails
+   */
+  @Test
+  public void testShouldFailWhenSduoidMismatchesServicePrincipalId()
+      throws Exception {
+    this.getConfiguration()
+        .set(FS_AZURE_TEST_END_USER_OBJECT_ID, TEST_OBJECT_ID);
+    AzureBlobFileSystem testFs = createTestFileSystem();
+    intercept(AccessDeniedException.class,
+        () -> {
+          testFs.create(testPath);
+        });
+  }
+
+  /**
+   * Verifies that both OAuth token provider and user-bound SAS token provider 
are configured and usable.
+   * @throws Exception if test fails
+   */
+  @Test
+  public void testOAuthTokenProviderAndSASTokenFlow() throws Exception {
+    AzureBlobFileSystem testFs = createTestFileSystem();
+
+    AbfsConfiguration abfsConfiguration = testFs.getAbfsStore()
+        .getAbfsConfiguration();
+
+    // Verify AbfsConfiguration has an OAuth token provider configured
+    AccessTokenProvider tokenProvider = abfsConfiguration.getTokenProvider();
+    assertNotNull(tokenProvider,
+        "AccessTokenProvider must be configured for UserboundSASWithOAuth");
+
+    // Acquire an OAuth token and assert it is non-empty
+    AzureADToken token = tokenProvider.getToken();
+    assertNotNull(token, "OAuth token must not be null");
+    assertNotNull(token.getAccessToken(),
+        "OAuth access token must not be null");
+    assertFalse(token.getAccessToken().isEmpty(),
+        "OAuth access token must not be empty");
+
+    // Verify AbfsConfiguration has an SASTokenProvider configured
+    SASTokenProvider sasProvider
+        = abfsConfiguration.getUserBoundSASTokenProvider(
+        AuthType.UserboundSASWithOAuth);
+    assertNotNull(sasProvider,
+        "SASTokenProvider for user-bound SAS must be configured");
+    assertInstanceOf(MockUserBoundSASTokenProvider.class, sasProvider,
+        "Expected MockUserBoundSASTokenProvider to be used for tests");
+
+    // Request a SAS token and assert we get a non-empty result
+    String sasToken = sasProvider.getSASToken(
+        "abfsdrivercanaryhns.dfs.core.windows.net", "userbound", "/",
+        SASTokenProvider.GET_PROPERTIES_OPERATION);
+    assertNotNull(sasToken, "SAS token must not be null");
+    assertFalse(sasToken.isEmpty(), "SAS token must not be empty");
+  }
+
+  /*
+   * Tests listing and deleting files under an implicit directory
+   */
+  @Test
+  public void testOperationsForImplicitPaths() throws Exception {

Review Comment:
   In setup, if non-hns, we're assuming it to be Blob endpoint. It won't run 
for FNS-DFS
   In this test, we're only running for Blob endpoint as well





> ABFS: Support for new auth type: User-bound SAS
> -----------------------------------------------
>
>                 Key: HADOOP-19736
>                 URL: https://issues.apache.org/jira/browse/HADOOP-19736
>             Project: Hadoop Common
>          Issue Type: Task
>          Components: fs/azure
>    Affects Versions: 3.4.1, 3.4.2
>            Reporter: Manika Joshi
>            Assignee: Manika Joshi
>            Priority: Major
>              Labels: pull-request-available
>
> Adding support for new authentication type: user bound SAS



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

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

Reply via email to