Skip to content

Commit b2cecec

Browse files
authored
feat: Add Metrics to SharpHound to be collected - BED-7080 (#202)
* wip: register metrics and dispose * chore: add default label cache * chore: coderabbbit suggested changes
1 parent 2bdeee1 commit b2cecec

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

src/Client/Flags.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ public class Flags
2828
public bool RecurseDomains { get; set; }
2929
public bool DoLocalAdminSessionEnum { get; set; }
3030
public bool ParititonLdapQueries { get; set; }
31+
public bool Metrics { get; set; }
3132
}
3233
}

src/Options.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ public class Options
142142

143143
[Option(HelpText = "Split the main ldap query into smaller chunks to attempt to reduce server load")]
144144
public bool PartitionLdapQueries { get; set; }
145+
146+
[Option(HelpText = "Output metrics that were captured from SharpHound")]
147+
public bool Metrics { get; set; }
145148

146149
//Loop Options
147150
[Option('l', "Loop", HelpText = "Loop computer collection")]

src/Sharphound.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
using Sharphound.Client;
2626
using SharpHoundCommonLib;
2727
using SharpHoundCommonLib.Enums;
28+
using SharpHoundCommonLib.Models;
29+
using SharpHoundCommonLib.Services;
30+
using SharpHoundCommonLib.Static;
2831

2932
namespace Sharphound
3033
{
@@ -36,6 +39,8 @@ namespace Sharphound
3639
#region Console Entrypoint
3740

3841
public class Program {
42+
private static MetricsFlushTimer _flushTimer;
43+
3944
public static async Task Main(string[] args) {
4045
var logger = new BasicLogger((int)LogLevel.Information);
4146
logger.LogInformation("This version of SharpHound is compatible with the 5.0.0 Release of BloodHound");
@@ -88,7 +93,8 @@ await options.WithParsedAsync(async options =>
8893
SearchForest = options.SearchForest,
8994
RecurseDomains = options.RecurseDomains,
9095
DoLocalAdminSessionEnum = options.DoLocalAdminSessionEnum,
91-
ParititonLdapQueries = options.PartitionLdapQueries
96+
ParititonLdapQueries = options.PartitionLdapQueries,
97+
Metrics = options.Metrics,
9298
};
9399

94100
var ldapOptions = new LdapConfig
@@ -149,10 +155,44 @@ await options.WithParsedAsync(async options =>
149155
}
150156
}
151157

158+
if (flags.Metrics) {
159+
var metricsRegistry = new MetricRegistry();
160+
metricsRegistry.RegisterDefaultMetrics();
161+
metricsRegistry.Seal();
162+
163+
var fileSinkOptions = new FileMetricSinkOptions {
164+
FlushInterval = TimeSpan.FromSeconds(5),
165+
};
166+
167+
var metricsWriter = new MetricWriter();
168+
169+
var metricsFileName = string.IsNullOrEmpty(options.OutputPrefix) ? "metrics.log" : $"{options.OutputPrefix}_metrics.log";
170+
var metricsFilePath = System.IO.Path.Combine(options.OutputDirectory, metricsFileName);
171+
172+
var fileSink = new FileMetricSink(
173+
metricsRegistry.Definitions,
174+
filePath: metricsFilePath,
175+
metricsWriter,
176+
fileSinkOptions);
177+
178+
var metricsRouter = new MetricRouter(
179+
metricsRegistry.Definitions,
180+
[fileSink],
181+
new DefaultLabelValuesCache());
182+
183+
Metrics.Factory = new MetricFactory(metricsRouter);
184+
185+
_flushTimer = new MetricsFlushTimer(
186+
flush: metricsRouter.Flush,
187+
interval: fileSinkOptions.FlushInterval);
188+
189+
}
190+
152191
await StartCollection(options, logger, resolved, flags, ldapOptions);
153192
});
154193
} catch (Exception ex) {
155194
logger.LogError($"Error running SharpHound: {ex.Message}\n{ex.StackTrace}");
195+
_flushTimer?.Dispose();
156196
}
157197
}
158198

@@ -214,6 +254,7 @@ private static async Task StartCollection(Options options, BasicLogger logger, C
214254
context = await links.AwaitLoopCompletion(context);
215255
context = links.SaveCacheFile(context);
216256
links.Finish(context);
257+
_flushTimer?.Dispose();
217258
}
218259

219260
// Accessor function for the PS1 to work, do not change or remove

0 commit comments

Comments
 (0)