[
https://issues.apache.org/jira/browse/HADOOP-19736?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18039135#comment-18039135
]
ASF GitHub Bot commented on HADOOP-19736:
-----------------------------------------
anmolanmol1234 commented on code in PR #8051:
URL: https://github.com/apache/hadoop/pull/8051#discussion_r2537688385
##########
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 the setup we don't assume non hns for all cases, shouldn't we add that
assumption here ?
> 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]