Add duo_flow_callback_enabled to the hooks API and webhook form

What does this MR do and why?

Lets a Maintainer or Owner mark a project or group webhook as a Duo flow callback endpoint, from the webhook settings form or over the REST API. This is the configuration half of Duo flow webhook callbacks; !249147 (merged) is the half that attaches a marked webhook to a running flow.

Stacked on !249147 (merged), which defines the duo_flow_callback_hooks flag this MR reads.

Three things you cannot see from the diff:

  • The container comes from the controller, not from hook.parent. On the create form the hook is unsaved, so hook.parent is nil — and Feature.enabled?(flag, nil) falls through to the global gate, showing the section to every namespace. System hooks have no container, so they never show it.
  • The parameter is only permitted when the feature is available. So a hand-rolled POST hook[duo_flow_callback_enabled]=true cannot set the attribute where the flag is off, nor on a system hook at all. The same predicate decides whether the checkbox renders, so the form and the guard cannot drift apart.
  • Enabling the attribute over the API where the feature is unavailable returns 400, rather than succeeding with the field quietly dropped. Disabling is always accepted, so a client can safely PUT back a payload it read from GET. Reads expose the field whatever the flag state, so the response shape does not change.

Not a security fix: the attribute is inert while the flag is off, because the trigger and delivery paths check it independently. The checkbox is an EE partial rendered through render_if_exists; the column and the REST parameter are CE, since web_hooks is a CE table.

References

Screenshots or screen recordings

Walkthrough

A 66-second capture of the whole path: the section renders with the flag on, the checkbox is ticked and saved, it survives a reopen, the REST API agrees, and the section disappears once the flag is turned off.

Project webhook, edit form

Flag on Flag off
project-edit-flag-on project-edit-flag-off

The setting survives a save

Ticked, saved, reopened — still ticked, and GET /projects/:id/hooks/:hook_id reports duo_flow_callback_enabled: true.

project-saved-still-ticked

The section stays after a failed update

An invalid submission re-renders the form instead of redirecting, and the section is still there.

project-edit-after-validation-error

Group webhook

group-saved-still-ticked

A hand-rolled request cannot set the field

With the flag off, a form POST that skips the UI does not persist the attribute.

$ curl .../api/v4/features | jq '.[] | select(.name=="duo_flow_callback_hooks")'
[{"key": "boolean", "value": false}, {"key": "expression", "value": null}, {"key": "actors", "value": ["Group:2281"]}]
# no Group:1000000 actor => the flag is OFF for the gitlab-duo namespace

$ sign in as $USER (session cookie, not a token)
# signed in

$ POST /gitlab-duo/test/-/hooks  hook[duo_flow_callback_enabled]=true
# target url: https://example.com/duo-flag-off-probe-1787661613
# HTTP 302 -> http://gdk.test:3000/gitlab-duo/test/-/hooks

$ find the hook that was just created (url is encrypted, so look it up over the API)
# hook id: 26

$ read the column straight from the database
hook id=26 url=https://example.com/duo-flag-off-probe-1787661613
duo_flow_callback_enabled = false
PASS 7: the request set hook[duo_flow_callback_enabled]=true, the column is still false
cleanup: probe hook deleted

How to set up and validate locally

Enable the flag for a top-level group:

Feature.enable(:duo_flow_callback_hooks, Group.find_by_full_path('my-group'))
  1. The setting appears, and it sticks. On that group, or a project inside it, go to Settings > Webhooks. Tick Send Duo flow events to this webhook, save, then reopen the webhook — it should still be ticked.

  2. The flag gates the form and the API together. Disable the flag. The section disappears from the form, and setting the field over the API is rejected:

    curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
      --url "https://gitlab.example.com/api/v4/projects/<project_id>/hooks/<hook_id>" \
      --data "duo_flow_callback_enabled=true"
    # => 400
  3. System hooks stay out of it. With the flag enabled, visit Admin > System hooks. The page renders normally and the section is absent.

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 Thomas Schmidt

Merge request reports

Loading
Loading