120 lines
4.0 KiB
C#
120 lines
4.0 KiB
C#
using ZB.MOM.WW.Auth.Abstractions.Ldap;
|
|
using ZB.MOM.WW.Auth.Ldap;
|
|
|
|
namespace ZB.MOM.WW.Auth.Ldap.Tests;
|
|
|
|
public class LdapOptionsValidatorTests
|
|
{
|
|
private static LdapOptions Opts() => new()
|
|
{
|
|
Enabled = true,
|
|
Server = "x",
|
|
Transport = LdapTransport.None,
|
|
AllowInsecure = true,
|
|
SearchBase = "dc=x",
|
|
ServiceAccountDn = "cn=svc,dc=x",
|
|
};
|
|
|
|
[Fact]
|
|
public void Validator_Fails_PlainTransport_WhenNotAllowInsecure() =>
|
|
Assert.True(new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { Transport = LdapTransport.None, AllowInsecure = false })
|
|
.Failed);
|
|
|
|
[Fact]
|
|
public void Validator_Fails_WhenServerEmpty() =>
|
|
Assert.True(new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { Server = " " })
|
|
.Failed);
|
|
|
|
[Fact]
|
|
public void Validator_Fails_WhenSearchBaseEmpty() =>
|
|
Assert.True(new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { SearchBase = "" })
|
|
.Failed);
|
|
|
|
[Fact]
|
|
public void Validator_FailureMessage_NamesOffendingField()
|
|
{
|
|
var result = new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { Server = "" });
|
|
|
|
Assert.True(result.Failed);
|
|
Assert.Contains(nameof(LdapOptions.Server), result.FailureMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public void Validator_Fails_WhenServiceAccountDnEmpty()
|
|
{
|
|
// I5: an empty ServiceAccountDn risks an anonymous bind, so it must be rejected
|
|
// and the failure message must name the offending key.
|
|
var result = new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { ServiceAccountDn = " " });
|
|
|
|
Assert.True(result.Failed);
|
|
Assert.Contains(nameof(LdapOptions.ServiceAccountDn), result.FailureMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public void Validator_Succeeds_OnValidSecureConfig() =>
|
|
Assert.False(new LdapOptionsValidator()
|
|
.Validate(null, Opts() with
|
|
{
|
|
Transport = LdapTransport.Ldaps,
|
|
AllowInsecure = false,
|
|
Server = "s",
|
|
SearchBase = "dc=x",
|
|
})
|
|
.Failed);
|
|
|
|
[Fact]
|
|
public void Validator_Succeeds_OnInsecureWhenAllowed() =>
|
|
Assert.False(new LdapOptionsValidator()
|
|
.Validate(null, Opts())
|
|
.Failed);
|
|
|
|
[Fact]
|
|
public void Validator_Skips_AllChecks_WhenDisabled() =>
|
|
// When LDAP is disabled its connection fields are inert; an otherwise-invalid
|
|
// config (plaintext + blank Server/SearchBase/ServiceAccountDn) must still pass.
|
|
Assert.False(new LdapOptionsValidator()
|
|
.Validate(null, new LdapOptions
|
|
{
|
|
Enabled = false,
|
|
Transport = LdapTransport.None,
|
|
AllowInsecure = false,
|
|
Server = "",
|
|
SearchBase = "",
|
|
ServiceAccountDn = "",
|
|
})
|
|
.Failed);
|
|
|
|
[Fact]
|
|
public void Validator_Succeeds_WithValidFallbackServers() =>
|
|
Assert.False(new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { FallbackServers = new[] { "dc2", "dc3:3894" } })
|
|
.Failed);
|
|
|
|
[Theory]
|
|
[InlineData("")]
|
|
[InlineData(":636")]
|
|
[InlineData("dc2:0")]
|
|
[InlineData("dc2:notaport")]
|
|
public void Validator_Fails_OnMalformedFallbackServer(string entry)
|
|
{
|
|
var result = new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { FallbackServers = new[] { entry } });
|
|
|
|
Assert.True(result.Failed);
|
|
Assert.Contains(nameof(LdapOptions.FallbackServers), result.FailureMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public void Validator_Skips_FallbackServers_WhenDisabled() =>
|
|
// Same inert-when-disabled rule as every other connection field: a disabled
|
|
// provider never opens a connection, so its fallback list is never walked.
|
|
Assert.False(new LdapOptionsValidator()
|
|
.Validate(null, Opts() with { Enabled = false, FallbackServers = new[] { ":::" } })
|
|
.Failed);
|
|
}
|