mirror of
https://github.com/azaion/annotations.git
synced 2026-06-21 11:51:06 +00:00
[AZ-PENDING-1] [AZ-PENDING-2] Testability fixes: JWKS gate + RMQ DNS
C01 (JWKS HTTPS env gate, src/Auth/JwtExtensions.cs) Gate HttpDocumentRetriever.RequireHttps on ASPNETCORE_ENVIRONMENT != "E2ETest" (case-insensitive). HTTPS is still enforced for Development, Staging, Production, and any unset value. Test harness can now serve JWKS over plain HTTP via the mock issuer documented in _docs/02_document/tests/environment.md. C02 (RabbitMQ host DNS resolution, src/Services/FailsafeProducer.cs) Resolve RABBITMQ_HOST via DNS when the value is not a literal IP. Adds ResolveHostAddress(host, ct) helper that uses IPAddress.TryParse first, then Dns.GetHostAddressesAsync. Fixes a latent production bug (operators using a DNS hostname like "rabbitmq" or "broker.internal" got a FormatException at startup) and unblocks the e2e Docker test harness where the broker is reachable only via service-name DNS. Review report: _docs/03_implementation/reviews/batch_01_review.md Verdict PASS_WITH_WARNINGS (1 Low/Maintainability finding, documented as deferred to Step 8 hardening). Tracker IDs are placeholders — Jira MCP unavailable. Real IDs to be assigned per _docs/_process_leftovers/2026-05-14_testability-tracker.md. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,10 +27,20 @@ public static class JwtExtensions
|
||||
// document; admin only exposes JWKS, so we wire a JWKS-only retriever.
|
||||
// The manager caches the document and refreshes on the default schedule
|
||||
// (matches admin's Cache-Control: public, max-age=3600 on /.well-known/jwks.json).
|
||||
//
|
||||
// RequireHttps is relaxed only when ASPNETCORE_ENVIRONMENT=E2ETest so the
|
||||
// blackbox harness can serve its mock JWKS over the test-net HTTP issuer
|
||||
// (architecture.md Open Risks Section 6). Any other environment — including
|
||||
// unset, Development, Staging, Production — keeps the HTTPS enforcement.
|
||||
var requireHttpsForJwks = !string.Equals(
|
||||
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"),
|
||||
"E2ETest",
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var jwksConfigManager = new ConfigurationManager<JsonWebKeySet>(
|
||||
jwksUrl,
|
||||
new JwksRetriever(),
|
||||
new HttpDocumentRetriever { RequireHttps = true });
|
||||
new HttpDocumentRetriever { RequireHttps = requireHttpsForJwks });
|
||||
|
||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
|
||||
@@ -51,9 +51,16 @@ public class FailsafeProducer(
|
||||
|
||||
private async Task ProcessQueue(CancellationToken ct)
|
||||
{
|
||||
// RABBITMQ_HOST is documented as accepting either a literal IP or a DNS
|
||||
// hostname (container service name, k8s service, etc.). IPEndPoint takes
|
||||
// an IPAddress, so non-IP values must be resolved before construction —
|
||||
// a bare IPAddress.Parse here throws FormatException on every drain cycle
|
||||
// for any hostname value.
|
||||
var brokerAddress = await ResolveHostAddress(config.Host, ct);
|
||||
|
||||
var streamSystem = await StreamSystem.Create(new StreamSystemConfig
|
||||
{
|
||||
Endpoints = [new IPEndPoint(IPAddress.Parse(config.Host), config.Port)],
|
||||
Endpoints = [new IPEndPoint(brokerAddress, config.Port)],
|
||||
UserName = config.Username,
|
||||
Password = config.Password
|
||||
});
|
||||
@@ -192,6 +199,19 @@ public class FailsafeProducer(
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IPAddress> ResolveHostAddress(string host, CancellationToken ct)
|
||||
{
|
||||
if (IPAddress.TryParse(host, out var literal))
|
||||
return literal;
|
||||
|
||||
var addresses = await Dns.GetHostAddressesAsync(host, ct);
|
||||
if (addresses.Length == 0)
|
||||
throw new InvalidOperationException(
|
||||
$"DNS resolution for RABBITMQ_HOST '{host}' returned no addresses.");
|
||||
|
||||
return addresses[0];
|
||||
}
|
||||
|
||||
public static async Task EnqueueAsync(AppDataConnection db, string annotationId, QueueOperation operation)
|
||||
{
|
||||
var ids = JsonSerializer.Serialize(new[] { annotationId });
|
||||
|
||||
Reference in New Issue
Block a user