protected ANALYSIS_RESULT_TYPE Apply(Rule rule, CompareResult compareResult)
        {
            if (compareResult != null && rule != null)
            {
                var properties = _Properties[compareResult.ResultType];

                foreach (Clause clause in rule.Clauses)
                {
                    PropertyInfo property = properties.FirstOrDefault(iProp => iProp.Name.Equals(clause.Field));
                    if (property == null)
                    {
                        //Custom field logic will go here
                        return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);
                    }

                    try
                    {
                        var valsToCheck = new List <string>();
                        List <KeyValuePair <string, string> > dictToCheck = new List <KeyValuePair <string, string> >();

                        if (property != null)
                        {
                            if (compareResult.ChangeType == CHANGE_TYPE.CREATED || compareResult.ChangeType == CHANGE_TYPE.MODIFIED)
                            {
                                try
                                {
                                    if (GetValueByPropertyName(compareResult.Compare, property.Name) is List <string> )
                                    {
                                        foreach (var value in (List <string>)GetValueByPropertyName(compareResult.Compare, property.Name))
                                        {
                                            valsToCheck.Add(value);
                                        }
                                    }
                                    else if (GetValueByPropertyName(compareResult.Compare, property.Name) is Dictionary <string, string> )
                                    {
                                        dictToCheck = ((Dictionary <string, string>)GetValueByPropertyName(compareResult.Compare, property.Name)).ToList();
                                    }
                                    else if (GetValueByPropertyName(compareResult.Compare, property.Name) is List <KeyValuePair <string, string> > )
                                    {
                                        dictToCheck = (List <KeyValuePair <string, string> >)GetValueByPropertyName(compareResult.Compare, property.Name);
                                    }
                                    else
                                    {
                                        valsToCheck.Add(GetValueByPropertyName(compareResult.Compare, property.Name).ToString());
                                    }
                                }
                                catch (Exception e)
                                {
                                    Log.Debug(e, "Error fetching Property {0} of Type {1}", property.Name, compareResult.ResultType);

                                    Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>();
                                    ExceptionEvent.Add("Exception Type", e.GetType().ToString());
                                    AsaTelemetry.TrackEvent("ApplyCreatedModifiedException", ExceptionEvent);
                                }
                            }
                            if (compareResult.ChangeType == CHANGE_TYPE.DELETED || compareResult.ChangeType == CHANGE_TYPE.MODIFIED)
                            {
                                try
                                {
                                    if (GetValueByPropertyName(compareResult.Base, property.Name) is List <string> )
                                    {
                                        foreach (var value in (List <string>)GetValueByPropertyName(compareResult.Base, property.Name))
                                        {
                                            valsToCheck.Add(value);
                                        }
                                    }
                                    else if (GetValueByPropertyName(compareResult.Base, property.Name) is Dictionary <string, string> )
                                    {
                                        dictToCheck = ((Dictionary <string, string>)GetValueByPropertyName(compareResult.Base, property.Name)).ToList();
                                    }
                                    else if (GetValueByPropertyName(compareResult.Base, property.Name) is List <KeyValuePair <string, string> > )
                                    {
                                        dictToCheck = (List <KeyValuePair <string, string> >)GetValueByPropertyName(compareResult.Base, property.Name);
                                    }
                                    else
                                    {
                                        valsToCheck.Add(GetValueByPropertyName(compareResult.Base, property.Name).ToString());
                                    }
                                }
                                catch (Exception e)
                                {
                                    Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>();
                                    ExceptionEvent.Add("Exception Type", e.GetType().ToString());
                                    AsaTelemetry.TrackEvent("ApplyDeletedModifiedException", ExceptionEvent);
                                }
                            }
                        }

                        int count = 0, dictCount = 0;

                        switch (clause.Operation)
                        {
                        case OPERATION.EQ:
                            foreach (string datum in clause.Data)
                            {
                                foreach (string val in valsToCheck)
                                {
                                    count += (datum.Equals(val)) ? 1 : 0;
                                    break;
                                }
                            }
                            if (count == clause.Data.Count)
                            {
                                break;
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        case OPERATION.NEQ:
                            foreach (string datum in clause.Data)
                            {
                                foreach (string val in valsToCheck)
                                {
                                    if (datum.Equals(val))
                                    {
                                        return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);
                                    }
                                }
                            }
                            break;

                        case OPERATION.CONTAINS:
                            if (dictToCheck.Count > 0)
                            {
                                foreach (KeyValuePair <string, string> value in clause.DictData)
                                {
                                    if (dictToCheck.Where((x) => x.Key == value.Key && x.Value == value.Value).Any())
                                    {
                                        dictCount++;
                                    }
                                }
                                if (dictCount == clause.DictData.Count)
                                {
                                    break;
                                }
                            }
                            else if (valsToCheck.Count > 0)
                            {
                                foreach (string datum in clause.Data)
                                {
                                    foreach (string val in valsToCheck)
                                    {
                                        count += (!val.Contains(datum)) ? 1 : 0;
                                        break;
                                    }
                                }
                                if (count == clause.Data.Count)
                                {
                                    break;
                                }
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        case OPERATION.DOES_NOT_CONTAIN:
                            if (dictToCheck.Count > 0)
                            {
                                foreach (KeyValuePair <string, string> value in clause.DictData)
                                {
                                    if (dictToCheck.Where((x) => x.Key == value.Key && x.Value == value.Value).Any())
                                    {
                                        return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);
                                    }
                                }
                            }
                            else if (valsToCheck.Count > 0)
                            {
                                foreach (string datum in clause.Data)
                                {
                                    if (valsToCheck.Contains(datum))
                                    {
                                        return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);
                                    }
                                }
                            }
                            break;

                        case OPERATION.GT:
                            foreach (string val in valsToCheck)
                            {
                                count += (int.Parse(val, CultureInfo.InvariantCulture) > int.Parse(clause.Data[0], CultureInfo.InvariantCulture)) ? 1 : 0;
                            }
                            if (count == valsToCheck.Count)
                            {
                                break;
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        case OPERATION.LT:
                            foreach (string val in valsToCheck)
                            {
                                count += (int.Parse(val, CultureInfo.InvariantCulture) < int.Parse(clause.Data[0], CultureInfo.InvariantCulture)) ? 1 : 0;
                            }
                            if (count == valsToCheck.Count)
                            {
                                break;
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        case OPERATION.REGEX:
                            foreach (string val in valsToCheck)
                            {
                                foreach (string datum in clause.Data)
                                {
                                    var r = new Regex(datum);
                                    if (r.IsMatch(val))
                                    {
                                        count++;
                                    }
                                }
                            }
                            if (count == valsToCheck.Count)
                            {
                                break;
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        case OPERATION.WAS_MODIFIED:
                            if ((valsToCheck.Count == 2) && (valsToCheck[0] == valsToCheck[1]))
                            {
                                break;
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        case OPERATION.ENDS_WITH:
                            foreach (string datum in clause.Data)
                            {
                                foreach (var val in valsToCheck)
                                {
                                    if (val.EndsWith(datum, StringComparison.CurrentCulture))
                                    {
                                        count++;
                                        break;
                                    }
                                }
                            }
                            if (count == clause.Data.Count)
                            {
                                break;
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        case OPERATION.STARTS_WITH:
                            foreach (string datum in clause.Data)
                            {
                                foreach (var val in valsToCheck)
                                {
                                    if (val.StartsWith(datum, StringComparison.CurrentCulture))
                                    {
                                        count++;
                                        break;
                                    }
                                }
                            }
                            if (count == clause.Data.Count)
                            {
                                break;
                            }
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);

                        default:
                            Log.Debug("Unimplemented operation {0}", clause.Operation);
                            return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Debug(e, $"Hit while parsing {JsonConvert.SerializeObject(rule)} onto {JsonConvert.SerializeObject(compareResult)}");
                        Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>();
                        ExceptionEvent.Add("Exception Type", e.GetType().ToString());
                        AsaTelemetry.TrackEvent("ApplyOverallException", ExceptionEvent);
                        return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]);
                    }
                }
                compareResult.Rules.Add(rule);
                return(rule.Flag);
            }
            else
            {
                throw new NullReferenceException();
            }
        }
        public static bool Setup(string filename, DBSettings?dbSettingsIn = null)
        {
            dbSettings = (dbSettingsIn == null) ? new DBSettings() : dbSettingsIn;

            if (filename != null)
            {
                if (SQLiteFilename != filename)
                {
                    SQLiteFilename = filename;
                }
            }

            if (Connections.Count > 0)
            {
                CloseDatabase();
            }

            if (Connections == null || Connections.Count == 0)
            {
                Connections = new List <SystemSQLiteSqlConnectionHolder>();

                PopulateConnections();

                var settings = GetSettings();
                if (settings != null)
                {
                    FirstRun = false;

                    if (SCHEMA_VERSION != settings.SchemaVersion)
                    {
                        Log.Fatal("Database has schema version {settings.SchemaVersion} but database has schema version {SCHEMA_VERSION}.");
                        Environment.Exit((int)ASA_ERROR.MATCHING_SCHEMA);
                    }

                    if (dbSettingsIn != null && settings.ShardingFactor != dbSettingsIn.ShardingFactor)
                    {
                        Log.Information($"Requested sharding level of {dbSettingsIn.ShardingFactor} but database was created with {settings.ShardingFactor}. Ignoring request and using {settings.ShardingFactor}.");
                    }

                    dbSettings.ShardingFactor = settings.ShardingFactor;

                    AsaTelemetry.SetEnabled(settings.TelemetryEnabled);
                }
                else
                {
                    FirstRun = true;
                }

                PopulateConnections();

                if (MainConnection == null)
                {
                    Log.Warning("Failed to set up Main Database connection. Cannot set up database.");
                    return(false);
                }

                if (FirstRun)
                {
                    try
                    {
                        BeginTransaction();

                        using var cmd2 = new SQLiteCommand(SQL_CREATE_RUNS, MainConnection.Connection, MainConnection.Transaction);
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_RESULTS;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_RESULTS;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_LEVEL_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_RESULT_TYPE_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_IDENTITY_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_LEVEL_RESULT_TYPE_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FILE_MONITORED;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_PERSISTED_SETTINGS;
                        cmd2.ExecuteNonQuery();

                        SetSettings(new Settings()
                        {
                            SchemaVersion    = SCHEMA_VERSION,
                            ShardingFactor   = dbSettings.ShardingFactor,
                            TelemetryEnabled = true
                        });

                        Connections.AsParallel().ForAll(cxn =>
                        {
                            using (var innerCmd = new SQLiteCommand(SQL_CREATE_COLLECT_RESULTS, cxn.Connection, cxn.Transaction))
                            {
                                innerCmd.ExecuteNonQuery();

                                innerCmd.CommandText = SQL_CREATE_COLLECT_RUN_ID_INDEX;
                                innerCmd.ExecuteNonQuery();

                                innerCmd.CommandText = SQL_CREATE_COLLECT_RUN_KEY_IDENTITY_COMBINED_INDEX;
                                innerCmd.ExecuteNonQuery();

                                innerCmd.CommandText = SQL_CREATE_COLLECT_RUN_ID_IDENTITY_INDEX;
                                innerCmd.ExecuteNonQuery();
                            }
                        });
                    }
                    catch (SQLiteException e)
                    {
                        Log.Debug(e, "Failed to set up fresh database.");
                        Environment.Exit((int)ASA_ERROR.FAILED_TO_CREATE_DATABASE);
                    }
                    finally
                    {
                        Commit();
                    }
                }

                return(true);
            }
            return(false);
        }
        public static ASA_ERROR Setup(string filename, DBSettings?dbSettingsIn = null)
        {
            dbSettings = (dbSettingsIn == null) ? new DBSettings() : dbSettingsIn;

            if (filename != null)
            {
                if (SqliteFilename != filename)
                {
                    SqliteFilename = filename;
                }
            }

            if (Connections.Count > 0)
            {
                CloseDatabase();
            }

            if (Connections == null || Connections.Count == 0)
            {
                Connections = new List <SqlConnectionHolder>();

                if (!EstablishMainConnection())
                {
                    Log.Fatal(Strings.Get("FailedToEstablishMainConnection"), SqliteFilename);
                    return(ASA_ERROR.FAILED_TO_ESTABLISH_MAIN_DB_CONNECTION);
                }

                var settingsFromDb = GetSettings();
                if (settingsFromDb != null)
                {
                    dbSettings.ShardingFactor = settingsFromDb.ShardingFactor;

                    FirstRun = false;

                    if (SCHEMA_VERSION != settingsFromDb.SchemaVersion)
                    {
                        Log.Fatal(Strings.Get("WrongSchema"), settingsFromDb.SchemaVersion, SCHEMA_VERSION);
                        return(ASA_ERROR.MATCHING_SCHEMA);
                    }

                    if (dbSettingsIn != null && settingsFromDb.ShardingFactor != dbSettingsIn.ShardingFactor)
                    {
                        Log.Information(Strings.Get("InvalidShardingRequest"), dbSettingsIn.ShardingFactor, dbSettings.ShardingFactor);
                    }

                    AsaTelemetry.SetEnabled(settingsFromDb.TelemetryEnabled);
                }
                else
                {
                    FirstRun = true;
                }

                PopulateConnections();

                if (MainConnection == null)
                {
                    Log.Fatal(Strings.Get("FailedToEstablishMainConnection"), SqliteFilename);
                    return(ASA_ERROR.FAILED_TO_ESTABLISH_MAIN_DB_CONNECTION);
                }

                if (FirstRun)
                {
                    try
                    {
                        BeginTransaction();

                        using var cmd2 = new SqliteCommand(SQL_CREATE_RUNS, MainConnection.Connection, MainConnection.Transaction);
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_RESULTS;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_RESULTS;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_LEVEL_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_RESULT_TYPE_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_IDENTITY_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FINDINGS_LEVEL_RESULT_TYPE_INDEX;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_FILE_MONITORED;
                        cmd2.ExecuteNonQuery();

                        cmd2.CommandText = SQL_CREATE_PERSISTED_SETTINGS;
                        cmd2.ExecuteNonQuery();

                        SetSettings(new Settings()
                        {
                            SchemaVersion    = SCHEMA_VERSION,
                            ShardingFactor   = dbSettings.ShardingFactor,
                            TelemetryEnabled = true
                        });

                        Connections.AsParallel().ForAll(cxn =>
                        {
                            using (var innerCmd = new SqliteCommand(SQL_CREATE_COLLECT_RESULTS, cxn.Connection, cxn.Transaction))
                            {
                                innerCmd.ExecuteNonQuery();

                                innerCmd.CommandText = SQL_CREATE_COLLECT_RUN_ID_INDEX;
                                innerCmd.ExecuteNonQuery();

                                innerCmd.CommandText = SQL_CREATE_COLLECT_RUN_KEY_IDENTITY_COMBINED_INDEX;
                                innerCmd.ExecuteNonQuery();

                                innerCmd.CommandText = SQL_CREATE_COLLECT_RUN_ID_IDENTITY_INDEX;
                                innerCmd.ExecuteNonQuery();
                            }
                        });
                    }
                    catch (SqliteException e)
                    {
                        Log.Debug(e, "Failed to set up fresh database.");
                        return(ASA_ERROR.FAILED_TO_CREATE_DATABASE);
                    }
                    finally
                    {
                        Commit();
                    }
                }
            }
            return(ASA_ERROR.NONE);
        }
        public static IEnumerable <RegistryObject> WalkHive(RegistryHive Hive, string startingKey = null)
        {
            Stack <RegistryKey> keys = new Stack <RegistryKey>();

            RegistryKey x86_View = null, x64_View = null;

            try
            {
                x86_View = RegistryKey.OpenBaseKey(Hive, RegistryView.Registry32);
            }
            catch (Exception e) when(
                e is IOException ||
                e is ArgumentException ||
                e is UnauthorizedAccessException ||
                e is System.Security.SecurityException)
            {
            }
            try
            {
                x64_View = RegistryKey.OpenBaseKey(Hive, RegistryView.Registry32);
            }
            catch (Exception e) when(
                e is IOException ||
                e is ArgumentException ||
                e is UnauthorizedAccessException ||
                e is System.Security.SecurityException)
            {
            }

            if (x86_View != null)
            {
                if (startingKey != null)
                {
                    x86_View = x86_View.OpenSubKey(startingKey);
                }
                keys.Push(x86_View);
            }

            if (x64_View != null)
            {
                if (startingKey != null)
                {
                    x64_View = x64_View.OpenSubKey(startingKey);
                }
                keys.Push(x64_View);
            }

            while (keys.Count > 0)
            {
                RegistryKey currentKey = keys.Pop();

                if (currentKey == null)
                {
                    continue;
                }
                if (Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Key", currentKey.Name))
                {
                    continue;
                }

                // First push all the new subkeys onto our stack.
                foreach (string key in currentKey.GetSubKeyNames())
                {
                    try
                    {
                        var next = currentKey.OpenSubKey(name: key, writable: false);
                        keys.Push(next);
                    }
                    // These are expected as we are running as administrator, not System.
                    catch (System.Security.SecurityException e)
                    {
                        Log.Verbose(e, "Permission Denied: {0}", currentKey.Name);
                    }
                    // There seem to be some keys which are listed as existing by the APIs but don't actually exist.
                    // Unclear if these are just super transient keys or what the other cause might be.
                    // Since this isn't user actionable, also just supress these to the verbose stream.
                    catch (System.IO.IOException e)
                    {
                        Log.Verbose(e, "Error Reading: {0}", currentKey.Name);
                    }
                    catch (Exception e)
                    {
                        Log.Information(e, "Unexpected error when parsing {0}:", currentKey.Name);
                        AsaTelemetry.TrackTrace(Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Error, e);
                    }
                }

                var regObj = RegistryKeyToRegistryObject(currentKey);

                if (regObj != null)
                {
                    yield return(regObj);
                }
            }

            x86_View.Dispose();
            x64_View.Dispose();
        }
示例#5
0
        public static string VerifyEmbeddedSignature(string filename)
        {
            try
            {
                WinTrustFileInfo winTrustFileInfo = null;
                WinTrustData     winTrustData     = null;

                // specify the WinVerifyTrust function/action that we want
                Guid action = new Guid(WINTRUST_ACTION_GENERIC_VERIFY_V2);

                // instantiate our WinTrustFileInfo and WinTrustData data structures
                winTrustFileInfo = new WinTrustFileInfo(filename);
                winTrustData     = new WinTrustData(filename);

                WinVerifyTrustResult result = WinVerifyTrust(INVALID_HANDLE_VALUE, action, winTrustData);
                // call into WinVerifyTrust
                switch (result)
                {
                case WinVerifyTrustResult.Success:
                    return("Valid");

                case WinVerifyTrustResult.ProviderUnknown:
                    return("ProviderUnknown");

                case WinVerifyTrustResult.ActionUnknown:
                    return("ActionUnknown");

                case WinVerifyTrustResult.SubjectFormUnknown:
                    return("SubjectFormUnknown");

                case WinVerifyTrustResult.SubjectNotTrusted:
                    return("SubjectNotTrusted");

                case WinVerifyTrustResult.FileNotSigned:
                    return("FileNotSigned");

                case WinVerifyTrustResult.SubjectExplicitlyDistrusted:
                    return("SubjectExplicitlyDistrusted");

                case WinVerifyTrustResult.SignatureOrFileCorrupt:
                    return("SignatureOrFileCorrupt");

                case WinVerifyTrustResult.SubjectCertExpired:
                    return("SubjectCertExpired");

                case WinVerifyTrustResult.SubjectCertificateRevoked:
                    return("SubjectCertificateRevoked");

                case WinVerifyTrustResult.UntrustedRoot:
                    return("UntrustedRoot");

                default:
                    // The UI was disabled in dwUIChoice or the admin policy
                    // has disabled user trust. lStatus contains the
                    // publisher or time stamp chain error.
                    return(result.ToString());
                }
            }
            catch (Exception e) when(
                e is System.AccessViolationException ||
                e is Exception)
            {
                Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>();

                ExceptionEvent.Add("Exception Type", e.GetType().ToString());
                AsaTelemetry.TrackEvent("VerifyEmbeddedSignatureException", ExceptionEvent);
                return("FailedToFetch");
            }
        }
        public static IEnumerable <RegistryKey> WalkHive(RegistryHive Hive, RegistryView View, string startingKey = "")
        {
            Stack <RegistryKey> keys = new Stack <RegistryKey>();

            RegistryKey?BaseKey = null;

            try
            {
                BaseKey = RegistryKey.OpenBaseKey(Hive, View);
            }
            catch (Exception e) when(
                e is IOException ||
                e is ArgumentException ||
                e is UnauthorizedAccessException ||
                e is System.Security.SecurityException)
            {
            }

            if (BaseKey != null)
            {
                if (startingKey != null)
                {
                    BaseKey = BaseKey.OpenSubKey(startingKey, writable: false);
                }
                keys.Push(BaseKey);
            }

            while (keys.Count > 0)
            {
                RegistryKey currentKey = keys.Pop();

                if (currentKey == null)
                {
                    continue;
                }

                // First push all the new subkeys onto our stack.
                foreach (string key in currentKey.GetSubKeyNames())
                {
                    try
                    {
                        var next = currentKey.OpenSubKey(name: key, writable: false);
                        keys.Push(next);
                    }
                    // TODO: Capture that these keys exist but we couldn't access them in the results
                    // These are expected as we are running as administrator, not System.
                    catch (System.Security.SecurityException)
                    {
                        Log.Debug("Permission Denied Opening Subkey: {0}\\{1}", currentKey.Name, key);
                    }
                    // There seem to be some keys which are listed as existing by the APIs but don't actually exist.
                    // Unclear if these are just super transient keys or what the other cause might be.
                    // Since this isn't user actionable, also just supress these to the verbose stream.
                    catch (System.IO.IOException)
                    {
                        Log.Debug("IOError Reading: {0}\\{1}", currentKey.Name, key);
                    }
                    catch (Exception e)
                    {
                        Log.Information(e, "Unexpected error when parsing {0}\\{1}", currentKey.Name, key);
                        AsaTelemetry.TrackTrace(Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Error, e);
                    }
                }

                yield return(currentKey);
            }

            BaseKey?.Dispose();
        }