Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-59305

Swarm Client failed to create a slave with response code: 403

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Duplicate
    • Component/s: swarm-plugin
    • Labels:
      None
    • Environment:
      Jenkins ver. 2.194
      Self-Organizing Swarm Plug-in Modules 3.17
      swarm-client-3.17.jar
    • Similar Issues:

      Description

      Since Jenkins ver.2.192, Swarm Client failed to create a slave with response code: 403.

       

      swarm-client log

      <record>
        <date>2019-09-11T08:11:50</date>
        <millis>1568157110925</millis>
        <sequence>276</sequence>
        <logger>hudson.plugins.swarm</logger>
        <level>SEVERE</level>
        <class&gt;hudson.plugins.swarm.Client</class&gt;
        <method>run</method>
        <thread>1</thread>
        <message>RetryException occurred</message>
        <exception>
          <message>hudson.plugins.swarm.RetryException: Failed to create a slave on Jenkins, response code: 403
      &lt;html&gt;
        &lt;head&gt;
          &lt;title&gt;The page is not found&lt;/title&gt;
        &lt;/head&gt;
        &lt;body&gt;
          &lt;h1&gt;The page is not found&lt;/h1&gt;
         ...
        &lt;/body&gt;
      &lt;/html&gt;
      </message>
          <frame>
            <class&gt;hudson.plugins.swarm.SwarmClient</class&gt;
            <method>createSwarmSlave</method>
            <line>472</line>
          </frame>
          <frame>
            <class&gt;hudson.plugins.swarm.Client</class&gt;
            <method>run</method>
            <line>150</line>
          </frame>
          <frame>
            <class&gt;hudson.plugins.swarm.Client</class&gt;
            <method>main</method>
            <line>104</line>
          </frame>
        </exception>
      </record>
      

      swam-client is executed with the following command.

      java -jar /var/lib/jenkins/swarm-client.jar -master htt
      p://jenkins-master.dev.xxx.yyy.zzz/jenkins-dev/ -username XXXXX -password YYYYY -name slave-xxx -disableClientsUniqueId -description jenkins-slave-xxx -executors 1 -fsroot /var/lib/jenkins -deleteExistingClients
      

        Attachments

          Issue Links

            Activity

            Show
            danielbeck Daniel Beck added a comment - The way the plugin obtains and uses the CSRF token is not compatible with https://jenkins.io/doc/upgrade-guide/2.176/#SECURITY-1491 https://github.com/jenkinsci/swarm-plugin/blob/75cb611554eca2e3ce0a7613847cbb91420211e7/client/src/main/java/hudson/plugins/swarm/SwarmClient.java#L379
            Hide
            basil Basil Crow added a comment -

            The way the plugin obtains and uses the CSRF token is not compatible with https://jenkins.io/doc/upgrade-guide/2.176/#SECURITY-1491

            Daniel Beck, could you please explain how the code here (the example you linked above) is not compatible with SECURITY-1491? I read SECURITY-1491 very carefully and stepped through the code in the Java debugger, and as far as I can tell I am doing everything correctly in Swarm:

            1. First, hudson.plugins.swarm.SwarmClient#createSwarmSlave creates an instance of HttpClientContext.
            2. Next, hudson.plugins.swarm.SwarmClient#getCsrfCrumb calls the crumbIssuer API, successfully obtaining a crumb request field and a crumb. The server's response sets a JSESSIONID cookie, which is visible in the HttpClientContext's BasicCookieStore (e.g., JSESSIONID.472fe218).
            3. Next, hudson.plugins.swarm.SwarmClient#createSwarmSlave adds the CSRF header returned by hudson.plugins.swarm.SwarmClient#getCsrfCrumb to the POST request.
            4. Next, hudson.plugins.swarm.SwarmClient#getCsrfCrumb executes the POST request. During this process, org.apache.http.client.protocol.RequestAddCookies examines the HttpClientContext's BasicCookieStore, finds the JSESSIONID cookie, and adds it to the set of headers before making the HTTP POST request.

            The key invariants for all this to work are that the HTTP GET in SwarmClient#getCsrfCrumb must always be called immediately before making any POST request, the HttpClientContext (and therefore the BasicCookieStore) must always be shared between the CSRF crumb retrieval GET and the subsequent POST, and the POST must contain both a CSRF header (obtained from the previous CSRF crumb retrieval GET) and a JSESSIONID header (which must be the same JSESSIONID from the previous CSRF crumb retrieval GET).

            As far as I can tell, I am meeting all of these invariants in my code. Furthermore, as I explained in JENKINS-59193, I cannot reproduce any CSRF-related issue, either in integration tests or against my production Jenkins instance running 2.204.4 with DefaultCrumbIssuer enabled.

            If there is something I am doing wrong, I would like to know what it is and/or how I could reproduce any potential issues.

            Show
            basil Basil Crow added a comment - The way the plugin obtains and uses the CSRF token is not compatible with https://jenkins.io/doc/upgrade-guide/2.176/#SECURITY-1491 Daniel Beck , could you please explain how the code here (the example you linked above) is not compatible with SECURITY-1491 ? I read SECURITY-1491 very carefully and stepped through the code in the Java debugger, and as far as I can tell I am doing everything correctly in Swarm: First, hudson.plugins.swarm.SwarmClient#createSwarmSlave creates an instance of HttpClientContext . Next, hudson.plugins.swarm.SwarmClient#getCsrfCrumb calls the crumbIssuer API, successfully obtaining a crumb request field and a crumb. The server's response sets a JSESSIONID cookie, which is visible in the HttpClientContext 's BasicCookieStore (e.g., JSESSIONID.472fe218 ). Next, hudson.plugins.swarm.SwarmClient#createSwarmSlave adds the CSRF header returned by hudson.plugins.swarm.SwarmClient#getCsrfCrumb to the POST request. Next, hudson.plugins.swarm.SwarmClient#getCsrfCrumb executes the POST request. During this process, org.apache.http.client.protocol.RequestAddCookies examines the HttpClientContext 's BasicCookieStore , finds the JSESSIONID cookie, and adds it to the set of headers before making the HTTP POST request. The key invariants for all this to work are that the HTTP GET in SwarmClient#getCsrfCrumb must always be called immediately before making any POST request, the HttpClientContext (and therefore the BasicCookieStore ) must always be shared between the CSRF crumb retrieval GET and the subsequent POST, and the POST must contain both a CSRF header (obtained from the previous CSRF crumb retrieval GET) and a JSESSIONID header (which must be the same JSESSIONID from the previous CSRF crumb retrieval GET). As far as I can tell, I am meeting all of these invariants in my code. Furthermore, as I explained in JENKINS-59193 , I cannot reproduce any CSRF-related issue, either in integration tests or against my production Jenkins instance running 2.204.4 with DefaultCrumbIssuer enabled. If there is something I am doing wrong, I would like to know what it is and/or how I could reproduce any potential issues.

              People

              • Assignee:
                Unassigned
                Reporter:
                ohzaki Hiroki OHZAKI
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: