mirror of
https://github.com/volodymyrsmirnov/MalwareMultiScan.git
synced 2025-08-24 05:22:22 +00:00
refactoring and adding clamav scanning backend
This commit is contained in:
parent
7e63c77419
commit
b1a2357b50
24
.idea/.idea.MalwareMultiScan/.idea/runConfigurations/Dockerfiles_Clamav_Dockerfile.xml
generated
Normal file
24
.idea/.idea.MalwareMultiScan/.idea/runConfigurations/Dockerfiles_Clamav_Dockerfile.xml
generated
Normal file
@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Dockerfiles/Clamav.Dockerfile" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="mindcollapse/malware-multi-scan-worker-clamav" />
|
||||
<option name="buildCliOptions" value="" />
|
||||
<option name="command" value="" />
|
||||
<option name="containerName" value="malware-multi-scan-worker-clamav" />
|
||||
<option name="entrypoint" value="" />
|
||||
<option name="portBindings">
|
||||
<list>
|
||||
<DockerPortBindingImpl>
|
||||
<option name="containerPort" value="9901" />
|
||||
<option name="hostPort" value="9901" />
|
||||
</DockerPortBindingImpl>
|
||||
</list>
|
||||
</option>
|
||||
<option name="commandLineOptions" value="" />
|
||||
<option name="sourceFilePath" value="MalwareMultiScan.Backends/Dockerfiles/Clamav.Dockerfile" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
@ -13,6 +13,11 @@ namespace MalwareMultiScan.Backends.Backends.Abstracts
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
protected AbstractLocalProcessScanBackend(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
protected virtual Regex MatchRegex { get; }
|
||||
protected virtual string BackendPath { get; }
|
||||
protected virtual bool ParseStdErr { get; }
|
||||
@ -22,11 +27,6 @@ namespace MalwareMultiScan.Backends.Backends.Abstracts
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected AbstractLocalProcessScanBackend(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task<string[]> ScanAsync(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
var process = new Process
|
||||
|
@ -41,7 +41,9 @@ namespace MalwareMultiScan.Backends.Backends.Abstracts
|
||||
try
|
||||
{
|
||||
await using (var tempFileStream = File.OpenWrite(tempFile))
|
||||
{
|
||||
await stream.CopyToAsync(tempFileStream, cancellationToken);
|
||||
}
|
||||
|
||||
return await ScanAsync(tempFile, cancellationToken);
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using MalwareMultiScan.Backends.Backends.Abstracts;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MalwareMultiScan.Backends.Backends.Implementations
|
||||
{
|
||||
public class ClamavScanBackend : AbstractLocalProcessScanBackend
|
||||
{
|
||||
public ClamavScanBackend(ILogger logger) : base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name { get; } = "Clamav";
|
||||
|
||||
public override DateTime DatabaseLastUpdate =>
|
||||
File.GetLastWriteTime("/var/lib/clamav/daily.cvd");
|
||||
|
||||
protected override string BackendPath { get; } = "/usr/bin/clamscan";
|
||||
|
||||
protected override Regex MatchRegex { get; } =
|
||||
new Regex(@"(\S+): (?<threat>[\S]+) FOUND", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||
|
||||
protected override bool ParseStdErr { get; } = false;
|
||||
|
||||
protected override string GetBackendArguments(string path)
|
||||
{
|
||||
return $"--no-summary {path}";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using MalwareMultiScan.Backends.Backends.Abstracts;
|
||||
@ -9,22 +8,26 @@ namespace MalwareMultiScan.Backends.Backends.Implementations
|
||||
{
|
||||
public class WindowsDefenderScanBackend : AbstractLocalProcessScanBackend
|
||||
{
|
||||
public WindowsDefenderScanBackend(ILogger logger) : base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name { get; } = "Windows Defender";
|
||||
|
||||
public override DateTime DatabaseLastUpdate =>
|
||||
File.GetLastWriteTime("/opt/engine/mpavbase.vdm");
|
||||
|
||||
protected override string BackendPath { get; } = "/opt/mpclient";
|
||||
|
||||
protected override Regex MatchRegex { get; } =
|
||||
new Regex(@"EngineScanCallback\(\)\: Threat (?<threat>[\S]+) identified",
|
||||
new Regex(@"EngineScanCallback\(\): Threat (?<threat>[\S]+) identified",
|
||||
RegexOptions.Compiled | RegexOptions.Multiline);
|
||||
|
||||
protected override bool ParseStdErr { get; } = true;
|
||||
|
||||
protected override string GetBackendArguments(string path) => path;
|
||||
|
||||
public WindowsDefenderScanBackend(ILogger logger) : base(logger)
|
||||
protected override string GetBackendArguments(string path)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
FROM mindcollapse/malware-multi-scan-base:latest
|
||||
FROM mindcollapse/malware-multi-scan-worker:latest
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
@ -6,3 +6,5 @@ RUN apt-get update && apt-get install -y clamav
|
||||
RUN freshclam --quiet
|
||||
|
||||
ENV MULTI_SCAN_BACKEND_BIN=/usr/bin/clamscan
|
||||
|
||||
ENV BackendType=Clamav
|
@ -19,4 +19,3 @@ COPY --from=backend /opt/loadlibrary/engine /opt/engine
|
||||
COPY --from=backend /opt/loadlibrary/mpclient /opt/mpclient
|
||||
|
||||
ENV BackendType=Defender
|
||||
ENV ScanTimeout=300
|
@ -2,6 +2,7 @@ namespace MalwareMultiScan.Shared.Data.Enums
|
||||
{
|
||||
public enum BackendType
|
||||
{
|
||||
Defender
|
||||
Defender,
|
||||
Clamav
|
||||
}
|
||||
}
|
@ -21,7 +21,9 @@ namespace MalwareMultiScan.Worker.Controllers
|
||||
var temporaryFile = Path.GetTempFileName();
|
||||
|
||||
await using (var temporaryFileSteam = System.IO.File.OpenWrite(temporaryFile))
|
||||
{
|
||||
await request.InputFile.CopyToAsync(temporaryFileSteam);
|
||||
}
|
||||
|
||||
BackgroundJob.Enqueue<ScanJob>(
|
||||
x => x.ScanFile(temporaryFile, request.CallbackUrl));
|
||||
@ -33,7 +35,7 @@ namespace MalwareMultiScan.Worker.Controllers
|
||||
[ProducesResponseType(StatusCodes.Status202Accepted)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[Route("/scan/url")]
|
||||
public IActionResult ScanUrl(UrlRequest request)
|
||||
public IActionResult ScanUrl([FromForm] UrlRequest request)
|
||||
{
|
||||
BackgroundJob.Enqueue<ScanJob>(
|
||||
x => x.ScanUrl(request.InputUrl, request.CallbackUrl));
|
||||
|
@ -6,8 +6,7 @@ COPY MalwareMultiScan.Worker /src/MalwareMultiScan.Worker
|
||||
COPY MalwareMultiScan.Shared /src/MalwareMultiScan.Shared
|
||||
COPY MalwareMultiScan.Backends /src/MalwareMultiScan.Backends
|
||||
|
||||
RUN dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true -o ./publish \
|
||||
MalwareMultiScan.Worker/MalwareMultiScan.Worker.csproj
|
||||
RUN dotnet publish -c Release -r linux-x64 -o ./publish MalwareMultiScan.Worker/MalwareMultiScan.Worker.csproj
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Hangfire;
|
||||
using MalwareMultiScan.Backends.Backends.Implementations;
|
||||
using MalwareMultiScan.Shared.Data.Enums;
|
||||
using MalwareMultiScan.Shared.Data.Responses;
|
||||
@ -14,23 +17,27 @@ namespace MalwareMultiScan.Worker.Jobs
|
||||
{
|
||||
public class ScanJob
|
||||
{
|
||||
private readonly ILogger<ScanJob> _logger;
|
||||
private readonly IScanBackend _backend;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<ScanJob> _logger;
|
||||
private readonly int _scanTimeout;
|
||||
|
||||
public ScanJob(IConfiguration configuration, ILogger<ScanJob> logger)
|
||||
public ScanJob(IConfiguration configuration, ILogger<ScanJob> logger,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_scanTimeout = configuration.GetValue<int>("ScanTimeout");
|
||||
|
||||
_backend = configuration.GetValue<BackendType>("BackendType") switch
|
||||
{
|
||||
BackendType.Defender => new WindowsDefenderScanBackend(logger),
|
||||
BackendType.Clamav => new ClamavScanBackend(logger),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
|
||||
public async Task PostResult(ResultResponse response, Uri callbackUrl, CancellationToken cancellationToken)
|
||||
private async Task PostResult(ResultResponse response, Uri callbackUrl, CancellationToken cancellationToken)
|
||||
{
|
||||
var serializedResponse = JsonSerializer.Serialize(
|
||||
response, typeof(ResultResponse), new JsonSerializerOptions
|
||||
@ -38,7 +45,15 @@ namespace MalwareMultiScan.Worker.Jobs
|
||||
WriteIndented = true
|
||||
});
|
||||
|
||||
_logger.LogInformation(serializedResponse);
|
||||
_logger.LogInformation(
|
||||
$"Sending following payload to {callbackUrl}: {serializedResponse}");
|
||||
|
||||
using var httpClient = _httpClientFactory.CreateClient();
|
||||
|
||||
var callbackResponse = await httpClient.PostAsync(callbackUrl,
|
||||
new StringContent(serializedResponse, Encoding.UTF8, "application/json"), cancellationToken);
|
||||
|
||||
_logger.LogInformation($"Callback URL {callbackUrl} returned a status {callbackResponse.StatusCode}");
|
||||
}
|
||||
|
||||
private async Task Scan(Func<CancellationToken, Task<string[]>> scanMethod, Uri callbackUrl)
|
||||
@ -70,11 +85,13 @@ namespace MalwareMultiScan.Worker.Jobs
|
||||
await PostResult(response, callbackUrl, cancellationToken);
|
||||
}
|
||||
|
||||
[AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
||||
public async Task ScanUrl(Uri url, Uri callbackUrl)
|
||||
{
|
||||
await Scan(async t => await _backend.ScanAsync(url, t), callbackUrl);
|
||||
}
|
||||
|
||||
[AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
||||
public async Task ScanFile(string file, Uri callbackUrl)
|
||||
{
|
||||
try
|
||||
|
@ -13,6 +13,7 @@ namespace MalwareMultiScan.Worker
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddControllers();
|
||||
services.AddHttpClient();
|
||||
|
||||
services.AddSingleton<ScanJob>();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user