Files
html/api/auto-key-renew.php
2026-04-12 22:57:03 +02:00

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);
}