Files
scadaproj/ZB.MOM.WW.Auth/tests/ZB.MOM.WW.Auth.Ldap.Tests/Integration/GLAuthIntegrationTests.cs
T

103 lines
4.9 KiB
C#

// GLAuth integration test — opt-in only.
//
// Prerequisites
// -------------
// 1. A running GLAuth instance (plaintext LDAP, no TLS).
// A ready-made Docker Compose stack lives in the sibling repo:
// ~/Desktop/ScadaBridge/infra/glauth
// Start it with: docker compose up -d
// Default listen address: localhost:3893
//
// 2. Set the following environment variables before running:
// ZB_LDAP_IT=1 (required — gates the test)
// ZB_LDAP_SERVER=localhost (optional, default localhost)
// ZB_LDAP_PORT=3893 (optional, default 3893)
// ZB_LDAP_BASE=dc=lmxopcua,dc=local (optional)
// ZB_LDAP_SVC_DN=cn=svc,dc=lmxopcua,dc=local (service-account DN)
// ZB_LDAP_SVC_PW=svcpass (service-account password)
// ZB_LDAP_USER=alice (test user login)
// ZB_LDAP_PW=alicepass (test user password)
// ZB_LDAP_USERATTR=cn (optional, default cn)
//
// Run command:
// ZB_LDAP_IT=1 ZB_LDAP_SVC_DN=... ZB_LDAP_SVC_PW=... \
// ZB_LDAP_USER=... ZB_LDAP_PW=... \
// dotnet test tests/ZB.MOM.WW.Auth.Ldap.Tests \
// --filter "FullyQualifiedName~GLAuthIntegrationTests"
//
// Without ZB_LDAP_IT=1 the test is SKIPPED — it does not affect the normal CI run.
using System.Net.Sockets;
using ZB.MOM.WW.Auth.Abstractions.Ldap;
using ZB.MOM.WW.Auth.Ldap;
namespace ZB.MOM.WW.Auth.Ldap.Tests.Integration;
public sealed class GLAuthIntegrationTests
{
/// <summary>
/// Performs a real bind-then-search-then-bind against a live GLAuth instance.
/// Verifies that authentication succeeds and that at least one LDAP group is returned.
/// Skipped unless <c>ZB_LDAP_IT=1</c> is set; skipped again if the server is unreachable.
/// </summary>
[SkippableFact]
public async Task Authenticate_AgainstRealGLAuth_Succeeds()
{
// ------------------------------------------------------------------ opt-in gate
Skip.IfNot(
Environment.GetEnvironmentVariable("ZB_LDAP_IT") == "1",
"Set ZB_LDAP_IT=1 and a reachable GLAuth to run.");
// ------------------------------------------------------------------ read config
var server = Environment.GetEnvironmentVariable("ZB_LDAP_SERVER") ?? "localhost";
var port = int.TryParse(Environment.GetEnvironmentVariable("ZB_LDAP_PORT"), out var p) ? p : 3893;
var baseDn = Environment.GetEnvironmentVariable("ZB_LDAP_BASE") ?? "dc=lmxopcua,dc=local";
var svcDn = Environment.GetEnvironmentVariable("ZB_LDAP_SVC_DN") ?? "";
var svcPw = Environment.GetEnvironmentVariable("ZB_LDAP_SVC_PW") ?? "";
var user = Environment.GetEnvironmentVariable("ZB_LDAP_USER") ?? "";
var pw = Environment.GetEnvironmentVariable("ZB_LDAP_PW") ?? "";
var userAttr = Environment.GetEnvironmentVariable("ZB_LDAP_USERATTR") ?? "cn";
// ------------------------------------------------------------------ reachability probe
try
{
using var tcp = new TcpClient();
// 3-second connect timeout to keep the test suite snappy when the server is absent
var connectTask = tcp.ConnectAsync(server, port);
if (!connectTask.Wait(TimeSpan.FromSeconds(3)))
Skip.If(true, $"GLAuth not reachable at {server}:{port} (connect timed out).");
}
catch (Exception ex)
{
Skip.If(true, $"GLAuth not reachable at {server}:{port}: {ex.Message}");
}
// ------------------------------------------------------------------ build options
var options = new LdapOptions
{
Enabled = true,
Server = server,
Port = port,
Transport = LdapTransport.None,
AllowInsecure = true,
SearchBase = baseDn,
ServiceAccountDn = svcDn,
ServiceAccountPassword = svcPw,
UserNameAttribute = userAttr,
// GLAuth returns memberOf by default; keep the library default
GroupAttribute = "memberOf",
};
// ------------------------------------------------------------------ exercise the real service
// Uses the public single-argument constructor, which wires up NovellLdapConnectionFactory
// internally — no test seam involved.
var svc = new LdapAuthService(options);
var result = await svc.AuthenticateAsync(user, pw, default);
// ------------------------------------------------------------------ assertions
Assert.True(result.Succeeded,
$"Authentication failed: {result.Failure} (server={server}:{port}, user={user})");
Assert.NotEmpty(result.Groups);
}
}