Skip to content

Aspire Configuration Example

Demonstrates Aspire publish-time configuration generation for security and infrastructure settings.

📋 Overview

This example shows how to:

  • Define security permissions and business roles in C# code
  • Configure upstream API dependencies with required permissions
  • Generate YAML configuration files during aspire publish

🏗️ Architecture

flowchart TB
    subgraph AppHost["AspireConfig.AppHost"]
        direction TB
        Auth["Auth/<br/>Permissions.cs<br/>BusinessRoles.cs"]
        Config["AppHost.cs<br/>AddSaifEnvironment()"]
    end

    subgraph Resources["Resource Model"]
        SaifEnv["SaifEnvironmentResource"]
        Security["SecurityResource<br/>(child)"]
        Upstream["UpstreamApiResource"]
        SaifEnv --> Security
    end

    subgraph Publish["aspire publish"]
        Generator["SecurityResource<br/>Pipeline Step"]
    end

    subgraph Output["Generated YAML"]
        API["infra/api/config.yml"]
        Corp["infra/auth/corp/config.yml"]
        ExtUser["infra/auth/ext/user/<br/>business-role-app-role.yml"]
        ExtApp["infra/auth/ext/app/<br/>authorized-apps.yml"]
    end

    AppHost --> Resources
    Security --> Generator
    Upstream --> Generator
    Generator --> Output

🧩 Components

File Description
Auth/Permissions.cs Defines app roles and scopes
Auth/BusinessRoles.cs Groups permissions into business roles
AppHost.cs Configures security for publish

🔑 Key Features

  • Composite Resource Pattern - SaifEnvironmentResource aggregates child resources like SecurityResource
  • Compile-Time Safety - Invalid configurations fail at build time
  • IntelliSense Support - Discover permissions and roles while coding
  • Type-Safe Permissions - AppRole vs Scope enforced by compiler
  • Dual Identity Support - Corporate (Entra) and external (Okta) users

📂 Project Structure

foundry/dotnet/aspire-config/
├── AspireConfig.sln
├── src/
│   ├── AspireConfig.AppHost/
│   │   ├── Auth/
│   │   │   ├── Permissions.cs        # App roles and scopes
│   │   │   └── BusinessRoles.cs      # Business role definitions
│   │   ├── AppHost.cs                # Security configuration
│   │   └── ResourceBuilders/         # Generated API builder
│   ├── AspireConfig/                 # API project
│   ├── AspireConfig.UnitTests/
│   └── AspireConfig.IntegrationTests/
└── infra/                            # Infrastructure config

🚀 Getting Started

Prerequisites

  • .NET 10.0 SDK
  • Aspire 13.x

Running the Example

cd foundry/dotnet/aspire-config
dotnet run --project src/AspireConfig.AppHost

Publishing Configuration

To generate the security YAML files:

dotnet run --project src/AspireConfig.AppHost -- publish

📝 Code Walkthrough

1. Define Permissions

// Auth/Permissions.cs
public static class Permissions
{
    // App roles exposed by this API
    public static readonly AppRole ClaimsRead = new("Claims.Read", "Read Claims");
    public static readonly AppRole ClaimsWrite = new("Claims.Write", "Write Claims");

    // Scopes for upstream API calls
    public static readonly Scope OrdersRead = new("Orders.Read", "Read Orders");
}

2. Define Business Roles

// Auth/BusinessRoles.cs
public static class BusinessRoles
{
    public static readonly BusinessRole ClaimsAdjuster = new("Claims Adjuster");
    public static readonly BusinessRole InjuredWorker = new("Injured Worker");
}

3. Define App Role Assignments

// Auth/AppRoleAssignments.cs
public static class AppRoleAssignments
{
    public static readonly AppRoleAssignment ClaimsAdjuster = new(
        BusinessRoles.ClaimsAdjuster,
        [Permissions.ClaimsRead, Permissions.ClaimsWrite]);

    public static readonly AppRoleAssignment InjuredWorker = new(
        BusinessRoles.InjuredWorker,
        [Permissions.ClaimsRead]);
}

4. Configure in AppHost

// AppHost.cs
builder.AddSecurity()
    .WithCorporateAssignment(AppRoleAssignments.ClaimsAdjuster)   // Entra users
    .WithExternalAssignment(AppRoleAssignments.InjuredWorker);    // Okta users

builder.AddUpstreamApi("it-api-proc-orders")
    .WithScope(Permissions.OrdersRead);

📄 Generated Output

infra/api/config.yml

app_roles:
  - value: Claims.Read
    display_name: Read Claims
  - value: Claims.Write
    display_name: Write Claims
scopes: []

infra/auth/corp/config.yml

business_roles:
  - name: Claims Adjuster
    app_roles:
      - Claims.Read
      - Claims.Write
authorized_apps:
  - project_id: it-api-proc-orders
    scopes:
      - Orders.Read

📍 Source Code

Location: foundry/dotnet/aspire-config/