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,99 @@
|
||||
using ZB.MOM.WW.Auth.Abstractions.Ldap;
|
||||
using ZB.MOM.WW.Auth.Ldap;
|
||||
|
||||
namespace ZB.MOM.WW.Auth.Ldap.Tests;
|
||||
|
||||
public class LdapAuthServiceTests
|
||||
{
|
||||
// Sensible test defaults: insecure plaintext transport (dev/test), a service
|
||||
// account set, and DisplayNameAttribute aligned with the fake's "displayName"
|
||||
// key so display-name extraction is genuinely exercised.
|
||||
private static LdapOptions Opts() => new()
|
||||
{
|
||||
Enabled = true,
|
||||
Server = "x",
|
||||
Port = 3893,
|
||||
Transport = LdapTransport.None,
|
||||
AllowInsecure = true,
|
||||
SearchBase = "dc=x",
|
||||
ServiceAccountDn = "cn=svc,dc=x",
|
||||
ServiceAccountPassword = "svcpw",
|
||||
UserNameAttribute = "cn",
|
||||
DisplayNameAttribute = "displayName",
|
||||
GroupAttribute = "memberOf",
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public async Task Succeeds_AndReturnsStrippedGroups_OnValidCredentials()
|
||||
{
|
||||
var fake = new FakeLdapConnection().WithUserEntry(
|
||||
"cn=alice,dc=x",
|
||||
memberOf: new[] { "cn=Engineers,ou=g,dc=x", "cn=Viewers,ou=g,dc=x" },
|
||||
displayName: "Alice");
|
||||
var svc = new LdapAuthService(Opts(), new FakeLdapConnectionFactory(fake));
|
||||
|
||||
var r = await svc.AuthenticateAsync(" alice ", "pw", default);
|
||||
|
||||
Assert.True(r.Succeeded);
|
||||
Assert.Equal("alice", r.Username); // trimmed
|
||||
Assert.Equal("Alice", r.DisplayName); // from DisplayNameAttribute
|
||||
Assert.Equal(new[] { "Engineers", "Viewers" }, r.Groups); // CN= stripped
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindsServiceAccountThenUser_OnValidCredentials()
|
||||
{
|
||||
// Non-empty memberOf: fail-closed requires at least one group for success, and this
|
||||
// test asserts bind ORDER, so the user must successfully resolve and bind.
|
||||
var fake = new FakeLdapConnection().WithUserEntry(
|
||||
"cn=alice,dc=x", memberOf: new[] { "cn=Engineers,ou=g,dc=x" }, displayName: "Alice");
|
||||
var svc = new LdapAuthService(Opts(), new FakeLdapConnectionFactory(fake));
|
||||
|
||||
await svc.AuthenticateAsync("alice", "pw", default);
|
||||
|
||||
// Service account first, user DN second (bind-then-search-then-bind).
|
||||
Assert.Equal(new[] { "cn=svc,dc=x", "cn=alice,dc=x" }, fake.BoundDns);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FallsBackToUsername_WhenNoDisplayName()
|
||||
{
|
||||
// Non-empty memberOf so fail-closed lets success through; this test only asserts the
|
||||
// display-name fallback (no displayName attribute -> username).
|
||||
var fake = new FakeLdapConnection().WithUserEntry(
|
||||
"cn=bob,dc=x", memberOf: new[] { "cn=Viewers,ou=g,dc=x" });
|
||||
var svc = new LdapAuthService(Opts(), new FakeLdapConnectionFactory(fake));
|
||||
|
||||
var r = await svc.AuthenticateAsync("bob", "pw", default);
|
||||
|
||||
Assert.True(r.Succeeded);
|
||||
Assert.Equal("bob", r.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Fails_Disabled_WhenNotEnabled()
|
||||
{
|
||||
var svc = new LdapAuthService(
|
||||
Opts() with { Enabled = false },
|
||||
new FakeLdapConnectionFactory(new FakeLdapConnection()));
|
||||
|
||||
Assert.Equal(LdapAuthFailure.Disabled, (await svc.AuthenticateAsync("a", "b", default)).Failure);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PreservesEscapedCommaInGroupName_OnRfc4514Dn()
|
||||
{
|
||||
// C1: a group CN that legitimately contains a comma (escaped per RFC 4514)
|
||||
// must be returned intact, not truncated at the escaped comma.
|
||||
var fake = new FakeLdapConnection().WithUserEntry(
|
||||
"cn=alice,dc=x",
|
||||
memberOf: new[] { @"cn=Eng\,ineers,ou=g,dc=x", @"cn=A\2cB,dc=x" },
|
||||
displayName: "Alice");
|
||||
var svc = new LdapAuthService(Opts(), new FakeLdapConnectionFactory(fake));
|
||||
|
||||
var r = await svc.AuthenticateAsync("alice", "pw", default);
|
||||
|
||||
Assert.True(r.Succeeded);
|
||||
Assert.Equal(new[] { "Eng,ineers", "A,B" }, r.Groups);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user