Initial OfficeCom Sentinel client and deployment assets

This commit is contained in:
OfficeCom Codex
2026-07-17 00:39:28 +02:00
commit 7cdc0395c4
58 changed files with 6199 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
namespace AttackTracerNinjaCli;
internal sealed record ScanOptions
{
public const string Usage = """
Usage:
OCSentinelCli [--output <path>] [--lookback-days <n>] [--top <n>] [--config <path>] [--vulnerability-csv <path>] [--json-only] [--ninja-output] [--fail-on-attacks] [--fail-on-threshold] [--help]
Options:
--output <path> Write the JSON report to the given file.
--lookback-days <n> Only include events newer than now minus n days. Default: 30
--top <n> Number of aggregated source IPs to show. Default: 10
--config <path> Load thresholds, path overrides, and exclusions from JSON.
--vulnerability-csv <path>
Correlate local attack results with exported CVE data for this host.
--json-only Print only JSON to stdout.
--ninja-output Print extra key=value lines for RMM/Ninja-style parsing.
--fail-on-attacks Return exit code 1 when attacks are found.
--fail-on-threshold Return exit code 1 when status is warning or critical.
--help Show this message.
""";
public string? OutputPath { get; init; }
public int LookbackDays { get; init; } = 30;
public int TopCount { get; init; } = 10;
public bool JsonOnly { get; init; }
public bool NinjaOutput { get; init; }
public bool FailOnAttacks { get; init; }
public bool FailOnThreshold { get; init; }
public string? ConfigPath { get; init; }
public string? VulnerabilityCsvPath { get; init; }
public bool ShowHelp { get; init; }
public static ScanOptions Parse(string[] args)
{
var options = new ScanOptions();
for (int i = 0; i < args.Length; i++)
{
string arg = args[i];
switch (arg)
{
case "--help":
case "-h":
case "/?":
options = options with { ShowHelp = true };
break;
case "--json-only":
options = options with { JsonOnly = true };
break;
case "--ninja-output":
options = options with { NinjaOutput = true };
break;
case "--fail-on-attacks":
options = options with { FailOnAttacks = true };
break;
case "--fail-on-threshold":
options = options with { FailOnThreshold = true };
break;
case "--output":
options = options with { OutputPath = ReadValue(args, ref i, arg) };
break;
case "--config":
options = options with { ConfigPath = ReadValue(args, ref i, arg) };
break;
case "--vulnerability-csv":
options = options with { VulnerabilityCsvPath = ReadValue(args, ref i, arg) };
break;
case "--lookback-days":
options = options with { LookbackDays = ReadPositiveInt(args, ref i, arg) };
break;
case "--top":
options = options with { TopCount = ReadPositiveInt(args, ref i, arg) };
break;
default:
throw new ArgumentException($"Unknown argument: {arg}");
}
}
return options;
}
private static string ReadValue(string[] args, ref int index, string argName)
{
if (index + 1 >= args.Length)
{
throw new ArgumentException($"Missing value for {argName}");
}
index++;
return args[index];
}
private static int ReadPositiveInt(string[] args, ref int index, string argName)
{
string raw = ReadValue(args, ref index, argName);
if (!int.TryParse(raw, out int value) || value <= 0)
{
throw new ArgumentException($"{argName} must be a positive integer");
}
return value;
}
}