mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(github): check clock skew only from failed GitHub App responses
Stop calling /zen before each installation token request. A short network problem to GitHub failed deployments with a cURL timeout on /zen. assertGithubClockInSync now takes the failed response and reads its Date header, so the "System time is out of sync" error still shows when GitHub rejects the JWT. Call it on failed JWT requests in the webhook installation check, the permission job, the source connection test, and the server transfer checklist. Remove the /zen fakes from the tests.
This commit is contained in:
@@ -6,6 +6,7 @@ use Carbon\Carbon;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Http\Client\ConnectionException;
|
||||
use Illuminate\Http\Client\RequestException;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -150,11 +151,25 @@ function encodeGithubPathSegment(string $segment): string
|
||||
return rawurlencode($segment);
|
||||
}
|
||||
|
||||
function assertGithubClockInSync(string $apiUrl): void
|
||||
/**
|
||||
* GitHub rejects an App JWT when the clocks of Coolify and GitHub differ.
|
||||
* Call this with the failed response of a JWT request: its Date header shows the difference without an extra request.
|
||||
*/
|
||||
function assertGithubClockInSync(Response $response): void
|
||||
{
|
||||
$response = Http::GitSource($apiUrl)->get("{$apiUrl}/zen");
|
||||
$date = $response->header('Date');
|
||||
|
||||
if (blank($date)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$githubTime = Carbon::parse($date);
|
||||
} catch (Throwable) {
|
||||
return;
|
||||
}
|
||||
|
||||
$serverTime = CarbonImmutable::now()->setTimezone('UTC');
|
||||
$githubTime = Carbon::parse($response->header('date'));
|
||||
$timeDiff = abs($serverTime->diffInSeconds($githubTime));
|
||||
|
||||
if ($timeDiff > 50) {
|
||||
@@ -179,8 +194,6 @@ function generateGithubToken(GithubApp $source, string $type)
|
||||
{
|
||||
$privateKey = githubAppPrivateKey($source) ?? throw new RuntimeException('Private key not found for this GitHub App.');
|
||||
|
||||
assertGithubClockInSync($source->api_url);
|
||||
|
||||
$signingKey = InMemory::plainText($privateKey->private_key);
|
||||
$algorithm = new Sha256;
|
||||
$tokenBuilder = (new Builder(new JoseEncoder, ChainedFormatter::default()));
|
||||
@@ -210,6 +223,7 @@ function generateGithubToken(GithubApp $source, string $type)
|
||||
)->post("{$source->api_url}/app/installations/{$source->installation_id}/access_tokens");
|
||||
|
||||
if (! $response->successful()) {
|
||||
assertGithubClockInSync($response);
|
||||
$error = data_get($response->json(), 'message', "HTTP {$response->status()}");
|
||||
if ($error === 'Not Found') {
|
||||
$error = "GitHub App installation {$source->installation_id} was not found. Install the GitHub App again or update its installation ID.";
|
||||
@@ -303,8 +317,6 @@ function syncGithubAppName(GithubApp $source, bool $throw = false): ?string
|
||||
return null;
|
||||
}
|
||||
|
||||
assertGithubClockInSync($source->api_url);
|
||||
|
||||
$jwt = generateGithubAppJwt($privateKey->private_key, $source->app_id);
|
||||
|
||||
$response = Http::GitSource($source->api_url)->withHeaders([
|
||||
@@ -314,6 +326,7 @@ function syncGithubAppName(GithubApp $source, bool $throw = false): ?string
|
||||
])->get("{$source->api_url}/app");
|
||||
|
||||
if (! $response->successful()) {
|
||||
assertGithubClockInSync($response);
|
||||
throw new RuntimeException(data_get($response->json(), 'message', 'Failed to fetch GitHub App information.'));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user