Add unit tests for RabbitMq and Udp transport servers and clients
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implemented comprehensive unit tests for RabbitMqTransportServer, covering constructor, disposal, connection management, event handlers, and exception handling. - Added configuration tests for RabbitMqTransportServer to validate SSL, durable queues, auto-recovery, and custom virtual host options. - Created unit tests for UdpFrameProtocol, including frame parsing and serialization, header size validation, and round-trip data preservation. - Developed tests for UdpTransportClient, focusing on connection handling, event subscriptions, and exception scenarios. - Established tests for UdpTransportServer, ensuring proper start/stop behavior, connection state management, and event handling. - Included tests for UdpTransportOptions to verify default values and modification capabilities. - Enhanced service registration tests for Udp transport services in the dependency injection container.
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace StellaOps.Cryptography;
|
||||
|
||||
/// <summary>
|
||||
/// Service for resolving cryptographic algorithms based on the active compliance profile.
|
||||
/// </summary>
|
||||
public sealed class CryptoComplianceService : ICryptoComplianceService
|
||||
{
|
||||
private readonly IOptionsMonitor<CryptoComplianceOptions> _options;
|
||||
private readonly ILogger<CryptoComplianceService> _logger;
|
||||
|
||||
public CryptoComplianceService(
|
||||
IOptionsMonitor<CryptoComplianceOptions> options,
|
||||
ILogger<CryptoComplianceService>? logger = null)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_logger = logger ?? NullLogger<CryptoComplianceService>.Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the currently active compliance profile.
|
||||
/// </summary>
|
||||
public ComplianceProfile ActiveProfile
|
||||
{
|
||||
get
|
||||
{
|
||||
var opts = _options.CurrentValue;
|
||||
opts.ApplyEnvironmentOverrides();
|
||||
return ComplianceProfiles.GetProfile(opts.ProfileId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the algorithm for a given purpose based on the active profile.
|
||||
/// </summary>
|
||||
/// <param name="purpose">The hash purpose.</param>
|
||||
/// <returns>The algorithm identifier.</returns>
|
||||
public string GetAlgorithmForPurpose(string purpose)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(purpose))
|
||||
{
|
||||
throw new ArgumentException("Purpose cannot be null or empty.", nameof(purpose));
|
||||
}
|
||||
|
||||
var opts = _options.CurrentValue;
|
||||
opts.ApplyEnvironmentOverrides();
|
||||
|
||||
// Check for purpose overrides first
|
||||
if (opts.PurposeOverrides?.TryGetValue(purpose, out var overrideAlgorithm) == true &&
|
||||
!string.IsNullOrWhiteSpace(overrideAlgorithm))
|
||||
{
|
||||
_logger.LogDebug(
|
||||
"Using purpose override for {Purpose}: {Algorithm} (profile: {Profile})",
|
||||
purpose, overrideAlgorithm, opts.ProfileId);
|
||||
return overrideAlgorithm;
|
||||
}
|
||||
|
||||
// Get from active profile
|
||||
var profile = ComplianceProfiles.GetProfile(opts.ProfileId);
|
||||
return profile.GetAlgorithmForPurpose(purpose);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash prefix for a given purpose (e.g., "blake3:", "sha256:").
|
||||
/// </summary>
|
||||
/// <param name="purpose">The hash purpose.</param>
|
||||
/// <returns>The hash prefix string.</returns>
|
||||
public string GetHashPrefix(string purpose)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(purpose))
|
||||
{
|
||||
throw new ArgumentException("Purpose cannot be null or empty.", nameof(purpose));
|
||||
}
|
||||
|
||||
var profile = ActiveProfile;
|
||||
return profile.GetHashPrefix(purpose);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates an algorithm request against the active compliance profile.
|
||||
/// </summary>
|
||||
/// <param name="purpose">The hash purpose (or null if unknown).</param>
|
||||
/// <param name="requestedAlgorithm">The requested algorithm.</param>
|
||||
/// <exception cref="CryptoComplianceException">
|
||||
/// Thrown when StrictValidation is enabled and the algorithm is not compliant.
|
||||
/// </exception>
|
||||
public void ValidateAlgorithm(string? purpose, string requestedAlgorithm)
|
||||
{
|
||||
var opts = _options.CurrentValue;
|
||||
opts.ApplyEnvironmentOverrides();
|
||||
|
||||
var profile = ComplianceProfiles.GetProfile(opts.ProfileId);
|
||||
|
||||
// If purpose is specified, check compliance
|
||||
if (!string.IsNullOrWhiteSpace(purpose))
|
||||
{
|
||||
if (!profile.IsCompliant(purpose, requestedAlgorithm))
|
||||
{
|
||||
var expectedAlgorithm = profile.GetAlgorithmForPurpose(purpose);
|
||||
var message = $"Algorithm '{requestedAlgorithm}' is not compliant for purpose '{purpose}' " +
|
||||
$"in profile '{profile.ProfileId}'. Expected: '{expectedAlgorithm}'.";
|
||||
|
||||
if (opts.StrictValidation)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Compliance violation: {Message}",
|
||||
message);
|
||||
throw new CryptoComplianceException(message, profile.ProfileId, purpose, requestedAlgorithm, expectedAlgorithm);
|
||||
}
|
||||
|
||||
if (opts.WarnOnNonCompliant)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Compliance warning: {Message}",
|
||||
message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given algorithm is compliant for any purpose in the active profile.
|
||||
/// </summary>
|
||||
/// <param name="algorithmId">The algorithm to check.</param>
|
||||
/// <returns>True if the algorithm is used by any purpose in the profile.</returns>
|
||||
public bool IsAlgorithmCompliant(string algorithmId)
|
||||
{
|
||||
var profile = ActiveProfile;
|
||||
return HashPurpose.All.Any(purpose => profile.IsCompliant(purpose, algorithmId));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for compliance-aware cryptographic algorithm resolution.
|
||||
/// </summary>
|
||||
public interface ICryptoComplianceService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the currently active compliance profile.
|
||||
/// </summary>
|
||||
ComplianceProfile ActiveProfile { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the algorithm for a given purpose based on the active profile.
|
||||
/// </summary>
|
||||
string GetAlgorithmForPurpose(string purpose);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash prefix for a given purpose.
|
||||
/// </summary>
|
||||
string GetHashPrefix(string purpose);
|
||||
|
||||
/// <summary>
|
||||
/// Validates an algorithm request against the active compliance profile.
|
||||
/// </summary>
|
||||
void ValidateAlgorithm(string? purpose, string requestedAlgorithm);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given algorithm is compliant for any purpose in the active profile.
|
||||
/// </summary>
|
||||
bool IsAlgorithmCompliant(string algorithmId);
|
||||
}
|
||||
Reference in New Issue
Block a user