Skip to content

Add Bitwarden Secrets Manager hosting and client integrations - #1329

Merged
aaronpowell merged 99 commits into
CommunityToolkit:mainfrom
sliekens:bitwarden-secret-manager-integration
Jun 23, 2026
Merged

aaronpowell merged 99 commits into
CommunityToolkit:mainfrom
sliekens:bitwarden-secret-manager-integration

Conversation

@sliekens

@sliekens sliekens commented May 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add Bitwarden Secrets Manager hosting and client integrations for Aspire.

This targets Bitwarden Secrets Manager, the application and machine secret management product, rather than the Bitwarden Password Manager end-user vault. The AppHost can now provision and manage a Bitwarden project as a first-class resource, with managed secret definitions attached to it. It can also pass structured configuration to consuming services and adopt existing Bitwarden projects or secrets when needed.

Why

This removes the need for ad hoc Bitwarden bootstrap scripts and manual client wiring by letting the AppHost provision a Bitwarden project and its managed secrets and pass structured configuration to consuming services. It also supports adopting existing Bitwarden projects or secrets when a greenfield setup is not appropriate.

What changed

  • Add a non-container AppHost resource for provisioning and managing a Bitwarden project, with managed secret definitions attached to it.
  • Add a companion client integration that registers authenticated Bitwarden clients for consuming services.
  • Support adopting existing Bitwarden projects or secrets when a greenfield setup is not appropriate.
  • Add sample usage, unit tests, and the necessary solution, documentation, and CI wiring for the new integrations.

Design note

This follows a similar shape to Azure Key Vault in Aspire: the AppHost models Bitwarden Secrets Manager as an external managed secret store rather than as a local containerized dependency. Bitwarden Secrets Manager can be self-hosted, but doing so requires an enterprise server license, so a local self-hosted setup is not a practical default for many development teams.

Validation

  • dotnet build
  • dotnet test tests/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.Tests/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.Tests.csproj --no-build
  • dotnet test tests/CommunityToolkit.Aspire.Bitwarden.SecretManager.Tests/CommunityToolkit.Aspire.Bitwarden.SecretManager.Tests.csproj --no-build

Hosting-side tests currently use a fake provider rather than a live Bitwarden tenant.

I manually tested this against a real Bitwarden instance using the example project included in this pull request.

Planning Docs

The original planning documents I gave to my agent:

You might notice there were some iterations on the original plan, so the PLAN document doesn't accurately reflect the current state of this pull request.

The final architecture is documented in ARCHITECTURE.md and has been expanded and kept up-to-date while iterating on the original design.

@github-actions

github-actions Bot commented May 19, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1329

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1329"

@sliekens sliekens changed the title Add Bitwarden Secrets Manager integrations Add Bitwarden Secrets Manager hosting and client integrations May 19, 2026
@sliekens
sliekens marked this pull request as ready for review May 19, 2026 23:15
Copilot AI review requested due to automatic review settings May 19, 2026 23:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds new Aspire Community Toolkit integrations for Bitwarden Secrets Manager: a hosting-side resource that reconciles a Bitwarden project + managed secrets during AppHost startup, and a client-side integration that registers authenticated BitwardenClient instances from structured Aspire configuration.

Changes:

  • Introduces BitwardenSecretManagerResource + reconciler/state store to provision/adopt projects and create/adopt/update secrets, and to publish manifest + structured configuration via WithReference(...).
  • Adds a client integration (AddBitwardenSecretManagerClient / keyed variant) with settings binding, validation, and optional health checks.
  • Adds tests, documentation, CI wiring, and a runnable example AppHost + consumer service.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.Tests/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.Tests.csproj Adds hosting integration test project.
tests/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.Tests/BitwardenSecretManagerReconcilerTests.cs Tests reconciler behavior (create/adopt/update project + secrets) using a fake provider.
tests/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.Tests/BitwardenSecretManagerBuilderTests.cs Tests builder/resource model behavior and WithReference environment injection.
tests/CommunityToolkit.Aspire.Bitwarden.SecretManager.Tests/CommunityToolkit.Aspire.Bitwarden.SecretManager.Tests.csproj Adds client integration test project.
tests/CommunityToolkit.Aspire.Bitwarden.SecretManager.Tests/BitwardenSecretManagerClientPublicApiTests.cs Verifies client extension methods validate inputs.
tests/CommunityToolkit.Aspire.Bitwarden.SecretManager.Tests/AspireBitwardenSecretManagerExtensionsTests.cs Tests client settings binding + health check registration behavior.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/README.md Documents hosting integration usage and configuration.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.csproj Adds hosting package project + dependencies.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/BitwardenSecretResource.cs Adds managed secret resource type and value/expression behavior.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/BitwardenSecretReference.cs Adds public secret reference interface + internal reference implementation.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/BitwardenSecretManagerResource.cs Implements the Bitwarden project resource model and reference/env var support.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/BitwardenSecretManagerReconciler.cs Implements startup reconciliation + state persistence + provider abstraction.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/BitwardenSecretManagerExtensions.cs Adds AppHost builder extensions, manifest publishing, and initialization wiring.
src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/AssemblyInfo.cs Exposes internals to hosting tests.
src/CommunityToolkit.Aspire.Bitwarden.SecretManager/README.md Documents client integration configuration and usage.
src/CommunityToolkit.Aspire.Bitwarden.SecretManager/CommunityToolkit.Aspire.Bitwarden.SecretManager.csproj Adds client package project + dependencies.
src/CommunityToolkit.Aspire.Bitwarden.SecretManager/BitwardenSecretManagerHealthCheck.cs Adds health check implementation for the client integration.
src/CommunityToolkit.Aspire.Bitwarden.SecretManager/BitwardenSecretManagerClientSettings.cs Adds settings POCO for client configuration.
src/CommunityToolkit.Aspire.Bitwarden.SecretManager/AspireBitwardenSecretManagerExtensions.cs Adds client registration extensions (keyed + unkeyed), binding, validation, and health checks.
README.md Adds integration entries + NuGet/doc links for Bitwarden Secrets Manager.
examples/bitwarden-secret-manager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.AppHost/Properties/launchSettings.json Adds example AppHost launch profiles.
examples/bitwarden-secret-manager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.AppHost/Program.cs Adds example AppHost using the hosting integration + passing config to a consumer.
examples/bitwarden-secret-manager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.AppHost/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.AppHost.csproj Adds example AppHost project.
examples/bitwarden-secret-manager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.AppHost/aspire.config.json Adds aspire config pointing to the AppHost project.
examples/bitwarden-secret-manager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.ApiService/Properties/launchSettings.json Adds example consumer service launch profiles.
examples/bitwarden-secret-manager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.ApiService/Program.cs Adds example consumer service using the client integration.
examples/bitwarden-secret-manager/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.ApiService/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager.ApiService.csproj Adds example consumer service project.
Directory.Packages.props Adds Bitwarden.Secrets.Sdk package version.
CommunityToolkit.Aspire.slnx Adds new src/tests projects and example projects to the solution.
.github/workflows/tests.yaml Wires new hosting + client test projects into CI.
Comments suppressed due to low confidence (2)

src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/BitwardenSecretManagerExtensions.cs:127

  • This overload also dereferences projectName.Resource without validating projectName for null, which can lead to NullReferenceException for invalid caller input. Add ArgumentNullException.ThrowIfNull(projectName); to match the validation used for other IResourceBuilder<> parameters.
    public static IResourceBuilder<BitwardenSecretManagerResource> AddBitwardenSecretManager(
        this IDistributedApplicationBuilder builder,
        [ResourceName] string name,
        IResourceBuilder<ParameterResource> projectName,
        IResourceBuilder<ParameterResource> organizationId,
        IResourceBuilder<ParameterResource> accessToken)
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentException.ThrowIfNullOrWhiteSpace(name);
        ArgumentNullException.ThrowIfNull(organizationId);
        ArgumentNullException.ThrowIfNull(accessToken);

        return AddBitwardenSecretManagerCore(
            builder,
            name,
            ConfiguredStringValue.FromParameter(projectName.Resource),
            ConfiguredGuidValue.FromParameter(organizationId.Resource),
            accessToken);

src/CommunityToolkit.Aspire.Hosting.Bitwarden.SecretManager/BitwardenSecretManagerExtensions.cs:275

  • This AddSecret overload (ReferenceExpression) also doesn't validate builder for null before using it, which can produce NullReferenceException for invalid caller input. Add ArgumentNullException.ThrowIfNull(builder); to align with the rest of the public API surface.
    /// <summary>
    /// Adds a managed Bitwarden secret whose local and remote names are the same.
    /// </summary>
    /// <param name="builder">The parent Bitwarden resource builder.</param>
    /// <param name="name">The Aspire resource name and Bitwarden secret name.</param>
    /// <param name="value">The secret value expression.</param>
    /// <returns>The managed secret resource builder.</returns>
    public static IResourceBuilder<BitwardenSecretResource> AddSecret(
        this IResourceBuilder<BitwardenSecretManagerResource> builder,
        [ResourceName] string name,
        ReferenceExpression value)
    {
        ArgumentNullException.ThrowIfNull(value);
        return builder.AddSecret(name, name, value);
    }

@sliekens
sliekens marked this pull request as draft May 20, 2026 18:21
@sliekens
sliekens marked this pull request as ready for review May 20, 2026 19:39
@sliekens
sliekens marked this pull request as draft May 21, 2026 21:46
@sliekens
sliekens marked this pull request as ready for review May 21, 2026 22:50
@sliekens
sliekens marked this pull request as draft May 22, 2026 20:55
@sliekens

Copy link
Copy Markdown
Contributor Author

Back in draft, I'm not happy with the (lack of a real) deployment model.
New plan: rewrite secret provisioning as pipeline steps instead of in InitializeAsync.

@davidfowl

Copy link
Copy Markdown
Contributor

master class

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants