Skip to content

Conversation

@Blind-Striker
Copy link
Contributor

@Blind-Striker Blind-Striker commented Sep 30, 2025

What does this PR do?

This PR fixes the critical issue where AWS Lambda functions with SQS Event Sources fail to connect to LocalStack, throwing "Invalid URI" errors. The fix automatically injects the AWS_ENDPOINT_URL environment variable into SQS Event Source resources, enabling the AWS Lambda Tools to properly connect to LocalStack's SQS service.

Additionally, this PR includes a complete testing playground with an analytics-driven architecture to validate the fix in a real-world scenario.

Related Issue(s):

🔄 Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🧹 Code cleanup/refactoring
  • ⚡ Performance improvement
  • 🧪 Test improvements

🎯 Aspire Compatibility

  • Compatible with .NET Aspire 9.x (tested with 9.5.0)
  • Supports both .NET 8.0 and .NET 9.0
  • Follows Aspire.Hosting.AWS patterns
  • Works with existing AWS integrations

🧪 Testing

How has this been tested?

  • Unit tests added/updated
    • Added ConfigureSqsEventSourceResource tests
    • Updated mock tests to work with WithEnvironment() pattern
    • 208 unit tests passing
  • Integration tests added/updated
    • Complete analytics playground with 3 Lambda functions
    • SQS Event Source triggering Analyzer Lambda
    • End-to-end event flow testing
  • Manual testing with playground examples
    • URL creation triggers analytics events
    • URL redirect triggers analytics events
    • Analyzer Lambda processes events from SQS
  • Tested with LocalStack container
  • Tested across multiple .NET versions
  • Tested auto-configure (UseLocalStack())
  • Tested manual configuration (WithReference()) - Not applicable for this fix

Test Environment:

  • LocalStack Version: 4.x
  • .NET Aspire Version: 9.5.0
  • .NET Versions Tested: 8.0, 9.0
  • Operating Systems: Windows

📚 Documentation

  • Code is self-documenting with clear naming
  • XML documentation comments added/updated
  • README.md updated (if needed)
    • Updated playground/lambda/README.md with analytics architecture
    • Updated playground/README.md with SQS mention
  • Playground examples updated (if needed)
    • Added LocalStack.Lambda.Analyzer project
    • Enhanced UrlShortener and Redirector with analytics
  • Breaking changes documented - N/A (no breaking changes)

✅ Code Quality Checklist

  • Code follows project coding standards
  • No new analyzer warnings introduced
  • All tests pass locally (208 tests passing)
  • No merge conflicts
  • Branch is up to date with target branch
  • Commit messages follow Conventional Commits

🔍 Additional Notes

Breaking Changes:
None. This is a backward-compatible fix that enhances existing functionality.

Performance Impact:
Minimal. The fix only adds environment variable injection during resource configuration (one-time setup cost). No runtime performance impact.

Dependencies:

  • Updated to .NET Aspire 9.5.0
  • Added AWSSDK.SQS to Redirector and UrlShortener Lambda projects (for analytics testing)

🎯 Reviewer Focus Areas

Please pay special attention to:

  • Security implications
    • Environment variable injection is safe and scoped to SQS Event Source resources only
    • No credentials or sensitive data exposed
  • Performance impact
    • Configuration-time only, no runtime overhead
  • Breaking changes
    • None
  • Test coverage
    • Comprehensive unit tests for the fix
    • Real-world integration testing via analytics playground
  • Documentation completeness
    • Architecture diagrams updated
    • CLI testing examples added
    • Request flow documented
  • Aspire integration patterns
    • Follows WithEnvironment() extension pattern
    • Consistent with Aspire resource configuration
  • LocalStack compatibility
    • Tested with LocalStack 3.x
    • Works with SQS, DynamoDB, S3, Lambda emulators

🏗️ Architecture Overview

The Problem

When using WithSQSEventSource() with LocalStack, the AWS Lambda Tools process tries to parse the LocalStack URL (http://localhost.localstack.cloud:4566) as an AWS region, causing an "Invalid URI" error.

The Solution

Automatically inject AWS_ENDPOINT_URL environment variable into SQS Event Source resources, instructing Lambda Tools to use the LocalStack endpoint instead of AWS.

Implementation Details

1. Detection (LocalStackResourceConfigurator.cs)

private const string SQSEventSourceResource = "Aspire.Hosting.AWS.SQS.SQSEventSourceResource";

// Detect SQS Event Source resources
if (string.Equals(resource.Resource.GetType().FullName,
    Constants.SQSEventSourceResource,
    StringComparison.Ordinal))
{
    ConfigureSqsEventSourceResource(resource, localStackUrl);
}

2. Configuration (Simplified Approach)

internal static void ConfigureSqsEventSourceResource(
    IResourceBuilder<ExecutableResource> builder,
    Uri localStackUrl)
{
    builder.WithEnvironment(context =>
    {
        context.EnvironmentVariables["AWS_ENDPOINT_URL"] = localStackUrl.ToString();
    });
}

3. Validation (ConstantsTests.cs)

  • Added AWS assembly validation to detect breaking changes
  • Ensures SQSEventSourceResource type exists in Aspire.Hosting.AWS

Analytics Testing Playground

New Resources:

  • Analyzer Lambda: Processes SQS events and writes to DynamoDB
  • Analytics Queue: SQS queue receiving events from UrlShortener/Redirector
  • Analytics Table: DynamoDB table storing analytics data

Event Flow:

POST /shorten → UrlShortener → url_created event → SQS → Analyzer → DynamoDB
GET /{slug}   → Redirector   → url_accessed event → SQS → Analyzer → DynamoDB

📸 Screenshots/Examples

Using the Analytics Flow

# 1. Create a short URL
curl -d '{"url":"https://aws.amazon.com","format":"qr"}' \
     -H "Content-Type: application/json" \
     -X POST {GATEWAY_BASE_URL}/shorten
# Response: { "id":"abc123", "qrUrl":"..." }

# 2. Access the short URL (triggers redirect + analytics)
curl -I {GATEWAY_BASE_URL}/abc123
# Response: 302 Found → https://aws.amazon.com

# 3. Check analytics in DynamoDB
aws dynamodb scan \
    --table-name UrlAnalytics \
    --endpoint-url <localstack_address> \
    --region eu-central-1
# Shows both url_created and url_accessed events

Code Example in AppHost

var builder = DistributedApplication.CreateBuilder(args);

// LocalStack with auto-configuration
var localstack = builder.AddLocalStack("localstack");

// CDK Stack with SQS Queue
var urlShortenerStack = builder.AddAWSCDKStack("UrlShortenerStack")
    .WithReference(localstack);

// Lambda with SQS Event Source (now works with LocalStack!)
var analyzer = builder.AddAWSLambdaFunction("analyzer")
    .WithReference(localstack)
    .WithSQSEventSource(urlShortenerStack.GetOutput("AnalyticsQueueUrl"));

builder.Build().Run();

🎯 Validation Criteria


By submitting this pull request, I confirm that:

  • I have read and agree to the project's Code of Conduct
  • I understand that this contribution may be subject to the .NET Foundation CLA
  • My contribution is licensed under the same terms as the project (MIT License)

Note

Detects SQS Event Source resources and injects AWS_ENDPOINT_URL for LocalStack, adds an end-to-end analytics playground (SQS+DynamoDB) and updates versions/CI to Aspire 9.5 with SemVer2 artifacts.

  • Core (Aspire.Hosting.LocalStack)
    • Detects SQSEventSourceResource and injects AWS_ENDPOINT_URL to route SDK calls to LocalStack.
    • Extends UseLocalStack/connection callback to handle ExecutableResource SQS event sources; adds Constants.SQSEventSourceResource.
    • Bumps package version to 9.5.0.
  • Playground (Lambda analytics)
    • Adds LocalStack.Lambda.Analyzer (SQS-triggered) and wires SQS event source in AppHost.
    • Extends CDK stack with AnalyticsQueue (SQS) and UrlAnalytics (DynamoDB) outputs.
    • Updates UrlShortener/Redirector to emit analytics to SQS; analyzer persists to DynamoDB.
    • Solution updates and README docs reflecting new analytics flow and CLI.
  • CI/CD
    • Switches package versioning to NuGet SemVer 2 pre-release format and standardizes artifact suffixes/names in summaries.
  • Dependencies
    • Upgrades to Aspire 9.5.0 and refreshes AWS/OpenTelemetry/SkiaSharp/xUnit analyzer versions.
  • Tests
    • Adds unit tests for SQS event source detection/configuration and AWS type presence; includes test package refs.
  • Misc
    • Timestamp format in provisioning handler changed to ISO-8601.

Written by Cursor Bugbot for commit 4915669. This will update automatically on new commits. Configure here.

Add SQSEventSourceResource detection in UseLocalStack()
Implement ConfigureSqsEventSourceResource() with surgical annotation insertion
Add AWS_ENDPOINT_URL environment variable injection for Lambda Tools
Enhance ConstantsTests with AWS class validation for breaking change detection
Add comprehensive unit tests for new SQS Event Source configuration

Resolves issue #6 - Invalid URL error when Lambda with SQS event source uses LocalStack endpoint

BREAKING: This fix requires playground validation before release completion
TODO: Test with Lambda playground to validate the fix effectiveness
…mplementation

Add comprehensive SQS Event Source testing with analytics flow:
- Add Analyzer Lambda to process SQS events (url_created, url_accessed)
- Add AnalyticsQueue (SQS) and UrlAnalytics (DynamoDB) to CDK stack
- Update UrlShortener and Redirector Lambdas to send analytics events
- Demonstrate complete event-driven architecture with LocalStack

Simplify SQS Event Source configuration:
- Replace surgical annotation insertion with WithEnvironment() extension
- Remove complex annotation ordering logic (not needed with Aspire's append behavior)
- Update unit tests to properly mock WithAnnotation() callbacks

Update documentation:
- Add analytics flow architecture diagram to lambda README
- Update resource inventory (3 Lambdas, SQS, analytics table)
- Add CLI commands for testing analytics functionality
- Highlight SQS Event Source demonstration

This validates the fix from commit c0005ad and provides a real-world
test case for the AWS_ENDPOINT_URL environment variable injection.

Closes #6
@Blind-Striker Blind-Striker self-assigned this Sep 30, 2025
@github-actions
Copy link

github-actions bot commented Sep 30, 2025

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
nuget/AWSSDK.Core >= 0 🟢 5.9
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
Code-Review⚠️ 1Found 3/30 approved changesets -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Fuzzing⚠️ 0project is not fuzzed
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Vulnerabilities🟢 100 existing vulnerabilities detected
SAST🟢 10SAST tool is run on all commits
Binary-Artifacts🟢 6binaries present in source code
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
nuget/AWSSDK.DynamoDBv2 >= 0 🟢 5.9
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
Code-Review⚠️ 1Found 3/30 approved changesets -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Fuzzing⚠️ 0project is not fuzzed
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Vulnerabilities🟢 100 existing vulnerabilities detected
SAST🟢 10SAST tool is run on all commits
Binary-Artifacts🟢 6binaries present in source code
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
nuget/Amazon.Lambda.Core >= 0 🟢 6.1
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 5 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
Code-Review🟢 8Found 18/22 approved changesets -- score normalized to 8
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Security-Policy🟢 10security policy file detected
Vulnerabilities🟢 100 existing vulnerabilities detected
Binary-Artifacts⚠️ 0binaries present in source code
SAST🟢 10SAST tool is run on all commits
Pinned-Dependencies⚠️ 1dependency not pinned by hash detected -- score normalized to 1
nuget/Amazon.Lambda.SQSEvents >= 0 🟢 6.1
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 5 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
Code-Review🟢 8Found 18/22 approved changesets -- score normalized to 8
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Security-Policy🟢 10security policy file detected
Vulnerabilities🟢 100 existing vulnerabilities detected
Binary-Artifacts⚠️ 0binaries present in source code
SAST🟢 10SAST tool is run on all commits
Pinned-Dependencies⚠️ 1dependency not pinned by hash detected -- score normalized to 1
nuget/Amazon.Lambda.Serialization.SystemTextJson >= 0 🟢 6.1
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 5 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
Code-Review🟢 8Found 18/22 approved changesets -- score normalized to 8
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Security-Policy🟢 10security policy file detected
Vulnerabilities🟢 100 existing vulnerabilities detected
Binary-Artifacts⚠️ 0binaries present in source code
SAST🟢 10SAST tool is run on all commits
Pinned-Dependencies⚠️ 1dependency not pinned by hash detected -- score normalized to 1
nuget/LocalStack.Client >= 0 UnknownUnknown
nuget/LocalStack.Client.Extensions >= 0 UnknownUnknown
nuget/AWSSDK.SQS >= 0 🟢 5.9
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
Code-Review⚠️ 1Found 3/30 approved changesets -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Fuzzing⚠️ 0project is not fuzzed
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Vulnerabilities🟢 100 existing vulnerabilities detected
SAST🟢 10SAST tool is run on all commits
Binary-Artifacts🟢 6binaries present in source code
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
nuget/AWSSDK.SQS >= 0 🟢 5.9
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
Code-Review⚠️ 1Found 3/30 approved changesets -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Fuzzing⚠️ 0project is not fuzzed
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Vulnerabilities🟢 100 existing vulnerabilities detected
SAST🟢 10SAST tool is run on all commits
Binary-Artifacts🟢 6binaries present in source code
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0

Scanned Files

  • playground/lambda/LocalStack.Lambda.Analyzer/LocalStack.Lambda.Analyzer.csproj
  • playground/lambda/LocalStack.Lambda.Redirector/LocalStack.Lambda.Redirector.csproj
  • playground/lambda/LocalStack.Lambda.UrlShortener/LocalStack.Lambda.UrlShortener.csproj

Copy link

Copilot AI left a comment

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 a critical issue where AWS Lambda functions with SQS Event Sources fail to connect to LocalStack due to "Invalid URI" errors. The fix automatically injects the AWS_ENDPOINT_URL environment variable into SQS Event Source resources. Additionally, it includes a comprehensive analytics testing playground with event-driven architecture to validate the fix.

  • Fixes SQS Event Source LocalStack integration by adding environment variable injection
  • Updates test coverage with new unit tests for the SQS configuration logic
  • Adds complete analytics playground with 3 Lambda functions demonstrating real-world SQS Event Source usage

Reviewed Changes

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

Show a summary per file
File Description
src/Aspire.Hosting.LocalStack/Internal/Constants.cs Adds constant for SQS Event Source resource type name
src/Aspire.Hosting.LocalStack/Internal/LocalStackResourceConfigurator.cs Implements SQS Event Source configuration method
src/Aspire.Hosting.LocalStack/Internal/LocalStackConnectionStringAvailableCallback.cs Adds SQS Event Source detection and configuration logic
src/Aspire.Hosting.LocalStack/LocalStackResourceBuilderExtensions.cs Adds SQS Event Source resource detection in UseLocalStack method
tests/Aspire.Hosting.LocalStack.Unit.Tests/Internal/LocalStackResourceConfiguratorTests.cs Comprehensive unit tests for SQS Event Source configuration
tests/Aspire.Hosting.LocalStack.Unit.Tests/Internal/ConstantsTests.cs Validation tests for AWS assembly type existence
playground/lambda/* Complete analytics playground demonstrating SQS Event Source functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

cursor[bot]

This comment was marked as outdated.

…ests

Replace type reference hack with Assembly.Load("Aspire.Hosting.AWS") to
ensure assembly loads consistently across all platforms and configurations.

Fixes test failures on Linux/macOS where AWS types were not found in
Release builds due to compiler optimizations.
Fix artifact name containing invalid forward slash character that caused
upload failures. Introduce ARTIFACT_SUFFIX variable using sanitized branch
name for artifact naming.

Enforce NuGet Semantic Versioning 2.0.0 compliance for all CI builds:
- Feature branches: 9.5.0-feature-name.buildnumber
- Master CI builds: 9.5.0-ci.buildnumber (explicit pre-release marker)

The -ci prefix ensures all automated builds are marked as pre-release,
while stable releases remain controlled via manual workflow dispatch.

Changes:
- Use SAFE_BRANCH for artifact names instead of raw github.head_ref
- Add explicit -ci suffix for master builds (was 4-part version)
- Export artifact_suffix as step output for reuse
- Update build summary to show artifact name and SemVer compliance

Fixes GitHub Actions artifact upload error:
"The artifact name is not valid: packages-feature/full-release-preparations-29.
Contains the following character: Forward slash /"
Sanitize user input before logging to prevent log injection attacks in
Redirector and UrlShortener Lambda functions.
Add ITestOutputHelper integration with xUnit logging and verify analytics
resources (SQS queue + DynamoDB table) from PR #9.

Phase 1 of integration testing improvements:
- Configure structured logging with MartinCostello.Logging.XUnit.v3
- Verify AnalyticsQueueUrl and AnalyticsTableName outputs
- Add SQS and DynamoDB resource existence checks
- Improve test diagnostics with better assertions
- Clean up commented code

Created integration-tests-roadmap.md for Phase 2 (fixtures) and Phase 3 (e2e).

Tests: 2/2 passing ✅
…d test methods

BREAKING CHANGE: Deleted monolithic integration test files in favor of structured approach

- Replace 2 monolithic test files with 4 focused test classes using IClassFixture<T>
- Create LocalStackLambdaFixture and LocalStackCdkFixture for shared AppHost instances
- Extract common test helpers to LocalStackTestHelpers (CloudFormation outputs, session creation)
- Split large test methods into 12 focused, individual test methods (6 Lambda + 6 CDK)
- Dynamically extract AWS region from LocalStack resource configuration (no hardcoding)
- Move CloudFormationStackOutputs to dedicated file for better organization
- Mark legacy CdkTestCollection as obsolete

Benefits:
- Better test isolation and clarity
- Faster test execution (shared AppHost per collection)
- Easier debugging with focused test methods
- Dynamic region configuration prevents configuration drift

Deleted:
- tests/.../Playground/Lambda/LocalStackLambdaHostTests.cs
- tests/.../Playground/Provisioning/LocalStackCDKHostTests.cs

Relates-to: #6
- Remove flaky SQS message verification test
- Simplify HttpClient handler initialization to avoid linter warnings
- Adjust Analyzer Lambda test with manual JSON serialization
- Reduce wait time in analytics processing test (10s → 1s)
- Remove unused SQS imports

The SQS-only verification test was removed as it depends on LocalStack
emulator features that aren't fully supported in test scenarios. Core
functional tests (URL shortening, QR codes, redirects) remain passing.

Refs: Phase 3 integration test improvements
- Adjusted the wait time in the analytics processing test from 1 second to 10 seconds to ensure reliable event processing by the Analyzer Lambda.

This change addresses potential timing issues in the test, improving the accuracy of the analytics verification.
Add AWS credential environment variables to SQSEventSourceResource to prevent
AWS SDK from attempting SSO token refresh when connecting to LocalStack.

The AWS Lambda Test Tool's SQS Event Source background service requires valid
AWS credentials before making API calls. On Linux systems with AWS SSO profiles,
the SDK would attempt to refresh SSO tokens from real AWS endpoints, causing
the Lambda emulator to crash before reaching LocalStack.

By explicitly setting AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN,
and AWS_DEFAULT_REGION from LocalStack's session options, we force the SDK to use
basic authentication and skip SSO/IAM role credential chain resolution.

Changes:
- Set AWS credential env vars in ConfigureSqsEventSourceResource
- Use ILocalStackOptions.Session credentials for consistency
- Ensures cross-platform compatibility (Windows, macOS, Linux)

This completes the SQS Event Source LocalStack integration and resolves
authentication failures in CI environments.

Fixes: #6
Tested: WSL Linux, Windows, macOS
cursor[bot]

This comment was marked as outdated.

Updated the HTTP client timeout from 30 seconds to 60 seconds in multiple Lambda functional tests to accommodate longer cold start times. This change aims to enhance test reliability and prevent timeouts during integration testing with LocalStack.

Changes:
- Increased timeout for API Gateway client and redirect client in various test methods.

This adjustment addresses potential timing issues and improves the overall stability of the tests.
…configuration

Changes:
- Replaced options.Session.AwsSessionToken with options.Session.AwsAccessKey for AWS_SECRET_ACCESS_KEY.
@Blind-Striker Blind-Striker requested a review from Copilot October 3, 2025 06:55
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 41 out of 41 changed files in this pull request and generated 4 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +157 to +172
var mockExecutableResource = new ExecutableResource("test-sqs-resource", "test-command", "test-workdir");
var (options, _, _) = TestDataBuilders.CreateMockLocalStackOptions(
localStackHost: "test-host",
edgePort: 9999,
useSsl: false);
var mockBuilder = Substitute.For<IResourceBuilder<ExecutableResource>>();
mockBuilder.Resource.Returns(mockExecutableResource);

// Configure the mock to actually add annotations when WithAnnotation is called
mockBuilder.WithAnnotation(Arg.Do<EnvironmentCallbackAnnotation>(ann => mockExecutableResource.Annotations.Add(ann)), Arg.Any<ResourceAnnotationMutationBehavior>())
.Returns(mockBuilder);

var localStackUrl = new Uri("http://localhost:4566");

// Act
LocalStackResourceConfigurator.ConfigureSqsEventSourceResource(mockBuilder, localStackUrl, options);
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

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

The test setup pattern for mocking WithAnnotation is duplicated across multiple test methods. Consider extracting this common setup into a helper method to reduce code duplication and improve maintainability.

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +12
var awsAssembly = Assembly.Load("Aspire.Hosting.AWS");
_ = awsAssembly; // Suppress unused warning
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

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

The assembly loading in the constructor could fail with FileNotFoundException if the AWS assembly is not available, causing all tests in this class to fail during construction. Consider wrapping this in a try-catch block or moving it to a static constructor with proper error handling.

Suggested change
var awsAssembly = Assembly.Load("Aspire.Hosting.AWS");
_ = awsAssembly; // Suppress unused warning
try
{
var awsAssembly = Assembly.Load("Aspire.Hosting.AWS");
_ = awsAssembly; // Suppress unused warning
}
catch (System.IO.FileNotFoundException)
{
// AWS assembly not found. Tests that require it may fail or should handle this case.
}
catch (System.IO.FileLoadException)
{
// AWS assembly could not be loaded. Tests that require it may fail or should handle this case.
}
catch (BadImageFormatException)
{
// AWS assembly is not a valid assembly. Tests that require it may fail or should handle this case.
}

Copilot uses AI. Check for mistakes.
catch (Exception ex)
{
// Log but don't throw - analytics shouldn't break URL creation
lambdaContext.Logger.LogWarning($"Failed to send analytics event: {ex.Message}");
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

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

Logging the exception message directly could potentially expose sensitive information. Consider logging a sanitized message or using structured logging with appropriate filtering for production environments.

Suggested change
lambdaContext.Logger.LogWarning($"Failed to send analytics event: {ex.Message}");
lambdaContext.Logger.LogWarning("Failed to send analytics event.");

Copilot uses AI. Check for mistakes.
catch (Exception ex)
{
// Log but don't throw - analytics shouldn't break redirects
lambdaContext.Logger.LogWarning($"Failed to send analytics event: {ex.Message}");
Copy link

Copilot AI Oct 3, 2025

Choose a reason for hiding this comment

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

Same security concern as in UrlShortener - logging exception messages directly could expose sensitive information. Consider using structured logging or sanitizing the message.

Suggested change
lambdaContext.Logger.LogWarning($"Failed to send analytics event: {ex.Message}");
lambdaContext.Logger.LogWarning($"Failed to send analytics event for slug '{slug}'. Exception type: {ex.GetType().Name}");

Copilot uses AI. Check for mistakes.
@Blind-Striker Blind-Striker merged commit 44f4cdb into master Oct 3, 2025
12 checks passed
@Blind-Striker Blind-Striker mentioned this pull request Oct 3, 2025
39 tasks
Blind-Striker added a commit that referenced this pull request Oct 4, 2025
- Replace Gist-based badge system with BadgeSmith REST API
- Implement HMAC-SHA256 authentication for secure badge updates
- Add branch-specific badge support (master and feature branches)
- Update CI/CD workflow to post test results via authenticated API
- Refactor update-test-badge action to extract owner/repo/branch from context
- Update README badges to use new BadgeSmith endpoints
- Add Windows and macOS test badges to README
- Remove Release Candidate status and warnings
- Add comprehensive v9.5.0 CHANGELOG entry
- Document SQS Event Source bug fix (#6, #9)
- Document eager service loading feature (#7, #8)
- Update LocalStack container to 4.9.1
- Update Aspire.Hosting to 9.5.0
- Credit contributors: @slang25 (eager loading), @Blind-Striker (bug fixes, infra)
@Blind-Striker Blind-Striker mentioned this pull request Oct 4, 2025
36 tasks
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.

Invalid URL error when Lambda with SQS event source uses LocalStack endpoint in .NET Aspire

2 participants