File tree Expand file tree Collapse file tree
Shared/ConduitLLM.Core/Utilities Expand file tree Collapse file tree Original file line number Diff line number Diff line change 55using ConduitLLM . Configuration . Extensions ;
66using ConduitLLM . Core . Converters ;
77using ConduitLLM . Core . Extensions ;
8+ using ConduitLLM . Core . Utilities ;
89using ConduitLLM . Providers . Extensions ;
910
1011using MassTransit ; // Added for event bus infrastructure
@@ -351,14 +352,13 @@ public static async Task Main(string[] args)
351352 Predicate = check => check . Tags . Contains ( "ready" ) || check . Tags . Count == 0
352353 } ) ;
353354
354- // Map Prometheus metrics endpoint - requires authentication
355+ // Map Prometheus metrics endpoint
356+ // Allow unauthenticated access from private networks (Docker internal, localhost)
357+ // Require authentication for external/public network requests
355358 app . UseOpenTelemetryPrometheusScrapingEndpoint (
356- context => context . Request . Path == "/metrics" &&
357- ( context . User . Identity ? . IsAuthenticated ?? false )
358- ) ;
359-
360- // Alternative: Map metrics endpoint without authentication (for monitoring systems)
361- // app.UseOpenTelemetryPrometheusScrapingEndpoint();
359+ context => context . Request . Path == "/metrics" &&
360+ ( IpAddressHelper . IsPrivateNetworkRequest ( context ) ||
361+ context . User . Identity ? . IsAuthenticated == true ) ) ;
362362
363363 // For the prometheus-net library metrics
364364 app . UseHttpMetrics ( options =>
Original file line number Diff line number Diff line change 11using System . Text . Json ;
2+ using ConduitLLM . Core . Utilities ;
23
34public partial class Program
45{
@@ -85,8 +86,13 @@ public static void ConfigureEndpoints(WebApplication app)
8586 } ) ;
8687
8788 // Map Prometheus metrics endpoint for scraping
88- app . UseOpenTelemetryPrometheusScrapingEndpoint ( "/metrics" ) ;
89- Console . WriteLine ( "[Gateway API] Prometheus metrics endpoint registered at /metrics" ) ;
89+ // Allow unauthenticated access from private networks (Docker internal, localhost)
90+ // Require authentication for external/public network requests
91+ app . UseOpenTelemetryPrometheusScrapingEndpoint (
92+ context => context . Request . Path == "/metrics" &&
93+ ( IpAddressHelper . IsPrivateNetworkRequest ( context ) ||
94+ context . User . Identity ? . IsAuthenticated == true ) ) ;
95+ Console . WriteLine ( "[Gateway API] Prometheus metrics endpoint registered at /metrics (private network or authenticated)" ) ;
9096
9197 Console . WriteLine ( "[Gateway API] All API endpoints are now handled by controllers." ) ;
9298 }
Original file line number Diff line number Diff line change @@ -363,6 +363,29 @@ public static string GetClientIpAddress(Microsoft.AspNetCore.Http.HttpContext co
363363
364364 #endregion
365365
366+ #region Private Network Request Detection
367+
368+ /// <summary>
369+ /// Checks if an HTTP request originates from a private/internal network.
370+ /// Useful for allowing internal monitoring tools (e.g., Prometheus) to access
371+ /// endpoints without authentication while still requiring auth for external requests.
372+ /// </summary>
373+ /// <param name="context">The HTTP context.</param>
374+ /// <returns>True if the request comes from a private network, false otherwise.</returns>
375+ public static bool IsPrivateNetworkRequest ( Microsoft . AspNetCore . Http . HttpContext context )
376+ {
377+ // For internal Docker network requests, we check the direct connection IP
378+ // rather than forwarded headers (which could be spoofed from external sources)
379+ var remoteIp = context . Connection . RemoteIpAddress ;
380+
381+ if ( remoteIp == null )
382+ return false ;
383+
384+ return IsPrivateIp ( remoteIp ) ;
385+ }
386+
387+ #endregion
388+
366389 #region Address Family Detection
367390
368391 /// <summary>
You can’t perform that action at this time.
0 commit comments