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:
dohertj2
2026-06-01 03:59:23 -04:00
commit 37e23cf9f2
73 changed files with 6836 additions and 0 deletions
@@ -0,0 +1,88 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.Auth.Abstractions.Ldap;
using ZB.MOM.WW.Auth.AspNetCore;
using ZB.MOM.WW.Auth.Ldap;
namespace ZB.MOM.WW.Auth.AspNetCore.Tests;
public class ServiceCollectionExtensionsTests
{
private const string LdapSection = "Auth:Ldap";
private const string LdapServer = "ldap.example.com";
private static IConfiguration BuildConfiguration() =>
new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"{LdapSection}:Server"] = LdapServer,
[$"{LdapSection}:SearchBase"] = "dc=example,dc=com",
[$"{LdapSection}:ServiceAccountDn"] = "cn=svc,dc=example,dc=com",
[$"{LdapSection}:Transport"] = nameof(LdapTransport.Ldaps),
})
.Build();
[Fact]
public void AddZbLdapAuth_ResolvesLdapAuthService()
{
IConfiguration config = BuildConfiguration();
var services = new ServiceCollection();
services.AddZbLdapAuth(config, LdapSection);
using ServiceProvider provider = services.BuildServiceProvider();
var service = provider.GetRequiredService<ILdapAuthService>();
Assert.NotNull(service);
}
[Fact]
public void AddZbLdapAuth_ILdapAuthService_IsSingleton()
{
IConfiguration config = BuildConfiguration();
var services = new ServiceCollection();
services.AddZbLdapAuth(config, LdapSection);
using ServiceProvider provider = services.BuildServiceProvider();
var first = provider.GetRequiredService<ILdapAuthService>();
var second = provider.GetRequiredService<ILdapAuthService>();
Assert.Same(first, second);
}
[Fact]
public void AddZbLdapAuth_BindsOptionsFromSection()
{
IConfiguration config = BuildConfiguration();
var services = new ServiceCollection();
services.AddZbLdapAuth(config, LdapSection);
using ServiceProvider provider = services.BuildServiceProvider();
var options = provider.GetRequiredService<IOptions<LdapOptions>>();
Assert.Equal(LdapServer, options.Value.Server);
Assert.Equal("dc=example,dc=com", options.Value.SearchBase);
Assert.Equal(LdapTransport.Ldaps, options.Value.Transport);
}
[Fact]
public void AddZbLdapAuth_RegistersOptionsValidator()
{
IConfiguration config = BuildConfiguration();
var services = new ServiceCollection();
services.AddZbLdapAuth(config, LdapSection);
using ServiceProvider provider = services.BuildServiceProvider();
var validators = provider.GetServices<IValidateOptions<LdapOptions>>().ToList();
Assert.Contains(validators, v => v is LdapOptionsValidator);
}
}
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<!-- Resolves CookieAuthenticationOptions, IServiceCollection, IConfiguration, and the
in-memory configuration provider used by the DI/cookie tests. -->
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ZB.MOM.WW.Auth.AspNetCore\ZB.MOM.WW.Auth.AspNetCore.csproj" />
<ProjectReference Include="..\..\src\ZB.MOM.WW.Auth.Abstractions\ZB.MOM.WW.Auth.Abstractions.csproj" />
<!-- Referenced so the DI tests can assert the concrete LdapOptionsValidator registration. -->
<ProjectReference Include="..\..\src\ZB.MOM.WW.Auth.Ldap\ZB.MOM.WW.Auth.Ldap.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,37 @@
using System.Security.Claims;
using ZB.MOM.WW.Auth.AspNetCore;
namespace ZB.MOM.WW.Auth.AspNetCore.Tests;
public class ZbClaimTypesTests
{
[Fact]
public void Name_AliasesClaimTypesName()
{
Assert.Equal(ClaimTypes.Name, ZbClaimTypes.Name);
}
[Fact]
public void Role_AliasesClaimTypesRole()
{
Assert.Equal(ClaimTypes.Role, ZbClaimTypes.Role);
}
[Fact]
public void DisplayName_HasExpectedLiteralValue()
{
Assert.Equal("zb:displayname", ZbClaimTypes.DisplayName);
}
[Fact]
public void Username_HasExpectedLiteralValue()
{
Assert.Equal("zb:username", ZbClaimTypes.Username);
}
[Fact]
public void ScopeId_HasExpectedLiteralValue()
{
Assert.Equal("zb:scopeid", ZbClaimTypes.ScopeId);
}
}
@@ -0,0 +1,77 @@
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using ZB.MOM.WW.Auth.AspNetCore;
namespace ZB.MOM.WW.Auth.AspNetCore.Tests;
public class ZbCookieDefaultsTests
{
[Fact]
public void Apply_SetsHardenedCookieFlags()
{
var options = new CookieAuthenticationOptions();
ZbCookieDefaults.Apply(options);
Assert.True(options.Cookie.HttpOnly);
Assert.Equal(SameSiteMode.Strict, options.Cookie.SameSite);
Assert.True(options.SlidingExpiration);
}
[Fact]
public void Apply_UsesSuppliedIdleTimeout()
{
var options = new CookieAuthenticationOptions();
var idle = TimeSpan.FromMinutes(12);
ZbCookieDefaults.Apply(options, idleTimeout: idle);
Assert.Equal(idle, options.ExpireTimeSpan);
}
[Fact]
public void Apply_DefaultsToDefaultIdleTimeout_WhenNotSupplied()
{
var options = new CookieAuthenticationOptions();
ZbCookieDefaults.Apply(options);
Assert.Equal(ZbCookieDefaults.DefaultIdleTimeout, options.ExpireTimeSpan);
}
[Fact]
public void Apply_RequireHttpsTrue_SetsSecurePolicyAlways()
{
var options = new CookieAuthenticationOptions();
ZbCookieDefaults.Apply(options, requireHttps: true);
Assert.Equal(CookieSecurePolicy.Always, options.Cookie.SecurePolicy);
}
[Fact]
public void Apply_RequireHttpsFalse_SetsSecurePolicySameAsRequest()
{
var options = new CookieAuthenticationOptions();
ZbCookieDefaults.Apply(options, requireHttps: false);
Assert.Equal(CookieSecurePolicy.SameAsRequest, options.Cookie.SecurePolicy);
}
[Fact]
public void Apply_DefaultsRequireHttpsToAlways()
{
var options = new CookieAuthenticationOptions();
ZbCookieDefaults.Apply(options);
Assert.Equal(CookieSecurePolicy.Always, options.Cookie.SecurePolicy);
}
[Fact]
public void Apply_NullOptions_Throws()
{
Assert.Throws<ArgumentNullException>(() => ZbCookieDefaults.Apply(null!));
}
}