Skip to content

Commit b130802

Browse files
authored
Adds a first-run notice informing user of telemetry. (#145)
* Adds a first-run reminder about telemetry. * Improve telemetry opt out message * Fixes #120 * Updated strings * Clean up telemetry strings some more Now use three lines instead of 2 for telemetry info notice. * Adds a clarifying comment.
1 parent 0c24af3 commit b130802

File tree

4 files changed

+180
-70
lines changed

4 files changed

+180
-70
lines changed

Cli/Program.cs

Lines changed: 102 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,11 @@ public static class AttackSurfaceAnalyzerCLI
195195

196196
private static readonly string SQL_GET_RUN = "select run_id from runs where run_id=@run_id";
197197

198+
private static bool _isFirstRun = false;
199+
198200
static void Main(string[] args)
199201
{
202+
200203
#if DEBUG
201204
Logger.Setup(true,false);
202205
#else
@@ -209,8 +212,17 @@ static void Main(string[] args)
209212
.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)
210213
as AssemblyInformationalVersionAttribute[])[0].InformationalVersion;
211214
Log.Information("AttackSurfaceAnalyzerCli v.{0}",version);
212-
Log.Debug(version);
215+
216+
Strings.Setup();
213217
DatabaseManager.Setup();
218+
if (DatabaseManager.IsFirstRun())
219+
{
220+
_isFirstRun = true;
221+
string exeStr = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "AttackSurfaceAnalyzerCli.exe config --telemetry-opt-out true" : "AttackSurfaceAnalyzerCli config --telemetry-opt-out true";
222+
Log.Information(Strings.Get("ApplicationHasTelemetry"));
223+
Log.Information(Strings.Get("ApplicationHasTelemetry2"), "https://github.com/Microsoft/AttackSurfaceAnalyzer/blob/master/PRIVACY.md");
224+
Log.Information(Strings.Get("ApplicationHasTelemetry3"), exeStr);
225+
}
214226
Telemetry.Setup(Gui : false);
215227

216228
var argsResult = Parser.Default.ParseArguments<CollectCommandOptions, CompareCommandOptions, MonitorCommandOptions, ExportMonitorCommandOptions, ExportCollectCommandOptions, ConfigCommandOptions>(args)
@@ -245,92 +257,116 @@ private static int RunConfigCommand(ConfigCommandOptions opts)
245257
if (opts.ListRuns)
246258
{
247259

248-
Log.Information(Strings.Get("Begin")+" {0}", Strings.Get("EnumeratingCollectRunIds"));
249-
List<string> CollectRuns = GetRuns("collect");
250-
foreach (string run in CollectRuns)
260+
if (_isFirstRun)
261+
{
262+
Log.Warning(Strings.Get("FirstRunListRunsError"), opts.DatabaseFilename);
263+
}
264+
else
251265
{
252-
using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction))
266+
Log.Information(Strings.Get("DumpingDataFromDatabase"), opts.DatabaseFilename);
267+
List<string> CollectRuns = GetRuns("collect");
268+
if(CollectRuns.Count > 0)
253269
{
254-
cmd.Parameters.AddWithValue("@run_id", run);
255-
using (var reader = cmd.ExecuteReader())
270+
Log.Information(Strings.Get("Begin") + " {0}", Strings.Get("EnumeratingCollectRunIds"));
271+
foreach (string run in CollectRuns)
256272
{
257-
while (reader.Read())
273+
using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction))
258274
{
259-
Log.Information("RunId:{2} Timestamp:{0} AsaVersion:{1} ",
260-
reader["timestamp"],
261-
reader["version"],
262-
reader["run_id"]);
263-
List<RESULT_TYPE> resultTypes = new List<RESULT_TYPE>();
264-
if (int.Parse(reader["file_system"].ToString()) != 0)
265-
{
266-
resultTypes.Add(RESULT_TYPE.FILE);
267-
}
268-
if (int.Parse(reader["ports"].ToString()) != 0)
269-
{
270-
resultTypes.Add(RESULT_TYPE.PORT);
271-
}
272-
if (int.Parse(reader["users"].ToString()) != 0)
273-
{
274-
resultTypes.Add(RESULT_TYPE.USER);
275-
}
276-
if (int.Parse(reader["services"].ToString()) != 0)
277-
{
278-
resultTypes.Add(RESULT_TYPE.SERVICES);
279-
}
280-
if (int.Parse(reader["certificates"].ToString()) != 0)
281-
{
282-
resultTypes.Add(RESULT_TYPE.CERTIFICATE);
283-
}
284-
if (int.Parse(reader["registry"].ToString()) != 0)
285-
{
286-
resultTypes.Add(RESULT_TYPE.REGISTRY);
287-
}
288-
289-
foreach (RESULT_TYPE type in resultTypes)
275+
cmd.Parameters.AddWithValue("@run_id", run);
276+
using (var reader = cmd.ExecuteReader())
290277
{
291-
int num = DatabaseManager.GetNumResults(type, reader["run_id"].ToString());
292-
Log.Information("{0} : {1}", type, num);
278+
while (reader.Read())
279+
{
280+
Log.Information("RunId:{2} Timestamp:{0} AsaVersion:{1} ",
281+
reader["timestamp"],
282+
reader["version"],
283+
reader["run_id"]);
284+
List<RESULT_TYPE> resultTypes = new List<RESULT_TYPE>();
285+
if (int.Parse(reader["file_system"].ToString()) != 0)
286+
{
287+
resultTypes.Add(RESULT_TYPE.FILE);
288+
}
289+
if (int.Parse(reader["ports"].ToString()) != 0)
290+
{
291+
resultTypes.Add(RESULT_TYPE.PORT);
292+
}
293+
if (int.Parse(reader["users"].ToString()) != 0)
294+
{
295+
resultTypes.Add(RESULT_TYPE.USER);
296+
}
297+
if (int.Parse(reader["services"].ToString()) != 0)
298+
{
299+
resultTypes.Add(RESULT_TYPE.SERVICES);
300+
}
301+
if (int.Parse(reader["certificates"].ToString()) != 0)
302+
{
303+
resultTypes.Add(RESULT_TYPE.CERTIFICATE);
304+
}
305+
if (int.Parse(reader["registry"].ToString()) != 0)
306+
{
307+
resultTypes.Add(RESULT_TYPE.REGISTRY);
308+
}
309+
310+
foreach (RESULT_TYPE type in resultTypes)
311+
{
312+
int num = DatabaseManager.GetNumResults(type, reader["run_id"].ToString());
313+
Log.Information("{0} : {1}", type, num);
314+
}
315+
}
293316
}
294317
}
295318
}
296319
}
297-
}
298-
Log.Information(Strings.Get("Begin") + " {0}", Strings.Get("EnumeratingMonitorRunIds"));
299-
List<string> MonitorRuns = GetRuns("monitor");
300-
foreach (string monitorRun in MonitorRuns)
301-
{
302-
using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction))
320+
else
303321
{
304-
cmd.Parameters.AddWithValue("@run_id", monitorRun);
305-
using (var reader = cmd.ExecuteReader())
322+
Log.Information(Strings.Get("NoCollectRuns"));
323+
}
324+
325+
List<string> MonitorRuns = GetRuns("monitor");
326+
if (MonitorRuns.Count > 0)
327+
{
328+
Log.Information(Strings.Get("Begin") + " {0}", Strings.Get("EnumeratingMonitorRunIds"));
329+
330+
foreach (string monitorRun in MonitorRuns)
306331
{
307-
while (reader.Read())
332+
using (var cmd = new SqliteCommand(SQL_GET_RESULT_TYPES_SINGLE, DatabaseManager.Connection, DatabaseManager.Transaction))
308333
{
309-
string output = String.Format("{0} {1} {2} {3}",
310-
reader["timestamp"].ToString(),
311-
reader["version"].ToString(),
312-
reader["type"].ToString(),
313-
reader["run_id"].ToString());
314-
Log.Information(output);
315-
output = String.Format("{0} {1} {2} {3} {4} {5}",
316-
(int.Parse(reader["file_system"].ToString()) != 0) ? "FILES" : "",
317-
(int.Parse(reader["ports"].ToString()) != 0) ? "PORTS" : "",
318-
(int.Parse(reader["users"].ToString()) != 0) ? "USERS" : "",
319-
(int.Parse(reader["services"].ToString()) != 0) ? "SERVICES" : "",
320-
(int.Parse(reader["certificates"].ToString()) != 0) ? "CERTIFICATES" : "",
321-
(int.Parse(reader["registry"].ToString()) != 0) ? "REGISTRY" : "");
322-
Log.Information(output);
323-
334+
cmd.Parameters.AddWithValue("@run_id", monitorRun);
335+
using (var reader = cmd.ExecuteReader())
336+
{
337+
while (reader.Read())
338+
{
339+
string output = String.Format("{0} {1} {2} {3}",
340+
reader["timestamp"].ToString(),
341+
reader["version"].ToString(),
342+
reader["type"].ToString(),
343+
reader["run_id"].ToString());
344+
Log.Information(output);
345+
output = String.Format("{0} {1} {2} {3} {4} {5}",
346+
(int.Parse(reader["file_system"].ToString()) != 0) ? "FILES" : "",
347+
(int.Parse(reader["ports"].ToString()) != 0) ? "PORTS" : "",
348+
(int.Parse(reader["users"].ToString()) != 0) ? "USERS" : "",
349+
(int.Parse(reader["services"].ToString()) != 0) ? "SERVICES" : "",
350+
(int.Parse(reader["certificates"].ToString()) != 0) ? "CERTIFICATES" : "",
351+
(int.Parse(reader["registry"].ToString()) != 0) ? "REGISTRY" : "");
352+
Log.Information(output);
353+
354+
}
355+
}
324356
}
325357
}
326358
}
359+
else
360+
{
361+
Log.Information(Strings.Get("NoMonitorRuns"));
362+
}
327363
}
328364
}
329365

330366
if (opts.TelemetryOptOut != null)
331367
{
332368
Telemetry.SetOptOut(bool.Parse(opts.TelemetryOptOut));
333-
Log.Information("{1} {0}.", Strings.Get("TelemetryOptOut"), (bool.Parse(opts.TelemetryOptOut)) ? "Opted out" : "Opted in");
369+
Log.Information(Strings.Get("TelemetryOptOut"), (bool.Parse(opts.TelemetryOptOut)) ? "Opted out" : "Opted in");
334370
}
335371
if (opts.DeleteRunId != null)
336372
{

Cli/Properties/Resources.Designer.cs

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cli/Properties/Resources.resx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
<value>Monitor started for</value>
170170
</data>
171171
<data name="TelemetryOptOut" xml:space="preserve">
172-
<value>Your telemetry opt out setting is now</value>
172+
<value>Your telemetry opt out setting is now {0}.</value>
173173
</data>
174174
<data name="WelcomeHeader" xml:space="preserve">
175175
<value>Welcome to Attack Surface Analyzer</value>
@@ -396,4 +396,25 @@
396396
<data name="OutputWrittenTo" xml:space="preserve">
397397
<value>Output written to: {0}</value>
398398
</data>
399+
<data name="ApplicationHasTelemetry" xml:space="preserve">
400+
<value>This application collects usage data to help us improve Attack Surface Analyzer.</value>
401+
</data>
402+
<data name="ApplicationHasTelemetry2" xml:space="preserve">
403+
<value>For our privacy policy visit: {0}.</value>
404+
</data>
405+
<data name="ApplicationHasTelemetry3" xml:space="preserve">
406+
<value>To disable telemetry run '{0}'.</value>
407+
</data>
408+
<data name="DumpingDataFromDatabase" xml:space="preserve">
409+
<value>Dumping data from database located at {0}.</value>
410+
</data>
411+
<data name="NoCollectRuns" xml:space="preserve">
412+
<value>There were no collect runs in the database.</value>
413+
</data>
414+
<data name="NoMonitorRuns" xml:space="preserve">
415+
<value>There were no monitor runs in the database.</value>
416+
</data>
417+
<data name="FirstRunListRunsError" xml:space="preserve">
418+
<value>This appears to be the first run with database {0}. There are no runs to list.</value>
419+
</data>
399420
</root>

Lib/Utils/DatabaseManager.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public static class DatabaseManager
2323
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)";
2424
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)";
2525

26-
2726
private static readonly string SQL_CREATE_ANALYZED_TABLE = "create table if not exists results (base_run_id text, compare_run_id text, status int)";
2827

2928
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
6564

6665
private static SqliteTransaction _transaction;
6766

68-
public static void Setup()
67+
private static bool _firstRun = true;
68+
69+
public static bool Setup()
6970
{
7071
if (Connection == null)
7172
{
@@ -109,7 +110,10 @@ public static void Setup()
109110

110111
cmd.CommandText = SQL_CREATE_DEFAULT_SETTINGS;
111112
cmd.Parameters.AddWithValue("@schema_version", SCHEMA_VERSION);
112-
cmd.ExecuteNonQuery();
113+
if(cmd.ExecuteNonQuery() == 0)
114+
{
115+
_firstRun = false;
116+
}
113117

114118
cmd.CommandText = SQL_CREATE_FILE_SYSTEM_INDEX;
115119
cmd.ExecuteNonQuery();
@@ -142,7 +146,14 @@ public static void Setup()
142146
DatabaseManager.Transaction.Commit();
143147
_transaction = null;
144148
Log.Debug("Done with database setup");
149+
return true;
145150
}
151+
return false;
152+
}
153+
154+
public static bool IsFirstRun()
155+
{
156+
return _firstRun;
146157
}
147158

148159
public static void VerifySchemaVersion()

0 commit comments

Comments
 (0)