Multi-Provider Key Scanner + Checker (OpenAI, Google, 15 Key-Typen)

- KeyPatterns.cs: Zentrale Pattern-Klasse für 15 Key-Typen
  (Anthropic, OpenAI, Google, AWS, GitHub, GitLab, HuggingFace, Stripe, SendGrid, Slack)
- OpenAiKeyChecker.cs: Prüft sk-proj/sk-svcacct/sk- Keys via /v1/models
  (Org, Modelle, RPM/TPM, Tier-Erkennung Free bis 5+)
- GoogleKeyChecker.cs: Prüft AIza-Keys via Gemini /v1/models
  (Gemini-Modelle, Maps-Key-Erkennung)
- KeyScannerService + GitHubEventScannerService: Dispatch nach Key-Typ
- ApiKeysEndpoint: GET /scanned/summary + ?type= Filter
- Frontend: 2-stufige UI (Typ-Übersicht → Keys pro Typ)
This commit is contained in:
Meleki committed 2026-03-13 20:43:20 +01:00
1 parent eb8844a4f1
commit c8859a89d0
9 files changed
+536 -52

No files matched your search

+34 -18
View File
@@ -38,10 +38,10 @@ public class KeyScannerService : BackgroundService
// ── GitHub Search Config ──
private static readonly (string Pattern, string SearchTerm)[] KeyPatterns =
{
(@"sk-ant-oat01-[A-Za-z0-9_\-]{95}", "sk-ant-oat01"),
};
// Zentrale Key-Patterns aus KeyPatterns.cs (für Code Search: nur spezifische Suchterme)
private static readonly (string Pattern, string SearchTerm, string Type)[] SearchPatterns = KeyPatterns.ForCodeSearch;
// Alle Patterns für Regex-Matching im Dateiinhalt
private static readonly Regex[] AllCompiledPatterns = KeyPatterns.Compiled;
private static readonly string[] SearchLanguages =
{
@@ -249,7 +249,7 @@ public class KeyScannerService : BackgroundService
var allKeys = new Dictionary<string, string>(StringComparer.Ordinal);
var queries = new List<(string Query, Regex Regex)>();
foreach (var (pattern, searchTerm) in KeyPatterns)
foreach (var (pattern, searchTerm, _) in SearchPatterns)
{
var regex = new Regex(pattern, RegexOptions.Compiled);
foreach (var lang in QuickLanguages)
@@ -440,7 +440,7 @@ public class KeyScannerService : BackgroundService
private static List<(string Query, Regex Regex)> BuildSearchQueries()
{
var queries = new List<(string, Regex)>();
foreach (var (pattern, searchTerm) in KeyPatterns)
foreach (var (pattern, searchTerm, _) in SearchPatterns)
{
var regex = new Regex(pattern, RegexOptions.Compiled);
foreach (var lang in SearchLanguages)
@@ -470,7 +470,7 @@ public class KeyScannerService : BackgroundService
var client = _httpFactory.CreateClient();
client.DefaultRequestHeaders.Add("X-API-KEY", _serperApiKey);
foreach (var (pattern, searchTerm) in KeyPatterns)
foreach (var (pattern, searchTerm, _) in SearchPatterns)
{
ct.ThrowIfCancellationRequested();
var regex = new Regex(pattern, RegexOptions.Compiled);
@@ -519,15 +519,37 @@ public class KeyScannerService : BackgroundService
return allKeys.Select(kv => (kv.Key, kv.Value)).ToList();
}
// ── Anthropic Key Check (via shared AnthropicKeyChecker) ──
// ── Key Check ──
public async Task CheckAndUpdateKey(ScannedKeyRecord sk)
{
var type = KeyPatterns.DetectType(sk.ApiKey);
try
{
var result = await AnthropicKeyChecker.CheckKeyAsync(_httpFactory, sk.ApiKey);
var status = (result.Status == "ok" || result.Status == "usage_limited") ? "valid" : result.Status;
await _db.UpdateScannedKeyStatus(sk.ScannedKeyId, status, result.Plan, result.Usage7d, result.Usage5h);
if (KeyPatterns.IsAnthropic(type))
{
var result = await AnthropicKeyChecker.CheckKeyAsync(_httpFactory, sk.ApiKey);
var status = (result.Status == "ok" || result.Status == "usage_limited") ? "valid" : result.Status;
await _db.UpdateScannedKeyStatus(sk.ScannedKeyId, status, result.Plan, result.Usage7d, result.Usage5h);
}
else if (type == "openai_project" || type == "openai_service" || type == "openai_legacy")
{
var result = await OpenAiKeyChecker.CheckKeyAsync(_httpFactory, sk.ApiKey);
var status = result.Status == "ok" ? "valid" : result.Status;
await _db.UpdateScannedKeyStatus(sk.ScannedKeyId, status, result.Message, null, null);
}
else if (type == "google_api")
{
var result = await GoogleKeyChecker.CheckKeyAsync(_httpFactory, sk.ApiKey);
var status = result.Status == "ok" ? "valid" : result.Status;
await _db.UpdateScannedKeyStatus(sk.ScannedKeyId, status, result.Message, null, null);
}
else
{
// Andere Key-Typen: Typ korrekt setzen, kein Check möglich
await _db.UpdateScannedKeyStatus(sk.ScannedKeyId, "unchecked", type, null, null);
}
}
catch (Exception ex)
{
@@ -536,11 +558,5 @@ public class KeyScannerService : BackgroundService
}
}
private static string DetectKeyType(string key)
{
if (key.StartsWith("sk-ant-oat01-", StringComparison.Ordinal)) return "anthropic_oauth";
if (key.StartsWith("sk-ant-api03-", StringComparison.Ordinal)) return "anthropic_api";
if (key.StartsWith("sk-ant-", StringComparison.Ordinal)) return "anthropic_unknown";
return "unknown";
}
private static string DetectKeyType(string key) => KeyPatterns.DetectType(key);
}