Пример #1
0
        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();
        }
Пример #2
0
        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();
        }
Пример #3
0
        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);
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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));
        }
Пример #10
0
 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);
 }