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

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

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: Major Major
    • swarm-plugin
    • None
    • Jenkins ver. 2.194
      Self-Organizing Swarm Plug-in Modules 3.17
      swarm-client-3.17.jar

      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
      

          [JENKINS-59305] Swarm Client failed to create a slave with response code: 403

          Daniel Beck added a comment -

          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

          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

          danielbeck, 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.

          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 danielbeck , 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.

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

              Created:
              Updated:
              Resolved: