fix(coordinator): bind JWT caller to worker at claim (close quarantine bypass)
The trust tier was read off the caller-supplied worker_id, so a JWT user who knew any trusted worker's id could claim as it — draining and poisoning the trusted queue and bypassing the untrusted-worker quarantine entirely. Claim now requires a JWT caller to own the worker it acts as; a shared-token caller (lab operator) may still act as any worker. Claim is the sole grantor of a lease, so this also protects the downstream heartbeat/result/failure paths. Tests: reject claim as another user's worker; allow claim as own worker.
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/emil28092005/SciMesh/coordinator/internal/authctx"
|
||||
"github.com/emil28092005/SciMesh/coordinator/internal/domain"
|
||||
)
|
||||
|
||||
@@ -51,6 +52,18 @@ func (uc *ClaimTask) Execute(ctx context.Context, in ClaimTaskInput) (*domain.Cl
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Bind the caller to the worker it claims as. A JWT-authenticated
|
||||
// volunteer may operate only its own workers; without this the trust
|
||||
// tier would be read off a caller-supplied worker_id, letting anyone who
|
||||
// knows a trusted worker's id claim as it and bypass the quarantine
|
||||
// below. A shared-token caller (no requester) is a lab operator and may
|
||||
// act as any worker, preserving the original behaviour.
|
||||
if r, ok := authctx.From(ctx); ok {
|
||||
if worker.OwnerID == nil || *worker.OwnerID != r.UserID {
|
||||
// Don't disclose that another user's worker exists.
|
||||
return nil, domain.ErrWorkerNotFound
|
||||
}
|
||||
}
|
||||
// C1 quarantine: an untrusted volunteer worker may register but receives
|
||||
// no tasks, because there is not yet (until quorum, C2) any way to verify
|
||||
// its results. Report an empty queue rather than an error, so its poller
|
||||
|
||||
Reference in New Issue
Block a user