Initial commit: scadaproj umbrella — sister-project index, auth component normalization (design + GAPS), and the built ZB.MOM.WW.Auth shared library (0.1.0, flattened in).
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.Auth.Abstractions.Ldap;
|
||||
|
||||
namespace ZB.MOM.WW.Auth.Ldap;
|
||||
|
||||
/// <summary>
|
||||
/// Validates <see cref="LdapOptions"/> at startup so a misconfiguration fails fast at
|
||||
/// boot with a clear, field-naming message — rather than surfacing later as an opaque
|
||||
/// low-level error on the first real login attempt.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Four conditions are enforced:
|
||||
/// <list type="bullet">
|
||||
/// <item>plaintext transport (<see cref="LdapTransport.None"/>) is rejected unless
|
||||
/// <see cref="LdapOptions.AllowInsecure"/> is explicitly set (dev/test only);</item>
|
||||
/// <item><see cref="LdapOptions.Server"/> must be specified (no sane default host);</item>
|
||||
/// <item><see cref="LdapOptions.SearchBase"/> must be specified (the DN root every
|
||||
/// search runs against);</item>
|
||||
/// <item><see cref="LdapOptions.ServiceAccountDn"/> must be specified — an empty value
|
||||
/// would bind anonymously, defeating the search-then-bind authentication flow.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public sealed class LdapOptionsValidator : IValidateOptions<LdapOptions>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ValidateOptionsResult Validate(string? name, LdapOptions options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
if (options.Transport == LdapTransport.None && !options.AllowInsecure)
|
||||
{
|
||||
return ValidateOptionsResult.Fail(
|
||||
$"{nameof(LdapOptions.Transport)} is {nameof(LdapTransport.None)} (insecure/plaintext) " +
|
||||
$"but {nameof(LdapOptions.AllowInsecure)} is false. Enable TLS " +
|
||||
$"({nameof(LdapTransport.Ldaps)} or {nameof(LdapTransport.StartTls)}) " +
|
||||
$"or set {nameof(LdapOptions.AllowInsecure)} for dev/test.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(options.Server))
|
||||
{
|
||||
return ValidateOptionsResult.Fail(
|
||||
$"{nameof(LdapOptions.Server)} is required but was empty or whitespace — " +
|
||||
"set it to the LDAP server hostname or IP (e.g. \"ldap.example.com\").");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(options.SearchBase))
|
||||
{
|
||||
return ValidateOptionsResult.Fail(
|
||||
$"{nameof(LdapOptions.SearchBase)} is required but was empty or whitespace — " +
|
||||
"set it to the search-base DN (e.g. \"dc=example,dc=com\").");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(options.ServiceAccountDn))
|
||||
{
|
||||
return ValidateOptionsResult.Fail(
|
||||
$"{nameof(LdapOptions.ServiceAccountDn)} is required but was empty or whitespace — " +
|
||||
"an empty value would bind anonymously. Set it to the service-account DN " +
|
||||
"(e.g. \"cn=svc,dc=example,dc=com\").");
|
||||
}
|
||||
|
||||
return ValidateOptionsResult.Success;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user