Loading
Add granular token authorization to Vulnerability management mutations
What does this MR do and why?
Adds granular (fine-grained) personal access token authorization to the Vulnerability management group of GraphQL mutations (group 4 of the authorization todo list), following the GraphQL implementation guide.
For each mutation this MR adds an authorize_granular_token directive, raw/assignable
permission definitions where none existed, an authorization request spec, and removes the
mutation's entry from config/authz/graphql/authorization_todo.txt.
Mutation → permission → boundary
| Mutation | Permission | Boundary |
|---|---|---|
AddProjectToSecurityDashboard |
update_security_dashboard |
project (boundary_argument: :id) |
RemoveProjectFromSecurityDashboard |
update_security_dashboard |
project (boundary_argument: :id) |
BulkSetVulnerabilityFindingsDueDates |
update_finding_due_date |
project (boundary_argument: :project_full_path) |
RefreshFindingTokenStatus |
update_finding_token_status |
project (boundary_argument: :vulnerability_id, boundary: :project) |
RefreshVulnerabilityFindingTokenStatus |
update_finding_token_status |
project (boundary_argument: :vulnerability_id, boundary: :project) |
SecurityFindingCreateIssue |
create_vulnerability_issue_link |
project (boundary_argument: :project) |
SecurityFindingExternalIssueLinkCreate |
create_vulnerability_external_issue_link |
project (boundary_argument: :project) |
SecurityFindingJiraIssueFormUrlCreate |
create_vulnerability_external_issue_link |
project (boundary_argument: :project) |
VulnerabilitiesArchive |
archive_vulnerability |
project (boundary_argument: :project_id) |
VulnerabilitiesCreateIssue |
create_vulnerability_issue_link |
project (boundary_argument: :project) |
VulnerabilityDismissFalsePositiveFlag |
update_vulnerability_flag |
project (boundary_argument: :id, boundary: :project) |
VulnerabilityExternalIssueLinkCreate |
create_vulnerability_external_issue_link |
project (boundary_argument: :id, boundary: :project) |
VulnerabilityExternalIssueLinkDestroy |
delete_vulnerability_external_issue_link |
project (boundary_argument: :id, boundary: :project) |
VulnerabilityIssueLinkCreate |
create_vulnerability_issue_link |
project (boundary_argument: :issue_id, boundary: :project) |
VulnerabilityLinkMergeRequest |
create_vulnerability_merge_request_link |
project (boundary_argument: :vulnerability_id, boundary: :project) |
VulnerabilityUnlinkMergeRequest |
delete_vulnerability_merge_request_link |
project (boundary_argument: :vulnerability_id, boundary: :project) |
Permissions
- Reused existing permissions:
create_vulnerability_issue_link,update_vulnerability_flag. - New raw permissions (all project-bounded,
available_for: granular_access_token):archive_vulnerability,create_vulnerability_external_issue_link,delete_vulnerability_external_issue_link,create_vulnerability_merge_request_link,delete_vulnerability_merge_request_link,update_finding_due_date,update_finding_token_status,update_security_dashboard. - Assignable grouping: rather than adding a parallel assignable per new raw, the nested and
lifecycle raws are folded into the existing master assignables (raw permission names and
mutation directives are unchanged; only assignable membership moves):
update_finding_due_date→ existingupdate_vulnerabilityassignable, alongside theconfirm/dismiss/resolve/revertlifecycle raws. Findings' due dates are vulnerability attributes, so they belong in the same assignable.archive_vulnerability→ new standalonearchive_vulnerabilityassignable (project-bounded). Archiving is semi-destructive and removes items from the active view, so it is kept out ofupdate_vulnerabilityrather than broadening that assignable.create_vulnerability_external_issue_link→ existingcreate_vulnerability_issue_linkassignable;delete_vulnerability_external_issue_link→ existingdelete_vulnerability_issue_linkassignable (external Jira/Zentao links are the same user-facing capability as internal issue links).- Standalone assignables kept:
create_vulnerability_merge_request_link,delete_vulnerability_merge_request_link,update_security_dashboard,update_finding_token_status.
Judgment calls
Vulnerabilities::ExternalIssueLinkgainedhas_one :project, through: :vulnerabilityso the boundary extractor can reach the project from the link GlobalID inVulnerabilityExternalIssueLinkDestroy. A real association (rather than adelegate) is required because the boundary preloader resolves paths viareflect_on_association.AddProjectToSecurityDashboard/RemoveProjectFromSecurityDashboardoperate on the user-scoped instance security dashboard, but the mutation argument is a project GlobalID and the effective capability is exposing that project's security data, so they are bounded to the project with a sharedupdate_security_dashboardpermission.- The token status refresh mutations use a single
update_finding_token_statuspermission — they perform the same domain action on the same resource.
Skipped mutations (todo entries kept)
These cannot be authorized with the current framework because Gitlab::Graphql::Authz::BoundaryExtractor#locate
only resolves a single GlobalID or a full-path string; it cannot resolve raw
Security::Finding UUID strings or arrays of IDs:
| Mutation | Blocking argument |
|---|---|
SecurityFindingCreateMergeRequest |
uuid (raw finding UUID string) |
SecurityFindingCreateVulnerability |
uuid |
SecurityFindingDismiss |
uuid |
SecurityFindingRevertToDetected |
uuid |
SecurityFindingSeverityOverride |
uuid |
RefreshSecurityFindingTokenStatus |
security_finding_uuid |
VulnerabilitiesDismiss |
vulnerability_ids (array) |
vulnerabilitiesSeverityOverride |
vulnerability_ids (array) |
VulnerabilitiesRemoveAllFromProject |
project_ids (array) |
How was this validated?
bundle exec rake gitlab:permissions:validatepasses.bundle exec rake gitlab:permissions:graphql:compile_docsandbundle exec rake gitlab:permissions:routes:compile_docsregenerated the reference docs (committed).- Every declared permission/boundary has an
authorizing granular token permissions for GraphQLshared-example request spec; specs run in CI. - RuboCop clean on all changed files.
Edited by Alex Buijs