mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 04:32:32 +00:00
a20ff48ae6
- Add JWT-based authentication to all API endpoints - Implement tenant isolation and access control validation - Add Galactic Admin role validation for cross-tenant endpoints - Enhance certificate validation with full X.509 chain checking - Add certificate validation cache (5-min TTL) and self-signed cert protection - Implement NDJSON payload size limit protection (configurable per tenant) - Replace placeholder audit user identifiers with actual JWT user principals - Add TenantHelper utility for consistent tenant/user extraction from tokens - Disable PII logging in production (ShowPII = false) Agent: - Add automatic tenant ID detection from Windows Registry (AAD Join enrollment) - Implement tenant ID precedence: CLI argument > Registry > Fallback SignalR: - Add authentication checks to all SignalR functions - Implement tenant-based group access control - Add user identifier logging for SignalR operations Frontend: - Change MSAL cache from localStorage to sessionStorage (XSS protection) - Add warning status support to health check page - Add Admin Configuration link in navbar (Galactic Admin only) - Move maintenance trigger from Settings to Admin Configuration page - Update tenant context logging for clarity Configuration: - Add MaxNdjsonPayloadSizeMB setting to TenantConfiguration model - Update configuration service to persist new retention/timeout settings
111 lines
4.4 KiB
C#
111 lines
4.4 KiB
C#
using System.Net;
|
|
using AutopilotMonitor.Functions.Extensions;
|
|
using AutopilotMonitor.Functions.Helpers;
|
|
using AutopilotMonitor.Functions.Services;
|
|
using Microsoft.Azure.Functions.Worker;
|
|
using Microsoft.Azure.Functions.Worker.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace AutopilotMonitor.Functions.Functions
|
|
{
|
|
public class HealthCheckFunction
|
|
{
|
|
private readonly ILogger<HealthCheckFunction> _logger;
|
|
private readonly HealthCheckService _healthCheckService;
|
|
private readonly GalacticAdminService _galacticAdminService;
|
|
|
|
public HealthCheckFunction(
|
|
ILogger<HealthCheckFunction> logger,
|
|
HealthCheckService healthCheckService,
|
|
GalacticAdminService galacticAdminService)
|
|
{
|
|
_logger = logger;
|
|
_healthCheckService = healthCheckService;
|
|
_galacticAdminService = galacticAdminService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// GET /api/health
|
|
/// Basic health check endpoint (anonymous access)
|
|
/// </summary>
|
|
[Function("HealthCheck")]
|
|
public async Task<HttpResponseData> Run(
|
|
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")] HttpRequestData req)
|
|
{
|
|
_logger.LogInformation("Basic health check requested");
|
|
|
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
|
await response.WriteAsJsonAsync(new
|
|
{
|
|
status = "healthy",
|
|
service = "Autopilot Monitor API",
|
|
version = "1.0.0-phase1",
|
|
timestamp = DateTime.UtcNow
|
|
});
|
|
|
|
return response;
|
|
}
|
|
|
|
/// <summary>
|
|
/// GET /api/health/detailed
|
|
/// Detailed health check with comprehensive system checks (Galactic Admin only)
|
|
/// </summary>
|
|
[Function("DetailedHealthCheck")]
|
|
public async Task<HttpResponseData> GetDetailedHealthCheck(
|
|
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health/detailed")] HttpRequestData req,
|
|
FunctionContext context)
|
|
{
|
|
_logger.LogInformation("Detailed health check requested");
|
|
|
|
// Validate authentication
|
|
var httpContext = req.FunctionContext.GetHttpContext();
|
|
if (httpContext?.User?.Identity?.IsAuthenticated != true)
|
|
{
|
|
_logger.LogWarning("Unauthenticated detailed health check attempt");
|
|
var unauthorizedResponse = req.CreateResponse(HttpStatusCode.Unauthorized);
|
|
await unauthorizedResponse.WriteAsJsonAsync(new
|
|
{
|
|
success = false,
|
|
message = "Authentication required. Please provide a valid JWT token."
|
|
});
|
|
return unauthorizedResponse;
|
|
}
|
|
|
|
// Check if user is Galactic Admin via GalacticAdminService (Azure Table Storage)
|
|
var userEmail = TenantHelper.GetUserIdentifier(req);
|
|
var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userEmail);
|
|
|
|
if (!isGalacticAdmin)
|
|
{
|
|
_logger.LogWarning($"Non-Galactic Admin user {userEmail} attempted to access detailed health check");
|
|
var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden);
|
|
await forbiddenResponse.WriteAsJsonAsync(new
|
|
{
|
|
success = false,
|
|
message = "Access denied. Galactic Admin role required."
|
|
});
|
|
return forbiddenResponse;
|
|
}
|
|
|
|
_logger.LogInformation($"Detailed health check accessed by Galactic Admin: {userEmail}");
|
|
|
|
// Perform comprehensive health checks
|
|
var healthCheckResult = await _healthCheckService.PerformAllChecksAsync();
|
|
|
|
// Always return 200 OK with the health status in the body
|
|
// This allows the frontend to properly display the results even if some checks fail
|
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
|
await response.WriteAsJsonAsync(new
|
|
{
|
|
service = "Autopilot Monitor API",
|
|
version = "1.0.0-phase1",
|
|
timestamp = healthCheckResult.Timestamp,
|
|
overallStatus = healthCheckResult.OverallStatus,
|
|
checks = healthCheckResult.Checks
|
|
});
|
|
|
|
return response;
|
|
}
|
|
}
|
|
}
|