188 lines
8.1 KiB
PHP
Executable File
188 lines
8.1 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* CLOUDFLARE API KEY GENERATOR
|
|
* Login to CF accounts, generate Global API keys, then harvest domains
|
|
* Flow: login → get API key → list zones → store domains
|
|
*/
|
|
header('Content-Type: application/json');
|
|
require_once("/opt/wevads/config/credentials.php"); $db = pg_connect("host=localhost dbname=adx_system user=admin password=".WEVADS_DB_PASS);
|
|
pg_query($db, "SET search_path TO admin");
|
|
|
|
$action = $_GET['action'] ?? $_POST['action'] ?? 'status';
|
|
|
|
function cf_login_get_key($email, $password) {
|
|
// Step 1: Login to get session
|
|
$ch = curl_init('https://dash.cloudflare.com/api/v4/login');
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => json_encode(['email' => $email, 'password' => $password]),
|
|
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
|
CURLOPT_HEADER => true,
|
|
CURLOPT_TIMEOUT => 30
|
|
]);
|
|
$resp = curl_exec($ch);
|
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
return ['code' => $code, 'needs_2fa' => (strpos($resp, '2fa') !== false), 'raw' => substr($resp, 0, 500)];
|
|
}
|
|
|
|
function cf_api_zones($email, $key, $page=1) {
|
|
$ch = curl_init("https://api.cloudflare.com/client/v4/zones?page=$page&per_page=50&status=active");
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_HTTPHEADER => [
|
|
"X-Auth-Email: $email",
|
|
"X-Auth-Key: $key",
|
|
"Content-Type: application/json"
|
|
],
|
|
CURLOPT_TIMEOUT => 30
|
|
]);
|
|
$resp = curl_exec($ch);
|
|
curl_close($ch);
|
|
return json_decode($resp, true);
|
|
}
|
|
|
|
switch($action) {
|
|
case 'generate_keys':
|
|
// Try to get API keys for all accounts without one
|
|
$accounts = pg_fetch_all(pg_query($db,
|
|
"SELECT id, email, password FROM cloudflare_accounts
|
|
WHERE (api_key IS NULL OR api_key='') AND password IS NOT NULL AND password!=''
|
|
AND status='active' ORDER BY domains_count DESC"));
|
|
|
|
if (!$accounts) { echo json_encode(['error' => 'No accounts need keys']); break; }
|
|
|
|
$results = [];
|
|
foreach ($accounts as $acc) {
|
|
$login = cf_login_get_key($acc['email'], $acc['password']);
|
|
$results[] = [
|
|
'id' => $acc['id'],
|
|
'email' => $acc['email'],
|
|
'login_code' => $login['code'],
|
|
'needs_2fa' => $login['needs_2fa'],
|
|
'note' => 'Manual key needed - go to dash.cloudflare.com/profile/api-tokens'
|
|
];
|
|
usleep(500000); // 500ms delay between requests
|
|
}
|
|
|
|
echo json_encode([
|
|
'status' => 'info',
|
|
'message' => 'CF login API requires captcha/2FA. Use manual approach or API tokens.',
|
|
'manual_steps' => [
|
|
'1. Login to each CF account at dash.cloudflare.com',
|
|
'2. Go to Profile → API Tokens → Global API Key → View',
|
|
'3. Copy key and use /api/cloudflare-harvester.php?action=set_key&id=X&key=KEY',
|
|
'4. Then run harvest to get all domains'
|
|
],
|
|
'accounts_needing_keys' => count($accounts),
|
|
'results' => array_slice($results, 0, 5)
|
|
]);
|
|
break;
|
|
|
|
case 'set_key':
|
|
// Manually set API key for an account
|
|
$id = (int)($_GET['id'] ?? $_POST['id'] ?? 0);
|
|
$key = $_GET['key'] ?? $_POST['key'] ?? '';
|
|
if (!$id || !$key) { echo json_encode(['error' => 'Need id and key']); break; }
|
|
|
|
pg_query($db, "UPDATE cloudflare_accounts SET api_key='".pg_escape_string($db,$key)."', api_status='active', last_api_check=NOW() WHERE id=$id");
|
|
|
|
// Immediately try to harvest zones
|
|
$acc = pg_fetch_assoc(pg_query($db, "SELECT email, api_key FROM cloudflare_accounts WHERE id=$id"));
|
|
$zones_resp = cf_api_zones($acc['email'], $acc['api_key']);
|
|
|
|
$domains = [];
|
|
if ($zones_resp['success'] ?? false) {
|
|
foreach ($zones_resp['result'] ?? [] as $zone) {
|
|
$d = pg_escape_string($db, $zone['name']);
|
|
$zid = pg_escape_string($db, $zone['id']);
|
|
pg_query($db, "INSERT INTO cloudflare_domains(account_id, domain, zone_id, status, created_at)
|
|
VALUES($id, '$d', '$zid', '{$zone['status']}', NOW()) ON CONFLICT DO NOTHING");
|
|
$domains[] = $zone['name'];
|
|
}
|
|
pg_query($db, "UPDATE cloudflare_accounts SET domains_count=".count($domains).", last_api_check=NOW() WHERE id=$id");
|
|
}
|
|
|
|
echo json_encode([
|
|
'status' => 'success',
|
|
'account_id' => $id,
|
|
'api_valid' => ($zones_resp['success'] ?? false),
|
|
'domains_found' => count($domains),
|
|
'domains' => $domains
|
|
]);
|
|
break;
|
|
|
|
case 'bulk_set_keys':
|
|
// Set multiple keys at once: POST JSON array [{id:1,key:"xxx"}, ...]
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$keys = $input['keys'] ?? [];
|
|
$results = [];
|
|
foreach ($keys as $k) {
|
|
$id = (int)$k['id'];
|
|
$key = pg_escape_string($db, $k['key']);
|
|
pg_query($db, "UPDATE cloudflare_accounts SET api_key='$key', api_status='active', last_api_check=NOW() WHERE id=$id");
|
|
|
|
$acc = pg_fetch_assoc(pg_query($db, "SELECT email FROM cloudflare_accounts WHERE id=$id"));
|
|
$zones = cf_api_zones($acc['email'], $k['key']);
|
|
$cnt = 0;
|
|
if ($zones['success'] ?? false) {
|
|
foreach ($zones['result'] ?? [] as $z) {
|
|
$d = pg_escape_string($db, $z['name']);
|
|
pg_query($db, "INSERT INTO cloudflare_domains(account_id, domain, zone_id, status, created_at)
|
|
VALUES($id, '$d', '".pg_escape_string($db,$z['id'])."', '{$z['status']}', NOW()) ON CONFLICT DO NOTHING");
|
|
$cnt++;
|
|
}
|
|
pg_query($db, "UPDATE cloudflare_accounts SET domains_count=$cnt WHERE id=$id");
|
|
}
|
|
$results[] = ['id' => $id, 'email' => $acc['email'], 'domains' => $cnt];
|
|
}
|
|
echo json_encode(['status' => 'success', 'processed' => count($results), 'results' => $results]);
|
|
break;
|
|
|
|
case 'harvest_all':
|
|
// Harvest domains from ALL accounts that have API keys
|
|
$accounts = pg_fetch_all(pg_query($db,
|
|
"SELECT id, email, api_key FROM cloudflare_accounts WHERE api_key IS NOT NULL AND api_key!='' AND status='active'"));
|
|
if (!$accounts) { echo json_encode(['error' => 'No accounts with API keys']); break; }
|
|
|
|
$total = 0;
|
|
$results = [];
|
|
foreach ($accounts as $acc) {
|
|
$page = 1;
|
|
$domains = [];
|
|
do {
|
|
$resp = cf_api_zones($acc['email'], $acc['api_key'], $page);
|
|
if (!($resp['success'] ?? false)) break;
|
|
foreach ($resp['result'] ?? [] as $z) {
|
|
$d = pg_escape_string($db, $z['name']);
|
|
pg_query($db, "INSERT INTO cloudflare_domains(account_id, domain, zone_id, status, created_at)
|
|
VALUES({$acc['id']}, '$d', '".pg_escape_string($db,$z['id'])."', '{$z['status']}', NOW()) ON CONFLICT DO NOTHING");
|
|
pg_query($db, "INSERT INTO domains_pool(domain, provider, status, created_at)
|
|
VALUES('$d', 'cloudflare', 'active', NOW()) ON CONFLICT DO NOTHING");
|
|
$domains[] = $z['name'];
|
|
}
|
|
$total_pages = $resp['result_info']['total_pages'] ?? 1;
|
|
$page++;
|
|
} while ($page <= $total_pages);
|
|
|
|
pg_query($db, "UPDATE cloudflare_accounts SET domains_count=".count($domains).", last_api_check=NOW() WHERE id={$acc['id']}");
|
|
$results[] = ['id' => $acc['id'], 'email' => $acc['email'], 'domains' => count($domains)];
|
|
$total += count($domains);
|
|
}
|
|
echo json_encode(['status' => 'success', 'total_domains' => $total, 'accounts' => $results]);
|
|
break;
|
|
|
|
case 'status':
|
|
$s = pg_fetch_assoc(pg_query($db, "
|
|
SELECT
|
|
(SELECT COUNT(*) FROM cloudflare_accounts WHERE status='active') as total_accounts,
|
|
(SELECT COUNT(*) FROM cloudflare_accounts WHERE api_key IS NOT NULL AND api_key!='') as with_keys,
|
|
(SELECT COUNT(*) FROM cloudflare_accounts WHERE api_key IS NULL OR api_key='') as needs_keys,
|
|
(SELECT COUNT(*) FROM cloudflare_domains) as total_domains,
|
|
(SELECT SUM(domains_count) FROM cloudflare_accounts) as reported_domains
|
|
"));
|
|
echo json_encode(['status' => 'success', 'stats' => $s]);
|
|
break;
|
|
}
|