Authorize available deploy keys for fine-grained tokens in GraphQL
What does this MR do and why?
Project.availableDeployKeys returns an empty list to a fine-grained personal access token, whatever the token is granted. Neither AccessLevelDeployKey nor AccessLevelUser declares a granular token directive (both are in config/authz/graphql/authorization_todo.txt), so the granular check denies every node, while a legacy token gets them.
This MR:
- Declares
read_deploy_keyon the project boundary inResolvers::Projects::DeployKeyResolver, which onlyProject.availableDeployKeysmounts. It is the permissionGET /projects/:id/deploy_keysrequires. - Marks
AccessLevelDeployKeyandAccessLevelUserwithskip_reason: :parent_authorizes. A deploy key cannot declare a project boundary of its own: it belongs to a user and can be enabled in many projects. It is the shapeProject.workItemTypesuses forWorkItemType.AccessLevelUsercarries only public profile fields, so it follows its parent rather than asking forread_useron the user boundary asUserCoredoes. - Removes the two types from the todo list and regenerates
doc/auth/tokens/fine_grained_access_tokens_graphql.md.
A token with read_project but not read_deploy_key now gets the project with availableDeployKeys: null.
The other parents of the two types, PushAccessLevel and the EE user field of the access level types, are reached only through BranchRule, which fine-grained tokens still cannot read, so nothing changes there.
References
- Related to #593878
WorkItemTypeskips the check the same way in !251840 (merged)
I found this while working on gitlab-mcp-server.
Screenshots or screen recordings
Not applicable: no UI change.
How to set up and validate locally
- Pick a project with a deploy key that has write access, and a user who is a maintainer of it.
- In the Rails console, create a fine-grained token for that user with the
read_projectandread_deploy_keyassignable permissions on the project, as in step 7 of the GraphQL implementation guide. - With that token, run
{ project(fullPath: "<path>") { availableDeployKeys { nodes { id title user { username } } } } }. On master the deploy key is missing; on this branch it is listed with its user. - With a token that has only
read_project, the same query returns the project withavailableDeployKeys: null.
Specs I ran (Ruby 3.3.11)
spec/requests/api/graphql/project/available_deploy_keys_spec.rb(new), with master's code: 7 examples, 1 failure. On master the field returns{ nodes: [] }to a token withread_projectandread_deploy_key.- The same spec at this branch's head without the resolver's declaration: 7 examples, 1 failure. A token with only
read_projectthen gets the deploy keys. - The same spec at this branch's head, with
spec/graphql/types/access_levels/deploy_key_type_spec.rb,spec/graphql/types/access_levels/user_type_spec.rb, and the branch protection and branch rule request specs underspec/requests/api/graphql/project/andee/spec/requests/api/graphql/project/branch_protections/: 61 examples, 0 failures. - The
available_deploy_keysblock ofspec/graphql/types/project_type_spec.rb: 2 examples, 0 failures. bundle exec rake gitlab:permissions:graphql:compile_docsleaves the page unchanged,bundle exec rake gitlab:permissions:validatepasses, and RuboCop finds no offenses in the changed Ruby files.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.