2020-10-25 16:11:36 +02:00

111 lines
3.8 KiB
C#

using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using MalwareMultiScan.Api.Data.Configuration;
using MalwareMultiScan.Shared.Data.Requests;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace MalwareMultiScan.Api.Services
{
public class ScanBackendService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<ScanBackendService> _logger;
public ScanBackendService(IConfiguration configuration, IHttpClientFactory httpClientFactory,
ILogger<ScanBackendService> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
var configurationPath = configuration.GetValue<string>("BackendsConfiguration");
if (!File.Exists(configurationPath))
throw new FileNotFoundException("Missing BackendsConfiguration YAML file", configurationPath);
var configurationContent = File.ReadAllText(configurationPath);
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
List = deserializer.Deserialize<ScanBackend[]>(configurationContent);
}
public ScanBackend[] List { get; }
public async Task<bool> Ping(ScanBackend backend)
{
var cancellationTokenSource = new CancellationTokenSource(
TimeSpan.FromSeconds(1));
try
{
using var httpClient = _httpClientFactory.CreateClient();
var pingResponse = await httpClient.GetAsync(
new Uri(new Uri(backend.Endpoint), "/ping"), cancellationTokenSource.Token);
pingResponse.EnsureSuccessStatusCode();
}
catch (Exception exception)
{
_logger.LogError(
exception, $"Failed to ping {backend.Id}");
return false;
}
return true;
}
private async Task<bool> QueueScan(ScanBackend backend, string uri, HttpContent content)
{
var cancellationTokenSource = new CancellationTokenSource(
TimeSpan.FromSeconds(5));
using var httpClient = _httpClientFactory.CreateClient();
try
{
var response = await httpClient.PostAsync(
new Uri(new Uri(backend.Endpoint), uri), content, cancellationTokenSource.Token);
response.EnsureSuccessStatusCode();
}
catch (Exception exception)
{
_logger.LogError(
exception, $"Failed to initiate scan against {backend.Id}");
return false;
}
return true;
}
public async Task<bool> QueueFileScan(
ScanBackend backend, string fileName, Stream fileStream, string callbackUrl)
{
return await QueueScan(backend, "/scan/file", new MultipartFormDataContent
{
{new StringContent(callbackUrl), nameof(FileRequest.CallbackUrl)},
{new StreamContent(fileStream), nameof(FileRequest.InputFile), fileName}
});
}
public async Task<bool> QueueUrlScan(
ScanBackend backend, string url, string callbackUrl)
{
return await QueueScan(backend, "/scan/url", new MultipartFormDataContent
{
{new StringContent(callbackUrl), nameof(UrlRequest.CallbackUrl)},
{new StringContent(url), nameof(UrlRequest.InputUrl)}
});
}
}
}