public async Task Handle(AggregateReportRecordBatch message) { Stopwatch stopwatch = Stopwatch.StartNew(); _log.LogInformation($"Enricher received batch of {message.Records?.Count ?? 0} aggregate reports"); List <IpAddressDetailsRequest> requests = message .Records.Select(x => new IpAddressDetailsRequest(x.HostSourceIp, x.EffectiveDate)) .ToList(); List <IpAddressDetails> responses = await _ipAddressProcessor.Process(requests); List <AggregateReportRecordEnriched> enrichedReports = new List <AggregateReportRecordEnriched>(); foreach (AggregateReportRecord aggregateReportRecord in message.Records) { IpAddressDetails ipAddressDetails = responses.FirstOrDefault(x => x.IpAddress == aggregateReportRecord.HostSourceIp); if (ipAddressDetails is null) { _log.LogInformation($"Unable to enrich message for ip {aggregateReportRecord.HostSourceIp} and date {aggregateReportRecord.EffectiveDate}"); } OrganisationalDomain organisationalDomain = await _organisationalDomainProvider.GetOrganisationalDomain(aggregateReportRecord.HeaderFrom.Trim().Trim('.').ToLower()); AggregateReportRecordEnriched aggregateReportRecordEnriched = _aggregateReportRecordEnrichedFactory.Create(ipAddressDetails, aggregateReportRecord, organisationalDomain.OrgDomain, message.CorrelationId, message.Id); enrichedReports.Add(aggregateReportRecordEnriched); } foreach (AggregateReportRecordEnriched aggregateReportRecordEnriched in enrichedReports) { await _publisher.Publish(aggregateReportRecordEnriched, _enricherConfig.SnsTopicArn); } _log.LogInformation($"Enricher published batch of {enrichedReports.Count} enriched aggregate reports from request for {message.Records.Count} in {stopwatch.Elapsed.Milliseconds} ms"); stopwatch.Stop(); }
public async Task DoesNotAccessOrgDmarcRecordWhenOrgDomain() { string[] records = { "v=DMARC1;p=reject;adkim=s;aspf=s ..." }; string orgDomain = "def.gov.uk"; string domain = "abc.def.gov.uk"; Response domainDnsQueryResponse = CreateRecord(domain, records, RCode.NXDomain); Response orgDomainDnsQueryResponse = CreateRecord(domain, records); OrganisationalDomain organisationalDomain = new OrganisationalDomain(orgDomain, orgDomain); A.CallTo(() => _dnsResolver.GetRecord($"_dmarc.{domain}", A <QType> ._)) .Returns(Task.FromResult(domainDnsQueryResponse)); A.CallTo(() => _dnsResolver.GetRecord($"_dmarc.{orgDomain}", A <QType> ._)) .Returns(Task.FromResult(orgDomainDnsQueryResponse)); A.CallTo(() => _organisationalDomainProvider.GetOrganisationalDomain(A <string> ._)) .Returns(Task.FromResult(organisationalDomain)); DnsResponse dmarcRecords = await _dmarcRecordDnsClient.GetRecord(domain); Assert.That(dmarcRecords.Records.Count, Is.EqualTo(1)); Assert.That(((DmarcRecordInfo)dmarcRecords.Records[0]).Record, Is.EqualTo(records[0])); A.CallTo(() => _organisationalDomainProvider.GetOrganisationalDomain(A <string> ._)).WithAnyArguments() .MustHaveHappenedOnceExactly(); A.CallTo(() => _dnsResolver.GetRecord(A <string> ._, A <QType> ._)).WithAnyArguments() .MustHaveHappenedOnceExactly(); }
private async Task <ReverseDnsResult> Lookup(string ipAddress) { ReverseDnsResult reverseDnsResult = await _reverseDnsLookup.Lookup(ipAddress); if (!reverseDnsResult.ForwardResponses.Any()) { return(new ReverseDnsResult(ipAddress, new List <ReverseDnsResponse> { new ReverseDnsResponse("Unknown", null, "Unknown") })); } if (!reverseDnsResult.ForwardResponses.Any(x => x.IpAddresses.Contains(ipAddress))) { List <ReverseDnsResponse> responses = reverseDnsResult.ForwardResponses.Select(x => new ReverseDnsResponse("Mismatch", x.IpAddresses, "Mismatch")).ToList(); return(new ReverseDnsResult(ipAddress, responses)); } foreach (ReverseDnsResponse forwardResponse in reverseDnsResult.ForwardResponses) { OrganisationalDomain organisationalDomain = await _organisationalDomainProvider.GetOrganisationalDomain(forwardResponse.Host); forwardResponse.OrganisationalDomain = organisationalDomain.OrgDomain; } return(reverseDnsResult); }
public async Task <IActionResult> AddDomain([FromBody] DomainForCreation domain) { string email = User.GetEmail(); ValidationResult validationResult = _domainForCreationValidator.Validate(domain); if (!validationResult.IsValid) { _log.LogWarning($"User {email} made bad request: {validationResult.GetErrorString()}"); return(BadRequest(new ErrorResponse(validationResult.GetErrorString()))); } if (!User.IsAdmin()) { ValidationResult publicDomainValidationResult = _publicDomainForCreationValidator.Validate(new PublicDomainForCreation { Name = domain.Name }); if (!publicDomainValidationResult.IsValid) { _log.LogWarning($"User {email} made bad request: {publicDomainValidationResult.GetErrorString()}"); return(BadRequest(new ErrorResponse(publicDomainValidationResult.GetErrorString()))); } } OrganisationalDomain organisationalDomain = await _organisationalDomainProvider.GetOrganisationalDomain(domain.Name); int?userId = User.GetId(); if (!userId.HasValue) { return(BadRequest(new ErrorResponse("Unable to retrieve user id"))); } if (!organisationalDomain.IsOrgDomain && !organisationalDomain.IsTld) { _log.LogDebug( $"{domain.Name} is not an organisational domain adding {organisationalDomain.OrgDomain}"); Domain.Domain newOrgDomain = await _domainDao.CreateDomain(organisationalDomain.OrgDomain, userId.Value); await _publisher.Publish(new DomainCreated(newOrgDomain.Name, email, DateTime.UtcNow), _config.PublisherConnectionString); } Domain.Domain newDomain = await _domainDao.CreateDomain(domain.Name, userId.Value); await _publisher.Publish(new DomainCreated(domain.Name, email, DateTime.UtcNow), _config.PublisherConnectionString); return(CreatedAtRoute(nameof(GetDomain), new { id = newDomain.Id }, newDomain)); }
public async Task <IActionResult> GetDmarcReadModel(DomainRequest domainRequest) { ValidationResult validationResult = await _domainRequestValidator.ValidateAsync(domainRequest); if (!validationResult.IsValid) { _log.LogWarning($"Bad request: {validationResult.GetErrorString()}"); return(BadRequest(new ErrorResponse(validationResult.GetErrorString()))); } DmarcReadModel dmarc = await _domainStatusDao.GetDmarcReadModel(domainRequest.Id); if (dmarc == null) { Domain.Domain domain = await _domainStatusDao.GetDomain(domainRequest.Id); if (domain == null) { return(NotFound(new ErrorResponse($"No domain found for ID {domainRequest.Id}."))); } return(new ObjectResult(new { records = (List <string>)null, pending = true })); } if (dmarc.HasDmarc) { return(new ObjectResult(dmarc.Model)); } OrganisationalDomain organisationalDomain = await _organisationalDomainProvider.GetOrganisationalDomain(dmarc.Domain.Name); if (organisationalDomain.IsOrgDomain || organisationalDomain.IsTld) { return(new ObjectResult(dmarc.Model)); } DmarcReadModel organisationalDomainDmarcRecord = await _domainStatusDao.GetDmarcReadModel(organisationalDomain.OrgDomain); if (organisationalDomainDmarcRecord == null) { return(new ObjectResult(dmarc.Model)); } JObject readModel = JObject.Parse(organisationalDomainDmarcRecord.Model); readModel.AddFirst(new JProperty("inheritedFrom", JToken.FromObject(organisationalDomainDmarcRecord.Domain, new JsonSerializer { ContractResolver = new CamelCasePropertyNamesContractResolver() }))); return(new ObjectResult(readModel.ToString())); }
public bool IsErrored(DmarcRecord record, out Error error) { SubDomainPolicy subDomainPolicy = record.Tags.OfType <SubDomainPolicy>().FirstOrDefault(); OrganisationalDomain orgDomain = _organisationalDomainProvider.GetOrganisationalDomain(record.Domain) .GetAwaiter().GetResult(); if (orgDomain?.IsOrgDomain == false && subDomainPolicy != null && !subDomainPolicy.IsImplicit) { error = new Error(ErrorType.Warning, string.Format(DmarcRulesResource.SubDomainIneffectualErrorMessage, record.Domain)); return(true); } error = null; return(false); }
public bool IsErrored(DmarcRecord record, out Error error) { SubDomainPolicy subDomainPolicy = record.Tags.OfType <SubDomainPolicy>().FirstOrDefault(); OrganisationalDomain orgDomain = _organisationalDomainProvider.GetOrganisationalDomain(record.Domain).GetAwaiter().GetResult(); if (IsValid(subDomainPolicy, orgDomain)) { error = null; return(false); } string errorMessage = string.Format(DmarcRulesResource.SubdomainPolicyMustBeQuarantineOrRejectErrorMessage, subDomainPolicy?.PolicyType); error = new Error(ErrorType.Warning, errorMessage); return(true); }
public async Task GetDmarcReadModelForDomainWhenDomainDoesntHaveDmarcAndOrgDomainDoesReturnsOrgDomainResult() { int domainId = 1; string readmodel = "{\"readModel\": \"Test\"}"; string orgDomainReadModel = "{\"readModel\": \"Test\"}"; string domainName = "abc.xyz.com"; string organisationalDomainName = "xyz.com"; DomainRequest request = new DomainRequest { Id = domainId }; ValidationResult validationResult = new ValidationResult(new List <ValidationFailure>()); A.CallTo(() => _domainRequestValidator.ValidateAsync(request, CancellationToken.None)).Returns(Task.FromResult(validationResult)); DmarcReadModel dmarcReadModel = new DmarcReadModel(new Domain.Domain(1, domainName), false, readmodel); A.CallTo(() => _domainStatusDao.GetDmarcReadModel(request.Id)).Returns(Task.FromResult(dmarcReadModel)); OrganisationalDomain organisationalDomain = new OrganisationalDomain(organisationalDomainName, domainName); A.CallTo(() => _organisationalDomainProvider.GetOrganisationalDomain(domainName)).Returns(Task.FromResult(organisationalDomain)); DmarcReadModel orgDomainDmarcReadModel = new DmarcReadModel(new Domain.Domain(1, domainName), false, orgDomainReadModel); A.CallTo(() => _domainStatusDao.GetDmarcReadModel(A <string> ._)).Returns(Task.FromResult(orgDomainDmarcReadModel)); IActionResult result = await _domainStatusController.GetDmarcReadModel(request); ObjectResult objectResult = result as ObjectResult; Assert.That(objectResult.Value, Is.TypeOf <string>()); string dmarcReadModelString = objectResult.Value as string; Assert.That(dmarcReadModelString, Does.Contain("\"readModel\": \"Test\"")); Assert.That(dmarcReadModelString, Does.Contain("inheritedFrom")); A.CallTo(() => _domainStatusDao.GetDmarcReadModel(A <int> ._)).MustHaveHappened(Repeated.Exactly.Once); A.CallTo(() => _organisationalDomainProvider.GetOrganisationalDomain(A <string> ._)).MustHaveHappened(Repeated.Exactly.Once); A.CallTo(() => _domainStatusDao.GetDmarcReadModel(A <string> ._)).MustHaveHappened(Repeated.Exactly.Once); }
public override async Task <DnsResponse> GetRecord(string domain) { Response response = await _dnsResolver.GetRecord(FormatQuery(domain), _recordType); OrganisationalDomain organisationalDomain = await _organisationalDomainProvider.GetOrganisationalDomain(domain); string orgDomain = organisationalDomain.OrgDomain; bool isTld = organisationalDomain.IsTld; List <RecordInfo> dnsRecords = GetDmarcRecords(response, orgDomain, isTld); if (!dnsRecords.Any()) { if (!organisationalDomain.IsOrgDomain && !organisationalDomain.IsTld) { response = await _dnsResolver.GetRecord(FormatQuery(orgDomain), _recordType); dnsRecords = GetDmarcRecords(response, orgDomain, isTld, true); } } if (response.header.RCODE == RCode.NoError || response.header.RCODE == RCode.NXDomain) { string records = string.Join(Environment.NewLine, dnsRecords); _log.Trace($"Found following {_recordName} records for {domain}: {Environment.NewLine}{records}"); } else { _log.Error($"Failed to retrieve {_recordName} records with RCODE: {response.header.RCODE}"); } return(new DnsResponse( !dnsRecords.Any() ? new List <RecordInfo> { DmarcRecordInfo.EmptyRecordInfo } : dnsRecords, response.header.RCODE)); }
public bool IsValid(SubDomainPolicy subDomainPolicy, OrganisationalDomain orgDomain) { // Don't error on unknown because there will already be a parser error for this return(!orgDomain.IsOrgDomain || subDomainPolicy == null || subDomainPolicy.PolicyType != PolicyType.None); }