Skip to content

Conversation

@manika137
Copy link
Contributor

@manika137 manika137 commented Oct 24, 2025

Description of PR

JIRA: https://issues.apache.org/jira/browse/HADOOP-19736
Adding support for new authentication type: user bound SAS

How was this patch tested?

Test suite will be run for the patch

@hadoop-yetus
Copy link

💔 -1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 20m 52s Docker mode activated.
_ Prechecks _
+1 💚 dupname 0m 0s No case conflicting files found.
+0 🆗 codespell 0m 0s codespell was not available.
+0 🆗 detsecrets 0m 0s detect-secrets was not available.
+0 🆗 markdownlint 0m 0s markdownlint was not available.
+1 💚 @author 0m 0s The patch does not contain any @author tags.
+1 💚 test4tests 0m 0s The patch appears to include 5 new or modified test files.
_ trunk Compile Tests _
+1 💚 mvninstall 34m 38s trunk passed
+1 💚 compile 0m 44s trunk passed with JDK Ubuntu-21.0.7+6-Ubuntu-0ubuntu120.04
+1 💚 compile 0m 45s trunk passed with JDK Ubuntu-17.0.15+6-Ubuntu-0ubuntu120.04
+1 💚 checkstyle 0m 34s trunk passed
+1 💚 mvnsite 0m 50s trunk passed
+1 💚 javadoc 0m 45s trunk passed with JDK Ubuntu-21.0.7+6-Ubuntu-0ubuntu120.04
+1 💚 javadoc 0m 37s trunk passed with JDK Ubuntu-17.0.15+6-Ubuntu-0ubuntu120.04
-1 ❌ spotbugs 1m 23s /branch-spotbugs-hadoop-tools_hadoop-azure-warnings.html hadoop-tools/hadoop-azure in trunk has 178 extant spotbugs warnings.
+1 💚 shadedclient 26m 16s branch has no errors when building and testing our client artifacts.
_ Patch Compile Tests _
-1 ❌ mvninstall 0m 34s /patch-mvninstall-hadoop-tools_hadoop-azure.txt hadoop-azure in the patch failed.
-1 ❌ compile 0m 35s /patch-compile-hadoop-tools_hadoop-azure-jdkUbuntu-21.0.7+6-Ubuntu-0ubuntu120.04.txt hadoop-azure in the patch failed with JDK Ubuntu-21.0.7+6-Ubuntu-0ubuntu120.04.
-1 ❌ javac 0m 35s /patch-compile-hadoop-tools_hadoop-azure-jdkUbuntu-21.0.7+6-Ubuntu-0ubuntu120.04.txt hadoop-azure in the patch failed with JDK Ubuntu-21.0.7+6-Ubuntu-0ubuntu120.04.
-1 ❌ compile 0m 35s /patch-compile-hadoop-tools_hadoop-azure-jdkUbuntu-17.0.15+6-Ubuntu-0ubuntu120.04.txt hadoop-azure in the patch failed with JDK Ubuntu-17.0.15+6-Ubuntu-0ubuntu120.04.
-1 ❌ javac 0m 35s /patch-compile-hadoop-tools_hadoop-azure-jdkUbuntu-17.0.15+6-Ubuntu-0ubuntu120.04.txt hadoop-azure in the patch failed with JDK Ubuntu-17.0.15+6-Ubuntu-0ubuntu120.04.
-1 ❌ blanks 0m 0s /blanks-eol.txt The patch has 3 line(s) that end in blanks. Use git apply --whitespace=fix <<patch_file>>. Refer https://git-scm.com/docs/git-apply
-0 ⚠️ checkstyle 0m 22s /results-checkstyle-hadoop-tools_hadoop-azure.txt hadoop-tools/hadoop-azure: The patch generated 36 new + 4 unchanged - 0 fixed = 40 total (was 4)
-1 ❌ mvnsite 0m 37s /patch-mvnsite-hadoop-tools_hadoop-azure.txt hadoop-azure in the patch failed.
-1 ❌ javadoc 0m 32s /results-javadoc-javadoc-hadoop-tools_hadoop-azure-jdkUbuntu-21.0.7+6-Ubuntu-0ubuntu120.04.txt hadoop-tools_hadoop-azure-jdkUbuntu-21.0.7+6-Ubuntu-0ubuntu120.04 with JDK Ubuntu-21.0.7+6-Ubuntu-0ubuntu120.04 generated 2 new + 1472 unchanged - 0 fixed = 1474 total (was 1472)
-1 ❌ javadoc 0m 30s /results-javadoc-javadoc-hadoop-tools_hadoop-azure-jdkUbuntu-17.0.15+6-Ubuntu-0ubuntu120.04.txt hadoop-tools_hadoop-azure-jdkUbuntu-17.0.15+6-Ubuntu-0ubuntu120.04 with JDK Ubuntu-17.0.15+6-Ubuntu-0ubuntu120.04 generated 2 new + 1413 unchanged - 0 fixed = 1415 total (was 1413)
-1 ❌ spotbugs 0m 34s /patch-spotbugs-hadoop-tools_hadoop-azure.txt hadoop-azure in the patch failed.
+1 💚 shadedclient 29m 4s patch has no errors when building and testing our client artifacts.
_ Other Tests _
-1 ❌ unit 0m 41s /patch-unit-hadoop-tools_hadoop-azure.txt hadoop-azure in the patch failed.
+1 💚 asflicense 0m 34s The patch does not generate ASF License warnings.
119m 57s
Subsystem Report/Notes
Docker ClientAPI=1.51 ServerAPI=1.51 base: https://ci-hadoop.apache.org/job/hadoop-multibranch/job/PR-8051/1/artifact/out/Dockerfile
GITHUB PR #8051
JIRA Issue HADOOP-19736
Optional Tests dupname asflicense compile javac javadoc mvninstall mvnsite unit shadedclient spotbugs checkstyle codespell detsecrets markdownlint
uname Linux 88abe69cd96c 5.15.0-156-generic #166-Ubuntu SMP Sat Aug 9 00:02:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Build tool maven
Personality dev-support/bin/hadoop.sh
git revision trunk / 05b52e4
Default Java Ubuntu-17.0.15+6-Ubuntu-0ubuntu120.04
Multi-JDK versions /usr/lib/jvm/java-21-openjdk-amd64:Ubuntu-21.0.7+6-Ubuntu-0ubuntu120.04 /usr/lib/jvm/java-17-openjdk-amd64:Ubuntu-17.0.15+6-Ubuntu-0ubuntu120.04
Test Results https://ci-hadoop.apache.org/job/hadoop-multibranch/job/PR-8051/1/testReport/
Max. process+thread count 779 (vs. ulimit of 5500)
modules C: hadoop-tools/hadoop-azure U: hadoop-tools/hadoop-azure
Console output https://ci-hadoop.apache.org/job/hadoop-multibranch/job/PR-8051/1/console
versions git=2.25.1 maven=3.9.11 spotbugs=4.9.7
Powered by Apache Yetus 0.14.0 https://yetus.apache.org

This message was automatically generated.

@manika137 manika137 marked this pull request as draft October 27, 2025 15:26
@hadoop-yetus
Copy link

💔 -1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 0m 0s Docker mode activated.
-1 ❌ docker 4m 52s Docker failed to build run-specific yetus/hadoop:tp-4947}.
Subsystem Report/Notes
GITHUB PR #8051
JIRA Issue HADOOP-19736
Console output https://ci-hadoop.apache.org/job/hadoop-multibranch/job/PR-8051/2/console
versions git=2.34.1
Powered by Apache Yetus 0.14.0 https://yetus.apache.org

This message was automatically generated.

@hadoop-yetus
Copy link

💔 -1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 0m 0s Docker mode activated.
-1 ❌ docker 6m 57s Docker failed to build run-specific yetus/hadoop:tp-29291}.
Subsystem Report/Notes
GITHUB PR #8051
JIRA Issue HADOOP-19736
Console output https://ci-hadoop.apache.org/job/hadoop-multibranch/job/PR-8051/3/console
versions git=2.34.1
Powered by Apache Yetus 0.14.0 https://yetus.apache.org

This message was automatically generated.

@hadoop-yetus
Copy link

💔 -1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 0m 0s Docker mode activated.
-1 ❌ docker 6m 5s Docker failed to build run-specific yetus/hadoop:tp-27223}.
Subsystem Report/Notes
GITHUB PR #8051
JIRA Issue HADOOP-19736
Console output https://ci-hadoop.apache.org/job/hadoop-multibranch/job/PR-8051/4/console
versions git=2.34.1
Powered by Apache Yetus 0.14.0 https://yetus.apache.org

This message was automatically generated.

AUG_03_2023("2023-08-03"),
NOV_04_2024("2024-11-04");
NOV_04_2024("2024-11-04"),
JULY_05_2025("2025-07-05");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should follow the same format: JUL_05_2025, what do you think?

abfsClientContext);
}

public AbfsClientHandler(final URL baseUrl,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java doc missing for the constructor

this.sasTokenProvider = sasTokenProvider;
}

public AbfsClient(final URL baseUrl,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java doc missing

encryptionContextProvider, abfsClientContext, AbfsServiceType.DFS);
}

public AbfsDfsClient(final URL baseUrl,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java doc missing

case UserboundSASWithOAuth:
httpOperation.setRequestProperty(HttpHeaderConfigurations.AUTHORIZATION,
client.getAccessToken());
httpOperation.setMaskForSAS(); //mask sig/oid from url for logs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: *sign

tokenProvider, sasTokenProvider, encryptionContextProvider,
populateAbfsClientContext());
}
else if (tokenProvider != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above


LOG.trace("Initializing AbfsClient for {}", baseUrl);
if (tokenProvider != null) {
if(tokenProvider != null && sasTokenProvider != null){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space between if and (

3. Deployed in-Azure with the Azure VMs providing OAuth 2.0 tokens to the application, "Managed Instance".
4. Using Shared Access Signature (SAS) tokens provided by a custom implementation of the SASTokenProvider interface.
5. By directly configuring a fixed Shared Access Signature (SAS) token in the account configuration settings files.
6. Using user-bound SAS auth type, which is requires OAuth 2.0 setup (point 2 above) and SAS setup (point 4 above)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammatical mistake: which requires or which is required?


public static final String FS_AZURE_TEST_APP_SERVICE_PRINCIPAL_OBJECT_ID = "fs.azure.test.app.service.principal.object.id";

public static final String FS_AZURE_END_USER_TENANT_ID = "fs.azure.test.end.user.tenant.id";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the variable to FS_AZURE_TEST_END_USER_TENANT_ID

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think TEST should come first. Check for how other test related configs are defined. TestConfigurationKeys.java have them

public static final String FS_AZURE_TEST_APP_SERVICE_PRINCIPAL_OBJECT_ID = "fs.azure.test.app.service.principal.object.id";

public static final String FS_AZURE_END_USER_TENANT_ID = "fs.azure.test.end.user.tenant.id";
public static final String FS_AZURE_END_USER_OBJECT_ID = "fs.azure.test.end.user.object.id";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Dec19("2019-12-12"),
Feb20("2020-02-10");
Feb20("2020-02-10"),
July5("2025-07-05");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here should be JUL

private final String sduoid;

public DelegationSASGenerator(byte[] userDelegationKey, String skoid, String sktid, String skt, String ske, String skv) {
public DelegationSASGenerator(byte[] userDelegationKey, String skoid, String sktid, String skt, String ske, String skv, String skdutid, String sduoid) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add javadoc for what do all these params signify

qb.addQuery("skv", skv);

//skdutid and sduoid are required for user bound SAS only
if(!Objects.equals(skdutid, EMPTY_STRING)){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spaces after if


String stringToSign = sb.toString();
LOG.debug("Delegation SAS stringToSign: " + stringToSign.replace("\n", "."));
System.out.println("Delegation SAS stringToSign: " + stringToSign.replace("\n", "."));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this


// Invokes the AAD v2.0 authentication endpoint with a client credentials grant to get an
// access token. See https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow.
private String getAuthorizationHeader(String accountName, String appID, String appSecret, String sktid) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include params in javadoc as well

// Invokes the AAD v2.0 authentication endpoint with a client credentials grant to get an
// access token. See https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow.
private String getAuthorizationHeader(String accountName, String appID, String appSecret, String sktid) throws IOException {
String authEndPoint = String.format("https://login.microsoftonline.com/%s/oauth2/v2.0/token", sktid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a constant for the string

return "Bearer " + provider.getToken().getAccessToken();
}

private byte[] getUserDelegationKey(String accountName, String appID, String appSecret,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javadoc

private byte[] getUserDelegationKey(String accountName, String appID, String appSecret,
String sktid, String skt, String ske, String skv, String skdutid) throws IOException {

String method = "POST";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have constants for HTTP methods, can be used here

final StringBuilder sb = new StringBuilder(128);
sb.append("https://");
sb.append(account);
sb.append(".blob.core.windows.net/?restype=service&comp=userdelegationkey");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to use constants as much as possible

requestBody.append(skdutid);
requestBody.append("</DelegatedUserTid></KeyInfo>");

// requestBody.append("<?xml version=\"1.0\" encoding=\"utf-8\"?><KeyInfo><Start>");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove comments


public static ApiVersion getCurrentVersion() {
return NOV_04_2024;
return JULY_05_2025;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we bumping up version for all the requests?
Wasn't this version bump only needed for Auth related APIs?

this.sasTokenProvider = sasTokenProvider;
}

public AbfsClient(final URL baseUrl,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we simply combine the 3 constructors to accept both AccessTokenProvider, SASTokenProvider and the caller can set what it has and null as other?

abfsClientContext);
}

public AbfsClientHandler(final URL baseUrl,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. We can combine into a single constructor.
But do check if there are any caveats there or a risk of running into NPE

final AbfsClientContext abfsClientContext) throws IOException {
URL dfsUrl = changeUrlFromBlobToDfs(baseUrl);
if (tokenProvider != null) {
if (tokenProvider != null && sasTokenProvider != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from UDS, can there be a case where caller can send both as not null? Makes ure no flow leads to this and also add a test around it.

encryptionContextProvider, abfsClientContext, AbfsServiceType.DFS);
}

public AbfsDfsClient(final URL baseUrl,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this only for DFS Client?

* @return sasTokenProvider object based on configurations provided
* @throws AzureBlobFileSystemException
*/
public SASTokenProvider getSASTokenProviderForUserBoundSAS() throws AzureBlobFileSystemException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can be renamed as getUserBoundSASTokenProvider

getTokenProviderClass(authType, FS_AZURE_SAS_TOKEN_PROVIDER_TYPE,
null, SASTokenProvider.class);

if (customSasTokenProviderImplementation == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar check for OAuth also needed right?
For UBS, Cx must configure OAuth as well?

LOG.trace("Fetching SAS Token Provider");
sasTokenProvider = abfsConfiguration.getSASTokenProvider();
} else {
} else if(authType == AuthType.UserboundSASWithOAuth){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here also, it can be combined into a single call with both passed.


public static final String FS_AZURE_TEST_APP_SERVICE_PRINCIPAL_OBJECT_ID = "fs.azure.test.app.service.principal.object.id";

public static final String FS_AZURE_END_USER_TENANT_ID = "fs.azure.test.end.user.tenant.id";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think TEST should come first. Check for how other test related configs are defined. TestConfigurationKeys.java have them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants