How to curl the CloudBees Jenkins websocket endpoint

Article ID:360059154791
2 minute readKnowledge base

Issue

  • How do I verify that my CloudBees Jenkins instance is listening for websocket connections?

  • When I attempt to connect my agent to a controller using websockets I see a Response code was not 101: 403, e.g.,

Feb 11, 2021 6:33:34 PM hudson.remoting.jnlp.Main$CuiListener error
SEVERE: Handshake error.
io.jenkins.remoting.shaded.javax.websocket.DeploymentException: Handshake error.
at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:674)
at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:712)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:866)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:511)
at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:355)
at hudson.remoting.Engine.runWebSocket(Engine.java:627)
at hudson.remoting.Engine.run(Engine.java:469)
Caused by: io.jenkins.remoting.shaded.org.glassfish.tyrus.core.HandshakeException: Response code was not 101: 403.

Resolution

Agent to controller connections begin as TCP connections, before TLS is negotiated and messages are encrypted between agents and controllers. Afterwards, either a JNLP4-Connect procotol connection (on port 50000 by default) or Websocket protocol connection is attempted. In order to verify that Jenkins is listening for websocket connections you can use the following curl command,

$ curl --http1.1 -i -N --header "Connection: Upgrade" --header "Upgrade: websocket" --header "Host: JENKINS_URL" --header "Origin: JENKINS_URL" --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" --header "Sec-WebSocket-Version: 13" --header "Secret-Key:SECRET" --header "X-Remoting-Capability:rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAf4=" --header "Node-Name:my-agent" https://JENKINS_URL/wsagents/
HTTP/1.1 101 Switching Protocols
Date: Fri, 12 Feb 2021 22:51:56 GMT
Connection: upgrade
X-Content-Type-Options: nosniff
X-Remoting-Capability: rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAf4=
X-Remoting-Minimum-Version: 3.14
Cookie: e834e14558b07b6a0099f06226f7862469b5c5eacd92bb65d5190988ba990548
Sec-WebSocket-Accept: qGEgH3En71di5rrssAZTmtRTyFk=
Upgrade: WebSocket
Strict-Transport-Security: max-age=15724800; includeSubDomains


Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
$

Note:

  • Secret-Key (secret generated by Jenkins)

  • X-Remoting-Capability

  • Node-Name (the name of the node created in Jenkins)