diff --git a/insight.sln b/insight.sln index d27bbe4..85085b4 100644 --- a/insight.sln +++ b/insight.sln @@ -27,8 +27,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{35BA5DCB-BEC EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Api", "src\Api\Insight.Api\Insight.Api.csproj", "{EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Server", "src\Server\Insight.Server\Insight.Server.csproj", "{1E75F7E9-E6AA-44E7-A2F3-DB4CA85E0118}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Updater", "src\Updater\Insight.Updater\Insight.Updater.csproj", "{4875D70F-A96B-4EBA-99BE-218886D29BEB}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Agent", "src\Agent\Insight.Agent\Insight.Agent.csproj", "{2A391CA2-F96B-4DB7-80AA-0668A5141640}" @@ -41,7 +39,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Remote.Windows", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Infrastructure.Web", "src\Core\Insight.Infrastructure.Web\Insight.Infrastructure.Web.csproj", "{39B81A0D-A88C-44D3-9624-1A19C78A4310}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Insight.Server2", "src\Server\Insight.Server2\Insight.Server2.csproj", "{9F7E88B2-7415-410C-9C31-7720596B0607}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Server", "src\Server\Insight.Server\Insight.Server.csproj", "{FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -69,10 +67,6 @@ Global {EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6}.Debug|Any CPU.Build.0 = Debug|Any CPU {EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6}.Release|Any CPU.ActiveCfg = Release|Any CPU {EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6}.Release|Any CPU.Build.0 = Release|Any CPU - {1E75F7E9-E6AA-44E7-A2F3-DB4CA85E0118}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E75F7E9-E6AA-44E7-A2F3-DB4CA85E0118}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E75F7E9-E6AA-44E7-A2F3-DB4CA85E0118}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E75F7E9-E6AA-44E7-A2F3-DB4CA85E0118}.Release|Any CPU.Build.0 = Release|Any CPU {4875D70F-A96B-4EBA-99BE-218886D29BEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4875D70F-A96B-4EBA-99BE-218886D29BEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {4875D70F-A96B-4EBA-99BE-218886D29BEB}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -93,10 +87,10 @@ Global {39B81A0D-A88C-44D3-9624-1A19C78A4310}.Debug|Any CPU.Build.0 = Debug|Any CPU {39B81A0D-A88C-44D3-9624-1A19C78A4310}.Release|Any CPU.ActiveCfg = Release|Any CPU {39B81A0D-A88C-44D3-9624-1A19C78A4310}.Release|Any CPU.Build.0 = Release|Any CPU - {9F7E88B2-7415-410C-9C31-7720596B0607}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9F7E88B2-7415-410C-9C31-7720596B0607}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9F7E88B2-7415-410C-9C31-7720596B0607}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9F7E88B2-7415-410C-9C31-7720596B0607}.Release|Any CPU.Build.0 = Release|Any CPU + {FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -107,13 +101,12 @@ Global {CA99B8CF-520A-4B48-ACCE-0A301C35A7FE} = {15D04093-4974-4B2F-AE8A-F3721F31767A} {375EF474-512A-4410-86CF-46974E07C1F7} = {3F000016-069D-477E-ACA3-F643880B57E8} {EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6} = {35BA5DCB-BECC-4F51-8DD0-694C555D205A} - {1E75F7E9-E6AA-44E7-A2F3-DB4CA85E0118} = {038C3821-E554-496D-B585-A3BC193B7913} {4875D70F-A96B-4EBA-99BE-218886D29BEB} = {F2D241DB-7692-46DB-8A6A-958B365DAAF8} {2A391CA2-F96B-4DB7-80AA-0668A5141640} = {140F73DD-29D3-4C44-809B-5B470880AA0D} {5C4697BD-BC97-484F-9DB1-CA87E2BEAA4B} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D} {AF313B47-3079-407F-91D1-9989C1E1AF2A} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D} {39B81A0D-A88C-44D3-9624-1A19C78A4310} = {88B03853-2215-4E52-8986-0E76602E5F21} - {9F7E88B2-7415-410C-9C31-7720596B0607} = {038C3821-E554-496D-B585-A3BC193B7913} + {FCAE9C42-1DCE-4C2E-BAE0-251C147903B4} = {038C3821-E554-496D-B585-A3BC193B7913} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F376A326-7590-4E7E-AB9B-76CED8527AB0} diff --git a/src/Agent/Insight.Agent/Extensions/ServiceExtensions.cs b/src/Agent/Insight.Agent/Extensions/ServiceExtensions.cs new file mode 100644 index 0000000..a6d644e --- /dev/null +++ b/src/Agent/Insight.Agent/Extensions/ServiceExtensions.cs @@ -0,0 +1,33 @@ +using Insight.Agent.Network; +using Insight.Agent.Network.Handlers; +using Insight.Domain.Interfaces; +using Microsoft.Extensions.DependencyInjection; +using System.Runtime.Versioning; + +namespace Insight.Agent.Extensions; + +internal static class ServiceExtensions +{ + [SupportedOSPlatform("windows")] + internal static IServiceCollection InjectWindowsHandler(this IServiceCollection services) + { + services.AddSingleton, DriveHandler>(); + services.AddSingleton, InterfaceHandler>(); + services.AddSingleton, MainboardHandler>(); + services.AddSingleton, MemoryHandler>(); + services.AddSingleton, OperationSystemHandler>(); + services.AddSingleton, PrinterHandler>(); + services.AddSingleton, ProcessorHandler>(); + services.AddSingleton, ServiceHandler>(); + services.AddSingleton, SessionHandler>(); + services.AddSingleton, SoftwareHandler>(); + services.AddSingleton, StoragePoolHandler>(); + services.AddSingleton, SystemInfoHandler>(); + services.AddSingleton, UpdateHandler>(); + services.AddSingleton, UserHandler>(); + services.AddSingleton, VideocardHandler>(); + services.AddSingleton, VirtualMaschineHandler>(); + + return services; + } +} \ No newline at end of file diff --git a/src/Agent/Insight.Agent/Insight.Agent.csproj b/src/Agent/Insight.Agent/Insight.Agent.csproj index 27e5746..becf45f 100644 --- a/src/Agent/Insight.Agent/Insight.Agent.csproj +++ b/src/Agent/Insight.Agent/Insight.Agent.csproj @@ -11,6 +11,7 @@ enable enable none + true diff --git a/src/Agent/Insight.Agent/Program.cs b/src/Agent/Insight.Agent/Program.cs index 3d85d84..6671d77 100644 --- a/src/Agent/Insight.Agent/Program.cs +++ b/src/Agent/Insight.Agent/Program.cs @@ -1,4 +1,5 @@ -using Insight.Agent.Network; +using Insight.Agent.Extensions; +using Insight.Agent.Network; using Insight.Agent.Network.Handlers; using Insight.Agent.Services; using Insight.Domain.Constants; @@ -9,7 +10,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using System.Runtime.Versioning; +using System.Diagnostics; using Vaitr.Network; using Vaitr.Network.Hosting; @@ -39,8 +40,7 @@ internal class Program options.SingleLine = true; options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff "; }); - - options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/agent_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); + options.AddFile(Configuration.AppDirectory?.FullName + "/logs/" + Process.GetCurrentProcess().ProcessName + "_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); }); builder.ConfigureServices((host, services) => @@ -70,7 +70,7 @@ internal class Program services.AddSingleton, ProxyHandler>(); services.AddSingleton, CustomHandler>(); - if (OperatingSystem.IsWindows()) ServiceCollectionExtensions.InjectWindowsHandler(services); + if (OperatingSystem.IsWindows()) ServiceExtensions.InjectWindowsHandler(services); // GLOBAL DEPENDENCIES services.AddTransient(provider => new HttpClient(new HttpClientHandler @@ -83,30 +83,4 @@ internal class Program var host = builder.Build(); await host.RunAsync().ConfigureAwait(false); } -} - -internal static class ServiceCollectionExtensions -{ - [SupportedOSPlatform("windows")] - internal static IServiceCollection InjectWindowsHandler(this IServiceCollection services) - { - services.AddSingleton, DriveHandler>(); - services.AddSingleton, InterfaceHandler>(); - services.AddSingleton, MainboardHandler>(); - services.AddSingleton, MemoryHandler>(); - services.AddSingleton, OperationSystemHandler>(); - services.AddSingleton, PrinterHandler>(); - services.AddSingleton, ProcessorHandler>(); - services.AddSingleton, ServiceHandler>(); - services.AddSingleton, SessionHandler>(); - services.AddSingleton, SoftwareHandler>(); - services.AddSingleton, StoragePoolHandler>(); - services.AddSingleton, SystemInfoHandler>(); - services.AddSingleton, UpdateHandler>(); - services.AddSingleton, UserHandler>(); - services.AddSingleton, VideocardHandler>(); - services.AddSingleton, VirtualMaschineHandler>(); - - return services; - } } \ No newline at end of file diff --git a/src/Api/Insight.Api/Extensions/ServiceExtensions.cs b/src/Api/Insight.Api/Extensions/ServiceExtensions.cs index 40098f1..aa913cf 100644 --- a/src/Api/Insight.Api/Extensions/ServiceExtensions.cs +++ b/src/Api/Insight.Api/Extensions/ServiceExtensions.cs @@ -1,15 +1,49 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; +using Insight.Infrastructure; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.OpenApi.Models; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; using System.Reflection; namespace Insight.Api.Extensions; -public static class ServiceExtensions +internal static class ServiceExtensions { - internal static IServiceCollection AddSwaggerServices(this IServiceCollection services) + internal static WebApplicationBuilder AddMetrics(this WebApplicationBuilder builder) { - services.AddEndpointsApiExplorer(); - services.AddSwaggerGen(options => + builder.Services.AddOpenTelemetry() + .WithMetrics(provider => + { + provider.ConfigureResource(configure => + { + configure.Clear(); + configure.AddService(builder.Configuration.GetValue(Appsettings.Influx.Service) ?? throw new Exception($"{Appsettings.Influx.Service} value not set (appsettings)")); + }) + .AddRuntimeInstrumentation() + .AddProcessInstrumentation() + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + //.AddMeter("test") + .AddInfluxDBMetricsExporter(configure => + { + configure.Endpoint = builder.Configuration.GetValue(Appsettings.Influx.Endpoint) ?? throw new Exception($"{Appsettings.Influx.Endpoint} value not set (appsettings)"); + configure.Token = builder.Configuration.GetValue(Appsettings.Influx.Token) ?? throw new Exception($"{Appsettings.Influx.Token} value not set (appsettings)"); + configure.Org = builder.Configuration.GetValue(Appsettings.Influx.Organization) ?? throw new Exception($"{Appsettings.Influx.Organization} value not set (appsettings)"); + configure.Bucket = builder.Configuration.GetValue(Appsettings.Influx.Bucket) ?? throw new Exception($"{Appsettings.Influx.Bucket} value not set (appsettings)"); + + configure.MetricExportIntervalMilliseconds = 1000; + }); + } + ); + + //builder.Services.AddSingleton(); + + return builder; + } + + internal static WebApplicationBuilder AddSwagger(this WebApplicationBuilder builder) + { + builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { @@ -53,6 +87,23 @@ public static class ServiceExtensions options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); }); - return services; + return builder; + } + + internal static WebApplication ConfigureSwagger(this WebApplication app) + { + app.UseSwagger(options => + { + options.RouteTemplate = "api/swagger/{documentName}/swagger.json"; + }); + + app.UseSwaggerUI(options => + { + options.DefaultModelsExpandDepth(-1); + options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "v1"); + options.RoutePrefix = "api/swagger"; + }); + + return app; } } \ No newline at end of file diff --git a/src/Api/Insight.Api/Insight.Api.csproj b/src/Api/Insight.Api/Insight.Api.csproj index 89f1bc9..0713355 100644 --- a/src/Api/Insight.Api/Insight.Api.csproj +++ b/src/Api/Insight.Api/Insight.Api.csproj @@ -16,16 +16,22 @@ false--> True $(NoWarn);1591 - none + none + true - - - - - - + + + + + + + + + + + diff --git a/src/Api/Insight.Api/Program.cs b/src/Api/Insight.Api/Program.cs index 66b1d11..9df123f 100644 --- a/src/Api/Insight.Api/Program.cs +++ b/src/Api/Insight.Api/Program.cs @@ -2,6 +2,7 @@ using Insight.Api.Extensions; using Insight.Domain.Constants; using Insight.Infrastructure; using Microsoft.Extensions.FileProviders; +using System.Diagnostics; namespace Insight.Api; @@ -13,47 +14,37 @@ internal class Program builder.Host.UseWindowsService(); builder.Host.UseSystemd(); - // LOGGER + // Configuration + builder.Configuration.Defaults(); + + // Logging builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(LogLevel.Trace); builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning); - builder.Logging.AddSimpleConsole(options => { options.IncludeScopes = true; options.SingleLine = true; options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff "; }); + builder.Logging.AddFile(Configuration.AppDirectory?.FullName + "/logs/" + Process.GetCurrentProcess().ProcessName + "_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); - builder.Logging.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/api_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); - - // INFRASTRUCTURE + // Services builder.Services.AddDatabase(builder.Configuration); - builder.Services.AddInfrastructureServices(); - - // IDENTITY - builder.Services.AddIdentityServices(builder.Configuration); + builder.Services.AddIdentity(builder.Configuration); + builder.Services.AddIdentityServices(); builder.Services.AddBearerAuthentication(builder.Configuration); builder.Services.AddTokenServices(builder.Configuration); - - // SECURITY builder.Services.AddAuthorization(); - // WEBSERVICES - builder.Services.AddProxyServices(); - builder.Services.AddRoutingServices(); - builder.Services.AddControllers(); - - // SWAGGER - builder.Services.AddSwaggerServices(); - - //builder.Services.AddControllers(); - //builder.Services.AddEndpointsApiExplorer(); - //builder.Services.AddSwaggerGen(); + // Modules + builder.AddDefaults(); + builder.AddApiDefaults(); + builder.AddMetrics(); + builder.AddSwagger(); + // HTTP Pipeline var app = builder.Build(); - - // Configure the HTTP request pipeline. app.UseForwardedHeaders(); if (app.Environment.IsDevelopment()) @@ -61,17 +52,7 @@ internal class Program } - app.UseSwagger(options => - { - options.RouteTemplate = "api/swagger/{documentName}/swagger.json"; - }); - - app.UseSwaggerUI(options => - { - options.DefaultModelsExpandDepth(-1); - options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "v1"); - options.RoutePrefix = "api/swagger"; - }); + app.ConfigureSwagger(); app.UseCors(x => x .AllowAnyOrigin() @@ -93,6 +74,6 @@ internal class Program ServeUnknownFileTypes = true }); - await app.RunAsync(); + await app.RunAsync().ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/Api/Insight.Api/appsettings.Development.json b/src/Api/Insight.Api/appsettings.Development.json index 9bac897..09790f7 100644 --- a/src/Api/Insight.Api/appsettings.Development.json +++ b/src/Api/Insight.Api/appsettings.Development.json @@ -1,7 +1,16 @@ { "AllowedHosts": "*", "Urls": "http://127.0.0.1:5000", + + // set in env vars + //"influx.endpoint": "http://127.0.0.1:8086", + //"influx.token": "", + "influx.org": "insight", + "influx.bucket": "insight", + "influx.service": "api", + "mongo.connection": "mongodb://db.insight.local:27017", + "jwt.key": "x5dcaE8fiBmHfgsNrwIEtSWzZkz6gpouzKOIgEiVjxJnW28V1aUnYXF19IcnF5x", "jwt.exp": 3600, "jwt.audience": "http://127.0.0.1:5000", diff --git a/src/Api/Insight.Api/appsettings.json b/src/Api/Insight.Api/appsettings.json index 6b62cc2..39a0d2a 100644 --- a/src/Api/Insight.Api/appsettings.json +++ b/src/Api/Insight.Api/appsettings.json @@ -1,7 +1,16 @@ { "AllowedHosts": "*", "Urls": "http://127.0.0.1:5000", + + // set in env vars + //"influx.endpoint": "http://127.0.0.1:8086", + //"influx.token": "", + "influx.org": "insight", + "influx.bucket": "insight", + "influx.service": "api", + "mongo.connection": "mongodb://127.0.0.1:27017", + "jwt.key": "x5dcaE8fiBmHfgsNrwIEtSWzZkz6gpouzKOIgEiVjxJnW28V1aUnYXF19IcnF5x", "jwt.exp": 3600, "jwt.audience": "https://insight.webmatic.de/api", diff --git a/src/Core/Insight.Domain/Extensions/Configuration.cs b/src/Core/Insight.Domain/Extensions/ConfigurationExtensions.cs similarity index 60% rename from src/Core/Insight.Domain/Extensions/Configuration.cs rename to src/Core/Insight.Domain/Extensions/ConfigurationExtensions.cs index 592de33..6d2a378 100644 --- a/src/Core/Insight.Domain/Extensions/Configuration.cs +++ b/src/Core/Insight.Domain/Extensions/ConfigurationExtensions.cs @@ -8,6 +8,9 @@ public static class ConfigurationExtensions { configuration.Sources.Clear(); configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); - return configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true); + configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true); + configuration.AddEnvironmentVariables(); + + return configuration; } } \ No newline at end of file diff --git a/src/Core/Insight.Domain/Insight.Domain.csproj b/src/Core/Insight.Domain/Insight.Domain.csproj index b2e0753..dcfe56d 100644 --- a/src/Core/Insight.Domain/Insight.Domain.csproj +++ b/src/Core/Insight.Domain/Insight.Domain.csproj @@ -17,6 +17,7 @@ + diff --git a/src/Core/Insight.Infrastructure.Web/Extensions/ServiceExtensions.cs b/src/Core/Insight.Infrastructure.Web/Extensions/ServiceExtensions.cs index 1dda883..3333b32 100644 --- a/src/Core/Insight.Infrastructure.Web/Extensions/ServiceExtensions.cs +++ b/src/Core/Insight.Infrastructure.Web/Extensions/ServiceExtensions.cs @@ -16,43 +16,29 @@ namespace Insight.Infrastructure; public static partial class ServiceExtensions { - public static IServiceCollection AddTokenServices(this IServiceCollection services, IConfiguration configuration) + public static WebApplicationBuilder AddDefaults(this WebApplicationBuilder builder) { - var options = new Models.TokenOptions( - key: configuration.GetValue(Appsettings.Jwt.Key) ?? throw new Exception($"{Appsettings.Jwt.Key} value not set (appsettings)"), - expires: configuration.GetValue(Appsettings.Jwt.Exp) ?? throw new Exception($"{Appsettings.Jwt.Exp} value not set (appsettings)"), - audience: configuration.GetValue(Appsettings.Jwt.Audience) ?? throw new Exception($"{Appsettings.Jwt.Audience} value not set (appsettings)"), - issuer: configuration.GetValue(Appsettings.Jwt.Issuer) ?? throw new Exception($"{Appsettings.Jwt.Issuer} value not set (appsettings)")); - - services.AddSingleton(options); - services.AddTransient(); - - return services; - } - - public static IServiceCollection AddProxyServices(this IServiceCollection services) - { - // add before routing - services.Configure(options => + builder.Services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); - - return services; - } - - public static IServiceCollection AddRoutingServices(this IServiceCollection services) - { - // add after proxy - services.AddRouting(options => + builder.Services.AddRouting(options => { options.LowercaseUrls = true; }); - return services; + return builder; } - public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration configuration) + public static WebApplicationBuilder AddApiDefaults(this WebApplicationBuilder builder) + { + builder.Services.AddControllers(); + builder.Services.AddEndpointsApiExplorer(); + + return builder; + } + + public static IServiceCollection AddIdentity(this IServiceCollection services, IConfiguration configuration) { var connectionString = configuration.GetValue(Appsettings.Mongo.ConnectionString) ?? throw new Exception($"{Appsettings.Mongo.ConnectionString} value not set (appsettings)"); @@ -67,6 +53,20 @@ public static partial class ServiceExtensions return services; } + public static IServiceCollection AddTokenServices(this IServiceCollection services, IConfiguration configuration) + { + var options = new Models.TokenOptions( + key: configuration.GetValue(Appsettings.Jwt.Key) ?? throw new Exception($"{Appsettings.Jwt.Key} value not set (appsettings)"), + expires: configuration.GetValue(Appsettings.Jwt.Exp) ?? throw new Exception($"{Appsettings.Jwt.Exp} value not set (appsettings)"), + audience: configuration.GetValue(Appsettings.Jwt.Audience) ?? throw new Exception($"{Appsettings.Jwt.Audience} value not set (appsettings)"), + issuer: configuration.GetValue(Appsettings.Jwt.Issuer) ?? throw new Exception($"{Appsettings.Jwt.Issuer} value not set (appsettings)")); + + services.AddSingleton(options); + services.AddTransient(); + + return services; + } + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) { // REWRITE TO COOKIE ONLY FOR WEB diff --git a/src/Core/Insight.Infrastructure.Web/Insight.Infrastructure.Web.csproj b/src/Core/Insight.Infrastructure.Web/Insight.Infrastructure.Web.csproj index 903db67..253b8f2 100644 --- a/src/Core/Insight.Infrastructure.Web/Insight.Infrastructure.Web.csproj +++ b/src/Core/Insight.Infrastructure.Web/Insight.Infrastructure.Web.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Core/Insight.Infrastructure/Extensions/ConfigurationExtensions.cs b/src/Core/Insight.Infrastructure/Extensions/ConfigurationExtensions.cs index b347b0d..aee6395 100644 --- a/src/Core/Insight.Infrastructure/Extensions/ConfigurationExtensions.cs +++ b/src/Core/Insight.Infrastructure/Extensions/ConfigurationExtensions.cs @@ -8,6 +8,9 @@ public static class ConfigurationExtensions { configuration.Sources.Clear(); configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); - return configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true); + configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true); + configuration.AddEnvironmentVariables(); + + return configuration; } } \ No newline at end of file diff --git a/src/Core/Insight.Infrastructure/Extensions/ServiceExtensions.cs b/src/Core/Insight.Infrastructure/Extensions/ServiceExtensions.cs index 34ae81d..ed4cab2 100644 --- a/src/Core/Insight.Infrastructure/Extensions/ServiceExtensions.cs +++ b/src/Core/Insight.Infrastructure/Extensions/ServiceExtensions.cs @@ -27,7 +27,7 @@ public static partial class ServiceExtensions return services.AddSingleton(provider => provider.GetRequiredService().GetDatabase(Settings.Database)); } - public static IServiceCollection AddInfrastructureServices(this IServiceCollection services) + public static IServiceCollection AddIdentityServices(this IServiceCollection services) { services.AddTransient(); services.AddTransient(); diff --git a/src/Core/Insight.Infrastructure/Insight.Infrastructure.csproj b/src/Core/Insight.Infrastructure/Insight.Infrastructure.csproj index bd92b41..01ab804 100644 --- a/src/Core/Insight.Infrastructure/Insight.Infrastructure.csproj +++ b/src/Core/Insight.Infrastructure/Insight.Infrastructure.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Remote/Insight.Remote.Windows/Insight.Remote.Windows.csproj b/src/Remote/Insight.Remote.Windows/Insight.Remote.Windows.csproj index 96a02c5..27c43b2 100644 --- a/src/Remote/Insight.Remote.Windows/Insight.Remote.Windows.csproj +++ b/src/Remote/Insight.Remote.Windows/Insight.Remote.Windows.csproj @@ -14,6 +14,7 @@ enable True none + true diff --git a/src/Server/Insight.Server/Controllers/BlankController.cs b/src/Server/Insight.Server/Controllers/BlankController.cs new file mode 100644 index 0000000..e58d21a --- /dev/null +++ b/src/Server/Insight.Server/Controllers/BlankController.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Insight.Server.Controllers +{ + [ApiController] + [Route("[controller]")] + public class BlankController(ILogger logger) : ControllerBase + { + private readonly ILogger _logger = logger; + + [HttpGet(Name = "Test")] + public async Task Get() + { + return Ok(); + } + } +} diff --git a/src/Server/Insight.Server/Extensions/Async.cs b/src/Server/Insight.Server/Extensions/Async.cs deleted file mode 100644 index 225b569..0000000 --- a/src/Server/Insight.Server/Extensions/Async.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Threading.Tasks.Dataflow; - -namespace Insight.Server.Extensions; - -public static class Async -{ - public static async Task ParallelForEach( - this IAsyncEnumerable source, - Func body, - int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded, - TaskScheduler? scheduler = null) - { - var options = new ExecutionDataflowBlockOptions - { - MaxDegreeOfParallelism = maxDegreeOfParallelism - }; - - if (scheduler != null) - options.TaskScheduler = scheduler; - - var block = new ActionBlock(body, options); - - await foreach (var item in source) - block.Post(item); - - block.Complete(); - await block.Completion; - } - - public static async Task ParallelForEach( - this IEnumerable source, - Func body, - int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded, - TaskScheduler? scheduler = null) - { - var options = new ExecutionDataflowBlockOptions - { - MaxDegreeOfParallelism = maxDegreeOfParallelism - }; - - if (scheduler != null) - options.TaskScheduler = scheduler; - - var block = new ActionBlock(body, options); - - foreach (var item in source) - block.Post(item); - - block.Complete(); - await block.Completion; - } -} diff --git a/src/Server/Insight.Server2/Program.cs b/src/Server/Insight.Server/Extensions/ServiceExtensions.cs similarity index 77% rename from src/Server/Insight.Server2/Program.cs rename to src/Server/Insight.Server/Extensions/ServiceExtensions.cs index 06410c5..3632a6f 100644 --- a/src/Server/Insight.Server2/Program.cs +++ b/src/Server/Insight.Server/Extensions/ServiceExtensions.cs @@ -1,74 +1,21 @@ -using Insight.Domain.Constants; -using Insight.Domain.Interfaces; +using Insight.Domain.Interfaces; using Insight.Domain.Network; using Insight.Infrastructure; using Insight.Server.Network.Agent; using Insight.Server.Network.Agent.Handlers; using Insight.Server.Network.Globals; using Insight.Server.Network.Web; +using Microsoft.OpenApi.Models; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using System.Net; using Vaitr.Network; using Vaitr.Network.Hosting; -namespace Insight.Server; - -internal class Program -{ - public static async Task Main(string[] args) - { - var builder = WebApplication.CreateBuilder(args); - builder.Host.UseWindowsService(); - builder.Host.UseSystemd(); - - // Configuration - builder.Configuration.Defaults(); - - // Logging - builder.Logging.ClearProviders(); - builder.Logging.SetMinimumLevel(LogLevel.Trace); - builder.Logging.AddSimpleConsole(options => - { - options.IncludeScopes = true; - options.SingleLine = true; - options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff "; - }); - builder.Logging.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/server_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); - - // Modules - builder.AddDefaults(); - builder.AddMetrics(); - builder.AddAgentServices(); - builder.AddWebServices(); - - // HTTP Pipeline - var app = builder.Build(); - - if (app.Environment.IsDevelopment()) - { - app.UseSwagger(); - app.UseSwaggerUI(); - } - - app.UseAuthorization(); - app.MapControllers(); - - await app.RunAsync(); - } -} +namespace Insight.Server.Extensions; internal static class ServiceExtensions { - internal static WebApplicationBuilder AddDefaults(this WebApplicationBuilder builder) - { - builder.Services.AddControllers(); - builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddSwaggerGen(); - - return builder; - } - internal static WebApplicationBuilder AddMetrics(this WebApplicationBuilder builder) { builder.Services.AddOpenTelemetry() @@ -82,6 +29,7 @@ internal static class ServiceExtensions .AddRuntimeInstrumentation() .AddProcessInstrumentation() .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() //.AddMeter("test") .AddInfluxDBMetricsExporter(configure => { @@ -100,7 +48,21 @@ internal static class ServiceExtensions return builder; } - internal static WebApplicationBuilder AddAgentServices(this WebApplicationBuilder builder) + internal static WebApplicationBuilder AddSwagger(this WebApplicationBuilder builder) + { + builder.Services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Insight Server", + Version = "v1" + }); + }); + + return builder; + } + + internal static WebApplicationBuilder AddAgentBackend(this WebApplicationBuilder builder) { // SERVER builder.Services.UseHostedServer(options => @@ -144,7 +106,7 @@ internal static class ServiceExtensions return builder; } - internal static WebApplicationBuilder AddWebServices(this WebApplicationBuilder builder) + internal static WebApplicationBuilder AddWebBackend(this WebApplicationBuilder builder) { // SERVER builder.Services.UseHostedServer(options => @@ -168,4 +130,21 @@ internal static class ServiceExtensions return builder; } + + internal static WebApplication ConfigureSwagger(this WebApplication app) + { + app.UseSwagger(options => + { + options.RouteTemplate = "api/swagger/{documentName}/swagger.json"; + }); + + app.UseSwaggerUI(options => + { + options.DefaultModelsExpandDepth(-1); + options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "v1"); + options.RoutePrefix = "api/swagger"; + }); + + return app; + } } \ No newline at end of file diff --git a/src/Server/Insight.Server/Insight.Server.csproj b/src/Server/Insight.Server/Insight.Server.csproj index 41f9fe3..41d6fbe 100644 --- a/src/Server/Insight.Server/Insight.Server.csproj +++ b/src/Server/Insight.Server/Insight.Server.csproj @@ -1,59 +1,36 @@ - + - Exe - net8.0 - latest - Insight - server - 2023.12.14.0 - Insight.Server - enable - enable - none + Exe + net8.0 + latest + Insight + server + 2024.1.10.0 + Insight.Server + enable + enable + none + true - - none - - - - none - - - - + + + + + + + + + + + - - - Always - true - PreserveNewest - - - Always - true - PreserveNewest - - - - - - - - - - - - - - - - + @@ -61,10 +38,6 @@ PreserveNewest - - true - Never - diff --git a/src/Server/Insight.Server2/Insight.Server2.http b/src/Server/Insight.Server/Insight.Server.http similarity index 100% rename from src/Server/Insight.Server2/Insight.Server2.http rename to src/Server/Insight.Server/Insight.Server.http diff --git a/src/Server/Insight.Server/Network/Agent/AgentSession.cs b/src/Server/Insight.Server/Network/Agent/AgentSession.cs index 91744ca..363853e 100644 --- a/src/Server/Insight.Server/Network/Agent/AgentSession.cs +++ b/src/Server/Insight.Server/Network/Agent/AgentSession.cs @@ -3,7 +3,6 @@ using Insight.Domain.Interfaces; using Insight.Domain.Network; using Insight.Domain.Network.Agent.Messages; using Insight.Infrastructure.Entities; -using Microsoft.Extensions.Logging; using MongoDB.Driver; using Vaitr.Network; @@ -184,15 +183,13 @@ public class AgentSession( { while (cancellationToken.IsCancellationRequested is false) { - _logger.LogWarning("try get inventory"); - // find assigned host - var host = await _database.Host() + var hostCount = await _database.Host() .CountDocumentsAsync(Builders.Filter.Eq(p => p.Agent, Id), cancellationToken: cancellationToken) .ConfigureAwait(false); // if not assigned => short delay - if (host == 0) + if (hostCount == 0) { await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken); continue; diff --git a/src/Server/Insight.Server/Program.cs b/src/Server/Insight.Server/Program.cs index b8abbee..395f24e 100644 --- a/src/Server/Insight.Server/Program.cs +++ b/src/Server/Insight.Server/Program.cs @@ -1,20 +1,8 @@ -using Insight.Domain.Constants; -using Insight.Domain.Interfaces; -using Insight.Domain.Network; +using Insight.Domain.Constants; using Insight.Infrastructure; -using Insight.Server.Network.Agent; -using Insight.Server.Network.Agent.Handlers; -using Insight.Server.Network.Globals; -using Insight.Server.Network.Web; -using Insight.Server.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System.Net; -using Vaitr.Bus; -using Vaitr.Network; -using Vaitr.Network.Hosting; +using Insight.Server.Extensions; +using System.Collections; +using System.Diagnostics; namespace Insight.Server; @@ -22,126 +10,54 @@ internal class Program { public static async Task Main(string[] args) { - var builder = Host.CreateDefaultBuilder(args); - builder.UseWindowsService(); - builder.UseSystemd(); + var builder = WebApplication.CreateBuilder(args); + builder.Host.UseWindowsService(); + builder.Host.UseSystemd(); - builder.ConfigureAppConfiguration(options => + // Configuration + builder.Configuration.Defaults(); + + // Logging + builder.Logging.ClearProviders(); + builder.Logging.SetMinimumLevel(LogLevel.Trace); + builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning); + builder.Logging.AddSimpleConsole(options => { - options.Defaults(); + options.IncludeScopes = true; + options.SingleLine = true; + options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff "; }); + builder.Logging.AddFile(Configuration.AppDirectory?.FullName + "/logs/" + Process.GetCurrentProcess().ProcessName + "_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); - builder.ConfigureLogging(options => + // Services + builder.Services.AddDatabase(builder.Configuration); + + // Modules + builder.AddDefaults(); + builder.AddApiDefaults(); + builder.AddMetrics(); + builder.AddSwagger(); + builder.AddAgentBackend(); + builder.AddWebBackend(); + + // HTTP Pipeline + var app = builder.Build(); + + if (app.Environment.IsDevelopment()) { - options.ClearProviders(); - options.SetMinimumLevel(LogLevel.Trace); + + } - options.AddSimpleConsole(options => - { - options.IncludeScopes = true; - options.SingleLine = true; - options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff "; - }); + app.ConfigureSwagger(); - options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/server_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); - }); + app.UseCors(x => x + .AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader()); - builder.ConfigureServices((host, services) => - { - // AGENT - services.AddAgentServices(host.Configuration); + app.UseAuthorization(); + app.MapControllers(); - // WEB - services.AddWebServices(host.Configuration); - - // INFRASTRUCTURE - services.AddDatabase(host.Configuration); - - // BACKGROUND SERVICES - services.AddHostedService(); - - // GLOBAL DEPENDENCIES - services.AddSingleton(); - services.AddTransient(provider => new HttpClient(new HttpClientHandler - { - ClientCertificateOptions = ClientCertificateOption.Manual, - ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true - })); - }); - - var host = builder.Build(); - await host.RunAsync().ConfigureAwait(false); - } -} - -internal static class ServiceExtensions -{ - internal static IServiceCollection AddAgentServices(this IServiceCollection services, IConfiguration configuration) - { - // AGENT SERVER - services.UseHostedServer(options => - { - options.Address = IPAddress.Any; - options.Port = configuration.GetValue(Appsettings.Agent.Port) ?? throw new Exception($"{Appsettings.Agent.Port} value not set (appsettings)"); - options.Keepalive = 10000; - options.Timeout = 30000; - options.Backlog = 128; - - options.Compression = true; - options.Encryption = Encryption.Tls12; - options.Certificate = configuration.GetValue(Appsettings.Agent.Certificate) ?? throw new Exception($"{Appsettings.Agent.Certificate} value not set (appsettings)"); - options.CertificatePassword = configuration.GetValue(Appsettings.Agent.CertificatePassword) ?? throw new Exception($"{Appsettings.Agent.CertificatePassword} value not set (appsettings)"); - - options.UseSerializer>(); - }); - - // HANDLER - services.AddSingleton, CustomHandler>(); - services.AddSingleton, ProxyHandler>(); - services.AddSingleton, DriveHandler>(); - services.AddSingleton, Network.Agent.Handlers.EventHandler>(); - services.AddSingleton, InterfaceHandler>(); - services.AddSingleton, MainboardHandler>(); - services.AddSingleton, MemoryHandler>(); - services.AddSingleton, OperationSystemHandler>(); - services.AddSingleton, PrinterHandler>(); - services.AddSingleton, ProcessorHandler>(); - services.AddSingleton, ServiceHandler>(); - services.AddSingleton, SessionHandler>(); - services.AddSingleton, SoftwareHandler>(); - services.AddSingleton, StoragePoolHandler>(); - services.AddSingleton, SystemInfoHandler>(); - services.AddSingleton, TrapHandler>(); - services.AddSingleton, UpdateHandler>(); - services.AddSingleton, UserHandler>(); - services.AddSingleton, VideocardHandler>(); - services.AddSingleton, VirtualMaschineHandler>(); - - return services; - } - - internal static IServiceCollection AddWebServices(this IServiceCollection services, IConfiguration configuration) - { - // SERVER - services.UseHostedServer(options => - { - options.Address = IPAddress.Any; - options.Port = configuration.GetValue(Appsettings.Web.Port) ?? throw new Exception($"{Appsettings.Web.Port} value not set (appsettings)"); - options.Keepalive = 10000; - options.Timeout = 30000; - options.Backlog = 128; - options.Encryption = Encryption.Tls12; - options.Compression = true; - - options.Certificate = configuration.GetValue(Appsettings.Web.Certificate) ?? throw new Exception($"{Appsettings.Web.Certificate} value not set (appsettings)"); - options.CertificatePassword = configuration.GetValue(Appsettings.Web.CertificatePassword) ?? throw new Exception($"{Appsettings.Web.CertificatePassword} value not set (appsettings)"); - - options.UseSerializer>(); - }); - - // HANDLER - services.AddSingleton, ProxyHandler>(); - - return services; + await app.RunAsync(); } } \ No newline at end of file diff --git a/src/Server/Insight.Server/Properties/launchSettings.json b/src/Server/Insight.Server/Properties/launchSettings.json index c95fc24..060a2b2 100644 --- a/src/Server/Insight.Server/Properties/launchSettings.json +++ b/src/Server/Insight.Server/Properties/launchSettings.json @@ -1,14 +1,19 @@ { - "$schema": "https://json.schemastore.org/launchsettings.json", + "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { "Development": { "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Production": { - "commandName": "Project" + "commandName": "Project", + "applicationUrl": "http://localhost:5001" } } -} \ No newline at end of file +} diff --git a/src/Server/Insight.Server/appsettings.Development.json b/src/Server/Insight.Server/appsettings.Development.json index 9138b80..c4b7350 100644 --- a/src/Server/Insight.Server/appsettings.Development.json +++ b/src/Server/Insight.Server/appsettings.Development.json @@ -1,4 +1,20 @@ { + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Urls": "http://127.0.0.1:5005", + + // set in env vars + //"influx.endpoint": "http://127.0.0.1:8086", + //"influx.token": "", + "influx.org": "insight", + "influx.bucket": "insight", + "influx.service": "server", + "mongo.connection": "mongodb://db.insight.local:27017", "agent.port": 3002, @@ -10,4 +26,4 @@ "web.certificate.password": "Webmatic12", "dispatch.webmatic": false -} \ No newline at end of file +} diff --git a/src/Server/Insight.Server/appsettings.json b/src/Server/Insight.Server/appsettings.json index d9ce71c..879f162 100644 --- a/src/Server/Insight.Server/appsettings.json +++ b/src/Server/Insight.Server/appsettings.json @@ -1,4 +1,20 @@ { + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Urls": "http://127.0.0.1:5005", + + // set in env vars + //"influx.endpoint": "http://127.0.0.1:8086", + //"influx.token": "", + "influx.org": "insight", + "influx.bucket": "insight", + "influx.service": "server", + "mongo.connection": "mongodb://127.0.0.1:27017", "agent.port": 3002, @@ -9,5 +25,5 @@ "web.certificate": "localhost.pfx", "web.certificate.password": "Webmatic12", - "dispatch.webmatic": false -} \ No newline at end of file + "dispatch.webmatic": true +} diff --git a/src/Server/Insight.Server/libman.json b/src/Server/Insight.Server/libman.json new file mode 100644 index 0000000..ceee271 --- /dev/null +++ b/src/Server/Insight.Server/libman.json @@ -0,0 +1,5 @@ +{ + "version": "1.0", + "defaultProvider": "cdnjs", + "libraries": [] +} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Controllers/WeatherForecastController.cs b/src/Server/Insight.Server2/Controllers/WeatherForecastController.cs deleted file mode 100644 index 4a44f33..0000000 --- a/src/Server/Insight.Server2/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Insight.Server2.Controllers -{ - [ApiController] - [Route("[controller]")] - public class WeatherForecastController : ControllerBase - { - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - private readonly ILogger _logger; - - public WeatherForecastController(ILogger logger) - { - _logger = logger; - } - - [HttpGet(Name = "GetWeatherForecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } - } -} diff --git a/src/Server/Insight.Server2/Extensions/Async.cs b/src/Server/Insight.Server2/Extensions/Async.cs deleted file mode 100644 index 225b569..0000000 --- a/src/Server/Insight.Server2/Extensions/Async.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Threading.Tasks.Dataflow; - -namespace Insight.Server.Extensions; - -public static class Async -{ - public static async Task ParallelForEach( - this IAsyncEnumerable source, - Func body, - int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded, - TaskScheduler? scheduler = null) - { - var options = new ExecutionDataflowBlockOptions - { - MaxDegreeOfParallelism = maxDegreeOfParallelism - }; - - if (scheduler != null) - options.TaskScheduler = scheduler; - - var block = new ActionBlock(body, options); - - await foreach (var item in source) - block.Post(item); - - block.Complete(); - await block.Completion; - } - - public static async Task ParallelForEach( - this IEnumerable source, - Func body, - int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded, - TaskScheduler? scheduler = null) - { - var options = new ExecutionDataflowBlockOptions - { - MaxDegreeOfParallelism = maxDegreeOfParallelism - }; - - if (scheduler != null) - options.TaskScheduler = scheduler; - - var block = new ActionBlock(body, options); - - foreach (var item in source) - block.Post(item); - - block.Complete(); - await block.Completion; - } -} diff --git a/src/Server/Insight.Server2/Insight.Server2.csproj b/src/Server/Insight.Server2/Insight.Server2.csproj deleted file mode 100644 index d35f0cc..0000000 --- a/src/Server/Insight.Server2/Insight.Server2.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - Exe - net8.0 - latest - Insight - server - 2024.1.10.0 - Insight.Server - enable - enable - none - true - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - diff --git a/src/Server/Insight.Server2/Models/MonitorMessage.cs b/src/Server/Insight.Server2/Models/MonitorMessage.cs deleted file mode 100644 index 3886d21..0000000 --- a/src/Server/Insight.Server2/Models/MonitorMessage.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Insight.Domain.Enums; - -namespace Insight.Server.Models; - -internal class MonitorMessage -{ - public DateTime? Timestamp { get; set; } - public string? Community { get; set; } - public ApplicationEnum? Application { get; set; } - public CategoryEnum? Category { get; set; } - public StatusEnum? Status { get; set; } - public string? Endpoint { get; set; } - public string? Hostname { get; set; } - public string? Subject { get; set; } - public string? Message { get; set; } - - public enum ApplicationEnum - { - Unknown = 0, - Insight = 1, - Acronis = 2, - Veeam = 3, - QNAP = 4, - FreeNas = 5 - } -} diff --git a/src/Server/Insight.Server2/Network/Agent/AgentSession.cs b/src/Server/Insight.Server2/Network/Agent/AgentSession.cs deleted file mode 100644 index 91744ca..0000000 --- a/src/Server/Insight.Server2/Network/Agent/AgentSession.cs +++ /dev/null @@ -1,206 +0,0 @@ -using Insight.Domain.Enums; -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using Microsoft.Extensions.Logging; -using MongoDB.Driver; -using Vaitr.Network; - -namespace Insight.Server.Network.Agent; - -public class AgentSession( - IMongoDatabase database, - IEnumerable> handlers, - ISerializer serializer, - ILogger logger) : TcpSession(serializer, logger) -{ - public string? Id { get; set; } - - private readonly IMongoDatabase _database = database; - private readonly IEnumerable> _handlers = handlers; - - protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Agent ({ep?}) connected", RemoteEndPoint); - - // auth request - await SendAsync(new AuthenticationRequest(), cancellationToken); - - // wait for ack - for (int i = 0; i < 200; i++) - { - if (Id is not null) - break; - - await Task.Delay(50, cancellationToken).ConfigureAwait(false); - } - - // if ack not received - if (Id is null) - { - _logger.LogError("Agent ({ep?}) authentication timeout", RemoteEndPoint); - Disconnect(); - return; - } - - _logger.LogInformation("Agent ({ep?} / {id}) authenticated", RemoteEndPoint, Id); - - // insert log - await WriteLogAsync(CategoryEnum.Network, StatusEnum.Information, $"Connected ({RemoteEndPoint})", default); - - // update entity - await UpdateAsync(default); - - // init inventory task - _ = InitInventoryAsync(cancellationToken); - } - - protected override async ValueTask OnDisconnectedAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Agent ({ep?}) disconnected", RemoteEndPoint); - - // insert log - await WriteLogAsync(CategoryEnum.Network, StatusEnum.Information, $"Disconnected ({RemoteEndPoint})", default); - - // update entity - await UpdateAsync(default); - } - - protected override async ValueTask OnSentAsync(IPacketContext context, CancellationToken cancellationToken) - { - await base.OnSentAsync(context, cancellationToken); - - // update entity - await UpdateAsync(cancellationToken); - } - - protected override async ValueTask OnReceivedAsync(IPacketContext context, CancellationToken cancellationToken) - { - await base.OnReceivedAsync(context, cancellationToken); - - // only accept auth response if not authenticated - if (Id is null) - { - if (context.Packet is not AuthenticationResponse authentication) return; - await OnAuthenticationAsync(authentication, cancellationToken); - } - - // update entity - await UpdateAsync(cancellationToken); - - // pass message to handlers - foreach (var handler in _handlers) - { - try - { - await handler.HandleAsync(this, context.Packet, cancellationToken); - } - catch (Exception ex) - { - _logger.LogWarning("Agent ({ep?}) {ex}", RemoteEndPoint, ex.ToString()); - } - } - } - - protected override async ValueTask OnHeartbeatAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Agent ({ep?}) Heartbeat", RemoteEndPoint); - - // update entity - await UpdateAsync(cancellationToken); - } - - private async ValueTask OnAuthenticationAsync(AuthenticationResponse authentication, CancellationToken cancellationToken) - { - // check serial - if (authentication.Serial == default) - throw new InvalidDataException($"authentication failed ({nameof(authentication.Serial)})"); - - // check version - //if (authentication.Version == default || authentication.Version < Domain.Constants.Configuration.Version) - // throw new InvalidDataException($"authentication failed ({nameof(authentication.Version)})"); - - // upsert agent - await _database.Agent() - .UpdateOneAsync(Builders - .Filter - .Eq(p => p.Serial, authentication.Serial.ToString()), Builders.Update - .SetOnInsert(p => p.Insert, DateTime.Now) - .SetOnInsert(p => p.Serial, authentication.Serial.ToString()) - .Set(p => p.Update, DateTime.Now) - .Set(p => p.Connected, DateTime.Now) - .Set(p => p.Version, authentication.Version) - .Set(p => p.Endpoint, RemoteEndPoint?.ToString()) - .Set(p => p.Hostname, authentication.Hostname), new UpdateOptions - { - IsUpsert = true - }, cancellationToken) - .ConfigureAwait(false); - - // get agent - var agentEntity = await _database.Agent() - .Find(Builders - .Filter - .Eq(p => p.Serial, authentication.Serial.ToString())) - .FirstOrDefaultAsync(cancellationToken) - .ConfigureAwait(false); - - // set session id - Id = agentEntity.Id; - } - - private async ValueTask WriteLogAsync(CategoryEnum category, StatusEnum status, string message, CancellationToken cancellationToken) - { - await _database.AgentLog() - .InsertOneAsync(new AgentLogEntity - { - Insert = DateTime.Now, - Agent = Id, - Category = category.ToString(), - Status = status.ToString(), - Message = message, - Timestamp = DateTime.Now - }, cancellationToken: cancellationToken) - .ConfigureAwait(false); - } - - private async ValueTask UpdateAsync(CancellationToken cancellationToken) - { - await _database.Agent().UpdateOneAsync(Builders - .Filter - .Eq(p => p.Id, Id), Builders - .Update - .Set(p => p.Update, DateTime.Now) - .Set(p => p.Activity, Activity) - .Set(p => p.SentBytes, SentBytes) - .Set(p => p.SentPackets, SentPackets) - .Set(p => p.ReceivedBytes, ReceivedBytes) - .Set(p => p.ReceivedPackets, ReceivedPackets), null, cancellationToken) - .ConfigureAwait(false); - } - - private async Task InitInventoryAsync(CancellationToken cancellationToken) - { - while (cancellationToken.IsCancellationRequested is false) - { - _logger.LogWarning("try get inventory"); - - // find assigned host - var host = await _database.Host() - .CountDocumentsAsync(Builders.Filter.Eq(p => p.Agent, Id), cancellationToken: cancellationToken) - .ConfigureAwait(false); - - // if not assigned => short delay - if (host == 0) - { - await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken); - continue; - } - - // send request - await SendAsync(new InventoryRequest(), cancellationToken); - await Task.Delay(TimeSpan.FromHours(1), cancellationToken); - } - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/CustomHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/CustomHandler.cs deleted file mode 100644 index 14e1e87..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/CustomHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Microsoft.Extensions.Logging; - -namespace Insight.Server.Network.Agent.Handlers; - -public class CustomHandler(ILogger logger) : IMessageHandler -{ - private readonly ILogger _logger = logger; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Response response: - await OnResponseAsync(sender, response, cancellationToken); - break; - } - } - - private ValueTask OnResponseAsync(AgentSession sender, Response response, CancellationToken cancellationToken) - { - _logger.LogWarning("Response: {response}", response.ResponseData); - return default; - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/DriveHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/DriveHandler.cs deleted file mode 100644 index 2fe86a6..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/DriveHandler.cs +++ /dev/null @@ -1,141 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class DriveHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection drives: - await OnDrivesAsync(sender, drives, cancellationToken); - break; - } - } - - private async ValueTask OnDrivesAsync(AgentSession session, List drives, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var driveBulk = new List>(); - - if (drives is not null && drives.Count != 0) - { - foreach (var drive in drives) - { - var driveFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Index, drive.Index) - }); - - var driveUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Index, drive.Index) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.Company, drive.Manufacturer) - .Set(p => p.Name, drive.Name) - .Set(p => p.Size, drive.Size) - .Set(p => p.Type, drive.InterfaceType) - .Set(p => p.Serial, drive.SerialNumber) - .Set(p => p.Firmware, drive.FirmwareRevision) - .Set(p => p.Status, drive.Status) - .Set(p => p.Pnp, drive.PNPDeviceID); - - driveBulk.Add(new UpdateOneModel(driveFilter, driveUpdate) - { - IsUpsert = true - }); - } - } - - driveBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var driveResult = await _database.HostDrive().BulkWriteAsync(driveBulk, cancellationToken: cancellationToken); - - // volumes - - var volumeBulk = new List>(); - - if (drives is not null && drives.Count != 0) - { - foreach (var drive in drives) - { - var driveId = await _database.HostDrive() - .Find(p => p.Host == hostEntity.Id && p.Index == drive.Index) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (drive.Volumes is not null && drive.Volumes.Count != 0) - { - foreach (var volume in drive.Volumes) - { - var volumeFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Drive, driveId), - Builders.Filter.Eq(x => x.Index, volume.Index) - }); - - var volumeUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Drive, driveId) - .SetOnInsert(p => p.Index, volume.Index) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.Name, volume.Name) - .Set(p => p.Label, volume.Id) - .Set(p => p.Serial, volume.SerialNumber) - .Set(p => p.Size, volume.Size) - .Set(p => p.FreeSpace, volume.FreeSpace) - .Set(p => p.Type, volume.Type) - .Set(p => p.FileSystem, volume.FileSystem) - .Set(p => p.Compressed, volume.Compressed) - .Set(p => p.Bootable, volume.Bootable) - .Set(p => p.Primary, volume.PrimaryPartition) - .Set(p => p.Boot, volume.Bootable) - .Set(p => p.BlockSize, volume.BlockSize) - .Set(p => p.Blocks, volume.NumberOfBlocks) - .Set(p => p.StartingOffset, volume.StartingOffset) - .Set(p => p.Provider, volume.ProviderName); - - volumeBulk.Add(new UpdateOneModel(volumeFilter, volumeUpdate) - { - IsUpsert = true - }); - } - } - } - } - - volumeBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var volumeResult = await _database.HostVolume().BulkWriteAsync(volumeBulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/EventHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/EventHandler.cs deleted file mode 100644 index ee6080c..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/EventHandler.cs +++ /dev/null @@ -1,261 +0,0 @@ -using Insight.Domain.Enums; -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Driver; -using static Insight.Domain.Network.Agent.Messages.Event; - -namespace Insight.Server.Network.Agent.Handlers; - -public class EventHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Event @event: - await OnEventAsync(sender, @event, cancellationToken); - break; - } - } - - private async ValueTask OnEventAsync(AgentSession session, Event @event, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - if (FilterEventId(@event)) return; - - var hostLog = await InsertHostLogAsync(hostEntity, @event, cancellationToken); - - if (hostLog is null || FilterMonitoringHostLog(hostLog)) return; - - await _database.HostLogMonitoring() - .InsertOneAsync(new HostLogMonitoringEntity - { - Host = hostEntity.Id, - Insert = hostLog.Insert, - Timestamp = hostLog.Timestamp, - Category = hostLog.Category, - Status = hostLog.Status, - Message = hostLog.Message, - Dispatch = DispatchEnum.Pending.ToString() - }, cancellationToken: cancellationToken); - } - - private async ValueTask InsertAgentLogAsync(AgentSession session, Event @event, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent() - .Aggregate() - .Match(Builders.Filter.Eq(p => p.Id, session.Id)) - .Lookup(_database.Host(), p => p.Serial, p => p.Agent, p => p.Hosts) - .FirstOrDefaultAsync(cancellationToken); - - if (agentEntity is null) return null; - - StatusEnum? status = @event.Status switch - { - StatusType.Information => StatusEnum.Information, - StatusType.Warning => StatusEnum.Warning, - StatusType.Error => StatusEnum.Error, - _ => null - }; - - CategoryEnum? category = @event.Category?.ToLower() switch - { - "network" => CategoryEnum.Network, - "application" => CategoryEnum.Application, - "security" => CategoryEnum.Security, - "system" => CategoryEnum.System, - _ => CategoryEnum.None - }; - - var date = DateTime.Now; - - var log = new AgentLogEntity - { - Insert = date, - Agent = agentEntity.Id, - Timestamp = @event.Timestamp, - EventId = @event.EventId.ToString(), - Source = @event.Source, - Status = status.ToString(), - Category = category.ToString(), - Message = @event.Message - }; - - await _database.AgentLog().InsertOneAsync(log, cancellationToken: cancellationToken); - return log; - } - - private async ValueTask InsertHostLogAsync(HostEntity hostEntity, Event @event, CancellationToken cancellationToken) - { - StatusEnum? status = @event.Status switch - { - StatusType.Information => StatusEnum.Information, - StatusType.Warning => StatusEnum.Warning, - StatusType.Error => StatusEnum.Error, - StatusType.Critical => StatusEnum.Error, - StatusType.Unknown => null, - _ => null - }; - - var category = CategoryEnum.None; - - if (@event.Category is not null) - { - switch (@event.Category) - { - case var _ when @event.Category.Contains("network", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.Network; - break; - - case var _ when @event.Category.Contains("application", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.Application; - break; - - case var _ when @event.Category.Contains("security", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.Security; - break; - - case var _ when @event.Category.Contains("system", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.System; - break; - - case var _ when @event.Category.Contains("printservice", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.Printer; - break; - - case var _ when @event.Category.Contains("taskscheduler", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.Task; - break; - - case var _ when @event.Category.Contains("terminalservices", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.RDP; - break; - - case var _ when @event.Category.Contains("smbclient", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.Network; - break; - - case var _ when @event.Category.Contains("smbserver", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.Network; - break; - - case var _ when @event.Category.Contains("storagespaces", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.System; - break; - - case var _ when @event.Category.Contains("diagnostics", StringComparison.InvariantCultureIgnoreCase): - category = CategoryEnum.System; - break; - - default: - break; - } - } - - var date = DateTime.Now; - - var log = new HostLogEntity - { - Insert = date, - Host = hostEntity.Id, - Timestamp = @event.Timestamp, - EventId = @event.EventId.ToString(), - Status = status.ToString(), - Source = @event.Source, - Category = category.ToString(), - Message = @event.Message - }; - - await _database.HostLog().InsertOneAsync(log, cancellationToken: cancellationToken); - return log; - } - - private static bool FilterEventId(Event @event) - { - var filter = new List - { - 0, - 3, - 4, - 16, - 37, - 900, - 902, - 903, - 1001, - 1003, - 1008, - 1023, - 1066, - 4624, - 4625, - 4634, - 4648, - 4672, - 4776, - 4798, - 4799, - 5058, - 5059, - 5061, - 5379, - 5612, - 5781, - //7036, - 8014, - 8016, - 8019, - 8194, - 8224, - 9009, - 9027, - 10001, - 10016, - 16384, - 16394, - 36874, - 36888, - }; - - if (filter.Any(p => p == @event.EventId)) return true; - return false; - } - - private static bool FilterMonitoringHostLog(HostLogEntity hostLog) - { - if (Enum.TryParse(hostLog.Status, out StatusType status) is false) return true; - - if (hostLog.Category == CategoryEnum.System.ToString()) - { - if (hostLog.Source == "Service Control Manager" && status < StatusType.Warning) return true; - } - - if (hostLog.Category == CategoryEnum.Task.ToString()) - { - if (status < StatusType.Error) return true; - } - - // skip rdp infos - if (hostLog.Category == CategoryEnum.RDP.ToString()) - { - if (hostLog.EventId == "261") return true; - } - - // skip smbclient (veeam errors) - if (hostLog.Category == CategoryEnum.Security.ToString()) - { - if (hostLog.Source == "Microsoft-Windows-SMBClient") return true; - } - - return false; - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/InterfaceHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/InterfaceHandler.cs deleted file mode 100644 index c986aad..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/InterfaceHandler.cs +++ /dev/null @@ -1,295 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class InterfaceHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection interfaces: - await OnInterfacesAsync(sender, interfaces, cancellationToken); - break; - } - } - - private async ValueTask OnInterfacesAsync(AgentSession session, List interfaces, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - // interfaces - - if (interfaces is not null && interfaces.Count != 0) - { - var interfaceBulk = new List>(); - - foreach (var @interface in interfaces) - { - var interfaceFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Index, @interface.Index) - }); - - var interfaceUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Index, @interface.Index) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Mac, @interface?.Mac) - .Set(p => p.Name, @interface?.Name) - .Set(p => p.Description, @interface?.Description) - .Set(p => p.Physical, @interface?.Physical) - .Set(p => p.Status, @interface?.Status?.ToString()) - .Set(p => p.Suffix, @interface?.Suffix) - .Set(p => p.Speed, @interface?.Speed) - .Set(p => p.Ipv4Mtu, @interface?.Ipv4Mtu) - .Set(p => p.Ipv4Dhcp, @interface?.Ipv4Dhcp) - - .Set(p => p.Ipv4Forwarding, @interface?.Ipv4Forwarding) - .Set(p => p.Ipv6Mtu, @interface?.Ipv6Mtu) - .Set(p => p.Sent, @interface?.Sent) - .Set(p => p.Received, @interface?.Received) - .Set(p => p.IncomingPacketsDiscarded, @interface?.IncomingPacketsDiscarded) - .Set(p => p.IncomingPacketsWithErrors, @interface?.IncomingPacketsWithErrors) - .Set(p => p.IncomingUnknownProtocolPackets, @interface?.IncomingUnknownProtocolPackets) - .Set(p => p.OutgoingPacketsDiscarded, @interface?.OutgoingPacketsDiscarded) - .Set(p => p.OutgoingPacketsWithErrors, @interface?.OutgoingPacketsWithErrors); - - interfaceBulk.Add(new UpdateOneModel(interfaceFilter, interfaceUpdate) - { - IsUpsert = true - }); - } - - interfaceBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var interfaceResult = await _database.HostInterface().BulkWriteAsync(interfaceBulk, cancellationToken: cancellationToken); - } - - // addresses - - if (interfaces is not null && interfaces.Count != 0) - { - var addressBulk = new List>(); - - foreach (var @interface in interfaces) - { - var interfaceId = await _database.HostInterface() - .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (@interface.Addresses is not null && @interface.Addresses.Count != 0) - { - foreach (var address in @interface.Addresses) - { - var addressFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Interface, interfaceId), - Builders.Filter.Eq(x => x.Address, address?.IpAddress?.Address), - Builders.Filter.Eq(x => x.Mask, address?.Ipv4Mask?.Address) - }); - - var addressUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Interface, interfaceId) - .SetOnInsert(p => p.Address, address?.IpAddress?.Address) - .SetOnInsert(p => p.Mask, address?.Ipv4Mask?.Address) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch); - - addressBulk.Add(new UpdateOneModel(addressFilter, addressUpdate) - { - IsUpsert = true - }); - } - } - } - - addressBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var addressResult = await _database.HostInterfaceAddress().BulkWriteAsync(addressBulk, cancellationToken: cancellationToken); - } - - // gateways - - if (interfaces is not null && interfaces.Count != 0) - { - var gatewayBulk = new List>(); - - foreach (var @interface in interfaces) - { - var interfaceId = await _database.HostInterface() - .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (@interface.Gateways is not null && @interface.Gateways.Count != 0) - { - foreach (var gateway in @interface.Gateways) - { - var gatewayFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Interface, interfaceId), - Builders.Filter.Eq(x => x.Address, gateway?.Address) - }); - - var gatewayUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Interface, interfaceId) - .SetOnInsert(p => p.Address, gateway?.Address) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch); - - gatewayBulk.Add(new UpdateOneModel(gatewayFilter, gatewayUpdate) - { - IsUpsert = true - }); - } - } - } - - gatewayBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var gatewayResult = await _database.HostInterfaceGateway().BulkWriteAsync(gatewayBulk, cancellationToken: cancellationToken); - } - - // nameservers - - if (interfaces is not null && interfaces.Count != 0) - { - var nameserverBulk = new List>(); - - foreach (var @interface in interfaces) - { - var interfaceId = await _database.HostInterface() - .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (@interface.Dns is not null && @interface.Dns.Count != 0) - { - foreach (var nameserver in @interface.Dns) - { - var nameserverFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Interface, interfaceId), - Builders.Filter.Eq(x => x.Address, nameserver?.Address) - }); - - var nameserverUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Interface, interfaceId) - .SetOnInsert(p => p.Address, nameserver?.Address) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch); - - nameserverBulk.Add(new UpdateOneModel(nameserverFilter, nameserverUpdate) - { - IsUpsert = true - }); - } - } - } - - nameserverBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var nameserverResult = await _database.HostInterfaceNameserver().BulkWriteAsync(nameserverBulk, cancellationToken: cancellationToken); - } - - // routes - - if (interfaces is not null && interfaces.Count != 0) - { - var routeBulk = new List>(); - - foreach (var @interface in interfaces) - { - var interfaceId = await _database.HostInterface() - .Find(p => p.Host == hostEntity.Id && p.Index == @interface.Index) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (@interface.Routes is not null && @interface.Routes.Count != 0) - { - foreach (var route in @interface.Routes) - { - var routeFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Interface, interfaceId), - Builders.Filter.Eq(x => x.Destination, route?.Destination?.Address), - Builders.Filter.Eq(x => x.Gateway, route?.Gateway?.Address), - Builders.Filter.Eq(x => x.Mask, route?.Mask), - }); - - var routeUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Interface, interfaceId) - .SetOnInsert(p => p.Destination, route?.Destination?.Address) - .SetOnInsert(p => p.Gateway, route?.Gateway?.Address) - .SetOnInsert(p => p.Mask, route?.Mask) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Metric, route?.Metric); - - routeBulk.Add(new UpdateOneModel(routeFilter, routeUpdate) - { - IsUpsert = true - }); - } - } - } - - routeBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var routeResult = await _database.HostInterfaceRoute().BulkWriteAsync(routeBulk, cancellationToken: cancellationToken); - } - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/MainboardHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/MainboardHandler.cs deleted file mode 100644 index 95811a8..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/MainboardHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers -{ - public class MainboardHandler(IMongoDatabase database) : IMessageHandler - { - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Mainboard mainboard: - await OnMainboardAsync(sender, mainboard, cancellationToken); - break; - } - } - - private async ValueTask OnMainboardAsync(AgentSession session, Mainboard mainboard, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var date = DateTime.Now; - - await _database.HostMainboard().UpdateOneAsync(p => p.Host == hostEntity.Id, Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .Set(p => p.Update, date) - .Set(p => p.Name, mainboard?.Manufacturer) - .Set(p => p.Name, mainboard?.Model) - .Set(p => p.Serial, mainboard?.Serial) - .Set(p => p.Bios, mainboard?.BiosManufacturer) - .Set(p => p.Version, mainboard?.BiosVersion) - .Set(p => p.Date, mainboard?.BiosDate), new UpdateOptions - { - IsUpsert = true - }, cancellationToken); - } - } -} diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/MemoryHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/MemoryHandler.cs deleted file mode 100644 index 97e1ae5..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/MemoryHandler.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class MemoryHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection memory: - await OnMemoryAsync(sender, memory, cancellationToken); - break; - } - } - - private async ValueTask OnMemoryAsync(AgentSession session, List memory, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (memory is not null && memory.Count != 0) - { - foreach (var mem in memory) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Index, mem.Index) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Index, mem.Index) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.Company, mem.Manufacturer) - .Set(p => p.Name, mem.Model) - .Set(p => p.Tag, mem.Tag) - .Set(p => p.Location, mem.Location) - .Set(p => p.Serial, mem.Serial) - .Set(p => p.Capacity, mem.Capacity) - .Set(p => p.Clock, mem.Speed) - .Set(p => p.CurrentClock, mem.ConfiguredSpeed) - .Set(p => p.Voltage, mem.Voltage) - .Set(p => p.CurrentVoltage, mem.ConfiguredVoltage); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostMemory().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/OperationSystemHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/OperationSystemHandler.cs deleted file mode 100644 index 3fb0d47..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/OperationSystemHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class OperationSystemHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case OperationSystem os: - await OnOperationSystemAsync(sender, os, cancellationToken); - break; - } - } - - private async ValueTask OnOperationSystemAsync(AgentSession session, OperationSystem operatingSystem, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var date = DateTime.Now; - - await _database.HostOs().UpdateOneAsync(p => p.Host == hostEntity.Id, Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .Set(p => p.Update, date) - .Set(p => p.Name, operatingSystem.Name) - .Set(p => p.Version, operatingSystem.Version) - .Set(p => p.Architecture, operatingSystem.Architecture.ToString()) - .Set(p => p.SerialNumber, operatingSystem.SerialNumber) - .Set(p => p.Virtual, operatingSystem.Virtual) - .Set(p => p.Installed, operatingSystem.InstallDate), new UpdateOptions - { - IsUpsert = true - }, cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/PrinterHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/PrinterHandler.cs deleted file mode 100644 index e57f0c0..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/PrinterHandler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class PrinterHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection printers: - await OnPrintersAsync(sender, printers, cancellationToken); - break; - } - } - - private async ValueTask OnPrintersAsync(AgentSession session, List printers, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (printers is not null && printers.Count != 0) - { - foreach (var printer in printers) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Name, printer.Name) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Name, printer.Name) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.Port, printer.Port) - .Set(p => p.Location, printer.Location) - .Set(p => p.Comment, printer.Comment); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostPrinter().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/ProcessorHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/ProcessorHandler.cs deleted file mode 100644 index d11ed9c..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/ProcessorHandler.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class ProcessorHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection processors: - await OnProcessorsAsync(sender, processors, cancellationToken); - break; - } - } - - private async ValueTask OnProcessorsAsync(AgentSession session, List processors, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (processors is not null && processors.Count != 0) - { - foreach (var processor in processors) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Index, processor.Index) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Index, processor.Index) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.Company, processor.Manufacturer) - .Set(p => p.Name, processor.Name) - .Set(p => p.Socket, processor.Socket) - .Set(p => p.Serial, processor.SerialNumber) - .Set(p => p.Version, processor.Version) - .Set(p => p.Cores, processor.Cores) - .Set(p => p.LogicalCores, processor.LogicalCores) - .Set(p => p.Clock, processor.MaxSpeed) - .Set(p => p.CurrentClock, processor.CurrentSpeed) - .Set(p => p.L1Size, processor.L1Size) - .Set(p => p.L2Size, processor.L2Size) - .Set(p => p.L3Size, processor.L3Size) - .Set(p => p.Virtualization, processor.Virtualization) - .Set(p => p.PNP, processor.DeviceId); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostProcessor().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/ServiceHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/ServiceHandler.cs deleted file mode 100644 index be6d45a..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/ServiceHandler.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class ServiceHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection services: - await OnServicesAsync(sender, services, cancellationToken); - break; - } - } - - private async ValueTask OnServicesAsync(AgentSession session, List services, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (services is not null && services.Count != 0) - { - foreach (var service in services) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Name, service.Name) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Name, service.Name) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.DisplayName, service.Display) - .Set(p => p.Description, service.Description) - .Set(p => p.StartMode, service.StartMode.ToString()) - .Set(p => p.State, service.Status.ToString()) - .Set(p => p.ProcessId, service.ProcessId) - .Set(p => p.Delay, service.Delay) - .Set(p => p.Path, service.PathName) - .Set(p => p.Account, service.Account); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostService().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/SessionHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/SessionHandler.cs deleted file mode 100644 index b1ecdc6..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/SessionHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class SessionHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection sessions: - await OnSessionsAsync(sender, sessions, cancellationToken); - break; - } - } - - private async ValueTask OnSessionsAsync(AgentSession session, List sessions, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (sessions is not null && sessions.Count != 0) - { - foreach (var sess in sessions) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Sid, sess.Sid) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Sid, sess.Sid) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.User, sess.User) - .Set(p => p.Remote, sess.Remote) - .Set(p => p.Type, sess.Type) - .Set(p => p.State, sess.Status); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostSession().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/SoftwareHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/SoftwareHandler.cs deleted file mode 100644 index acb7d0e..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/SoftwareHandler.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class SoftwareHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection applications: - await OnApplicationsAsync(sender, applications, cancellationToken); - break; - } - } - - private async ValueTask OnApplicationsAsync(AgentSession session, List applications, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (applications is not null && applications.Count != 0) - { - foreach (var app in applications) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Name, app.Name), - Builders.Filter.Eq(x => x.Architecture, app.Architecture?.ToString()) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Name, app.Name) - .SetOnInsert(p => p.Architecture, app.Architecture?.ToString()) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.Company, app.Publisher) - .Set(p => p.Version, app.Version) - .Set(p => p.InstallDate, app.InstallDate); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostApplication().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/StoragePoolHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/StoragePoolHandler.cs deleted file mode 100644 index c443248..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/StoragePoolHandler.cs +++ /dev/null @@ -1,243 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class StoragePoolHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection storagePools: - await OnStoragePoolsAsync(sender, storagePools, cancellationToken); - break; - } - } - - private async ValueTask OnStoragePoolsAsync(AgentSession session, List? storagePools, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - // storagepools - - if (storagePools is not null && storagePools.Count != 0) - { - var storagepoolBulk = new List>(); - - foreach (var storagePool in storagePools) - { - var storagePoolFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.UniqueId, storagePool.UniqueId) - }); - - List? states = null; - - if (storagePool.States is not null) - { - states = []; - - foreach (var state in storagePool.States) - states.Add(state.ToString()); - } - - var storagePoolUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.UniqueId, storagePool.UniqueId) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Name, storagePool.FriendlyName) - .Set(p => p.Health, storagePool.Health?.ToString()) - .Set(p => p.Resiliency, storagePool.Resiliency) - .Set(p => p.Primordial, storagePool.IsPrimordial) - .Set(p => p.ReadOnly, storagePool.IsReadOnly) - .Set(p => p.Clustered, storagePool.IsClustered) - .Set(p => p.Size, storagePool.Size) - .Set(p => p.AllocatedSize, storagePool.AllocatedSize) - .Set(p => p.SectorSize, storagePool.SectorSize) - .Set(p => p.States, states); - - storagepoolBulk.Add(new UpdateOneModel(storagePoolFilter, storagePoolUpdate) - { - IsUpsert = true - }); - } - - storagepoolBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var storagePoolResult = await _database.HostStoragePool().BulkWriteAsync(storagepoolBulk, cancellationToken: cancellationToken); - } - - // physicaldisks - - if (storagePools is not null && storagePools.Count != 0) - { - var physicalDiskBulk = new List>(); - - foreach (var storagePool in storagePools) - { - var storagePoolId = await _database.HostStoragePool() - .Find(p => p.Host == hostEntity.Id && p.UniqueId == storagePool.UniqueId) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (storagePool.PhysicalDisks is not null && storagePool.PhysicalDisks.Count != 0) - { - foreach (var physicalDisk in storagePool.PhysicalDisks) - { - var physicalDiskFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.StoragePool, storagePoolId), - Builders.Filter.Eq(x => x.UniqueId, physicalDisk.UniqueId) - }); - - List? states = null; - - if (physicalDisk.States is not null) - { - states = []; - - foreach (var state in physicalDisk.States) - states.Add(state.ToString()); - } - - var physicalDiskUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.StoragePool, storagePoolId) - .SetOnInsert(p => p.UniqueId, physicalDisk.UniqueId) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.DeviceId, physicalDisk.DeviceId) - .Set(p => p.Name, physicalDisk.FriendlyName) - .Set(p => p.Manufacturer, physicalDisk.Manufacturer) - .Set(p => p.Model, physicalDisk.Model) - .Set(p => p.Media, physicalDisk.MediaType.ToString()) - .Set(p => p.Bus, physicalDisk.BusType.ToString()) - .Set(p => p.Health, physicalDisk.Health.ToString()) - .Set(p => p.Usage, physicalDisk.Usage) - .Set(p => p.Location, physicalDisk.PhysicalLocation) - .Set(p => p.Serial, physicalDisk.SerialNumber) - .Set(p => p.Firmware, physicalDisk.FirmwareVersion) - .Set(p => p.Size, physicalDisk.Size) - .Set(p => p.AllocatedSize, physicalDisk.AllocatedSize) - .Set(p => p.Footprint, physicalDisk.VirtualDiskFootprint) - .Set(p => p.LogicalSectorSize, physicalDisk.LogicalSectorSize) - .Set(p => p.PhysicalSectorSize, physicalDisk.PhysicalSectorSize) - .Set(p => p.States, states); - - physicalDiskBulk.Add(new UpdateOneModel(physicalDiskFilter, physicalDiskUpdate) - { - IsUpsert = true - }); - } - } - } - - physicalDiskBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var physicalDiskResult = await _database.HostStoragePoolPhysicalDisk().BulkWriteAsync(physicalDiskBulk, cancellationToken: cancellationToken); - } - - // virtual disks - - if (storagePools is not null && storagePools.Count != 0) - { - var virtualDiskBulk = new List>(); - - foreach (var storagePool in storagePools) - { - if (storagePool.VirtualDisks is not null && storagePool.VirtualDisks.Count != 0) - { - foreach (var virtualDisk in storagePool.VirtualDisks) - { - var storagePoolId = await _database.HostStoragePool() - .Find(p => p.Host == hostEntity.Id && p.UniqueId == storagePool.UniqueId) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - var virtualDiskFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.StoragePool, storagePoolId), - Builders.Filter.Eq(x => x.UniqueId, virtualDisk.UniqueId) - }); - - List? states = null; - - if (virtualDisk.States is not null) - { - states = []; - - foreach (var state in virtualDisk.States) - states.Add(state.ToString()); - } - - var virtualDiskUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.StoragePool, storagePoolId) - .SetOnInsert(p => p.UniqueId, virtualDisk.UniqueId) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Name, virtualDisk.FriendlyName) - .Set(p => p.Health, virtualDisk.Health.ToString()) - .Set(p => p.Access, virtualDisk.AccessType.ToString()) - .Set(p => p.Provisioning, virtualDisk.ProvisioningType.ToString()) - .Set(p => p.PhysicalRedundancy, virtualDisk.PhysicalDiskRedundancy) - .Set(p => p.Resiliency, virtualDisk.ResiliencySettingName) - .Set(p => p.Deduplication, virtualDisk.Deduplication) - .Set(p => p.Snapshot, virtualDisk.IsSnapshot) - .Set(p => p.Size, virtualDisk.Size) - .Set(p => p.AllocatedSize, virtualDisk.AllocatedSize) - .Set(p => p.Footprint, virtualDisk.FootprintOnPool) - .Set(p => p.ReadCacheSize, virtualDisk.ReadCacheSize) - .Set(p => p.WriteCacheSize, virtualDisk.WriteCacheSize) - .Set(p => p.States, states); - - virtualDiskBulk.Add(new UpdateOneModel(virtualDiskFilter, virtualDiskUpdate) - { - IsUpsert = true - }); - } - } - } - - virtualDiskBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var virtualDiskResult = await _database.HostStoragePoolVirtualDisk().BulkWriteAsync(virtualDiskBulk, cancellationToken: cancellationToken); - } - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/SystemInfoHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/SystemInfoHandler.cs deleted file mode 100644 index 58a2e09..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/SystemInfoHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class SystemInfoHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case SystemInfo systemInfo: - await OnSystemInfoAsync(sender, systemInfo, cancellationToken); - break; - } - } - - private async ValueTask OnSystemInfoAsync(AgentSession session, SystemInfo? system, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session?.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity?.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var date = DateTime.Now; - - if (hostEntity.Id is null) return; - - await _database.HostSystem().UpdateOneAsync(p => p.Host == hostEntity.Id, Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .Set(p => p.Update, date) - .Set(p => p.BootUpTime, system?.LastBootUpTime) - .Set(p => p.LocalTime, system?.LocalDateTime) - .Set(p => p.Processes, system?.Processes) - .Set(p => p.License, system?.License), new UpdateOptions - { - IsUpsert = true - }, cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/TrapHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/TrapHandler.cs deleted file mode 100644 index 0ef5449..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/TrapHandler.cs +++ /dev/null @@ -1,264 +0,0 @@ -using Insight.Domain.Enums; -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using Insight.Server.Models; -using MongoDB.Driver; -using System.Text; -using System.Text.RegularExpressions; -using static Insight.Server.Models.MonitorMessage; - -namespace Insight.Server.Network.Agent.Handlers; - -public partial class TrapHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Trap trap: - await OnTrapAsync(sender, trap, cancellationToken); - break; - } - } - - private async ValueTask OnTrapAsync(AgentSession session, Trap? trap, CancellationToken cancellationToken) - { - if (trap is null) return; - - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - if (TryParse(trap, out var monitoring) is false) - { - //_logger.LogWarning($"Failed to parse"); - } - - // insert monitoring log - var monitoringLog = new HostLogMonitoringEntity - { - Host = hostEntity.Id, - Insert = DateTime.Now, - Timestamp = monitoring?.Timestamp, - Category = monitoring?.Category?.ToString(), - Status = monitoring?.Status?.ToString(), - Hostname = monitoring?.Hostname, - Task = monitoring?.Subject, - Message = monitoring?.Message, - Dispatch = DispatchEnum.Pending.ToString() - }; - - await _database.HostLogMonitoring() - .InsertOneAsync(monitoringLog, cancellationToken: cancellationToken); - - // insert host log - var log = new HostLogEntity - { - Insert = monitoringLog.Insert, - Host = monitoringLog.Host, - Category = monitoringLog.Category, - Status = monitoringLog.Status, - Source = "Trap", - Message = monitoringLog?.Task, - Timestamp = monitoringLog?.Insert - }; - - if (monitoringLog?.Message is not null) log.Message += $"\n{monitoringLog.Message}"; - - await _database.HostLog() - .InsertOneAsync(log, cancellationToken: cancellationToken) - .ConfigureAwait(false); - } - - private static bool TryParse(Trap packet, out MonitorMessage? monitoring) - { - monitoring = null; - - if (packet is null || packet.Data is null || packet.Data.Count == 0) - return false; - - monitoring = new MonitorMessage - { - Community = packet.Community, - Category = CategoryEnum.Monitoring, - Endpoint = packet.Endpoint, - Timestamp = packet.Timestamp - }; - - if (Enum.TryParse(packet.Community, true, out var application)) - monitoring.Application = application; - - StatusEnum? status; - string? task; - string? message; - - switch (application) - { - case ApplicationEnum.Acronis: - monitoring.Application = ApplicationEnum.Acronis; - if (ParseAcronis(packet.Data, out status, out task, out message) is false) return false; - break; - case ApplicationEnum.Veeam: - monitoring.Application = ApplicationEnum.Veeam; - if (ParseVeeam(packet.Data, out status, out task, out message) is false) return false; - break; - case ApplicationEnum.QNAP: - monitoring.Application = ApplicationEnum.QNAP; - monitoring.Category = CategoryEnum.System; - monitoring.Hostname = packet.Hostname; - if (ParseQnap(packet.Data, out status, out task, out message) is false) return false; - break; - default: - return false; - } - - monitoring.Status = status; - monitoring.Subject = task; - monitoring.Message = message; - - return true; - } - - [GeneratedRegex(@"\s+")] - private static partial Regex AcronisRegex(); - - private static bool ParseAcronis(List> data, out StatusEnum? status, out string? task, out string? message) - { - status = data[0].Value?.ToLower() switch - { - "erfolgreich" => StatusEnum.Information, - "success" => StatusEnum.Information, - "information" => StatusEnum.Information, - "warnung" => StatusEnum.Warning, - "warning" => StatusEnum.Warning, - "fehler" => StatusEnum.Error, - "failed" => StatusEnum.Error, - "error" => StatusEnum.Error, - _ => null, - }; - - task = null; - message = null; - - var trim = data[1].Value?.Split(':', StringSplitOptions.None); - if (trim is null || trim.Length == 0) return false; - - task = trim[1].Split("'", StringSplitOptions.None)[1].Split("'")[0].Trim(); - message = trim[1].Split("' ", StringSplitOptions.None)[1].Trim(); - if (message is not null) return true; - - if (data[1].Value is not string val) return false; - - var content = AcronisRegex().Replace(val, ""); - var bytes = Enumerable.Range(0, content.Length) - .Where(x => x % 2 == 0) - .Select(x => Convert.ToByte(content.Substring(x, 2), 16)) - .ToArray(); - - content = Encoding.UTF8.GetString(bytes); - - trim = content.Split(':', StringSplitOptions.None); - if (trim is null || trim.Length == 0) return false; - - task = trim[1].Split("'", StringSplitOptions.None)[1].Split("'")[0].Trim(); - message = trim[1].Split("' ", StringSplitOptions.None)[1].Trim(); - return message is not null; - } - - private static bool ParseVeeam(List> data, out StatusEnum? status, out string? task, out string? message) - { - status = null; - task = null; - message = null; - - var parsed = false; - - try - { - var summary = false; - - if (Guid.TryParse(data[0].Value, out _)) - summary = true; - - if (data[1].Value?.ToLower() == "backup configuration job") - return false; - - status = (summary ? data[2].Value?.ToLower() : data[3].Value?.ToLower()) switch - { - "success" => StatusEnum.Information, - "warning" => StatusEnum.Warning, - "failed" => StatusEnum.Error, - "error" => StatusEnum.Error, - _ => null, - }; - - task = data[1].Value; - parsed = true; - } - catch (Exception) - { - - } - - if (parsed) return true; - return false; - } - - private static bool ParseQnap(List> data, out StatusEnum? status, out string? task, out string? message) - { - status = StatusEnum.Information; - task = null; - message = string.Empty; - - var parsed = false; - - try - { - var keywords = new Dictionary - { - { "power", StatusEnum.Information }, - { "rights", StatusEnum.Information }, - { "added", StatusEnum.Information }, - { "changed", StatusEnum.Information }, - { "password", StatusEnum.Information }, - { "firmware", StatusEnum.Information }, - { "restarting", StatusEnum.Information }, - { "detected", StatusEnum.Warning }, - { "external", StatusEnum.Warning }, - { "threshold", StatusEnum.Warning }, - { "file system", StatusEnum.Warning }, - { "raid", StatusEnum.Warning }, - { "full", StatusEnum.Error }, - { "failure", StatusEnum.Error }, - { "failed", StatusEnum.Error }, - { "resyncing", StatusEnum.Error }, - { "degraded", StatusEnum.Error }, - { "error", StatusEnum.Error }, - { "without error", StatusEnum.Information }, - { "ncsi", StatusEnum.Information } - }; - - foreach (var key in keywords) - if (Regex.IsMatch(string.Concat(data).ToLowerInvariant(), $@"\b{key.Key}\b")) - status = key.Value; - - foreach (var kv in data) - message += kv.Value; - - parsed = true; - } - catch (Exception) - { - //_logger.LogError("{ex}", ex); - } - - if (parsed) return true; - return false; - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/UpdateHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/UpdateHandler.cs deleted file mode 100644 index 9185b26..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/UpdateHandler.cs +++ /dev/null @@ -1,117 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class UpdateHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case UpdateCollection updates: - await OnUpdatesAsync(sender, updates, cancellationToken); - break; - } - } - - private async ValueTask OnUpdatesAsync(AgentSession session, UpdateCollection updates, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (updates is not null) - { - if (updates.Installed is not null && updates.Installed.Count != 0) - { - foreach (var update in updates.Installed) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Serial, update.Id) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Serial, update.Id) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Pending, false) - .Set(p => p.Name, update.Name) - .Set(p => p.Description, update.Description) - .Set(p => p.SupportUrl, update.SupportUrl) - .Set(p => p.Result, update.Result.ToString()) - .Set(p => p.Date, update.Date); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - - if (updates.Pending is not null && updates.Pending.Count != 0) - { - foreach (var update in updates.Pending) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Serial, update.Id) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Serial, update.Id) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Pending, true) - .Set(p => p.Name, update.Name) - .Set(p => p.Description, update.Description) - .Set(p => p.SupportUrl, update.SupportUrl) - .Set(p => p.Result, update.Result?.ToString()) - - .Set(p => p.Type, update.Type.ToString()) - .Set(p => p.Size, update.Size) - .Set(p => p.IsDownloaded, update.IsDownloaded) - .Set(p => p.CanRequestUserInput, update.CanRequestUserInput) - .Set(p => p.RebootBehavior, update.RebootBehavior?.ToString()) - - .Set(p => p.Date, update.Date); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - } - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostUpdate().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/UserHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/UserHandler.cs deleted file mode 100644 index 5051971..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/UserHandler.cs +++ /dev/null @@ -1,183 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class UserHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection users: - await OnUsersAsync(sender, users, cancellationToken); - break; - } - } - - private async ValueTask OnUsersAsync(AgentSession session, List? users, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - // users - - if (users is not null && users.Count != 0) - { - var userBulk = new List>(); - - foreach (var user in users) - { - var userFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Domain, user?.Domain), - Builders.Filter.Eq(x => x.Name, user?.Name) - }); - - var userUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Domain, user?.Domain) - .SetOnInsert(p => p.Name, user?.Name) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Sid, user?.Sid) - .Set(p => p.FullName, user?.FullName) - .Set(p => p.Description, user?.Description) - .Set(p => p.Status, user?.Status) - .Set(p => p.LocalAccount, user?.LocalAccount) - .Set(p => p.Disabled, user?.Disabled) - .Set(p => p.Lockout, user?.Lockout) - .Set(p => p.PasswordChangeable, user?.PasswordChangeable) - .Set(p => p.PasswordExpires, user?.PasswordExpires) - .Set(p => p.PasswordRequired, user?.PasswordRequired); - - userBulk.Add(new UpdateOneModel(userFilter, userUpdate) - { - IsUpsert = true - }); - } - - userBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var userResult = await _database.HostSystemUser().BulkWriteAsync(userBulk, cancellationToken: cancellationToken); - } - - // groups - - if (users is not null && users.Count != 0) - { - var groupBulk = new List>(); - - var distinctGroups = users.SelectMany(p => p.Groups ?? []) - .GroupBy(p => new { p?.Domain, p?.Name }) - .Select(p => p.First()); - - foreach (var group in distinctGroups) - { - var groupFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Domain, group?.Domain), - Builders.Filter.Eq(x => x.Name, group?.Name) - }); - - var groupUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Domain, group?.Domain) - .SetOnInsert(p => p.Name, group?.Name) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Sid, group?.Sid) - .Set(p => p.Description, group?.Description) - .Set(p => p.LocalAccount, group?.LocalAccount); - - groupBulk.Add(new UpdateOneModel(groupFilter, groupUpdate) - { - IsUpsert = true - }); - } - - groupBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var groupResult = await _database.HostSystemGroup().BulkWriteAsync(groupBulk, cancellationToken: cancellationToken); - } - - // relations - if (users is not null && users.Count != 0) - { - var relationBulk = new List>(); - - foreach (var user in users) - { - var userId = await _database.HostSystemUser() - .Find(p => p.Host == hostEntity.Id && p.Domain == user.Domain && p.Name == user.Name) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (user.Groups is not null && user.Groups.Count != 0) - { - foreach (var group in user.Groups) - { - var groupId = await _database.HostSystemGroup() - .Find(p => p.Host == hostEntity.Id && p.Domain == group.Domain && p.Name == group.Name) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - var relationFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.User, userId), - Builders.Filter.Eq(x => x.Group, groupId) - }); - - var relationUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.User, userId) - .SetOnInsert(p => p.Group, groupId) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch); - - relationBulk.Add(new UpdateOneModel(relationFilter, relationUpdate) - { - IsUpsert = true - }); - } - } - } - - relationBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var relationResult = await _database.HostSystemUserSystemGroup().BulkWriteAsync(relationBulk, cancellationToken: cancellationToken); - } - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/VideocardHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/VideocardHandler.cs deleted file mode 100644 index b8316b5..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/VideocardHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class VideocardHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection videocards: - await OnVideocardsAsync(sender, videocards, cancellationToken); - break; - } - } - - private async ValueTask OnVideocardsAsync(AgentSession session, List? videocards, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - var bulk = new List>(); - - if (videocards is not null && videocards.Count != 0) - { - foreach (var videocard in videocards) - { - var filterDefinition = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.Name, videocard.Model) - }); - - var updateDefinition = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.Name, videocard.Model) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - .Set(p => p.Company, null) - .Set(p => p.Memory, videocard.Memory) - .Set(p => p.Driver, videocard.DriverVersion) - .Set(p => p.Date, videocard.DriverDate); - - bulk.Add(new UpdateOneModel(filterDefinition, updateDefinition) - { - IsUpsert = true - }); - } - - bulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var result = await _database.HostVideocard().BulkWriteAsync(bulk, cancellationToken: cancellationToken); - } - } -} diff --git a/src/Server/Insight.Server2/Network/Agent/Handlers/VirtualMaschineHandler.cs b/src/Server/Insight.Server2/Network/Agent/Handlers/VirtualMaschineHandler.cs deleted file mode 100644 index c70dd02..0000000 --- a/src/Server/Insight.Server2/Network/Agent/Handlers/VirtualMaschineHandler.cs +++ /dev/null @@ -1,173 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace Insight.Server.Network.Agent.Handlers; - -public class VirtualMaschineHandler(IMongoDatabase database) : IMessageHandler -{ - private readonly IMongoDatabase _database = database; - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Collection virtualMaschines: - await OnVirtualMaschinesAsync(sender, virtualMaschines, cancellationToken); - break; - } - } - - private async ValueTask OnVirtualMaschinesAsync(AgentSession session, List? virtualMaschines, CancellationToken cancellationToken) - { - var agentEntity = await _database.Agent().Find(Builders.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken); - if (agentEntity is null) return; - - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return; - - var batch = ObjectId.GenerateNewId().ToString(); - var date = DateTime.Now; - - // virtual maschines - if (virtualMaschines is not null && virtualMaschines.Count != 0) - { - var virtualMaschineBulk = new List>(); - - foreach (var virtualMaschine in virtualMaschines) - { - var virtualMaschineFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.UniqueId, virtualMaschine.Id.ToString()) - }); - - var virtualMaschineUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.UniqueId, virtualMaschine.Id.ToString()) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.Name, virtualMaschine?.Name) - .Set(p => p.Notes, virtualMaschine?.Notes) - .Set(p => p.Enabled, virtualMaschine?.Enabled?.ToString()) - .Set(p => p.EnabledDefault, virtualMaschine?.EnabledDefault?.ToString()) - .Set(p => p.Health, virtualMaschine?.HealthState?.ToString()) - .Set(p => p.Status, virtualMaschine?.Status) - .Set(p => p.OnTime, virtualMaschine?.OnTime) - .Set(p => p.ReplicationState, virtualMaschine?.ReplicationState?.ToString()) - .Set(p => p.ReplicationHealth, virtualMaschine?.ReplicationHealth?.ToString()) - .Set(p => p.ConfigurationVersion, virtualMaschine?.ConfigurationVersion) - .Set(p => p.IntegrationServicesVersionState, virtualMaschine?.IntegrationServicesVersionState?.ToString()) - .Set(p => p.ProcessId, virtualMaschine?.ProcessId) - .Set(p => p.NumberOfProcessors, virtualMaschine?.NumberOfProcessors) - .Set(p => p.ProcessorLoad, virtualMaschine?.ProcessorLoad) - .Set(p => p.MemoryAvailable, virtualMaschine?.MemoryAvailable) - .Set(p => p.MemoryUsage, virtualMaschine?.MemoryUsage) - .Set(p => p.InstallDate, virtualMaschine?.InstallDate) - .Set(p => p.ConfigurationVersion, virtualMaschine?.ConfigurationVersion) - .Set(p => p.TimeOfLastStateChange, virtualMaschine?.TimeOfLastStateChange) - .Set(p => p.LastReplicationTime, virtualMaschine?.LastReplicationTime) - .Set(p => p.Os, virtualMaschine?.GuestOperatingSystem); - - virtualMaschineBulk.Add(new UpdateOneModel(virtualMaschineFilter, virtualMaschineUpdate) - { - IsUpsert = true - }); - } - - virtualMaschineBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var virtualMaschineResult = await _database.HostHypervisorVirtualMaschine().BulkWriteAsync(virtualMaschineBulk, cancellationToken: cancellationToken); - } - - // virtual maschine configurations - - if (virtualMaschines is not null && virtualMaschines.Count != 0) - { - var configurationBulk = new List>(); - - foreach (var virtualmaschine in virtualMaschines) - { - var virtualMaschineId = await _database.HostHypervisorVirtualMaschine() - .Find(p => p.Host == hostEntity.Id && p.UniqueId == virtualmaschine.Id.ToString()) - .Project(p => p.Id) - .FirstOrDefaultAsync(cancellationToken: default); - - if (virtualmaschine.Configurations is not null && virtualmaschine.Configurations.Count != 0) - { - foreach (var config in virtualmaschine.Configurations) - { - var configFilter = Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Eq(x => x.VirtualMaschine, virtualMaschineId), - Builders.Filter.Eq(x => x.UniqueId, config.Id) - }); - - // custom "notes" concat - string notes = string.Empty; - - if (config?.Notes is not null) - foreach (var n in config.Notes) notes += n; - - if (config?.Id is null) continue; - - var configUpdate = Builders.Update - .SetOnInsert(p => p.Insert, date) - .SetOnInsert(p => p.Host, hostEntity.Id) - .SetOnInsert(p => p.VirtualMaschine, virtualMaschineId) - .SetOnInsert(p => p.UniqueId, config.Id) - .Set(p => p.Update, date) - .Set(p => p.Batch, batch) - - .Set(p => p.ParentId, config.ParentId) - .Set(p => p.Type, config.Type) - .Set(p => p.Name, config.Name) - .Set(p => p.Notes, notes) - .Set(p => p.CreationTime, config.CreationTime) - .Set(p => p.Generation, config.Generation) - .Set(p => p.Architecture, config.Architecture) - .Set(p => p.SecureBootEnabled, config.SecureBootEnabled) - .Set(p => p.IsAutomaticSnapshot, config.IsAutomaticSnapshot) - .Set(p => p.AutomaticStartupAction, config.AutomaticStartupAction?.ToString()) - .Set(p => p.AutomaticShutdownAction, config.AutomaticShutdownAction?.ToString()) - .Set(p => p.AutomaticRecoveryAction, config.AutomaticRecoveryAction?.ToString()) - .Set(p => p.AutomaticSnapshotsEnabled, config.AutomaticSnapshotsEnabled) - .Set(p => p.BaseBoardSerialNumber, config.BaseBoardSerialNumber) - .Set(p => p.BIOSSerialNumber, config.BIOSSerialNumber) - .Set(p => p.BIOSGUID, config.BIOSGUID) - .Set(p => p.ConfigurationDataRoot, config.ConfigurationDataRoot) - .Set(p => p.ConfigurationFile, config.ConfigurationFile) - .Set(p => p.GuestStateDataRoot, config.GuestStateDataRoot) - .Set(p => p.GuestStateFile, config.GuestStateFile) - .Set(p => p.SnapshotDataRoot, config.SnapshotDataRoot) - .Set(p => p.SuspendDataRoot, config.SuspendDataRoot) - .Set(p => p.SwapFileDataRoot, config.SwapFileDataRoot); - - configurationBulk.Add(new UpdateOneModel(configFilter, configUpdate) - { - IsUpsert = true - }); - } - } - } - - configurationBulk.Add(new DeleteManyModel(Builders.Filter.And(new List> - { - Builders.Filter.Eq(x => x.Host, hostEntity.Id), - Builders.Filter.Ne(x => x.Batch, batch) - }))); - - var configurationResult = await _database.HostVirtualMaschineConfig().BulkWriteAsync(configurationBulk, cancellationToken: cancellationToken); - } - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Remote/Handlers/RemoteHandler.cs b/src/Server/Insight.Server2/Network/Remote/Handlers/RemoteHandler.cs deleted file mode 100644 index 9e96aa7..0000000 --- a/src/Server/Insight.Server2/Network/Remote/Handlers/RemoteHandler.cs +++ /dev/null @@ -1,104 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Remote.Messages; -using Microsoft.Extensions.Logging; -using Vaitr.Bus; -using Vaitr.Network; - -namespace Insight.Server.Network.Remote.Handlers; - -public class RemoteHandler(Bus bus, ISessionPool remotePool, ILogger logger) : IMessageHandler -{ - private readonly Bus _bus = bus; - private readonly ISessionPool _remotePool = remotePool; - private readonly ILogger _logger = logger; - - public async ValueTask HandleAsync(RemoteSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - if (message is RemoteSessionRequest sessionRequest) - { - await OnSessionRequest(sender, sessionRequest, cancellationToken); - } - else if (message is CastRequestResponse castRequestResponse) - { - await OnCastRequestResponse(sender, castRequestResponse, cancellationToken); - } - else if (message is CastMetric metricData) - { - await OnMetricData(sender, metricData, cancellationToken); - } - else if (message is CastScreen screenData) - { - await OnScreenData(sender, screenData, cancellationToken); - } - else if (message is CastCursor cursorData) - { - await OnCursorData(sender, cursorData, cancellationToken); - } - else if (message is CastClipboardReceived clipboardData) - { - await OnClipboardData(sender, clipboardData, cancellationToken); - } - else if (message is CastAudio audioData) - { - await OnAudioData(sender, audioData, cancellationToken); - } - } - - private async Task OnSessionRequest(RemoteSession session, RemoteSessionRequest sessionRequest, CancellationToken cancellationToken) - { - _logger.LogInformation("Remote {session} => SessionRequest", session.Id); - - session.Mode = sessionRequest.Mode; - - await session.SendAsync(new RemoteSessionResponse - { - SessionId = session.Id - }, cancellationToken); - } - - private async Task OnCastRequestResponse(RemoteSession session, CastRequestResponse castRequestResponse, CancellationToken cancellationToken) - { - await _bus.PublishAsync(castRequestResponse, cancellationToken); - } - - private async Task OnMetricData(RemoteSession session, CastMetric streamMetrics, CancellationToken cancellationToken) - { - //_logger.LogInformation($"Remote {session.Id} => MetricData"); - - await _bus.PublishAsync(streamMetrics, cancellationToken); - } - - private async Task OnScreenData(RemoteSession session, CastScreen screenData, CancellationToken cancellationToken) - { - //_logger.LogInformation($"Remote {session.Id} => ScreenData"); - - await _bus.PublishAsync(screenData, cancellationToken); - - await session.SendAsync(new CastScreenReceived - { - Timestamp = screenData.Timestamp - }, cancellationToken); - } - - private async Task OnCursorData(RemoteSession session, CastCursor cursorChanged, CancellationToken cancellationToken) - { - //_logger.LogInformation($"Remote {session.Id} => CursorData"); - - await _bus.PublishAsync(cursorChanged, cancellationToken); - } - - private async Task OnClipboardData(RemoteSession session, CastClipboardReceived clipboardChanged, CancellationToken cancellationToken) - { - _logger.LogInformation("Remote {session} => ClipboardData", session.Id); - - await _bus.PublishAsync(clipboardChanged, cancellationToken); - } - - private async Task OnAudioData(RemoteSession session, CastAudio audioSample, CancellationToken cancellationToken) - { - _logger.LogInformation("Remote {session} => AudioData", session.Id); - - await _bus.PublishAsync(audioSample, cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Remote/RemoteSession.cs b/src/Server/Insight.Server2/Network/Remote/RemoteSession.cs deleted file mode 100644 index 1da69a2..0000000 --- a/src/Server/Insight.Server2/Network/Remote/RemoteSession.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Insight.Domain.Enums; -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Server.Network.Web; -using Microsoft.Extensions.Logging; -using Vaitr.Network; - -namespace Insight.Server.Network.Remote; - -public class RemoteSession( - ISessionPool webPool, - IEnumerable> handlers, - ISerializer serializer, - ILogger logger) : TcpSession(serializer, logger) -{ - public string Id { get; } = GenerateRandomId(); - public RemoteControlMode Mode { get; set; } - - private readonly ISessionPool _webPool = webPool; - private readonly IEnumerable> _handlers = handlers; - - public async ValueTask ProxyAsync(TMessage message, CancellationToken cancellationToken) - where TMessage : IMessage - { - // check if web online - if (_webPool.FirstOrDefault().Value is not WebSession web) return; - - // proxy-send request packet to web - await web.SendAsync(new Proxy - { - Message = message - }, cancellationToken); - } - - protected override ValueTask OnConnectedAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Remote ({ep?}) connected", RemoteEndPoint); - return default; - } - - protected override ValueTask OnDisconnectedAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Remote ({ep?}) disconnected", RemoteEndPoint); - return default; - } - - protected override async ValueTask OnSentAsync(IPacketContext context, CancellationToken cancellationToken) - { - await base.OnSentAsync(context, cancellationToken); - } - - protected override async ValueTask OnReceivedAsync(IPacketContext context, CancellationToken cancellationToken) - { - await base.OnReceivedAsync(context, cancellationToken); - - foreach (var handler in _handlers) - { - try - { - await handler.HandleAsync(this, context.Packet, cancellationToken); - } - catch (Exception ex) - { - _logger.LogWarning("Remote ({ep?}) {ex}", RemoteEndPoint, ex.ToString()); - } - } - } - - protected override ValueTask OnHeartbeatAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Remote ({ep?}) Heartbeat", RemoteEndPoint); - return default; - } - - private static string GenerateRandomId() - { - var random = new Random(); - string? sessionId = string.Empty; - - for (var i = 0; i < 3; i++) sessionId += random.Next(0, 999).ToString().PadLeft(3, '0'); - return sessionId; - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Shared/ProxyHandler.cs b/src/Server/Insight.Server2/Network/Shared/ProxyHandler.cs deleted file mode 100644 index 0a003b3..0000000 --- a/src/Server/Insight.Server2/Network/Shared/ProxyHandler.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Insight.Domain.Network.Agent.Messages; -using Insight.Infrastructure.Entities; -using Insight.Server.Network.Agent; -using Insight.Server.Network.Web; -using Microsoft.Extensions.Logging; -using MongoDB.Driver; -using Vaitr.Network; - -namespace Insight.Server.Network.Globals; - -public class ProxyHandler( - ISessionPool agentPool, - ISessionPool webPool, - IMongoDatabase database, - ILogger logger) : IMessageHandler, IMessageHandler -{ - private readonly ISessionPool _agentPool = agentPool; - private readonly ISessionPool _webPool = webPool; - private readonly IMongoDatabase _database = database; - private readonly ILogger _logger = logger; - - public async ValueTask HandleAsync(WebSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Proxy proxyRequest: - await OnProxyRequestAsync(sender, proxyRequest, cancellationToken); - break; - } - } - - public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage - { - switch (message) - { - case Proxy proxyResponse: - await OnProxyResponseAsync(sender, proxyResponse, cancellationToken); - break; - } - } - - private async ValueTask OnProxyRequestAsync(WebSession session, Proxy request, CancellationToken cancellationToken) - { - // get host - var hostEntity = await _database.Host() - .Find(Builders - .Filter - .Eq(p => p.Id, request.ProxyId)) - .FirstOrDefaultAsync(cancellationToken); - - if (hostEntity is null) - { - _logger.LogWarning("hostEntity is null"); - return; - } - - // get agent - var agentEntity = await _database.Agent() - .Find(Builders - .Filter - .Eq(p => p.Id, hostEntity.Agent)) - .FirstOrDefaultAsync(cancellationToken); - - if (agentEntity is null) - { - _logger.LogWarning("agentEntity is null"); - return; - } - - // check if agent online - if (_agentPool.FirstOrDefault(p => p.Value.Id == agentEntity.Id).Value is not AgentSession agent) return; - - // proxy-send request packet to agent - await agent.SendAsync(request, cancellationToken); - } - - private async ValueTask OnProxyResponseAsync(AgentSession session, Proxy response, CancellationToken cancellationToken) - { - // check if web online - if (_webPool.FirstOrDefault().Value is not WebSession web) return; - - await web.SendAsync(response, cancellationToken); - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Network/Web/WebSession.cs b/src/Server/Insight.Server2/Network/Web/WebSession.cs deleted file mode 100644 index 7603f96..0000000 --- a/src/Server/Insight.Server2/Network/Web/WebSession.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Insight.Domain.Interfaces; -using Insight.Domain.Network; -using Microsoft.Extensions.Logging; -using Vaitr.Network; - -namespace Insight.Server.Network.Web; - -public class WebSession(IEnumerable> handlers, ISerializer serializer, ILogger logger) : TcpSession(serializer, logger) -{ - public string? Id { get; set; } - - private readonly IEnumerable> _handlers = handlers; - - protected override ValueTask OnConnectedAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Web ({ep?}) connected", RemoteEndPoint); - return default; - } - - protected override ValueTask OnDisconnectedAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Web ({ep?}) disconnected", RemoteEndPoint); - return default; - } - - protected override async ValueTask OnSentAsync(IPacketContext context, CancellationToken cancellationToken) - { - await base.OnSentAsync(context, cancellationToken); - } - - protected override async ValueTask OnReceivedAsync(IPacketContext context, CancellationToken cancellationToken) - { - await base.OnReceivedAsync(context, cancellationToken); - - foreach (var handler in _handlers) - { - try - { - await handler.HandleAsync(this, context.Packet, cancellationToken); - } - catch (Exception ex) - { - _logger.LogWarning("Web ({ep?}) {ex}", RemoteEndPoint, ex.ToString()); - } - } - } - - protected override ValueTask OnHeartbeatAsync(CancellationToken cancellationToken) - { - _logger.LogInformation("Web ({ep?}) Heartbeat", RemoteEndPoint); - return default; - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/Properties/launchSettings.json b/src/Server/Insight.Server2/Properties/launchSettings.json deleted file mode 100644 index 060a2b2..0000000 --- a/src/Server/Insight.Server2/Properties/launchSettings.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { - "Development": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": false, - "launchUrl": "swagger", - "applicationUrl": "http://localhost:5001", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Production": { - "commandName": "Project", - "applicationUrl": "http://localhost:5001" - } - } -} diff --git a/src/Server/Insight.Server2/Services/DispatchService.cs b/src/Server/Insight.Server2/Services/DispatchService.cs deleted file mode 100644 index 6f08467..0000000 --- a/src/Server/Insight.Server2/Services/DispatchService.cs +++ /dev/null @@ -1,148 +0,0 @@ -using Insight.Domain.Enums; -using Insight.Infrastructure; -using Insight.Infrastructure.Entities; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using MongoDB.Driver; - -namespace Insight.Server.Services; - -internal class DispatchService(HttpClient httpClient, IMongoDatabase database, IConfiguration configuration, ILogger logger) : BackgroundService -{ - private readonly HttpClient _httpClient = httpClient; - private readonly IMongoDatabase _database = database; - private readonly IConfiguration _configuration = configuration; - private readonly ILogger _logger = logger; - - protected override async Task ExecuteAsync(CancellationToken cancellationToken) - { - _logger.LogTrace("ExecuteAsync"); - - var enabled = _configuration.GetValue(Appsettings.Dispatch.Webmatic) ?? throw new Exception($"{Appsettings.Dispatch.Webmatic} value not set (appsettings)"); - if (enabled is false) return; - - try - { - while (cancellationToken.IsCancellationRequested is false) - { - await DispatchAsync(cancellationToken); - await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); - } - } - catch (OperationCanceledException) { } - catch (Exception) { } - } - - private async ValueTask DispatchAsync(CancellationToken cancellationToken) - { - _logger.LogTrace($"DispatchAsync"); - - var pendings = await _database.HostLogMonitoring() - .Find(Builders - .Filter.Eq(p => p.Dispatch, DispatchEnum.Pending.ToString())) - .Limit(10) - .ToListAsync(cancellationToken); - - if (pendings is null || pendings.Count == 0) return; - - foreach (var entity in pendings) - { - try - { - var result = await SendAsync(entity, default); - - await _database.HostLogMonitoring() - .UpdateOneAsync(Builders.Filter - .Eq(p => p.Id, entity.Id), Builders - .Update - .Set(p => p.Dispatch, result.ToString()), cancellationToken: default); - } - catch (Exception ex) - { - _logger.LogError("{exception}", ex.Message); - } - finally - { - // webmatic safety offset - await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken: default); - } - } - } - - private async ValueTask SendAsync(HostLogMonitoringEntity monitoring, CancellationToken cancellationToken) - { - _logger.LogTrace("SendAsync ({monitoring})", monitoring); - - var monitoringApi = Monitoring.LogUri; - var monitoringContent = new List>(); - var monitoringResult = new List>(); - - // adjust by category - if (Enum.TryParse(monitoring.Category, true, out var monitoringCategory) is false) return DispatchEnum.Failure; - - if (monitoringCategory == CategoryEnum.Monitoring) monitoringApi = Monitoring.StatusUri; - - // set category (if log) - if (monitoringApi == Monitoring.LogUri) monitoringContent.Add(new KeyValuePair("category", monitoringCategory.ToString())); - - // host resolve - var hostEntity = await _database.Host().Find(Builders.Filter.Eq(p => p.Id, monitoring.Host?.ToString())).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return DispatchEnum.Failure; - - // customer resolve - var customerEntity = await _database.Customer().Find(Builders.Filter.Eq(p => p.Id, hostEntity.Customer)).FirstOrDefaultAsync(cancellationToken); - if (hostEntity is null) return DispatchEnum.Failure; - - // set host name if no remote host set - if (string.IsNullOrEmpty(monitoring.Hostname)) monitoring.Hostname = hostEntity.Name; - - // remove any domain from hostname - if (monitoring.Hostname is not null && monitoring.Hostname.Contains('.')) monitoring.Hostname = monitoring.Hostname.Split(".")[0]; - - // add customer tag to hostname - monitoring.Hostname += $".{customerEntity.Tag}"; - - // if task null, set hostname - if (string.IsNullOrEmpty(monitoring.Task)) monitoring.Task = monitoring.Hostname; - - // insert hostname as computer-name (lowercase) - monitoringContent.Add(new KeyValuePair("computer_name", monitoring.Hostname.ToLower())); - - // insert converted status (api styled) - if (Enum.TryParse(monitoring.Status, true, out var monitoringStatus) is false) return DispatchEnum.Failure; - - monitoringContent.Add(monitoringStatus switch - { - StatusEnum.Information => new KeyValuePair("status", monitoringApi == Monitoring.StatusUri ? "erfolgreich" : "info"), - StatusEnum.Warning => new KeyValuePair("status", monitoringApi == Monitoring.StatusUri ? "Interaktion" : "warning"), - StatusEnum.Error => new KeyValuePair("status", monitoringApi == Monitoring.StatusUri ? "fehlgeschlagen" : "error"), - _ => throw new NotImplementedException(nameof(monitoringStatus)) - }); - - // insert task, timestamp, message, - monitoringContent.Add(new KeyValuePair("task", monitoring.Task)); - - if (monitoring.Timestamp is not null) - { - monitoringContent.Add(new KeyValuePair("timestamp", monitoring.Timestamp.Value.ToLocalTime().ToString())); - } - - if (string.IsNullOrWhiteSpace(monitoring.Message) is false) - { - monitoringContent.Add(new KeyValuePair("message", monitoring.Message)); - } - - // send message - var result = await _httpClient.PostAsync(monitoringApi, new FormUrlEncodedContent(monitoringContent), default); - - monitoringResult.Add(new KeyValuePair("HttpStatusCode", result.StatusCode.ToString())); - monitoringResult.Add(new KeyValuePair("HttpResponseMessage", await result.Content.ReadAsStringAsync(default))); - - // if content != "OK" - if (result is null || result.IsSuccessStatusCode == false) return DispatchEnum.Failure; - - // success - return DispatchEnum.Success; - } -} \ No newline at end of file diff --git a/src/Server/Insight.Server2/WeatherForecast.cs b/src/Server/Insight.Server2/WeatherForecast.cs deleted file mode 100644 index 9e81231..0000000 --- a/src/Server/Insight.Server2/WeatherForecast.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Insight.Server2 -{ - public class WeatherForecast - { - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } - } -} diff --git a/src/Server/Insight.Server2/appsettings.Development.json b/src/Server/Insight.Server2/appsettings.Development.json deleted file mode 100644 index b133754..0000000 --- a/src/Server/Insight.Server2/appsettings.Development.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*", - "Urls": "http://127.0.0.1:5001", - - "influx.endpoint": "http://10.22.70.40:8086", - "influx.endpoint0": "http://192.168.1.10:8086", - "influx.token": "253pd3prqWfwhyLH3eirJkgCE5n6tzPVZcRwRrDcla9z1fIPVLB6tGqJ641e4yI5LY8lxb1VfJX_HrrIXMEv5A==", - "influx.token0": "x7ldV7EYb8ocnNAVbtpfpX0nS2HMyPxq3WyBPrVWBRT3C3tCjU8L8h5WPeESFnUqVvYubOM48GBydz5b3n69YA==", - "influx.org": "insight", - "influx.bucket": "insight", - "influx.service": "server", - - "mongo.connection": "mongodb://db.insight.local:27017", - - "agent.port": 3002, - "agent.certificate": "localhost.pfx", - "agent.certificate.password": "Webmatic12", - - "web.port": 3001, - "web.certificate": "localhost.pfx", - "web.certificate.password": "Webmatic12", - - "dispatch.webmatic": false -} diff --git a/src/Server/Insight.Server2/appsettings.json b/src/Server/Insight.Server2/appsettings.json deleted file mode 100644 index 1726f9b..0000000 --- a/src/Server/Insight.Server2/appsettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*", - "Urls": "http://127.0.0.1:5001", - - "influx.endpoint": "http://10.22.70.40:8086", - "influx.endpoint0": "http://192.168.1.10:8086", - "influx.token": "253pd3prqWfwhyLH3eirJkgCE5n6tzPVZcRwRrDcla9z1fIPVLB6tGqJ641e4yI5LY8lxb1VfJX_HrrIXMEv5A==", - "influx.token0": "x7ldV7EYb8ocnNAVbtpfpX0nS2HMyPxq3WyBPrVWBRT3C3tCjU8L8h5WPeESFnUqVvYubOM48GBydz5b3n69YA==", - "influx.org": "insight", - "influx.bucket": "insight", - "influx.service": "server", - - "mongo.connection": "mongodb://127.0.0.1:27017", - - "agent.port": 3002, - "agent.certificate": "localhost.pfx", - "agent.certificate.password": "Webmatic12", - - "web.port": 3001, - "web.certificate": "localhost.pfx", - "web.certificate.password": "Webmatic12", - - "dispatch.webmatic": true -} diff --git a/src/Setup/Insight.Setup.Windows/Insight.Setup.Windows.csproj b/src/Setup/Insight.Setup.Windows/Insight.Setup.Windows.csproj index 3a2de0e..b36a2d9 100644 --- a/src/Setup/Insight.Setup.Windows/Insight.Setup.Windows.csproj +++ b/src/Setup/Insight.Setup.Windows/Insight.Setup.Windows.csproj @@ -11,6 +11,7 @@ Insight 2023.12.14.0 none + true diff --git a/src/Updater/Insight.Updater/Insight.Updater.csproj b/src/Updater/Insight.Updater/Insight.Updater.csproj index 222459b..816226a 100644 --- a/src/Updater/Insight.Updater/Insight.Updater.csproj +++ b/src/Updater/Insight.Updater/Insight.Updater.csproj @@ -11,6 +11,7 @@ enable enable none + true diff --git a/src/Updater/Insight.Updater/Program.cs b/src/Updater/Insight.Updater/Program.cs index 55d2eab..db97d63 100644 --- a/src/Updater/Insight.Updater/Program.cs +++ b/src/Updater/Insight.Updater/Program.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using System.Diagnostics; namespace Insight.Updater.Windows; @@ -33,8 +34,7 @@ internal class Program options.SingleLine = true; options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff "; }); - - options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/updater_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); + options.AddFile(Configuration.AppDirectory?.FullName + "/logs/" + Process.GetCurrentProcess().ProcessName + "_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); }); builder.ConfigureServices((host, services) => diff --git a/src/Web/Insight.Web/Extensions/ServiceExtensions.cs b/src/Web/Insight.Web/Extensions/ServiceExtensions.cs index ee933f6..79b37e3 100644 --- a/src/Web/Insight.Web/Extensions/ServiceExtensions.cs +++ b/src/Web/Insight.Web/Extensions/ServiceExtensions.cs @@ -1,13 +1,57 @@ using Blazored.LocalStorage; using Blazored.SessionStorage; +using Insight.Domain.Interfaces; +using Insight.Domain.Network; +using Insight.Infrastructure; +using Insight.Web.Network.Broker; +using Insight.Web.Network.Broker.Handlers; +using Insight.Web.Network.Remote; +using Insight.Web.Network.Remote.Handlers; using Insight.Web.Services; using Microsoft.AspNetCore.Components.Server.Circuits; using MudBlazor.Services; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using System.Net; +using Vaitr.Network; +using Vaitr.Network.Hosting; namespace Insight.Web.Extensions; public static class ServiceExtensions { + internal static WebApplicationBuilder AddMetrics(this WebApplicationBuilder builder) + { + builder.Services.AddOpenTelemetry() + .WithMetrics(provider => + { + provider.ConfigureResource(configure => + { + configure.Clear(); + configure.AddService(builder.Configuration.GetValue(Appsettings.Influx.Service) ?? throw new Exception($"{Appsettings.Influx.Service} value not set (appsettings)")); + }) + .AddRuntimeInstrumentation() + .AddProcessInstrumentation() + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + //.AddMeter("test") + .AddInfluxDBMetricsExporter(configure => + { + configure.Endpoint = builder.Configuration.GetValue(Appsettings.Influx.Endpoint) ?? throw new Exception($"{Appsettings.Influx.Endpoint} value not set (appsettings)"); + configure.Token = builder.Configuration.GetValue(Appsettings.Influx.Token) ?? throw new Exception($"{Appsettings.Influx.Token} value not set (appsettings)"); + configure.Org = builder.Configuration.GetValue(Appsettings.Influx.Organization) ?? throw new Exception($"{Appsettings.Influx.Organization} value not set (appsettings)"); + configure.Bucket = builder.Configuration.GetValue(Appsettings.Influx.Bucket) ?? throw new Exception($"{Appsettings.Influx.Bucket} value not set (appsettings)"); + + configure.MetricExportIntervalMilliseconds = 1000; + }); + } + ); + + //builder.Services.AddSingleton(); + + return builder; + } + internal static IServiceCollection AddWebServices(this IServiceCollection services) { // HOSTS @@ -42,4 +86,46 @@ public static class ServiceExtensions return services; } + + internal static IServiceCollection AddBrokerServices(this IServiceCollection services, IConfiguration configuration) + { + services.UseHostedClient(options => + { + options.Host = configuration.GetValue(Appsettings.Backend.Host) ?? throw new Exception($"{Appsettings.Backend.Host} value not set (appsettings)"); + options.Port = configuration.GetValue(Appsettings.Backend.Port) ?? throw new Exception($"{Appsettings.Backend.Port} value not set (appsettings)"); + options.Keepalive = 10000; + options.Timeout = 30000; + options.Encryption = Encryption.Tls12; + options.Compression = true; + + options.UseSerializer>(); + }); + + services.AddSingleton, AgentHandler>(); + + return services; + } + + internal static IServiceCollection AddRemoteServices(this IServiceCollection services, IConfiguration configuration) + { + services.UseHostedServer(options => + { + options.Address = IPAddress.Any; + options.Port = configuration.GetValue(Appsettings.Remote.Port) ?? throw new Exception($"{Appsettings.Remote.Port} value not set (appsettings)"); + options.Keepalive = 10000; + options.Timeout = 30000; + options.Backlog = 128; + + options.Compression = true; + options.Encryption = Encryption.Tls12; + options.Certificate = configuration.GetValue(Appsettings.Remote.Certificate) ?? throw new Exception($"{Appsettings.Remote.Certificate} value not set (appsettings)"); + options.CertificatePassword = configuration.GetValue(Appsettings.Remote.CertificatePassword) ?? throw new Exception($"{Appsettings.Remote.CertificatePassword} value not set (appsettings)"); + + options.UseSerializer>(); + }); + + services.AddSingleton, RemoteHandler>(); + + return services; + } } \ No newline at end of file diff --git a/src/Web/Insight.Web/Insight.Web.csproj b/src/Web/Insight.Web/Insight.Web.csproj index ffbd257..0cba988 100644 --- a/src/Web/Insight.Web/Insight.Web.csproj +++ b/src/Web/Insight.Web/Insight.Web.csproj @@ -12,6 +12,7 @@ false false none + true @@ -29,13 +30,18 @@ + + + + + + + - - diff --git a/src/Web/Insight.Web/Program.cs b/src/Web/Insight.Web/Program.cs index 6fc43a8..1529e47 100644 --- a/src/Web/Insight.Web/Program.cs +++ b/src/Web/Insight.Web/Program.cs @@ -1,17 +1,9 @@ using Insight.Domain.Constants; -using Insight.Domain.Interfaces; -using Insight.Domain.Network; using Insight.Infrastructure; using Insight.Web.Extensions; using Insight.Web.Middleware; -using Insight.Web.Network.Broker; -using Insight.Web.Network.Broker.Handlers; -using Insight.Web.Network.Remote; -using Insight.Web.Network.Remote.Handlers; -using System.Net; +using System.Diagnostics; using Vaitr.Bus; -using Vaitr.Network; -using Vaitr.Network.Hosting; namespace Insight.Web; @@ -22,43 +14,26 @@ internal class Program var builder = WebApplication.CreateBuilder(args); builder.Host.UseWindowsService(options => options.ServiceName = "insight_web"); builder.Host.UseSystemd(); + builder.WebHost.UseStaticWebAssets(); - // LOGGING + // Configuration + builder.Configuration.Defaults(); + + // Logging builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(LogLevel.Trace); builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Error); builder.Logging.AddFilter("MudBlazor", LogLevel.Warning); - builder.Logging.AddSimpleConsole(options => { options.IncludeScopes = false; options.SingleLine = true; options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff "; }); + builder.Logging.AddFile(Configuration.AppDirectory?.FullName + "/logs/" + Process.GetCurrentProcess().ProcessName + "_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); - builder.Logging.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/web_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}"); - - // BROKER - builder.Services.AddBrokerServices(builder.Configuration); - - // REMOTE - builder.Services.AddRemoteServices(builder.Configuration); - - // ASSETS - builder.WebHost.UseStaticWebAssets(); - - // IDENTITY - builder.Services.AddIdentityServices(builder.Configuration); - builder.Services.AddCustomAuthentication(builder.Configuration); - builder.Services.AddSingleton(); - - // SECURITY - builder.Services.AddAuthorization(); - - // WEBSERVICES + // Services builder.Services.AddWebServices(); - builder.Services.AddProxyServices(); - builder.Services.AddRoutingServices(); builder.Services.AddSignalR(options => { options.EnableDetailedErrors = true; @@ -66,19 +41,23 @@ internal class Program //options.StreamBufferCapacity = 1024; options.EnableDetailedErrors = true; }); - - // INFRASTRUCTURE builder.Services.AddDatabase(builder.Configuration); - builder.Services.AddInfrastructureServices(); + builder.Services.AddIdentity(builder.Configuration); + builder.Services.AddIdentityServices(); + builder.Services.AddCustomAuthentication(builder.Configuration); + builder.Services.AddAuthorization(); + builder.Services.AddBrokerServices(builder.Configuration); + builder.Services.AddRemoteServices(builder.Configuration); + builder.Services.AddSingleton(); - // WEB:APP + // Modules + builder.AddDefaults(); + builder.AddMetrics(); + + // HTTP Pipeline var app = builder.Build(); - - // BASICS app.UseForwardedHeaders(); - //app.UseHttpsRedirection(); - // DEV-PROD SETTINGS if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); @@ -89,77 +68,14 @@ internal class Program //app.UseHsts(); } - // CORS - //app.UseCors(x => x - // .AllowAnyOrigin() - // .AllowAnyMethod() - // .AllowAnyHeader()); - - // ROUTING app.UseRouting(); - - // SECURITY //app.UseAuthentication(); app.UseAuthorization(); - - // MIDDLEWARE app.UseMiddleware(); - - // BLAZOR HUBS (SIGNALR) app.MapBlazorHub(); - - // FALLBACK app.MapFallbackToPage("/_Host"); - - // STATIC FILES app.UseStaticFiles(); - // HOST START await app.RunAsync().ConfigureAwait(false); } -} - -internal static class ServiceExtensions -{ - internal static IServiceCollection AddBrokerServices(this IServiceCollection services, IConfiguration configuration) - { - services.UseHostedClient(options => - { - options.Host = configuration.GetValue(Appsettings.Backend.Host) ?? throw new Exception($"{Appsettings.Backend.Host} value not set (appsettings)"); - options.Port = configuration.GetValue(Appsettings.Backend.Port) ?? throw new Exception($"{Appsettings.Backend.Port} value not set (appsettings)"); - options.Keepalive = 10000; - options.Timeout = 30000; - options.Encryption = Encryption.Tls12; - options.Compression = true; - - options.UseSerializer>(); - }); - - services.AddSingleton, AgentHandler>(); - - return services; - } - - internal static IServiceCollection AddRemoteServices(this IServiceCollection services, IConfiguration configuration) - { - services.UseHostedServer(options => - { - options.Address = IPAddress.Any; - options.Port = configuration.GetValue(Appsettings.Remote.Port) ?? throw new Exception($"{Appsettings.Remote.Port} value not set (appsettings)"); - options.Keepalive = 10000; - options.Timeout = 30000; - options.Backlog = 128; - - options.Compression = true; - options.Encryption = Encryption.Tls12; - options.Certificate = configuration.GetValue(Appsettings.Remote.Certificate) ?? throw new Exception($"{Appsettings.Remote.Certificate} value not set (appsettings)"); - options.CertificatePassword = configuration.GetValue(Appsettings.Remote.CertificatePassword) ?? throw new Exception($"{Appsettings.Remote.CertificatePassword} value not set (appsettings)"); - - options.UseSerializer>(); - }); - - services.AddSingleton, RemoteHandler>(); - - return services; - } } \ No newline at end of file diff --git a/src/Web/Insight.Web/appsettings.Development.json b/src/Web/Insight.Web/appsettings.Development.json index 6544bc9..ece4a60 100644 --- a/src/Web/Insight.Web/appsettings.Development.json +++ b/src/Web/Insight.Web/appsettings.Development.json @@ -2,8 +2,14 @@ "AllowedHosts": "*", "Urls": "http://127.0.0.1:5001", + // set in env vars + //"influx.endpoint": "http://127.0.0.1:8086", + //"influx.token": "", + "influx.org": "insight", + "influx.bucket": "insight", + "influx.service": "web", + "mongo.connection": "mongodb://db.insight.local:27017", - "mongo.connection0": "mongodb://insight.webmatic.de:27017", "server.host": "insight.local", "server.port": 3001, diff --git a/src/Web/Insight.Web/appsettings.json b/src/Web/Insight.Web/appsettings.json index bf3265f..f66168d 100644 --- a/src/Web/Insight.Web/appsettings.json +++ b/src/Web/Insight.Web/appsettings.json @@ -2,6 +2,13 @@ "AllowedHosts": "*", "Urls": "http://127.0.0.1:5001", + // set in env vars + //"influx.endpoint": "http://127.0.0.1:8086", + //"influx.token": "", + "influx.org": "insight", + "influx.bucket": "insight", + "influx.service": "web", + "mongo.connection": "mongodb://127.0.0.1:27017", "server.host": "127.0.0.1",