Skip to content

[DSIP-104][ApiServer][UI] Introduce project-scoped authorization - #18718

Open
ruanwenjun wants to merge 27 commits into
apache:devfrom
ruanwenjun:Feature-17923
Open

ruanwenjun wants to merge 27 commits into
apache:devfrom
ruanwenjun:Feature-17923

Conversation

@ruanwenjun

@ruanwenjun ruanwenjun commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Was this PR generated or assisted by AI?

YES. The implementation, UI, schema upgrades, tests and documentation were generated or assisted by AI.

Purpose of the pull request

Implements DSIP-104 by separating project operation permissions from shared-resource grants. Users receive permissions within a project; resources are granted to projects. An operation requires both the relevant project permission and the resource grants it uses.

Closes #17923.

Authorization model

Aspect Before DSIP-104 After DSIP-104
Workflow operations Legacy read/write permissions and endpoint-specific checks Four explicit permissions assigned to users within each project
Resource authorization Personal datasource/namespace grants, a separate worker-group project association, and resource-specific rules Project grants for all eight supported shared-resource types
Protected operations Checks vary by endpoint and resource type Required project permission AND required project resource grants

Users receive four project operation permissions: VIEW, DEVELOP, EXECUTE and MANAGE_MEMBERS. DEVELOP includes definition publishing; EXECUTE includes schedule management. These are permissions assigned directly to users, not separate role entities. Supported resources are datasources, worker groups, tenants, queues, environments, alert groups, Kubernetes namespaces and task groups. Resource files retain their existing authorization mechanism.

System administrators grant or revoke project resources. System administrators and users with MANAGE_MEMBERS manage member permissions within the relevant project. Resource-use grants do not confer resource modification, deletion or re-granting rights. System administrators pass the project operation check, but required resource grants still apply.

Project metadata updates and deletion are restricted to system administrators or project creators. DEVELOP covers workflow/task definitions and their publishing; editing project metadata preserves its recorded owner.

Before DSIP-104

Datasource and namespace grants belong to users. Worker groups already have a separate project association; other resources follow their existing ownership or resource-specific rules.

Authorization before DSIP-104

After DSIP-104

All eight resource-use grants belong to the project. Each operation checks the user's permission in that project and the required project grants.

Project-scoped authorization after DSIP-104

Brief change log

  • Separate failed/suspended recovery from new execution: validate the parent instance's recorded task version and execution settings without recursively checking current child definitions. New starts, backfills, reruns and schedule management retain recursive child validation.
  • Use four project operation permissions: VIEW, DEVELOP (including publishing), EXECUTE (including schedule management), and MANAGE_MEMBERS. Align backend checks, compatibility queries, UI labels, both language guides, upgrade notes and the authorization diagram.
  • Require workflows and schedules to be offline before switching workflow versions. Switching versions no longer implicitly disables schedules.
  • Authorize historical instance task/variable reads through the instance's persisted project, so moving a definition does not transfer access to old instances.
  • Reject worker-group renames while task definitions, schedules or environment relations reference the old name; preserve allowed rename grant cleanup and after-commit Master refresh.
  • Require administrators at the service boundary for global datasource, tenant, queue, environment, namespace and alert-group existence checks; controllers pass the authenticated user.
  • Record project member-permission replacement and resource grant/revoke in the existing audit table with operator, project, subject and before/after state. Serialize authorization mutations per project and keep audit writes in the same transaction; rollback and audit-write failures cannot leave successful changes without their audit records.
  • Normalize the historical PostgreSQL default tenant's queue by resolving the actual default queue ID, preserving explicitly configured queues. Cover non-1 IDs and editable queue display names.
  • Bind the timing form model so authorized tenant selections pass schedule creation and update validation. Add a browser E2E regression for both operations.
  • Remove project grants for deleted resources across all eight supported types in the same transaction. Worker-group renames revoke old-name grants, and Master refresh notifications run after commit.
  • Reject cross-project moves while either the workflow or its schedule is online. Moving offline definitions retains destination-project task-resource checks; enabling them checks the destination's current grants.
  • Preserve complete cross-project lineage nodes, edges and summaries without requiring VIEW on every related project. Document this intentional visibility rule in both languages and add a positive regression; related workflow details and operations retain their project permission checks.
  • Remove legacy object-creator checks from workflow-definition and schedule deletion. Project members use DEVELOP and EXECUTE respectively, subject to existing state and dependency constraints. Add non-owner deletion regressions and update obsolete ownership assertions.
  • Explicitly document administrator-only datasource management, including creation, global listing, details/configuration, updates, connection tests and deletion. Clarify ordinary users' project-scoped datasource use in both permission guides, security models and 3.5.0 incompatible-change notes.
  • Normalize K8sNamespaceMapper.xml to LF without changing its SQL and validate whitespace across the entire PR diff.
  • Document the authorization boundaries in the English permission guide and Chinese permission guide, with operation/resource checks, execution examples, cross-project and subworkflow rules, default-resource grants and revocation limits. Align the security model, project-management guide and upgrade notes in both languages.
  • Add user-project permission and project-resource grant tables, assignment APIs, project management UI, MySQL/PostgreSQL 3.5.0 upgrade scripts and English/Chinese upgrade notes.
  • Apply project visibility in SQL so pagination, counts and searches agree. Batch workflow-task reads use VIEW-based project visibility for every actual project, including cross-project batches and administrator access. Project resource selectors return safe metadata without datasource connection parameters or environment configuration.
  • Validate grants when saving, publishing, managing schedules, manually executing and rerunning workflows. Resolve actual projects for instance and lineage reads, and validate the stored task version against the destination project before moving a workflow.
  • For new starts, backfills, reruns and schedule management, recursively check subworkflow permissions, task resources and inherited execution settings against each child's own project. Failed/suspended recovery checks the parent instance's pinned resources and settings without consulting current child definitions.
  • Support explicit grants for the existing built-in default tenant (id=-1). Reuse its existing database record; no additional tenant insert is required. Startup and schedule forms use authorized tenant choices, require a selection when needed and clear revoked choices. Workflow E2E fixtures explicitly select their granted tenant.
  • Use explicit authorization Mapper XML queries and Service interfaces with implementations in api.service.impl.
  • Complete workflow test fixtures with explicit project grants for worker groups, tenants, queues and environments. Python tests select their granted interpreter environment; Java/Python environment selection waits for the visible matching option. API schedule fixtures explicitly select no alert group when alerts are disabled, and workflow-definition integration tests verify rejection before a grant and success afterwards.
  • Pass the image-build job's DolphinScheduler Maven artifacts to the API-test matrix through a run-scoped artifact, restoring them after the shared dependency cache. Disable remote snapshot updates while running API tests so the test classpath uses the current build.
  • Load project datasource grants once per request and check every referenced datasource, including mixed-task and partially granted requests. Parse every bulk project ID inside explicit exception handling before changing any permissions.

Upgrade: Legacy authorization tables and data are retained, without automatic permission migration or fallback. Administrators must explicitly assign project member permissions and project resource grants, including any required default resources.

Revocation: Subsequent manual operations and schedule creation, update or enabling validate current grants. Existing running/queued instances, published schedule triggers and automatic retries continue without rechecking project grants. Revocation does not stop those instances or disable existing schedules.

Verify this pull request

Latest recovery-fix verification at a1400b2d4b:

  • Reproduced both failed/suspended recovery failures against the preceding implementation: current child-definition validation rejected otherwise authorized recovery.
  • 62 focused API tests passed, 0 failures/errors/skips: ExecutorService (19), TaskSubWorkflowPermissionChecker (13), SchedulerService (30). Recovery retains the parent project's EXECUTE check, pinned parent task resources and original execution settings. New tests verify that current child definitions are not consulted, and revoked parent permissions/settings still block submission. Existing rerun denial and schedule/new-execution recursive checks remain covered.
  • Root/API Spotless, both documentation image checks and git diff --check passed. Both language guides distinguish recovery from rerunning; Master recovery behavior is unchanged.
  • Full API, Master integration and browser E2E suites were not rerun for this commit. CI for the new head is not yet verified.

Earlier review-fix verification at 9e9c19bfd0:

  • Full API verification: 954 tests, 0 failures/errors, 10 existing skips. Includes 7 real H2 transaction/audit regressions, 6 administrator-only existence-check regressions and permission-model updates.
  • 32 H2 DAO tests passed, including permission-level compatibility, project visibility and authorization isolation. 2 MySQL/PostgreSQL upgrade integration tests passed, also exercising the project row-lock query against both databases.
  • Nine regressions reproduced failures against the preceding implementation: online version switching (2), moved-instance task/variable reads (4), and referenced worker-group renames (3).
  • Frontend TypeScript/ESLint/Prettier/production build, Root/API/Common/DAO/Tools Spotless, both documentation image checks and git diff --check passed. The draw.io-rendered diagram shows four permissions; no .drawio files are committed.
  • Full browser E2E and production behavior were not verified for this commit; new-head CI results are pending.

Earlier review-fix verification at e51c111da4:

  • 211 focused API tests, 14 H2 DAO tests, and 2 MySQL/PostgreSQL upgrade integration tests passed. Coverage includes resource deletion/rename, offline-only moves, default-tenant queue grants, deferred Master refresh and intentional cross-project lineage visibility.
  • The PostgreSQL upgrade regression fails against the previous migration (queue_id remains 0) and passes with the actual default queue at ID 42; reapplying the migration preserves an explicitly configured queue.
  • Chromium component checks with mocked APIs reproduce both schedule create/update failures without the model binding. Both pass with the fix; empty and revoked tenant selections remain rejected. The new Java browser E2E regression compiles, but the complete browser E2E stack was not rerun.
  • Frontend TypeScript/ESLint/Prettier/production build, Root/API/DAO/Tools Spotless, both documentation image checks and git diff --check passed.
  • Full API and browser E2E suites were not rerun for this commit. New-head CI results are not yet verified.

Earlier review-fix verification at 2aaf1d48f0:

  • Reproduced both non-owner deletion regressions against the preceding implementation: both were rejected by legacy ownership checks despite passing the required project permission check.
  • 112 tests passed, 0 failures/errors/skips: WorkflowDefinitionService (62), SchedulerService (30), DataSourceService (13), ResourcePermissionCheckService (4), and DataSourceResourcePermissionCheck (3). Includes both new positive regressions and existing permission/state/dependency checks.
  • Root/API Spotless, both documentation image checks, and Markdown rendering/local-link checks for six changed pages (36 local links/images and anchors) passed.
  • git diff --check upstream/dev...HEAD passed for the entire cumulative PR diff. The namespace mapper parses as XML and is byte-equivalent to its preceding content after normalizing CRLF to LF.
  • Full API and browser E2E suites were not rerun for this commit; CI for the new head is pending. No draw.io files are included.

Documentation verification at 514a283cba:

  • Root Spotless, both documentation image checks and git diff --check passed.
  • Rendered all eight changed Markdown pages and verified 45 local links/images and anchors. Existing image references are preserved; no draw.io files are included.
  • Independent reader review covered execution versus personal resource grants, administrator/member-manager boundaries, creator permissions, subworkflows, default resources and revocation semantics.
  • This commit changes documentation only; Java and browser suites were not rerun for it. CI for this head is pending.

Code verification at 0332c02a3b:

  • Reproduced four batch-read regressions before the fix: newly granted viewers were omitted, legacy-only access could remain visible, mixed-project requests included hidden workflows, and administrator results were incomplete.
  • Workflow-definition Service/Controller verification: 79 passed, 0 failures/errors/skips.
  • H2 project mapper verification: 18 passed, including new-table VIEW visibility, administrator access, revocation and rejection of legacy-only permissions.
  • Root/API Spotless and git diff --check passed. Execution-time authorization semantics are unchanged.

Full API verification at e86016e109:

  • Full API verification: 920 tests, 0 failures/errors, 10 existing skips. This includes multi-datasource grant checks, mixed tasks, destination-project isolation and rejection of malformed bulk project IDs before permission changes.
  • Project API integration tests against a locally built standalone server with H2: 13 passed, 0 failures/errors/skips. Assertions cover the creator's granted permissions in authorized/unauthorized project lists and authorized-member lists.
  • H2 authorization DAO verification: 6 passed, including grant-query isolation by project and resource type.
  • Root/API Spotless and git diff --check passed.

Other validation:

  • The complete Linux browser E2E workflow and Backend workflow passed at 8130a4d927. CodeQL also passed at e86016e109. These CI results apply to the listed earlier commits.
  • API-test artifact handoff: reproduced nine missing-type compiler errors with a stale dependency in an isolated Maven repository. Running the workflow's export/restore commands restored the current common JAR byte for byte and made clean API-test compilation pass. The local project archive was approximately 35 MiB; third-party dependency caching is retained. actionlint passed.
  • Workflow-definition, schedule and manual-execution API integration tests: 15 passed at 34cee246f6, including explicit default-tenant/queue grants and rejection before a required worker-group grant.
  • At 2eca6ace52, H2 DAO verification (13 passed), shared startup/schedule tenant-selection checks (14 scenarios), frontend TypeScript/ESLint/Prettier/production build and documentation image checks passed. API-test and E2E sources compiled on Java 11.

Pull Request Notice

Pull Request Notice

@github-actions github-actions Bot added UI ui and front end related backend test document labels Oct 16, 2026
@ruanwenjun ruanwenjun added this to the 3.5.0 milestone Oct 16, 2026
@ruanwenjun ruanwenjun added feature new feature DSIP labels Oct 16, 2026
@github-actions github-actions Bot added the e2e e2e test label Oct 16, 2026
@SbloodyS SbloodyS changed the title [Feature-17923][ApiServer][UI] Introduce project-scoped authorization [DSIP-104][ApiServer][UI] Introduce project-scoped authorization Oct 17, 2026

@SbloodyS SbloodyS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEVELOP unexpectedly authorizes project deletion and ownership transfer

Path: dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectServiceImpl.java:299,346-361

[Evidence] DSIP-104 defines DEVELOP as creating, editing, and deleting workflow/task definitions. deleteProject nevertheless requires only DEVELOP, so a member granted only that permission can delete an empty project. The update path uses the same permission and then unconditionally changes project.user_id to the editing user.

[Impact] A workflow developer can perform project-lifecycle operations outside the documented permission scope and can silently replace the recorded project owner.

[Request] Define an explicit project-lifecycle policy—system administrator/project owner, or a dedicated permission—and use it for rename/delete. A metadata edit must not change user_id; ownership transfer should be an explicit operation. Add tests for a user holding only DEVELOP.

Schedule validation does not include nested subworkflow resources

Path: dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java:618-625

[Evidence] Schedule create, update, and online operations call checkScheduleResources, but it validates only the parent workflow's execution settings and direct task definitions. It never calls the recursive TaskSubWorkflowPermissionChecker.

[Impact] If a child workflow's project grants are revoked after that child was published, a new or newly enabled parent schedule still passes validation. Scheduled triggers do not perform API-layer authorization again, so this bypasses the stated “check grants during schedule management” contract.

[Request] Reuse a recursive execution-resource validator from schedule creation/update/online and cover a cross-project child whose datasource or worker-group grant was revoked before the parent schedule is enabled.

Nested subworkflows do not validate inherited execution settings against the child project

Path: dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskSubWorkflowPermissionChecker.java:68-80

[Evidence] The recursive execution check validates only resources embedded in each child task definition. At runtime, SubWorkflowLogicTask copies the parent instance's warning group, worker group, tenant, and environment into every child instance (SubWorkflowLogicTask.java:242-252).

[Impact] A cross-project child can run with a tenant/queue, worker group, environment, or warning group that is granted to the parent project but not to the child project. This contradicts the PR's claim that every child workflow is checked against its own project grants.

[Request] Pass the effective execution settings into recursive validation and call checkExecutionSettings for every child project. Add coverage where child task-level resources are valid but one inherited execution-setting grant is absent.

Several read APIs still trust the caller-supplied project instead of the resource's actual project

Paths:

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowInstanceServiceImpl.java:532-552
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowInstanceServiceImpl.java:761-773
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowLineageServiceImpl.java:96-115

[Evidence] These methods authorize projectCode first, then query a subworkflow instance, trigger relation, or workflow lineage by an independently supplied identifier without proving that the returned object belongs to that project.

[Impact] A user with VIEW on project A can supply an identifier from project B and obtain parent-instance IDs, workflow-instance summaries, or lineage metadata from B.

[Request] Resolve the target instance/workflow first and require VIEW on its actual project, or include project_code in the DAO predicates. Add cross-project negative tests for all three endpoints.

Cross-project workflow move bypasses target resource validation

Path: dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java:1509-1522

[Evidence] moveWorkflowDefinitions changes the workflow's project and calls updateDagDefine with an empty task-definition list. updateDagDefine invokes both resource checkers on that empty list, so they return without inspecting the moved workflow's actual tasks.

[Impact] A workflow referencing datasources, worker groups, environments, namespaces, task groups, or subworkflows can be moved into a project that has none of the required grants. This bypasses the configuration-time authorization contract.

[Request] Load the moved workflow version's real task-definition logs and validate them, including nested subworkflows, against the target project before persisting the move. Add a cross-project move test with one missing target grant.

[Repository requirement] Do not add MyBatis lambda-wrapper persistence

Paths:

  • dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/impl/ProjectUserPermissionDaoImpl.java:46-82
  • dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/impl/ProjectResourceAuthorizationDaoImpl.java:46-68

[Evidence] Both new repositories implement their queries and deletes through LambdaQueryWrapper.

[Request] Move these operations to explicit Mapper methods and mapper XML, following the repository requirement against MyBatis lambda mapper usage.

[Repository requirement] New services need Service interfaces plus Impl classes

Paths:

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/ProjectAuthorizationService.java
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/ProjectResourceAuthorizationService.java

[Evidence] Both new Spring services are concrete classes named *Service, with no corresponding interface/*ServiceImpl.

[Request] Preserve the project's Service-plus-Impl ownership convention by introducing interfaces and moving the implementations into impl classes.

@github-actions github-actions Bot added the CI&CD label Oct 30, 2026

@SbloodyS SbloodyS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legacy ownership checks defeat project-scoped delete permissions

Paths:

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java:929-935
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java:364-378

[Evidence] DSIP-104 and the updated permission guide define DEVELOP as allowing workflow-definition deletion and MANAGE_SCHEDULES as allowing schedule deletion. Both deletion paths check the corresponding project permission, but then retain legacy object-owner checks that reject every non-owner ordinary user.

[Impact] A project member explicitly granted DEVELOP cannot delete a workflow created by another member, and a member granted MANAGE_SCHEDULES cannot delete another member's offline schedule. These project roles therefore cannot perform the operations they promise, leaving shared project administration dependent on the original creator or a system administrator.

[Request] Remove these legacy ownership checks, or document and model ownership as an additional explicit authorization dimension. Add positive tests using non-owner members who hold the required project permissions.

The security model still promises ordinary-user datasource management after making it administrator-only

Paths:

  • docs/docs/en/contribute/join/security-model.md:44-60
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/ResourcePermissionCheckServiceImpl.java:72-75,121-132,410-421

[Evidence] The security model still states that ordinary users can create datasource connections and modify or delete authorized connections. The implementation now returns no datasource IDs for every non-administrator and makes DataSourceResourcePermissionCheck.permissionCheck always return false. This blocks ordinary-user datasource creation, listing, inspection, update, connection testing, and deletion. The updated tests explicitly assert this administrator-only behavior.

[Impact] The documented security boundary and the shipped behavior disagree. The incompatible-upgrade notes also do not clearly state that ordinary users lose datasource-management access.

[Request] If administrator-only global resource management is intentional, update both language versions of the security model and the 3.5.0 incompatible-change notes explicitly. Otherwise, preserve datasource owner-management permissions while keeping project resource-use grants separate.

Normalize the new K8s namespace mapper lines

Path: dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml:79-95

[Evidence] git diff --check apache/dev...pr/18718 reports trailing whitespace on every newly added line in this block, caused by inconsistent line endings.

[Impact] The PR does not currently pass a clean git diff --check, despite the verification notes stating that it does.

[Request] Normalize this block to the repository's line-ending format and rerun git diff --check.

@ruanwenjun

Copy link
Copy Markdown
Member Author

Thanks for the review. Addressed all three points in 2aaf1d48f0:

  1. Removed the legacy creator checks from workflow-definition and schedule deletion. The corresponding project permission checks (DEVELOP / MANAGE_SCHEDULES) and existing state/dependency constraints are retained. Added positive regression tests for non-owner members and updated the obsolete ownership assertions.
  2. Administrator-only datasource management is intentional. Updated both language versions of the security model, permission guide and 3.5.0 incompatible-change notes to explicitly cover creation, global listing, details/configuration, updates, connection tests and deletion. Ordinary users can still select and use datasources granted to their projects within their project permissions.
  3. Normalized K8sNamespaceMapper.xml to LF without changing its SQL. git diff --check upstream/dev...HEAD now passes for the full cumulative PR diff.

Both new regression tests failed before the fix. After the fix, all 112 focused tests passed, along with Root/API Spotless, documentation image checks and local-link checks. CI for this commit is still queued/running.

@SbloodyS SbloodyS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostgreSQL upgrades can bypass the default tenant's queue grant

[Fact] checkExecutionSettings skips queue authorization whenever tenant.queueId <= 0. The historical PostgreSQL 3.2.0 upgrade inserts the built-in default tenant with queue_id = 0, while the MySQL upgrade and fresh PostgreSQL schema associate it with the default queue. No later PostgreSQL migration normalizes this value.

[Inference] On an installation upgraded through that PostgreSQL path, granting the default tenant is sufficient to pass execution and schedule checks without granting its queue. Authorization therefore depends on the database type and installation history, contradicting the documented requirement that a configured tenant queue also needs an explicit project grant.

[Request] Normalize the PostgreSQL default tenant's queue during the 3.5.0 upgrade, resolving the actual default queue rather than blindly assuming an ID. Add an upgrade regression starting from the historical PostgreSQL state and assert that execution requires both the default tenant and queue grants.

The timing form does not bind the model required for tenant validation

[Fact] This PR adds a required tenantCode rule, and schedule creation and update both call timingFormRef.validate(). However, the NForm in timing-modal.tsx has no model prop. Naive UI obtains an item's validation value from form.props.model[path], so this rule receives undefined even after the select updates timingForm.tenantCode. The start modal correctly passes its model.

[Inference] The timing modal cannot pass validation, blocking schedule creation and update through the UI for every selected tenant.

[Request] Pass model={this.timingForm} to this NForm and add a browser regression that creates and updates a schedule with an authorized tenant.

Lineage results do not check every related workflow project

[Fact] The new lineage check validates the actual project of the requested root workflow. The method then collects both workflow codes from every lineage record and calls queryWorkFlowLineageByCode for each one without checking the related workflow's project. That query returns workflow names, release states, and schedule timing data. queryWorkFlowLineage and queryDependentWorkflowDefinitions have the same per-related-node gap.

[Inference] If a user originally had VIEW on projects A and B, created a cross-project dependency, and later lost VIEW on B, querying lineage from A still exposes B's workflow and schedule metadata. This contradicts the documented cross-project and revocation semantics.

[Request] Resolve the owning project for every workflow included in a lineage result and enforce VIEW before returning its relations or details. Add a regression that revokes project B visibility after creating an A-to-B lineage.

Resource deletion leaves stale project datasource grants

[Fact] The new datasource permission checker treats rows in t_ds_project_resource_authorization as the complete authorization result and does not verify datasource existence. Datasource deletion removes the datasource and legacy datasource-user rows, but not the new project authorization rows. The new authorization table has no foreign key or cascade that performs this cleanup.

[Inference] A saved or imported task referencing a deleted datasource can still pass save, publish, and execution authorization checks and fail only later when runtime code attempts to load the missing datasource. Project authorization views also retain orphan grant state.

[Request] Revoke all DATASOURCE grants for a deleted datasource in the same transaction. Apply the same lifecycle rule to the other resource types, including name-keyed worker-group updates, and add deletion and rename regressions.

Moving an online workflow bypasses schedule-level grants in the target project

[Fact] The move path checks task resources against the target project and then changes the workflow's projectCode. It does not inspect the associated schedule, require it to be offline, validate its worker group, tenant and queue, environment, or alert group against the target project, or re-register the Quartz job.

[Fact] An existing Quartz job continues loading the same schedule and current workflow definition. WorkflowScheduleTrigger assigns the workflow's new project code to the created instance, while background schedule triggers intentionally do not repeat project resource authorization.

[Inference] Moving an online scheduled workflow lets the target project continue executing with schedule-level resources it was never granted. The move also changes effective scheduled execution without requiring MANAGE_SCHEDULES.

[Request] Reject moves while the workflow or its schedule is online, or atomically take the schedule offline, validate every effective execution setting against the target project, and re-register it under the target project. Add a regression covering an online schedule whose tenant or worker group is not granted to the destination.

@ruanwenjun

Copy link
Copy Markdown
Member Author

Thanks for the review. Updated in e51c111da4:

  1. The PostgreSQL upgrade now resolves the actual default queue for the historical queue_id=0 tenant. Existing explicit queue settings are preserved. Regression coverage includes a default queue with ID 42 and checks that execution requires both tenant and queue grants.
  2. Bound model={this.timingForm}. Authorized tenants now pass schedule creation and update validation. Added a browser E2E regression for both operations.
  3. Complete cross-project lineage is intentional: users can see related nodes, edges and summaries (including names, release states and schedule timing) from a visible root without VIEW on every related project. Hiding those nodes would make the graph incomplete. Related workflow details and operations still require their project's permissions. Kept this behavior and clarified it in the English/Chinese permission guides and security models, with a positive regression.
  4. Resource deletion now removes grants from all projects in the same transaction for all eight supported types. Worker-group renames revoke old-name grants; administrators must explicitly grant the new name. Master refresh notifications run after commit.
  5. Moves now require both the workflow and its schedule to be offline. Added regressions for online workflows and schedules with source-only execution settings.

Validation: 211 focused API tests, 14 H2 DAO tests and 2 MySQL/PostgreSQL upgrade tests passed. Chromium checks with mocked APIs reproduced the original form failures and verified the fix, including empty/revoked tenant rejection. Frontend checks/build, Spotless and documentation image checks passed. The new browser E2E test compiles; full API/browser E2E suites were not rerun, and CI for this commit is not yet verified.

@SbloodyS SbloodyS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workflow version-switch permission boundary

[Fact — paths]

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java:1674-1723
  • dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/process/ProcessServiceImpl.java:520-545
  • docs/docs/en/guide/security/security.md:112-123

[Fact] switchWorkflowDefinitionVersion requires only DEVELOP. ProcessServiceImpl.switchVersion unconditionally changes the selected workflow version to OFFLINE, and the caller then invokes offlineSchedulerByWorkflowCode, which also disables an existing online schedule.

[Fact] DSIP-104 defines DEVELOP, PUBLISH, and MANAGE_SCHEDULES as independent permissions. Taking a workflow offline belongs to PUBLISH, while disabling a schedule belongs to MANAGE_SCHEDULES.

[Inference] A member holding only DEVELOP can switch the version of an online workflow and consequently take both the workflow and its schedule offline. This bypasses two independent permission boundaries and allows a developer to interrupt scheduled production execution.

[Request] Reject workflow version switching while the workflow or its schedule is online, matching the existing task-version behavior, or explicitly require every permission needed by the resulting state changes. Add a regression using a user who has DEVELOP but lacks PUBLISH and MANAGE_SCHEDULES.

Moved-instance project resolution

[Fact — path] dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowInstanceServiceImpl.java:299-320,579-615

[Fact] queryTaskListByWorkflowInstanceId and viewVariables load the requested workflow instance, but they do not authorize its persisted workflowInstance.projectCode. Instead, they compare the caller-supplied project with the workflow definition's current project.

[Fact] Moving a workflow creates a new definition version under the destination project, while existing workflow instances retain the source project code.

[Inference] After a move from project A to project B, a user with VIEW only on B can supply an old instance ID from A and pass these checks because the current workflow definition belongs to B. The same instance can become inaccessible to users who still have VIEW on A. This violates DSIP-104's requirement to authorize existing objects through their actual owning project.

[Request] Use workflowInstance.getProjectCode() as the authorization source of truth before reading task-instance or variable data. Do not derive historical instance ownership from the current workflow definition. Add cross-project regressions covering completed instances before and after a workflow move.

Worker-group rename lifecycle

[Fact — path] dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkerGroupServiceImpl.java:143-158

[Fact] Renaming a worker group updates only the worker-group row, revokes every project grant for the old name, and refreshes the Master's worker-group state. It does not call the existing dependency checker and does not update task definitions, schedules, or environment relations that still store the old worker-group name.

[Fact] Granting the new worker-group name cannot repair those existing references because the saved definitions and schedules continue requesting the old name. The old name also cannot be granted again after it no longer resolves to an existing worker group.

[Inference] Renaming a worker group that is referenced by workflows or schedules leaves those objects bound to a resource that no longer exists and no longer has grants. Existing background schedules may continue reaching the trigger path, but task dispatch or subsequent authorization checks will fail on the obsolete name.

[Request] Reuse checkWorkerGroupDependencies to reject renames while the old name is referenced, or atomically migrate all stored references and define an explicit grant-migration policy. Add regressions for task definitions, schedules, and environment relations instead of testing only that the old grants are deleted.

Global resource verification endpoints

[Fact — paths]

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java:272-281
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/TenantController.java:198-208
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/QueueController.java:189-201
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/EnvironmentController.java:214-224
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java:122-134
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java:222-237

[Fact] These verification endpoints either do not receive the session user or receive it and never pass it to the service. They perform global existence checks without an administrator check or a project resource grant.

[Fact] Other list and detail paths in this PR restrict global resource metadata to administrators and expose ordinary users only to resources granted to a project where they have VIEW.

[Inference] An ordinary authenticated user can enumerate ungranted datasource names, tenant codes, queues, environments, Kubernetes namespaces, and alert-group names by comparing the verification responses. This leaves a metadata side channel outside the newly documented authorization boundary.

[Request] Require system-administrator permission on global verification endpoints. If a verification endpoint is also needed for project-scoped selection, require projectCode, VIEW, and the matching project resource grant rather than exposing the global namespace.

Authorization auditability

[Fact — paths]

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProjectAuthorizationController.java:63-69
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProjectResourceAuthorizationController.java:55-70
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectAuthorizationServiceImpl.java:83-101
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectResourceAuthorizationServiceImpl.java:75-96

[Fact] Member-permission replacement and resource grant/revoke operations have no @OperatorLog annotation, corresponding AuditType, or service-level mutation log. Permission replacement first deletes the complete old set and then inserts the new set without recording either state.

[Inference] DolphinScheduler's audit log cannot determine who granted or revoked a project permission or resource, which subject was changed, or what the previous and resulting permission sets were. These are the central security mutations introduced by this PR.

[Request] Add explicit audit events for member-permission replacement and project resource grant/revoke. Record the operator, project code, target user or resource type/key, and before/after permission state without including credentials or sensitive resource configuration. Add audit regressions for successful mutations and ensure failed transactions do not produce successful audit records.

@ruanwenjun

Copy link
Copy Markdown
Member Author

Thanks for the review. Updated in 9e9c19bfd0:

  1. Simplified the model to four project permissions: VIEW, DEVELOP, EXECUTE and MANAGE_MEMBERS. Publishing belongs to DEVELOP, and schedule management belongs to EXECUTE. Backend checks, UI, compatibility queries, documentation and the diagram now agree. Version switching additionally requires both the workflow and its schedule to be offline and no longer implicitly disables the schedule.
  2. Task-list and variable reads now check the instance's persisted projectCode. Moving its definition does not transfer access to historical instances. Added positive source-project and negative destination-project regressions for both APIs.
  3. Worker-group renames now use the dependency checker before changing the name or grants. Added task, schedule and environment-reference regressions. Updates that preserve the name remain allowed.
  4. All six global existence checks now receive the authenticated user and require administrator permission before querying resource metadata.
  5. Added service-level audit records for member-permission replacement and resource grant/revoke, including the operator, project, target and before/after state, without resource configuration or credentials. Authorization changes and audit writes share one transaction, with a project row lock for consistent snapshots. Tests cover outer rollback, rejected changes and audit-write failure.

Validation: full API verification ran 954 tests with 0 failures/errors and 10 existing skips; 32 H2 DAO tests and 2 MySQL/PostgreSQL upgrade integration tests passed. The latter also exercise the row-lock query on both databases. Frontend checks/build, Spotless, documentation image checks and git diff --check passed. Full browser E2E was not rerun, and CI for this commit is not yet verified. The agreed cross-project lineage behavior is unchanged.

@ruanwenjun

Copy link
Copy Markdown
Member Author

Follow-up in a1400b2d4b: failed/suspended recovery was using the parent's recorded task version but then recursively checking the current child definitions. An existing child can still be bound to an older version, so a later child-definition change could incorrectly block recovery.

Recovery now retains the parent project's EXECUTE check, pinned parent task resources and original execution settings without consulting current child definitions. New starts, backfills, reruns and schedule management retain recursive child validation. Master recovery behavior is unchanged.

Both recovery regressions reproduced before the fix. All 62 focused tests passed, including revoked parent permission/settings checks and existing rerun/schedule checks. Spotless, documentation image checks and git diff --check passed. Full API/Master integration/browser E2E suites were not rerun for this commit; new-head CI is not yet verified.

@SbloodyS SbloodyS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Authorization audit payload exceeds the database schema

[Fact — paths]

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/audit/ProjectAuthorizationAuditLogger.java:42-58
  • dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql:1208-1221
  • dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql:1222-1234
  • dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql:1209-1222

[Fact] ProjectAuthorizationAuditLogger serializes the complete before/after state, action, operator ID/name and project code into t_ds_audit_log.detail. The MySQL schema defines this column as varchar(100). A minimal resource-grant payload with a one-character operator name and resource key is already 154 ASCII characters.

[Fact] PostgreSQL and H2 use varchar(255), but resource keys are allowed to contain up to 255 characters. A valid long worker-group name plus the audit envelope also exceeds those columns. No 3.5.0 migration widens the existing audit column.

[Inference] Under MySQL strict SQL mode, every normal member-permission replacement and resource grant/revoke can fail while inserting its audit row, rolling back the authorization transaction. Without strict mode, MySQL can truncate the JSON, leaving an invalid and unusable audit record. PostgreSQL and H2 remain vulnerable for sufficiently long valid keys or names.

[Request] Widen t_ds_audit_log.detail to a text-capable type in the fresh schemas and database upgrade scripts. Add real MySQL and PostgreSQL authorization-mutation tests that verify both a normal payload and the maximum supported resource-key length, and assert that the stored detail remains parseable JSON.

Recovery can create an unvalidated current subworkflow

[Fact — paths]

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ExecutorServiceImpl.java:279-295
  • dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/command/handler/RecoverFailureTaskCommandHandler.java:53-55,147-204
  • dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/subworkflow/SubWorkflowLogicTask.java:156-174,192-260

[Fact] Failed and suspended recovery now checks only the parent workflow's pinned tasks and completely skips TaskSubWorkflowPermissionChecker. This is correct only when a subworkflow task already has a bound child instance.

[Fact] RecoverFailureTaskCommandHandler explicitly includes downstream tasks that were never triggered. When such a subworkflow task has no runtime context, SubWorkflowLogicTask calls triggerNewSubWorkflow, loads the child definition's current version, and creates a new child instance from that version.

[Inference] A parent can fail before reaching its subworkflow task, after which the user's child-project EXECUTE permission or the child project's resource grants can be revoked. Recovering the parent still passes the API checks and later creates a new child instance from the current child definition without validating either the child project permission or its resources.

[Request] Distinguish bound child instances from subworkflow tasks that will create a new child. Recover existing children against their persisted instance/version, but retain recursive current-child authorization for unbound or newly recreated subworkflow tasks. Add a regression where the parent fails before the subworkflow starts, the child permission or grant is revoked, and recovery must be rejected before command submission.

The four-permission model no longer implements the linked DSIP

[Fact — paths]

  • dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ProjectPermission.java:20-25
  • docs/docs/en/guide/security/security.md:106-125
  • Linked issue: apache/dolphinscheduler#17923

[Fact] The current implementation reduces the model to VIEW, DEVELOP, EXECUTE and MANAGE_MEMBERS. Publishing is bundled into DEVELOP, while all schedule management is bundled into EXECUTE.

[Fact] The still-open linked DSIP-104 issue continues to specify six independent permissions: View, Develop, Publish, Execute, Manage schedules and Manage members. It explicitly separates workflow publishing from definition development and schedule management from manual execution. No issue update or maintainer discussion approves replacing that contract with four broader permissions.

[Inference] A user who only needs to develop definitions must also receive publishing authority. A user who only needs to operate schedules must also receive manual run, backfill, rerun, recovery, pause and stop authority, and every ordinary executor automatically gains schedule modification authority. This removes the least-privilege separation that DSIP-104 was designed to introduce.

[Request] Restore the six independent operation permissions defined by the linked DSIP, or obtain explicit design approval and update the DSIP before merging the broader four-permission model. Updating only the PR description, implementation and documentation does not resolve the conflict with the issue this PR closes.

@ruanwenjun

Copy link
Copy Markdown
Member Author

Thanks for the review. Updated in 34a4f3b182:

  1. Audit details now contain only the target and before/after state; operator, project and action use the existing audit columns. Widened detail to varchar(2048) in the fresh schemas and MySQL/PostgreSQL upgrades, and aligned MySQL model_name with the existing 255-character columns. Database tests cover normal keys, 255-character keys and JSON escaping, with exact round-trip and parseability assertions for fresh and upgraded schemas.
  2. Failed/suspended recovery now reuses the execution authorization path before submitting the command. The parent uses its instance's recorded definition version and execution settings; referenced children are recursively checked using their current definitions and owning projects, including EXECUTE, resource grants and inherited execution settings. We kept one API policy rather than branching on bound child instances. Both language guides now explicitly state that current child-definition changes, moves or revoked grants can reject historical recovery. Master runtime behavior is unchanged.
  3. Updated DSIP-104 to describe the four-permission model explicitly: publishing belongs to DEVELOP, and schedule management belongs to EXECUTE. The issue also documents the resulting permission scope and recovery policy.

Validation: 41 focused API tests passed, including recovery rejection/success and H2 authorization/audit transaction tests. Two real MySQL/PostgreSQL schema/upgrade tests passed. Spotless, documentation image checks and git diff --check passed. Full API/browser E2E suites were not rerun; CI for this commit is not yet verified.

@SbloodyS SbloodyS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional execution and authorization lifecycle gaps

Recursive execution validation ignores offline child definitions

[Fact — paths]

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskSubWorkflowPermissionChecker.java:68-139
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ExecutorServiceImpl.java:138-190,254-296
  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java:475-493
  • dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/subworkflow/SubWorkflowLogicTask.java:226-260

[Fact] checkExecutionPermission recursively resolves every current child definition and checks its project EXECUTE permission, resources and inherited execution settings, but it never checks WorkflowDefinition.releaseState.

[Fact] Manual start and backfill validate only the parent definition's online state before calling this recursive checker. Failed/suspended recovery and rerun also use the recursive checker without a child release-state check. When Master creates an unbound child instance, triggerNewSubWorkflow loads the current child definition and submits it without checking whether it is online.

[Fact] Schedule enabling has a separate checkSubWorkflowDefinitionValid call, but that implementation checks only direct children. A direct child that is online but references an offline grandchild passes that check, and the recursive authorization traversal still does not reject the grandchild.

[Inference] After publishing a parent, an administrator can take a referenced child offline. Subsequent manual starts, backfills, reruns or recoveries can still create an instance of that offline child. A newly enabled schedule can likewise reach an offline nested child. This defeats the definition release-state boundary even though project permissions and resource grants pass.

[Request] Extend the execution-time recursive traversal to require every child definition that may create a new instance to be ONLINE. Apply it to manual start, backfill, rerun, recovery and schedule enabling, while keeping pure save or offline schedule-edit paths separate if they are intended to allow offline children. Add regressions for a direct offline child and an online child with an offline grandchild. Existing published background schedules can retain the separately documented no-recheck behavior.

User deletion leaves orphan project permissions

[Fact — paths]

  • dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UsersServiceImpl.java:414-447
  • dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProjectUserPermissionDao.java:25-39
  • dolphinscheduler-dao/src/main/resources/sql/upgrade/3.5.0_schema/mysql/dolphinscheduler_ddl.sql:18-27
  • dolphinscheduler-dao/src/main/resources/sql/upgrade/3.5.0_schema/postgresql/dolphinscheduler_ddl.sql:18-27

[Fact] Deleting a non-owner user removes access tokens, sessions and the user row, but does not remove rows from t_ds_project_user_permission. The new permission table has no foreign key or delete cascade, and its DAO has no revoke-by-user operation.

[Inference] Every deleted project member leaves hidden authorization rows indefinitely. If a user ID is restored or reused through import, database repair or sequence manipulation, the replacement user inherits the deleted account's project permissions. Even without ID reuse, authorization-level queries and database maintenance retain state for a subject that no longer exists.

[Request] Add an explicit Mapper/XML revokeAllPermissionsByUserId operation and invoke it in the same transaction before deleting the user. Add a regression that grants a non-owner permissions in multiple projects, deletes the user, and verifies that all new-table grants are removed while a failed user deletion rolls the cleanup back.

@ruanwenjun

Copy link
Copy Markdown
Member Author

Thanks for the review. Both findings are addressed in 992e5c2093:

  1. Execution checks now recursively require child definitions to be ONLINE, including nested grandchildren. This covers manual starts, backfills, reruns, failed/suspended recovery and schedule enabling. Offline schedule creation/update still validates recursive permissions, resource grants and inherited settings without requiring children to be online.
  2. User deletion now removes all project permissions through an explicit Mapper/XML operation in the same transaction. Regressions cover grants in multiple projects, preservation of other users' permissions and rollback when user deletion fails.

Merged the current dev in 1856a02330, retaining both the project-authorization and RPC-authentication upgrade notes. I also rechecked the earlier review points; their fixes and the documented permission, lineage and recovery policies remain in place. All four CodeQL review threads are resolved.

Validation after the merge: full API verification ran 976 tests with 0 failures/errors and 10 skips; 14 DAO tests and both real MySQL/PostgreSQL schema/upgrade tests passed. Spotless, documentation image/link checks and the cumulative diff check passed. Browser E2E was not rerun locally. The previous head's dependency scan failed its vulnerability threshold, and Shell E2E reported a Chrome renderer timeout. New-head CI is not yet verified.

}
if ("K8S".equals(task.getTaskType()) || "KUBEFLOW".equals(task.getTaskType())
|| "SPARK".equals(task.getTaskType())) {
String namespace = JSONUtils.toMap(task.getTaskParams()).get("namespace");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving a Spark task with mainJar fails before namespace authorization

Path: dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskResourcePermissionChecker.java:83-85

checkPermission parses the whole taskParams with JSONUtils.toMap, which targets Map<String, String>. With Jackson 2.13.4, numbers, booleans, nulls and empty arrays are accepted. Nested objects are rejected.

This is deterministic for the default Spark form. programType defaults to SCALA, and use-main-jar.ts requires mainJar unless the type is SQL. format-data.ts writes the selection as mainJar: { resourceName }. Saving goes through WorkflowDefinitionServiceImpl.createDagDefine → checkPermission. PYTHON has the same requirement. A SQL Spark task without nested fields does not hit this.

Payload:

{"mainClass":"org.apache.spark.examples.SparkPi","mainJar":{"resourceName":"spark-examples.jar"},"programType":"SCALA","driverCores":1,"localParams":[],"resourceList":[]}

JSONUtils.toMap fails at mainJar on every save:

MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
(through reference chain: java.util.LinkedHashMap["mainJar"])

The API returns 500 and the workflow is not saved. Namespace can be empty. This happens before the worker-group grant check. The same toMap(taskParams) also fails when localParams or resourceList contains an object, or when a K8S task has a non-empty customizedLabels array.

namespaceGrantMustMatchBothNameAndCluster only uses {"namespace":"{\"name\":\"jobs\",\"cluster\":\"production\"}"}, so it does not catch this.

Please read namespace with JsonNode or JSONUtils.getNodeString, and keep the existing JSONUtils.toMap(namespace) for the {"name","cluster"} string. Spark, K8S and Kubeflow already share that value shape (useNamespace(), and SparkTask reads toMap(namespace).get("name")). Add a regression whose taskParams includes mainJar.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this. Fixed in 680f586c66.

The checker now reads only the top-level namespace with JsonNode, preserving the existing namespace JSON-string parsing and name/cluster grant checks. Non-string namespace values are rejected.

Regression coverage includes Scala/Python mainJar, non-empty localParams, resourceList and customizedLabels, and missing/null namespaces. The tests also verify that worker-group grants, namespace grants and cluster matching are still enforced.

All 165 focused API tests passed, along with Spotless and git diff --check. Full API/browser E2E suites were not rerun for this commit; new-head CI is not yet verified.

@SbloodyS SbloodyS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Task-level YARN queues bypass project QUEUE grants

[Fact] TaskResourcePermissionChecker.checkPermission collects and validates datasources, worker groups, environments, task groups, SQL alert groups, and Kubernetes namespaces, but it never reads the task-level yarnQueue. checkExecutionSettings validates only the queue associated with the selected tenant.

[Fact] The UI serializes yarnQueue into the task parameters for Spark, MapReduce, Flink, and Flink Stream tasks. The corresponding runtime implementations then pass this value directly to Spark's --queue, MapReduce's mapreduce.job.queuename, or Flink's YARN queue options.

[Inference] A project can therefore hold a grant for the tenant's queue while saving and executing a task whose yarnQueue names a different, ungranted queue. Both definition-time and execution-time authorization pass because they call TaskResourcePermissionChecker, while the Worker later submits the job to the task-level queue. This contradicts the documented rule that task-referenced resources must be granted to the project.

[Fact] The raw others field can also contain the same queue options, and the Spark, MapReduce, and Flink command builders prefer those options over the structured yarnQueue value. Validating only the structured field would therefore leave another built-in path around the grant.

[Inference] Please define and enforce one consistent boundary. If project queue grants are intended to cover task-level YARN queues, resolve the structured yarnQueue against t_ds_queue.queue, require the matching queue ID grant during save, online, schedule validation, and manual execution, and handle the recognized queue options in others consistently. If grants intentionally cover only the tenant's queue, narrow the documentation and UI wording so they do not promise authorization for all task-referenced queues. Add regressions for Spark, MapReduce, Flink, and Flink Stream using a granted tenant queue together with an ungranted task-level queue.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend CI&CD document DSIP e2e e2e test feature new feature test UI ui and front end related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DSIP-104][ApiServer] Refactor the permission verification template code.

4 participants