public async Task Publish(TlsResultsEvaluated message) { List <TlsEvaluatedResult> evaluatedResults = message.TlsRecords?.Records?.Select(x => x.TlsEvaluatedResult).ToList(); List <Error> evaluatedCertificates = message.Certificates?.Errors; Dictionary <string, List <TlsEntityState> > domainsContainingHost = await _dao.GetDomains(message.Id); foreach (string domain in domainsContainingHost.Keys) { List <TlsEntityState> existingHostStates = domainsContainingHost[domain]; List <TlsEvaluatedResult> existingResults = existingHostStates .Where(x => x.TlsRecords?.Records != null) .SelectMany(x => x.TlsRecords?.Records?.Select(y => y.TlsEvaluatedResult)).ToList(); List <Error> existingCertificates = existingHostStates .Where(x => x.CertificateResults?.Errors != null) .SelectMany(x => x.CertificateResults?.Errors).ToList(); existingResults.AddRange(evaluatedResults ?? new List <TlsEvaluatedResult>()); existingCertificates.AddRange(evaluatedCertificates ?? new List <Error>()); Status status = _domainStatusEvaluator.GetStatus(existingResults, existingCertificates); DomainStatusEvaluation domainStatusEvaluation = new DomainStatusEvaluation(domain, "TLS", status); _log.LogInformation( $"Publishing TLS domain status for domain {domain} because it contains mx host {message.Id} which was evaluated"); _dispatcher.Dispatch(domainStatusEvaluation, _tlsEntityConfig.SnsTopicArn); } }
public async Task WhenAllTestAreTcpConnectionFailedShouldReturnOneError() { EvaluatorResult expectedResult = EvaluatorResult.INCONCLUSIVE; string expectedMessage = "We were unable to create a TLS connection with this server. This could be because the server does not support TLS " + "or because Mail Check servers have been blocked. We will keep trying to test TLS with this server, so please check back later or get in touch " + "if you think there's a problem."; var mxHostTlsResults = new TlsTestResults("abc.def.gov.uk", false, false, new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), new BouncyCastleTlsTestResult(TlsError.TCP_CONNECTION_FAILED, "", null), null); IMxSecurityEvaluator mxSecurityEvaluator = A.Fake <IMxSecurityEvaluator>(); ILogger <EvaluationProcessor> log = A.Fake <ILogger <EvaluationProcessor> >(); IEvaluationProcessor processor = new EvaluationProcessor(mxSecurityEvaluator, log); TlsResultsEvaluated results = await processor.Process(mxHostTlsResults); Assert.AreEqual(expectedResult, results.TlsRecords.Tls12AvailableWithBestCipherSuiteSelected.TlsEvaluatedResult.Result.Value); Assert.AreEqual(expectedMessage, results.TlsRecords.Tls12AvailableWithBestCipherSuiteSelected.TlsEvaluatedResult.Description); }
public async Task <TlsResultsEvaluated> Process(TlsTestResults tlsTestRptRecords) { Stopwatch stopwatch = Stopwatch.StartNew(); TlsResultsEvaluated result = await EvaluateMxRecordProfile(tlsTestRptRecords); stopwatch.Stop(); _log.LogDebug($"Processed domain with ID {tlsTestRptRecords.Id}. Took {stopwatch.Elapsed.TotalSeconds} seconds."); return(result); }
public async Task ShouldHandleChangeSaveAndDispatchWhenTlsTestResultIsReceived() { string snsTopicArn = "snsTopicArn"; A.CallTo(() => _tlsEntityConfig.SnsTopicArn).Returns(snsTopicArn); string hostName = "testhostname"; TlsEntityState stateFromDb = new TlsEntityState(hostName) { TlsState = TlsState.Created }; A.CallTo(() => _dao.Get(hostName)).Returns(Task.FromResult(stateFromDb)); A.CallTo(() => _dao.GetDomainsFromHost(hostName)).Returns(Task.FromResult(new List <string> { "test.gov.uk" })); A.CallTo(() => _tlsEntityConfig.NextScheduledInSeconds).Returns(33); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.MinValue); CertificateResults certificateResults = new CertificateResults(null, null); TlsResultsEvaluated message = new TlsResultsEvaluated(hostName, false, new TlsRecords( new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) , new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) , new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) , new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) ), certificateResults); await _tlsEntity.Handle(message); Assert.AreEqual(stateFromDb.TlsState, TlsState.Evaluated); Assert.AreEqual(stateFromDb.TlsRecords, message.TlsRecords); Assert.AreEqual(stateFromDb.LastUpdated, message.Timestamp); List <string> domains = new List <string>(); A.CallTo(() => _changeNotifierComposite.Handle(stateFromDb, message, A <List <string> > ._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dao.Save(stateFromDb)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <TlsRecordEvaluationsChanged> .That.Matches(a => a.Id == message.Id && a.TlsRecords == message.TlsRecords && a.CertificateResults == message.Certificates), snsTopicArn)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <CreateScheduledReminder> .That.Matches(a => a.ResourceId == hostName && a.Service == "Tls" && a.ScheduledTime.Second == 33), snsTopicArn)).MustHaveHappenedOnceExactly(); }
public async Task AllRulePassNoErrors() { TlsResultsEvaluated EvaluatorResults = A.Fake <TlsResultsEvaluated>(); A.CallTo(() => _rule1.Evaluate(EvaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult>()); A.CallTo(() => _rule2.Evaluate(EvaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult>()); var evaluationResult = await _evaluator.Evaluate(EvaluatorResults); Assert.That(evaluationResult.Messages, Is.Empty); }
public async Task Handle(TlsTestResults message) { TlsResultsEvaluated results = await _tlsRptEvaluationProcessor.Process(message); if (message.Certificates.Any()) { CertificateResults certs = await _certificateProcessor.Process(message); results = new TlsResultsEvaluated(results.Id, results.Failed, results.TlsRecords, certs); } _dispatcher.Dispatch(results, _config.SnsTopicArn); }
protected async Task <TlsResultsEvaluated> EvaluateMxRecordProfile(TlsTestResults tlsTestResults) { List <BouncyCastleTlsTestResult> bouncyCastleTlsTestResults = new List <BouncyCastleTlsTestResult> { tlsTestResults.Ssl3FailsWithBadCipherSuite, tlsTestResults.Tls10AvailableWithBestCipherSuiteSelected, tlsTestResults.Tls10AvailableWithWeakCipherSuiteNotSelected, tlsTestResults.Tls11AvailableWithBestCipherSuiteSelected, tlsTestResults.Tls11AvailableWithWeakCipherSuiteNotSelected, tlsTestResults.Tls12AvailableWithBestCipherSuiteSelected, tlsTestResults.Tls12AvailableWithBestCipherSuiteSelectedFromReverseList, tlsTestResults.Tls12AvailableWithSha2HashFunctionSelected, tlsTestResults.Tls12AvailableWithWeakCipherSuiteNotSelected, tlsTestResults.TlsSecureDiffieHellmanGroupSelected, tlsTestResults.TlsSecureEllipticCurveSelected, tlsTestResults.TlsWeakCipherSuitesRejected }; bool hasFailedConnection = bouncyCastleTlsTestResults.All(_ => _.TlsError == TlsError.SESSION_INITIALIZATION_FAILED || _.TlsError == TlsError.TCP_CONNECTION_FAILED); if (hasFailedConnection) { _log.LogDebug($"TLS connection failed for host {tlsTestResults.Id}"); string failedConnectionErrors = string.Join(", ", bouncyCastleTlsTestResults .Select(_ => _.ErrorDescription) .Distinct() .ToList()); return(GetConnectionFailedResults(tlsTestResults.Id, failedConnectionErrors, tlsTestResults.ToTlsResult())); } bool hostNotFound = bouncyCastleTlsTestResults.All(_ => _.TlsError == TlsError.HOST_NOT_FOUND); if (hostNotFound) { _log.LogDebug($"Host not found for {tlsTestResults.Id}"); return(GetHostNotFoundResults(tlsTestResults.Id, tlsTestResults.ToTlsResult())); } _log.LogDebug($"Evaluating TLS connection results for {tlsTestResults.Id}."); TlsResultsEvaluated tlsEvaluatedResults = await _mxSecurityEvaluator.Evaluate(tlsTestResults); return(tlsEvaluatedResults); }
public async Task ShouldRescheduledWhenItHasFailedToCorrectPeriod() { string snsTopicArn = "snsTopicArn"; A.CallTo(() => _tlsEntityConfig.SnsTopicArn).Returns(snsTopicArn); string hostName = "testhostname"; TlsEntityState stateFromDb = new TlsEntityState(hostName) { TlsState = TlsState.Created }; A.CallTo(() => _dao.Get(hostName)).Returns(Task.FromResult(stateFromDb)); A.CallTo(() => _tlsEntityConfig.FailureNextScheduledInSeconds).Returns(15); A.CallTo(() => _tlsEntityConfig.MaxTlsRetryAttempts).Returns(5); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.MinValue); CertificateResults certificateResults = new CertificateResults(null, null); TlsResultsEvaluated message = new TlsResultsEvaluated(hostName, true, new TlsRecords( new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) , new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) , new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) , new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)), new TlsRecord(new TlsEvaluatedResult(Guid.NewGuid(), EvaluatorResult.PASS)) ), certificateResults); await _tlsEntity.Handle(message); A.CallTo(() => _changeNotifierComposite.Handle(stateFromDb, message, A <List <string> > ._)).MustNotHaveHappened(); A.CallTo(() => _dao.Save(stateFromDb)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <TlsRecordEvaluationsChanged> .That.Matches(a => a.Id == message.Id && a.TlsRecords == message.TlsRecords && a.CertificateResults == message.Certificates), snsTopicArn, null)).MustNotHaveHappened(); A.CallTo(() => _dispatcher.Dispatch(A <CreateScheduledReminder> .That.Matches(a => a.ResourceId == hostName && a.Service == "Tls" && a.ScheduledTime.Second == 15), snsTopicArn)).MustHaveHappenedOnceExactly(); }
public async Task MixedRuleFailuresErrorsAsExpected() { TlsResultsEvaluated evaluatorResults = A.Fake <TlsResultsEvaluated>(); var evaluationError1 = new RuleTypedTlsEvaluationResult(TlsTestType.Tls10Available, Guid.NewGuid(), EvaluatorResult.FAIL, "Rule 1 Failed"); A.CallTo(() => _rule1.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult> { evaluationError1 }); A.CallTo(() => _rule2.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult>()); EvaluationResult <TlsResultsEvaluated, RuleTypedTlsEvaluationResult> evaluationResult = await _evaluator.Evaluate(evaluatorResults); Assert.That(evaluationResult.Messages.Count, Is.EqualTo(1)); Assert.That(evaluationResult.Messages[0], Is.EqualTo(evaluationError1)); }
public async Task Handle(TlsResultsEvaluated message) { string messageId = message.Id.ToLower(); TlsEntityState state = await LoadState(messageId, nameof(message)); await _domainStatusPublisher.Publish(message); state.TlsState = TlsState.Evaluated; state.FailureCount = message.Failed ? state.FailureCount + 1 : 0; CreateScheduledReminder reminder; if (!message.Failed || message.Failed && state.FailureCount >= _tlsEntityConfig.MaxTlsRetryAttempts) { List <string> domains = await _dao.GetDomainsFromHost(messageId); _changeNotifiersComposite.Handle(state, message, domains); state.CertificateResults = message.Certificates; state.TlsRecords = message.TlsRecords; state.LastUpdated = message.Timestamp; await _dao.Save(state); _dispatcher.Dispatch(new TlsRecordEvaluationsChanged(messageId, state.TlsRecords, state.CertificateResults), _tlsEntityConfig.SnsTopicArn); reminder = new CreateScheduledReminder(Guid.NewGuid().ToString(), ServiceName, messageId, _clock.GetDateTimeUtc().AddSeconds(_tlsEntityConfig.NextScheduledInSeconds)); } else { await _dao.Save(state); reminder = new CreateScheduledReminder(Guid.NewGuid().ToString(), ServiceName, messageId, _clock.GetDateTimeUtc().AddSeconds(_tlsEntityConfig.FailureNextScheduledInSeconds)); } _dispatcher.Dispatch(reminder, _tlsEntityConfig.SnsTopicArn); }
public async Task StopRuleFailureHaltProcessing() { TlsResultsEvaluated evaluatorResults = A.Fake <TlsResultsEvaluated>(); var evaluationError1 = new RuleTypedTlsEvaluationResult(TlsTestType.Tls10Available, Guid.NewGuid(), EvaluatorResult.FAIL, "Rule 1 Failed"); var evaluationError2 = new RuleTypedTlsEvaluationResult(TlsTestType.Tls10Available, Guid.NewGuid(), EvaluatorResult.WARNING, "Rule 2 Failed"); A.CallTo(() => _rule1.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult> { evaluationError1 }); A.CallTo(() => _rule1.IsStopRule).Returns(true); A.CallTo(() => _rule2.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult> { evaluationError2 }); EvaluationResult <TlsResultsEvaluated, RuleTypedTlsEvaluationResult> evaluationResult = await _evaluator.Evaluate(evaluatorResults); Assert.That(evaluationResult.Messages.Count, Is.EqualTo(1)); Assert.That(evaluationResult.Messages[0], Is.EqualTo(evaluationError1)); }
public async Task FailureEvaluatorUsedWhenProvided() { TlsResultsEvaluated evaluatorResults = A.Fake <TlsResultsEvaluated>(); var evaluationError1 = new RuleTypedTlsEvaluationResult(TlsTestType.Tls10Available, Guid.NewGuid(), EvaluatorResult.PASS, "Rule 1 Failed"); var evaluationError2 = new RuleTypedTlsEvaluationResult(TlsTestType.Tls10Available, Guid.NewGuid(), EvaluatorResult.WARNING, "Rule 2 Failed"); A.CallTo(() => _rule1.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult> { evaluationError1 }); A.CallTo(() => _rule1.Category).Returns("Cat1"); A.CallTo(() => _rule1.IsStopRule).Returns(true); A.CallTo(() => _rule2.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult> { evaluationError2 }); A.CallTo(() => _rule2.Category).Returns("Cat1"); EvaluationResult <TlsResultsEvaluated, RuleTypedTlsEvaluationResult> evaluationResult = await _evaluator.Evaluate(evaluatorResults, _ => true); Assert.That(evaluationResult.Messages.Count, Is.EqualTo(1)); }
public async Task RulesInDifferentCategoriesStillProcessedOnOtherCategoryFailure() { TlsResultsEvaluated evaluatorResults = A.Fake <TlsResultsEvaluated>(); var evaluationError1 = new RuleTypedTlsEvaluationResult(TlsTestType.Tls10Available, Guid.NewGuid(), EvaluatorResult.FAIL, "Rule 1 Failed"); var evaluationError2 = new RuleTypedTlsEvaluationResult(TlsTestType.Tls10Available, Guid.NewGuid(), EvaluatorResult.WARNING, "Rule 2 Failed"); A.CallTo(() => _rule1.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult> { evaluationError1 }); A.CallTo(() => _rule1.Category).Returns("Cat1"); A.CallTo(() => _rule1.IsStopRule).Returns(true); A.CallTo(() => _rule2.Evaluate(evaluatorResults)).Returns(new List <RuleTypedTlsEvaluationResult> { evaluationError2 }); A.CallTo(() => _rule2.Category).Returns("Cat2"); EvaluationResult <TlsResultsEvaluated, RuleTypedTlsEvaluationResult> evaluationResult = await _evaluator.Evaluate(evaluatorResults); Assert.That(evaluationResult.Messages.Count, Is.EqualTo(2)); Assert.That(evaluationResult.Messages[0], Is.EqualTo(evaluationError1)); Assert.That(evaluationResult.Messages[1], Is.EqualTo(evaluationError2)); }
private TlsResultsEvaluated CreateTlsResultsEvaluatedWithResults(TlsRecords records = null) { TlsResultsEvaluated recordsEvaluated = new TlsResultsEvaluated("mailchecktest.host.gov.uk", false, records ?? CreateTlsRecords()); return(recordsEvaluated); }