Protected container tags: Add GET endpoint for container protection tag rules API

What does this MR do and why?

Implements the GET endpoint at /api/v4/projects/:id/registry/protection/tag/rules to list container registry protection tag rules for a project. This enables REST API access to tag protection rules, providing feature parity with the existing GraphQL API and enabling automation through tools like Terraform that do not support GraphQL.

The implementation follows established patterns from container repository protection rules REST API and package protection rules REST API. It reuses the existing ContainerRegistry::Protection::TagRule model and authorization via :admin_container_image permission (maintainer or higher).

Technical changes:

  • Created API entity exposing id, project_id, tag_name_pattern, minimum_access_level_for_push, minimum_access_level_for_delete
  • Added GET endpoint with centralized authorization in after_validation block
  • Registered new API class in lib/api/api.rb
  • Added comprehensive request specs using GitLab shared examples for authorization testing

Test coverage includes 10 examples verifying success cases, authorization for all roles (reporter, developer, guest, non-member), empty results, and error scenarios (invalid project, invalid token).

This is the first of four endpoints for full CRUD operations on container protection tag rules. POST, PATCH, and DELETE endpoints will follow in subsequent merge requests.

🛠️ with ❤️ at Siemens

References

Main issue:

Related issues:

Reference implementations:

Documentation:

Screenshots or screen recordings

N/A - This is a REST API endpoint with no UI changes.

How to set up and validate locally

  1. Create a test project and container protection tag rule via Rails console:

    project = Project.find_by_full_path('flightjs/flight')
    rule = ContainerRegistry::Protection::TagRule.create!(
      project: project,
      tag_name_pattern: 'v*',
      minimum_access_level_for_push: :maintainer,
      minimum_access_level_for_delete: :maintainer
    )
  2. Test the GET endpoint with curl:

    curl -H "PRIVATE-TOKEN: <your-token>" \
      "http://gdk.test:3000/api/v4/projects/<project-id>/registry/protection/tag/rules"
  3. Expected response (HTTP 200) :

    [
      {
        "id": 1,
        "project_id": 123,
        "tag_name_pattern": "v*",
        "minimum_access_level_for_push": "maintainer",
        "minimum_access_level_for_delete": "maintainer"
      }
    ]
  4. Test authorization with a developer user (should return 403 Forbidden):

    curl -H "PRIVATE-TOKEN: <developer-token>" \
      "http://gdk.test:3000/api/v4/projects/<project-id>/registry/protection/tag/rules"

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

MR Checklist (@gerardo-navarro)
Edited by Gerardo Navarro

Merge request reports

Loading