Postbode is an operational management tool for Azure Service Bus, built with .NET Blazor Server. It provides advanced authorization through Azure Entra ID and focuses exclusively on message management — infrastructure provisioning (queues, topics, subscriptions) is intentionally left to Infrastructure as Code (Bicep).
Unlike tools such as Service Bus Explorer, Postbode offers fine-grained authorization at different levels, ensuring effective permission management. It operates entirely within Azure.
Ideally, no messages should end up in the dead-letter queue of a service bus. However, in reality, this can happen due to factors outside your team's control. Postbode surfaces the dead-letter reason and description for each message, and can deep-link to Azure Application Insights — by correlation ID or message ID — so you can trace what happened end-to-end. From there you can delete the message, resubmit it, or send a new one.
- Overview of all queues, topics, and subscriptions
- Status monitoring of queues, topics, and subscriptions
- Peek and inspect messages on queues and topics
- Send new messages to queues and topics
- Delete messages from queues
- Dead-letter queue management (inspect, resubmit, delete) with reason and description
- Deep-link from messages to Application Insights for end-to-end tracing (optional, requires configuration)
- Background processing for long-running operations
- Audit logging of all user message actions
- Authorization through Azure Entra ID
- Fully operates on Azure
Postbode follows Clean Architecture with four layers:
┌──────────────────────────────────────────┐
│ WebApp (Blazor Server + BackgroundService)│
├──────────────────────────────────────────┤
│ Application (Interfaces / Contracts) │
├──────────────────────────────────────────┤
│ Core / Domain (Models, Value Types) │
├──────────────────────────────────────────┤
│ Infrastructure (Azure Service Bus, Audit)│
└──────────────────────────────────────────┘
- WebApp: Blazor Server application with interactive server-side rendering and a background service for long-running tasks
- Application: Pure interface layer — service contracts, adapter contracts, factory contracts
- Core/Domain: Domain models (Queue, Topic, Subscription, WorkerItem), value types, and enums
- Infrastructure: Azure Service Bus adapter/service implementations, audit logging, worker service
| Component | Technology |
|---|---|
| Framework | .NET 10.0 / C# latest |
| UI | Blazor Server (Interactive Server) |
| Authentication | Microsoft Entra ID (OpenID Connect) |
| Token Flow | On-Behalf-Of (user delegation) + Managed Identity (service account) |
| Service Bus | Azure.Messaging.ServiceBus SDK |
| Telemetry | Application Insights |
| IaC | Bicep |
| CI/CD | GitHub Actions |
- .NET 10 SDK (or .NET 8+ with
rollForward: latestMajor) - Azure Subscription
- Azure Service Bus namespace
- Azure Entra ID (app registration)
- Azure Service Principal
- Azure Application Insights (optional)
# Build the solution
dotnet build
# Run the web application
dotnet run --project src/Droomploeg.Postbode.WebApp
# Run with Aspire orchestration (development)
dotnet run --project src/Droomploeg.Postbode.AppHost
# Run tests
dotnet testThe application requires the following settings in appsettings.json:
{
"AzureEntra": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "<domain>.onmicrosoft.com",
"TenantId": "<TenantId>",
"ClientId": "<ClientId>",
"ClientSecret": "<ClientSecret>",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath": "/signout-oidc"
},
"AzureServiceBusConnections": [
{
"Name": "<ConnectionName>",
"FullyQualifiedNamespace": "<namespace>.servicebus.windows.net"
}
],
"ManagedIdentityClientId": "<ManagedIdentityClientId>",
"ApplicationInsights": {
"ConnectionString": "<ConnectionString>"
}
}For this manual, a demo application name is used. You can change it as needed. The demo application name is "PostbodeDemo01".
- Open Azure Entra ID
- Go to Applications > App registrations
- Select New registration
- Fill in the form (this is where the demo name is set: "PostbodeDemo01")
- After creation, go to the app registration and set the Authentication:
- Select Add URI and fill in the redirect URIs:
- Localhost:
https://localhost:7273/signin-oidc - Azure:
https://postbodedemo01.azurewebsites.net/signin-oidc
- Localhost:
- Select checkbox ID tokens (used for implicit and hybrid flows)
- Press Save
- Select Add URI and fill in the redirect URIs:
- Go to Certificates & Secrets:
- Select tab Client secrets and create a secret (this will be the
ClientSecretin appsettings)
- Select tab Client secrets and create a secret (this will be the
- Go to API permissions and grant:
Microsoft.Graph>User.Read(Delegated)Microsoft.ServiceBus>user_impersonation(Delegated)
- Go to App roles and create a role:
- Display name:
General_Access - Allowed member types: Users/Groups
- Value:
General_Access - Description:
General access for Postbode - Check Do you want to enable this app role?
- Press Apply
- Display name:
- Open Azure Entra ID
- Go to Applications > Enterprise applications
- Select your application
- Select Users and Groups to manage access
- Select Add user/group, choose a User/Group and the Role
- Press Assign
Contributions are welcome! Please read CONTRIBUTING.md for the contribution process and CODE_OF_CONDUCT.md for community standards. By submitting a pull request, you agree to the Contributor License Agreement.
For security-related issues, please follow the process described in SECURITY.md — do not open a public issue.
This project is licensed under AGPL-3.0. See CLA.md for the Contributor License Agreement.
Postbode is provided "AS IS", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or its use. See sections 15 and 16 of the AGPL-3.0 license for the full disclaimer.