Workflow Permissions#
Workflow permissions restrict which users or roles can execute a given workflow. They are defined per-workflow in YAML, evaluated server-side on every run request, and reflected in the frontend via a canRun boolean to gate UI actions.
YAML Definition#
Add a top-level permissions list to a workflow definition. Each entry is either a role name or a user email address (case-insensitive):
workflow:
id: my-restricted-workflow
permissions:
- admin
- sarah.smith@example.com
See the full example in examples/workflows/permissions_example.yml. Omitting permissions (or leaving it empty) allows any authenticated user to run the workflow.
Backend Enforcement#
Permission check logic lives in Workflow.check_run_permissions():
- If
workflow_permissionsis empty β allow (open to all). - If the caller's role is
adminβ allow unconditionally. - Otherwise, check whether the caller's email or role appears in the lowercased, stripped permissions list. If neither matches β deny.
The Roles enum (keep/identitymanager/rbac.py) defines available roles: admin, noc, webhook, and workflowrunner .
Enforcement happens in two places:
-
POST /{workflow_id}/runβ The run endpoint callscheck_run_permissions()against the loadedWorkflowobject'sworkflow_permissions. On failure it raises HTTP 403: "Insufficient permissions to execute this workflow" . -
POST /workflows/queryβ For each workflow returned by the list endpoint, the raw YAML is parsed,permissionsextracted, andcheck_run_permissions()called with the requesting user's email and role. The result is set as thecanRunfield on theWorkflowDTO. This means the list API tells the frontend ahead of time whether a workflow is executable by the current user.
Frontend Surfacing#
The Workflow TypeScript type carries canRun?: boolean from the API response.
In ManualRunWorkflowModal, after fetching workflows via useWorkflowsV2, the list is immediately filtered:
const filteredWorkflows = workflows?.filter((w) => w.canRun);
If any workflows were removed by this filter (i.e., filteredWorkflows.length !== workflows?.length), a yellow callout is shown: "Some workflows are not visible to you because you lack permissions" . Workflows with canRun: false never appear in the run selector.
Flow Summary#
Key Files#
| Layer | File | Purpose |
|---|---|---|
| YAML example | examples/workflows/permissions_example.yml | Reference workflow with permissions |
| Core logic | keep/workflowmanager/workflow.py | check_run_permissions() static method |
| API (list) | keep/api/routes/workflows.py | Sets canRun on WorkflowDTO |
| API (run) | keep/api/routes/workflows.py | Enforces 403 on unauthorized run |
| Data model | keep/api/models/workflow.py | WorkflowDTO.canRun field |
| TS type | keep-ui/shared/api/workflows.ts | Workflow.canRun frontend type |
| UI | keep-ui/features/workflows/manual-run-workflow/ui/manual-run-workflow-modal.tsx | Filter + callout warning |