initial upload
This commit is contained in:
parent
a0aa9cc28e
commit
f857f43df4
553 changed files with 46169 additions and 13 deletions
89
src/Server/Insight.Server/Network/AgentSession.cs
Normal file
89
src/Server/Insight.Server/Network/AgentSession.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Server.Network.Handlers.Agent;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Vaitr.Network;
|
||||
|
||||
namespace Insight.Server.Network
|
||||
{
|
||||
public class AgentSession : TcpSession<IAgentMessage>
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
|
||||
private readonly AgentHandler _agentHandler;
|
||||
private readonly IEnumerable<IAgentMessageHandler<AgentSession>> _handlers;
|
||||
|
||||
public AgentSession(AgentHandler agentHandler, IEnumerable<IAgentMessageHandler<AgentSession>> handlers, ISerializer<IAgentMessage> serializer, ILogger<AgentSession> logger) : base(serializer, logger)
|
||||
{
|
||||
_agentHandler = agentHandler;
|
||||
_handlers = handlers;
|
||||
}
|
||||
|
||||
protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Agent ({ep?}) connected", RemoteEndPoint);
|
||||
|
||||
var request = new AuthenticationRequest();
|
||||
|
||||
foreach (var handler in _handlers)
|
||||
{
|
||||
await handler.HandleAsync(this, request, cancellationToken);
|
||||
}
|
||||
|
||||
await _agentHandler.ConnectedAsync(this, default);
|
||||
await _agentHandler.StatisticUpdateAsync(this, default);
|
||||
|
||||
_logger.LogInformation("Agent ({ep?}) ID: {id}", RemoteEndPoint, Id);
|
||||
}
|
||||
|
||||
protected override async ValueTask OnDisconnectedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Agent ({ep?}) disconnected", RemoteEndPoint);
|
||||
|
||||
await _agentHandler.StatisticUpdateAsync(this, default);
|
||||
await _agentHandler.DisconnectedAsync(this, default);
|
||||
}
|
||||
|
||||
protected override async ValueTask OnSentAsync(IPacketContext<IAgentMessage> context, CancellationToken cancellationToken)
|
||||
{
|
||||
await base.OnSentAsync(context, cancellationToken);
|
||||
|
||||
await _agentHandler.StatisticUpdateAsync(this, cancellationToken);
|
||||
}
|
||||
|
||||
protected override async ValueTask OnReceivedAsync(IPacketContext<IAgentMessage> context, CancellationToken cancellationToken)
|
||||
{
|
||||
await base.OnReceivedAsync(context, cancellationToken);
|
||||
|
||||
if (Id is null && context.Packet is not Authentication) return;
|
||||
|
||||
await _agentHandler.StatisticUpdateAsync(this, cancellationToken);
|
||||
|
||||
foreach (var handler in _handlers)
|
||||
{
|
||||
try
|
||||
{
|
||||
await handler.HandleAsync(this, context.Packet, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Agent ({ep?}) {ex}", RemoteEndPoint, ex.ToString());
|
||||
|
||||
//await _mediator.Send(new AgentLog(new AgentLogEntity
|
||||
//{
|
||||
// Category = CategoryEnum.Network.ToString(),
|
||||
// Status = StatusEnum.Error.ToString(),
|
||||
// Message = e.StackTrace
|
||||
//}, this), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override async ValueTask OnHeartbeatAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Agent ({ep?}) Heartbeat", RemoteEndPoint);
|
||||
|
||||
await _agentHandler.StatisticUpdateAsync(this, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
162
src/Server/Insight.Server/Network/Handlers/Agent/AgentHandler.cs
Normal file
162
src/Server/Insight.Server/Network/Handlers/Agent/AgentHandler.cs
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
using Insight.Agent.Enums;
|
||||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class AgentHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
private readonly ILogger<AgentHandler> _logger;
|
||||
|
||||
public AgentHandler(IMongoDatabase database, ILogger<AgentHandler> logger)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is AuthenticationRequest authenticationRequest)
|
||||
{
|
||||
await AuthenticationRequestAsync(sender, authenticationRequest, cancellationToken);
|
||||
}
|
||||
|
||||
if (message is Authentication authentication)
|
||||
{
|
||||
await AuthenticationAsync(sender, authentication, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask AuthenticationRequestAsync(AgentSession session, AuthenticationRequest message, CancellationToken cancellationToken)
|
||||
{
|
||||
await session.SendAsync(message, cancellationToken);
|
||||
|
||||
for (int i = 0; i < 200; i++)
|
||||
{
|
||||
if (session.Id is not null)
|
||||
{
|
||||
_logger.LogInformation("Agent ({ep?}) authenticated", session.RemoteEndPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(50, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_logger.LogError("Authentication Timeout ({ep?})", session.RemoteEndPoint);
|
||||
session.Disconnect();
|
||||
}
|
||||
|
||||
private async ValueTask AuthenticationAsync(AgentSession session, Authentication authentication, CancellationToken cancellationToken)
|
||||
{
|
||||
if (authentication is null)
|
||||
{
|
||||
throw new NullReferenceException($"authentication failed (empty response)");
|
||||
}
|
||||
|
||||
if (authentication.Serial == default)
|
||||
{
|
||||
throw new InvalidDataException($"authentication failed ({nameof(authentication.Serial)})");
|
||||
}
|
||||
|
||||
//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, session.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
|
||||
session.Id = agentEntity.Id;
|
||||
}
|
||||
|
||||
public async ValueTask ConnectedAsync(AgentSession session, CancellationToken cancellationToken)
|
||||
{
|
||||
if (session.Id is null) return;
|
||||
|
||||
// insert connect log
|
||||
await _database.AgentLog()
|
||||
.InsertOneAsync(new AgentLogEntity
|
||||
{
|
||||
Insert = DateTime.Now,
|
||||
Agent = session.Id,
|
||||
Category = CategoryEnum.Network.ToString(),
|
||||
Status = StatusEnum.Information.ToString(),
|
||||
Message = $"Connected ({session.RemoteEndPoint})",
|
||||
Timestamp = DateTime.Now
|
||||
}, cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask DisconnectedAsync(AgentSession session, CancellationToken cancellationToken)
|
||||
{
|
||||
if (session.Id is null) return;
|
||||
|
||||
// insert disconnect log
|
||||
await _database.AgentLog()
|
||||
.InsertOneAsync(new AgentLogEntity
|
||||
{
|
||||
Insert = DateTime.Now,
|
||||
Agent = session.Id,
|
||||
Category = CategoryEnum.Network.ToString(),
|
||||
Status = StatusEnum.Information.ToString(),
|
||||
Message = $"Disconnected ({session.RemoteEndPoint})",
|
||||
Timestamp = DateTime.Now
|
||||
}, cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask StatisticUpdateAsync(AgentSession session, CancellationToken cancellationToken)
|
||||
{
|
||||
if (session.Id is null) return;
|
||||
|
||||
// update agents stats
|
||||
await _database.Agent().UpdateOneAsync(Builders<AgentEntity>
|
||||
.Filter
|
||||
.Eq(p => p.Id, session.Id), Builders<AgentEntity>
|
||||
.Update
|
||||
.Set(p => p.Update, DateTime.Now)
|
||||
.Set(p => p.Activity, session.Activity)
|
||||
.Set(p => p.SentBytes, session.SentBytes)
|
||||
.Set(p => p.ReceivedBytes, session.ReceivedBytes)
|
||||
.Set(p => p.SentPackets, session.SentPackets)
|
||||
.Set(p => p.ReceivedPackets, session.ReceivedPackets), null, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask LogAsync(AgentSession session, AgentLogEntity log, CancellationToken cancellationToken)
|
||||
{
|
||||
if (session.Id is null) return;
|
||||
|
||||
await _database.AgentLog()
|
||||
.InsertOneAsync(log, cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Web.Messages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
using Vaitr.Network;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class ConsoleHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly ISessionPool<WebSession, IWebMessage> _webPool;
|
||||
private readonly IMongoDatabase _database;
|
||||
private readonly ILogger<ConsoleHandler> _logger;
|
||||
|
||||
public ConsoleHandler(
|
||||
ISessionPool<WebSession, IWebMessage> webPool,
|
||||
IMongoDatabase database,
|
||||
ILogger<ConsoleHandler> logger)
|
||||
{
|
||||
_webPool = webPool;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is ConsoleQuery consoleQuery)
|
||||
{
|
||||
await OnConsoleQueryAsync(sender, consoleQuery, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask OnConsoleQueryAsync(AgentSession session, ConsoleQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// check if web online
|
||||
if (_webPool.FirstOrDefault().Value is not WebSession web) return;
|
||||
|
||||
await web.SendAsync(new ConsoleQueryProxy
|
||||
{
|
||||
Id = query.Id,
|
||||
HostId = query.HostId,
|
||||
Query = query.Query,
|
||||
Data = query.Data,
|
||||
Errors = query.Errors,
|
||||
HadErrors = query.HadErrors
|
||||
}, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
145
src/Server/Insight.Server/Network/Handlers/Agent/DriveHandler.cs
Normal file
145
src/Server/Insight.Server/Network/Handlers/Agent/DriveHandler.cs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class DriveHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public DriveHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is DriveList drives)
|
||||
{
|
||||
await OnDrivesAsync(sender, drives, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
if (drive.Volumes is not null && drive.Volumes.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
266
src/Server/Insight.Server/Network/Handlers/Agent/EventHandler.cs
Normal file
266
src/Server/Insight.Server/Network/Handlers/Agent/EventHandler.cs
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
using Insight.Agent.Enums;
|
||||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
using static Insight.Agent.Messages.Event;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class EventHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
private readonly ILogger<EventHandler> _logger;
|
||||
|
||||
public EventHandler(IMongoDatabase database, ILogger<EventHandler> logger)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is Event @event)
|
||||
{
|
||||
await OnEventAsync(sender, @event, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
_ => null
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
CategoryEnum? category = 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 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 bool FilterMonitoringHostLog(HostLogEntity hostLog)
|
||||
{
|
||||
//_logger.LogDebug($"try filter event: {hostLog.Category}.{hostLog.Source}.{hostLog.Status}");
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class InterfaceHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public InterfaceHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is InterfaceList interfaces)
|
||||
{
|
||||
await OnInterfacesAsync(sender, interfaces, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
if (@interface.Addresses is not null && @interface.Addresses.Any())
|
||||
{
|
||||
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.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
if (@interface.Gateways is not null && @interface.Gateways.Any())
|
||||
{
|
||||
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.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
if (@interface.Dns is not null && @interface.Dns.Any())
|
||||
{
|
||||
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.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
if (@interface.Routes is not null && @interface.Routes.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class MainboardHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public MainboardHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is Mainboard mainboard)
|
||||
{
|
||||
await OnMainboardAsync(sender, mainboard, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class MemoryHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public MemoryHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is MemoryList memory)
|
||||
{
|
||||
await OnMemoryAsync(sender, memory, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class OperationSystemHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public OperationSystemHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is OperationSystem os)
|
||||
{
|
||||
await OnOperationSystemAsync(sender, os, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class PrinterHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public PrinterHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is PrinterList printers)
|
||||
{
|
||||
await OnPrintersAsync(sender, printers, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class ProcessorHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public ProcessorHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is ProcessorList processors)
|
||||
{
|
||||
await OnProcessorsAsync(sender, processors, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class ServiceHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public ServiceHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is ServiceList services)
|
||||
{
|
||||
await OnServicesAsync(sender, services, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class SessionHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public SessionHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is SessionList sessions)
|
||||
{
|
||||
await OnSessionsAsync(sender, sessions, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class SoftwareHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public SoftwareHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is ApplicationList applications)
|
||||
{
|
||||
await OnApplicationsAsync(sender, applications, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class StoragePoolHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public StoragePoolHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is StoragePoolList storagePools)
|
||||
{
|
||||
await OnStoragePoolsAsync(sender, storagePools, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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 = new List<string>();
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
if (storagePool.PhysicalDisks is not null && storagePool.PhysicalDisks.Any())
|
||||
{
|
||||
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 = new List<string>();
|
||||
|
||||
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.Any())
|
||||
{
|
||||
var virtualDiskBulk = new List<WriteModel<HostStoragePoolVirtualDiskEntity>>();
|
||||
|
||||
foreach (var storagePool in storagePools)
|
||||
{
|
||||
if (storagePool.VirtualDisks is not null && storagePool.VirtualDisks.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
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 = new List<string>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class SystemInfoHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public SystemInfoHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is SystemInfo systemInfo)
|
||||
{
|
||||
await OnSystemInfoAsync(sender, systemInfo, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
289
src/Server/Insight.Server/Network/Handlers/Agent/TrapHandler.cs
Normal file
289
src/Server/Insight.Server/Network/Handlers/Agent/TrapHandler.cs
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
using Insight.Agent.Enums;
|
||||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
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.Handlers.Agent
|
||||
{
|
||||
public class TrapHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public TrapHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is Trap trap)
|
||||
{
|
||||
await OnTrapAsync(sender, trap, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any() is false) 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;
|
||||
}
|
||||
|
||||
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 parsed = false;
|
||||
|
||||
try
|
||||
{
|
||||
var trim = data[1].Value.Split(new string[] { ":" }, StringSplitOptions.None);
|
||||
task = trim[1].Split(new string[] { "'" }, StringSplitOptions.None)[1].Split("'")[0].Trim();
|
||||
message = trim[1].Split(new string[] { "' " }, StringSplitOptions.None)[1].Trim();
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// skipped for base64 parse
|
||||
}
|
||||
|
||||
if (parsed) return true;
|
||||
|
||||
try
|
||||
{
|
||||
var content = Regex.Replace(data[1].Value, @"\s+", "");
|
||||
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);
|
||||
|
||||
var trim = content.Split(new string[] { ":" }, StringSplitOptions.None);
|
||||
task = trim[1].Split(new string[] { "'" }, StringSplitOptions.None)[1].Split("'")[0].Trim();
|
||||
message = trim[1].Split(new string[] { "' " }, StringSplitOptions.None)[1].Trim();
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//_logger.LogError("{ex}", ex);
|
||||
}
|
||||
|
||||
if (parsed) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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 ex)
|
||||
{
|
||||
//_logger.LogError("{ex}", ex);
|
||||
}
|
||||
|
||||
if (parsed) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class UpdateHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public UpdateHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is UpdateList updates)
|
||||
{
|
||||
await OnUpdatesAsync(sender, updates, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask OnUpdatesAsync(AgentSession session, UpdateList 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.Any())
|
||||
{
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
188
src/Server/Insight.Server/Network/Handlers/Agent/UserHandler.cs
Normal file
188
src/Server/Insight.Server/Network/Handlers/Agent/UserHandler.cs
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class UserHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public UserHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is UserList users)
|
||||
{
|
||||
await OnUsersAsync(sender, users, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
var userBulk = new List<WriteModel<HostUserEntity>>();
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
var userFilter = Builders<HostUserEntity>.Filter.And(new List<FilterDefinition<HostUserEntity>>
|
||||
{
|
||||
Builders<HostUserEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
||||
Builders<HostUserEntity>.Filter.Eq(x => x.Domain, user?.Domain),
|
||||
Builders<HostUserEntity>.Filter.Eq(x => x.Name, user?.Name)
|
||||
});
|
||||
|
||||
var userUpdate = Builders<HostUserEntity>.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<HostUserEntity>(userFilter, userUpdate)
|
||||
{
|
||||
IsUpsert = true
|
||||
});
|
||||
}
|
||||
|
||||
userBulk.Add(new DeleteManyModel<HostUserEntity>(Builders<HostUserEntity>.Filter.And(new List<FilterDefinition<HostUserEntity>>
|
||||
{
|
||||
Builders<HostUserEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
||||
Builders<HostUserEntity>.Filter.Ne(x => x.Batch, batch)
|
||||
})));
|
||||
|
||||
var userResult = await _database.HostSystemUser().BulkWriteAsync(userBulk, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
// groups
|
||||
|
||||
if (users is not null && users.Any())
|
||||
{
|
||||
var groupBulk = new List<WriteModel<HostGroupEntity>>();
|
||||
|
||||
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<HostGroupEntity>.Filter.And(new List<FilterDefinition<HostGroupEntity>>
|
||||
{
|
||||
Builders<HostGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
||||
Builders<HostGroupEntity>.Filter.Eq(x => x.Domain, group?.Domain),
|
||||
Builders<HostGroupEntity>.Filter.Eq(x => x.Name, group?.Name)
|
||||
});
|
||||
|
||||
var groupUpdate = Builders<HostGroupEntity>.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<HostGroupEntity>(groupFilter, groupUpdate)
|
||||
{
|
||||
IsUpsert = true
|
||||
});
|
||||
}
|
||||
|
||||
groupBulk.Add(new DeleteManyModel<HostGroupEntity>(Builders<HostGroupEntity>.Filter.And(new List<FilterDefinition<HostGroupEntity>>
|
||||
{
|
||||
Builders<HostGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
||||
Builders<HostGroupEntity>.Filter.Ne(x => x.Batch, batch)
|
||||
})));
|
||||
|
||||
var groupResult = await _database.HostSystemGroup().BulkWriteAsync(groupBulk, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
// relations
|
||||
|
||||
if (users is not null && users.Any())
|
||||
{
|
||||
var relationBulk = new List<WriteModel<HostUserGroupEntity>>();
|
||||
|
||||
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();
|
||||
|
||||
if (user.Groups is not null && user.Groups.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
var relationFilter = Builders<HostUserGroupEntity>.Filter.And(new List<FilterDefinition<HostUserGroupEntity>>
|
||||
{
|
||||
Builders<HostUserGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
||||
Builders<HostUserGroupEntity>.Filter.Eq(x => x.User, userId),
|
||||
Builders<HostUserGroupEntity>.Filter.Eq(x => x.Group, groupId)
|
||||
});
|
||||
|
||||
var relationUpdate = Builders<HostUserGroupEntity>.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<HostUserGroupEntity>(relationFilter, relationUpdate)
|
||||
{
|
||||
IsUpsert = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
relationBulk.Add(new DeleteManyModel<HostUserGroupEntity>(Builders<HostUserGroupEntity>.Filter.And(new List<FilterDefinition<HostUserGroupEntity>>
|
||||
{
|
||||
Builders<HostUserGroupEntity>.Filter.Eq(x => x.Host, hostEntity.Id),
|
||||
Builders<HostUserGroupEntity>.Filter.Ne(x => x.Batch, batch)
|
||||
})));
|
||||
|
||||
var relationResult = await _database.HostSystemUserSystemGroup().BulkWriteAsync(relationBulk, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class VideocardHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public VideocardHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is VideocardList videocards)
|
||||
{
|
||||
await OnVideocardsAsync(sender, videocards, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
using Insight.Agent.Interfaces;
|
||||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Agent
|
||||
{
|
||||
public class VirtualMaschineHandler : IAgentMessageHandler<AgentSession>
|
||||
{
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
public VirtualMaschineHandler(IMongoDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
||||
{
|
||||
if (message is VirtualMaschineList virtualMaschines)
|
||||
{
|
||||
await OnVirtualMaschinesAsync(sender, virtualMaschines, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
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.Any())
|
||||
{
|
||||
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.Any())
|
||||
{
|
||||
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();
|
||||
|
||||
if (virtualmaschine.Configurations is not null && virtualmaschine.Configurations.Any())
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
using Insight.Agent.Messages;
|
||||
using Insight.Infrastructure;
|
||||
using Insight.Infrastructure.Entities;
|
||||
using Insight.Web.Interfaces;
|
||||
using Insight.Web.Messages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
using Vaitr.Bus;
|
||||
using Vaitr.Network;
|
||||
|
||||
namespace Insight.Server.Network.Handlers.Web
|
||||
{
|
||||
public class ConsoleProxyHandler : IWebMessageHandler<WebSession>
|
||||
{
|
||||
private readonly List<IDisposable> _subscriptions = new();
|
||||
|
||||
private readonly ISessionPool<AgentSession, IAgentMessage> _agentPool;
|
||||
private readonly ISessionPool<WebSession, IWebMessage> _webPool;
|
||||
private readonly IMongoDatabase _database;
|
||||
private readonly Bus _bus;
|
||||
private readonly ILogger<ConsoleProxyHandler> _logger;
|
||||
|
||||
public ConsoleProxyHandler(
|
||||
ISessionPool<AgentSession, IAgentMessage> agentPool,
|
||||
ISessionPool<WebSession, IWebMessage> webPool,
|
||||
IMongoDatabase database,
|
||||
Bus bus,
|
||||
ILogger<ConsoleProxyHandler> logger)
|
||||
{
|
||||
_agentPool = agentPool;
|
||||
_webPool = webPool;
|
||||
_database = database;
|
||||
_bus = bus;
|
||||
_logger = logger;
|
||||
|
||||
_subscriptions.Add(_bus.SubscribeAsync<ConsoleQuery>(OnConsoleQueryAsync, null));
|
||||
}
|
||||
|
||||
public async ValueTask HandleAsync<TMessage>(WebSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IWebMessage
|
||||
{
|
||||
if (message is ConsoleQueryProxyRequest consoleRequest)
|
||||
{
|
||||
await OnConsoleQueryRequestAsync(sender, consoleRequest, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask OnConsoleQueryRequestAsync(WebSession session, ConsoleQueryProxyRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// get host
|
||||
var hostEntity = await _database.Host()
|
||||
.Find(Builders<HostEntity>
|
||||
.Filter
|
||||
.Eq(p => p.Id, request.HostId))
|
||||
.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;
|
||||
|
||||
// send "real" packet to agent
|
||||
await agent.SendAsync(new ConsoleQueryRequest
|
||||
{
|
||||
Id = request.Id,
|
||||
HostId = request.HostId,
|
||||
Query = request.Query
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private async ValueTask OnConsoleQueryAsync(ConsoleQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// check if web online
|
||||
if (_webPool.FirstOrDefault().Value is not WebSession web) return;
|
||||
|
||||
await web.SendAsync(new ConsoleQueryProxy
|
||||
{
|
||||
Id = query.Id,
|
||||
HostId = query.HostId,
|
||||
Query = query.Query,
|
||||
Data = query.Data,
|
||||
Errors = query.Errors,
|
||||
HadErrors = query.HadErrors
|
||||
}, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/Server/Insight.Server/Network/WebSession.cs
Normal file
55
src/Server/Insight.Server/Network/WebSession.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
using Insight.Web.Interfaces;
|
||||
using Insight.Web.Messages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Vaitr.Network;
|
||||
|
||||
namespace Insight.Server.Network;
|
||||
|
||||
public class WebSession : TcpSession<IWebMessage>
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
|
||||
private readonly IEnumerable<IWebMessageHandler<WebSession>> _handlers;
|
||||
|
||||
public WebSession(IEnumerable<IWebMessageHandler<WebSession>> handlers, ISerializer<IWebMessage> serializer, ILogger<WebSession> logger) : base(serializer, logger)
|
||||
{
|
||||
_handlers = handlers;
|
||||
}
|
||||
|
||||
protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Web ({ep?}) connected", RemoteEndPoint);
|
||||
}
|
||||
|
||||
protected override async ValueTask OnDisconnectedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Web ({ep?}) disconnected", RemoteEndPoint);
|
||||
}
|
||||
|
||||
protected override async ValueTask OnSentAsync(IPacketContext<IWebMessage> context, CancellationToken cancellationToken)
|
||||
{
|
||||
await base.OnSentAsync(context, cancellationToken);
|
||||
}
|
||||
|
||||
protected override async ValueTask OnReceivedAsync(IPacketContext<IWebMessage> 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 async ValueTask OnHeartbeatAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Web ({ep?}) Heartbeat", RemoteEndPoint);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue