public async Task <MxRecordTlsSecurityProfile> Test(MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile)
        {
            if (_config.CachingEnabled)
            {
                string cachedStringResult = await _cache.GetString($"{KeyPrefix}-{mxRecordTlsSecurityProfile.MxRecord.Hostname?.ToLower()}");

                if (cachedStringResult != null)
                {
                    _log.Debug($"Successfully retrieved TLSSecurityProfile from cache for host {mxRecordTlsSecurityProfile.MxRecord.Hostname}");
                    TlsTestResults cachedResults = JsonConvert.DeserializeObject <TlsTestResults>(cachedStringResult);
                    return(new MxRecordTlsSecurityProfile(mxRecordTlsSecurityProfile.MxRecord,
                                                          new TlsSecurityProfile(mxRecordTlsSecurityProfile.TlsSecurityProfile.Id, null, cachedResults)));
                }
            }

            MxRecordTlsSecurityProfile result = await _tlsSecurityTesterAdaptor.Test(mxRecordTlsSecurityProfile);

            _log.Debug($"Successfully retrieved TLSSecurityProfile from tls tester for host {mxRecordTlsSecurityProfile.MxRecord.Hostname}");

            if (_config.CachingEnabled && (result.TlsSecurityProfile.TlsResults.FailureCount == 0 || result.TlsSecurityProfile.TlsResults.FailureCount >= FailureCountBeforeCaching))
            {
                string resultToCache = JsonConvert.SerializeObject(result.TlsSecurityProfile.TlsResults);

                await _cache.SetString($"{KeyPrefix}-{mxRecordTlsSecurityProfile.MxRecord.Hostname}", resultToCache,
                                       TimeSpan.FromSeconds(_config.RefreshIntervalSeconds *RefreshIntervalSecondsMultiplier));

                _log.Debug($"Successfully set TLSSecurityProfile to cache for host {mxRecordTlsSecurityProfile.MxRecord.Hostname}");
            }

            return(result);
        }
Esempio n. 2
0
        public async Task DifferenceInRecordsOldAndNewRecordsReturnedIsReturned()
        {
            MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile1 = CreateTlsSecurityProfile();
            MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile2 =
                CreateTlsSecurityProfile(2, CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA);

            A.CallTo(() => _tlsSecurityTester.Test(mxRecordTlsSecurityProfile1))
            .Returns(Task.FromResult(mxRecordTlsSecurityProfile2));

            List <DomainTlsSecurityProfile> securityProfiles = await _tlsSecurityProfileUpdater.UpdateSecurityProfiles(
                new List <DomainTlsSecurityProfile>
            {
                new DomainTlsSecurityProfile(new Domain(1, "domain"),
                                             new List <MxRecordTlsSecurityProfile> {
                    mxRecordTlsSecurityProfile1
                })
            });

            Assert.That(securityProfiles[0].Profiles.Count, Is.EqualTo(2));
            Assert.That(securityProfiles[0].Profiles[0].TlsSecurityProfile.Id,
                        Is.EqualTo(mxRecordTlsSecurityProfile1.TlsSecurityProfile.Id));
            Assert.That(securityProfiles[0].Profiles[0].TlsSecurityProfile.EndDate, Is.Not.Null);
            Assert.That(securityProfiles[0].Profiles[1].TlsSecurityProfile.Id, Is.Null);
            Assert.That(securityProfiles[0].Profiles[1].TlsSecurityProfile.EndDate, Is.Null);
        }
Esempio n. 3
0
 private MxRecordTlsSecurityProfile CreateNewRecord(MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile)
 {
     return(new MxRecordTlsSecurityProfile(
                mxRecordTlsSecurityProfile.MxRecord,
                new TlsSecurityProfile(
                    null,
                    null, mxRecordTlsSecurityProfile.TlsSecurityProfile.TlsResults.Clone())));
 }
Esempio n. 4
0
 private MxRecordTlsSecurityProfile CreateExpiredRecord(MxRecordTlsSecurityProfile oldMxRecordTlsSecurityProfile)
 {
     return(new MxRecordTlsSecurityProfile(
                oldMxRecordTlsSecurityProfile.MxRecord,
                new TlsSecurityProfile(
                    oldMxRecordTlsSecurityProfile.TlsSecurityProfile.Id,
                    DateTime.UtcNow,
                    oldMxRecordTlsSecurityProfile.TlsSecurityProfile.TlsResults.Clone())));
 }
Esempio n. 5
0
        public async Task <List <DomainTlsSecurityProfile> > GetSecurityProfilesForUpdate()
        {
            Stopwatch stopwatch = Stopwatch.StartNew();

            Dictionary <Domain, Dictionary <MxRecord, MxRecordTlsSecurityProfile> > values
                = new Dictionary <Domain, Dictionary <MxRecord, MxRecordTlsSecurityProfile> >();

            string connectionString = await _connectionInfo.GetConnectionStringAsync();

            using (MySqlConnection connection = new MySqlConnection(connectionString))
            {
                await connection.OpenAsync().ConfigureAwait(false);

                MySqlCommand command = new MySqlCommand(TlsSecurityProfileDaoResources.SelectSecurityProfilesToUpdate, connection);

                command.Parameters.AddWithValue("refreshIntervalSeconds", _mxSecurityTesterConfig.RefreshIntervalSeconds);
                command.Parameters.AddWithValue("failureRefreshIntervalSeconds", _mxSecurityTesterConfig.FailureRefreshIntervalSeconds);
                command.Parameters.AddWithValue("limit", _mxSecurityTesterConfig.DomainLimit);

                using (DbDataReader reader = await command.ExecuteReaderAsync())
                {
                    while (await reader.ReadAsync())
                    {
                        Domain domain = CreateDomain(reader);
                        Dictionary <MxRecord, MxRecordTlsSecurityProfile> domainValue;
                        if (!values.TryGetValue(domain, out domainValue))
                        {
                            domainValue = new Dictionary <MxRecord, MxRecordTlsSecurityProfile>();
                            values.Add(domain, domainValue);
                        }

                        MxRecord record = CreateMxRecord(reader);
                        MxRecordTlsSecurityProfile profile;
                        if (!domainValue.TryGetValue(record, out profile))
                        {
                            profile = new MxRecordTlsSecurityProfile(record, CreateTlsSecurityProfile(reader));
                            domainValue.Add(record, profile);
                        }

                        X509Certificate2 certificate = CreateCertificate(reader);
                        if (certificate != null)
                        {
                            profile.TlsSecurityProfile.TlsResults.Certificates.Add(certificate);
                        }
                    }
                }
                connection.Close();
            }
            stopwatch.Stop();
            _log.Debug($"Retrieving domains to refresh security profiles for took {stopwatch.Elapsed}");
            return(values.Select(_ => new DomainTlsSecurityProfile(_.Key, _.Value.Values.ToList())).ToList());
        }
        public async Task CachingNotEnabledCacheNotUsed()
        {
            A.CallTo(() => _config.CachingEnabled).Returns(false);

            MxRecordTlsSecurityProfile securityProfile = CreateSecurityProfile();

            MxRecordTlsSecurityProfile updatedSecurityProfile =
                await _cachingTlsSecurityTesterAdaptor.Test(securityProfile);

            A.CallTo(() => _cache.GetString(A <string> ._)).MustNotHaveHappened();
            A.CallTo(() => _tlsSecurityTesterAdaptor.Test(securityProfile)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => _cache.SetString(A <string> ._, A <string> ._, A <TimeSpan> ._)).MustNotHaveHappened();
        }
        public async Task ErroredResultsNotCachedBeforeThirdFailedRetry()
        {
            MxRecordTlsSecurityProfile securityProfile = CreateSecurityProfile(1);

            A.CallTo(() => _config.CachingEnabled).Returns(true);
            A.CallTo(() => _cache.GetString(A <string> ._)).Returns(Task.FromResult((string)null));
            A.CallTo(() => _tlsSecurityTesterAdaptor.Test(securityProfile)).Returns(Task.FromResult(securityProfile));

            MxRecordTlsSecurityProfile updatedSecurityProfile =
                await _cachingTlsSecurityTesterAdaptor.Test(securityProfile);

            A.CallTo(() => _cache.GetString(A <string> ._)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => _tlsSecurityTesterAdaptor.Test(securityProfile)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => _cache.SetString(A <string> ._, A <string> ._, A <TimeSpan> ._)).MustNotHaveHappened();
        }
Esempio n. 8
0
        public async Task <MxRecordTlsSecurityProfile> Test(MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile)
        {
            List <Console.TlsTestResult> results      = new List <Console.TlsTestResult>();
            List <X509Certificate2>      certificates = null;

            if (!string.IsNullOrWhiteSpace(mxRecordTlsSecurityProfile.MxRecord.Hostname))
            {
                results = await _tlsSecurityTester.Test(mxRecordTlsSecurityProfile.MxRecord.Hostname);

                certificates = results.FirstOrDefault(_ => _.Result.Certificates.Any())?
                               .Result.Certificates.ToList() ?? new List <X509Certificate2>();
            }

            return(new MxRecordTlsSecurityProfile(mxRecordTlsSecurityProfile.MxRecord,
                                                  new TlsSecurityProfile(
                                                      mxRecordTlsSecurityProfile.TlsSecurityProfile.Id,
                                                      null,
                                                      new TlsTestResults(
                                                          IsErrored(results)
                            ? mxRecordTlsSecurityProfile.TlsSecurityProfile.TlsResults.FailureCount + 1
                            : 0, new TlsTestResultsWithoutCertificate(
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Tls12AvailableWithBestCipherSuiteSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id ==
                                                                                                  (int)TlsTestType.Tls12AvailableWithBestCipherSuiteSelectedFromReverseList)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Tls12AvailableWithSha2HashFunctionSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Tls12AvailableWithWeakCipherSuiteNotSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Tls11AvailableWithBestCipherSuiteSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Tls11AvailableWithWeakCipherSuiteNotSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Tls10AvailableWithBestCipherSuiteSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Tls10AvailableWithWeakCipherSuiteNotSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.Ssl3FailsWithBadCipherSuite)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.TlsSecureEllipticCurveSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.TlsSecureDiffieHellmanGroupSelected)),
                                                              ToTestResult(results.FirstOrDefault(_ =>
                                                                                                  _.Test.Id == (int)TlsTestType.TlsWeakCipherSuitesRejected))),
                                                          certificates))));
        }
        public async Task CachingEnabledValueNotInCacheValueReturnedFromTlsTesterAndCached()
        {
            MxRecordTlsSecurityProfile securityProfile = CreateSecurityProfile();

            A.CallTo(() => _config.CachingEnabled).Returns(true);
            A.CallTo(() => _cache.GetString(A <string> ._)).Returns(Task.FromResult((string)null));
            A.CallTo(() => _tlsSecurityTesterAdaptor.Test(securityProfile)).Returns(Task.FromResult(securityProfile));

            MxRecordTlsSecurityProfile updatedSecurityProfile =
                await _cachingTlsSecurityTesterAdaptor.Test(securityProfile);

            A.CallTo(() => _cache.GetString(A <string> ._)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => _tlsSecurityTesterAdaptor.Test(securityProfile)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => _cache.SetString(A <string> ._, A <string> ._, A <TimeSpan> ._))
            .MustHaveHappened(Repeated.Exactly.Once);
        }
        public async Task CachingEnabledAndValueInCacheValueFromCacheReturned()
        {
            MxRecordTlsSecurityProfile securityProfile = CreateSecurityProfile();
            string serializedSecurityProfile           =
                JsonConvert.SerializeObject(securityProfile.TlsSecurityProfile.TlsResults);

            A.CallTo(() => _config.CachingEnabled).Returns(true);
            A.CallTo(() => _cache.GetString(A <string> ._)).Returns(Task.FromResult(serializedSecurityProfile));

            MxRecordTlsSecurityProfile updatedSecurityProfile =
                await _cachingTlsSecurityTesterAdaptor.Test(securityProfile);

            Assert.That(updatedSecurityProfile.TlsSecurityProfile, Is.EqualTo(securityProfile.TlsSecurityProfile));

            A.CallTo(() => _cache.GetString(A <string> ._)).MustHaveHappened(Repeated.Exactly.Once);
            A.CallTo(() => _tlsSecurityTesterAdaptor.Test(securityProfile)).MustNotHaveHappened();
            A.CallTo(() => _cache.SetString(A <string> ._, A <string> ._, A <TimeSpan> ._)).MustNotHaveHappened();
        }
Esempio n. 11
0
        private async Task <List <MxRecordTlsSecurityProfile> > UpdateMxSecurityProfile(MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile)
        {
            MxRecordTlsSecurityProfile updatedSecurityProfile = await _tlsSecurityTester.Test(mxRecordTlsSecurityProfile);

            bool recordUnchanged = mxRecordTlsSecurityProfile.TlsSecurityProfile.TlsResults.Equals(updatedSecurityProfile.TlsSecurityProfile.TlsResults);
            bool newRecord       = !mxRecordTlsSecurityProfile.TlsSecurityProfile.Id.HasValue;

            _log.Debug($"Updated tls profile (mx record id:{mxRecordTlsSecurityProfile.MxRecord.Id}, " +
                       $"tls profile id:{mxRecordTlsSecurityProfile.TlsSecurityProfile.Id?.ToString() ?? "null"}) " +
                       $"record changed: {!recordUnchanged}, new record: {newRecord}");

            return(recordUnchanged || newRecord
                ? new List <MxRecordTlsSecurityProfile> {
                updatedSecurityProfile
            }
                : new List <MxRecordTlsSecurityProfile> {
                CreateExpiredRecord(mxRecordTlsSecurityProfile), CreateNewRecord(updatedSecurityProfile)
            });
        }
Esempio n. 12
0
        public async Task NoDifferenceInRecordsRecordIsReturned()
        {
            MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile1 = CreateTlsSecurityProfile();

            A.CallTo(() => _tlsSecurityTester.Test(mxRecordTlsSecurityProfile1))
            .Returns(Task.FromResult(mxRecordTlsSecurityProfile1));

            List <DomainTlsSecurityProfile> securityProfiles = await _tlsSecurityProfileUpdater.UpdateSecurityProfiles(
                new List <DomainTlsSecurityProfile>
            {
                new DomainTlsSecurityProfile(new Domain(1, "domain"),
                                             new List <MxRecordTlsSecurityProfile> {
                    mxRecordTlsSecurityProfile1
                })
            });

            Assert.That(securityProfiles[0].Profiles.Count, Is.EqualTo(1));
            Assert.That(securityProfiles[0].Profiles.First(), Is.EqualTo(mxRecordTlsSecurityProfile1));
        }
Esempio n. 13
0
        private async Task InsertOrUpdateSecurityProfiles(List <MxRecordTlsSecurityProfile> profiles, MySqlTransaction transaction)
        {
            if (profiles.Any())
            {
                StringBuilder stringBuilder = new StringBuilder(TlsSecurityProfileDaoResources.InsertRecord);
                MySqlCommand  command       = new MySqlCommand((MySqlConnection)transaction.Connection, transaction);

                for (int i = 0; i < profiles.Count; i++)
                {
                    stringBuilder.AppendFormat(TlsSecurityProfileDaoResources.InsertRecordValueFormatString, i);
                    stringBuilder.Append(i < profiles.Count - 1 ? "," : " ");

                    MxRecordTlsSecurityProfile profile = profiles[i];

                    command.Parameters.AddWithValue($"a{i}", profile.TlsSecurityProfile.Id);
                    command.Parameters.AddWithValue($"b{i}", profile.MxRecord.Id);
                    command.Parameters.AddWithValue($"c{i}", profile.TlsSecurityProfile.EndDate);
                    command.Parameters.AddWithValue($"d{i}", profile.TlsSecurityProfile.TlsResults.FailureCount);
                    command.Parameters.AddWithValue($"e{i}", JsonConvert.SerializeObject(profile.TlsSecurityProfile.TlsResults.Results, _serializerSettings));
                }

                stringBuilder.Append(TlsSecurityProfileDaoResources.InsertRecordOnDuplicateKey);

                command.CommandText = stringBuilder.ToString();

                ulong id = (ulong)await command.ExecuteScalarAsync();

                foreach (MxRecordTlsSecurityProfile profile in profiles)
                {
                    if (!profile.TlsSecurityProfile.Id.HasValue)
                    {
                        profile.TlsSecurityProfile.Id = id++;
                    }
                }
            }
        }
Esempio n. 14
0
 protected bool Equals(MxRecordTlsSecurityProfile other)
 {
     return(Equals(MxRecord, other.MxRecord) &&
            Equals(TlsSecurityProfile, other.TlsSecurityProfile));
 }
Esempio n. 15
0
        public async Task EmptyRecordsAreNotReturned()
        {
            MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile1 = CreateTlsSecurityProfile(null);
            MxRecordTlsSecurityProfile mxRecordTlsSecurityProfile2 =
                CreateTlsSecurityProfile(null, CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA);

            A.CallTo(() => _tlsSecurityTester.Test(mxRecordTlsSecurityProfile1))
            .Returns(Task.FromResult(mxRecordTlsSecurityProfile2));

            List <DomainTlsSecurityProfile> securityProfiles = await _tlsSecurityProfileUpdater.UpdateSecurityProfiles(
                new List <DomainTlsSecurityProfile>
            {
                new DomainTlsSecurityProfile(new Domain(1, "domain"),
                                             new List <MxRecordTlsSecurityProfile> {
                    mxRecordTlsSecurityProfile1
                })
            });

            Assert.That(securityProfiles[0].Profiles.Count, Is.EqualTo(1));
            Assert.That(securityProfiles[0].Profiles[0].TlsSecurityProfile.Id, Is.Null);
            Assert.That(securityProfiles[0].Profiles[0].MxRecord, Is.EqualTo(mxRecordTlsSecurityProfile1.MxRecord));
            Assert.That(securityProfiles[0].Profiles[0].TlsSecurityProfile.EndDate, Is.Null);
            Assert.That(securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.FailureCount,
                        Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.FailureCount));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls12AvailableWithBestCipherSuiteSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls12AvailableWithBestCipherSuiteSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls12AvailableWithBestCipherSuiteSelectedFromReverseList,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls12AvailableWithBestCipherSuiteSelectedFromReverseList));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls12AvailableWithSha2HashFunctionSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls12AvailableWithSha2HashFunctionSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls12AvailableWithWeakCipherSuiteNotSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls12AvailableWithWeakCipherSuiteNotSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls11AvailableWithBestCipherSuiteSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls11AvailableWithBestCipherSuiteSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls11AvailableWithWeakCipherSuiteNotSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls11AvailableWithWeakCipherSuiteNotSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls10AvailableWithBestCipherSuiteSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls10AvailableWithBestCipherSuiteSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .Tls10AvailableWithWeakCipherSuiteNotSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .Tls10AvailableWithWeakCipherSuiteNotSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results.Ssl3FailsWithBadCipherSuite,
                Is.EqualTo(
                    mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results.Ssl3FailsWithBadCipherSuite));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results.TlsSecureEllipticCurveSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .TlsSecureEllipticCurveSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results
                .TlsSecureDiffieHellmanGroupSelected,
                Is.EqualTo(mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results
                           .TlsSecureDiffieHellmanGroupSelected));
            Assert.That(
                securityProfiles[0].Profiles[0].TlsSecurityProfile.TlsResults.Results.TlsWeakCipherSuitesRejected,
                Is.EqualTo(
                    mxRecordTlsSecurityProfile2.TlsSecurityProfile.TlsResults.Results.TlsWeakCipherSuitesRejected));
        }