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_key on the project boundary in Resolvers::Projects::DeployKeyResolver, which only Project.availableDeployKeys mounts. It is the permission GET /projects/:id/deploy_keys requires.
  • Marks AccessLevelDeployKey and AccessLevelUser with skip_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 shape Project.workItemTypes uses for WorkItemType. AccessLevelUser carries only public profile fields, so it follows its parent rather than asking for read_user on the user boundary as UserCore does.
  • 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

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

  1. Pick a project with a deploy key that has write access, and a user who is a maintainer of it.
  2. In the Rails console, create a fine-grained token for that user with the read_project and read_deploy_key assignable permissions on the project, as in step 7 of the GraphQL implementation guide.
  3. 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.
  4. With a token that has only read_project, the same query returns the project with availableDeployKeys: 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 with read_project and read_deploy_key.
  • The same spec at this branch's head without the resolver's declaration: 7 examples, 1 failure. A token with only read_project then 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 under spec/requests/api/graphql/project/ and ee/spec/requests/api/graphql/project/branch_protections/: 61 examples, 0 failures.
  • The available_deploy_keys block of spec/graphql/types/project_type_spec.rb: 2 examples, 0 failures.
  • bundle exec rake gitlab:permissions:graphql:compile_docs leaves the page unchanged, bundle exec rake gitlab:permissions:validate passes, 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.

Edited by José M. Requena Plens

Merge request reports

Loading
Loading