backend metrics implementation
This commit is contained in:
parent
a4ed1a5956
commit
62c22d057b
69 changed files with 494 additions and 3834 deletions
19
insight.sln
19
insight.sln
|
|
@ -27,8 +27,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{35BA5DCB-BEC
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Api", "src\Api\Insight.Api\Insight.Api.csproj", "{EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Api", "src\Api\Insight.Api\Insight.Api.csproj", "{EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6}"
|
||||||
EndProject
|
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}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Updater", "src\Updater\Insight.Updater\Insight.Updater.csproj", "{4875D70F-A96B-4EBA-99BE-218886D29BEB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Agent", "src\Agent\Insight.Agent\Insight.Agent.csproj", "{2A391CA2-F96B-4DB7-80AA-0668A5141640}"
|
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
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Infrastructure.Web", "src\Core\Insight.Infrastructure.Web\Insight.Infrastructure.Web.csproj", "{39B81A0D-A88C-44D3-9624-1A19C78A4310}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Insight.Infrastructure.Web", "src\Core\Insight.Infrastructure.Web\Insight.Infrastructure.Web.csproj", "{39B81A0D-A88C-44D3-9624-1A19C78A4310}"
|
||||||
EndProject
|
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
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{4875D70F-A96B-4EBA-99BE-218886D29BEB}.Debug|Any CPU.Build.0 = 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
|
{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}.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.ActiveCfg = Release|Any CPU
|
||||||
{39B81A0D-A88C-44D3-9624-1A19C78A4310}.Release|Any CPU.Build.0 = 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
|
{FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{9F7E88B2-7415-410C-9C31-7720596B0607}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{9F7E88B2-7415-410C-9C31-7720596B0607}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{FCAE9C42-1DCE-4C2E-BAE0-251C147903B4}.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}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -107,13 +101,12 @@ Global
|
||||||
{CA99B8CF-520A-4B48-ACCE-0A301C35A7FE} = {15D04093-4974-4B2F-AE8A-F3721F31767A}
|
{CA99B8CF-520A-4B48-ACCE-0A301C35A7FE} = {15D04093-4974-4B2F-AE8A-F3721F31767A}
|
||||||
{375EF474-512A-4410-86CF-46974E07C1F7} = {3F000016-069D-477E-ACA3-F643880B57E8}
|
{375EF474-512A-4410-86CF-46974E07C1F7} = {3F000016-069D-477E-ACA3-F643880B57E8}
|
||||||
{EF3188D7-338D-43DA-BF6B-D26E5BDAC3A6} = {35BA5DCB-BECC-4F51-8DD0-694C555D205A}
|
{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}
|
{4875D70F-A96B-4EBA-99BE-218886D29BEB} = {F2D241DB-7692-46DB-8A6A-958B365DAAF8}
|
||||||
{2A391CA2-F96B-4DB7-80AA-0668A5141640} = {140F73DD-29D3-4C44-809B-5B470880AA0D}
|
{2A391CA2-F96B-4DB7-80AA-0668A5141640} = {140F73DD-29D3-4C44-809B-5B470880AA0D}
|
||||||
{5C4697BD-BC97-484F-9DB1-CA87E2BEAA4B} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D}
|
{5C4697BD-BC97-484F-9DB1-CA87E2BEAA4B} = {D4D7BF4A-B2E3-470A-A14C-FC658FF7461D}
|
||||||
{AF313B47-3079-407F-91D1-9989C1E1AF2A} = {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}
|
{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
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {F376A326-7590-4E7E-AB9B-76CED8527AB0}
|
SolutionGuid = {F376A326-7590-4E7E-AB9B-76CED8527AB0}
|
||||||
|
|
|
||||||
33
src/Agent/Insight.Agent/Extensions/ServiceExtensions.cs
Normal file
33
src/Agent/Insight.Agent/Extensions/ServiceExtensions.cs
Normal file
|
|
@ -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<IMessageHandler<AgentSession>, DriveHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, InterfaceHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, MainboardHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, MemoryHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, OperationSystemHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, PrinterHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, ProcessorHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, ServiceHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, SessionHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, SoftwareHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, StoragePoolHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, SystemInfoHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, UpdateHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, UserHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, VideocardHandler>();
|
||||||
|
services.AddSingleton<IMessageHandler<AgentSession>, VirtualMaschineHandler>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using Insight.Agent.Network;
|
using Insight.Agent.Extensions;
|
||||||
|
using Insight.Agent.Network;
|
||||||
using Insight.Agent.Network.Handlers;
|
using Insight.Agent.Network.Handlers;
|
||||||
using Insight.Agent.Services;
|
using Insight.Agent.Services;
|
||||||
using Insight.Domain.Constants;
|
using Insight.Domain.Constants;
|
||||||
|
|
@ -9,7 +10,7 @@ using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Runtime.Versioning;
|
using System.Diagnostics;
|
||||||
using Vaitr.Network;
|
using Vaitr.Network;
|
||||||
using Vaitr.Network.Hosting;
|
using Vaitr.Network.Hosting;
|
||||||
|
|
||||||
|
|
@ -39,8 +40,7 @@ internal class Program
|
||||||
options.SingleLine = true;
|
options.SingleLine = true;
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
||||||
});
|
});
|
||||||
|
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}");
|
||||||
options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/agent_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.ConfigureServices((host, services) =>
|
builder.ConfigureServices((host, services) =>
|
||||||
|
|
@ -70,7 +70,7 @@ internal class Program
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, ProxyHandler>();
|
services.AddSingleton<IMessageHandler<AgentSession>, ProxyHandler>();
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, CustomHandler>();
|
services.AddSingleton<IMessageHandler<AgentSession>, CustomHandler>();
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows()) ServiceCollectionExtensions.InjectWindowsHandler(services);
|
if (OperatingSystem.IsWindows()) ServiceExtensions.InjectWindowsHandler(services);
|
||||||
|
|
||||||
// GLOBAL DEPENDENCIES
|
// GLOBAL DEPENDENCIES
|
||||||
services.AddTransient(provider => new HttpClient(new HttpClientHandler
|
services.AddTransient(provider => new HttpClient(new HttpClientHandler
|
||||||
|
|
@ -84,29 +84,3 @@ internal class Program
|
||||||
await host.RunAsync().ConfigureAwait(false);
|
await host.RunAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class ServiceCollectionExtensions
|
|
||||||
{
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
internal static IServiceCollection InjectWindowsHandler(this IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, DriveHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, InterfaceHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, MainboardHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, MemoryHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, OperationSystemHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, PrinterHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, ProcessorHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, ServiceHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, SessionHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, SoftwareHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, StoragePoolHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, SystemInfoHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, UpdateHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, UserHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, VideocardHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, VirtualMaschineHandler>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +1,49 @@
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Insight.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
using OpenTelemetry.Metrics;
|
||||||
|
using OpenTelemetry.Resources;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Insight.Api.Extensions;
|
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();
|
builder.Services.AddOpenTelemetry()
|
||||||
services.AddSwaggerGen(options =>
|
.WithMetrics(provider =>
|
||||||
|
{
|
||||||
|
provider.ConfigureResource(configure =>
|
||||||
|
{
|
||||||
|
configure.Clear();
|
||||||
|
configure.AddService(builder.Configuration.GetValue<string?>(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<Uri?>(Appsettings.Influx.Endpoint) ?? throw new Exception($"{Appsettings.Influx.Endpoint} value not set (appsettings)");
|
||||||
|
configure.Token = builder.Configuration.GetValue<string?>(Appsettings.Influx.Token) ?? throw new Exception($"{Appsettings.Influx.Token} value not set (appsettings)");
|
||||||
|
configure.Org = builder.Configuration.GetValue<string?>(Appsettings.Influx.Organization) ?? throw new Exception($"{Appsettings.Influx.Organization} value not set (appsettings)");
|
||||||
|
configure.Bucket = builder.Configuration.GetValue<string?>(Appsettings.Influx.Bucket) ?? throw new Exception($"{Appsettings.Influx.Bucket} value not set (appsettings)");
|
||||||
|
|
||||||
|
configure.MetricExportIntervalMilliseconds = 1000;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
//builder.Services.AddSingleton<BasicMetrics>();
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static WebApplicationBuilder AddSwagger(this WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
options.SwaggerDoc("v1", new OpenApiInfo
|
options.SwaggerDoc("v1", new OpenApiInfo
|
||||||
{
|
{
|
||||||
|
|
@ -53,6 +87,23 @@ public static class ServiceExtensions
|
||||||
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,15 +17,21 @@
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Exporter.InfluxDB" Version="1.0.0-alpha.3" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.7.0" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.4" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.7.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
||||||
<!--Unix Serilog stuff-->
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using Insight.Api.Extensions;
|
||||||
using Insight.Domain.Constants;
|
using Insight.Domain.Constants;
|
||||||
using Insight.Infrastructure;
|
using Insight.Infrastructure;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Insight.Api;
|
namespace Insight.Api;
|
||||||
|
|
||||||
|
|
@ -13,47 +14,37 @@ internal class Program
|
||||||
builder.Host.UseWindowsService();
|
builder.Host.UseWindowsService();
|
||||||
builder.Host.UseSystemd();
|
builder.Host.UseSystemd();
|
||||||
|
|
||||||
// LOGGER
|
// Configuration
|
||||||
|
builder.Configuration.Defaults();
|
||||||
|
|
||||||
|
// Logging
|
||||||
builder.Logging.ClearProviders();
|
builder.Logging.ClearProviders();
|
||||||
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
||||||
builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning);
|
builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning);
|
||||||
|
|
||||||
builder.Logging.AddSimpleConsole(options =>
|
builder.Logging.AddSimpleConsole(options =>
|
||||||
{
|
{
|
||||||
options.IncludeScopes = true;
|
options.IncludeScopes = true;
|
||||||
options.SingleLine = true;
|
options.SingleLine = true;
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
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}");
|
// Services
|
||||||
|
|
||||||
// INFRASTRUCTURE
|
|
||||||
builder.Services.AddDatabase(builder.Configuration);
|
builder.Services.AddDatabase(builder.Configuration);
|
||||||
builder.Services.AddInfrastructureServices();
|
builder.Services.AddIdentity(builder.Configuration);
|
||||||
|
builder.Services.AddIdentityServices();
|
||||||
// IDENTITY
|
|
||||||
builder.Services.AddIdentityServices(builder.Configuration);
|
|
||||||
builder.Services.AddBearerAuthentication(builder.Configuration);
|
builder.Services.AddBearerAuthentication(builder.Configuration);
|
||||||
builder.Services.AddTokenServices(builder.Configuration);
|
builder.Services.AddTokenServices(builder.Configuration);
|
||||||
|
|
||||||
// SECURITY
|
|
||||||
builder.Services.AddAuthorization();
|
builder.Services.AddAuthorization();
|
||||||
|
|
||||||
// WEBSERVICES
|
// Modules
|
||||||
builder.Services.AddProxyServices();
|
builder.AddDefaults();
|
||||||
builder.Services.AddRoutingServices();
|
builder.AddApiDefaults();
|
||||||
builder.Services.AddControllers();
|
builder.AddMetrics();
|
||||||
|
builder.AddSwagger();
|
||||||
// SWAGGER
|
|
||||||
builder.Services.AddSwaggerServices();
|
|
||||||
|
|
||||||
//builder.Services.AddControllers();
|
|
||||||
//builder.Services.AddEndpointsApiExplorer();
|
|
||||||
//builder.Services.AddSwaggerGen();
|
|
||||||
|
|
||||||
|
// HTTP Pipeline
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
app.UseForwardedHeaders();
|
app.UseForwardedHeaders();
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
|
|
@ -61,17 +52,7 @@ internal class Program
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseSwagger(options =>
|
app.ConfigureSwagger();
|
||||||
{
|
|
||||||
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.UseCors(x => x
|
app.UseCors(x => x
|
||||||
.AllowAnyOrigin()
|
.AllowAnyOrigin()
|
||||||
|
|
@ -93,6 +74,6 @@ internal class Program
|
||||||
ServeUnknownFileTypes = true
|
ServeUnknownFileTypes = true
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.RunAsync();
|
await app.RunAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,16 @@
|
||||||
{
|
{
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"Urls": "http://127.0.0.1:5000",
|
"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",
|
"mongo.connection": "mongodb://db.insight.local:27017",
|
||||||
|
|
||||||
"jwt.key": "x5dcaE8fiBmHfgsNrwIEtSWzZkz6gpouzKOIgEiVjxJnW28V1aUnYXF19IcnF5x",
|
"jwt.key": "x5dcaE8fiBmHfgsNrwIEtSWzZkz6gpouzKOIgEiVjxJnW28V1aUnYXF19IcnF5x",
|
||||||
"jwt.exp": 3600,
|
"jwt.exp": 3600,
|
||||||
"jwt.audience": "http://127.0.0.1:5000",
|
"jwt.audience": "http://127.0.0.1:5000",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,16 @@
|
||||||
{
|
{
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"Urls": "http://127.0.0.1:5000",
|
"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",
|
"mongo.connection": "mongodb://127.0.0.1:27017",
|
||||||
|
|
||||||
"jwt.key": "x5dcaE8fiBmHfgsNrwIEtSWzZkz6gpouzKOIgEiVjxJnW28V1aUnYXF19IcnF5x",
|
"jwt.key": "x5dcaE8fiBmHfgsNrwIEtSWzZkz6gpouzKOIgEiVjxJnW28V1aUnYXF19IcnF5x",
|
||||||
"jwt.exp": 3600,
|
"jwt.exp": 3600,
|
||||||
"jwt.audience": "https://insight.webmatic.de/api",
|
"jwt.audience": "https://insight.webmatic.de/api",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ public static class ConfigurationExtensions
|
||||||
{
|
{
|
||||||
configuration.Sources.Clear();
|
configuration.Sources.Clear();
|
||||||
configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||||
<PackageReference Include="Vaitr.Network" Version="2024.1.8" />
|
<PackageReference Include="Vaitr.Network" Version="2024.1.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -16,43 +16,29 @@ namespace Insight.Infrastructure;
|
||||||
|
|
||||||
public static partial class ServiceExtensions
|
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(
|
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||||
key: configuration.GetValue<string?>(Appsettings.Jwt.Key) ?? throw new Exception($"{Appsettings.Jwt.Key} value not set (appsettings)"),
|
|
||||||
expires: configuration.GetValue<int?>(Appsettings.Jwt.Exp) ?? throw new Exception($"{Appsettings.Jwt.Exp} value not set (appsettings)"),
|
|
||||||
audience: configuration.GetValue<Uri?>(Appsettings.Jwt.Audience) ?? throw new Exception($"{Appsettings.Jwt.Audience} value not set (appsettings)"),
|
|
||||||
issuer: configuration.GetValue<Uri?>(Appsettings.Jwt.Issuer) ?? throw new Exception($"{Appsettings.Jwt.Issuer} value not set (appsettings)"));
|
|
||||||
|
|
||||||
services.AddSingleton(options);
|
|
||||||
services.AddTransient<TokenService>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IServiceCollection AddProxyServices(this IServiceCollection services)
|
|
||||||
{
|
|
||||||
// add before routing
|
|
||||||
services.Configure<ForwardedHeadersOptions>(options =>
|
|
||||||
{
|
{
|
||||||
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||||
});
|
});
|
||||||
|
builder.Services.AddRouting(options =>
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IServiceCollection AddRoutingServices(this IServiceCollection services)
|
|
||||||
{
|
|
||||||
// add after proxy
|
|
||||||
services.AddRouting(options =>
|
|
||||||
{
|
{
|
||||||
options.LowercaseUrls = true;
|
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<string?>(Appsettings.Mongo.ConnectionString) ?? throw new Exception($"{Appsettings.Mongo.ConnectionString} value not set (appsettings)");
|
var connectionString = configuration.GetValue<string?>(Appsettings.Mongo.ConnectionString) ?? throw new Exception($"{Appsettings.Mongo.ConnectionString} value not set (appsettings)");
|
||||||
|
|
||||||
|
|
@ -67,6 +53,20 @@ public static partial class ServiceExtensions
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddTokenServices(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
var options = new Models.TokenOptions(
|
||||||
|
key: configuration.GetValue<string?>(Appsettings.Jwt.Key) ?? throw new Exception($"{Appsettings.Jwt.Key} value not set (appsettings)"),
|
||||||
|
expires: configuration.GetValue<int?>(Appsettings.Jwt.Exp) ?? throw new Exception($"{Appsettings.Jwt.Exp} value not set (appsettings)"),
|
||||||
|
audience: configuration.GetValue<Uri?>(Appsettings.Jwt.Audience) ?? throw new Exception($"{Appsettings.Jwt.Audience} value not set (appsettings)"),
|
||||||
|
issuer: configuration.GetValue<Uri?>(Appsettings.Jwt.Issuer) ?? throw new Exception($"{Appsettings.Jwt.Issuer} value not set (appsettings)"));
|
||||||
|
|
||||||
|
services.AddSingleton(options);
|
||||||
|
services.AddTransient<TokenService>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
// REWRITE TO COOKIE ONLY FOR WEB
|
// REWRITE TO COOKIE ONLY FOR WEB
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.1" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ public static class ConfigurationExtensions
|
||||||
{
|
{
|
||||||
configuration.Sources.Clear();
|
configuration.Sources.Clear();
|
||||||
configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,7 +27,7 @@ public static partial class ServiceExtensions
|
||||||
return services.AddSingleton(provider => provider.GetRequiredService<MongoClient>().GetDatabase(Settings.Database));
|
return services.AddSingleton(provider => provider.GetRequiredService<MongoClient>().GetDatabase(Settings.Database));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services)
|
public static IServiceCollection AddIdentityServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddTransient<IdentityService>();
|
services.AddTransient<IdentityService>();
|
||||||
services.AddTransient<AuthenticatorService>();
|
services.AddTransient<AuthenticatorService>();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AspNetCore.Identity.MongoDbCore" Version="3.1.2" />
|
<PackageReference Include="AspNetCore.Identity.MongoDbCore" Version="3.1.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.23.1" />
|
<PackageReference Include="MongoDB.Driver" Version="2.23.1" />
|
||||||
<PackageReference Include="Vaitr.Scheduler" Version="2023.12.15.1" />
|
<PackageReference Include="Vaitr.Scheduler" Version="2023.12.15.1" />
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
17
src/Server/Insight.Server/Controllers/BlankController.cs
Normal file
17
src/Server/Insight.Server/Controllers/BlankController.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Insight.Server.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class BlankController(ILogger<BlankController> logger) : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILogger<BlankController> _logger = logger;
|
||||||
|
|
||||||
|
[HttpGet(Name = "Test")]
|
||||||
|
public async Task<IActionResult> Get()
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
using System.Threading.Tasks.Dataflow;
|
|
||||||
|
|
||||||
namespace Insight.Server.Extensions;
|
|
||||||
|
|
||||||
public static class Async
|
|
||||||
{
|
|
||||||
public static async Task ParallelForEach<T>(
|
|
||||||
this IAsyncEnumerable<T> source,
|
|
||||||
Func<T, Task> body,
|
|
||||||
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
|
|
||||||
TaskScheduler? scheduler = null)
|
|
||||||
{
|
|
||||||
var options = new ExecutionDataflowBlockOptions
|
|
||||||
{
|
|
||||||
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
|
||||||
};
|
|
||||||
|
|
||||||
if (scheduler != null)
|
|
||||||
options.TaskScheduler = scheduler;
|
|
||||||
|
|
||||||
var block = new ActionBlock<T>(body, options);
|
|
||||||
|
|
||||||
await foreach (var item in source)
|
|
||||||
block.Post(item);
|
|
||||||
|
|
||||||
block.Complete();
|
|
||||||
await block.Completion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task ParallelForEach<T>(
|
|
||||||
this IEnumerable<T> source,
|
|
||||||
Func<T, Task> body,
|
|
||||||
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
|
|
||||||
TaskScheduler? scheduler = null)
|
|
||||||
{
|
|
||||||
var options = new ExecutionDataflowBlockOptions
|
|
||||||
{
|
|
||||||
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
|
||||||
};
|
|
||||||
|
|
||||||
if (scheduler != null)
|
|
||||||
options.TaskScheduler = scheduler;
|
|
||||||
|
|
||||||
var block = new ActionBlock<T>(body, options);
|
|
||||||
|
|
||||||
foreach (var item in source)
|
|
||||||
block.Post(item);
|
|
||||||
|
|
||||||
block.Complete();
|
|
||||||
await block.Completion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +1,21 @@
|
||||||
using Insight.Domain.Constants;
|
using Insight.Domain.Interfaces;
|
||||||
using Insight.Domain.Interfaces;
|
|
||||||
using Insight.Domain.Network;
|
using Insight.Domain.Network;
|
||||||
using Insight.Infrastructure;
|
using Insight.Infrastructure;
|
||||||
using Insight.Server.Network.Agent;
|
using Insight.Server.Network.Agent;
|
||||||
using Insight.Server.Network.Agent.Handlers;
|
using Insight.Server.Network.Agent.Handlers;
|
||||||
using Insight.Server.Network.Globals;
|
using Insight.Server.Network.Globals;
|
||||||
using Insight.Server.Network.Web;
|
using Insight.Server.Network.Web;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
using OpenTelemetry.Metrics;
|
using OpenTelemetry.Metrics;
|
||||||
using OpenTelemetry.Resources;
|
using OpenTelemetry.Resources;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Vaitr.Network;
|
using Vaitr.Network;
|
||||||
using Vaitr.Network.Hosting;
|
using Vaitr.Network.Hosting;
|
||||||
|
|
||||||
namespace Insight.Server;
|
namespace Insight.Server.Extensions;
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class ServiceExtensions
|
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)
|
internal static WebApplicationBuilder AddMetrics(this WebApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Services.AddOpenTelemetry()
|
builder.Services.AddOpenTelemetry()
|
||||||
|
|
@ -82,6 +29,7 @@ internal static class ServiceExtensions
|
||||||
.AddRuntimeInstrumentation()
|
.AddRuntimeInstrumentation()
|
||||||
.AddProcessInstrumentation()
|
.AddProcessInstrumentation()
|
||||||
.AddAspNetCoreInstrumentation()
|
.AddAspNetCoreInstrumentation()
|
||||||
|
.AddHttpClientInstrumentation()
|
||||||
//.AddMeter("test")
|
//.AddMeter("test")
|
||||||
.AddInfluxDBMetricsExporter(configure =>
|
.AddInfluxDBMetricsExporter(configure =>
|
||||||
{
|
{
|
||||||
|
|
@ -100,7 +48,21 @@ internal static class ServiceExtensions
|
||||||
return builder;
|
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
|
// SERVER
|
||||||
builder.Services.UseHostedServer<AgentSession, IMessage>(options =>
|
builder.Services.UseHostedServer<AgentSession, IMessage>(options =>
|
||||||
|
|
@ -144,7 +106,7 @@ internal static class ServiceExtensions
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static WebApplicationBuilder AddWebServices(this WebApplicationBuilder builder)
|
internal static WebApplicationBuilder AddWebBackend(this WebApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
// SERVER
|
// SERVER
|
||||||
builder.Services.UseHostedServer<WebSession, IMessage>(options =>
|
builder.Services.UseHostedServer<WebSession, IMessage>(options =>
|
||||||
|
|
@ -168,4 +130,21 @@ internal static class ServiceExtensions
|
||||||
|
|
||||||
return builder;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
|
|
@ -6,54 +6,31 @@
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyName>server</AssemblyName>
|
<AssemblyName>server</AssemblyName>
|
||||||
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
<AssemblyVersion>2024.1.10.0</AssemblyVersion>
|
||||||
<RootNamespace>Insight.Server</RootNamespace>
|
<RootNamespace>Insight.Server</RootNamespace>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
|
||||||
<DebugType>none</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
|
||||||
<DebugType>none</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="appsettings.Development.json" />
|
|
||||||
<None Remove="appsettings.json" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="appsettings.Development.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="appsettings.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
|
||||||
<PackageReference Include="Vaitr.Bus" Version="2023.12.15.1" />
|
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.InfluxDB" Version="1.0.0-alpha.3" />
|
<PackageReference Include="OpenTelemetry.Exporter.InfluxDB" Version="1.0.0-alpha.3" />
|
||||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
|
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.7.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.4" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.4" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.7.0" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.7.0" />
|
||||||
<!--Unix Serilog stuff-->
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
||||||
|
<PackageReference Include="Vaitr.Bus" Version="2023.12.15.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Core\Insight.Domain\Insight.Domain.csproj" />
|
<ProjectReference Include="..\..\Core\Insight.Domain\Insight.Domain.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Core\Insight.Infrastructure.Web\Insight.Infrastructure.Web.csproj" />
|
||||||
<ProjectReference Include="..\..\Core\Insight.Infrastructure\Insight.Infrastructure.csproj" />
|
<ProjectReference Include="..\..\Core\Insight.Infrastructure\Insight.Infrastructure.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
@ -61,10 +38,6 @@
|
||||||
<None Update="localhost.pfx">
|
<None Update="localhost.pfx">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="Properties\launchSettings.json">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ using Insight.Domain.Interfaces;
|
||||||
using Insight.Domain.Network;
|
using Insight.Domain.Network;
|
||||||
using Insight.Domain.Network.Agent.Messages;
|
using Insight.Domain.Network.Agent.Messages;
|
||||||
using Insight.Infrastructure.Entities;
|
using Insight.Infrastructure.Entities;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using Vaitr.Network;
|
using Vaitr.Network;
|
||||||
|
|
||||||
|
|
@ -184,15 +183,13 @@ public class AgentSession(
|
||||||
{
|
{
|
||||||
while (cancellationToken.IsCancellationRequested is false)
|
while (cancellationToken.IsCancellationRequested is false)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("try get inventory");
|
|
||||||
|
|
||||||
// find assigned host
|
// find assigned host
|
||||||
var host = await _database.Host()
|
var hostCount = await _database.Host()
|
||||||
.CountDocumentsAsync(Builders<HostEntity>.Filter.Eq(p => p.Agent, Id), cancellationToken: cancellationToken)
|
.CountDocumentsAsync(Builders<HostEntity>.Filter.Eq(p => p.Agent, Id), cancellationToken: cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
// if not assigned => short delay
|
// if not assigned => short delay
|
||||||
if (host == 0)
|
if (hostCount == 0)
|
||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
|
await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,8 @@
|
||||||
using Insight.Domain.Constants;
|
using Insight.Domain.Constants;
|
||||||
using Insight.Domain.Interfaces;
|
|
||||||
using Insight.Domain.Network;
|
|
||||||
using Insight.Infrastructure;
|
using Insight.Infrastructure;
|
||||||
using Insight.Server.Network.Agent;
|
using Insight.Server.Extensions;
|
||||||
using Insight.Server.Network.Agent.Handlers;
|
using System.Collections;
|
||||||
using Insight.Server.Network.Globals;
|
using System.Diagnostics;
|
||||||
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;
|
|
||||||
|
|
||||||
namespace Insight.Server;
|
namespace Insight.Server;
|
||||||
|
|
||||||
|
|
@ -22,126 +10,54 @@ internal class Program
|
||||||
{
|
{
|
||||||
public static async Task Main(string[] args)
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
var builder = Host.CreateDefaultBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
builder.UseWindowsService();
|
builder.Host.UseWindowsService();
|
||||||
builder.UseSystemd();
|
builder.Host.UseSystemd();
|
||||||
|
|
||||||
builder.ConfigureAppConfiguration(options =>
|
// Configuration
|
||||||
{
|
builder.Configuration.Defaults();
|
||||||
options.Defaults();
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.ConfigureLogging(options =>
|
// Logging
|
||||||
{
|
builder.Logging.ClearProviders();
|
||||||
options.ClearProviders();
|
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
||||||
options.SetMinimumLevel(LogLevel.Trace);
|
builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning);
|
||||||
|
builder.Logging.AddSimpleConsole(options =>
|
||||||
options.AddSimpleConsole(options =>
|
|
||||||
{
|
{
|
||||||
options.IncludeScopes = true;
|
options.IncludeScopes = true;
|
||||||
options.SingleLine = true;
|
options.SingleLine = true;
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
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}");
|
||||||
|
|
||||||
options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/server_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}");
|
// Services
|
||||||
});
|
builder.Services.AddDatabase(builder.Configuration);
|
||||||
|
|
||||||
builder.ConfigureServices((host, services) =>
|
// Modules
|
||||||
|
builder.AddDefaults();
|
||||||
|
builder.AddApiDefaults();
|
||||||
|
builder.AddMetrics();
|
||||||
|
builder.AddSwagger();
|
||||||
|
builder.AddAgentBackend();
|
||||||
|
builder.AddWebBackend();
|
||||||
|
|
||||||
|
// HTTP Pipeline
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
// AGENT
|
|
||||||
services.AddAgentServices(host.Configuration);
|
|
||||||
|
|
||||||
// WEB
|
}
|
||||||
services.AddWebServices(host.Configuration);
|
|
||||||
|
|
||||||
// INFRASTRUCTURE
|
app.ConfigureSwagger();
|
||||||
services.AddDatabase(host.Configuration);
|
|
||||||
|
|
||||||
// BACKGROUND SERVICES
|
app.UseCors(x => x
|
||||||
services.AddHostedService<DispatchService>();
|
.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader());
|
||||||
|
|
||||||
// GLOBAL DEPENDENCIES
|
app.UseAuthorization();
|
||||||
services.AddSingleton<Bus>();
|
app.MapControllers();
|
||||||
services.AddTransient(provider => new HttpClient(new HttpClientHandler
|
|
||||||
{
|
|
||||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
|
||||||
ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
var host = builder.Build();
|
await app.RunAsync();
|
||||||
await host.RunAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class ServiceExtensions
|
|
||||||
{
|
|
||||||
internal static IServiceCollection AddAgentServices(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
// AGENT SERVER
|
|
||||||
services.UseHostedServer<AgentSession, IMessage>(options =>
|
|
||||||
{
|
|
||||||
options.Address = IPAddress.Any;
|
|
||||||
options.Port = configuration.GetValue<int?>(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<string?>(Appsettings.Agent.Certificate) ?? throw new Exception($"{Appsettings.Agent.Certificate} value not set (appsettings)");
|
|
||||||
options.CertificatePassword = configuration.GetValue<string?>(Appsettings.Agent.CertificatePassword) ?? throw new Exception($"{Appsettings.Agent.CertificatePassword} value not set (appsettings)");
|
|
||||||
|
|
||||||
options.UseSerializer<AgentSession, IMessage, MemPackSerializer<IMessage>>();
|
|
||||||
});
|
|
||||||
|
|
||||||
// HANDLER
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, CustomHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, ProxyHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, DriveHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, Network.Agent.Handlers.EventHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, InterfaceHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, MainboardHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, MemoryHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, OperationSystemHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, PrinterHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, ProcessorHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, ServiceHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, SessionHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, SoftwareHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, StoragePoolHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, SystemInfoHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, TrapHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, UpdateHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, UserHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, VideocardHandler>();
|
|
||||||
services.AddSingleton<IMessageHandler<AgentSession>, VirtualMaschineHandler>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static IServiceCollection AddWebServices(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
// SERVER
|
|
||||||
services.UseHostedServer<WebSession, IMessage>(options =>
|
|
||||||
{
|
|
||||||
options.Address = IPAddress.Any;
|
|
||||||
options.Port = configuration.GetValue<int?>(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<string?>(Appsettings.Web.Certificate) ?? throw new Exception($"{Appsettings.Web.Certificate} value not set (appsettings)");
|
|
||||||
options.CertificatePassword = configuration.GetValue<string?>(Appsettings.Web.CertificatePassword) ?? throw new Exception($"{Appsettings.Web.CertificatePassword} value not set (appsettings)");
|
|
||||||
|
|
||||||
options.UseSerializer<WebSession, IMessage, MemPackSerializer<IMessage>>();
|
|
||||||
});
|
|
||||||
|
|
||||||
// HANDLER
|
|
||||||
services.AddSingleton<IMessageHandler<WebSession>, ProxyHandler>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"Development": {
|
"Development": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": false,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5001",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Production": {
|
"Production": {
|
||||||
"commandName": "Project"
|
"commandName": "Project",
|
||||||
|
"applicationUrl": "http://localhost:5001"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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",
|
"mongo.connection": "mongodb://db.insight.local:27017",
|
||||||
|
|
||||||
"agent.port": 3002,
|
"agent.port": 3002,
|
||||||
|
|
|
||||||
|
|
@ -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",
|
"mongo.connection": "mongodb://127.0.0.1:27017",
|
||||||
|
|
||||||
"agent.port": 3002,
|
"agent.port": 3002,
|
||||||
|
|
@ -9,5 +25,5 @@
|
||||||
"web.certificate": "localhost.pfx",
|
"web.certificate": "localhost.pfx",
|
||||||
"web.certificate.password": "Webmatic12",
|
"web.certificate.password": "Webmatic12",
|
||||||
|
|
||||||
"dispatch.webmatic": false
|
"dispatch.webmatic": true
|
||||||
}
|
}
|
||||||
5
src/Server/Insight.Server/libman.json
Normal file
5
src/Server/Insight.Server/libman.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"version": "1.0",
|
||||||
|
"defaultProvider": "cdnjs",
|
||||||
|
"libraries": []
|
||||||
|
}
|
||||||
|
|
@ -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<WeatherForecastController> _logger;
|
|
||||||
|
|
||||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet(Name = "GetWeatherForecast")]
|
|
||||||
public IEnumerable<WeatherForecast> 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
using System.Threading.Tasks.Dataflow;
|
|
||||||
|
|
||||||
namespace Insight.Server.Extensions;
|
|
||||||
|
|
||||||
public static class Async
|
|
||||||
{
|
|
||||||
public static async Task ParallelForEach<T>(
|
|
||||||
this IAsyncEnumerable<T> source,
|
|
||||||
Func<T, Task> body,
|
|
||||||
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
|
|
||||||
TaskScheduler? scheduler = null)
|
|
||||||
{
|
|
||||||
var options = new ExecutionDataflowBlockOptions
|
|
||||||
{
|
|
||||||
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
|
||||||
};
|
|
||||||
|
|
||||||
if (scheduler != null)
|
|
||||||
options.TaskScheduler = scheduler;
|
|
||||||
|
|
||||||
var block = new ActionBlock<T>(body, options);
|
|
||||||
|
|
||||||
await foreach (var item in source)
|
|
||||||
block.Post(item);
|
|
||||||
|
|
||||||
block.Complete();
|
|
||||||
await block.Completion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task ParallelForEach<T>(
|
|
||||||
this IEnumerable<T> source,
|
|
||||||
Func<T, Task> body,
|
|
||||||
int maxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
|
|
||||||
TaskScheduler? scheduler = null)
|
|
||||||
{
|
|
||||||
var options = new ExecutionDataflowBlockOptions
|
|
||||||
{
|
|
||||||
MaxDegreeOfParallelism = maxDegreeOfParallelism
|
|
||||||
};
|
|
||||||
|
|
||||||
if (scheduler != null)
|
|
||||||
options.TaskScheduler = scheduler;
|
|
||||||
|
|
||||||
var block = new ActionBlock<T>(body, options);
|
|
||||||
|
|
||||||
foreach (var item in source)
|
|
||||||
block.Post(item);
|
|
||||||
|
|
||||||
block.Complete();
|
|
||||||
await block.Completion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<Product>Insight</Product>
|
|
||||||
<AssemblyName>server</AssemblyName>
|
|
||||||
<AssemblyVersion>2024.1.10.0</AssemblyVersion>
|
|
||||||
<RootNamespace>Insight.Server</RootNamespace>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
|
||||||
<InvariantGlobalization>true</InvariantGlobalization>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
|
||||||
<PackageReference Include="Vaitr.Bus" Version="2023.12.15.1" />
|
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.InfluxDB" Version="1.0.0-alpha.3" />
|
|
||||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
|
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
|
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.4" />
|
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.7.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\Core\Insight.Domain\Insight.Domain.csproj" />
|
|
||||||
<ProjectReference Include="..\..\Core\Insight.Infrastructure\Insight.Infrastructure.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="localhost.pfx">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<IMessageHandler<AgentSession>> handlers,
|
|
||||||
ISerializer<IMessage> serializer,
|
|
||||||
ILogger<AgentSession> logger) : TcpSession<IMessage>(serializer, logger)
|
|
||||||
{
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
private readonly IEnumerable<IMessageHandler<AgentSession>> _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<IMessage> context, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await base.OnSentAsync(context, cancellationToken);
|
|
||||||
|
|
||||||
// update entity
|
|
||||||
await UpdateAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async ValueTask OnReceivedAsync(IPacketContext<IMessage> 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<AgentEntity>
|
|
||||||
.Filter
|
|
||||||
.Eq(p => p.Serial, authentication.Serial.ToString()), Builders<AgentEntity>.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<AgentEntity>
|
|
||||||
.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<AgentEntity>
|
|
||||||
.Filter
|
|
||||||
.Eq(p => p.Id, Id), Builders<AgentEntity>
|
|
||||||
.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<HostEntity>.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<CustomHandler> logger) : IMessageHandler<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly ILogger<CustomHandler> _logger = logger;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Drive> drives:
|
|
||||||
await OnDrivesAsync(sender, drives, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnDrivesAsync(AgentSession session, List<Drive> drives, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostDriveEntity>>();
|
|
||||||
|
|
||||||
if (drives is not null && drives.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var drive in drives)
|
|
||||||
{
|
|
||||||
var driveFilter = Builders<HostDriveEntity>.Filter.And(new List<FilterDefinition<HostDriveEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostDriveEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostDriveEntity>.Filter.Eq(x => x.Index, drive.Index)
|
|
||||||
});
|
|
||||||
|
|
||||||
var driveUpdate = Builders<HostDriveEntity>.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<HostDriveEntity>(driveFilter, driveUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
driveBulk.Add(new DeleteManyModel<HostDriveEntity>(Builders<HostDriveEntity>.Filter.And(new List<FilterDefinition<HostDriveEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostDriveEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostDriveEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var driveResult = await _database.HostDrive().BulkWriteAsync(driveBulk, cancellationToken: cancellationToken);
|
|
||||||
|
|
||||||
// volumes
|
|
||||||
|
|
||||||
var volumeBulk = new List<WriteModel<HostVolumeEntity>>();
|
|
||||||
|
|
||||||
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<HostVolumeEntity>.Filter.And(new List<FilterDefinition<HostVolumeEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostVolumeEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostVolumeEntity>.Filter.Eq(x => x.Drive, driveId),
|
|
||||||
Builders<HostVolumeEntity>.Filter.Eq(x => x.Index, volume.Index)
|
|
||||||
});
|
|
||||||
|
|
||||||
var volumeUpdate = Builders<HostVolumeEntity>.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<HostVolumeEntity>(volumeFilter, volumeUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volumeBulk.Add(new DeleteManyModel<HostVolumeEntity>(Builders<HostVolumeEntity>.Filter.And(new List<FilterDefinition<HostVolumeEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostVolumeEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostVolumeEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var volumeResult = await _database.HostVolume().BulkWriteAsync(volumeBulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<AgentLogEntity?> InsertAgentLogAsync(AgentSession session, Event @event, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent()
|
|
||||||
.Aggregate()
|
|
||||||
.Match(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id))
|
|
||||||
.Lookup<AgentEntity, HostEntity, AgentEntity>(_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<HostLogEntity?> 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<int>
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Interface> interfaces:
|
|
||||||
await OnInterfacesAsync(sender, interfaces, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnInterfacesAsync(AgentSession session, List<Interface> interfaces, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostInterfaceEntity>>();
|
|
||||||
|
|
||||||
foreach (var @interface in interfaces)
|
|
||||||
{
|
|
||||||
var interfaceFilter = Builders<HostInterfaceEntity>.Filter.And(new List<FilterDefinition<HostInterfaceEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceEntity>.Filter.Eq(x => x.Index, @interface.Index)
|
|
||||||
});
|
|
||||||
|
|
||||||
var interfaceUpdate = Builders<HostInterfaceEntity>.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<HostInterfaceEntity>(interfaceFilter, interfaceUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
interfaceBulk.Add(new DeleteManyModel<HostInterfaceEntity>(Builders<HostInterfaceEntity>.Filter.And(new List<FilterDefinition<HostInterfaceEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceEntity>.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<WriteModel<HostInterfaceAddressEntity>>();
|
|
||||||
|
|
||||||
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<HostInterfaceAddressEntity>.Filter.And(new List<FilterDefinition<HostInterfaceAddressEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceAddressEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceAddressEntity>.Filter.Eq(x => x.Interface, interfaceId),
|
|
||||||
Builders<HostInterfaceAddressEntity>.Filter.Eq(x => x.Address, address?.IpAddress?.Address),
|
|
||||||
Builders<HostInterfaceAddressEntity>.Filter.Eq(x => x.Mask, address?.Ipv4Mask?.Address)
|
|
||||||
});
|
|
||||||
|
|
||||||
var addressUpdate = Builders<HostInterfaceAddressEntity>.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<HostInterfaceAddressEntity>(addressFilter, addressUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addressBulk.Add(new DeleteManyModel<HostInterfaceAddressEntity>(Builders<HostInterfaceAddressEntity>.Filter.And(new List<FilterDefinition<HostInterfaceAddressEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceAddressEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceAddressEntity>.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<WriteModel<HostInterfaceGatewayEntity>>();
|
|
||||||
|
|
||||||
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<HostInterfaceGatewayEntity>.Filter.And(new List<FilterDefinition<HostInterfaceGatewayEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceGatewayEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceGatewayEntity>.Filter.Eq(x => x.Interface, interfaceId),
|
|
||||||
Builders<HostInterfaceGatewayEntity>.Filter.Eq(x => x.Address, gateway?.Address)
|
|
||||||
});
|
|
||||||
|
|
||||||
var gatewayUpdate = Builders<HostInterfaceGatewayEntity>.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<HostInterfaceGatewayEntity>(gatewayFilter, gatewayUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gatewayBulk.Add(new DeleteManyModel<HostInterfaceGatewayEntity>(Builders<HostInterfaceGatewayEntity>.Filter.And(new List<FilterDefinition<HostInterfaceGatewayEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceGatewayEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceGatewayEntity>.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<WriteModel<HostInterfaceNameserverEntity>>();
|
|
||||||
|
|
||||||
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<HostInterfaceNameserverEntity>.Filter.And(new List<FilterDefinition<HostInterfaceNameserverEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceNameserverEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceNameserverEntity>.Filter.Eq(x => x.Interface, interfaceId),
|
|
||||||
Builders<HostInterfaceNameserverEntity>.Filter.Eq(x => x.Address, nameserver?.Address)
|
|
||||||
});
|
|
||||||
|
|
||||||
var nameserverUpdate = Builders<HostInterfaceNameserverEntity>.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<HostInterfaceNameserverEntity>(nameserverFilter, nameserverUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nameserverBulk.Add(new DeleteManyModel<HostInterfaceNameserverEntity>(Builders<HostInterfaceNameserverEntity>.Filter.And(new List<FilterDefinition<HostInterfaceNameserverEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceNameserverEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceNameserverEntity>.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<WriteModel<HostInterfaceRouteEntity>>();
|
|
||||||
|
|
||||||
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<HostInterfaceRouteEntity>.Filter.And(new List<FilterDefinition<HostInterfaceRouteEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceRouteEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceRouteEntity>.Filter.Eq(x => x.Interface, interfaceId),
|
|
||||||
Builders<HostInterfaceRouteEntity>.Filter.Eq(x => x.Destination, route?.Destination?.Address),
|
|
||||||
Builders<HostInterfaceRouteEntity>.Filter.Eq(x => x.Gateway, route?.Gateway?.Address),
|
|
||||||
Builders<HostInterfaceRouteEntity>.Filter.Eq(x => x.Mask, route?.Mask),
|
|
||||||
});
|
|
||||||
|
|
||||||
var routeUpdate = Builders<HostInterfaceRouteEntity>.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<HostInterfaceRouteEntity>(routeFilter, routeUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
routeBulk.Add(new DeleteManyModel<HostInterfaceRouteEntity>(Builders<HostInterfaceRouteEntity>.Filter.And(new List<FilterDefinition<HostInterfaceRouteEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostInterfaceRouteEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostInterfaceRouteEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var routeResult = await _database.HostInterfaceRoute().BulkWriteAsync(routeBulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<HostMainboardEntity>.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Memory> memory:
|
|
||||||
await OnMemoryAsync(sender, memory, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnMemoryAsync(AgentSession session, List<Memory> memory, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostMemoryEntity>>();
|
|
||||||
|
|
||||||
if (memory is not null && memory.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var mem in memory)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostMemoryEntity>.Filter.And(new List<FilterDefinition<HostMemoryEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostMemoryEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostMemoryEntity>.Filter.Eq(x => x.Index, mem.Index)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostMemoryEntity>.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<HostMemoryEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostMemoryEntity>(Builders<HostMemoryEntity>.Filter.And(new List<FilterDefinition<HostMemoryEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostMemoryEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostMemoryEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostMemory().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<HostOsEntity>.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Printer> printers:
|
|
||||||
await OnPrintersAsync(sender, printers, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnPrintersAsync(AgentSession session, List<Printer> printers, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostPrinterEntity>>();
|
|
||||||
|
|
||||||
if (printers is not null && printers.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var printer in printers)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostPrinterEntity>.Filter.And(new List<FilterDefinition<HostPrinterEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostPrinterEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostPrinterEntity>.Filter.Eq(x => x.Name, printer.Name)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostPrinterEntity>.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<HostPrinterEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostPrinterEntity>(Builders<HostPrinterEntity>.Filter.And(new List<FilterDefinition<HostPrinterEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostPrinterEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostPrinterEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostPrinter().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Processor> processors:
|
|
||||||
await OnProcessorsAsync(sender, processors, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnProcessorsAsync(AgentSession session, List<Processor> processors, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostProcessorEntity>>();
|
|
||||||
|
|
||||||
if (processors is not null && processors.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var processor in processors)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostProcessorEntity>.Filter.And(new List<FilterDefinition<HostProcessorEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostProcessorEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostProcessorEntity>.Filter.Eq(x => x.Index, processor.Index)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostProcessorEntity>.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<HostProcessorEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostProcessorEntity>(Builders<HostProcessorEntity>.Filter.And(new List<FilterDefinition<HostProcessorEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostProcessorEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostProcessorEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostProcessor().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Service> services:
|
|
||||||
await OnServicesAsync(sender, services, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnServicesAsync(AgentSession session, List<Service> services, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostServiceEntity>>();
|
|
||||||
|
|
||||||
if (services is not null && services.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var service in services)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostServiceEntity>.Filter.And(new List<FilterDefinition<HostServiceEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostServiceEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostServiceEntity>.Filter.Eq(x => x.Name, service.Name)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostServiceEntity>.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<HostServiceEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostServiceEntity>(Builders<HostServiceEntity>.Filter.And(new List<FilterDefinition<HostServiceEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostServiceEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostServiceEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostService().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Session> sessions:
|
|
||||||
await OnSessionsAsync(sender, sessions, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnSessionsAsync(AgentSession session, List<Session> sessions, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostSessionEntity>>();
|
|
||||||
|
|
||||||
if (sessions is not null && sessions.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var sess in sessions)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostSessionEntity>.Filter.And(new List<FilterDefinition<HostSessionEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSessionEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSessionEntity>.Filter.Eq(x => x.Sid, sess.Sid)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostSessionEntity>.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<HostSessionEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostSessionEntity>(Builders<HostSessionEntity>.Filter.And(new List<FilterDefinition<HostSessionEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSessionEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSessionEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostSession().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Application> applications:
|
|
||||||
await OnApplicationsAsync(sender, applications, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnApplicationsAsync(AgentSession session, List<Application> applications, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostApplicationEntity>>();
|
|
||||||
|
|
||||||
if (applications is not null && applications.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var app in applications)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostApplicationEntity>.Filter.And(new List<FilterDefinition<HostApplicationEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostApplicationEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostApplicationEntity>.Filter.Eq(x => x.Name, app.Name),
|
|
||||||
Builders<HostApplicationEntity>.Filter.Eq(x => x.Architecture, app.Architecture?.ToString())
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostApplicationEntity>.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<HostApplicationEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostApplicationEntity>(Builders<HostApplicationEntity>.Filter.And(new List<FilterDefinition<HostApplicationEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostApplicationEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostApplicationEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostApplication().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<StoragePool> storagePools:
|
|
||||||
await OnStoragePoolsAsync(sender, storagePools, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnStoragePoolsAsync(AgentSession session, List<StoragePool>? storagePools, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostStoragePoolEntity>>();
|
|
||||||
|
|
||||||
foreach (var storagePool in storagePools)
|
|
||||||
{
|
|
||||||
var storagePoolFilter = Builders<HostStoragePoolEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostStoragePoolEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostStoragePoolEntity>.Filter.Eq(x => x.UniqueId, storagePool.UniqueId)
|
|
||||||
});
|
|
||||||
|
|
||||||
List<string>? states = null;
|
|
||||||
|
|
||||||
if (storagePool.States is not null)
|
|
||||||
{
|
|
||||||
states = [];
|
|
||||||
|
|
||||||
foreach (var state in storagePool.States)
|
|
||||||
states.Add(state.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
var storagePoolUpdate = Builders<HostStoragePoolEntity>.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<HostStoragePoolEntity>(storagePoolFilter, storagePoolUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
storagepoolBulk.Add(new DeleteManyModel<HostStoragePoolEntity>(Builders<HostStoragePoolEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostStoragePoolEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostStoragePoolEntity>.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<WriteModel<HostStoragePoolPhysicalDiskEntity>>();
|
|
||||||
|
|
||||||
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<HostStoragePoolPhysicalDiskEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolPhysicalDiskEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostStoragePoolPhysicalDiskEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostStoragePoolPhysicalDiskEntity>.Filter.Eq(x => x.StoragePool, storagePoolId),
|
|
||||||
Builders<HostStoragePoolPhysicalDiskEntity>.Filter.Eq(x => x.UniqueId, physicalDisk.UniqueId)
|
|
||||||
});
|
|
||||||
|
|
||||||
List<string>? states = null;
|
|
||||||
|
|
||||||
if (physicalDisk.States is not null)
|
|
||||||
{
|
|
||||||
states = [];
|
|
||||||
|
|
||||||
foreach (var state in physicalDisk.States)
|
|
||||||
states.Add(state.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
var physicalDiskUpdate = Builders<HostStoragePoolPhysicalDiskEntity>.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<HostStoragePoolPhysicalDiskEntity>(physicalDiskFilter, physicalDiskUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
physicalDiskBulk.Add(new DeleteManyModel<HostStoragePoolPhysicalDiskEntity>(Builders<HostStoragePoolPhysicalDiskEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolPhysicalDiskEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostStoragePoolPhysicalDiskEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostStoragePoolPhysicalDiskEntity>.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<WriteModel<HostStoragePoolVirtualDiskEntity>>();
|
|
||||||
|
|
||||||
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<HostStoragePoolVirtualDiskEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolVirtualDiskEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostStoragePoolVirtualDiskEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostStoragePoolVirtualDiskEntity>.Filter.Eq(x => x.StoragePool, storagePoolId),
|
|
||||||
Builders<HostStoragePoolVirtualDiskEntity>.Filter.Eq(x => x.UniqueId, virtualDisk.UniqueId)
|
|
||||||
});
|
|
||||||
|
|
||||||
List<string>? states = null;
|
|
||||||
|
|
||||||
if (virtualDisk.States is not null)
|
|
||||||
{
|
|
||||||
states = [];
|
|
||||||
|
|
||||||
foreach (var state in virtualDisk.States)
|
|
||||||
states.Add(state.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
var virtualDiskUpdate = Builders<HostStoragePoolVirtualDiskEntity>.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<HostStoragePoolVirtualDiskEntity>(virtualDiskFilter, virtualDiskUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtualDiskBulk.Add(new DeleteManyModel<HostStoragePoolVirtualDiskEntity>(Builders<HostStoragePoolVirtualDiskEntity>.Filter.And(new List<FilterDefinition<HostStoragePoolVirtualDiskEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostStoragePoolVirtualDiskEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostStoragePoolVirtualDiskEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var virtualDiskResult = await _database.HostStoragePoolVirtualDisk().BulkWriteAsync(virtualDiskBulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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<AgentEntity>.Filter.Eq(p => p.Id, session?.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<HostSystemEntity>.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<ApplicationEnum>(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<KeyValuePair<string, string?>> 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<KeyValuePair<string, string?>> 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<KeyValuePair<string, string?>> 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<string, StatusEnum>
|
|
||||||
{
|
|
||||||
{ "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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostUpdateEntity>>();
|
|
||||||
|
|
||||||
if (updates is not null)
|
|
||||||
{
|
|
||||||
if (updates.Installed is not null && updates.Installed.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var update in updates.Installed)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostUpdateEntity>.Filter.And(new List<FilterDefinition<HostUpdateEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostUpdateEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostUpdateEntity>.Filter.Eq(x => x.Serial, update.Id)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostUpdateEntity>.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<HostUpdateEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updates.Pending is not null && updates.Pending.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var update in updates.Pending)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostUpdateEntity>.Filter.And(new List<FilterDefinition<HostUpdateEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostUpdateEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostUpdateEntity>.Filter.Eq(x => x.Serial, update.Id)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostUpdateEntity>.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<HostUpdateEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostUpdateEntity>(Builders<HostUpdateEntity>.Filter.And(new List<FilterDefinition<HostUpdateEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostUpdateEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostUpdateEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostUpdate().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<User> users:
|
|
||||||
await OnUsersAsync(sender, users, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnUsersAsync(AgentSession session, List<User>? users, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostSysUserEntity>>();
|
|
||||||
|
|
||||||
foreach (var user in users)
|
|
||||||
{
|
|
||||||
var userFilter = Builders<HostSysUserEntity>.Filter.And(new List<FilterDefinition<HostSysUserEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSysUserEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSysUserEntity>.Filter.Eq(x => x.Domain, user?.Domain),
|
|
||||||
Builders<HostSysUserEntity>.Filter.Eq(x => x.Name, user?.Name)
|
|
||||||
});
|
|
||||||
|
|
||||||
var userUpdate = Builders<HostSysUserEntity>.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<HostSysUserEntity>(userFilter, userUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
userBulk.Add(new DeleteManyModel<HostSysUserEntity>(Builders<HostSysUserEntity>.Filter.And(new List<FilterDefinition<HostSysUserEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSysUserEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSysUserEntity>.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<WriteModel<HostSysGroupEntity>>();
|
|
||||||
|
|
||||||
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<HostSysGroupEntity>.Filter.And(new List<FilterDefinition<HostSysGroupEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSysGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSysGroupEntity>.Filter.Eq(x => x.Domain, group?.Domain),
|
|
||||||
Builders<HostSysGroupEntity>.Filter.Eq(x => x.Name, group?.Name)
|
|
||||||
});
|
|
||||||
|
|
||||||
var groupUpdate = Builders<HostSysGroupEntity>.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<HostSysGroupEntity>(groupFilter, groupUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
groupBulk.Add(new DeleteManyModel<HostSysGroupEntity>(Builders<HostSysGroupEntity>.Filter.And(new List<FilterDefinition<HostSysGroupEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSysGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSysGroupEntity>.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<WriteModel<HostSysUserSysGroupEntity>>();
|
|
||||||
|
|
||||||
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<HostSysUserSysGroupEntity>.Filter.And(new List<FilterDefinition<HostSysUserSysGroupEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSysUserSysGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSysUserSysGroupEntity>.Filter.Eq(x => x.User, userId),
|
|
||||||
Builders<HostSysUserSysGroupEntity>.Filter.Eq(x => x.Group, groupId)
|
|
||||||
});
|
|
||||||
|
|
||||||
var relationUpdate = Builders<HostSysUserSysGroupEntity>.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<HostSysUserSysGroupEntity>(relationFilter, relationUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
relationBulk.Add(new DeleteManyModel<HostSysUserSysGroupEntity>(Builders<HostSysUserSysGroupEntity>.Filter.And(new List<FilterDefinition<HostSysUserSysGroupEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostSysUserSysGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostSysUserSysGroupEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var relationResult = await _database.HostSystemUserSystemGroup().BulkWriteAsync(relationBulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<Videocard> videocards:
|
|
||||||
await OnVideocardsAsync(sender, videocards, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnVideocardsAsync(AgentSession session, List<Videocard>? videocards, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostVideocardEntity>>();
|
|
||||||
|
|
||||||
if (videocards is not null && videocards.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var videocard in videocards)
|
|
||||||
{
|
|
||||||
var filterDefinition = Builders<HostVideocardEntity>.Filter.And(new List<FilterDefinition<HostVideocardEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostVideocardEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostVideocardEntity>.Filter.Eq(x => x.Name, videocard.Model)
|
|
||||||
});
|
|
||||||
|
|
||||||
var updateDefinition = Builders<HostVideocardEntity>.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<HostVideocardEntity>(filterDefinition, updateDefinition)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bulk.Add(new DeleteManyModel<HostVideocardEntity>(Builders<HostVideocardEntity>.Filter.And(new List<FilterDefinition<HostVideocardEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostVideocardEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostVideocardEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var result = await _database.HostVideocard().BulkWriteAsync(bulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession>
|
|
||||||
{
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Collection<VirtualMaschine> virtualMaschines:
|
|
||||||
await OnVirtualMaschinesAsync(sender, virtualMaschines, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnVirtualMaschinesAsync(AgentSession session, List<VirtualMaschine>? virtualMaschines, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
|
|
||||||
if (agentEntity is null) return;
|
|
||||||
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<WriteModel<HostHypervisorVirtualMaschineEntity>>();
|
|
||||||
|
|
||||||
foreach (var virtualMaschine in virtualMaschines)
|
|
||||||
{
|
|
||||||
var virtualMaschineFilter = Builders<HostHypervisorVirtualMaschineEntity>.Filter.And(new List<FilterDefinition<HostHypervisorVirtualMaschineEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostHypervisorVirtualMaschineEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostHypervisorVirtualMaschineEntity>.Filter.Eq(x => x.UniqueId, virtualMaschine.Id.ToString())
|
|
||||||
});
|
|
||||||
|
|
||||||
var virtualMaschineUpdate = Builders<HostHypervisorVirtualMaschineEntity>.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<HostHypervisorVirtualMaschineEntity>(virtualMaschineFilter, virtualMaschineUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
virtualMaschineBulk.Add(new DeleteManyModel<HostHypervisorVirtualMaschineEntity>(Builders<HostHypervisorVirtualMaschineEntity>.Filter.And(new List<FilterDefinition<HostHypervisorVirtualMaschineEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostHypervisorVirtualMaschineEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostHypervisorVirtualMaschineEntity>.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<WriteModel<HostHypervisorVirtualMaschineConfigEntity>>();
|
|
||||||
|
|
||||||
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<HostHypervisorVirtualMaschineConfigEntity>.Filter.And(new List<FilterDefinition<HostHypervisorVirtualMaschineConfigEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostHypervisorVirtualMaschineConfigEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostHypervisorVirtualMaschineConfigEntity>.Filter.Eq(x => x.VirtualMaschine, virtualMaschineId),
|
|
||||||
Builders<HostHypervisorVirtualMaschineConfigEntity>.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<HostHypervisorVirtualMaschineConfigEntity>.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<HostHypervisorVirtualMaschineConfigEntity>(configFilter, configUpdate)
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configurationBulk.Add(new DeleteManyModel<HostHypervisorVirtualMaschineConfigEntity>(Builders<HostHypervisorVirtualMaschineConfigEntity>.Filter.And(new List<FilterDefinition<HostHypervisorVirtualMaschineConfigEntity>>
|
|
||||||
{
|
|
||||||
Builders<HostHypervisorVirtualMaschineConfigEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
|
||||||
Builders<HostHypervisorVirtualMaschineConfigEntity>.Filter.Ne(x => x.Batch, batch)
|
|
||||||
})));
|
|
||||||
|
|
||||||
var configurationResult = await _database.HostVirtualMaschineConfig().BulkWriteAsync(configurationBulk, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<RemoteSession, IMessage> remotePool, ILogger<RemoteHandler> logger) : IMessageHandler<RemoteSession>
|
|
||||||
{
|
|
||||||
private readonly Bus _bus = bus;
|
|
||||||
private readonly ISessionPool<RemoteSession, IMessage> _remotePool = remotePool;
|
|
||||||
private readonly ILogger<RemoteHandler> _logger = logger;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<WebSession, IMessage> webPool,
|
|
||||||
IEnumerable<IMessageHandler<RemoteSession>> handlers,
|
|
||||||
ISerializer<IMessage> serializer,
|
|
||||||
ILogger<RemoteSession> logger) : TcpSession<IMessage>(serializer, logger)
|
|
||||||
{
|
|
||||||
public string Id { get; } = GenerateRandomId();
|
|
||||||
public RemoteControlMode Mode { get; set; }
|
|
||||||
|
|
||||||
private readonly ISessionPool<WebSession, IMessage> _webPool = webPool;
|
|
||||||
private readonly IEnumerable<IMessageHandler<RemoteSession>> _handlers = handlers;
|
|
||||||
|
|
||||||
public async ValueTask ProxyAsync<TMessage>(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<TMessage>
|
|
||||||
{
|
|
||||||
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<IMessage> context, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await base.OnSentAsync(context, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async ValueTask OnReceivedAsync(IPacketContext<IMessage> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AgentSession, IMessage> agentPool,
|
|
||||||
ISessionPool<WebSession, IMessage> webPool,
|
|
||||||
IMongoDatabase database,
|
|
||||||
ILogger<ProxyHandler> logger) : IMessageHandler<AgentSession>, IMessageHandler<WebSession>
|
|
||||||
{
|
|
||||||
private readonly ISessionPool<AgentSession, IMessage> _agentPool = agentPool;
|
|
||||||
private readonly ISessionPool<WebSession, IMessage> _webPool = webPool;
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
private readonly ILogger<ProxyHandler> _logger = logger;
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(WebSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Proxy<Request> proxyRequest:
|
|
||||||
await OnProxyRequestAsync(sender, proxyRequest, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
||||||
{
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case Proxy<Response> proxyResponse:
|
|
||||||
await OnProxyResponseAsync(sender, proxyResponse, cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask OnProxyRequestAsync(WebSession session, Proxy<Request> request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// get host
|
|
||||||
var hostEntity = await _database.Host()
|
|
||||||
.Find(Builders<HostEntity>
|
|
||||||
.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<AgentEntity>
|
|
||||||
.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> response, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// check if web online
|
|
||||||
if (_webPool.FirstOrDefault().Value is not WebSession web) return;
|
|
||||||
|
|
||||||
await web.SendAsync(response, cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<IMessageHandler<WebSession>> handlers, ISerializer<IMessage> serializer, ILogger<WebSession> logger) : TcpSession<IMessage>(serializer, logger)
|
|
||||||
{
|
|
||||||
public string? Id { get; set; }
|
|
||||||
|
|
||||||
private readonly IEnumerable<IMessageHandler<WebSession>> _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<IMessage> context, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await base.OnSentAsync(context, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async ValueTask OnReceivedAsync(IPacketContext<IMessage> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<DispatchService> logger) : BackgroundService
|
|
||||||
{
|
|
||||||
private readonly HttpClient _httpClient = httpClient;
|
|
||||||
private readonly IMongoDatabase _database = database;
|
|
||||||
private readonly IConfiguration _configuration = configuration;
|
|
||||||
private readonly ILogger<DispatchService> _logger = logger;
|
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_logger.LogTrace("ExecuteAsync");
|
|
||||||
|
|
||||||
var enabled = _configuration.GetValue<bool?>(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<HostLogMonitoringEntity>
|
|
||||||
.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<HostLogMonitoringEntity>.Filter
|
|
||||||
.Eq(p => p.Id, entity.Id), Builders<HostLogMonitoringEntity>
|
|
||||||
.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<DispatchEnum> SendAsync(HostLogMonitoringEntity monitoring, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_logger.LogTrace("SendAsync ({monitoring})", monitoring);
|
|
||||||
|
|
||||||
var monitoringApi = Monitoring.LogUri;
|
|
||||||
var monitoringContent = new List<KeyValuePair<string, string>>();
|
|
||||||
var monitoringResult = new List<KeyValuePair<string, string>>();
|
|
||||||
|
|
||||||
// adjust by category
|
|
||||||
if (Enum.TryParse<CategoryEnum>(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<string, string>("category", monitoringCategory.ToString()));
|
|
||||||
|
|
||||||
// host resolve
|
|
||||||
var hostEntity = await _database.Host().Find(Builders<HostEntity>.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<CustomerEntity>.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<string, string>("computer_name", monitoring.Hostname.ToLower()));
|
|
||||||
|
|
||||||
// insert converted status (api styled)
|
|
||||||
if (Enum.TryParse<StatusEnum>(monitoring.Status, true, out var monitoringStatus) is false) return DispatchEnum.Failure;
|
|
||||||
|
|
||||||
monitoringContent.Add(monitoringStatus switch
|
|
||||||
{
|
|
||||||
StatusEnum.Information => new KeyValuePair<string, string>("status", monitoringApi == Monitoring.StatusUri ? "erfolgreich" : "info"),
|
|
||||||
StatusEnum.Warning => new KeyValuePair<string, string>("status", monitoringApi == Monitoring.StatusUri ? "Interaktion" : "warning"),
|
|
||||||
StatusEnum.Error => new KeyValuePair<string, string>("status", monitoringApi == Monitoring.StatusUri ? "fehlgeschlagen" : "error"),
|
|
||||||
_ => throw new NotImplementedException(nameof(monitoringStatus))
|
|
||||||
});
|
|
||||||
|
|
||||||
// insert task, timestamp, message,
|
|
||||||
monitoringContent.Add(new KeyValuePair<string, string>("task", monitoring.Task));
|
|
||||||
|
|
||||||
if (monitoring.Timestamp is not null)
|
|
||||||
{
|
|
||||||
monitoringContent.Add(new KeyValuePair<string, string>("timestamp", monitoring.Timestamp.Value.ToLocalTime().ToString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(monitoring.Message) is false)
|
|
||||||
{
|
|
||||||
monitoringContent.Add(new KeyValuePair<string, string>("message", monitoring.Message));
|
|
||||||
}
|
|
||||||
|
|
||||||
// send message
|
|
||||||
var result = await _httpClient.PostAsync(monitoringApi, new FormUrlEncodedContent(monitoringContent), default);
|
|
||||||
|
|
||||||
monitoringResult.Add(new KeyValuePair<string, string>("HttpStatusCode", result.StatusCode.ToString()));
|
|
||||||
monitoringResult.Add(new KeyValuePair<string, string>("HttpResponseMessage", await result.Content.ReadAsStringAsync(default)));
|
|
||||||
|
|
||||||
// if content != "OK"
|
|
||||||
if (result is null || result.IsSuccessStatusCode == false) return DispatchEnum.Failure;
|
|
||||||
|
|
||||||
// success
|
|
||||||
return DispatchEnum.Success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Insight.Updater.Windows;
|
namespace Insight.Updater.Windows;
|
||||||
|
|
||||||
|
|
@ -33,8 +34,7 @@ internal class Program
|
||||||
options.SingleLine = true;
|
options.SingleLine = true;
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
||||||
});
|
});
|
||||||
|
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}");
|
||||||
options.AddFile($"{Configuration.AppDirectory?.FullName}/" + "logs/updater_{Date}.log", LogLevel.Trace, fileSizeLimitBytes: 104857600, retainedFileCountLimit: 10, outputTemplate: "{Timestamp:o} [{Level:u3}] {Message} {NewLine}{Exception}");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.ConfigureServices((host, services) =>
|
builder.ConfigureServices((host, services) =>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,57 @@
|
||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Blazored.SessionStorage;
|
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 Insight.Web.Services;
|
||||||
using Microsoft.AspNetCore.Components.Server.Circuits;
|
using Microsoft.AspNetCore.Components.Server.Circuits;
|
||||||
using MudBlazor.Services;
|
using MudBlazor.Services;
|
||||||
|
using OpenTelemetry.Metrics;
|
||||||
|
using OpenTelemetry.Resources;
|
||||||
|
using System.Net;
|
||||||
|
using Vaitr.Network;
|
||||||
|
using Vaitr.Network.Hosting;
|
||||||
|
|
||||||
namespace Insight.Web.Extensions;
|
namespace Insight.Web.Extensions;
|
||||||
|
|
||||||
public static class ServiceExtensions
|
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<string?>(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<Uri?>(Appsettings.Influx.Endpoint) ?? throw new Exception($"{Appsettings.Influx.Endpoint} value not set (appsettings)");
|
||||||
|
configure.Token = builder.Configuration.GetValue<string?>(Appsettings.Influx.Token) ?? throw new Exception($"{Appsettings.Influx.Token} value not set (appsettings)");
|
||||||
|
configure.Org = builder.Configuration.GetValue<string?>(Appsettings.Influx.Organization) ?? throw new Exception($"{Appsettings.Influx.Organization} value not set (appsettings)");
|
||||||
|
configure.Bucket = builder.Configuration.GetValue<string?>(Appsettings.Influx.Bucket) ?? throw new Exception($"{Appsettings.Influx.Bucket} value not set (appsettings)");
|
||||||
|
|
||||||
|
configure.MetricExportIntervalMilliseconds = 1000;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
//builder.Services.AddSingleton<BasicMetrics>();
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
internal static IServiceCollection AddWebServices(this IServiceCollection services)
|
internal static IServiceCollection AddWebServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
// HOSTS
|
// HOSTS
|
||||||
|
|
@ -42,4 +86,46 @@ public static class ServiceExtensions
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static IServiceCollection AddBrokerServices(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
services.UseHostedClient<WebSession, IMessage>(options =>
|
||||||
|
{
|
||||||
|
options.Host = configuration.GetValue<string?>(Appsettings.Backend.Host) ?? throw new Exception($"{Appsettings.Backend.Host} value not set (appsettings)");
|
||||||
|
options.Port = configuration.GetValue<int?>(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<WebSession, IMessage, MemPackSerializer<IMessage>>();
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddSingleton<IMessageHandler<WebSession>, AgentHandler>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IServiceCollection AddRemoteServices(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
services.UseHostedServer<RemoteSession, IMessage>(options =>
|
||||||
|
{
|
||||||
|
options.Address = IPAddress.Any;
|
||||||
|
options.Port = configuration.GetValue<int?>(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<string?>(Appsettings.Remote.Certificate) ?? throw new Exception($"{Appsettings.Remote.Certificate} value not set (appsettings)");
|
||||||
|
options.CertificatePassword = configuration.GetValue<string?>(Appsettings.Remote.CertificatePassword) ?? throw new Exception($"{Appsettings.Remote.CertificatePassword} value not set (appsettings)");
|
||||||
|
|
||||||
|
options.UseSerializer<RemoteSession, IMessage, MemPackSerializer<IMessage>>();
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddSingleton<IMessageHandler<RemoteSession>, RemoteHandler>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<PublishAot>false</PublishAot>
|
<PublishAot>false</PublishAot>
|
||||||
<PublishTrimmed>false</PublishTrimmed>
|
<PublishTrimmed>false</PublishTrimmed>
|
||||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<!--<ServerGarbageCollection>false</ServerGarbageCollection>
|
<!--<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||||
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>-->
|
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>-->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -29,13 +30,18 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.1" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Exporter.InfluxDB" Version="1.0.0-alpha.3" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.7.0" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.4" />
|
||||||
|
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.7.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
||||||
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
|
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
|
||||||
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
|
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.1" />
|
|
||||||
<PackageReference Include="MudBlazor" Version="6.12.0" />
|
<PackageReference Include="MudBlazor" Version="6.12.0" />
|
||||||
<PackageReference Include="Vaitr.Bus" Version="2023.12.15.1" />
|
<PackageReference Include="Vaitr.Bus" Version="2023.12.15.1" />
|
||||||
<!--Unix Serilog stuff-->
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,9 @@
|
||||||
using Insight.Domain.Constants;
|
using Insight.Domain.Constants;
|
||||||
using Insight.Domain.Interfaces;
|
|
||||||
using Insight.Domain.Network;
|
|
||||||
using Insight.Infrastructure;
|
using Insight.Infrastructure;
|
||||||
using Insight.Web.Extensions;
|
using Insight.Web.Extensions;
|
||||||
using Insight.Web.Middleware;
|
using Insight.Web.Middleware;
|
||||||
using Insight.Web.Network.Broker;
|
using System.Diagnostics;
|
||||||
using Insight.Web.Network.Broker.Handlers;
|
|
||||||
using Insight.Web.Network.Remote;
|
|
||||||
using Insight.Web.Network.Remote.Handlers;
|
|
||||||
using System.Net;
|
|
||||||
using Vaitr.Bus;
|
using Vaitr.Bus;
|
||||||
using Vaitr.Network;
|
|
||||||
using Vaitr.Network.Hosting;
|
|
||||||
|
|
||||||
namespace Insight.Web;
|
namespace Insight.Web;
|
||||||
|
|
||||||
|
|
@ -22,43 +14,26 @@ internal class Program
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
builder.Host.UseWindowsService(options => options.ServiceName = "insight_web");
|
builder.Host.UseWindowsService(options => options.ServiceName = "insight_web");
|
||||||
builder.Host.UseSystemd();
|
builder.Host.UseSystemd();
|
||||||
|
builder.WebHost.UseStaticWebAssets();
|
||||||
|
|
||||||
// LOGGING
|
// Configuration
|
||||||
|
builder.Configuration.Defaults();
|
||||||
|
|
||||||
|
// Logging
|
||||||
builder.Logging.ClearProviders();
|
builder.Logging.ClearProviders();
|
||||||
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
||||||
builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Error);
|
builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Error);
|
||||||
builder.Logging.AddFilter("MudBlazor", LogLevel.Warning);
|
builder.Logging.AddFilter("MudBlazor", LogLevel.Warning);
|
||||||
|
|
||||||
builder.Logging.AddSimpleConsole(options =>
|
builder.Logging.AddSimpleConsole(options =>
|
||||||
{
|
{
|
||||||
options.IncludeScopes = false;
|
options.IncludeScopes = false;
|
||||||
options.SingleLine = true;
|
options.SingleLine = true;
|
||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff ";
|
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}");
|
// Services
|
||||||
|
|
||||||
// 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<Bus>();
|
|
||||||
|
|
||||||
// SECURITY
|
|
||||||
builder.Services.AddAuthorization();
|
|
||||||
|
|
||||||
// WEBSERVICES
|
|
||||||
builder.Services.AddWebServices();
|
builder.Services.AddWebServices();
|
||||||
builder.Services.AddProxyServices();
|
|
||||||
builder.Services.AddRoutingServices();
|
|
||||||
builder.Services.AddSignalR(options =>
|
builder.Services.AddSignalR(options =>
|
||||||
{
|
{
|
||||||
options.EnableDetailedErrors = true;
|
options.EnableDetailedErrors = true;
|
||||||
|
|
@ -66,19 +41,23 @@ internal class Program
|
||||||
//options.StreamBufferCapacity = 1024;
|
//options.StreamBufferCapacity = 1024;
|
||||||
options.EnableDetailedErrors = true;
|
options.EnableDetailedErrors = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// INFRASTRUCTURE
|
|
||||||
builder.Services.AddDatabase(builder.Configuration);
|
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<Bus>();
|
||||||
|
|
||||||
// WEB:APP
|
// Modules
|
||||||
|
builder.AddDefaults();
|
||||||
|
builder.AddMetrics();
|
||||||
|
|
||||||
|
// HTTP Pipeline
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// BASICS
|
|
||||||
app.UseForwardedHeaders();
|
app.UseForwardedHeaders();
|
||||||
//app.UseHttpsRedirection();
|
|
||||||
|
|
||||||
// DEV-PROD SETTINGS
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
|
|
@ -89,77 +68,14 @@ internal class Program
|
||||||
//app.UseHsts();
|
//app.UseHsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
// CORS
|
|
||||||
//app.UseCors(x => x
|
|
||||||
// .AllowAnyOrigin()
|
|
||||||
// .AllowAnyMethod()
|
|
||||||
// .AllowAnyHeader());
|
|
||||||
|
|
||||||
// ROUTING
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
// SECURITY
|
|
||||||
//app.UseAuthentication();
|
//app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
// MIDDLEWARE
|
|
||||||
app.UseMiddleware<IdentityMiddleware>();
|
app.UseMiddleware<IdentityMiddleware>();
|
||||||
|
|
||||||
// BLAZOR HUBS (SIGNALR)
|
|
||||||
app.MapBlazorHub();
|
app.MapBlazorHub();
|
||||||
|
|
||||||
// FALLBACK
|
|
||||||
app.MapFallbackToPage("/_Host");
|
app.MapFallbackToPage("/_Host");
|
||||||
|
|
||||||
// STATIC FILES
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
||||||
// HOST START
|
|
||||||
await app.RunAsync().ConfigureAwait(false);
|
await app.RunAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class ServiceExtensions
|
|
||||||
{
|
|
||||||
internal static IServiceCollection AddBrokerServices(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.UseHostedClient<WebSession, IMessage>(options =>
|
|
||||||
{
|
|
||||||
options.Host = configuration.GetValue<string?>(Appsettings.Backend.Host) ?? throw new Exception($"{Appsettings.Backend.Host} value not set (appsettings)");
|
|
||||||
options.Port = configuration.GetValue<int?>(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<WebSession, IMessage, MemPackSerializer<IMessage>>();
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddSingleton<IMessageHandler<WebSession>, AgentHandler>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static IServiceCollection AddRemoteServices(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.UseHostedServer<RemoteSession, IMessage>(options =>
|
|
||||||
{
|
|
||||||
options.Address = IPAddress.Any;
|
|
||||||
options.Port = configuration.GetValue<int?>(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<string?>(Appsettings.Remote.Certificate) ?? throw new Exception($"{Appsettings.Remote.Certificate} value not set (appsettings)");
|
|
||||||
options.CertificatePassword = configuration.GetValue<string?>(Appsettings.Remote.CertificatePassword) ?? throw new Exception($"{Appsettings.Remote.CertificatePassword} value not set (appsettings)");
|
|
||||||
|
|
||||||
options.UseSerializer<RemoteSession, IMessage, MemPackSerializer<IMessage>>();
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddSingleton<IMessageHandler<RemoteSession>, RemoteHandler>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,8 +2,14 @@
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"Urls": "http://127.0.0.1:5001",
|
"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.connection": "mongodb://db.insight.local:27017",
|
||||||
"mongo.connection0": "mongodb://insight.webmatic.de:27017",
|
|
||||||
|
|
||||||
"server.host": "insight.local",
|
"server.host": "insight.local",
|
||||||
"server.port": 3001,
|
"server.port": 3001,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,13 @@
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"Urls": "http://127.0.0.1:5001",
|
"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",
|
"mongo.connection": "mongodb://127.0.0.1:27017",
|
||||||
|
|
||||||
"server.host": "127.0.0.1",
|
"server.host": "127.0.0.1",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue