using OTSSignsOrchestrator.Server.Clients; using OTSSignsOrchestrator.Server.Data.Entities; namespace OTSSignsOrchestrator.Server.Health.Checks; /// /// Verifies the per-instance SAML provider in Authentik is active by checking /// the provider exists using the stored . /// public sealed class AuthentikSamlProviderHealthCheck : IHealthCheck { private readonly IAuthentikClient _authentikClient; private readonly ILogger _logger; public string CheckName => "AuthentikSamlProvider"; public bool AutoRemediate => false; public AuthentikSamlProviderHealthCheck( IAuthentikClient authentikClient, ILogger logger) { _authentikClient = authentikClient; _logger = logger; } public async Task RunAsync(Instance instance, CancellationToken ct) { if (string.IsNullOrEmpty(instance.AuthentikProviderId)) { return new HealthCheckResult(HealthStatus.Degraded, "No Authentik provider ID stored — SAML not provisioned"); } if (!int.TryParse(instance.AuthentikProviderId, out var providerId)) { return new HealthCheckResult(HealthStatus.Critical, $"Invalid Authentik provider ID: {instance.AuthentikProviderId}"); } try { var response = await _authentikClient.GetSamlProviderAsync(providerId); if (response.IsSuccessStatusCode && response.Content is not null) { return new HealthCheckResult(HealthStatus.Healthy, $"SAML provider {providerId} is active in Authentik"); } return new HealthCheckResult(HealthStatus.Critical, $"SAML provider {providerId} not found or inaccessible", response.Error?.Content); } catch (Exception ex) { return new HealthCheckResult(HealthStatus.Critical, $"Failed to check SAML provider: {ex.Message}"); } } }