Derive console API key scopes from project API key

Instead of hardcoding scopes in the console key, read them from the
project API key. Added platforms.read and keys.read to the project
key, and the console key now receives only scopes that the project
key already has.
This commit is contained in:
Prem Palanisamy
2026-02-12 17:54:42 +00:00
parent 06c6fac915
commit 6565f2ff91
+35 -13
View File
@@ -319,6 +319,8 @@ class Migrations extends Action
'functions.write',
'tokens.read',
'tokens.write',
'platforms.read',
'keys.read',
]
]);
@@ -326,23 +328,37 @@ class Migrations extends Action
}
/**
* Generate a console-scoped dynamic API key for settings migration.
*
* This key allows the source adapter to read platforms and keys
* via the console API endpoints (same-instance only).
*
* @throws Exception
* Decode a dynamic API key and extract its scopes.
*/
protected function generateConsoleAPIKey(string $targetProjectId): string
protected function decodeAPIKeyScopes(string $apiKey): array
{
if (\str_contains($apiKey, '_')) {
[, $secret] = \explode('_', $apiKey, 2);
} else {
$secret = $apiKey;
}
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 86400, 0);
$payload = $jwt->decode($secret);
return $payload['scopes'] ?? [];
}
/**
* Generate a console-scoped dynamic API key for settings migration.
* Scopes are derived from the project API key (same-instance only).
*/
protected function generateConsoleAPIKey(string $targetProjectId, array $scopes): string
{
if (empty($scopes)) {
return '';
}
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 86400, 0);
$apiKey = $jwt->encode([
'projectId' => 'console',
'scopes' => [
'platforms.read',
'keys.read',
],
'scopes' => $scopes,
'targetProjectId' => $targetProjectId,
]);
@@ -389,8 +405,14 @@ class Migrations extends Action
// Only generate and set consoleApiKey for same-instance migrations
// to avoid leaking a locally-signed JWT to untrusted remote servers
if ($credentials['endpoint'] === $endpoint) {
$credentials['consoleApiKey'] = $this->generateConsoleAPIKey($credentials['projectId']);
$credentials['sourceProjectId'] = $credentials['projectId'];
// Read scopes from the project API key
$projectKeyScopes = $this->decodeAPIKeyScopes($credentials['apiKey']);
$consoleApiKey = $this->generateConsoleAPIKey($credentials['projectId'], $projectKeyScopes);
if (!empty($consoleApiKey)) {
$credentials['consoleApiKey'] = $consoleApiKey;
$credentials['sourceProjectId'] = $credentials['projectId'];
}
}
}