99 lines
3.3 KiB
C#
99 lines
3.3 KiB
C#
using System.Security.Cryptography;
|
|
using ZA.CoreService.ESBCertificateManager.Models;
|
|
|
|
namespace ZA.CoreService.ESBCertificateManager.Services;
|
|
|
|
public sealed class CertificateDeployer
|
|
{
|
|
public Task<(bool Success, string Status, string? Detail, string? BackupPath)> DeployAsync(
|
|
string sourceCertificatePath,
|
|
DeploymentTarget target,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.Run(() => Deploy(sourceCertificatePath, target, cancellationToken), cancellationToken);
|
|
}
|
|
|
|
private static (bool Success, string Status, string? Detail, string? BackupPath) Deploy(
|
|
string sourceCertificatePath,
|
|
DeploymentTarget target,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
if (!File.Exists(sourceCertificatePath))
|
|
{
|
|
return (false, "Quelle fehlt", $"Quelldatei nicht gefunden: {sourceCertificatePath}", null);
|
|
}
|
|
|
|
string targetDirectory = PathResolver.ResolvePath(target.TargetDirectory);
|
|
Directory.CreateDirectory(targetDirectory);
|
|
|
|
string destinationPath = Path.Combine(targetDirectory, target.CertificateFileName);
|
|
string? backupPath = null;
|
|
|
|
try
|
|
{
|
|
if (File.Exists(destinationPath))
|
|
{
|
|
backupPath = $"{destinationPath}.bak-{DateTime.Now:yyyyMMddHHmmss}";
|
|
File.Copy(destinationPath, backupPath, overwrite: false);
|
|
}
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
File.Copy(sourceCertificatePath, destinationPath, overwrite: true);
|
|
|
|
string sourceHash = ComputeSha256(sourceCertificatePath);
|
|
string destHash = ComputeSha256(destinationPath);
|
|
|
|
if (!string.Equals(sourceHash, destHash, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
RestoreFromBackupOrDelete(destinationPath, backupPath);
|
|
return (false, "Hash-Fehler", "SHA-256 von Quelle und Ziel stimmen nicht überein. Rollback ausgeführt.", backupPath);
|
|
}
|
|
|
|
return (true, "Kopiert", $"Ziel: {destinationPath}", backupPath);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
throw;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
try
|
|
{
|
|
if (backupPath is not null && File.Exists(backupPath) && File.Exists(destinationPath))
|
|
{
|
|
File.Copy(backupPath, destinationPath, overwrite: true);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Rollback best-effort
|
|
}
|
|
|
|
return (false, "Kopierfehler", ex.Message, backupPath);
|
|
}
|
|
}
|
|
|
|
private static void RestoreFromBackupOrDelete(string destinationPath, string? backupPath)
|
|
{
|
|
if (backupPath is not null && File.Exists(backupPath))
|
|
{
|
|
File.Copy(backupPath, destinationPath, overwrite: true);
|
|
return;
|
|
}
|
|
|
|
if (File.Exists(destinationPath))
|
|
{
|
|
File.Delete(destinationPath);
|
|
}
|
|
}
|
|
|
|
public static string ComputeSha256(string filePath)
|
|
{
|
|
using FileStream stream = File.OpenRead(filePath);
|
|
byte[] hash = SHA256.HashData(stream);
|
|
return Convert.ToHexString(hash);
|
|
}
|
|
}
|