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:
1 parent
eb8844a4f1
commit
c8859a89d0
9 files changed
+536
-52
No files matched your search
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user