Skip to content

Fix Redis DbGate TLS connections - #1549

Open
0mar-rivero wants to merge 3 commits into
CommunityToolkit:mainfrom
0mar-rivero:fix/redis-dbgate-tls
Open

Fix Redis DbGate TLS connections#1549
0mar-rivero wants to merge 3 commits into
CommunityToolkit:mainfrom
0mar-rivero:fix/redis-dbgate-tls

Conversation

@0mar-rivero

Copy link
Copy Markdown

**Closes #1548 **

Fixes the Redis DbGate integration by using RedisResource.UriExpression instead of manually constructing the connection URL.

The DbGate container is also configured to trust Aspire's development certificate through NODE_EXTRA_CA_CERTS.

Validation

  • Updated the environment-variable tests to inspect deferred ReferenceExpression values directly. Resolving them with GetEnvironmentVariablesAsync() before Aspire allocates the Redis endpoint caused the tests to wait indefinitely.
  • Added app-model tests for the deferred Redis URI and certificate trust configuration.
  • Added a Docker-backed integration test that:
    • Opens the configured Redis connection through DbGate.
    • Executes Redis PING.
    • Verifies the response is PONG.

PR Checklist

  • Created a feature/dev branch in your fork (vs. submitting directly from a commit on main)
  • Based off latest main branch of toolkit
  • PR doesn't include merge commits (always rebase on top of our main, if needed)
  • Tests for the changes have been added (for bug fixes / features) (if applicable)
  • Contains NO breaking changes
  • Code follows all style conventions

Other information

Adding certificate trust alone was not sufficient. The previous URL used the Redis resource name directly as the hostname, while Aspire’s certificate is issued for the hostname produced by its deferred endpoint expression.

The fix uses RedisResource.UriExpression, preserving Aspire’s runtime-resolved hostname, port, credentials, and TLS scheme so the hostname matches the generated certificate.

The existing tests only verified the generated environment-variable values and that the DbGate web UI responded. They did not verify that DbGate could establish and use the Redis connection. The new Docker-backed test opens the configured connection through DbGate, executes Redis PING, and asserts that it returns PONG.

The unit tests now inspect the deferred ReferenceExpression directly. Calling GetEnvironmentVariablesAsync() before Aspire allocates the endpoint attempts to resolve it prematurely and can wait indefinitely.

Copilot AI lite review requested due to automatic review settings August 27, 2026 07:11
@0mar-rivero
0mar-rivero requested a review from Alirexaa as a code owner August 27, 2026 07:11

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 fixes the Redis WithDbGate() integration to work reliably when Redis uses TLS by (1) sourcing the connection URL from Aspire’s deferred RedisResource.UriExpression and (2) configuring the DbGate container to trust Aspire’s development certificate.

Changes:

  • Update WithDbGate() to set DbGate’s URL_* env var from RedisResource.UriExpression and add a certificate trust configuration for DbGate.
  • Update resource-creation tests to validate the deferred ReferenceExpression rather than forcing early resolution.
  • Add a Docker-backed integration test that logs into DbGate and verifies Redis connectivity by issuing PING and asserting PONG.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/CommunityToolkit.Aspire.Hosting.Redis.Extensions/RedisBuilderExtensions.cs Switch DbGate Redis URL to UriExpression and add cert-trust configuration for Node/DbGate.
tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs Adjust tests to inspect deferred expressions and assert cert-trust annotation exists.
tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/AppHostTests.cs Add Docker integration test that exercises DbGate → Redis TLS connectivity via PING.
Suppressed comments (2)

tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/AppHostTests.cs:60

  • The refresh HTTP call should use the 5-minute linked token (cts.Token). Using TestContext.Current.CancellationToken here bypasses the CancelAfter timeout and can cause the test to hang indefinitely if DbGate stops responding.
        using var refreshResponse = await httpClient.PostAsJsonAsync(
            "/server-connections/refresh",
            new
            {
                conid = "redis1",
                keepOpen = true
            },
            cancellationToken: TestContext.Current.CancellationToken);

tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/AppHostTests.cs:72

  • The Redis PING call (and response body read) should use cts.Token so it respects the 5-minute timeout you set up for this test. Right now it uses TestContext.Current.CancellationToken, so a stuck request can outlive the intended timeout.
        using var pingResponse = await httpClient.PostAsJsonAsync(
            "/database-connections/call-method",
            new
            {
                conid = "redis1",
                database = "db0",
                method = "ping",
                args = Array.Empty<object>()
            },
            cancellationToken: TestContext.Current.CancellationToken);

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/AppHostTests.cs Outdated
@0mar-rivero

Copy link
Copy Markdown
Author

@dotnet-policy-service agree

Comment on lines +206 to +221
private static async Task<Dictionary<string, object>> GetEnvironmentVariablesAsync(
IDistributedApplicationBuilder builder,
IResource resource)
{
Assert.True(resource.TryGetAnnotationsOfType<EnvironmentCallbackAnnotation>(out var annotations));

var environmentVariables = new Dictionary<string, object>();
var context = new EnvironmentCallbackContext(builder.ExecutionContext, environmentVariables);

foreach (var annotation in annotations)
{
await annotation.Callback(context);
}

return environmentVariables;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the need for this over the original approach to getting environment variables?

@0mar-rivero 0mar-rivero Aug 28, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The original approach was deadlocking when resolving the env variables that referenced the endpoint. Probably because the endpoint was not allocated yet.

May be related to microsoft/aspire#14954

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.

Redis WithDbGate fails to connect when Redis uses TLS

3 participants