Skip to content

Conversation

@g2vinay
Copy link
Member

@g2vinay g2vinay commented Oct 20, 2025

Adds Workload Identity Auth Support in KV JCA

@github-actions github-actions bot added the azure-spring All azure-spring related issues label Oct 20, 2025
@g2vinay g2vinay marked this pull request as ready for review November 4, 2025 07:05
@g2vinay g2vinay requested a review from rujche as a code owner November 4, 2025 07:05
Copilot AI review requested due to automatic review settings November 4, 2025 07:05
@g2vinay g2vinay requested review from a team, Netyyyy, moarychan and saragluna as code owners November 4, 2025 07:05
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for Azure Workload Identity authentication for Azure Kubernetes Service (AKS) workloads in the Key Vault JCA library. This enables credential-free authentication for AKS pods using federated tokens.

Key changes:

  • Implemented federated token-based authentication flow using environment variables (AZURE_FEDERATED_TOKEN_FILE, AZURE_CLIENT_ID, AZURE_TENANT_ID)
  • Added automatic detection and prioritization of Workload Identity authentication
  • Updated documentation with detailed authentication method examples and selection logic

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/utils/AccessTokenUtil.java Added Workload Identity support with detection logic, token file reading, and OAuth2 client assertion flow implementation
sdk/keyvault/azure-security-keyvault-jca/README.md Added comprehensive authentication method documentation with examples for Service Principal, Managed Identity, and Workload Identity
sdk/keyvault/azure-security-keyvault-jca/CHANGELOG.md Documented new Workload Identity feature in the unreleased version section

Comment on lines +234 to +238
requestBody.append("grant_type=client_credentials")
.append("&client_id=").append(clientId)
.append("&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.append("&client_assertion=").append(federatedToken)
.append("&scope=").append(resource);
Copy link

Copilot AI Nov 4, 2025

Choose a reason for hiding this comment

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

The clientId, federatedToken, and resource parameters should be URL-encoded before being appended to the request body to prevent malformed requests or potential injection issues. Other methods in this class (e.g., getAccessToken on line 149 and KeyVaultClient.getAccessTokenByHttpRequest on lines 196-199) properly URL-encode parameters. Add URLEncoder.encode(parameter, \"UTF-8\") for these values.

Suggested change
requestBody.append("grant_type=client_credentials")
.append("&client_id=").append(clientId)
.append("&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.append("&client_assertion=").append(federatedToken)
.append("&scope=").append(resource);
try {
requestBody.append("grant_type=client_credentials")
.append("&client_id=").append(URLEncoder.encode(clientId, "UTF-8"))
.append("&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.append("&client_assertion=").append(URLEncoder.encode(federatedToken, "UTF-8"))
.append("&scope=").append(URLEncoder.encode(resource, "UTF-8"));
} catch (UnsupportedEncodingException e) {
LOGGER.log(WARNING, "Failed to URL-encode parameters for access token request.", e);
return null;
}

Copilot uses AI. Check for mistakes.
Comment on lines +273 to +274
java.nio.file.Path path = java.nio.file.Paths.get(tokenFilePath);
String token = new String(java.nio.file.Files.readAllBytes(path), java.nio.charset.StandardCharsets.UTF_8).trim();
Copy link

Copilot AI Nov 4, 2025

Choose a reason for hiding this comment

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

Use standard Java imports instead of fully-qualified class names. Add import java.nio.file.Path;, import java.nio.file.Paths;, import java.nio.file.Files;, and import java.nio.charset.StandardCharsets; at the top of the file, then use Path, Paths, Files, and StandardCharsets directly. This follows the existing code style where other Java classes are imported.

Copilot uses AI. Check for mistakes.

try {
String tokenFilePath = System.getenv(PROPERTY_AZURE_FEDERATED_TOKEN_FILE);
String clientId = System.getenv(PROPERTY_AZURE_CLIENT_ID);
Copy link

@thomob thomob Nov 6, 2025

Choose a reason for hiding this comment

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

I think it would be better to use the fields (clientId and tenantId) of KeyVaultClient and fallback to the environment variables only if unset. This would allow configuring a different identity then the default pod identity.

String clientId = (identity != null && !identity.isEmpty()) ? identity : System.getenv(PROPERTY_AZURE_CLIENT_ID)

@writemevenkat
Copy link

Any ETA for this implementation ?

@github-actions
Copy link
Contributor

Hi @g2vinay. Thank you for your interest in helping to improve the Azure SDK experience and for your contribution. We've noticed that there hasn't been recent engagement on this pull request. If this is still an active work stream, please let us know by pushing some changes or leaving a comment. Otherwise, we'll close this out in 7 days.

@github-actions github-actions bot added the no-recent-activity There has been no recent activity on this issue. label Jan 16, 2026
@writemevenkat
Copy link

Hi Azure SDK Team,

Our team is currently blocked from moving to AKS due to the absence of this feature. Please prioritize this enhancement, as it is critical for our migration plans. @g2vinay

* `azure.keyvault.tenant-id`: The Microsoft Entra ID tenant ID (required for Service Principal authentication).
* `azure.keyvault.client-id`: The client/application ID (required for Service Principal authentication).
* `azure.keyvault.client-secret`: The client secret (required for Service Principal authentication).
* `azure.keyvault.managed-identity`: The user-assigned managed identity object ID (optional, for user-assigned managed identity).
Copy link
Member

Choose a reason for hiding this comment

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

nit: Change above 4 lines to format like this: (Only required when using ...)

**Note:**
- **For Service Principal authentication**: Set all four properties (`uri`, `tenant-id`, `client-id`, `client-secret`)
- **For Managed Identity authentication**: Only set `azure.keyvault.uri` (and optionally `managed-identity` for user-assigned identity)
- **For Workload Identity authentication (AKS)**: Only set `azure.keyvault.uri` - the provider automatically detects Workload Identity environment variables
Copy link
Member

Choose a reason for hiding this comment

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

How about avoid duplication by adding link to other section of current file?

&& System.getenv(PROPERTY_AZURE_CLIENT_ID) != null
&& !System.getenv(PROPERTY_AZURE_CLIENT_ID).isEmpty()
&& System.getenv(PROPERTY_AZURE_TENANT_ID) != null
&& !System.getenv(PROPERTY_AZURE_TENANT_ID).isEmpty();
Copy link
Member

Choose a reason for hiding this comment

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

How about using a util method like in this PR: https://github.com/Azure/azure-sdk-for-java/pull/47749/files

// Read the federated token from the file
String federatedToken = readTokenFromFile(tokenFilePath);

if (federatedToken == null || federatedToken.isEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

The util method mentioned above can be used here, too.

private static String readTokenFromFile(String tokenFilePath) throws IOException {
LOGGER.entering("AccessTokenUtil", "readTokenFromFile", tokenFilePath);

java.nio.file.Path path = java.nio.file.Paths.get(tokenFilePath);
Copy link
Member

Choose a reason for hiding this comment

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

Import the package here.

Copy link
Member

@rujche rujche left a comment

Choose a reason for hiding this comment

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

Please update the PR according to the comments and this PR: https://github.com/Azure/azure-sdk-for-java/pull/47749/files

@github-project-automation github-project-automation bot moved this from Todo to In Progress in Spring Cloud Azure Jan 21, 2026
@rujche rujche added this to the 2026-02 milestone Jan 21, 2026
@github-actions
Copy link
Contributor

Hi @g2vinay. Thank you for your contribution. Since there hasn't been recent engagement, we're going to close this out. Feel free to respond with a comment containing /reopen if you'd like to continue working on these changes. Please be sure to use the command to reopen or remove the no-recent-activity label; otherwise, this is likely to be closed again with the next cleanup pass.

@github-actions github-actions bot closed this Jan 28, 2026
@github-project-automation github-project-automation bot moved this from In Progress to Done in Spring Cloud Azure Jan 28, 2026
@writemevenkat
Copy link

Hi @g2vinay, @rujche - I’m not sure why this PR was auto-closed even though there was recent activity. Could you please take a look and continue/reopen it? We’ve been waiting for this feature to be available.

@github-actions
Copy link
Contributor

Sorry, @writemevenkat, only the original author can reopen this pull request.

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

Labels

azure-spring All azure-spring related issues no-recent-activity There has been no recent activity on this issue.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants