Cloud applications rarely live inside a single subscription forever. As an organization grows, different teams may own different Azure subscriptions, environments may be separated by business unit, and shared infrastructure can live in a dedicated platform subscription.
That creates a practical infrastructure problem for application developers: an application deployed from one Azure subscription may need to reference resources that belong to another subscription or tenant.
.NET Aspire 13.5 introduces improvements for modeling Azure resources across subscription and tenant boundaries. This makes the AppHost more useful for applications where infrastructure ownership does not follow a single-subscription model.
The important part is understanding what Aspire can model, what Azure still controls, and where permissions become the real constraint.
Why Cross-Tenant Infrastructure Is Difficult
A simple application might have everything in one subscription:
Azure Subscription
|
+-- Resource Group
|
+-- Application
+-- Database
+-- Storage
+-- Messaging
An enterprise environment may look more like this:
Tenant A
|
+-- Subscription A
| |
| +-- Application
|
+-- Subscription B
|
+-- Shared Infrastructure
Tenant B
|
+-- Subscription C
|
+-- Shared Service
The application can therefore have dependencies outside the subscription where the application itself is deployed.
This is where resource references become important.
What Is a Cross-Tenant Resource Reference?
A resource reference represents an existing Azure resource that an application needs to consume without necessarily owning or provisioning that resource as part of the application's deployment.
For example:
Application
|
+----> Storage Account
|
+----> Key Vault
|
+----> Service Bus
The application may be deployed from one subscription while the referenced resource belongs somewhere else.
The distinction between resource ownership and resource consumption is important.
The application deployment does not automatically gain permissions merely because a resource is referenced.
How Aspire Fits Into the Architecture
.NET Aspire uses the AppHost as a central place to describe application resources and their relationships.
A simplified model looks like this:
AppHost
|
+-----------+-----------+
| |
v v
Application Azure Resource
| |
+-----------> Reference+
The AppHost describes the relationship.
Azure remains responsible for:
Resource existence
Identity
Authorization
Subscription boundaries
Tenant boundaries
Deployment permissions
This means Aspire should be viewed as an infrastructure modeling layer rather than an authorization bypass.
Cross-Subscription vs Cross-Tenant
These two scenarios are related but should not be treated as identical.
Cross-Subscription
Two subscriptions belong to the same Microsoft Entra tenant.
Tenant
|
+-- Subscription A
| |
| +-- Application
|
+-- Subscription B
|
+-- Database
Identity and authorization can often be managed within the same organizational identity boundary.
Cross-Tenant
The resources belong to different Microsoft Entra tenants.
Tenant A
|
+-- Application
Tenant B
|
+-- Shared Resource
This introduces additional identity and trust considerations.
The deployment identity needs appropriate access in the target tenant, and the application identity may also need permissions to consume the external resource.
This is fundamentally an Azure identity and authorization problem, not simply an Aspire configuration problem.
Modeling Existing Azure Resources
The general pattern is to distinguish an Azure resource that Aspire manages from one that the application consumes as an existing resource.
Conceptually:
var builder = DistributedApplication.CreateBuilder(args);
var existingStorage = builder.AddAzureStorage(
"shared-storage");
builder.AddProject<Projects.Api>("api")
.WithReference(existingStorage);
builder.Build().Run();
The exact resource API and configuration depend on the Azure resource type and the Aspire version being used.
The important architectural concept is the dependency:
API
|
+-- requires --> Shared Storage
Rather than embedding resource-specific configuration throughout the application, the dependency is represented centrally.
Why Resource References Matter
Without a centralized infrastructure model, configuration often becomes scattered:
appsettings.json
Environment Variables
CI Variables
Deployment Templates
Secrets
Application Code
This can make it difficult to determine which resource an application actually depends on.
A resource reference provides a more explicit relationship.
For example:
Order API
|
+-- PostgreSQL
|
+-- Service Bus
|
+-- Shared Blob Storage
This improves the readability of the application's infrastructure model.
Identity Is the Critical Part
Cross-tenant access usually becomes difficult at the identity layer.
Suppose an application in Tenant A needs to access a storage account in Tenant B.
The architecture might look like:
Application Identity
|
v
Microsoft Entra ID
|
v
Tenant B
|
v
Storage Account
The application identity must be recognized and authorized appropriately.
Simply adding a resource reference does not grant access.
This distinction should be made explicit when designing the deployment.
Avoid Connection Strings Where Managed Identity Is Appropriate
A common pattern in cloud applications is to put a connection string into configuration:
{
"Storage": {
"ConnectionString": "..."
}
}
This can work, but it introduces secret-management responsibilities.
Where the target Azure service supports Microsoft Entra authentication and the application's identity model permits it, managed identity or workload identity can reduce the need to distribute long-lived credentials.
The application might instead authenticate using a credential chain:
var credential = new DefaultAzureCredential();
var client = new BlobServiceClient(
new Uri(storageEndpoint),
credential);
The important production consideration is not simply using DefaultAzureCredential, but ensuring that the deployed identity has exactly the permissions it needs.
Least-Privilege Access
Cross-tenant infrastructure should follow least privilege.
Suppose the application only needs to read blobs.
Do not grant broad administrative permissions when a narrower data-plane role is sufficient.
Think about permissions at multiple levels:
Tenant
|
+-- Subscription
|
+-- Resource Group
|
+-- Resource
|
+-- Data Plane
Join the conversation! Your thoughts help the community grow.