up
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace StellaOps.Cryptography.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
/// Validates and normalises crypto provider registry options for RU/GOST baselines.
|
||||
/// </summary>
|
||||
public static class CryptoProviderRegistryValidator
|
||||
{
|
||||
private static readonly StringComparer OrdinalIgnoreCase = StringComparer.OrdinalIgnoreCase;
|
||||
|
||||
public static void EnforceRuLinuxDefaults(CryptoProviderRegistryOptions options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
var enableOpenSsl = GetEnvFlag("STELLAOPS_CRYPTO_ENABLE_RU_OPENSSL", defaultValue: OperatingSystem.IsLinux());
|
||||
var enablePkcs11 = GetEnvFlag("STELLAOPS_CRYPTO_ENABLE_RU_PKCS11", defaultValue: true);
|
||||
var enableWineCsp = GetEnvFlag("STELLAOPS_CRYPTO_ENABLE_RU_WINECSP", defaultValue: false);
|
||||
|
||||
#if STELLAOPS_CRYPTO_PRO
|
||||
var enableCryptoPro = GetEnvFlag("STELLAOPS_CRYPTO_ENABLE_RU_CSP", defaultValue: OperatingSystem.IsWindows());
|
||||
#endif
|
||||
|
||||
options.ActiveProfile = string.IsNullOrWhiteSpace(options.ActiveProfile)
|
||||
? "ru-offline"
|
||||
: options.ActiveProfile;
|
||||
|
||||
EnsureBaselineProfiles(options);
|
||||
EnsureDefaultPreferred(options.PreferredProviders, enableOpenSsl, enablePkcs11, enableWineCsp
|
||||
#if STELLAOPS_CRYPTO_PRO
|
||||
, enableCryptoPro
|
||||
#endif
|
||||
);
|
||||
|
||||
if (options.Profiles.TryGetValue(options.ActiveProfile, out var profile))
|
||||
{
|
||||
EnsureDefaultPreferred(profile.PreferredProviders, enableOpenSsl, enablePkcs11, enableWineCsp
|
||||
#if STELLAOPS_CRYPTO_PRO
|
||||
, enableCryptoPro
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
var resolved = options.ResolvePreferredProviders();
|
||||
if (resolved.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Crypto provider registry cannot be empty. Configure at least one provider for RU deployments.");
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsLinux() && enableOpenSsl &&
|
||||
!resolved.Contains("ru.openssl.gost", OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("Linux RU baseline requires provider 'ru.openssl.gost' (set STELLAOPS_CRYPTO_ENABLE_RU_OPENSSL=0 to override explicitly).");
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsLinux() && !enableOpenSsl && !enablePkcs11)
|
||||
{
|
||||
throw new InvalidOperationException("RU Linux baseline is misconfigured: both ru.openssl.gost and ru.pkcs11 are disabled via environment. Enable at least one provider.");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool GetEnvFlag(string name, bool defaultValue)
|
||||
{
|
||||
var raw = Environment.GetEnvironmentVariable(name);
|
||||
if (string.IsNullOrWhiteSpace(raw))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return raw.Equals("1", StringComparison.OrdinalIgnoreCase) ||
|
||||
raw.Equals("true", StringComparison.OrdinalIgnoreCase) ||
|
||||
raw.Equals("yes", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static void EnsureBaselineProfiles(CryptoProviderRegistryOptions options)
|
||||
{
|
||||
if (!options.PreferredProviders.Any())
|
||||
{
|
||||
options.PreferredProviders.Add("default");
|
||||
}
|
||||
|
||||
if (!options.Profiles.TryGetValue("ru-offline", out var ruOffline))
|
||||
{
|
||||
ruOffline = new CryptoProviderProfileOptions();
|
||||
options.Profiles["ru-offline"] = ruOffline;
|
||||
}
|
||||
|
||||
if (!options.Profiles.ContainsKey("ru-linux-soft"))
|
||||
{
|
||||
options.Profiles["ru-linux-soft"] = new CryptoProviderProfileOptions();
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureDefaultPreferred(
|
||||
IList<string> providers,
|
||||
bool enableOpenSsl,
|
||||
bool enablePkcs11,
|
||||
bool enableWineCsp
|
||||
#if STELLAOPS_CRYPTO_PRO
|
||||
, bool enableCryptoPro
|
||||
#endif
|
||||
)
|
||||
{
|
||||
InsertIfMissing(providers, "default");
|
||||
|
||||
if (enableOpenSsl)
|
||||
{
|
||||
InsertIfMissing(providers, "ru.openssl.gost");
|
||||
}
|
||||
|
||||
if (enablePkcs11)
|
||||
{
|
||||
InsertIfMissing(providers, "ru.pkcs11");
|
||||
}
|
||||
|
||||
if (enableWineCsp)
|
||||
{
|
||||
InsertIfMissing(providers, "ru.winecsp.http");
|
||||
}
|
||||
|
||||
#if STELLAOPS_CRYPTO_PRO
|
||||
if (enableCryptoPro && OperatingSystem.IsWindows())
|
||||
{
|
||||
InsertIfMissing(providers, "ru.cryptopro.csp");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void InsertIfMissing(IList<string> providers, string name)
|
||||
{
|
||||
for (var i = 0; i < providers.Count; i++)
|
||||
{
|
||||
if (string.Equals(providers[i], name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
providers.Insert(0, name);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ using StellaOps.Cryptography.Plugin.CryptoPro;
|
||||
#endif
|
||||
using StellaOps.Cryptography.Plugin.Pkcs11Gost;
|
||||
using StellaOps.Cryptography.Plugin.OpenSslGost;
|
||||
using StellaOps.Cryptography.Plugin.SmRemote;
|
||||
using StellaOps.Cryptography.Plugin.SmSoft;
|
||||
using StellaOps.Cryptography.Plugin.PqSoft;
|
||||
using StellaOps.Cryptography.Plugin.WineCsp;
|
||||
@@ -69,7 +70,17 @@ public static class CryptoServiceCollectionExtensions
|
||||
|
||||
services.TryAddSingleton<ICryptoHash, DefaultCryptoHash>();
|
||||
services.TryAddSingleton<ICryptoHmac, DefaultCryptoHmac>();
|
||||
services.AddOptions<SmRemoteProviderOptions>();
|
||||
services.AddHttpClient<SmRemoteHttpClient>((sp, httpClient) =>
|
||||
{
|
||||
var opts = sp.GetService<IOptions<SmRemoteProviderOptions>>()?.Value;
|
||||
if (opts is not null && !string.IsNullOrWhiteSpace(opts.BaseAddress))
|
||||
{
|
||||
httpClient.BaseAddress = new Uri(opts.BaseAddress);
|
||||
}
|
||||
});
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<ICryptoProvider, SmSoftCryptoProvider>());
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<ICryptoProvider, StellaOps.Cryptography.Plugin.SmRemote.SmRemoteHttpProvider>());
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<ICryptoProvider, PqSoftCryptoProvider>());
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<ICryptoProvider, FipsSoftCryptoProvider>());
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<ICryptoProvider, EidasSoftCryptoProvider>());
|
||||
@@ -171,41 +182,8 @@ public static class CryptoServiceCollectionExtensions
|
||||
}
|
||||
#endif
|
||||
|
||||
services.PostConfigure<CryptoProviderRegistryOptions>(options =>
|
||||
{
|
||||
EnsurePreferred(options.PreferredProviders);
|
||||
foreach (var profile in options.Profiles.Values)
|
||||
{
|
||||
EnsurePreferred(profile.PreferredProviders);
|
||||
}
|
||||
});
|
||||
services.PostConfigure<CryptoProviderRegistryOptions>(CryptoProviderRegistryValidator.EnforceRuLinuxDefaults);
|
||||
|
||||
return services;
|
||||
|
||||
static void EnsurePreferred(IList<string> providers)
|
||||
{
|
||||
InsertIfMissing(providers, "ru.pkcs11");
|
||||
InsertIfMissing(providers, "ru.openssl.gost");
|
||||
InsertIfMissing(providers, "ru.winecsp.http");
|
||||
#if STELLAOPS_CRYPTO_PRO
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
InsertIfMissing(providers, "ru.cryptopro.csp");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void InsertIfMissing(IList<string> providers, string name)
|
||||
{
|
||||
for (var i = 0; i < providers.Count; i++)
|
||||
{
|
||||
if (string.Equals(providers[i], name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
providers.Insert(0, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<ProjectReference Include="..\StellaOps.Cryptography.Plugin.Pkcs11Gost\StellaOps.Cryptography.Plugin.Pkcs11Gost.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Cryptography.Plugin.OpenSslGost\StellaOps.Cryptography.Plugin.OpenSslGost.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Cryptography.Plugin.SmSoft\StellaOps.Cryptography.Plugin.SmSoft.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Cryptography.Plugin.SmRemote\StellaOps.Cryptography.Plugin.SmRemote.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Cryptography.Plugin.PqSoft\StellaOps.Cryptography.Plugin.PqSoft.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Cryptography.Plugin.WineCsp\StellaOps.Cryptography.Plugin.WineCsp.csproj" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
|
||||
|
||||
Reference in New Issue
Block a user