From 5298a3e4dfb0ba127cdb41843e9d0d629f9e53e6 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Thu, 11 Jan 2024 10:03:05 +0100 Subject: [PATCH 01/31] Improved resilience in data protection mechanism --- src/fiskaltrust.Launcher/Commands/Common.cs | 67 ++++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 1fa6bf90..1237e36c 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -93,7 +93,8 @@ public static async Task HandleAsync( try { options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + launcherConfiguration = + LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); } catch (Exception e) { @@ -101,15 +102,19 @@ public static async Task HandleAsync( { if (File.Exists(options.LauncherConfigurationFile)) { - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", options.LauncherConfigurationFile); + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", + options.LauncherConfigurationFile); } else { - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", options.LauncherConfigurationFile); + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", + options.LauncherConfigurationFile); } + Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); } } + Log.Verbose("Merging legacy launcher config file."); if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) { @@ -132,7 +137,8 @@ public static async Task HandleAsync( Log.Verbose("Merging launcher cli args."); launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); - if (!launcherConfiguration.UseOffline!.Value && (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) + if (!launcherConfiguration.UseOffline!.Value && + (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) { Log.Error("CashBoxId and AccessToken are not provided."); } @@ -153,7 +159,8 @@ public static async Task HandleAsync( ECDiffieHellman? clientEcdh = null; try { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, + launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); using var downloader = new ConfigurationDownloader(launcherConfiguration); var exists = await downloader.DownloadConfigurationAsync(clientEcdh); if (launcherConfiguration.UseOffline!.Value && !exists) @@ -164,11 +171,13 @@ public static async Task HandleAsync( catch (Exception e) { var message = "Could not download Cashbox configuration. "; - message += $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; + message += + $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; if (!launcherConfiguration.Sandbox!.Value) { message += " Did you forget the --sandbox flag?"; } + message += ")"; Log.Error(e, message); } @@ -176,7 +185,9 @@ public static async Task HandleAsync( try { var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; - launcherConfiguration.OverwriteWith(LauncherConfigurationInCashBoxConfiguration.Deserialize(await File.ReadAllTextAsync(cashboxConfigurationFile))); + launcherConfiguration.OverwriteWith( + LauncherConfigurationInCashBoxConfiguration.Deserialize( + await File.ReadAllTextAsync(cashboxConfigurationFile))); } catch (Exception e) { @@ -186,7 +197,9 @@ public static async Task HandleAsync( var cashboxConfiguration = new ftCashBoxConfiguration(); try { - cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + cashboxConfiguration = + CashBoxConfigurationExt.Deserialize( + await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } catch (Exception e) @@ -196,7 +209,8 @@ public static async Task HandleAsync( Log.Logger = new LoggerConfiguration() .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .AddFileLoggingConfiguration(launcherConfiguration, + new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) .Enrich.FromLogContext() .CreateLogger(); @@ -211,22 +225,45 @@ public static async Task HandleAsync( } Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); - Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); + Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", + launcherConfiguration.CashboxConfigurationFile); Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); - - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, + useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); try { - launcherConfiguration.Decrypt(dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + launcherConfiguration.Decrypt( + dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); } catch (Exception e) { - Log.Warning(e, "Error decrypring launcher configuration file."); + Log.Warning(e, "Error decrypting launcher configuration. Attempting to regenerate and redownload."); + + var serviceFolder = launcherConfiguration.ServiceFolder!; + var cashboxId = launcherConfiguration.CashboxId!.Value; + + var dataProtector = dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE); + + clientEcdh = CashboxConfigEncryption.CreateCurve(); + var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); + + using var downloader = new ConfigurationDownloader(launcherConfiguration); + var exists = await downloader.DownloadConfigurationAsync(clientEcdh); + if (!exists) + { + throw new InvalidOperationException("Failed to download cashbox configuration."); + } + + cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } - return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + return await handler(options, + new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh, dataProtectionProvider), + specificOptions, host.Services.GetRequiredService()); } public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) From 9ba1d47f9ecdc3d3e8cf22cae1632a42664854c0 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Thu, 11 Jan 2024 22:20:02 +0100 Subject: [PATCH 02/31] Enhanced the Decrypt method in LauncherConfiguration to handle exceptions during the decryption process --- .../Configuration/Configuration.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs b/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs index 6f6f7232..1b282256 100644 --- a/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs +++ b/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs @@ -312,9 +312,16 @@ public void Decrypt(IDataProtector dataProtector) { MapFieldsWithAttribute((value) => { - if (value is null) { return null; } - - return dataProtector.Unprotect((string)value); + try + { + if (value is null) return null; + return dataProtector.Unprotect((string)value); + } + catch (Exception e) + { + Log.Warning($"Failed to decrypt field: {e.Message}"); + return null; + } }); } From e79e4709ad24e367e047d11b48ce20da0621eed5 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Thu, 11 Jan 2024 22:51:41 +0100 Subject: [PATCH 03/31] Enhance error handling in decryption of LauncherConfiguration --- .../Configuration/Configuration.cs | 2 +- src/fiskaltrust.Launcher/Commands/Common.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs b/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs index 1b282256..ea616d53 100644 --- a/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs +++ b/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs @@ -319,7 +319,7 @@ public void Decrypt(IDataProtector dataProtector) } catch (Exception e) { - Log.Warning($"Failed to decrypt field: {e.Message}"); + Log.Warning($"Failed to decrypt field: {e.Message}. Consider using 'config set' to reset."); return null; } }); diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 1237e36c..e5519948 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -234,12 +234,12 @@ public static async Task HandleAsync( try { - launcherConfiguration.Decrypt( - dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + launcherConfiguration.Decrypt + (dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); } catch (Exception e) { - Log.Warning(e, "Error decrypting launcher configuration. Attempting to regenerate and redownload."); + Log.Warning(e, "Error decrypting launcher configuration. Please check your configuration settings. If necessary, use 'config set' command to update your configuration."); var serviceFolder = launcherConfiguration.ServiceFolder!; var cashboxId = launcherConfiguration.CashboxId!.Value; From 73a3630738a3b31feb95a590f1eab133b05e6088 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Fri, 12 Jan 2024 21:07:37 +0100 Subject: [PATCH 04/31] Added log warning --- src/fiskaltrust.Launcher/Commands/DoctorCommand.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs b/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs index 9007e414..390f3975 100644 --- a/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs +++ b/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs @@ -90,7 +90,9 @@ public static async Task HandleAsync(CommonOptions commonOptions, CommonPro ftCashBoxConfiguration cashboxConfiguration = new(); if (clientEcdh is null) - { } + { + Log.Warning("Failed to load ECDH curve. Unable to proceed with Doctor checks."); + } else { using var downloader = new ConfigurationDownloader(launcherConfiguration); From d2951d652fa0301538da8701022ef9c497db0758 Mon Sep 17 00:00:00 2001 From: pvds <36538317+pawelvds@users.noreply.github.com> Date: Fri, 12 Jan 2024 21:27:33 +0100 Subject: [PATCH 05/31] Added try-catch block around ECDH curve loading --- src/fiskaltrust.Launcher/Commands/Common.cs | 75 +++++++++++++-------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index e5519948..b770b4d4 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -35,8 +35,10 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) if (addCliOnlyParameters) { - AddOption(new Option("--launcher-configuration-file", getDefaultValue: () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", getDefaultValue: () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--launcher-configuration-file", + getDefaultValue: () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", + getDefaultValue: () => Paths.LegacyConfigurationFileName)); AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); } } @@ -44,7 +46,8 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) public class CommonOptions { - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, + string legacyConfigurationFile, bool mergeLegacyConfigIfExists) { ArgsLauncherConfiguration = argsLauncherConfiguration; LauncherConfigurationFile = launcherConfigurationFile; @@ -60,7 +63,9 @@ public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string lau public record CommonProperties { - public CommonProperties(LauncherConfiguration launcherConfiguration, ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, IDataProtectionProvider dataProtectionProvider) + public CommonProperties(LauncherConfiguration launcherConfiguration, + ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, + IDataProtectionProvider dataProtectionProvider) { LauncherConfiguration = launcherConfiguration; CashboxConfiguration = cashboxConfiguration; @@ -239,12 +244,14 @@ public static async Task HandleAsync( } catch (Exception e) { - Log.Warning(e, "Error decrypting launcher configuration. Please check your configuration settings. If necessary, use 'config set' command to update your configuration."); + Log.Warning(e, + "Error decrypting launcher configuration. Please check your configuration settings. If necessary, use 'config set' command to update your configuration."); var serviceFolder = launcherConfiguration.ServiceFolder!; - var cashboxId = launcherConfiguration.CashboxId!.Value; + var cashboxId = launcherConfiguration.CashboxId!.Value; - var dataProtector = dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE); + var dataProtector = + dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE); clientEcdh = CashboxConfigEncryption.CreateCurve(); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); @@ -257,7 +264,9 @@ public static async Task HandleAsync( throw new InvalidOperationException("Failed to download cashbox configuration."); } - cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + cashboxConfiguration = + CashBoxConfigurationExt.Deserialize( + await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } @@ -266,42 +275,50 @@ public static async Task HandleAsync( specificOptions, host.Services.GetRequiredService()); } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, + bool useOffline = false, bool dryRun = false, bool useFallback = false) { Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) + .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - if (File.Exists(clientEcdhPath)) + try { - return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); + if (File.Exists(clientEcdhPath)) + { + return ECDiffieHellmanExt.Deserialize( + dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); + } } - else + catch (Exception e) { - const string offlineClientEcdhPath = "/client.ecdh"; - ECDiffieHellman clientEcdh; + Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); + } - if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) - { - clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); - try - { - File.Delete(offlineClientEcdhPath); - } - catch { } - } - else + const string offlineClientEcdhPath = "/client.ecdh"; + if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) + { + var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + try { - clientEcdh = CashboxConfigEncryption.CreateCurve(); + File.Delete(offlineClientEcdhPath); } - - if (!dryRun) + catch { - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); } return clientEcdh; } + + // Regenerating the curve if it's not loaded or in case of an error + var newClientEcdh = CashboxConfigEncryption.CreateCurve(); + if (!dryRun) + { + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); + } + + return newClientEcdh; } } } \ No newline at end of file From da46b84b6a185df53535be648a9e5c6e0e18da9d Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 22 Jan 2024 16:10:14 +0100 Subject: [PATCH 06/31] Updated Common.cs --- src/fiskaltrust.Launcher/Commands/Common.cs | 184 ++++++++++---------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index b770b4d4..9f80679d 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -1,5 +1,6 @@ using System.CommandLine; using System.CommandLine.Invocation; +using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text.Json; using fiskaltrust.Launcher.Common.Configuration; @@ -10,6 +11,7 @@ using fiskaltrust.Launcher.Extensions; using fiskaltrust.Launcher.Helpers; using fiskaltrust.Launcher.Logging; +using fiskaltrust.Launcher.ServiceInstallation; using fiskaltrust.storage.serialization.V0; using Microsoft.AspNetCore.DataProtection; using Serilog; @@ -35,10 +37,8 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) if (addCliOnlyParameters) { - AddOption(new Option("--launcher-configuration-file", - getDefaultValue: () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", - getDefaultValue: () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--launcher-configuration-file", getDefaultValue: () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", getDefaultValue: () => Paths.LegacyConfigurationFileName)); AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); } } @@ -46,8 +46,7 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) public class CommonOptions { - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, - string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, string legacyConfigurationFile, bool mergeLegacyConfigIfExists) { ArgsLauncherConfiguration = argsLauncherConfiguration; LauncherConfigurationFile = launcherConfigurationFile; @@ -63,9 +62,7 @@ public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string lau public record CommonProperties { - public CommonProperties(LauncherConfiguration launcherConfiguration, - ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, - IDataProtectionProvider dataProtectionProvider) + public CommonProperties(LauncherConfiguration launcherConfiguration, ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, IDataProtectionProvider dataProtectionProvider) { LauncherConfiguration = launcherConfiguration; CashboxConfiguration = cashboxConfiguration; @@ -87,6 +84,7 @@ public static async Task HandleAsync( IHost host, Func> handler) where S : notnull { + // Log messages will be save here and logged later when we have the configuration options to create the logger. var collectionSink = new CollectionSink(); Log.Logger = new LoggerConfiguration() .WriteTo.Sink(collectionSink) @@ -98,8 +96,7 @@ public static async Task HandleAsync( try { options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = - LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + launcherConfiguration = LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); } catch (Exception e) { @@ -107,19 +104,15 @@ public static async Task HandleAsync( { if (File.Exists(options.LauncherConfigurationFile)) { - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", - options.LauncherConfigurationFile); + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", options.LauncherConfigurationFile); } else { - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", - options.LauncherConfigurationFile); + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", options.LauncherConfigurationFile); } - Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); } } - Log.Verbose("Merging legacy launcher config file."); if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) { @@ -141,9 +134,9 @@ public static async Task HandleAsync( Log.Verbose("Merging launcher cli args."); launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); + await EnsureServiceDirectoryExists(launcherConfiguration); - if (!launcherConfiguration.UseOffline!.Value && - (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) + if (!launcherConfiguration.UseOffline!.Value && (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) { Log.Error("CashBoxId and AccessToken are not provided."); } @@ -164,8 +157,7 @@ public static async Task HandleAsync( ECDiffieHellman? clientEcdh = null; try { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, - launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); using var downloader = new ConfigurationDownloader(launcherConfiguration); var exists = await downloader.DownloadConfigurationAsync(clientEcdh); if (launcherConfiguration.UseOffline!.Value && !exists) @@ -176,13 +168,11 @@ public static async Task HandleAsync( catch (Exception e) { var message = "Could not download Cashbox configuration. "; - message += - $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; + message += $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; if (!launcherConfiguration.Sandbox!.Value) { message += " Did you forget the --sandbox flag?"; } - message += ")"; Log.Error(e, message); } @@ -190,32 +180,30 @@ public static async Task HandleAsync( try { var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; - launcherConfiguration.OverwriteWith( - LauncherConfigurationInCashBoxConfiguration.Deserialize( - await File.ReadAllTextAsync(cashboxConfigurationFile))); + launcherConfiguration.OverwriteWith(LauncherConfigurationInCashBoxConfiguration.Deserialize(await File.ReadAllTextAsync(cashboxConfigurationFile))); } catch (Exception e) { + // will exit with non-zero exit code later. Log.Fatal(e, "Could not read Cashbox configuration file."); } var cashboxConfiguration = new ftCashBoxConfiguration(); try { - cashboxConfiguration = - CashBoxConfigurationExt.Deserialize( - await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } catch (Exception e) { + // will exit with non-zero exit code later. Log.Fatal(e, "Could not parse Cashbox configuration."); } + // Previous log messages will be logged here using this logger. Log.Logger = new LoggerConfiguration() .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, - new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .AddFileLoggingConfiguration(launcherConfiguration, new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) .Enrich.FromLogContext() .CreateLogger(); @@ -224,101 +212,113 @@ public static async Task HandleAsync( Log.Write(logEvent); } + // If any critical errors occured, we exit with a non-zero exit code. + // In many cases we don't want to immediately exit the application, + // but we want to log the error and continue and see what else is going on before we exit. if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) { return 1; } Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); - Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", - launcherConfiguration.CashboxConfigurationFile); + Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, - useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); try { - launcherConfiguration.Decrypt - (dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + launcherConfiguration.Decrypt(dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); } catch (Exception e) { - Log.Warning(e, - "Error decrypting launcher configuration. Please check your configuration settings. If necessary, use 'config set' command to update your configuration."); - - var serviceFolder = launcherConfiguration.ServiceFolder!; - var cashboxId = launcherConfiguration.CashboxId!.Value; - - var dataProtector = - dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE); + Log.Warning(e, "Error decrypring launcher configuration file."); + } - clientEcdh = CashboxConfigEncryption.CreateCurve(); - var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); + return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + } - using var downloader = new ConfigurationDownloader(launcherConfiguration); - var exists = await downloader.DownloadConfigurationAsync(clientEcdh); - if (!exists) + private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) + { + var serviceDirectory = config.ServiceFolder; + try + { + if (!Directory.Exists(serviceDirectory)) { - throw new InvalidOperationException("Failed to download cashbox configuration."); - } + Directory.CreateDirectory(serviceDirectory); - cashboxConfiguration = - CashBoxConfigurationExt.Deserialize( - await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + var user = Environment.GetEnvironmentVariable("USER"); + if (!string.IsNullOrEmpty(user)) + { + var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, LogEventLevel.Debug); + if (chownResult.exitCode != 0) + { + Log.Warning("Failed to change owner of the service directory."); + } + + var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, LogEventLevel.Debug); + if (chmodResult.exitCode != 0) + { + Log.Warning("Failed to change permissions of the service directory."); + } + } + else + { + Log.Warning("Service user name is not set. Owner of the service directory will not be changed."); + } + } + else + { + Log.Debug("Changing owner and permissions is skipped on non-Unix operating systems."); + } + } + } + catch (UnauthorizedAccessException e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", serviceDirectory); } - - return await handler(options, - new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh, dataProtectionProvider), - specificOptions, host.Services.GetRequiredService()); } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, - bool useOffline = false, bool dryRun = false, bool useFallback = false) + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) { Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) - .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - try + if (File.Exists(clientEcdhPath)) { - if (File.Exists(clientEcdhPath)) - { - return ECDiffieHellmanExt.Deserialize( - dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); - } + return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); } - catch (Exception e) + else { - Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); - } + const string offlineClientEcdhPath = "/client.ecdh"; + ECDiffieHellman clientEcdh; - const string offlineClientEcdhPath = "/client.ecdh"; - if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) - { - var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); - try + if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) { - File.Delete(offlineClientEcdhPath); + clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + try + { + File.Delete(offlineClientEcdhPath); + } + catch { } } - catch + else { + clientEcdh = CashboxConfigEncryption.CreateCurve(); } - return clientEcdh; - } + if (!dryRun) + { + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); + } - // Regenerating the curve if it's not loaded or in case of an error - var newClientEcdh = CashboxConfigEncryption.CreateCurve(); - if (!dryRun) - { - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); + return clientEcdh; } - - return newClientEcdh; } } -} \ No newline at end of file +} From 4d66c72631aaaaaf8b22bdad432078872efcaf95 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Tue, 23 Jan 2024 11:23:17 +0100 Subject: [PATCH 07/31] Enhanced resilience in LoadCurve with error handling and automatic regeneration of ECDH curve --- src/fiskaltrust.Launcher/Commands/Common.cs | 45 ++++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 9f80679d..07b6727c 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -283,41 +283,46 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con } } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) - { - Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); - var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - - if (File.Exists(clientEcdhPath)) - { - return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); - } - else + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) { - const string offlineClientEcdhPath = "/client.ecdh"; - ECDiffieHellman clientEcdh; + Log.Verbose("Loading Curve."); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); + + try + { + if (File.Exists(clientEcdhPath)) + { + return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); + } + } + catch (Exception e) + { + Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); + } + // Handling offline client ECDH path + const string offlineClientEcdhPath = "/client.ecdh"; if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) { - clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); try { File.Delete(offlineClientEcdhPath); } catch { } - } - else - { - clientEcdh = CashboxConfigEncryption.CreateCurve(); + + return clientEcdh; } + // Regenerating the curve if it's not loaded or in case of an error + var newClientEcdh = CashboxConfigEncryption.CreateCurve(); if (!dryRun) { - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); } - return clientEcdh; + return newClientEcdh; } } } From 8925726f75c2105bd36a88b21120fb66e71284be Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Tue, 23 Jan 2024 12:27:15 +0100 Subject: [PATCH 08/31] Resolved merge conflict --- src/fiskaltrust.Launcher/Commands/Common.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 07b6727c..fa1a7ad1 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -301,28 +301,28 @@ public static async Task LoadCurve(Guid cashboxId, string acces Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); } - // Handling offline client ECDH path + // Handling offline client ECDH path and regenerating curve logic + ECDiffieHellman clientEcdh = CashboxConfigEncryption.CreateCurve(); const string offlineClientEcdhPath = "/client.ecdh"; if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) { - var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); try { + clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); File.Delete(offlineClientEcdhPath); } - catch { } - - return clientEcdh; + catch (Exception ex) + { + Log.Warning($"Failed to use offline ECDH curve: {ex.Message}"); + } } - // Regenerating the curve if it's not loaded or in case of an error - var newClientEcdh = CashboxConfigEncryption.CreateCurve(); if (!dryRun) { - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); } - return newClientEcdh; + return clientEcdh; } } } From d867424b1de01e737f9bed3899efb50fa163b4ad Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Tue, 23 Jan 2024 12:40:19 +0100 Subject: [PATCH 09/31] push --- src/fiskaltrust.Launcher/Commands/Common.cs | 43 +++++++++------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index fa1a7ad1..9f80679d 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -283,38 +283,33 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con } } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) - { - Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); - var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - - try - { - if (File.Exists(clientEcdhPath)) - { - return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); - } - } - catch (Exception e) - { - Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); - } + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) + { + Log.Verbose("Loading Curve."); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - // Handling offline client ECDH path and regenerating curve logic - ECDiffieHellman clientEcdh = CashboxConfigEncryption.CreateCurve(); + if (File.Exists(clientEcdhPath)) + { + return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); + } + else + { const string offlineClientEcdhPath = "/client.ecdh"; + ECDiffieHellman clientEcdh; + if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) { + clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); try { - clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); File.Delete(offlineClientEcdhPath); } - catch (Exception ex) - { - Log.Warning($"Failed to use offline ECDH curve: {ex.Message}"); - } + catch { } + } + else + { + clientEcdh = CashboxConfigEncryption.CreateCurve(); } if (!dryRun) From a58571d84aba7b78365bf614fc49b1abfa831c39 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Tue, 23 Jan 2024 13:19:06 +0100 Subject: [PATCH 10/31] Handle curve loading and decryption errors in LoadCurve --- src/fiskaltrust.Launcher/Commands/Common.cs | 46 +++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 9f80679d..42cbedc0 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -289,36 +289,38 @@ public static async Task LoadCurve(Guid cashboxId, string acces var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - if (File.Exists(clientEcdhPath)) - { - return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); - } - else + try { - const string offlineClientEcdhPath = "/client.ecdh"; - ECDiffieHellman clientEcdh; - - if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) + if (File.Exists(clientEcdhPath)) { - clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + var protectedData = await File.ReadAllTextAsync(clientEcdhPath); try { - File.Delete(offlineClientEcdhPath); + return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(protectedData)); + } + catch (Exception ex) + { + Log.Warning($"Could not decrypt ECDH curve, regenerating a new one. Error: {ex.Message}"); + // Handle failed decryption here if necessary, e.g., by deleting the existing file + // File.Delete(clientEcdhPath); } - catch { } - } - else - { - clientEcdh = CashboxConfigEncryption.CreateCurve(); - } - - if (!dryRun) - { - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); } + } + catch (Exception ex) + { + Log.Warning($"Error reading ECDH curve from file: {ex.Message}. Regenerating new curve."); + } - return clientEcdh; + // Rest of the method for regenerating curve if not loaded or in case of error + ECDiffieHellman clientEcdh = CashboxConfigEncryption.CreateCurve(); + if (!dryRun) + { + var serializedCurve = clientEcdh.Serialize(); + var protectedCurve = dataProtector.Protect(serializedCurve); + await File.WriteAllTextAsync(clientEcdhPath, protectedCurve); } + + return clientEcdh; } } } From f13409a526b555bf71be3668fa34b1ded788eb4d Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Tue, 23 Jan 2024 16:26:53 +0100 Subject: [PATCH 11/31] Changes related to suggestions from review --- .../Configuration/Configuration.cs | 31 +++++++------ src/fiskaltrust.Launcher/Commands/Common.cs | 46 ++++++++++--------- .../Commands/DoctorCommand.cs | 2 +- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs b/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs index ea616d53..d0c89a31 100644 --- a/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs +++ b/src/fiskaltrust.Launcher.Common/Configuration/Configuration.cs @@ -270,20 +270,20 @@ internal void SetAlternateNames(string text) } } } - - private void MapFieldsWithAttribute(Func action) + private void MapFieldsWithAttribute(Func action) { var errors = new List(); foreach (var field in GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) { var value = field.GetValue(this); + var name = field.Name; - if (field.GetCustomAttributes(typeof(T)).Any()) + if (field.GetCustomAttributes(typeof(T), false).Any()) { try { - field.SetValue(this, action(value)); + field.SetValue(this, action(value, name)); } catch (Exception e) { @@ -297,20 +297,26 @@ private void MapFieldsWithAttribute(Func action) throw new AggregateException(errors); } } - public void Encrypt(IDataProtector dataProtector) { - MapFieldsWithAttribute(value => + MapFieldsWithAttribute((value, name) => { - if (value is null) { return null; } + if (value is null) return null; - return dataProtector.Protect((string)value); + try + { + return dataProtector.Protect((string)value); + } + catch (Exception e) + { + Log.Warning($"Failed to encrypt value of configuration field {name}. Consider using the 'config set' command to set the field's value.", name); + return null; + } }); } - public void Decrypt(IDataProtector dataProtector) { - MapFieldsWithAttribute((value) => + MapFieldsWithAttribute((value, name) => { try { @@ -319,7 +325,7 @@ public void Decrypt(IDataProtector dataProtector) } catch (Exception e) { - Log.Warning($"Failed to decrypt field: {e.Message}. Consider using 'config set' to reset."); + Log.Warning("Failed to decrypt value of configuration field {name}. Consider using the 'config set' command to set the fields value.", name); return null; } }); @@ -335,7 +341,6 @@ public void Decrypt(IDataProtector dataProtector) return null; } } - public record LauncherConfigurationInCashBoxConfiguration { [JsonPropertyName("launcher")] @@ -356,4 +361,4 @@ public record LauncherConfigurationInCashBoxConfiguration return configuration; } } -} +} \ No newline at end of file diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 42cbedc0..ab979991 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -289,38 +289,40 @@ public static async Task LoadCurve(Guid cashboxId, string acces var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - try + if (File.Exists(clientEcdhPath)) { - if (File.Exists(clientEcdhPath)) + try { - var protectedData = await File.ReadAllTextAsync(clientEcdhPath); - try - { - return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(protectedData)); - } - catch (Exception ex) - { - Log.Warning($"Could not decrypt ECDH curve, regenerating a new one. Error: {ex.Message}"); - // Handle failed decryption here if necessary, e.g., by deleting the existing file - // File.Delete(clientEcdhPath); - } + return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); + } + catch (Exception e) + { + Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); } } - catch (Exception ex) + + // Handling offline client ECDH path + const string offlineClientEcdhPath = "/client.ecdh"; + if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) { - Log.Warning($"Error reading ECDH curve from file: {ex.Message}. Regenerating new curve."); + var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + try + { + File.Delete(offlineClientEcdhPath); + } + catch { } + + return clientEcdh; } - // Rest of the method for regenerating curve if not loaded or in case of error - ECDiffieHellman clientEcdh = CashboxConfigEncryption.CreateCurve(); + // Regenerating the curve if it's not loaded or in case of an error + var newClientEcdh = CashboxConfigEncryption.CreateCurve(); if (!dryRun) { - var serializedCurve = clientEcdh.Serialize(); - var protectedCurve = dataProtector.Protect(serializedCurve); - await File.WriteAllTextAsync(clientEcdhPath, protectedCurve); + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); } - return clientEcdh; + return newClientEcdh; } } -} +} \ No newline at end of file diff --git a/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs b/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs index 390f3975..357811fc 100644 --- a/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs +++ b/src/fiskaltrust.Launcher/Commands/DoctorCommand.cs @@ -91,7 +91,7 @@ public static async Task HandleAsync(CommonOptions commonOptions, CommonPro if (clientEcdh is null) { - Log.Warning("Failed to load ECDH curve. Unable to proceed with Doctor checks."); + Log.Warning("Failed to load ECDH curve. Skipping some related doctor checks."); } else { From 325a927a6bf0ceb4dff2f1452403b2f4d45a7bf0 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 14:27:06 +0100 Subject: [PATCH 12/31] Fixed Common.cs --- src/fiskaltrust.Launcher/Commands/Common.cs | 22 ++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index ab979991..b387f959 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -157,14 +157,26 @@ public static async Task HandleAsync( ECDiffieHellman? clientEcdh = null; try { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); - using var downloader = new ConfigurationDownloader(launcherConfiguration); - var exists = await downloader.DownloadConfigurationAsync(clientEcdh); - if (launcherConfiguration.UseOffline!.Value && !exists) + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + } + catch (Exception e) + { + Log.Fatal(e, "Could not load client curve."); + } + + try + { + if (clientEcdh is not null) { - Log.Warning("Cashbox configuration was not downloaded because UseOffline is set."); + using var downloader = new ConfigurationDownloader(launcherConfiguration); + var exists = await downloader.DownloadConfigurationAsync(clientEcdh); + if (launcherConfiguration.UseOffline!.Value && !exists) + { + Log.Warning("Cashbox configuration was not downloaded because UseOffline is set."); + } } } + catch (Exception e) { var message = "Could not download Cashbox configuration. "; From d176c14d1bf5fb79a8157056101c5104e4a1930e Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 15:04:42 +0100 Subject: [PATCH 13/31] fix --- src/fiskaltrust.Launcher/Commands/Common.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index b387f959..41bdb8b4 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -176,7 +176,6 @@ public static async Task HandleAsync( } } } - catch (Exception e) { var message = "Could not download Cashbox configuration. "; From f8992d0c8cd9188982d04c679829d2593e9d0631 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 15:13:10 +0100 Subject: [PATCH 14/31] Another try fix --- src/fiskaltrust.Launcher/Commands/Common.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 41bdb8b4..a4379010 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -203,7 +203,7 @@ public static async Task HandleAsync( try { cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); + if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } } catch (Exception e) { @@ -235,6 +235,7 @@ public static async Task HandleAsync( Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); + Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); @@ -247,12 +248,12 @@ public static async Task HandleAsync( Log.Warning(e, "Error decrypring launcher configuration file."); } - return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); } private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) { - var serviceDirectory = config.ServiceFolder; + var serviceDirectory = config.ServiceFolder!; try { if (!Directory.Exists(serviceDirectory)) @@ -333,7 +334,8 @@ public static async Task LoadCurve(Guid cashboxId, string acces await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); } - return newClientEcdh; + return clientEcdh; + } } } -} \ No newline at end of file +} From 2119715fc09aac0d3c95cf906d81452260d14988 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 15:27:04 +0100 Subject: [PATCH 15/31] f --- src/fiskaltrust.Launcher/Commands/Common.cs | 100 ++++++++++++++------ 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index a4379010..80cdd809 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -37,8 +37,10 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) if (addCliOnlyParameters) { - AddOption(new Option("--launcher-configuration-file", getDefaultValue: () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", getDefaultValue: () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--launcher-configuration-file", + getDefaultValue: () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", + getDefaultValue: () => Paths.LegacyConfigurationFileName)); AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); } } @@ -46,7 +48,8 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) public class CommonOptions { - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, + string legacyConfigurationFile, bool mergeLegacyConfigIfExists) { ArgsLauncherConfiguration = argsLauncherConfiguration; LauncherConfigurationFile = launcherConfigurationFile; @@ -62,7 +65,9 @@ public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string lau public record CommonProperties { - public CommonProperties(LauncherConfiguration launcherConfiguration, ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, IDataProtectionProvider dataProtectionProvider) + public CommonProperties(LauncherConfiguration launcherConfiguration, + ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, + IDataProtectionProvider dataProtectionProvider) { LauncherConfiguration = launcherConfiguration; CashboxConfiguration = cashboxConfiguration; @@ -96,7 +101,8 @@ public static async Task HandleAsync( try { options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + launcherConfiguration = + LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); } catch (Exception e) { @@ -104,15 +110,19 @@ public static async Task HandleAsync( { if (File.Exists(options.LauncherConfigurationFile)) { - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", options.LauncherConfigurationFile); + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", + options.LauncherConfigurationFile); } else { - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", options.LauncherConfigurationFile); + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", + options.LauncherConfigurationFile); } + Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); } } + Log.Verbose("Merging legacy launcher config file."); if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) { @@ -136,7 +146,8 @@ public static async Task HandleAsync( launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); await EnsureServiceDirectoryExists(launcherConfiguration); - if (!launcherConfiguration.UseOffline!.Value && (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) + if (!launcherConfiguration.UseOffline!.Value && + (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) { Log.Error("CashBoxId and AccessToken are not provided."); } @@ -157,7 +168,8 @@ public static async Task HandleAsync( ECDiffieHellman? clientEcdh = null; try { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, + launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); } catch (Exception e) { @@ -179,11 +191,13 @@ public static async Task HandleAsync( catch (Exception e) { var message = "Could not download Cashbox configuration. "; - message += $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; + message += + $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; if (!launcherConfiguration.Sandbox!.Value) { message += " Did you forget the --sandbox flag?"; } + message += ")"; Log.Error(e, message); } @@ -191,7 +205,9 @@ public static async Task HandleAsync( try { var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; - launcherConfiguration.OverwriteWith(LauncherConfigurationInCashBoxConfiguration.Deserialize(await File.ReadAllTextAsync(cashboxConfigurationFile))); + launcherConfiguration.OverwriteWith( + LauncherConfigurationInCashBoxConfiguration.Deserialize( + await File.ReadAllTextAsync(cashboxConfigurationFile))); } catch (Exception e) { @@ -202,8 +218,13 @@ public static async Task HandleAsync( var cashboxConfiguration = new ftCashBoxConfiguration(); try { - cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } + cashboxConfiguration = + CashBoxConfigurationExt.Deserialize( + await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + if (clientEcdh is not null) + { + cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); + } } catch (Exception e) { @@ -214,7 +235,8 @@ public static async Task HandleAsync( // Previous log messages will be logged here using this logger. Log.Logger = new LoggerConfiguration() .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .AddFileLoggingConfiguration(launcherConfiguration, + new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) .Enrich.FromLogContext() .CreateLogger(); @@ -232,23 +254,29 @@ public static async Task HandleAsync( } Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); - Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); + Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", + launcherConfiguration.CashboxConfigurationFile); Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); - Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); + Log.Debug("Launcher running as {ServiceType}", + Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, + useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); try { - launcherConfiguration.Decrypt(dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + launcherConfiguration.Decrypt( + dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); } catch (Exception e) { Log.Warning(e, "Error decrypring launcher configuration file."); } - return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + return await handler(options, + new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), + specificOptions, host.Services.GetRequiredService()); } private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) @@ -260,18 +288,21 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con { Directory.CreateDirectory(serviceDirectory); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var user = Environment.GetEnvironmentVariable("USER"); if (!string.IsNullOrEmpty(user)) { - var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, LogEventLevel.Debug); + var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, + LogEventLevel.Debug); if (chownResult.exitCode != 0) { Log.Warning("Failed to change owner of the service directory."); } - var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, LogEventLevel.Debug); + var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, + LogEventLevel.Debug); if (chmodResult.exitCode != 0) { Log.Warning("Failed to change permissions of the service directory."); @@ -279,7 +310,8 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con } else { - Log.Warning("Service user name is not set. Owner of the service directory will not be changed."); + Log.Warning( + "Service user name is not set. Owner of the service directory will not be changed."); } } else @@ -291,21 +323,26 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con catch (UnauthorizedAccessException e) { // will exit with non-zero exit code later. - Log.Fatal(e, "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", serviceDirectory); + Log.Fatal(e, + "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", + serviceDirectory); } } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, + bool useOffline = false, bool dryRun = false, bool useFallback = false) { Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) + .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); if (File.Exists(clientEcdhPath)) { try { - return ECDiffieHellmanExt.Deserialize(dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); + return ECDiffieHellmanExt.Deserialize( + dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); } catch (Exception e) { @@ -322,7 +359,9 @@ public static async Task LoadCurve(Guid cashboxId, string acces { File.Delete(offlineClientEcdhPath); } - catch { } + catch + { + } return clientEcdh; } @@ -334,8 +373,7 @@ public static async Task LoadCurve(Guid cashboxId, string acces await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); } - return clientEcdh; - } + return clientEcdh; } } -} +} \ No newline at end of file From e5d0842a9d56bc107ff25a3f4cd0ceebf8304f78 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 15:35:24 +0100 Subject: [PATCH 16/31] ff --- src/fiskaltrust.Launcher/Commands/Common.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 80cdd809..d4e92938 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -168,8 +168,7 @@ public static async Task HandleAsync( ECDiffieHellman? clientEcdh = null; try { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, - launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); } catch (Exception e) { From 55afd78a9a59dbf68bfd413c6cab263c9a701b35 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 15:41:15 +0100 Subject: [PATCH 17/31] fix conflicts --- src/fiskaltrust.Launcher/Commands/Common.cs | 63 +++++++++++++++++---- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index d4e92938..b2877fb9 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -217,13 +217,8 @@ public static async Task HandleAsync( var cashboxConfiguration = new ftCashBoxConfiguration(); try { - cashboxConfiguration = - CashBoxConfigurationExt.Deserialize( - await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - if (clientEcdh is not null) - { - cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); - } + cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } } catch (Exception e) { @@ -257,8 +252,7 @@ public static async Task HandleAsync( launcherConfiguration.CashboxConfigurationFile); Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); - Log.Debug("Launcher running as {ServiceType}", - Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); + Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); @@ -273,9 +267,54 @@ public static async Task HandleAsync( Log.Warning(e, "Error decrypring launcher configuration file."); } - return await handler(options, - new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), - specificOptions, host.Services.GetRequiredService()); + return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + } + + private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) + { + var serviceDirectory = config.ServiceFolder!; + try + { + if (!Directory.Exists(serviceDirectory)) + { + Directory.CreateDirectory(serviceDirectory); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + var user = Environment.GetEnvironmentVariable("USER"); + if (!string.IsNullOrEmpty(user)) + { + var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, LogEventLevel.Debug); + if (chownResult.exitCode != 0) + { + Log.Warning("Failed to change owner of the service directory."); + } + + var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, LogEventLevel.Debug); + if (chmodResult.exitCode != 0) + { + Log.Warning("Failed to change permissions of the service directory."); + } + } + else + { + Log.Warning( + "Service user name is not set. Owner of the service directory will not be changed."); + } + } + else + { + Log.Debug("Changing owner and permissions is skipped on non-Unix operating systems."); + } + } + } + catch (UnauthorizedAccessException e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, + "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", serviceDirectory); + } } private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) From 25422dab3ffaee8ccee4f9e445f52595796056c9 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 15:44:24 +0100 Subject: [PATCH 18/31] fff --- src/fiskaltrust.Launcher/Commands/Common.cs | 52 +-------------------- 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index b2877fb9..17ef7654 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -316,57 +316,7 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", serviceDirectory); } } - - private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) - { - var serviceDirectory = config.ServiceFolder!; - try - { - if (!Directory.Exists(serviceDirectory)) - { - Directory.CreateDirectory(serviceDirectory); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - var user = Environment.GetEnvironmentVariable("USER"); - if (!string.IsNullOrEmpty(user)) - { - var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, - LogEventLevel.Debug); - if (chownResult.exitCode != 0) - { - Log.Warning("Failed to change owner of the service directory."); - } - - var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, - LogEventLevel.Debug); - if (chmodResult.exitCode != 0) - { - Log.Warning("Failed to change permissions of the service directory."); - } - } - else - { - Log.Warning( - "Service user name is not set. Owner of the service directory will not be changed."); - } - } - else - { - Log.Debug("Changing owner and permissions is skipped on non-Unix operating systems."); - } - } - } - catch (UnauthorizedAccessException e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, - "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", - serviceDirectory); - } - } - + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) { From 0bb99c27930b67eb7a114d2ac8a562acedf6f99a Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 15:56:37 +0100 Subject: [PATCH 19/31] Refactor Common.cs for improved readability --- src/fiskaltrust.Launcher/Commands/Common.cs | 539 ++++++++++---------- 1 file changed, 257 insertions(+), 282 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 17ef7654..825a5b3c 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -17,351 +17,326 @@ using Serilog; using Serilog.Events; -namespace fiskaltrust.Launcher.Commands -{ - public record SubArguments(IEnumerable Args); +namespace fiskaltrust.Launcher.Commands; + +public record SubArguments(IEnumerable Args); - public class CommonCommand : Command +public class CommonCommand : Command +{ + public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) { - public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) - { - AddOption(new Option("--cashbox-id")); - AddOption(new Option("--access-token")); - AddOption(new Option("--sandbox")); - AddOption(new Option("--log-folder")); + AddOption(new Option("--cashbox-id")); + AddOption(new Option("--access-token")); + AddOption(new Option("--sandbox")); + AddOption(new Option("--log-folder")); - var logLevelOption = new Option("--log-level", "Set the log level of the application."); - logLevelOption.AddAlias("-v"); - logLevelOption.AddAlias("--verbosity"); - AddOption(logLevelOption); + var logLevelOption = new Option("--log-level", "Set the log level of the application."); + logLevelOption.AddAlias("-v"); + logLevelOption.AddAlias("--verbosity"); + AddOption(logLevelOption); - if (addCliOnlyParameters) - { - AddOption(new Option("--launcher-configuration-file", - getDefaultValue: () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", - getDefaultValue: () => Paths.LegacyConfigurationFileName)); - AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); - } + if (addCliOnlyParameters) + { + AddOption(new Option("--launcher-configuration-file", + () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", + () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--merge-legacy-config-if-exists", () => true)); } } +} - public class CommonOptions +public class CommonOptions +{ + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, + string legacyConfigurationFile, bool mergeLegacyConfigIfExists) { - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, - string legacyConfigurationFile, bool mergeLegacyConfigIfExists) - { - ArgsLauncherConfiguration = argsLauncherConfiguration; - LauncherConfigurationFile = launcherConfigurationFile; - LegacyConfigurationFile = legacyConfigurationFile; - MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; - } - - public LauncherConfiguration ArgsLauncherConfiguration { get; set; } - public string LauncherConfigurationFile { get; set; } - public string LegacyConfigurationFile { get; set; } - public bool MergeLegacyConfigIfExists { get; set; } + ArgsLauncherConfiguration = argsLauncherConfiguration; + LauncherConfigurationFile = launcherConfigurationFile; + LegacyConfigurationFile = legacyConfigurationFile; + MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; } - public record CommonProperties - { - public CommonProperties(LauncherConfiguration launcherConfiguration, - ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, - IDataProtectionProvider dataProtectionProvider) - { - LauncherConfiguration = launcherConfiguration; - CashboxConfiguration = cashboxConfiguration; - ClientEcdh = clientEcdh; - DataProtectionProvider = dataProtectionProvider; - } + public LauncherConfiguration ArgsLauncherConfiguration { get; set; } + public string LauncherConfigurationFile { get; set; } + public string LegacyConfigurationFile { get; set; } + public bool MergeLegacyConfigIfExists { get; set; } +} - public LauncherConfiguration LauncherConfiguration { get; set; } - public ftCashBoxConfiguration CashboxConfiguration { get; set; } - public ECDiffieHellman ClientEcdh { get; set; } - public IDataProtectionProvider DataProtectionProvider { get; set; } +public record CommonProperties +{ + public CommonProperties(LauncherConfiguration launcherConfiguration, + ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, + IDataProtectionProvider dataProtectionProvider) + { + LauncherConfiguration = launcherConfiguration; + CashboxConfiguration = cashboxConfiguration; + ClientEcdh = clientEcdh; + DataProtectionProvider = dataProtectionProvider; } - public static class CommonHandler + public LauncherConfiguration LauncherConfiguration { get; set; } + public ftCashBoxConfiguration CashboxConfiguration { get; set; } + public ECDiffieHellman ClientEcdh { get; set; } + public IDataProtectionProvider DataProtectionProvider { get; set; } +} + +public static class CommonHandler +{ + public static async Task HandleAsync( + CommonOptions options, + O specificOptions, + IHost host, + Func> handler) where S : notnull { - public static async Task HandleAsync( - CommonOptions options, - O specificOptions, - IHost host, - Func> handler) where S : notnull - { - // Log messages will be save here and logged later when we have the configuration options to create the logger. - var collectionSink = new CollectionSink(); - Log.Logger = new LoggerConfiguration() - .WriteTo.Sink(collectionSink) - .CreateLogger(); + // Log messages will be save here and logged later when we have the configuration options to create the logger. + var collectionSink = new CollectionSink(); + Log.Logger = new LoggerConfiguration() + .WriteTo.Sink(collectionSink) + .CreateLogger(); - var launcherConfiguration = new LauncherConfiguration(); + var launcherConfiguration = new LauncherConfiguration(); - Log.Verbose("Reading launcher config file."); - try + Log.Verbose("Reading launcher config file."); + try + { + options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); + launcherConfiguration = + LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + } + catch (Exception e) + { + if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) { - options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = - LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + if (File.Exists(options.LauncherConfigurationFile)) + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", + options.LauncherConfigurationFile); + else + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", + options.LauncherConfigurationFile); + + Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); } - catch (Exception e) - { - if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) - { - if (File.Exists(options.LauncherConfigurationFile)) - { - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", - options.LauncherConfigurationFile); - } - else - { - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", - options.LauncherConfigurationFile); - } + } - Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); - } - } + Log.Verbose("Merging legacy launcher config file."); + if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) + { + var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); + launcherConfiguration.OverwriteWith(legacyConfig); - Log.Verbose("Merging legacy launcher config file."); - if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) - { - var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); - launcherConfiguration.OverwriteWith(legacyConfig); + var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); + if (configFileDirectory is not null) Directory.CreateDirectory(configFileDirectory); - var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); - if (configFileDirectory is not null) - { - Directory.CreateDirectory(configFileDirectory); - } + await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); - await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); + var fi = new FileInfo(options.LegacyConfigurationFile); + fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); + fi.Delete(); + } - var fi = new FileInfo(options.LegacyConfigurationFile); - fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); - fi.Delete(); - } + Log.Verbose("Merging launcher cli args."); + launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); + await EnsureServiceDirectoryExists(launcherConfiguration); - Log.Verbose("Merging launcher cli args."); - launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); - await EnsureServiceDirectoryExists(launcherConfiguration); + if (!launcherConfiguration.UseOffline!.Value && + (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) + Log.Error("CashBoxId and AccessToken are not provided."); - if (!launcherConfiguration.UseOffline!.Value && - (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) - { - Log.Error("CashBoxId and AccessToken are not provided."); - } - - try - { - var configFileDirectory = Path.GetDirectoryName(launcherConfiguration.CashboxConfigurationFile); - if (configFileDirectory is not null) - { - Directory.CreateDirectory(configFileDirectory); - } - } - catch (Exception e) - { - Log.Error(e, "Could not create cashbox-configuration-file folder."); - } + try + { + var configFileDirectory = Path.GetDirectoryName(launcherConfiguration.CashboxConfigurationFile); + if (configFileDirectory is not null) Directory.CreateDirectory(configFileDirectory); + } + catch (Exception e) + { + Log.Error(e, "Could not create cashbox-configuration-file folder."); + } - ECDiffieHellman? clientEcdh = null; - try - { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); - } - catch (Exception e) - { - Log.Fatal(e, "Could not load client curve."); - } + ECDiffieHellman? clientEcdh = null; + try + { + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, + launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + } + catch (Exception e) + { + Log.Fatal(e, "Could not load client curve."); + } - try - { - if (clientEcdh is not null) - { - using var downloader = new ConfigurationDownloader(launcherConfiguration); - var exists = await downloader.DownloadConfigurationAsync(clientEcdh); - if (launcherConfiguration.UseOffline!.Value && !exists) - { - Log.Warning("Cashbox configuration was not downloaded because UseOffline is set."); - } - } - } - catch (Exception e) + try + { + if (clientEcdh is not null) { - var message = "Could not download Cashbox configuration. "; - message += - $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; - if (!launcherConfiguration.Sandbox!.Value) - { - message += " Did you forget the --sandbox flag?"; - } - - message += ")"; - Log.Error(e, message); + using var downloader = new ConfigurationDownloader(launcherConfiguration); + var exists = await downloader.DownloadConfigurationAsync(clientEcdh); + if (launcherConfiguration.UseOffline!.Value && !exists) + Log.Warning("Cashbox configuration was not downloaded because UseOffline is set."); } + } + catch (Exception e) + { + var message = "Could not download Cashbox configuration. "; + message += + $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; + if (!launcherConfiguration.Sandbox!.Value) message += " Did you forget the --sandbox flag?"; - try - { - var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; - launcherConfiguration.OverwriteWith( - LauncherConfigurationInCashBoxConfiguration.Deserialize( - await File.ReadAllTextAsync(cashboxConfigurationFile))); - } - catch (Exception e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, "Could not read Cashbox configuration file."); - } + message += ")"; + Log.Error(e, message); + } - var cashboxConfiguration = new ftCashBoxConfiguration(); - try - { - cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } - } - catch (Exception e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, "Could not parse Cashbox configuration."); - } + try + { + var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; + launcherConfiguration.OverwriteWith( + LauncherConfigurationInCashBoxConfiguration.Deserialize( + await File.ReadAllTextAsync(cashboxConfigurationFile))); + } + catch (Exception e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Could not read Cashbox configuration file."); + } - // Previous log messages will be logged here using this logger. - Log.Logger = new LoggerConfiguration() - .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, - new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) - .Enrich.FromLogContext() - .CreateLogger(); + var cashboxConfiguration = new ftCashBoxConfiguration(); + try + { + cashboxConfiguration = + CashBoxConfigurationExt.Deserialize( + await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + if (clientEcdh is not null) cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); + } + catch (Exception e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Could not parse Cashbox configuration."); + } - foreach (var logEvent in collectionSink.Events) - { - Log.Write(logEvent); - } + // Previous log messages will be logged here using this logger. + Log.Logger = new LoggerConfiguration() + .AddLoggingConfiguration(launcherConfiguration) + .AddFileLoggingConfiguration(launcherConfiguration, + new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .Enrich.FromLogContext() + .CreateLogger(); - // If any critical errors occured, we exit with a non-zero exit code. - // In many cases we don't want to immediately exit the application, - // but we want to log the error and continue and see what else is going on before we exit. - if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) - { - return 1; - } + foreach (var logEvent in collectionSink.Events) Log.Write(logEvent); - Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); - Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", - launcherConfiguration.CashboxConfigurationFile); - Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); + // If any critical errors occured, we exit with a non-zero exit code. + // In many cases we don't want to immediately exit the application, + // but we want to log the error and continue and see what else is going on before we exit. + if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) return 1; - Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); + Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); + Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", + launcherConfiguration.CashboxConfigurationFile); + Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, - useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + Log.Debug("Launcher running as {ServiceType}", + Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); - try - { - launcherConfiguration.Decrypt( - dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); - } - catch (Exception e) - { - Log.Warning(e, "Error decrypring launcher configuration file."); - } + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, + useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); - return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + try + { + launcherConfiguration.Decrypt( + dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + } + catch (Exception e) + { + Log.Warning(e, "Error decrypring launcher configuration file."); } - private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) + return await handler(options, + new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), + specificOptions, host.Services.GetRequiredService()); + } + + private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) + { + var serviceDirectory = config.ServiceFolder!; + try { - var serviceDirectory = config.ServiceFolder!; - try + if (!Directory.Exists(serviceDirectory)) { - if (!Directory.Exists(serviceDirectory)) - { - Directory.CreateDirectory(serviceDirectory); + Directory.CreateDirectory(serviceDirectory); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + var user = Environment.GetEnvironmentVariable("USER"); + if (!string.IsNullOrEmpty(user)) { - var user = Environment.GetEnvironmentVariable("USER"); - if (!string.IsNullOrEmpty(user)) - { - var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, LogEventLevel.Debug); - if (chownResult.exitCode != 0) - { - Log.Warning("Failed to change owner of the service directory."); - } - - var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, LogEventLevel.Debug); - if (chmodResult.exitCode != 0) - { - Log.Warning("Failed to change permissions of the service directory."); - } - } - else - { - Log.Warning( - "Service user name is not set. Owner of the service directory will not be changed."); - } + var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, + LogEventLevel.Debug); + if (chownResult.exitCode != 0) Log.Warning("Failed to change owner of the service directory."); + + var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, + LogEventLevel.Debug); + if (chmodResult.exitCode != 0) + Log.Warning("Failed to change permissions of the service directory."); } else { - Log.Debug("Changing owner and permissions is skipped on non-Unix operating systems."); + Log.Warning( + "Service user name is not set. Owner of the service directory will not be changed."); } } - } - catch (UnauthorizedAccessException e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, - "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", serviceDirectory); + else + { + Log.Debug("Changing owner and permissions is skipped on non-Unix operating systems."); + } } } - - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, - bool useOffline = false, bool dryRun = false, bool useFallback = false) + catch (UnauthorizedAccessException e) { - Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) - .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); - var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); + // will exit with non-zero exit code later. + Log.Fatal(e, + "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", + serviceDirectory); + } + } + + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, + bool useOffline = false, bool dryRun = false, bool useFallback = false) + { + Log.Verbose("Loading Curve."); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) + .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - if (File.Exists(clientEcdhPath)) + if (File.Exists(clientEcdhPath)) + try { - try - { - return ECDiffieHellmanExt.Deserialize( - dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); - } - catch (Exception e) - { - Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); - } + return ECDiffieHellmanExt.Deserialize( + dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); } - - // Handling offline client ECDH path - const string offlineClientEcdhPath = "/client.ecdh"; - if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) + catch (Exception e) { - var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); - try - { - File.Delete(offlineClientEcdhPath); - } - catch - { - } - - return clientEcdh; + Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); } - // Regenerating the curve if it's not loaded or in case of an error - var newClientEcdh = CashboxConfigEncryption.CreateCurve(); - if (!dryRun) + // Handling offline client ECDH path + const string offlineClientEcdhPath = "/client.ecdh"; + if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) + { + var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + try + { + File.Delete(offlineClientEcdhPath); + } + catch { - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); } return clientEcdh; } + + // Regenerating the curve if it's not loaded or in case of an error + var newClientEcdh = CashboxConfigEncryption.CreateCurve(); + if (!dryRun) await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); + + return clientEcdh; } } \ No newline at end of file From 69e6e9fbf38fba8e9e4169eece83dc92cc024d50 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 16:18:38 +0100 Subject: [PATCH 20/31] Add conditional return in Common.cs --- src/fiskaltrust.Launcher/Commands/Common.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 825a5b3c..a3583d20 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -337,6 +337,8 @@ public static async Task LoadCurve(Guid cashboxId, string acces var newClientEcdh = CashboxConfigEncryption.CreateCurve(); if (!dryRun) await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); - return clientEcdh; + return clientEcdh; + } + } } } \ No newline at end of file From 779982ba7957b2134ba063262516526502e16efa Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 16:18:38 +0100 Subject: [PATCH 21/31] Add conditional return in Common.cs --- src/fiskaltrust.Launcher/Commands/Common.cs | 221 ++++++++++---------- 1 file changed, 110 insertions(+), 111 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index a3583d20..731241e0 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -81,21 +81,21 @@ public CommonProperties(LauncherConfiguration launcherConfiguration, public IDataProtectionProvider DataProtectionProvider { get; set; } } -public static class CommonHandler -{ - public static async Task HandleAsync( - CommonOptions options, - O specificOptions, - IHost host, - Func> handler) where S : notnull + public static class CommonHandler { - // Log messages will be save here and logged later when we have the configuration options to create the logger. - var collectionSink = new CollectionSink(); - Log.Logger = new LoggerConfiguration() - .WriteTo.Sink(collectionSink) - .CreateLogger(); + public static async Task HandleAsync( + CommonOptions options, + O specificOptions, + IHost host, + Func> handler) where S : notnull + { + // Log messages will be save here and logged later when we have the configuration options to create the logger. + var collectionSink = new CollectionSink(); + Log.Logger = new LoggerConfiguration() + .WriteTo.Sink(collectionSink) + .CreateLogger(); - var launcherConfiguration = new LauncherConfiguration(); + var launcherConfiguration = new LauncherConfiguration(); Log.Verbose("Reading launcher config file."); try @@ -135,68 +135,72 @@ public static async Task HandleAsync( fi.Delete(); } - Log.Verbose("Merging launcher cli args."); - launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); - await EnsureServiceDirectoryExists(launcherConfiguration); - - if (!launcherConfiguration.UseOffline!.Value && - (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) - Log.Error("CashBoxId and AccessToken are not provided."); + Log.Verbose("Merging launcher cli args."); + launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); + await EnsureServiceDirectoryExists(launcherConfiguration); - try - { - var configFileDirectory = Path.GetDirectoryName(launcherConfiguration.CashboxConfigurationFile); - if (configFileDirectory is not null) Directory.CreateDirectory(configFileDirectory); - } - catch (Exception e) - { - Log.Error(e, "Could not create cashbox-configuration-file folder."); - } + if (!launcherConfiguration.UseOffline!.Value && (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) + { + Log.Error("CashBoxId and AccessToken are not provided."); + } - ECDiffieHellman? clientEcdh = null; - try - { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, - launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); - } - catch (Exception e) - { - Log.Fatal(e, "Could not load client curve."); - } + try + { + var configFileDirectory = Path.GetDirectoryName(launcherConfiguration.CashboxConfigurationFile); + if (configFileDirectory is not null) + { + Directory.CreateDirectory(configFileDirectory); + } + } + catch (Exception e) + { + Log.Error(e, "Could not create cashbox-configuration-file folder."); + } - try - { - if (clientEcdh is not null) + ECDiffieHellman? clientEcdh = null; + try { - using var downloader = new ConfigurationDownloader(launcherConfiguration); - var exists = await downloader.DownloadConfigurationAsync(clientEcdh); - if (launcherConfiguration.UseOffline!.Value && !exists) - Log.Warning("Cashbox configuration was not downloaded because UseOffline is set."); + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + } + catch (Exception e) + { + Log.Fatal(e, "Could not load client curve."); } - } - catch (Exception e) - { - var message = "Could not download Cashbox configuration. "; - message += - $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; - if (!launcherConfiguration.Sandbox!.Value) message += " Did you forget the --sandbox flag?"; - message += ")"; - Log.Error(e, message); - } + try + { + if (clientEcdh is not null) + { + using var downloader = new ConfigurationDownloader(launcherConfiguration); + var exists = await downloader.DownloadConfigurationAsync(clientEcdh); + if (launcherConfiguration.UseOffline!.Value && !exists) + { + Log.Warning("Cashbox configuration was not downloaded because UseOffline is set."); + } + } + } + catch (Exception e) + { + var message = "Could not download Cashbox configuration. "; + message += $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; + if (!launcherConfiguration.Sandbox!.Value) + { + message += " Did you forget the --sandbox flag?"; + } + message += ")"; + Log.Error(e, message); + } - try - { - var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; - launcherConfiguration.OverwriteWith( - LauncherConfigurationInCashBoxConfiguration.Deserialize( - await File.ReadAllTextAsync(cashboxConfigurationFile))); - } - catch (Exception e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, "Could not read Cashbox configuration file."); - } + try + { + var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; + launcherConfiguration.OverwriteWith(LauncherConfigurationInCashBoxConfiguration.Deserialize(await File.ReadAllTextAsync(cashboxConfigurationFile))); + } + catch (Exception e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Could not read Cashbox configuration file."); + } var cashboxConfiguration = new ftCashBoxConfiguration(); try @@ -227,13 +231,11 @@ public static async Task HandleAsync( // but we want to log the error and continue and see what else is going on before we exit. if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) return 1; - Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); - Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", - launcherConfiguration.CashboxConfigurationFile); - Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); + Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); + Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); + Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); - Log.Debug("Launcher running as {ServiceType}", - Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); + Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); @@ -248,55 +250,52 @@ public static async Task HandleAsync( Log.Warning(e, "Error decrypring launcher configuration file."); } - return await handler(options, - new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), - specificOptions, host.Services.GetRequiredService()); - } + return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + } - private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) - { - var serviceDirectory = config.ServiceFolder!; - try + private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) { - if (!Directory.Exists(serviceDirectory)) + var serviceDirectory = config.ServiceFolder!; + try { - Directory.CreateDirectory(serviceDirectory); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + if (!Directory.Exists(serviceDirectory)) { - var user = Environment.GetEnvironmentVariable("USER"); - if (!string.IsNullOrEmpty(user)) + Directory.CreateDirectory(serviceDirectory); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, - LogEventLevel.Debug); - if (chownResult.exitCode != 0) Log.Warning("Failed to change owner of the service directory."); - - var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, - LogEventLevel.Debug); - if (chmodResult.exitCode != 0) - Log.Warning("Failed to change permissions of the service directory."); + var user = Environment.GetEnvironmentVariable("USER"); + if (!string.IsNullOrEmpty(user)) + { + var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, LogEventLevel.Debug); + if (chownResult.exitCode != 0) + { + Log.Warning("Failed to change owner of the service directory."); + } + + var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, LogEventLevel.Debug); + if (chmodResult.exitCode != 0) + { + Log.Warning("Failed to change permissions of the service directory."); + } + } + else + { + Log.Warning("Service user name is not set. Owner of the service directory will not be changed."); + } } else { - Log.Warning( - "Service user name is not set. Owner of the service directory will not be changed."); + Log.Debug("Changing owner and permissions is skipped on non-Unix operating systems."); } } - else - { - Log.Debug("Changing owner and permissions is skipped on non-Unix operating systems."); - } + } + catch (UnauthorizedAccessException e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", serviceDirectory); } } - catch (UnauthorizedAccessException e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, - "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", - serviceDirectory); - } - } public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) From 2c3d294e74c946e99a93ca31b2656da85a24c349 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 16:28:21 +0100 Subject: [PATCH 22/31] changes --- src/fiskaltrust.Launcher/Commands/Common.cs | 248 ++++++++++---------- 1 file changed, 122 insertions(+), 126 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 731241e0..7173e400 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -17,69 +17,64 @@ using Serilog; using Serilog.Events; -namespace fiskaltrust.Launcher.Commands; - -public record SubArguments(IEnumerable Args); - -public class CommonCommand : Command +namespace fiskaltrust.Launcher.Commands { - public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) + public record SubArguments(IEnumerable Args); + + public class CommonCommand : Command { - AddOption(new Option("--cashbox-id")); - AddOption(new Option("--access-token")); - AddOption(new Option("--sandbox")); - AddOption(new Option("--log-folder")); + public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) + { + AddOption(new Option("--cashbox-id")); + AddOption(new Option("--access-token")); + AddOption(new Option("--sandbox")); + AddOption(new Option("--log-folder")); - var logLevelOption = new Option("--log-level", "Set the log level of the application."); - logLevelOption.AddAlias("-v"); - logLevelOption.AddAlias("--verbosity"); - AddOption(logLevelOption); + var logLevelOption = new Option("--log-level", "Set the log level of the application."); + logLevelOption.AddAlias("-v"); + logLevelOption.AddAlias("--verbosity"); + AddOption(logLevelOption); - if (addCliOnlyParameters) - { - AddOption(new Option("--launcher-configuration-file", - () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", - () => Paths.LegacyConfigurationFileName)); - AddOption(new Option("--merge-legacy-config-if-exists", () => true)); + if (addCliOnlyParameters) + { + AddOption(new Option("--launcher-configuration-file", getDefaultValue: () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", getDefaultValue: () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); + } } } -} -public class CommonOptions -{ - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, - string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + public class CommonOptions { - ArgsLauncherConfiguration = argsLauncherConfiguration; - LauncherConfigurationFile = launcherConfigurationFile; - LegacyConfigurationFile = legacyConfigurationFile; - MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; - } + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + { + ArgsLauncherConfiguration = argsLauncherConfiguration; + LauncherConfigurationFile = launcherConfigurationFile; + LegacyConfigurationFile = legacyConfigurationFile; + MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; + } - public LauncherConfiguration ArgsLauncherConfiguration { get; set; } - public string LauncherConfigurationFile { get; set; } - public string LegacyConfigurationFile { get; set; } - public bool MergeLegacyConfigIfExists { get; set; } -} + public LauncherConfiguration ArgsLauncherConfiguration { get; set; } + public string LauncherConfigurationFile { get; set; } + public string LegacyConfigurationFile { get; set; } + public bool MergeLegacyConfigIfExists { get; set; } + } -public record CommonProperties -{ - public CommonProperties(LauncherConfiguration launcherConfiguration, - ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, - IDataProtectionProvider dataProtectionProvider) + public record CommonProperties { - LauncherConfiguration = launcherConfiguration; - CashboxConfiguration = cashboxConfiguration; - ClientEcdh = clientEcdh; - DataProtectionProvider = dataProtectionProvider; - } + public CommonProperties(LauncherConfiguration launcherConfiguration, ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, IDataProtectionProvider dataProtectionProvider) + { + LauncherConfiguration = launcherConfiguration; + CashboxConfiguration = cashboxConfiguration; + ClientEcdh = clientEcdh; + DataProtectionProvider = dataProtectionProvider; + } - public LauncherConfiguration LauncherConfiguration { get; set; } - public ftCashBoxConfiguration CashboxConfiguration { get; set; } - public ECDiffieHellman ClientEcdh { get; set; } - public IDataProtectionProvider DataProtectionProvider { get; set; } -} + public LauncherConfiguration LauncherConfiguration { get; set; } + public ftCashBoxConfiguration CashboxConfiguration { get; set; } + public ECDiffieHellman ClientEcdh { get; set; } + public IDataProtectionProvider DataProtectionProvider { get; set; } + } public static class CommonHandler { @@ -97,43 +92,45 @@ public static async Task HandleAsync( var launcherConfiguration = new LauncherConfiguration(); - Log.Verbose("Reading launcher config file."); - try - { - options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = - LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); - } - catch (Exception e) - { - if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) + Log.Verbose("Reading launcher config file."); + try { - if (File.Exists(options.LauncherConfigurationFile)) - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", - options.LauncherConfigurationFile); - else - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", - options.LauncherConfigurationFile); - - Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); + options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); + launcherConfiguration = LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); } - } - - Log.Verbose("Merging legacy launcher config file."); - if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) - { - var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); - launcherConfiguration.OverwriteWith(legacyConfig); + catch (Exception e) + { + if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) + { + if (File.Exists(options.LauncherConfigurationFile)) + { + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", options.LauncherConfigurationFile); + } + else + { + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", options.LauncherConfigurationFile); + } + Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); + } + } + Log.Verbose("Merging legacy launcher config file."); + if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) + { + var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); + launcherConfiguration.OverwriteWith(legacyConfig); - var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); - if (configFileDirectory is not null) Directory.CreateDirectory(configFileDirectory); + var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); + if (configFileDirectory is not null) + { + Directory.CreateDirectory(configFileDirectory); + } - await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); + await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); - var fi = new FileInfo(options.LegacyConfigurationFile); - fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); - fi.Delete(); - } + var fi = new FileInfo(options.LegacyConfigurationFile); + fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); + fi.Delete(); + } Log.Verbose("Merging launcher cli args."); launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); @@ -202,34 +199,37 @@ public static async Task HandleAsync( Log.Fatal(e, "Could not read Cashbox configuration file."); } - var cashboxConfiguration = new ftCashBoxConfiguration(); - try - { - cashboxConfiguration = - CashBoxConfigurationExt.Deserialize( - await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - if (clientEcdh is not null) cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); - } - catch (Exception e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, "Could not parse Cashbox configuration."); - } + var cashboxConfiguration = new ftCashBoxConfiguration(); + try + { + cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } + } + catch (Exception e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Could not parse Cashbox configuration."); + } - // Previous log messages will be logged here using this logger. - Log.Logger = new LoggerConfiguration() - .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, - new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) - .Enrich.FromLogContext() - .CreateLogger(); + // Previous log messages will be logged here using this logger. + Log.Logger = new LoggerConfiguration() + .AddLoggingConfiguration(launcherConfiguration) + .AddFileLoggingConfiguration(launcherConfiguration, new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .Enrich.FromLogContext() + .CreateLogger(); - foreach (var logEvent in collectionSink.Events) Log.Write(logEvent); + foreach (var logEvent in collectionSink.Events) + { + Log.Write(logEvent); + } - // If any critical errors occured, we exit with a non-zero exit code. - // In many cases we don't want to immediately exit the application, - // but we want to log the error and continue and see what else is going on before we exit. - if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) return 1; + // If any critical errors occured, we exit with a non-zero exit code. + // In many cases we don't want to immediately exit the application, + // but we want to log the error and continue and see what else is going on before we exit. + if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) + { + return 1; + } Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); @@ -237,18 +237,16 @@ public static async Task HandleAsync( Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, - useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); - try - { - launcherConfiguration.Decrypt( - dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); - } - catch (Exception e) - { - Log.Warning(e, "Error decrypring launcher configuration file."); - } + try + { + launcherConfiguration.Decrypt(dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + } + catch (Exception e) + { + Log.Warning(e, "Error decrypring launcher configuration file."); + } return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); } @@ -297,13 +295,11 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con } } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, - bool useOffline = false, bool dryRun = false, bool useFallback = false) - { - Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) - .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); - var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) + { + Log.Verbose("Loading Curve."); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); if (File.Exists(clientEcdhPath)) try From 18a51ef23b5c780410f23af0003a93b26f49b02f Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 17:05:15 +0100 Subject: [PATCH 23/31] Fix indentation in Common.cs file --- src/fiskaltrust.Launcher/Commands/Common.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 7173e400..cc2b043a 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -332,8 +332,8 @@ public static async Task LoadCurve(Guid cashboxId, string acces var newClientEcdh = CashboxConfigEncryption.CreateCurve(); if (!dryRun) await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); - return clientEcdh; - } + return clientEcdh; } } +} } \ No newline at end of file From fb54d22cf8e6b74ee7f5905673478df7559c8038 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 17:08:55 +0100 Subject: [PATCH 24/31] Refactor code --- src/fiskaltrust.Launcher/Commands/Common.cs | 52 ++++++++++----------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index cc2b043a..ab97ca0c 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -218,18 +218,12 @@ public static async Task HandleAsync( .Enrich.FromLogContext() .CreateLogger(); - foreach (var logEvent in collectionSink.Events) - { - Log.Write(logEvent); - } + foreach (var logEvent in collectionSink.Events) Log.Write(logEvent); - // If any critical errors occured, we exit with a non-zero exit code. - // In many cases we don't want to immediately exit the application, - // but we want to log the error and continue and see what else is going on before we exit. - if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) - { - return 1; - } + // If any critical errors occured, we exit with a non-zero exit code. + // In many cases we don't want to immediately exit the application, + // but we want to log the error and continue and see what else is going on before we exit. + if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) return 1; Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); @@ -237,16 +231,18 @@ public static async Task HandleAsync( Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, + useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); - try - { - launcherConfiguration.Decrypt(dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); - } - catch (Exception e) - { - Log.Warning(e, "Error decrypring launcher configuration file."); - } + try + { + launcherConfiguration.Decrypt( + dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + } + catch (Exception e) + { + Log.Warning(e, "Error decrypring launcher configuration file."); + } return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); } @@ -295,11 +291,13 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con } } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) - { - Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); - var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, + bool useOffline = false, bool dryRun = false, bool useFallback = false) + { + Log.Verbose("Loading Curve."); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) + .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); if (File.Exists(clientEcdhPath)) try @@ -332,8 +330,8 @@ public static async Task LoadCurve(Guid cashboxId, string acces var newClientEcdh = CashboxConfigEncryption.CreateCurve(); if (!dryRun) await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); - return clientEcdh; + return clientEcdh; + } } - } } } \ No newline at end of file From 4ddffed5ed8c517a315f1f8c4c6cc5334324d80d Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 17:10:03 +0100 Subject: [PATCH 25/31] Revert "changes" This reverts commit 2c3d294e74c946e99a93ca31b2656da85a24c349. --- src/fiskaltrust.Launcher/Commands/Common.cs | 200 ++++++++++---------- 1 file changed, 103 insertions(+), 97 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index ab97ca0c..12213cae 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -17,65 +17,70 @@ using Serilog; using Serilog.Events; -namespace fiskaltrust.Launcher.Commands -{ - public record SubArguments(IEnumerable Args); +namespace fiskaltrust.Launcher.Commands; + +public record SubArguments(IEnumerable Args); - public class CommonCommand : Command +public class CommonCommand : Command +{ + public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) { - public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) - { - AddOption(new Option("--cashbox-id")); - AddOption(new Option("--access-token")); - AddOption(new Option("--sandbox")); - AddOption(new Option("--log-folder")); + AddOption(new Option("--cashbox-id")); + AddOption(new Option("--access-token")); + AddOption(new Option("--sandbox")); + AddOption(new Option("--log-folder")); - var logLevelOption = new Option("--log-level", "Set the log level of the application."); - logLevelOption.AddAlias("-v"); - logLevelOption.AddAlias("--verbosity"); - AddOption(logLevelOption); + var logLevelOption = new Option("--log-level", "Set the log level of the application."); + logLevelOption.AddAlias("-v"); + logLevelOption.AddAlias("--verbosity"); + AddOption(logLevelOption); - if (addCliOnlyParameters) - { - AddOption(new Option("--launcher-configuration-file", getDefaultValue: () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", getDefaultValue: () => Paths.LegacyConfigurationFileName)); - AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); - } + if (addCliOnlyParameters) + { + AddOption(new Option("--launcher-configuration-file", + () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", + () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--merge-legacy-config-if-exists", () => true)); } } +} - public class CommonOptions +public class CommonOptions +{ + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, + string legacyConfigurationFile, bool mergeLegacyConfigIfExists) { - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, string legacyConfigurationFile, bool mergeLegacyConfigIfExists) - { - ArgsLauncherConfiguration = argsLauncherConfiguration; - LauncherConfigurationFile = launcherConfigurationFile; - LegacyConfigurationFile = legacyConfigurationFile; - MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; - } - - public LauncherConfiguration ArgsLauncherConfiguration { get; set; } - public string LauncherConfigurationFile { get; set; } - public string LegacyConfigurationFile { get; set; } - public bool MergeLegacyConfigIfExists { get; set; } + ArgsLauncherConfiguration = argsLauncherConfiguration; + LauncherConfigurationFile = launcherConfigurationFile; + LegacyConfigurationFile = legacyConfigurationFile; + MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; } - public record CommonProperties - { - public CommonProperties(LauncherConfiguration launcherConfiguration, ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, IDataProtectionProvider dataProtectionProvider) - { - LauncherConfiguration = launcherConfiguration; - CashboxConfiguration = cashboxConfiguration; - ClientEcdh = clientEcdh; - DataProtectionProvider = dataProtectionProvider; - } + public LauncherConfiguration ArgsLauncherConfiguration { get; set; } + public string LauncherConfigurationFile { get; set; } + public string LegacyConfigurationFile { get; set; } + public bool MergeLegacyConfigIfExists { get; set; } +} - public LauncherConfiguration LauncherConfiguration { get; set; } - public ftCashBoxConfiguration CashboxConfiguration { get; set; } - public ECDiffieHellman ClientEcdh { get; set; } - public IDataProtectionProvider DataProtectionProvider { get; set; } +public record CommonProperties +{ + public CommonProperties(LauncherConfiguration launcherConfiguration, + ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, + IDataProtectionProvider dataProtectionProvider) + { + LauncherConfiguration = launcherConfiguration; + CashboxConfiguration = cashboxConfiguration; + ClientEcdh = clientEcdh; + DataProtectionProvider = dataProtectionProvider; } + public LauncherConfiguration LauncherConfiguration { get; set; } + public ftCashBoxConfiguration CashboxConfiguration { get; set; } + public ECDiffieHellman ClientEcdh { get; set; } + public IDataProtectionProvider DataProtectionProvider { get; set; } +} + public static class CommonHandler { public static async Task HandleAsync( @@ -92,45 +97,43 @@ public static async Task HandleAsync( var launcherConfiguration = new LauncherConfiguration(); - Log.Verbose("Reading launcher config file."); - try + Log.Verbose("Reading launcher config file."); + try + { + options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); + launcherConfiguration = + LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + } + catch (Exception e) + { + if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) { - options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + if (File.Exists(options.LauncherConfigurationFile)) + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", + options.LauncherConfigurationFile); + else + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", + options.LauncherConfigurationFile); + + Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); } - catch (Exception e) - { - if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) - { - if (File.Exists(options.LauncherConfigurationFile)) - { - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", options.LauncherConfigurationFile); - } - else - { - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", options.LauncherConfigurationFile); - } - Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); - } - } - Log.Verbose("Merging legacy launcher config file."); - if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) - { - var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); - launcherConfiguration.OverwriteWith(legacyConfig); + } - var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); - if (configFileDirectory is not null) - { - Directory.CreateDirectory(configFileDirectory); - } + Log.Verbose("Merging legacy launcher config file."); + if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) + { + var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); + launcherConfiguration.OverwriteWith(legacyConfig); - await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); + var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); + if (configFileDirectory is not null) Directory.CreateDirectory(configFileDirectory); - var fi = new FileInfo(options.LegacyConfigurationFile); - fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); - fi.Delete(); - } + await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); + + var fi = new FileInfo(options.LegacyConfigurationFile); + fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); + fi.Delete(); + } Log.Verbose("Merging launcher cli args."); launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); @@ -199,24 +202,27 @@ public static async Task HandleAsync( Log.Fatal(e, "Could not read Cashbox configuration file."); } - var cashboxConfiguration = new ftCashBoxConfiguration(); - try - { - cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } - } - catch (Exception e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, "Could not parse Cashbox configuration."); - } + var cashboxConfiguration = new ftCashBoxConfiguration(); + try + { + cashboxConfiguration = + CashBoxConfigurationExt.Deserialize( + await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + if (clientEcdh is not null) cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); + } + catch (Exception e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Could not parse Cashbox configuration."); + } - // Previous log messages will be logged here using this logger. - Log.Logger = new LoggerConfiguration() - .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) - .Enrich.FromLogContext() - .CreateLogger(); + // Previous log messages will be logged here using this logger. + Log.Logger = new LoggerConfiguration() + .AddLoggingConfiguration(launcherConfiguration) + .AddFileLoggingConfiguration(launcherConfiguration, + new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .Enrich.FromLogContext() + .CreateLogger(); foreach (var logEvent in collectionSink.Events) Log.Write(logEvent); From 691283f4b137554aa091bfabff4c138833e3b4aa Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 17:12:55 +0100 Subject: [PATCH 26/31] Refactor code formatting in fiskaltrust.Launcher --- src/fiskaltrust.Launcher/Commands/Common.cs | 202 ++++++++++---------- 1 file changed, 98 insertions(+), 104 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 12213cae..75294982 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -17,69 +17,64 @@ using Serilog; using Serilog.Events; -namespace fiskaltrust.Launcher.Commands; - -public record SubArguments(IEnumerable Args); - -public class CommonCommand : Command +namespace fiskaltrust.Launcher.Commands { - public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) + public record SubArguments(IEnumerable Args); + + public class CommonCommand : Command { - AddOption(new Option("--cashbox-id")); - AddOption(new Option("--access-token")); - AddOption(new Option("--sandbox")); - AddOption(new Option("--log-folder")); + public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) + { + AddOption(new Option("--cashbox-id")); + AddOption(new Option("--access-token")); + AddOption(new Option("--sandbox")); + AddOption(new Option("--log-folder")); - var logLevelOption = new Option("--log-level", "Set the log level of the application."); - logLevelOption.AddAlias("-v"); - logLevelOption.AddAlias("--verbosity"); - AddOption(logLevelOption); + var logLevelOption = new Option("--log-level", "Set the log level of the application."); + logLevelOption.AddAlias("-v"); + logLevelOption.AddAlias("--verbosity"); + AddOption(logLevelOption); - if (addCliOnlyParameters) - { - AddOption(new Option("--launcher-configuration-file", - () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", - () => Paths.LegacyConfigurationFileName)); - AddOption(new Option("--merge-legacy-config-if-exists", () => true)); + if (addCliOnlyParameters) + { + AddOption(new Option("--launcher-configuration-file", getDefaultValue: () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", getDefaultValue: () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); + } } } -} -public class CommonOptions -{ - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, - string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + public class CommonOptions { - ArgsLauncherConfiguration = argsLauncherConfiguration; - LauncherConfigurationFile = launcherConfigurationFile; - LegacyConfigurationFile = legacyConfigurationFile; - MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; - } + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + { + ArgsLauncherConfiguration = argsLauncherConfiguration; + LauncherConfigurationFile = launcherConfigurationFile; + LegacyConfigurationFile = legacyConfigurationFile; + MergeLegacyConfigIfExists = mergeLegacyConfigIfExists; + } - public LauncherConfiguration ArgsLauncherConfiguration { get; set; } - public string LauncherConfigurationFile { get; set; } - public string LegacyConfigurationFile { get; set; } - public bool MergeLegacyConfigIfExists { get; set; } -} + public LauncherConfiguration ArgsLauncherConfiguration { get; set; } + public string LauncherConfigurationFile { get; set; } + public string LegacyConfigurationFile { get; set; } + public bool MergeLegacyConfigIfExists { get; set; } + } -public record CommonProperties -{ - public CommonProperties(LauncherConfiguration launcherConfiguration, - ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, - IDataProtectionProvider dataProtectionProvider) + public record CommonProperties { - LauncherConfiguration = launcherConfiguration; - CashboxConfiguration = cashboxConfiguration; - ClientEcdh = clientEcdh; - DataProtectionProvider = dataProtectionProvider; - } + public CommonProperties(LauncherConfiguration launcherConfiguration, ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, IDataProtectionProvider dataProtectionProvider) + { + LauncherConfiguration = launcherConfiguration; + CashboxConfiguration = cashboxConfiguration; + ClientEcdh = clientEcdh; + DataProtectionProvider = dataProtectionProvider; + } - public LauncherConfiguration LauncherConfiguration { get; set; } - public ftCashBoxConfiguration CashboxConfiguration { get; set; } - public ECDiffieHellman ClientEcdh { get; set; } - public IDataProtectionProvider DataProtectionProvider { get; set; } -} + public LauncherConfiguration LauncherConfiguration { get; set; } + public ftCashBoxConfiguration CashboxConfiguration { get; set; } + public ECDiffieHellman ClientEcdh { get; set; } + public IDataProtectionProvider DataProtectionProvider { get; set; } + } public static class CommonHandler { @@ -97,43 +92,45 @@ public static async Task HandleAsync( var launcherConfiguration = new LauncherConfiguration(); - Log.Verbose("Reading launcher config file."); - try - { - options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = - LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); - } - catch (Exception e) - { - if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) + Log.Verbose("Reading launcher config file."); + try { - if (File.Exists(options.LauncherConfigurationFile)) - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", - options.LauncherConfigurationFile); - else - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", - options.LauncherConfigurationFile); - - Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); + options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); + launcherConfiguration = LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); } - } - - Log.Verbose("Merging legacy launcher config file."); - if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) - { - var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); - launcherConfiguration.OverwriteWith(legacyConfig); + catch (Exception e) + { + if (!(options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile))) + { + if (File.Exists(options.LauncherConfigurationFile)) + { + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", options.LauncherConfigurationFile); + } + else + { + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", options.LauncherConfigurationFile); + } + Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); + } + } + Log.Verbose("Merging legacy launcher config file."); + if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) + { + var legacyConfig = await LegacyConfigFileReader.ReadLegacyConfigFile(options.LegacyConfigurationFile); + launcherConfiguration.OverwriteWith(legacyConfig); - var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); - if (configFileDirectory is not null) Directory.CreateDirectory(configFileDirectory); + var configFileDirectory = Path.GetDirectoryName(Path.GetFullPath(options.LauncherConfigurationFile)); + if (configFileDirectory is not null) + { + Directory.CreateDirectory(configFileDirectory); + } - await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); + await File.WriteAllTextAsync(options.LauncherConfigurationFile, legacyConfig.Serialize()); - var fi = new FileInfo(options.LegacyConfigurationFile); - fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); - fi.Delete(); - } + var fi = new FileInfo(options.LegacyConfigurationFile); + fi.CopyTo(options.LegacyConfigurationFile + ".legacy"); + fi.Delete(); + } Log.Verbose("Merging launcher cli args."); launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); @@ -202,27 +199,24 @@ public static async Task HandleAsync( Log.Fatal(e, "Could not read Cashbox configuration file."); } - var cashboxConfiguration = new ftCashBoxConfiguration(); - try - { - cashboxConfiguration = - CashBoxConfigurationExt.Deserialize( - await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - if (clientEcdh is not null) cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); - } - catch (Exception e) - { - // will exit with non-zero exit code later. - Log.Fatal(e, "Could not parse Cashbox configuration."); - } + var cashboxConfiguration = new ftCashBoxConfiguration(); + try + { + cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } + } + catch (Exception e) + { + // will exit with non-zero exit code later. + Log.Fatal(e, "Could not parse Cashbox configuration."); + } - // Previous log messages will be logged here using this logger. - Log.Logger = new LoggerConfiguration() - .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, - new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) - .Enrich.FromLogContext() - .CreateLogger(); + // Previous log messages will be logged here using this logger. + Log.Logger = new LoggerConfiguration() + .AddLoggingConfiguration(launcherConfiguration) + .AddFileLoggingConfiguration(launcherConfiguration, new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .Enrich.FromLogContext() + .CreateLogger(); foreach (var logEvent in collectionSink.Events) Log.Write(logEvent); @@ -339,5 +333,5 @@ public static async Task LoadCurve(Guid cashboxId, string acces return clientEcdh; } } -} + } } \ No newline at end of file From f9fb2c91babb1dbf7407e942195b95af08dddc7f Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 17:15:00 +0100 Subject: [PATCH 27/31] Resolve diff --- src/fiskaltrust.Launcher/Commands/Common.cs | 48 +++++++++++---------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 75294982..7173e400 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -218,12 +218,18 @@ public static async Task HandleAsync( .Enrich.FromLogContext() .CreateLogger(); - foreach (var logEvent in collectionSink.Events) Log.Write(logEvent); + foreach (var logEvent in collectionSink.Events) + { + Log.Write(logEvent); + } - // If any critical errors occured, we exit with a non-zero exit code. - // In many cases we don't want to immediately exit the application, - // but we want to log the error and continue and see what else is going on before we exit. - if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) return 1; + // If any critical errors occured, we exit with a non-zero exit code. + // In many cases we don't want to immediately exit the application, + // but we want to log the error and continue and see what else is going on before we exit. + if (collectionSink.Events.Where(e => e.Level == LogEventLevel.Fatal).Any()) + { + return 1; + } Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); @@ -231,18 +237,16 @@ public static async Task HandleAsync( Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, - useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); - try - { - launcherConfiguration.Decrypt( - dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); - } - catch (Exception e) - { - Log.Warning(e, "Error decrypring launcher configuration file."); - } + try + { + launcherConfiguration.Decrypt(dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + } + catch (Exception e) + { + Log.Warning(e, "Error decrypring launcher configuration file."); + } return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); } @@ -291,13 +295,11 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con } } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, - bool useOffline = false, bool dryRun = false, bool useFallback = false) - { - Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) - .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); - var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) + { + Log.Verbose("Loading Curve."); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); if (File.Exists(clientEcdhPath)) try From f4f3c1709b22dcc56fdb2ac203c7dfb297e9b0f6 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 19:44:25 +0100 Subject: [PATCH 28/31] Refactor codein Common.cs --- src/fiskaltrust.Launcher/Commands/Common.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index 7173e400..4b31765e 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -330,10 +330,10 @@ public static async Task LoadCurve(Guid cashboxId, string acces // Regenerating the curve if it's not loaded or in case of an error var newClientEcdh = CashboxConfigEncryption.CreateCurve(); - if (!dryRun) await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); - - return clientEcdh; - } - } + if (!dryRun) await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); + + return clientEcdh; + + } } } \ No newline at end of file From 63118e54b4b6f47920a70dba8bd06ba29938e91b Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 20:16:42 +0100 Subject: [PATCH 29/31] Improve code --- src/fiskaltrust.Launcher/Commands/Common.cs | 147 +++++++++++++------- 1 file changed, 93 insertions(+), 54 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index f9cdf809..cd39ff11 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -37,8 +37,10 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) if (addCliOnlyParameters) { - AddOption(new Option("--launcher-configuration-file", getDefaultValue: () => Paths.LauncherConfigurationFileName)); - AddOption(new Option("--legacy-configuration-file", getDefaultValue: () => Paths.LegacyConfigurationFileName)); + AddOption(new Option("--launcher-configuration-file", + getDefaultValue: () => Paths.LauncherConfigurationFileName)); + AddOption(new Option("--legacy-configuration-file", + getDefaultValue: () => Paths.LegacyConfigurationFileName)); AddOption(new Option("--merge-legacy-config-if-exists", getDefaultValue: () => true)); } } @@ -46,7 +48,8 @@ public CommonCommand(string name, bool addCliOnlyParameters = true) : base(name) public class CommonOptions { - public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, string legacyConfigurationFile, bool mergeLegacyConfigIfExists) + public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string launcherConfigurationFile, + string legacyConfigurationFile, bool mergeLegacyConfigIfExists) { ArgsLauncherConfiguration = argsLauncherConfiguration; LauncherConfigurationFile = launcherConfigurationFile; @@ -62,7 +65,9 @@ public CommonOptions(LauncherConfiguration argsLauncherConfiguration, string lau public record CommonProperties { - public CommonProperties(LauncherConfiguration launcherConfiguration, ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, IDataProtectionProvider dataProtectionProvider) + public CommonProperties(LauncherConfiguration launcherConfiguration, + ftCashBoxConfiguration cashboxConfiguration, ECDiffieHellman clientEcdh, + IDataProtectionProvider dataProtectionProvider) { LauncherConfiguration = launcherConfiguration; CashboxConfiguration = cashboxConfiguration; @@ -96,7 +101,8 @@ public static async Task HandleAsync( try { options.LauncherConfigurationFile = Path.GetFullPath(options.LauncherConfigurationFile); - launcherConfiguration = LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); + launcherConfiguration = + LauncherConfiguration.Deserialize(await File.ReadAllTextAsync(options.LauncherConfigurationFile)); } catch (Exception e) { @@ -104,15 +110,19 @@ public static async Task HandleAsync( { if (File.Exists(options.LauncherConfigurationFile)) { - Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", options.LauncherConfigurationFile); + Log.Warning(e, "Could not parse launcher configuration file \"{LauncherConfigurationFile}\".", + options.LauncherConfigurationFile); } else { - Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", options.LauncherConfigurationFile); + Log.Warning("Launcher configuration file \"{LauncherConfigurationFile}\" does not exist.", + options.LauncherConfigurationFile); } + Log.Warning("Using command line parameters only.", options.LauncherConfigurationFile); } } + Log.Verbose("Merging legacy launcher config file."); if (options.MergeLegacyConfigIfExists && File.Exists(options.LegacyConfigurationFile)) { @@ -136,7 +146,8 @@ public static async Task HandleAsync( launcherConfiguration.OverwriteWith(options.ArgsLauncherConfiguration); await EnsureServiceDirectoryExists(launcherConfiguration); - if (!launcherConfiguration.UseOffline!.Value && (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) + if (!launcherConfiguration.UseOffline!.Value && + (launcherConfiguration.CashboxId is null || launcherConfiguration.AccessToken is null)) { Log.Error("CashBoxId and AccessToken are not provided."); } @@ -157,7 +168,8 @@ public static async Task HandleAsync( ECDiffieHellman? clientEcdh = null; try { - clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); + clientEcdh = await LoadCurve(launcherConfiguration.CashboxId!.Value, launcherConfiguration.AccessToken!, + launcherConfiguration.ServiceFolder!, launcherConfiguration.UseOffline!.Value); } catch (Exception e) { @@ -179,11 +191,13 @@ public static async Task HandleAsync( catch (Exception e) { var message = "Could not download Cashbox configuration. "; - message += $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; + message += + $"(Launcher is running in {(launcherConfiguration.Sandbox!.Value ? "sandbox" : "production")} mode."; if (!launcherConfiguration.Sandbox!.Value) { message += " Did you forget the --sandbox flag?"; } + message += ")"; Log.Error(e, message); } @@ -191,7 +205,9 @@ public static async Task HandleAsync( try { var cashboxConfigurationFile = launcherConfiguration.CashboxConfigurationFile!; - launcherConfiguration.OverwriteWith(LauncherConfigurationInCashBoxConfiguration.Deserialize(await File.ReadAllTextAsync(cashboxConfigurationFile))); + launcherConfiguration.OverwriteWith( + LauncherConfigurationInCashBoxConfiguration.Deserialize( + await File.ReadAllTextAsync(cashboxConfigurationFile))); } catch (Exception e) { @@ -202,8 +218,13 @@ public static async Task HandleAsync( var cashboxConfiguration = new ftCashBoxConfiguration(); try { - cashboxConfiguration = CashBoxConfigurationExt.Deserialize(await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); - if (clientEcdh is not null) { cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); } + cashboxConfiguration = + CashBoxConfigurationExt.Deserialize( + await File.ReadAllTextAsync(launcherConfiguration.CashboxConfigurationFile!)); + if (clientEcdh is not null) + { + cashboxConfiguration.Decrypt(launcherConfiguration, clientEcdh); + } } catch (Exception e) { @@ -214,7 +235,8 @@ public static async Task HandleAsync( // Previous log messages will be logged here using this logger. Log.Logger = new LoggerConfiguration() .AddLoggingConfiguration(launcherConfiguration) - .AddFileLoggingConfiguration(launcherConfiguration, new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) + .AddFileLoggingConfiguration(launcherConfiguration, + new[] { "fiskaltrust.Launcher", launcherConfiguration.CashboxId?.ToString() }) .Enrich.FromLogContext() .CreateLogger(); @@ -232,23 +254,29 @@ public static async Task HandleAsync( } Log.Debug("Launcher Configuration File: {LauncherConfigurationFile}", options.LauncherConfigurationFile); - Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", launcherConfiguration.CashboxConfigurationFile); + Log.Debug("Cashbox Configuration File: {CashboxConfigurationFile}", + launcherConfiguration.CashboxConfigurationFile); Log.Debug("Launcher Configuration: {@LauncherConfiguration}", launcherConfiguration.Redacted()); - Log.Debug("Launcher running as {ServiceType}", Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); + Log.Debug("Launcher running as {ServiceType}", + Enum.GetName(typeof(ServiceTypes), host.Services.GetRequiredService().Type)); - var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); + var dataProtectionProvider = DataProtectionExtensions.Create(launcherConfiguration.AccessToken, + useFallback: launcherConfiguration.UseLegacyDataProtection!.Value); try { - launcherConfiguration.Decrypt(dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); + launcherConfiguration.Decrypt( + dataProtectionProvider.CreateProtector(LauncherConfiguration.DATA_PROTECTION_DATA_PURPOSE)); } catch (Exception e) { Log.Warning(e, "Error decrypring launcher configuration file."); } - return await handler(options, new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), specificOptions, host.Services.GetRequiredService()); + return await handler(options, + new CommonProperties(launcherConfiguration, cashboxConfiguration, clientEcdh!, dataProtectionProvider), + specificOptions, host.Services.GetRequiredService()); } private static async Task EnsureServiceDirectoryExists(LauncherConfiguration config) @@ -260,18 +288,21 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con { Directory.CreateDirectory(serviceDirectory); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var user = Environment.GetEnvironmentVariable("USER"); if (!string.IsNullOrEmpty(user)) { - var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, LogEventLevel.Debug); + var chownResult = await ProcessHelper.RunProcess("chown", new[] { user, serviceDirectory }, + LogEventLevel.Debug); if (chownResult.exitCode != 0) { Log.Warning("Failed to change owner of the service directory."); } - var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, LogEventLevel.Debug); + var chmodResult = await ProcessHelper.RunProcess("chmod", new[] { "774", serviceDirectory }, + LogEventLevel.Debug); if (chmodResult.exitCode != 0) { Log.Warning("Failed to change permissions of the service directory."); @@ -279,7 +310,8 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con } else { - Log.Warning("Service user name is not set. Owner of the service directory will not be changed."); + Log.Warning( + "Service user name is not set. Owner of the service directory will not be changed."); } } else @@ -291,49 +323,56 @@ private static async Task EnsureServiceDirectoryExists(LauncherConfiguration con catch (UnauthorizedAccessException e) { // will exit with non-zero exit code later. - Log.Fatal(e, "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", serviceDirectory); + Log.Fatal(e, + "Access to the path '{ServiceDirectory}' is denied. Please run the application with sufficient permissions.", + serviceDirectory); } } - public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, bool useOffline = false, bool dryRun = false, bool useFallback = false) + public static async Task LoadCurve(Guid cashboxId, string accessToken, string serviceFolder, + bool useOffline = false, bool dryRun = false, bool useFallback = false) { Log.Verbose("Loading Curve."); - var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback).CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); + var dataProtector = DataProtectionExtensions.Create(accessToken, useFallback: useFallback) + .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); - if (File.Exists(clientEcdhPath)) - try - { - return ECDiffieHellmanExt.Deserialize( - dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); - } - catch (Exception e) - { - Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); - } + if (File.Exists(clientEcdhPath)) + try + { + return ECDiffieHellmanExt.Deserialize( + dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); + } + catch (Exception e) + { + Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); + } - // Handling offline client ECDH path - const string offlineClientEcdhPath = "/client.ecdh"; - if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) - { - var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); - try + // Handling offline client ECDH path + const string offlineClientEcdhPath = "/client.ecdh"; + if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) { - File.Delete(offlineClientEcdhPath); + var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + try + { + File.Delete(offlineClientEcdhPath); + } + catch + { + } + + return clientEcdh; } - catch + + // Regenerating the curve if it's not loaded or in case of an error + var newClientEcdh = CashboxConfigEncryption.CreateCurve(); + if (!dryRun) { + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); + return newClientEcdh; } - return clientEcdh; - } - // Regenerating the curve if it's not loaded or in case of an error - var newClientEcdh = CashboxConfigEncryption.CreateCurve(); - if (!dryRun) await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); - - return clientEcdh; - - } + } } -} +} \ No newline at end of file From 4609cfb971019087becdf74cb8a6db9a5102fc36 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 20:32:11 +0100 Subject: [PATCH 30/31] Refactor curve loading --- src/fiskaltrust.Launcher/Commands/Common.cs | 27 ++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index cd39ff11..b7a90405 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -337,42 +337,47 @@ public static async Task LoadCurve(Guid cashboxId, string acces .CreateProtector(CashBoxConfigurationExt.DATA_PROTECTION_DATA_PURPOSE); var clientEcdhPath = Path.Combine(serviceFolder, $"client-{cashboxId}.ecdh"); + ECDiffieHellman? clientEcdh = null; + if (File.Exists(clientEcdhPath)) + { try { - return ECDiffieHellmanExt.Deserialize( + clientEcdh = ECDiffieHellmanExt.Deserialize( dataProtector.Unprotect(await File.ReadAllTextAsync(clientEcdhPath))); } catch (Exception e) { Log.Warning($"Error loading or decrypting ECDH curve: {e.Message}. Regenerating new curve."); } + } // Handling offline client ECDH path const string offlineClientEcdhPath = "/client.ecdh"; - if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath)) + if (!dryRun && useOffline && File.Exists(offlineClientEcdhPath) && clientEcdh == null) { - var clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); + clientEcdh = ECDiffieHellmanExt.Deserialize(await File.ReadAllTextAsync(offlineClientEcdhPath)); try { File.Delete(offlineClientEcdhPath); } catch { + /* handle exception if needed */ } - - return clientEcdh; } - // Regenerating the curve if it's not loaded or in case of an error - var newClientEcdh = CashboxConfigEncryption.CreateCurve(); - if (!dryRun) + if (clientEcdh == null) { - await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(newClientEcdh.Serialize())); - return newClientEcdh; + // Regenerating the curve if it's not loaded or in case of an error + clientEcdh = CashboxConfigEncryption.CreateCurve(); + if (!dryRun) + { + await File.WriteAllTextAsync(clientEcdhPath, dataProtector.Protect(clientEcdh.Serialize())); + } } - return clientEcdh; + return clientEcdh; } } } \ No newline at end of file From b1783d5b07ac9c5aa9d39516379c0f9cdf2a6f24 Mon Sep 17 00:00:00 2001 From: PawelKarczewski Date: Mon, 29 Jan 2024 20:39:30 +0100 Subject: [PATCH 31/31] Improved error handling in ECDH file loading --- src/fiskaltrust.Launcher/Commands/Common.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/fiskaltrust.Launcher/Commands/Common.cs b/src/fiskaltrust.Launcher/Commands/Common.cs index b7a90405..2b9a3d10 100644 --- a/src/fiskaltrust.Launcher/Commands/Common.cs +++ b/src/fiskaltrust.Launcher/Commands/Common.cs @@ -361,9 +361,10 @@ public static async Task LoadCurve(Guid cashboxId, string acces { File.Delete(offlineClientEcdhPath); } - catch + catch (Exception e) { - /* handle exception if needed */ + Log.Error(e, "Error occurred while loading or decrypting ECDH curve from file: {ClientEcdhPath}", clientEcdhPath); + throw; } }