Blob Storage¶
This guide explains how to enable and integrate Azure Blob Storage with API services using the Forge platform, covering both Terraform infrastructure setup and Aspire local development.
đ¯ Overview¶
Azure Blob Storage provides scalable, secure object storage for unstructured data. The Forge platform provides:
- Terraform Module: Automated Azure Blob Storage Account provisioning
- Aspire Integration: Local development and testing with storage emulator
- RBAC Authentication: Secure, token-based access via managed identity
- Feature Flags: Flexible enable/disable configuration
đ§ Infrastructure Setup (Terraform)¶
Enable Blob Storage Feature Flag¶
In your saif-api-service Terraform configuration, add the blob storage feature flag:
enable_blob_storage = true
blob_storage_settings = {
containers = ["blobcontainer"]
contributor_group_id = "group-object-id-guid"
}
Configuration Options:
| Property | Type | Description | Example |
|---|---|---|---|
enable_blob_storage |
bool | Enable/disable blob storage deployment | true |
containers |
list(string) | List of blob container names to create | ["uploads", "archives"] |
contributor_group_id |
string | Azure AD group object ID for contributor access | "12345678-1234-1234-1234-123456789abc" |
Example Terraform Configuration¶
module "saif_api_service" {
source = "app.terraform.io/SAIFCorp/saif-api-service/azure"
environment = "dev"
project_id = "myapi"
owner = "Platform Team"
resource_location = "westus2"
# Enable blob storage
feature_flags = {
enable_blob_storage = true
blob_storage_settings = {
containers = [
"documents",
"uploads",
"archives"
]
contributor_group_id = data.azuread_group.platform_team.object_id
}
}
tags = {
Environment = "Development"
Application = "MyAPI"
}
}
data "azuread_group" "platform_team" {
display_name = "Platform Team"
}
Generated Resources¶
When enable_blob_storage = true, the following resources are automatically created:
- đī¸ Azure Storage Account (naming convention:
{projectid}{environment}corp, e.g.,myapitestcorp,myapiprodcorp) - đĻ Blob Containers (with names from
containerslist) - đ RBAC Role Assignments:
- Storage Account Contributor: Assigned to the contributor group
- Storage Blob Data Owner: Assigned to application managed identity
- âī¸ Environment Variables: Storage account connection details are automatically configured in Azure
đĨī¸ Local Development (Aspire)¶
Aspire Storage Emulator Setup¶
For local development, use the Azure Storage Emulator integrated with Aspire:
AppHost Configuration¶
// Program.cs in YourApp.AppHost
var builder = DistributedApplication.CreateBuilder(args);
// Add Azure Storage with emulator
var storage = builder
.AddAzureStorage("storage")
.RunAsEmulator()
.AddBlobs("blobstorage");
// Reference storage in your backend service
var backend = builder
.AddApi()
.WithReference(storage);
// Add web frontend
var frontend = builder
.AddWebFrontEnd(backend);
builder.Build().Run();
Configuration Options:
.RunAsEmulator()- Uses local storage emulator (no Azure account required).AddBlobs("blobstorage")- Adds blob storage resource with specified name (used to reference in services).WithReference()- Injects storage connection details into service
Using Blob Storage in Your Service¶
Service Registration¶
In your Program.cs, register the Azure Blob Service client:
âšī¸
AddAzureBlobServiceClientautomatically usesDefaultAzureCredentialwhen deployed to Azure and connection strings for local development.
Minimal API Examples¶
using Azure.Storage.Blobs;
// Upload endpoint
app.MapPost("/api/upload", async (IFormFile file, BlobServiceClient blobServiceClient) =>
{
if (file is null || file.Length == 0)
{
return Results.BadRequest(new { Error = "No file provided" });
}
var containerClient = blobServiceClient.GetBlobContainerClient("uploads");
await containerClient.CreateIfNotExistsAsync();
var blobName = $"{Guid.NewGuid()}-{file.FileName}";
var blobClient = containerClient.GetBlobClient(blobName);
await using var stream = file.OpenReadStream();
await blobClient.UploadAsync(stream, overwrite: true);
return Results.Ok(new
{
FileName = file.FileName,
BlobName = blobName,
Size = file.Length,
UploadedAt = DateTime.UtcNow
});
});
// List files endpoint
app.MapGet("/api/files", async (BlobServiceClient blobServiceClient) =>
{
var containerClient = blobServiceClient.GetBlobContainerClient("uploads");
if (!await containerClient.ExistsAsync())
{
return Results.Ok(Array.Empty<object>());
}
var blobs = new List<object>();
await foreach (var blob in containerClient.GetBlobsAsync())
{
blobs.Add(new
{
Name = blob.Name,
Size = blob.Properties.ContentLength,
CreatedOn = blob.Properties.CreatedOn
});
}
return Results.Ok(blobs);
});
đ Example: Aspire Blob Storage Project¶
The Forge platform includes a complete example at foundry/dotnet/aspire-blobstorage/:
Project Structure¶
aspire-blobstorage/
âââ src/
â âââ blobstorage.AppHost/ # Aspire orchestration
â â âââ AppHost.cs # Service configuration
â â âââ Extensions.cs # Aspire extensions
â âââ blobstorage/ # API backend
â â âââ [API endpoints]
â âââ blobstorage.Frontend/ # React frontend
â â âââ [UI components]
â âââ blobstorage.TypeSpec/ # OpenAPI definitions
âââ README.md
Running the Example¶
cd foundry/dotnet/aspire-blobstorage
# Start with Aspire orchestration
dotnet run --project src/blobstorage.AppHost
# Dashboard available at: http://localhost:15000
The dashboard shows:
- đī¸ Storage Account (Emulator)
- đĻ Blob Containers
- đ Service interactions
- đ Resource metrics
đ Configuration Checklist¶
-
Infrastructure
-
Set
enable_blob_storage = truein feature flags - Define container names in
containerslist - Obtain contributor group object ID
- Apply Terraform configuration
-
Verify storage account created in Azure
-
Application
-
Add
builder.AddAzureBlobServiceClient("blobstorage")to Program.cs - Implement blob upload/download endpoints using
BlobServiceClient -
Test with RBAC authentication
-
Local Development
-
Add Aspire storage emulator to AppHost with
.AddAzureStorage().RunAsEmulator().AddBlobs("blobstorage") - Reference storage in backend service with
.WithReference(storage) -
Test upload/download locally
-
Testing
- Test blob upload functionality
- Test blob download functionality
- Verify RBAC permissions in Azure
- Test with Aspire emulator locally
đ Deployment¶
Monitoring & Diagnostics¶
The storage account automatically includes:
- đ Diagnostic Settings (Azure Monitor)
- đ Metrics (requests, latency, errors)
- đ Activity Logs (operations audit trail)
- đ Storage Analytics (capacity and transaction metrics)
đ Related Resources¶
- Azure Blob Storage Documentation
- Aspire Storage Integration
- Azure Identity & RBAC
- Example: aspire-blobstorage
â FAQ¶
Q: Can I use connection strings instead of RBAC?
A: Yes, but RBAC is recommended for production. Connection strings are best for local development with the storage emulator.
Q: How do I add more containers after initial deployment?
A: Update the containers list in the feature flags and reapply Terraform.
Q: What happens if a container name is invalid?
A: Terraform validation will fail with a helpful error message. Container names must be 3-63 characters, lowercase, and contain only alphanumeric characters and hyphens.
Q: Can I access storage from multiple services?
A: Yes, multiple services can reference the same storage account. Just ensure they all have appropriate RBAC roles assigned.
Q: How do I monitor blob storage usage?
A: Use Azure Portal's Storage Account monitoring, Azure Monitor dashboards, or configure custom alerts on metrics like capacity and transaction count.