fix(security): scope workflow run dispatch and MCP run logs to the token's tags
This commit is contained in:
@@ -314,6 +314,20 @@ func init() {
|
||||
return nil, fmt.Errorf("server %q is not part of run %q", serverID, runID)
|
||||
}
|
||||
|
||||
// Membership in the run is not scope: a run started before this
|
||||
// token was restricted, or by an unrestricted credential, names
|
||||
// servers this token must not read. The stdout of an
|
||||
// out-of-scope host is exactly the data the tag restriction
|
||||
// exists to withhold.
|
||||
//
|
||||
// The refusal reuses the membership message verbatim so that
|
||||
// "in the run but out of your scope" and "not in the run at all"
|
||||
// are indistinguishable — otherwise the difference between the
|
||||
// two answers enumerates hosts the token cannot see.
|
||||
if _, err := services.GetServerScoped(c.InstanceID, serverID, c.TokenScope); err != nil {
|
||||
return nil, fmt.Errorf("server %q is not part of run %q", serverID, runID)
|
||||
}
|
||||
|
||||
limit := defaultLogLimit
|
||||
if raw, ok := args["limit"].(float64); ok && int(raw) > 0 {
|
||||
limit = int(raw)
|
||||
|
||||
@@ -76,6 +76,15 @@ func init() {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("this workflow matches no servers")
|
||||
}
|
||||
// This all-or-nothing pre-check is no longer the only guard:
|
||||
// services.TriggerWorkflow now resolves through
|
||||
// ResolveTargetsScoped itself, so a run started with this token
|
||||
// can never touch a server outside its scope regardless of what
|
||||
// happens here. It is kept because its refusal is the clearer
|
||||
// answer for a model: the service layer would silently run
|
||||
// against the in-scope subset, while a partially out-of-scope
|
||||
// workflow is documented here as refused outright, which is
|
||||
// behaviour a caller relies on.
|
||||
scopedTargets, err := services.ResolveTargetsScoped(c.InstanceID, wf.TargetServerIDs, wf.TargetTags, c.TokenScope)
|
||||
if err != nil || len(scopedTargets) != len(allTargets) {
|
||||
return nil, fmt.Errorf("%w: no servers visible to this token matched the request", ErrOutOfScope)
|
||||
@@ -85,7 +94,7 @@ func init() {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
runID, err := services.TriggerWorkflow(c.InstanceID, workflowID, c.TokenName)
|
||||
runID, err := services.TriggerWorkflow(c.InstanceID, workflowID, c.TokenName, c.TokenScope)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not start the run: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user