sln build fix (again), tests fixes, audit work and doctors work
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
using System.Globalization;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using StellaOps.Doctor.Models;
|
||||
using StellaOps.Doctor.Plugins;
|
||||
|
||||
namespace StellaOps.Doctor.Plugins.Integration.Checks;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies connectivity to LDAP/Active Directory servers.
|
||||
/// </summary>
|
||||
public sealed class LdapConnectivityCheck : IDoctorCheck
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string CheckId => "check.integration.ldap";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "LDAP/AD Connectivity";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Verifies connectivity to LDAP or Active Directory servers";
|
||||
|
||||
/// <inheritdoc />
|
||||
public DoctorSeverity DefaultSeverity => DoctorSeverity.Warn;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<string> Tags => ["connectivity", "ldap", "directory", "auth"];
|
||||
|
||||
/// <inheritdoc />
|
||||
public TimeSpan EstimatedDuration => TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanRun(DoctorPluginContext context)
|
||||
{
|
||||
var host = context.Configuration.GetValue<string>("Ldap:Host")
|
||||
?? context.Configuration.GetValue<string>("ActiveDirectory:Host")
|
||||
?? context.Configuration.GetValue<string>("Authority:Ldap:Host");
|
||||
return !string.IsNullOrWhiteSpace(host);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DoctorCheckResult> RunAsync(DoctorPluginContext context, CancellationToken ct)
|
||||
{
|
||||
var result = context.CreateResult(CheckId, "stellaops.doctor.integration", DoctorCategory.Integration.ToString());
|
||||
|
||||
var host = context.Configuration.GetValue<string>("Ldap:Host")
|
||||
?? context.Configuration.GetValue<string>("ActiveDirectory:Host")
|
||||
?? context.Configuration.GetValue<string>("Authority:Ldap:Host");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(host))
|
||||
{
|
||||
return result
|
||||
.Skip("LDAP not configured")
|
||||
.WithEvidence("Configuration", e => e.Add("Ldap:Host", "(not set)"))
|
||||
.Build();
|
||||
}
|
||||
|
||||
var port = context.Configuration.GetValue<int?>("Ldap:Port")
|
||||
?? context.Configuration.GetValue<int?>("ActiveDirectory:Port")
|
||||
?? context.Configuration.GetValue<int?>("Authority:Ldap:Port")
|
||||
?? 389;
|
||||
|
||||
var useSsl = context.Configuration.GetValue<bool?>("Ldap:UseSsl")
|
||||
?? context.Configuration.GetValue<bool?>("ActiveDirectory:UseSsl")
|
||||
?? false;
|
||||
|
||||
if (useSsl && port == 389)
|
||||
{
|
||||
port = 636;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var client = new TcpClient();
|
||||
var connectTask = client.ConnectAsync(host, port, ct);
|
||||
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5), ct);
|
||||
|
||||
var completedTask = await Task.WhenAny(connectTask.AsTask(), timeoutTask);
|
||||
|
||||
if (completedTask == timeoutTask)
|
||||
{
|
||||
return result
|
||||
.Fail($"Connection to LDAP server at {host}:{port} timed out")
|
||||
.WithEvidence("LDAP connectivity", e =>
|
||||
{
|
||||
e.Add("Host", host);
|
||||
e.Add("Port", port.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("UseSsl", useSsl.ToString());
|
||||
e.Add("Status", "timeout");
|
||||
})
|
||||
.WithCauses(
|
||||
"LDAP server is not responding",
|
||||
"Firewall blocking LDAP port",
|
||||
"Network connectivity issues")
|
||||
.WithRemediation(r => r
|
||||
.AddManualStep(1, "Check LDAP server", "Verify LDAP server is running and accessible")
|
||||
.AddManualStep(2, "Test connectivity", $"telnet {host} {port}"))
|
||||
.WithVerification("stella doctor --check check.integration.ldap")
|
||||
.Build();
|
||||
}
|
||||
|
||||
await connectTask;
|
||||
|
||||
if (client.Connected)
|
||||
{
|
||||
return result
|
||||
.Pass($"LDAP server reachable at {host}:{port}")
|
||||
.WithEvidence("LDAP connectivity", e =>
|
||||
{
|
||||
e.Add("Host", host);
|
||||
e.Add("Port", port.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("UseSsl", useSsl.ToString());
|
||||
e.Add("Status", "connected");
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
|
||||
return result
|
||||
.Fail($"Failed to connect to LDAP server at {host}:{port}")
|
||||
.WithEvidence("LDAP connectivity", e =>
|
||||
{
|
||||
e.Add("Host", host);
|
||||
e.Add("Port", port.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("Status", "connection_failed");
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
return result
|
||||
.Fail($"Socket error connecting to LDAP: {ex.Message}")
|
||||
.WithEvidence("LDAP connectivity", e =>
|
||||
{
|
||||
e.Add("Host", host);
|
||||
e.Add("Port", port.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("SocketErrorCode", ex.SocketErrorCode.ToString());
|
||||
e.Add("Error", ex.Message);
|
||||
})
|
||||
.WithCauses(
|
||||
"LDAP server is not running",
|
||||
"DNS resolution failed",
|
||||
"Network unreachable")
|
||||
.WithRemediation(r => r
|
||||
.AddManualStep(1, "Check LDAP configuration", "Verify Ldap:Host and Ldap:Port settings")
|
||||
.AddManualStep(2, "Check DNS", $"nslookup {host}"))
|
||||
.WithVerification("stella doctor --check check.integration.ldap")
|
||||
.Build();
|
||||
}
|
||||
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||
{
|
||||
return result
|
||||
.Fail($"Error connecting to LDAP: {ex.Message}")
|
||||
.WithEvidence("LDAP connectivity", e =>
|
||||
{
|
||||
e.Add("Host", host);
|
||||
e.Add("Port", port.ToString(CultureInfo.InvariantCulture));
|
||||
e.Add("ErrorType", ex.GetType().Name);
|
||||
e.Add("Error", ex.Message);
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user