f40409a688
Tracking IDs are review bookkeeping that rots in shipped source; the rationale they tagged is kept. Comment-only change (CommentChecker 458 -> 16 false positives).
165 lines
6.5 KiB
C#
165 lines
6.5 KiB
C#
using Microsoft.Extensions.Options;
|
|
using ZB.MOM.WW.MxGateway.Server.Configuration;
|
|
|
|
namespace ZB.MOM.WW.MxGateway.Tests.Configuration;
|
|
|
|
/// <summary>
|
|
/// Covers the projection <see cref="GatewayConfigurationProvider"/> makes from bound
|
|
/// <see cref="GatewayOptions"/> onto the effective-configuration record the dashboard renders.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The projection is hand-written member by member, so an option that exists and validates can
|
|
/// still be invisible on the settings page — which is exactly what happened to the two
|
|
/// dashboard-ACL options. These tests pin the dashboard-tag members to the options they come
|
|
/// from; the redaction assertions pin the opposite invariant, that the two secret-bearing members
|
|
/// are the only ones masked.
|
|
/// </remarks>
|
|
public sealed class GatewayConfigurationProviderTests
|
|
{
|
|
/// <summary>The group → tag map reaches the projection with its groups, tags and ordering intact.</summary>
|
|
[Fact]
|
|
public void GetEffectiveConfiguration_CopiesGroupToTagMapping()
|
|
{
|
|
GatewayOptions options = new()
|
|
{
|
|
Dashboard = new DashboardOptions
|
|
{
|
|
GroupToTag = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
// A multi-tag group is the interesting case: a projection that flattened the
|
|
// array to its first element, or to a joined string, would still satisfy a
|
|
// single-tag fixture.
|
|
["GwOps"] = ["team-a", "team-b"],
|
|
["GwViewers"] = ["team-a"],
|
|
},
|
|
},
|
|
};
|
|
|
|
EffectiveDashboardConfiguration dashboard = Project(options).Dashboard;
|
|
|
|
Assert.Equal(2, dashboard.GroupToTag.Count);
|
|
Assert.Equal(["team-a", "team-b"], dashboard.GroupToTag["GwOps"]);
|
|
Assert.Equal(["team-a"], dashboard.GroupToTag["GwViewers"]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The map's case-insensitive lookup survives the projection. LDAP group names arrive in
|
|
/// whatever case the directory returns them, so a projection that rebuilt the dictionary with
|
|
/// the default ordinal comparer would silently stop matching.
|
|
/// </summary>
|
|
[Fact]
|
|
public void GetEffectiveConfiguration_KeepsGroupToTagLookupCaseInsensitive()
|
|
{
|
|
GatewayOptions options = new()
|
|
{
|
|
Dashboard = new DashboardOptions
|
|
{
|
|
GroupToTag = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["GwOps"] = ["team-a"],
|
|
},
|
|
},
|
|
};
|
|
|
|
EffectiveDashboardConfiguration dashboard = Project(options).Dashboard;
|
|
|
|
Assert.True(dashboard.GroupToTag.ContainsKey("gwops"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// An unconfigured map projects as empty rather than null — the settings page renders the row
|
|
/// either way, and "none configured" is the operationally interesting answer.
|
|
/// </summary>
|
|
[Fact]
|
|
public void GetEffectiveConfiguration_WhenNoTagsConfigured_ProjectsEmptyMapping()
|
|
{
|
|
EffectiveDashboardConfiguration dashboard = Project(new GatewayOptions()).Dashboard;
|
|
|
|
Assert.Empty(dashboard.GroupToTag);
|
|
Assert.Empty(dashboard.GroupToRole);
|
|
}
|
|
|
|
/// <summary>The untagged-session visibility policy is projected, defaulting to the fail-closed value.</summary>
|
|
[Fact]
|
|
public void GetEffectiveConfiguration_CopiesUntaggedSessionVisibility()
|
|
{
|
|
Assert.Equal(
|
|
UntaggedSessionVisibility.AdminOnly,
|
|
Project(new GatewayOptions()).Dashboard.UntaggedSessionVisibility);
|
|
|
|
GatewayOptions widened = new()
|
|
{
|
|
Dashboard = new DashboardOptions
|
|
{
|
|
UntaggedSessionVisibility = UntaggedSessionVisibility.AllViewers,
|
|
},
|
|
};
|
|
|
|
Assert.Equal(
|
|
UntaggedSessionVisibility.AllViewers,
|
|
Project(widened).Dashboard.UntaggedSessionVisibility);
|
|
}
|
|
|
|
/// <summary>The pre-existing dashboard members keep coming from the options they always did.</summary>
|
|
[Fact]
|
|
public void GetEffectiveConfiguration_CopiesTheOtherDashboardMembers()
|
|
{
|
|
GatewayOptions options = new()
|
|
{
|
|
Dashboard = new DashboardOptions
|
|
{
|
|
Enabled = false,
|
|
AllowAnonymousLocalhost = false,
|
|
SnapshotIntervalMilliseconds = 2_500,
|
|
RecentFaultLimit = 7,
|
|
RecentSessionLimit = 11,
|
|
ShowTagValues = true,
|
|
GroupToRole = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["GwAdmins"] = "Administrator",
|
|
},
|
|
},
|
|
};
|
|
|
|
EffectiveDashboardConfiguration dashboard = Project(options).Dashboard;
|
|
|
|
Assert.False(dashboard.Enabled);
|
|
Assert.False(dashboard.AllowAnonymousLocalhost);
|
|
Assert.Equal(2_500, dashboard.SnapshotIntervalMilliseconds);
|
|
Assert.Equal(7, dashboard.RecentFaultLimit);
|
|
Assert.Equal(11, dashboard.RecentSessionLimit);
|
|
Assert.True(dashboard.ShowTagValues);
|
|
Assert.Equal("Administrator", dashboard.GroupToRole["GwAdmins"]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The masking boundary. Only the pepper name and the LDAP bind password are redacted; the
|
|
/// tag mapping is configuration, not a secret, so masking it would hide the very thing the
|
|
/// settings page was extended to show.
|
|
/// </summary>
|
|
[Fact]
|
|
public void GetEffectiveConfiguration_RedactsOnlyTheSecretBearingMembers()
|
|
{
|
|
GatewayOptions options = new()
|
|
{
|
|
Ldap = new LdapOptions { ServiceAccountPassword = "bind-password" },
|
|
Dashboard = new DashboardOptions
|
|
{
|
|
GroupToTag = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["GwOps"] = ["team-a"],
|
|
},
|
|
},
|
|
};
|
|
|
|
EffectiveGatewayConfiguration configuration = Project(options);
|
|
|
|
Assert.Equal(GatewayConfigurationProvider.RedactedValue, configuration.Authentication.PepperSecretName);
|
|
Assert.Equal(GatewayConfigurationProvider.RedactedValue, configuration.Ldap.ServiceAccountPassword);
|
|
Assert.Equal(["team-a"], configuration.Dashboard.GroupToTag["GwOps"]);
|
|
}
|
|
|
|
private static EffectiveGatewayConfiguration Project(GatewayOptions options) =>
|
|
new GatewayConfigurationProvider(Options.Create(options)).GetEffectiveConfiguration();
|
|
}
|