mirror of
https://github.com/bitwarden/server.git
synced 2025-05-28 23:04:50 -05:00

* Initial stubbing out of the phishing service * Add the phishing domain controller * Add changes for the phishing domain get * Add distributed cache to the phishing domain Signed-off-by: Cy Okeke <cokeke@bitwarden.com> * Rename the variable name Signed-off-by: Cy Okeke <cokeke@bitwarden.com> * Removed IPhishingDomainService * Feature/phishing detection cronjob (#5512) * Added caching to EF implementation. Added error handling and logging * Refactored update method to use sqlbulkcopy instead of performing a round trip for each new insert * Initial implementation for quartz job to get list of phishing domains * Updated phishing domain settings to be its own interface * Add phishing domain detection with checksum-based updates * Updated auth for phishing domain endpoints to either require api, or licensing claims to support both web and browser clients, and selfhost api clients * [Innovation Sprint] Updated Phishing domains to rely on blob storage (#5517) * Updated phishing detection data layer to rely on azure blob storage instead of sql server * dotnet format * Took rider refactors * Ensuring phishing.testcategory.com exists to test against * Added redis to dev's docker-compose * Removed redis from cloud profile * Remove the Authorize attribute * error whitespace fix whitespace formatting * error WHITESPACE: Fix whitespace formatting * Wrapped phishing detection feature behind feature flag (#5532) * Increased timeout for fetching source list a bunch * Removed PhishingDomains policy --------- Signed-off-by: Cy Okeke <cokeke@bitwarden.com> Co-authored-by: Cy Okeke <cokeke@bitwarden.com>
98 lines
3.9 KiB
C#
98 lines
3.9 KiB
C#
using Bit.Core;
|
|
using Bit.Core.Jobs;
|
|
using Bit.Core.PhishingDomainFeatures.Interfaces;
|
|
using Bit.Core.Repositories;
|
|
using Bit.Core.Services;
|
|
using Bit.Core.Settings;
|
|
using Quartz;
|
|
|
|
namespace Bit.Api.Jobs;
|
|
|
|
public class UpdatePhishingDomainsJob : BaseJob
|
|
{
|
|
private readonly GlobalSettings _globalSettings;
|
|
private readonly IPhishingDomainRepository _phishingDomainRepository;
|
|
private readonly ICloudPhishingDomainQuery _cloudPhishingDomainQuery;
|
|
private readonly IFeatureService _featureService;
|
|
public UpdatePhishingDomainsJob(
|
|
GlobalSettings globalSettings,
|
|
IPhishingDomainRepository phishingDomainRepository,
|
|
ICloudPhishingDomainQuery cloudPhishingDomainQuery,
|
|
IFeatureService featureService,
|
|
ILogger<UpdatePhishingDomainsJob> logger)
|
|
: base(logger)
|
|
{
|
|
_globalSettings = globalSettings;
|
|
_phishingDomainRepository = phishingDomainRepository;
|
|
_cloudPhishingDomainQuery = cloudPhishingDomainQuery;
|
|
_featureService = featureService;
|
|
}
|
|
|
|
protected override async Task ExecuteJobAsync(IJobExecutionContext context)
|
|
{
|
|
if (!_featureService.IsEnabled(FeatureFlagKeys.PhishingDetection))
|
|
{
|
|
_logger.LogInformation(Constants.BypassFiltersEventId, "Skipping phishing domain update. Feature flag is disabled.");
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(_globalSettings.PhishingDomain?.UpdateUrl))
|
|
{
|
|
_logger.LogInformation(Constants.BypassFiltersEventId, "Skipping phishing domain update. No URL configured.");
|
|
return;
|
|
}
|
|
|
|
if (_globalSettings.SelfHosted && !_globalSettings.EnableCloudCommunication)
|
|
{
|
|
_logger.LogInformation(Constants.BypassFiltersEventId, "Skipping phishing domain update. Cloud communication is disabled in global settings.");
|
|
return;
|
|
}
|
|
|
|
var remoteChecksum = await _cloudPhishingDomainQuery.GetRemoteChecksumAsync();
|
|
if (string.IsNullOrWhiteSpace(remoteChecksum))
|
|
{
|
|
_logger.LogWarning(Constants.BypassFiltersEventId, "Could not retrieve remote checksum. Skipping update.");
|
|
return;
|
|
}
|
|
|
|
var currentChecksum = await _phishingDomainRepository.GetCurrentChecksumAsync();
|
|
|
|
if (string.Equals(currentChecksum, remoteChecksum, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
_logger.LogInformation(Constants.BypassFiltersEventId,
|
|
"Phishing domains list is up to date (checksum: {Checksum}). Skipping update.",
|
|
currentChecksum);
|
|
return;
|
|
}
|
|
|
|
_logger.LogInformation(Constants.BypassFiltersEventId,
|
|
"Checksums differ (current: {CurrentChecksum}, remote: {RemoteChecksum}). Fetching updated domains from {Source}.",
|
|
currentChecksum, remoteChecksum, _globalSettings.SelfHosted ? "Bitwarden cloud API" : "external source");
|
|
|
|
try
|
|
{
|
|
var domains = await _cloudPhishingDomainQuery.GetPhishingDomainsAsync();
|
|
if (!domains.Contains("phishing.testcategory.com", StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
domains.Add("phishing.testcategory.com");
|
|
}
|
|
|
|
if (domains.Count > 0)
|
|
{
|
|
_logger.LogInformation(Constants.BypassFiltersEventId, "Updating {Count} phishing domains with checksum {Checksum}.",
|
|
domains.Count, remoteChecksum);
|
|
await _phishingDomainRepository.UpdatePhishingDomainsAsync(domains, remoteChecksum);
|
|
_logger.LogInformation(Constants.BypassFiltersEventId, "Successfully updated phishing domains.");
|
|
}
|
|
else
|
|
{
|
|
_logger.LogWarning(Constants.BypassFiltersEventId, "No valid domains found in the response. Skipping update.");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(Constants.BypassFiltersEventId, ex, "Error updating phishing domains.");
|
|
}
|
|
}
|
|
}
|