Skip to content

Recipe: Managed Identity in Java Apps on Azure Container Apps

Use managed identity with Spring Boot so Java applications can access Azure services without client secrets.

flowchart LR
    C[Client] --> APP[Spring Boot App]
    APP -.-> MI[Managed Identity]
    MI -.-> ENTRA[Microsoft Entra ID]
    MI -.-> BLOB[Azure Blob Storage]
    style APP fill:#107c10,color:#fff

Prerequisites

  • Existing Container App ($APP_NAME) and resource group ($RG)
  • Storage account ($STORAGE_ACCOUNT) and container ($STORAGE_CONTAINER)
  • Azure CLI with Container Apps extension
az extension add --name containerapp --upgrade

Enable managed identity and role assignment

az containerapp identity assign \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --system-assigned

export PRINCIPAL_ID=$(az containerapp show \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --query "identity.principalId" \
  --output tsv)

az role assignment create \
  --assignee-object-id "$PRINCIPAL_ID" \
  --assignee-principal-type ServicePrincipal \
  --role "Storage Blob Data Reader" \
  --scope "$(az storage account show --name "$STORAGE_ACCOUNT" --resource-group "$RG" --query id --output tsv)"

Spring Boot configuration

spring.cloud.azure.active-directory.managed-identity.client-id=${AZURE_CLIENT_ID:}
storage.account-url=https://${STORAGE_ACCOUNT}.blob.core.windows.net
storage.container=${STORAGE_CONTAINER:app-data}

Java example with DefaultAzureCredentialBuilder

import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BlobController {
    @Value("${storage.account-url}")
    private String accountUrl;

    @Value("${storage.container}")
    private String container;

    @GetMapping("/blobs")
    public Iterable<String> blobs() {
        var credential = new DefaultAzureCredentialBuilder().build();
        var service = new BlobServiceClientBuilder().endpoint(accountUrl).credential(credential).buildClient();
        BlobContainerClient containerClient = service.getBlobContainerClient(container);
        return containerClient.listBlobs().stream().map(item -> item.getName()).toList();
    }
}

Advanced Topics

  • Use user-assigned identities when one identity must be reused across services.
  • Scope RBAC at the narrowest resource level (container, vault, database).
  • Add health checks that validate downstream token and authorization readiness.

See Also

Sources