Duo self-hosted verifier WebSocket check reports 403 against a healthy endpoint
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Summary
The WebSocket connectivity check in gitlab:duo:verify_self_hosted_setup (added in !243425 (merged)) rejects itself. It sends Host: <host>:<port> with the scheme's default port and Origin: <external_url> without one, and Workhorse accepts the upgrade only when the Origin host equals the Host header. On any instance whose external_url has no explicit port the check prints WebSocket endpoint rejected the connection (HTTP 403) and tells the operator to check their Duo seat, licence, or proxy.
Steps to reproduce
- Self-managed instance with
external_urlset without a port (for examplehttps://gitlab.example.com), Duo self-hosted configured and working. - Run
gitlab-rake gitlab:duo:verify_self_hosted_setup. - Read the WebSocket section of the output.
What is the current bug behavior?
>> WebSocket endpoint rejected the connection (HTTP 403) ✗agent_platform_websocket.status: ERROR, http_status: 403. Rails logs 200 for the same request; the 403 comes from the Workhorse upgrade.
What is the expected correct behavior?
The check reports the upgrade as accepted (101) when the endpoint is healthy.
Relevant logs and/or screenshots
Reproduced on omnibus 19.3.1-ee. Replaying the check's handshake from the instance with curl: Host with the port plus Origin without it returns 403; dropping the port from Host, adding it to Origin, or omitting Origin each return 101.
Possible fixes
The headers are built at https://gitlab.com/gitlab-org/gitlab/-/blob/ec55628e9adfd92f1055485d13f2367d5d8b67a3/ee/lib/gitlab/duo/administration/agent_platform_websocket_check.rb#L106-111. Build the host header once, omitting the default port the way browsers do, and derive Origin from it. I have a one-method fix with specs ready to open against this issue.