Files
tiku-backend.net/Tiku.IntegrationTests/Api/ProductionConfigurationTests.cs
xiong 33375a38d7
Some checks failed
ci / release-gate (push) Has been cancelled
refactor(architecture): harden module boundaries
2026-08-04 12:10:36 +08:00

109 lines
4.1 KiB
C#

using Microsoft.Extensions.Configuration;
using Tiku.Api.Options;
using Tiku.Application.Security;
using Tiku.Infrastructure.Commerce;
namespace Tiku.IntegrationTests.Api;
public sealed class ProductionConfigurationTests
{
[Fact]
public void Database_connection_is_required_outside_development()
{
var configuration = new ConfigurationBuilder().Build();
var exception = Assert.Throws<InvalidOperationException>(() =>
OptionsValidation.ResolveDatabaseConnectionString(configuration, false));
Assert.Contains("Database connection is required", exception.Message, StringComparison.Ordinal);
}
[Fact]
public void Development_database_default_uses_current_system_user_without_a_password()
{
var configuration = new ConfigurationBuilder().Build();
var connectionString = OptionsValidation.ResolveDatabaseConnectionString(
configuration,
true);
Assert.Contains($"Username={Environment.UserName}", connectionString, StringComparison.Ordinal);
Assert.DoesNotContain("Password=", connectionString, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void Production_requires_an_explicit_rsa_private_key()
{
var options = new JwtOptions
{
KeyId = "production-key",
PrivateKeyPem = string.Empty
};
Assert.False(OptionsValidation.BeValidJwtOptions(options, true));
Assert.True(OptionsValidation.BeValidJwtOptions(options, false));
options.PrivateKeyPem = TestJwtKeys.PrivateKeyPem;
Assert.True(OptionsValidation.BeValidJwtOptions(options, true));
}
[Fact]
public void Jwt_configuration_rejects_development_kid_malformed_keys_and_current_kid_in_old_key_set()
{
var options = new JwtOptions
{
KeyId = "development-ephemeral",
PrivateKeyPem = TestJwtKeys.PrivateKeyPem
};
Assert.False(OptionsValidation.BeValidJwtOptions(options, true));
options.KeyId = "current-key";
options.PrivateKeyPem = "-----BEGIN PRIVATE KEY-----\ninvalid\n-----END PRIVATE KEY-----";
Assert.False(OptionsValidation.BeValidJwtOptions(options, false));
options.PrivateKeyPem = TestJwtKeys.PrivateKeyPem;
options.PublicKeys[options.KeyId] = TestJwtKeys.PublicKeyPem;
Assert.False(OptionsValidation.BeValidJwtOptions(options, false));
options.PublicKeys.Clear();
options.PublicKeys["old-key"] = TestJwtKeys.PublicKeyPem;
Assert.True(OptionsValidation.BeValidJwtOptions(options, true));
}
[Fact]
public void Tenant_secret_encryption_requires_a_32_byte_base64_key()
{
Assert.False(TenantSecretEncryptionOptions.BeValid(new TenantSecretEncryptionOptions()));
Assert.False(TenantSecretEncryptionOptions.BeValid(new TenantSecretEncryptionOptions
{
KeyId = "key-v1",
MasterKey = Convert.ToBase64String(new byte[16])
}));
Assert.True(TenantSecretEncryptionOptions.BeValid(new TenantSecretEncryptionOptions
{
KeyId = "key-v1",
MasterKey = Convert.ToBase64String(new byte[32])
}));
}
[Fact]
public void Production_network_configuration_requires_formal_hosts_allowed_hosts_and_proxy()
{
var developmentDefaults = new TenantResolutionOptions();
var wildcard = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?> { ["AllowedHosts"] = "*" })
.Build();
Assert.False(OptionsValidation.BeValidTenantResolutionOptions(developmentDefaults, wildcard, true));
var production = new TenantResolutionOptions
{
PlatformHosts = ["admin.example.com"],
TrustedProxyAddresses = ["10.0.0.10"]
};
var explicitHosts = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{ ["AllowedHosts"] = "admin.example.com;api.example.com" })
.Build();
Assert.True(OptionsValidation.BeValidTenantResolutionOptions(production, explicitHosts, true));
}
}