114 lines
5.1 KiB
PHP
114 lines
5.1 KiB
PHP
<?php
|
|
// WEVIA Auto Key Renewal — Cron: checks all keys, alerts, queues Blade tasks
|
|
// Cron: */60 * * * * php /var/www/html/api/auto-key-renew.php
|
|
|
|
$SECRETS = "/etc/weval/secrets.env";
|
|
$env = @file_get_contents($SECRETS) ?: "";
|
|
$results = [];
|
|
$expired = [];
|
|
$renewed = [];
|
|
|
|
function testKey($url, $key, $data, $extra_h = []) {
|
|
$h = array_merge(["Content-Type: application/json", "Authorization: Bearer $key"], $extra_h);
|
|
$ch = curl_init($url);
|
|
$opts = [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $h, CURLOPT_TIMEOUT => 8, CURLOPT_SSL_VERIFYPEER => false];
|
|
if ($data) { $opts[CURLOPT_POST] = true; $opts[CURLOPT_POSTFIELDS] = $data; }
|
|
curl_setopt_array($ch, $opts);
|
|
$r = curl_exec($ch);
|
|
return curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
}
|
|
|
|
$checks = [
|
|
"GITHUB_TOKEN" => ["GET", "https://api.github.com/repos/Yacineutt/weval-consulting", null, ["User-Agent: WEVIA"]],
|
|
"GROQ_KEY" => ["POST", "https://api.groq.com/openai/v1/chat/completions", '{"model":"llama-3.3-70b-versatile","messages":[{"role":"user","content":"hi"}],"max_tokens":5}'],
|
|
"CEREBRAS_API_KEY" => ["POST", "https://api.cerebras.ai/v1/chat/completions", '{"model":"llama3.1-8b","messages":[{"role":"user","content":"hi"}],"max_tokens":5}'],
|
|
"GEMINI_KEY" => ["POST", "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", '{"model":"gemini-2.5-flash","messages":[{"role":"user","content":"hi"}],"max_tokens":5}'],
|
|
"SAMBANOVA_KEY" => ["POST", "https://api.sambanova.ai/v1/chat/completions", '{"model":"DeepSeek-V3.2","messages":[{"role":"user","content":"hi"}],"max_tokens":5}'],
|
|
"MISTRAL_KEY" => ["POST", "https://api.mistral.ai/v1/chat/completions", '{"model":"open-mistral-nemo","messages":[{"role":"user","content":"hi"}],"max_tokens":5}'],
|
|
];
|
|
|
|
foreach ($checks as $name => $test) {
|
|
$key = ""; if (preg_match("/{$name}=(.+)/", $env, $m)) $key = trim($m[1]);
|
|
if (!$key) { $expired[] = ["name" => $name, "reason" => "NO_KEY"]; continue; }
|
|
$code = testKey($test[1], $key, $test[2] ?? null, $test[3] ?? []);
|
|
if ($code !== 200 && $code !== 429) {
|
|
$expired[] = ["name" => $name, "code" => $code, "reason" => $code == 401 ? "EXPIRED" : ($code == 402 ? "NO_BALANCE" : "FAIL")];
|
|
}
|
|
$results[$name] = $code;
|
|
}
|
|
|
|
// AUTO-ACTIONS for expired keys
|
|
foreach ($expired as $e) {
|
|
$name = $e["name"];
|
|
|
|
// 1. Queue to Blade for browser renewal
|
|
$task = [
|
|
"type" => "key_renewal",
|
|
"provider" => $name,
|
|
"reason" => $e["reason"],
|
|
"urls" => [
|
|
"GITHUB_TOKEN" => "https://github.com/settings/tokens/new?scopes=repo,workflow&description=WEVIA-Auto",
|
|
"GROQ_KEY" => "https://console.groq.com/keys",
|
|
"CEREBRAS_API_KEY" => "https://cloud.cerebras.ai/platform",
|
|
"GEMINI_KEY" => "https://aistudio.google.com/apikey",
|
|
"SAMBANOVA_KEY" => "https://cloud.sambanova.ai/apis",
|
|
"MISTRAL_KEY" => "https://console.mistral.ai/api-keys",
|
|
],
|
|
"ts" => date("c"),
|
|
"priority" => $name === "GITHUB_TOKEN" ? "P0" : "P1"
|
|
];
|
|
|
|
// Save task for Blade
|
|
$task_id = "key_" . strtolower($name) . "_" . date("Ymd");
|
|
@file_put_contents("/var/www/html/api/blade-tasks/{$task_id}.json", json_encode($task, JSON_PRETTY_PRINT));
|
|
|
|
// 2. Try auto-renewal via API where possible
|
|
if ($name === "GEMINI_KEY") {
|
|
// Gemini: can create new key via API
|
|
$existing = trim(shell_exec("grep GEMINI_KEY /etc/weval/secrets.env | cut -d= -f2"));
|
|
if ($existing && strlen($existing) > 10) {
|
|
// Key exists but might need refresh - Gemini keys don't expire
|
|
$renewed[] = $name . " (key valid, test transient)";
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. Alert via Mattermost webhook if any expired
|
|
if ($expired) {
|
|
$webhook = ""; if (preg_match("/MATTERMOST_WEBHOOK=(.+)/", $env, $m)) $webhook = trim($m[1]);
|
|
$alert = "⚠️ **WEVIA Key Alert**\n";
|
|
foreach ($expired as $e) {
|
|
$alert .= "❌ {$e['name']}: {$e['reason']} (HTTP {$e['code']})\n";
|
|
}
|
|
$alert .= "\n🔧 Tasks queued to Blade for auto-renewal.";
|
|
|
|
if ($webhook) {
|
|
$ch = curl_init($webhook);
|
|
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode(["text" => $alert]), CURLOPT_HTTPHEADER => ["Content-Type: application/json"], CURLOPT_TIMEOUT => 5]);
|
|
curl_exec($ch);
|
|
}
|
|
}
|
|
|
|
// Save status
|
|
$status = [
|
|
"ts" => date("c"),
|
|
"results" => $results,
|
|
"expired" => $expired,
|
|
"renewed" => $renewed,
|
|
"ok" => count($results) - count($expired),
|
|
"total" => count($results),
|
|
"blade_tasks" => count($expired)
|
|
];
|
|
file_put_contents("/var/www/html/api/key-health.json", json_encode($status, JSON_PRETTY_PRINT));
|
|
|
|
// Output
|
|
if (php_sapi_name() === 'cli') {
|
|
echo "KEY HEALTH: " . $status["ok"] . "/" . $status["total"] . " OK\n";
|
|
foreach ($expired as $e) echo " ❌ {$e['name']}: {$e['reason']}\n";
|
|
foreach ($renewed as $r) echo " 🔄 $r\n";
|
|
echo "Blade tasks: " . count($expired) . "\n";
|
|
} else {
|
|
header("Content-Type: application/json");
|
|
echo json_encode($status);
|
|
}
|