public async Task PublishesDomainMissingMessageWhenDomainExistsAndRecordsStale() { EntityDkimEntityState dkimInfoResponse = GetEntityDkimEntityState(DateTime.UnixEpoch.AddDays(-2)); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.UnixEpoch); A.CallTo(() => _dao.GetDkimSelectors("testDomain")).Returns(Task.FromResult(dkimInfoResponse)); EntityDkimEntityState result = await _dkimService.GetDkimForDomain("testDomain"); A.CallTo(() => _messagePublisher.Publish(A <DomainMissing> ._, A <string> ._)) .MustHaveHappenedOnceExactly(); Assert.AreSame(dkimInfoResponse, result); }
public void ContainsIsPositiveForItemInsideValidityPeriod() { A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.UnixEpoch); _recentlyProcessedLedger.Set("testHost"); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.UnixEpoch.AddSeconds(ValidityPeriod - 1)); Assert.True(_recentlyProcessedLedger.Contains("testHost")); }
public bool Contains(string host) { _log.LogDebug($"Searching ledger for host: {host}"); DateTime now = _clock.GetDateTimeUtc(); if (_ledgerItems.TryGetValue(host, out DateTime value) && value > now) { _log.LogDebug($"Host {host} found in ledger with TTL of {(_ledgerItems[host] - now).TotalSeconds} seconds"); return(true); } _log.LogDebug($"Host {host} not found in ledger"); return(false); }
public async Task ShouldSaveAndDispatchMxEntityCreatedWhenDomainCreatedReceivedAndDomainDoesNotExists() { string domainName = "testDomainName"; string snsTopicArn = "SnsTopicArn"; A.CallTo(() => _dao.Get(domainName.ToLower())).Returns(Task.FromResult((MxEntityState)null)); A.CallTo(() => _mxEntityConfig.SnsTopicArn).Returns(snsTopicArn); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.MinValue); await _mxEntity.Handle(new DomainCreated(domainName, string.Empty, DateTime.MaxValue)); A.CallTo(() => _dao.Save(A <MxEntityState> .That.Matches(state => state.MxState == MxState.Created))).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <MxEntityCreated> .That.Matches(entity => entity.Id == domainName.ToLower()), snsTopicArn)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <CreateScheduledReminder> .That.Matches(a => a.ResourceId == domainName.ToLower() && a.Service == "Mx" && a.ScheduledTime == DateTime.MinValue), snsTopicArn)).MustHaveHappenedOnceExactly(); }
public void Setup() { _asInfoProvider = A.Fake <IAsInfoProvider>(); _blocklistProvider = A.Fake <IBlocklistProvider>(); _reverseDnsProvider = A.Fake <IReverseDnsProvider>(); _log = A.Fake <ILogger <IpAddressLookup> >(); _clock = A.Fake <IClock>(); _ipAddressLookup = new IpAddressLookup(_asInfoProvider, _blocklistProvider, _reverseDnsProvider, _clock, _log); A.CallTo(() => _blocklistProvider.GetBlocklistAppearances(A <List <string> > ._)).ReturnsLazily((List <string> arguments) => { return(Task.FromResult(arguments.Select(x => new BlocklistResult(x, new List <BlocklistAppearance> { new BlocklistAppearance("flag", "source", Guid.NewGuid().ToString()) }) ).ToList())); }); A.CallTo(() => _reverseDnsProvider.GetReverseDnsResult(A <List <string> > ._)).ReturnsLazily((List <string> arguments) => { return(Task.FromResult(arguments.Select(x => new ReverseDnsResult(x, new List <ReverseDnsResponse> { new ReverseDnsResponse(Guid.NewGuid().ToString(), new List <string>()) })).ToList())); }); A.CallTo(() => _asInfoProvider.GetAsInfo(A <List <string> > ._)).ReturnsLazily((List <string> arguments) => { return(Task.FromResult(arguments.Select(x => new AsInfo { IpAddress = x, Description = Guid.NewGuid().ToString() }).ToList())); }); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(new DateTime(1999, 01, 01)); }
private async Task HandleReadyToPoll(string hostName, string messageType) { TlsEntityState state = await LoadState(hostName, messageType); if (state.LastUpdated == null || _clock.GetDateTimeUtc() > state.LastUpdated.Value.AddSeconds(_tlsEntityConfig.TlsResultsCacheInSeconds)) { state.TlsState = TlsState.PollPending; await _dao.Save(state); _dispatcher.Dispatch(new TlsTestPending(hostName), _tlsEntityConfig.SnsTopicArn); _log.LogInformation($"A TlsTestPending message for host: {hostName} has been dispatched to SnsTopic: {_tlsEntityConfig.SnsTopicArn}"); } else { _log.LogInformation($"A request to re-test {hostName} was ignored as it was last tested at {state.LastUpdated.Value} and the re-test cache " + $"is {TimeSpan.FromSeconds(_tlsEntityConfig.TlsResultsCacheInSeconds):dd\\d\\:hh\\h\\:mm\\m\\:ss\\s}."); // dd/hh/mm/ss } }
public async Task HandleCreateDomainPublishesIfStale() { A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.UnixEpoch); A.CallTo(() => _dkimEntityDao.Get(Id)).Returns(new DkimEntityState(Id, 1, DkimState.Created, DateTime.UnixEpoch, DateTime.UnixEpoch.AddDays(-2), DateTime.UnixEpoch, new List <DkimSelector>())); await _dkimEntity.Handle(new DomainCreated(Id, "*****@*****.**", DateTime.Now)); A.CallTo(() => _dkimEntityDao.Save(A <DkimEntityState> ._)).MustNotHaveHappened(); A.CallTo(() => _dispatcher.Dispatch(A <DkimEntityCreated> .That.Matches(x => x.State == DkimState.Created && x.Id == Id), A <string> ._)).MustHaveHappenedOnceExactly(); }
public async Task GetCertificatesGoesToOriginForStateOnFirstCallAndReturnsValue() { A.CallTo(() => _clock.GetDateTimeUtc()).Returns(new DateTime(2018, 01, 01)); string issuer = "CN=ABC, O=ABC, S=LONDON, C=uk"; X509Certificate x509Certificate = A.Fake <X509Certificate>(); A.CallTo(() => x509Certificate.Issuer).Returns(issuer); A.CallTo(() => x509Certificate.Subject).Returns(issuer); A.CallTo(() => _rootCertificateProvider.GetRootCaCertificates()) .Returns(Task.FromResult(new List <X509Certificate> { x509Certificate })); X509Certificate certificate = await _rootCertificateLookUp.GetCertificate(issuer); Assert.That(certificate, Is.Not.Null); A.CallTo(() => _rootCertificateProvider.GetRootCaCertificates()).MustHaveHappenedOnceExactly(); }
public async Task <X509Certificate> GetCertificate(string issuer) { DateTime now = _clock.GetDateTimeUtc(); if (_certificateDictionary == null || _certificateDictionaryCacheExpiryTime <= now) { List <X509Certificate> x509Certificates = await _rootCertificateProvider.GetRootCaCertificates(); _certificateDictionary = x509Certificates.Where(_ => _.Issuer.Trim() == _.Subject.Trim()).ToDictionary(_ => _.Issuer.Trim().ToLower()); _certificateDictionaryCacheExpiryTime = now.Add(_certificateDictionaryTtl); } _certificateDictionary.TryGetValue(issuer.Trim().ToLower(), out var cert); return(cert); }
public async Task <List <IpAddressDetails> > Lookup(List <IpAddressDetailsRequest> ipAddressDetailsRequests) { DateTime nowUtc = _clock.GetDateTimeUtc(); List <string> distinctIpAddresses = ipAddressDetailsRequests .Select(x => x.IpAddress).Distinct().ToList(); List <string> blockListIpAddressesToLookUp = ipAddressDetailsRequests .Where(x => x.Date >= nowUtc.Date.AddDays(BlocklistLookupWindowDays)) .Select(x => x.IpAddress).Distinct().ToList(); _log.LogDebug($"IpAddressLookup received request for {ipAddressDetailsRequests.Count} IpAddressDetails containing {distinctIpAddresses.Count} distinct IP addresses and {blockListIpAddressesToLookUp.Count} distinct IP addresses within blocklist window"); Task <List <BlocklistResult> > blocklistResultsTask = _blocklistProvider.GetBlocklistAppearances(blockListIpAddressesToLookUp); Task <List <AsInfo> > asInfoTask = _asInfoProvider.GetAsInfo(distinctIpAddresses); Task <List <ReverseDnsResult> > reverseDnsResponsesTask = _reverseDnsProvider.GetReverseDnsResult(distinctIpAddresses); await Task.WhenAll(blocklistResultsTask, asInfoTask, reverseDnsResponsesTask); List <BlocklistResult> blocklistResults = await blocklistResultsTask; List <AsInfo> asInfos = await asInfoTask; List <ReverseDnsResult> reverseDnsResponses = await reverseDnsResponsesTask; Dictionary <string, BlocklistResult> blocklistResultsDictionary = blocklistResults.Where(x => x.IpAddress != null).ToDictionary(x => x.IpAddress); Dictionary <string, AsInfo> asInfoDictionary = asInfos.Where(x => x.IpAddress != null).ToDictionary(x => x.IpAddress); Dictionary <string, ReverseDnsResult> reverseDnsResponseDictionary = reverseDnsResponses.Where(x => x.OriginalIpAddress != null).ToDictionary(x => x.OriginalIpAddress); List <IpAddressDetails> responses = ipAddressDetailsRequests.Select(request => { bool blockListResultHasValue = blocklistResultsDictionary.TryGetValue(request.IpAddress, out BlocklistResult blockListResult); bool asInfoHasValue = asInfoDictionary.TryGetValue(request.IpAddress, out AsInfo asInfo); bool reverseDnsResponseHasValue = reverseDnsResponseDictionary.TryGetValue(request.IpAddress, out ReverseDnsResult reverseDnsResult); return(new IpAddressDetails( request.IpAddress, request.Date, asInfoHasValue ? asInfo.AsNumber : 0, asInfoHasValue ? asInfo.Description : "", asInfoHasValue ? asInfo.CountryCode : "", blockListResultHasValue ? blockListResult.BlocklistAppearances : null, reverseDnsResponseHasValue ? reverseDnsResult.ForwardResponses : null, nowUtc.AddDays(AsnDataAgeDays).Date, nowUtc, nowUtc)); }).ToList(); _log.LogInformation($"Returning {responses.Count} IpAddressDetails from request for {ipAddressDetailsRequests.Count}"); return(responses); }
public async Task ShouldUpdateAndDispatchPollPendingWhenScheduledReminderArrivesAfterTtl() { const string hostName = "testhostname"; const string snsTopicArn = "snsTopicArn"; DateTime testDate = new DateTime(2000, 01, 01); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(testDate); A.CallTo(() => _dao.Get(hostName)).Returns(new TlsEntityState(hostName) { TlsState = TlsState.Created, LastUpdated = testDate - TimeSpan.FromSeconds(3) }); A.CallTo(() => _tlsEntityConfig.TlsResultsCacheInSeconds).Returns(2); A.CallTo(() => _tlsEntityConfig.SnsTopicArn).Returns(snsTopicArn); await _tlsEntity.Handle(new TlsScheduledReminder(Guid.NewGuid().ToString(), hostName)); A.CallTo(() => _dao.Save(A <TlsEntityState> .That.Matches(e => e.TlsState == TlsState.PollPending))).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <TlsTestPending> .That.Matches(entity => entity.Id == hostName), snsTopicArn)).MustHaveHappenedOnceExactly(); }
public async Task Handle(DomainCreated message) { string domainName = message.Id.ToLower(); MxEntityState state = await _dao.Get(domainName); if (state != null) { _log.LogInformation($"Ignoring {nameof(DomainCreated)} as MxEntity already exists for {domainName}."); return; } await _dao.Save(new MxEntityState(domainName)); _log.LogInformation($"Created MxEntity for {domainName}."); MxEntityCreated mxEntityCreated = new MxEntityCreated(domainName); _dispatcher.Dispatch(mxEntityCreated, _mxEntityConfig.SnsTopicArn); _log.LogInformation( $"An MxEntityCreated message for Domain: {domainName} has been dispatched to SnsTopic: {_mxEntityConfig.SnsTopicArn}"); Message createScheduledReminder = new CreateScheduledReminder(Guid.NewGuid().ToString(), "Mx", domainName, _clock.GetDateTimeUtc()); _dispatcher.Dispatch(createScheduledReminder, _mxEntityConfig.SnsTopicArn); _log.LogInformation( $"A CreateScheduledReminder message for Domain: {domainName} has been dispatched to SnsTopic: {_mxEntityConfig.SnsTopicArn}"); }
public async Task Handle(DomainCreated message) { string id = message.Id.ToLower(); DkimEntityState state = await _dao.Get(id); if (state != null) { if (state.RecordsLastUpdated == null || state.RecordsLastUpdated.Value.AddDays(DaysBeforeBeingConsideredStale) <= _clock.GetDateTimeUtc()) { _dispatcher.Dispatch(new DkimEntityCreated(id, state.Version), _config.SnsTopicArn); _log.LogInformation("Published DkimEntityCreated for stale DkimEntity {Id}.", id); } else { throw new MailCheckException($"Cannot handle event {nameof(DomainCreated)} as an up to date DkimEntity already exists for {id}."); } } else { state = new DkimEntityState(id, 1, DkimState.Created, DateTime.UtcNow, null, null, null); await _dao.Save(state); _dispatcher.Dispatch(new DkimEntityCreated(id, state.Version), _config.SnsTopicArn); _log.LogInformation("Created DkimEntity for {Id}.", id); } }
public async Task <EntityDkimEntityState> GetDkimForDomain(string requestDomain) { EntityDkimEntityState response = await _dao.GetDkimSelectors(requestDomain); if (response?.RecordsLastUpdated == null || response.RecordsLastUpdated.Value.AddDays(DaysBeforeBeingConsideredStale) <= _clock.GetDateTimeUtc()) { await _messagePublisher.Publish(new DomainMissing(requestDomain), _config.MicroserviceOutputSnsTopicArn); } return(response); }