Search code examples
azureazureservicebusazure-managed-identityazure-spring-boot

Send from Spring App to Azure Service Bus: 'Send' claim(s) are required...'


I'm trying to send a message from my Azure Spring App into my Azure Service Bus Queue. The Spring App has a system-assigned managed identity with the Azure Service Bus Data Sender RBAC assigned to it. However, the error still complains that Send claims are missing:

logger: com.azure.core.amqp.implementation.RetryUtil
message: ReactorSender connectionId[MF_1b9f17_166...] linkName[testapptestapp]: Waiting for send and receive handler to be ACTIVE
Unauthorized access. 'Send' claim(s) are required to perform this operation. Resource: 'sb://servicebus-namespace.servicebus.windows.net/testapp'. TrackingId:8479..., SystemTracker:gateway5, Timestamp:2022-08-10T09:46:42, errorContext[NAMESPACE: servicebus-namespace.servicebus.windows.net. ERROR CONTEXT: N/A, PATH: testapp, REFERENCE_ID: testapptestapp, LINK_CREDIT: 0]

One thing that is strange here is that the linkName[testapptestapp] is doubled, shouldn't it only be testapp, not testapptestapp?

This is my Java Code I'm using in my Azure Spring App:

TokenCredential credential = new DefaultAzureCredentialBuilder()
          .build(); // the credential is managed in Azure AD (Role: Azure Service Bus Data Sender)
ServiceBusSenderClient senderClient = new ServiceBusClientBuilder()
          .credential("servicebus-namespace.servicebus.windows.net", credential)
          .sender()
          .queueName("testapp")
          .buildClient();

senderClient.sendMessage(new ServiceBusMessage("test-message"));

Additional info: These additional logs are logged just before the above error message gets logged (in ascending order, the first message gets logged just before the error gets logged):

 logger: com.azure.core.amqp.implementation.ActiveClientTokenManager
   message: { [-]
     az.sdk.message: Scheduling refresh token task.
     scopes: https://servicebus.azure.net/.default

 logger: com.azure.identity.ManagedIdentityCredential
   message: Azure Identity => Managed Identity environment: AZURE VM IMDS ENDPOINT

logger: com.azure.identity.ManagedIdentityCredential
   message: Azure Identity => getToken() result for scopes [https://servicebus.azure.net/.default]: SUCCESS

logger: com.azure.identity.ChainedTokenCredential
   message: Azure Identity => Attempted credential ManagedIdentityCredential returns a token

logger: com.azure.identity.ChainedTokenCredential
   message: Azure Identity => Attempted credential EnvironmentCredential is unavailable.

Why is there a token refresh just before the error gets logged? Could that be the reason for it to fail, the refresh token was not received yet?


Solution

  • Our Service Bus is not in the resource group of the Spring App, so the scope for the role assignment was wrong. I changed the scope to the whole subscription with scope = data.azurerm_subscription.current.id, then it worked:

    resource "azurerm_spring_cloud_app" "myApp" {
      name                = var.spring_cloud_app_name
      resource_group_name = data.azurerm_resource_group.main.name
      service_name        = var.spring_cloud_name
      is_public           = true
    
      identity {
        type = "SystemAssigned"
      }
    }
    
    data "azurerm_subscription" "current" {}
    
    resource "azurerm_role_assignment" "myApp-asb-sender" {
      scope                = data.azurerm_subscription.current.id
      role_definition_name = "Azure Service Bus Data Sender"
      principal_id         = azurerm_spring_cloud_app.myApp.identity[0].principal_id
    }