mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-06 04:23:04 +00:00
fix(sentinel): validate push containers payload
Reject malformed sentinel push payloads before updating heartbeat state, dispatching jobs, or writing deduplication cache entries.
This commit is contained in:
@@ -8,6 +8,7 @@ use App\Models\Server;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class SentinelController extends Controller
|
||||
{
|
||||
@@ -77,6 +78,17 @@ class SentinelController extends Controller
|
||||
|
||||
return response()->json(['message' => 'Unauthorized'], 401);
|
||||
}
|
||||
$validator = Validator::make($request->all(), [
|
||||
'containers' => ['required', 'array', 'min:1'],
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(serializeApiResponse([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => $validator->errors(),
|
||||
]), 422);
|
||||
}
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
// Heartbeat MUST update on every push — drives isSentinelLive() and SSH-check skipping.
|
||||
|
||||
@@ -11,6 +11,8 @@ use Illuminate\Support\Facades\Queue;
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
config(['app.maintenance.store' => 'array']);
|
||||
|
||||
Queue::fake();
|
||||
Cache::flush();
|
||||
|
||||
@@ -69,6 +71,25 @@ it('updates the heartbeat even when the job is skipped', function () use ($runni
|
||||
expect(Carbon::parse($this->server->fresh()->sentinel_updated_at)->diffInSeconds(now()))->toBeLessThan(5);
|
||||
});
|
||||
|
||||
it('rejects malformed sentinel payloads before touching server state', function (array $payload) {
|
||||
$this->server->update(['sentinel_updated_at' => now()->subHour()]);
|
||||
$originalHeartbeat = $this->server->fresh()->sentinel_updated_at;
|
||||
|
||||
pushSentinel($this->token, $payload)
|
||||
->assertUnprocessable()
|
||||
->assertJsonPath('message', 'Validation failed.')
|
||||
->assertJsonValidationErrors('containers');
|
||||
|
||||
Queue::assertNotPushed(PushServerUpdateJob::class);
|
||||
expect($this->server->fresh()->sentinel_updated_at)->toBe($originalHeartbeat);
|
||||
expect(Cache::has('sentinel:push-hash:'.$this->server->id))->toBeFalse();
|
||||
expect(Cache::has('sentinel:push-force:'.$this->server->id))->toBeFalse();
|
||||
})->with([
|
||||
'missing containers' => [[]],
|
||||
'non-array containers' => [['containers' => 'not-an-array']],
|
||||
'empty containers' => [['containers' => []]],
|
||||
]);
|
||||
|
||||
it('dispatches the job when container state changes', function () use ($running) {
|
||||
pushSentinel($this->token, sentinelPayload($running()))->assertOk();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user