feat(gateway): persist/reuse self-signed cert with hardened permissions
This commit is contained in:
@@ -33,6 +33,75 @@ public sealed class SelfSignedCertificateProviderTests
|
||||
o => o.Value == "1.3.6.1.5.5.7.3.1"); // serverAuth
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadOrCreate_GeneratesPersistsAndReuses_SameThumbprint()
|
||||
{
|
||||
string dir = Directory.CreateTempSubdirectory().FullName;
|
||||
try
|
||||
{
|
||||
string path = Path.Combine(dir, "gw.pfx");
|
||||
FakeTimeProvider time = new(new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero));
|
||||
TlsOptions options = new() { SelfSignedCertPath = path };
|
||||
|
||||
using X509Certificate2 first = CreateProvider(options, time).LoadOrCreate();
|
||||
Assert.True(File.Exists(path));
|
||||
using X509Certificate2 second = CreateProvider(options, time).LoadOrCreate();
|
||||
|
||||
Assert.Equal(first.Thumbprint, second.Thumbprint); // reused, not regenerated
|
||||
}
|
||||
finally { Directory.Delete(dir, recursive: true); }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadOrCreate_Regenerates_WhenPersistedCertExpired()
|
||||
{
|
||||
string dir = Directory.CreateTempSubdirectory().FullName;
|
||||
try
|
||||
{
|
||||
string path = Path.Combine(dir, "gw.pfx");
|
||||
FakeTimeProvider time = new(new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero));
|
||||
TlsOptions options = new() { SelfSignedCertPath = path, ValidityYears = 1 };
|
||||
|
||||
using X509Certificate2 first = CreateProvider(options, time).LoadOrCreate();
|
||||
time.Advance(TimeSpan.FromDays(800)); // past 1-year validity
|
||||
using X509Certificate2 second = CreateProvider(options, time).LoadOrCreate();
|
||||
|
||||
Assert.NotEqual(first.Thumbprint, second.Thumbprint);
|
||||
}
|
||||
finally { Directory.Delete(dir, recursive: true); }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadOrCreate_Regenerates_WhenPersistedFileCorrupt()
|
||||
{
|
||||
string dir = Directory.CreateTempSubdirectory().FullName;
|
||||
try
|
||||
{
|
||||
string path = Path.Combine(dir, "gw.pfx");
|
||||
File.WriteAllText(path, "not a pfx");
|
||||
TlsOptions options = new() { SelfSignedCertPath = path };
|
||||
using X509Certificate2 cert = CreateProvider(options, new FakeTimeProvider()).LoadOrCreate();
|
||||
Assert.True(cert.HasPrivateKey);
|
||||
}
|
||||
finally { Directory.Delete(dir, recursive: true); }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadOrCreate_Throws_WhenExpiredAndRegenerateDisabled()
|
||||
{
|
||||
string dir = Directory.CreateTempSubdirectory().FullName;
|
||||
try
|
||||
{
|
||||
string path = Path.Combine(dir, "gw.pfx");
|
||||
FakeTimeProvider time = new(new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero));
|
||||
TlsOptions options = new() { SelfSignedCertPath = path, ValidityYears = 1, RegenerateIfExpired = false };
|
||||
using (CreateProvider(options, time).LoadOrCreate()) { }
|
||||
time.Advance(TimeSpan.FromDays(800));
|
||||
Assert.Throws<InvalidOperationException>(() => CreateProvider(options, time).LoadOrCreate());
|
||||
}
|
||||
finally { Directory.Delete(dir, recursive: true); }
|
||||
}
|
||||
|
||||
private static string ReadSubjectAltNames(X509Certificate2 cert)
|
||||
=> cert.Extensions
|
||||
.First(e => e.Oid?.Value == "2.5.29.17")
|
||||
|
||||
Reference in New Issue
Block a user