diff --git a/Cli/Program.cs b/Cli/Program.cs index 5beb80153..5133d9820 100644 --- a/Cli/Program.cs +++ b/Cli/Program.cs @@ -195,8 +195,11 @@ public static class AttackSurfaceAnalyzerCLI private static readonly string SQL_GET_RUN = "select run_id from runs where run_id=@run_id"; + private static bool _isFirstRun = false; + static void Main(string[] args) { + #if DEBUG Logger.Setup(true,false); #else @@ -209,8 +212,17 @@ static void Main(string[] args) .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) as AssemblyInformationalVersionAttribute[])[0].InformationalVersion; Log.Information("AttackSurfaceAnalyzerCli v.{0}",version); - Log.Debug(version); + + Strings.Setup(); DatabaseManager.Setup(); + if (DatabaseManager.IsFirstRun()) + { + _isFirstRun = true; + string exeStr = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "AttackSurfaceAnalyzerCli.exe config --telemetry-opt-out true" : "AttackSurfaceAnalyzerCli config --telemetry-opt-out true"; + Log.Information(Strings.Get("ApplicationHasTelemetry")); + Log.Information(Strings.Get("ApplicationHasTelemetry2"), "https://github.com/Microsoft/AttackSurfaceAnalyzer/blob/master/PRIVACY.md"); + Log.Information(Strings.Get("ApplicationHasTelemetry3"), exeStr); + } Telemetry.Setup(Gui : false); var argsResult = Parser.Default.ParseArguments(args) @@ -245,92 +257,116 @@ private static int RunConfigCommand(ConfigCommandOptions opts) if (opts.ListRuns) { - Log.Information(Strings.Get("Begin")+" {0}", Strings.Get("EnumeratingCollectRunIds")); - List CollectRuns = GetRuns("collect"); - foreach (string run in CollectRuns) + if (_isFirstRun) + { + Log.Warning(Strings.Get("FirstRunListRunsError"), opts.DatabaseFilename); + } + else { - using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction)) + Log.Information(Strings.Get("DumpingDataFromDatabase"), opts.DatabaseFilename); + List CollectRuns = GetRuns("collect"); + if(CollectRuns.Count > 0) { - cmd.Parameters.AddWithValue("@run_id", run); - using (var reader = cmd.ExecuteReader()) + Log.Information(Strings.Get("Begin") + " {0}", Strings.Get("EnumeratingCollectRunIds")); + foreach (string run in CollectRuns) { - while (reader.Read()) + using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction)) { - Log.Information("RunId:{2} Timestamp:{0} AsaVersion:{1} ", - reader["timestamp"], - reader["version"], - reader["run_id"]); - List resultTypes = new List(); - if (int.Parse(reader["file_system"].ToString()) != 0) - { - resultTypes.Add(RESULT_TYPE.FILE); - } - if (int.Parse(reader["ports"].ToString()) != 0) - { - resultTypes.Add(RESULT_TYPE.PORT); - } - if (int.Parse(reader["users"].ToString()) != 0) - { - resultTypes.Add(RESULT_TYPE.USER); - } - if (int.Parse(reader["services"].ToString()) != 0) - { - resultTypes.Add(RESULT_TYPE.SERVICES); - } - if (int.Parse(reader["certificates"].ToString()) != 0) - { - resultTypes.Add(RESULT_TYPE.CERTIFICATE); - } - if (int.Parse(reader["registry"].ToString()) != 0) - { - resultTypes.Add(RESULT_TYPE.REGISTRY); - } - - foreach (RESULT_TYPE type in resultTypes) + cmd.Parameters.AddWithValue("@run_id", run); + using (var reader = cmd.ExecuteReader()) { - int num = DatabaseManager.GetNumResults(type, reader["run_id"].ToString()); - Log.Information("{0} : {1}", type, num); + while (reader.Read()) + { + Log.Information("RunId:{2} Timestamp:{0} AsaVersion:{1} ", + reader["timestamp"], + reader["version"], + reader["run_id"]); + List resultTypes = new List(); + if (int.Parse(reader["file_system"].ToString()) != 0) + { + resultTypes.Add(RESULT_TYPE.FILE); + } + if (int.Parse(reader["ports"].ToString()) != 0) + { + resultTypes.Add(RESULT_TYPE.PORT); + } + if (int.Parse(reader["users"].ToString()) != 0) + { + resultTypes.Add(RESULT_TYPE.USER); + } + if (int.Parse(reader["services"].ToString()) != 0) + { + resultTypes.Add(RESULT_TYPE.SERVICES); + } + if (int.Parse(reader["certificates"].ToString()) != 0) + { + resultTypes.Add(RESULT_TYPE.CERTIFICATE); + } + if (int.Parse(reader["registry"].ToString()) != 0) + { + resultTypes.Add(RESULT_TYPE.REGISTRY); + } + + foreach (RESULT_TYPE type in resultTypes) + { + int num = DatabaseManager.GetNumResults(type, reader["run_id"].ToString()); + Log.Information("{0} : {1}", type, num); + } + } } } } } - } - Log.Information(Strings.Get("Begin") + " {0}", Strings.Get("EnumeratingMonitorRunIds")); - List MonitorRuns = GetRuns("monitor"); - foreach (string monitorRun in MonitorRuns) - { - using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction)) + else { - cmd.Parameters.AddWithValue("@run_id", monitorRun); - using (var reader = cmd.ExecuteReader()) + Log.Information(Strings.Get("NoCollectRuns")); + } + + List MonitorRuns = GetRuns("monitor"); + if (MonitorRuns.Count > 0) + { + Log.Information(Strings.Get("Begin") + " {0}", Strings.Get("EnumeratingMonitorRunIds")); + + foreach (string monitorRun in MonitorRuns) { - while (reader.Read()) + using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction)) { - string output = String.Format("{0} {1} {2} {3}", - reader["timestamp"].ToString(), - reader["version"].ToString(), - reader["type"].ToString(), - reader["run_id"].ToString()); - Log.Information(output); - output = String.Format("{0} {1} {2} {3} {4} {5}", - (int.Parse(reader["file_system"].ToString()) != 0) ? "FILES" : "", - (int.Parse(reader["ports"].ToString()) != 0) ? "PORTS" : "", - (int.Parse(reader["users"].ToString()) != 0) ? "USERS" : "", - (int.Parse(reader["services"].ToString()) != 0) ? "SERVICES" : "", - (int.Parse(reader["certificates"].ToString()) != 0) ? "CERTIFICATES" : "", - (int.Parse(reader["registry"].ToString()) != 0) ? "REGISTRY" : ""); - Log.Information(output); - + cmd.Parameters.AddWithValue("@run_id", monitorRun); + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + string output = String.Format("{0} {1} {2} {3}", + reader["timestamp"].ToString(), + reader["version"].ToString(), + reader["type"].ToString(), + reader["run_id"].ToString()); + Log.Information(output); + output = String.Format("{0} {1} {2} {3} {4} {5}", + (int.Parse(reader["file_system"].ToString()) != 0) ? "FILES" : "", + (int.Parse(reader["ports"].ToString()) != 0) ? "PORTS" : "", + (int.Parse(reader["users"].ToString()) != 0) ? "USERS" : "", + (int.Parse(reader["services"].ToString()) != 0) ? "SERVICES" : "", + (int.Parse(reader["certificates"].ToString()) != 0) ? "CERTIFICATES" : "", + (int.Parse(reader["registry"].ToString()) != 0) ? "REGISTRY" : ""); + Log.Information(output); + + } + } } } } + else + { + Log.Information(Strings.Get("NoMonitorRuns")); + } } } if (opts.TelemetryOptOut != null) { Telemetry.SetOptOut(bool.Parse(opts.TelemetryOptOut)); - Log.Information("{1} {0}.", Strings.Get("TelemetryOptOut"), (bool.Parse(opts.TelemetryOptOut)) ? "Opted out" : "Opted in"); + Log.Information(Strings.Get("TelemetryOptOut"), (bool.Parse(opts.TelemetryOptOut)) ? "Opted out" : "Opted in"); } if (opts.DeleteRunId != null) { diff --git a/Cli/Properties/Resources.Designer.cs b/Cli/Properties/Resources.Designer.cs index ca4b3ac8a..273d7205c 100644 --- a/Cli/Properties/Resources.Designer.cs +++ b/Cli/Properties/Resources.Designer.cs @@ -604,5 +604,47 @@ public class Resources { return ResourceManager.GetString("OutputWrittenTo", resourceCulture); } } + + public static string ApplicationHasTelemetry { + get { + return ResourceManager.GetString("ApplicationHasTelemetry", resourceCulture); + } + } + + public static string ApplicationHasTelemetry2 { + get { + return ResourceManager.GetString("ApplicationHasTelemetry2", resourceCulture); + } + } + + public static string ApplicationHasTelemetry3 { + get { + return ResourceManager.GetString("ApplicationHasTelemetry3", resourceCulture); + } + } + + public static string DumpingDataFromDatabase { + get { + return ResourceManager.GetString("DumpingDataFromDatabase", resourceCulture); + } + } + + public static string NoCollectRuns { + get { + return ResourceManager.GetString("NoCollectRuns", resourceCulture); + } + } + + public static string NoMonitorRuns { + get { + return ResourceManager.GetString("NoMonitorRuns", resourceCulture); + } + } + + public static string FirstRunListRunsError { + get { + return ResourceManager.GetString("FirstRunListRunsError", resourceCulture); + } + } } } diff --git a/Cli/Properties/Resources.resx b/Cli/Properties/Resources.resx index 9aa9ddc8d..8b00c19a7 100644 --- a/Cli/Properties/Resources.resx +++ b/Cli/Properties/Resources.resx @@ -169,7 +169,7 @@ Monitor started for - Your telemetry opt out setting is now + Your telemetry opt out setting is now {0}. Welcome to Attack Surface Analyzer @@ -396,4 +396,25 @@ Output written to: {0} + + This application collects usage data to help us improve Attack Surface Analyzer. + + + For our privacy policy visit: {0}. + + + To disable telemetry run '{0}'. + + + Dumping data from database located at {0}. + + + There were no collect runs in the database. + + + There were no monitor runs in the database. + + + This appears to be the first run with database {0}. There are no runs to list. + \ No newline at end of file diff --git a/Lib/Utils/DatabaseManager.cs b/Lib/Utils/DatabaseManager.cs index 081280f2d..347441a65 100644 --- a/Lib/Utils/DatabaseManager.cs +++ b/Lib/Utils/DatabaseManager.cs @@ -23,7 +23,6 @@ public static class DatabaseManager private static readonly string SQL_CREATE_REGISTRY_COLLECTION = "create table if not exists registry (run_id text, row_key text, key text, value text, subkeys text, permissions text, serialized text)"; private static readonly string SQL_CREATE_CERTIFICATES_COLLECTION = "create table if not exists certificates (run_id text, row_key text, pkcs12 text, store_location text, store_name text, hash text, hash_plus_store text, cert text, cn text, serialized text)"; - private static readonly string SQL_CREATE_ANALYZED_TABLE = "create table if not exists results (base_run_id text, compare_run_id text, status int)"; private static readonly string SQL_CREATE_FILE_SYSTEM_INDEX = "create index if not exists path_index on file_system(path)"; @@ -65,7 +64,9 @@ public static class DatabaseManager private static SqliteTransaction _transaction; - public static void Setup() + private static bool _firstRun = true; + + public static bool Setup() { if (Connection == null) { @@ -109,7 +110,10 @@ public static void Setup() cmd.CommandText = SQL_CREATE_DEFAULT_SETTINGS; cmd.Parameters.AddWithValue("@schema_version", SCHEMA_VERSION); - cmd.ExecuteNonQuery(); + if(cmd.ExecuteNonQuery() == 0) + { + _firstRun = false; + } cmd.CommandText = SQL_CREATE_FILE_SYSTEM_INDEX; cmd.ExecuteNonQuery(); @@ -142,7 +146,14 @@ public static void Setup() DatabaseManager.Transaction.Commit(); _transaction = null; Log.Debug("Done with database setup"); + return true; } + return false; + } + + public static bool IsFirstRun() + { + return _firstRun; } public static void VerifySchemaVersion()