up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
This commit is contained in:
@@ -4,22 +4,22 @@ using System.Globalization;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using StellaOps.Configuration;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Configuration.Tests;
|
||||
|
||||
public class StellaOpsAuthorityOptionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Validate_Throws_When_IssuerMissing()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions();
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
|
||||
Assert.Contains("issuer", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
namespace StellaOps.Configuration.Tests;
|
||||
|
||||
public class StellaOpsAuthorityOptionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Validate_Throws_When_IssuerMissing()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions();
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
|
||||
Assert.Contains("issuer", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Normalises_Collections()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
@@ -67,35 +67,35 @@ public class StellaOpsAuthorityOptionsTests
|
||||
|
||||
Assert.Contains("remote inference", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
[Fact]
|
||||
public void Validate_Normalises_PluginDescriptors()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
var descriptor = new AuthorityPluginDescriptorOptions
|
||||
{
|
||||
AssemblyName = "StellaOps.Authority.Plugin.Standard",
|
||||
ConfigFile = " standard.yaml ",
|
||||
Enabled = true
|
||||
};
|
||||
|
||||
descriptor.Capabilities.Add("password");
|
||||
descriptor.Capabilities.Add("PASSWORD");
|
||||
options.Plugins.Descriptors["standard"] = descriptor;
|
||||
|
||||
options.Validate();
|
||||
|
||||
var normalized = options.Plugins.Descriptors["standard"];
|
||||
Assert.Equal("standard.yaml", normalized.ConfigFile);
|
||||
Assert.Single(normalized.Capabilities);
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
var descriptor = new AuthorityPluginDescriptorOptions
|
||||
{
|
||||
AssemblyName = "StellaOps.Authority.Plugin.Standard",
|
||||
ConfigFile = " standard.yaml ",
|
||||
Enabled = true
|
||||
};
|
||||
|
||||
descriptor.Capabilities.Add("password");
|
||||
descriptor.Capabilities.Add("PASSWORD");
|
||||
options.Plugins.Descriptors["standard"] = descriptor;
|
||||
|
||||
options.Validate();
|
||||
|
||||
var normalized = options.Plugins.Descriptors["standard"];
|
||||
Assert.Equal("standard.yaml", normalized.ConfigFile);
|
||||
Assert.Single(normalized.Capabilities);
|
||||
Assert.Equal("password", normalized.Capabilities[0]);
|
||||
}
|
||||
|
||||
@@ -163,149 +163,149 @@ public class StellaOpsAuthorityOptionsTests
|
||||
|
||||
Assert.Contains("consentVersion", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Throws_When_StorageConnectionStringMissing()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
|
||||
Assert.Contains("Mongo connection string", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_Binds_From_Configuration()
|
||||
{
|
||||
var context = StellaOpsAuthorityConfiguration.Build(options =>
|
||||
{
|
||||
options.ConfigureBuilder = builder =>
|
||||
{
|
||||
builder.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Authority:SchemaVersion"] = "2",
|
||||
["Authority:Issuer"] = "https://authority.internal",
|
||||
["Authority:AccessTokenLifetime"] = "00:30:00",
|
||||
["Authority:RefreshTokenLifetime"] = "30.00:00:00",
|
||||
["Authority:Storage:ConnectionString"] = "mongodb://example/stellaops",
|
||||
["Authority:Storage:DatabaseName"] = "overrideDb",
|
||||
["Authority:Storage:CommandTimeout"] = "00:01:30",
|
||||
["Authority:PluginDirectories:0"] = "/var/lib/stellaops/plugins",
|
||||
["Authority:BypassNetworks:0"] = "127.0.0.1/32",
|
||||
["Authority:Security:RateLimiting:Token:PermitLimit"] = "25",
|
||||
["Authority:Security:RateLimiting:Token:Window"] = "00:00:30",
|
||||
["Authority:Security:RateLimiting:Authorize:Enabled"] = "true",
|
||||
["Authority:Security:RateLimiting:Internal:Enabled"] = "true",
|
||||
["Authority:Security:RateLimiting:Internal:PermitLimit"] = "3",
|
||||
["Authority:Signing:Enabled"] = "true",
|
||||
["Authority:Signing:ActiveKeyId"] = "authority-signing-dev",
|
||||
["Authority:Signing:KeyPath"] = "../certificates/authority-signing-dev.pem",
|
||||
["Authority:Signing:KeySource"] = "file"
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
var options = context.Options;
|
||||
|
||||
Assert.Equal(2, options.SchemaVersion);
|
||||
Assert.Equal(new Uri("https://authority.internal"), options.Issuer);
|
||||
Assert.Equal(TimeSpan.FromMinutes(30), options.AccessTokenLifetime);
|
||||
Assert.Equal(TimeSpan.FromDays(30), options.RefreshTokenLifetime);
|
||||
Assert.Equal(new[] { "/var/lib/stellaops/plugins" }, options.PluginDirectories);
|
||||
Assert.Equal(new[] { "127.0.0.1/32" }, options.BypassNetworks);
|
||||
Assert.Equal("mongodb://example/stellaops", options.Storage.ConnectionString);
|
||||
Assert.Equal("overrideDb", options.Storage.DatabaseName);
|
||||
Assert.Equal(TimeSpan.FromMinutes(1.5), options.Storage.CommandTimeout);
|
||||
Assert.Equal(25, options.Security.RateLimiting.Token.PermitLimit);
|
||||
Assert.Equal(TimeSpan.FromSeconds(30), options.Security.RateLimiting.Token.Window);
|
||||
Assert.True(options.Security.RateLimiting.Authorize.Enabled);
|
||||
Assert.True(options.Security.RateLimiting.Internal.Enabled);
|
||||
Assert.Equal(3, options.Security.RateLimiting.Internal.PermitLimit);
|
||||
Assert.True(options.Signing.Enabled);
|
||||
Assert.Equal("authority-signing-dev", options.Signing.ActiveKeyId);
|
||||
Assert.Equal("../certificates/authority-signing-dev.pem", options.Signing.KeyPath);
|
||||
Assert.Equal("file", options.Signing.KeySource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Normalises_ExceptionRoutingTemplates()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
options.Exceptions.RoutingTemplates.Add(new AuthorityExceptionRoutingTemplateOptions
|
||||
{
|
||||
Id = " SecOps ",
|
||||
AuthorityRouteId = " approvals/secops ",
|
||||
RequireMfa = true,
|
||||
Description = " Security approvals "
|
||||
});
|
||||
|
||||
options.Validate();
|
||||
|
||||
Assert.True(options.Exceptions.RequiresMfaForApprovals);
|
||||
var template = Assert.Single(options.Exceptions.NormalizedRoutingTemplates);
|
||||
Assert.Equal("SecOps", template.Key);
|
||||
Assert.Equal("SecOps", template.Value.Id);
|
||||
Assert.Equal("approvals/secops", template.Value.AuthorityRouteId);
|
||||
Assert.Equal("Security approvals", template.Value.Description);
|
||||
Assert.True(template.Value.RequireMfa);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Throws_When_ExceptionRoutingTemplatesDuplicate()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
options.Exceptions.RoutingTemplates.Add(new AuthorityExceptionRoutingTemplateOptions
|
||||
{
|
||||
Id = "secops",
|
||||
AuthorityRouteId = "route/a"
|
||||
});
|
||||
options.Exceptions.RoutingTemplates.Add(new AuthorityExceptionRoutingTemplateOptions
|
||||
{
|
||||
Id = "SecOps",
|
||||
AuthorityRouteId = "route/b"
|
||||
});
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
Assert.Contains("secops", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Throws_When_RateLimitingInvalid()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Security.RateLimiting.Token.PermitLimit = 0;
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
|
||||
Assert.Contains("permitLimit", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Throws_When_StorageConnectionStringMissing()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
|
||||
Assert.Contains("Mongo connection string", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_Binds_From_Configuration()
|
||||
{
|
||||
var context = StellaOpsAuthorityConfiguration.Build(options =>
|
||||
{
|
||||
options.ConfigureBuilder = builder =>
|
||||
{
|
||||
builder.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Authority:SchemaVersion"] = "2",
|
||||
["Authority:Issuer"] = "https://authority.internal",
|
||||
["Authority:AccessTokenLifetime"] = "00:30:00",
|
||||
["Authority:RefreshTokenLifetime"] = "30.00:00:00",
|
||||
["Authority:Storage:ConnectionString"] = "mongodb://example/stellaops",
|
||||
["Authority:Storage:DatabaseName"] = "overrideDb",
|
||||
["Authority:Storage:CommandTimeout"] = "00:01:30",
|
||||
["Authority:PluginDirectories:0"] = "/var/lib/stellaops/plugins",
|
||||
["Authority:BypassNetworks:0"] = "127.0.0.1/32",
|
||||
["Authority:Security:RateLimiting:Token:PermitLimit"] = "25",
|
||||
["Authority:Security:RateLimiting:Token:Window"] = "00:00:30",
|
||||
["Authority:Security:RateLimiting:Authorize:Enabled"] = "true",
|
||||
["Authority:Security:RateLimiting:Internal:Enabled"] = "true",
|
||||
["Authority:Security:RateLimiting:Internal:PermitLimit"] = "3",
|
||||
["Authority:Signing:Enabled"] = "true",
|
||||
["Authority:Signing:ActiveKeyId"] = "authority-signing-dev",
|
||||
["Authority:Signing:KeyPath"] = "../certificates/authority-signing-dev.pem",
|
||||
["Authority:Signing:KeySource"] = "file"
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
var options = context.Options;
|
||||
|
||||
Assert.Equal(2, options.SchemaVersion);
|
||||
Assert.Equal(new Uri("https://authority.internal"), options.Issuer);
|
||||
Assert.Equal(TimeSpan.FromMinutes(30), options.AccessTokenLifetime);
|
||||
Assert.Equal(TimeSpan.FromDays(30), options.RefreshTokenLifetime);
|
||||
Assert.Equal(new[] { "/var/lib/stellaops/plugins" }, options.PluginDirectories);
|
||||
Assert.Equal(new[] { "127.0.0.1/32" }, options.BypassNetworks);
|
||||
Assert.Equal("mongodb://example/stellaops", options.Storage.ConnectionString);
|
||||
Assert.Equal("overrideDb", options.Storage.DatabaseName);
|
||||
Assert.Equal(TimeSpan.FromMinutes(1.5), options.Storage.CommandTimeout);
|
||||
Assert.Equal(25, options.Security.RateLimiting.Token.PermitLimit);
|
||||
Assert.Equal(TimeSpan.FromSeconds(30), options.Security.RateLimiting.Token.Window);
|
||||
Assert.True(options.Security.RateLimiting.Authorize.Enabled);
|
||||
Assert.True(options.Security.RateLimiting.Internal.Enabled);
|
||||
Assert.Equal(3, options.Security.RateLimiting.Internal.PermitLimit);
|
||||
Assert.True(options.Signing.Enabled);
|
||||
Assert.Equal("authority-signing-dev", options.Signing.ActiveKeyId);
|
||||
Assert.Equal("../certificates/authority-signing-dev.pem", options.Signing.KeyPath);
|
||||
Assert.Equal("file", options.Signing.KeySource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Normalises_ExceptionRoutingTemplates()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
options.Exceptions.RoutingTemplates.Add(new AuthorityExceptionRoutingTemplateOptions
|
||||
{
|
||||
Id = " SecOps ",
|
||||
AuthorityRouteId = " approvals/secops ",
|
||||
RequireMfa = true,
|
||||
Description = " Security approvals "
|
||||
});
|
||||
|
||||
options.Validate();
|
||||
|
||||
Assert.True(options.Exceptions.RequiresMfaForApprovals);
|
||||
var template = Assert.Single(options.Exceptions.NormalizedRoutingTemplates);
|
||||
Assert.Equal("SecOps", template.Key);
|
||||
Assert.Equal("SecOps", template.Value.Id);
|
||||
Assert.Equal("approvals/secops", template.Value.AuthorityRouteId);
|
||||
Assert.Equal("Security approvals", template.Value.Description);
|
||||
Assert.True(template.Value.RequireMfa);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Throws_When_ExceptionRoutingTemplatesDuplicate()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
options.Exceptions.RoutingTemplates.Add(new AuthorityExceptionRoutingTemplateOptions
|
||||
{
|
||||
Id = "secops",
|
||||
AuthorityRouteId = "route/a"
|
||||
});
|
||||
options.Exceptions.RoutingTemplates.Add(new AuthorityExceptionRoutingTemplateOptions
|
||||
{
|
||||
Id = "SecOps",
|
||||
AuthorityRouteId = "route/b"
|
||||
});
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
Assert.Contains("secops", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Throws_When_RateLimitingInvalid()
|
||||
{
|
||||
var options = new StellaOpsAuthorityOptions
|
||||
{
|
||||
Issuer = new Uri("https://authority.stella-ops.test"),
|
||||
SchemaVersion = 1
|
||||
};
|
||||
options.Storage.ConnectionString = "mongodb://localhost:27017/authority";
|
||||
options.Security.RateLimiting.Token.PermitLimit = 0;
|
||||
options.Signing.ActiveKeyId = "test-key";
|
||||
options.Signing.KeyPath = "/tmp/test-key.pem";
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => options.Validate());
|
||||
|
||||
Assert.Contains("permitLimit", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user