Issue with Azure Container Apps - Workload Profiles - Blob Get User Delegation key

Mateus Parente 30 Reputation points
2025-02-17T17:43:39.74+00:00

Dears,

The Azure Container Apps environments in my current project are a bit old, about 2 years ago, and at that time the workload profiles weren't available yet in my region UK South.

Recently I decided to redeploy one of my environments and redeployed all the Applications. The deployment went fine, we are using Kotlin with Springboot and Azure starter lib for spring. For one Storage account, we use Managed Identities to generate Blob SAS using the User Delegation key but this call hangs forever if never interrupted.

Some bits of my code


BlobServiceAsyncClient client

fun getStorageCredential(): TokenCredential = DefaultAzureCredentialBuilder().build()

BlobServiceClientBuilder()
    .endpoint(endpoint)
    .credential(getStorageCredential())
    .buildAsyncClient()

//THIS CALL NEVER FINISHES
client.getUserDelegationKey(
    OffsetDateTime.ofInstant(Instant.now(), ZoneOffset.systemDefault()),
    OffsetDateTime.ofInstant(Instant.now().plusSeconds(expirationTime.seconds), ZoneOffset.systemDefault())
)

This logic works perfectly well in the old environments.

I mentioned workload profiles because this change is my reference, but I'm still using Consumption anyway, so could be another thing.

Some troubleshooting I did:

  • Configured the storage account as a public
  • Removed firewall and route table of subnet
  • Removed private DNS links to blob
  • Tried to download some files from this storage using a manually generated SAS URL and it worked inside the container.

Logs from the new environment

2025-02-17T17:38:01.1279828Z stdout F 2025-02-17T17:38:01.127Z trace_id= span_id= trace_flags= [NO_USER] INFO 1 --- [onPool-worker-5] c.azure.identity.ChainedTokenCredential  : Azure Identity => Attempted credential EnvironmentCredential is unavailable.
2025-02-17T17:38:01.1295060Z stdout F 2025-02-17T17:38:01.129Z trace_id= span_id= trace_flags= [NO_USER] INFO 1 --- [onPool-worker-5] c.azure.identity.ChainedTokenCredential  : Azure Identity => Attempted credential WorkloadIdentityCredential is unavailable.

And then it gets stuck.

I appreciate any help on that,
Best regards.

Azure Storage Accounts
Azure Storage Accounts
Globally unique resources that provide access to data management services and serve as the parent namespace for the services.
3,384 questions
Azure Blob Storage
Azure Blob Storage
An Azure service that stores unstructured data in the cloud as blobs.
3,094 questions
Azure Container Apps
Azure Container Apps
An Azure service that provides a general-purpose, serverless container platform.
543 questions
{count} votes

Accepted answer
  1. Keshavulu Dasari 3,380 Reputation points Microsoft Vendor
    2025-02-18T13:45:54.6733333+00:00

    Hi Mateus Parente

    You are covered a lot of ground. I Suggest few more suggestions that might help:

    Ensure you are using the latest version of the Azure Identity library. There might be updates or bug fixes that could resolve the issue. Verify that all necessary environment variables for the DefaultAzureCredential are correctly set. This includes variables like AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_CLIENT_SECRET if applicable.

    Double-check the TokenRequestContext to ensure the scope is correctly set. Sometimes, minor issues with the scope can cause the token request to hang.

    Even though there are no network restrictions on the storage account, ensure that the container app has outbound internet access to reach Azure AD endpoints for token acquisition.

    Enable detailed logging for the Azure Identity library to get more insights into what might be causing the hang. This can help identify if the issue is with token acquisition or something else.

    Here's a modified version of your code with added logging for better diagnostics:

    import com.azure.core.credential.TokenCredential
    import com.azure.identity.DefaultAzureCredentialBuilder
    import com.azure.storage.blob.BlobServiceAsyncClient
    import com.azure.storage.blob.BlobServiceClientBuilder
    import com.azure.core.util.logging.ClientLogger
    import java.time.OffsetDateTime
    import java.time.ZoneOffset
    import java.time.Instant
    
    val logger = ClientLogger("BlobService")
    
    fun getStorageCredential(): TokenCredential {
        logger.info("Building DefaultAzureCredential")
        return DefaultAzureCredentialBuilder().build()
    }
    
    val client: BlobServiceAsyncClient = BlobServiceClientBuilder()
        .endpoint(endpoint)
        .credential(getStorageCredential())
        .buildAsyncClient()
    
    // Adding logging and timeout
    val start = OffsetDateTime.ofInstant(Instant.now(), ZoneOffset.systemDefault())
    val expiry = OffsetDateTime.ofInstant(Instant.now().plusSeconds(expirationTime.seconds), ZoneOffset.systemDefault())
    
    client.getUserDelegationKey(start, expiry)
        .timeout(Duration.ofSeconds(30)) // Set a timeout
        .doOnSubscribe { logger.info("Requesting User Delegation Key") }
        .doOnError { error -> logger.error("Error requesting User Delegation Key", error) }
        .retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(10))) // Retry logic
        .subscribe(
            { key -> logger.info("User Delegation Key: $key") },
            { error -> logger.error("Error: ${error.message}") }
        )
    

    Please do not forget to "Accept the answer” and “up-vote” wherever the information provided helps you, this can be beneficial to other community members.   
    User's image

    If you have any other questions or are still running into more issues, let me know in the "comments" and I would be happy to help you.

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.