Files
tasks/common/primitives/task_queues.go
Stefan RichterandGitHub be4d9d91c8 Block usage of internal worker controller per-namespace task queue (#10289)
## What changed?
Add `WorkerControllerPerNSWorkerTaskQueue`
("temporal-sys-worker-controller-per-ns-tq") to the set of internal
per-namespace task queues and treat it the same as
`PerNSWorkerTaskQueue` in `IsInternalPerNsTaskQueue`, so user workflows
cannot start workflows, schedule activities, start child workflows,
continue-as-new, or update activity options targeting it.

## Why?
The Worker Controller internal task queue has the same security concerns
as the shared one, so treating it the same seems appropriate.

## How did you test it?
- [X] built
- [X] run locally and tested manually
- [X] covered by existing tests
- [X] added new unit test(s)
- [X] added new functional test(s)
2026-05-19 09:55:21 -07:00

73 lines
2.9 KiB
Go

package primitives
import (
"fmt"
"strings"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/api/serviceerror"
)
// all internal task queues shall be defined here such that we enhance security on top of them
const (
DefaultWorkerTaskQueue = "default-worker-tq"
PerNSWorkerTaskQueue = "temporal-sys-per-ns-tq"
WorkerControllerPerNSWorkerTaskQueue = "temporal-sys-worker-controller-per-ns-tq"
internalTaskQueuePrefix = "temporal-sys-"
internalTaskQueuePerNSPrefix = "temporal-sys-per-ns-"
MigrationActivityTQ = "temporal-sys-migration-activity-tq"
AddSearchAttributesActivityTQ = "temporal-sys-add-search-attributes-activity-tq"
DeleteNamespaceActivityTQ = "temporal-sys-delete-namespace-activity-tq"
DLQActivityTQ = "temporal-sys-dlq-activity-tq"
)
// IsInternalTaskQueueKind returns true if the task queue kind identifies a
// server-internal task queue (e.g. worker commands queues).
// All kinds are listed explicitly so that adding a new kind produces a compile error.
func IsInternalTaskQueueKind(kind enumspb.TaskQueueKind) bool {
switch kind {
case enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS:
return true
case enumspb.TASK_QUEUE_KIND_UNSPECIFIED,
enumspb.TASK_QUEUE_KIND_NORMAL,
enumspb.TASK_QUEUE_KIND_STICKY:
return false
}
return false
}
// IsInternalTaskQueue returns true if the task queue name belongs to an internal system task queue.
func IsInternalTaskQueue(taskQueue string) bool {
return strings.HasPrefix(taskQueue, internalTaskQueuePrefix)
}
// IsInternalPerNsTaskQueue returns true if the task queue name belongs to a per-namespace internal system worker
func IsInternalPerNsTaskQueue(taskQueue string) bool {
// TODO: remove WorkerControllerPerNSWorkerTaskQueue once it has been updated to match the prefix
return strings.HasPrefix(taskQueue, internalTaskQueuePerNSPrefix) || taskQueue == WorkerControllerPerNSWorkerTaskQueue
}
// CheckInternalPerNsTaskQueueAllowed tries to block the usage of internal per-namespace task queue for illegal cases.
// Parameters:
// - targetTaskQueue: The task queue of the component.
// - parentTaskQueue: The task queue of the parent component can be empty if the component has no parent.
//
// Returns an error if the usage is illegal, or nil if it's allowed.
func CheckInternalPerNsTaskQueueAllowed(targetTaskQueue, parentTaskQueue string) error {
if targetTaskQueue == "" {
return serviceerror.NewInvalidArgument("target task queue is not set")
}
if !IsInternalPerNsTaskQueue(targetTaskQueue) {
return nil
}
if !IsInternalPerNsTaskQueue(parentTaskQueue) {
errMessage := fmt.Sprintf("cannot use internal per-namespace task queue:%s", targetTaskQueue)
if parentTaskQueue != "" {
errMessage += fmt.Sprintf(" (in parent component task queue: %s)", parentTaskQueue)
}
return serviceerror.NewInvalidArgument(errMessage)
}
return nil
}