Serving resources from Jenkins

3 minute readSecurity

Jenkins serves many user-created files that may not be not fully trusted, such as files in project workspaces or archived artifacts. By default, Jenkins only serves these files with the HTTP header Content-Security-Policy ("CSP") set to a value that disallows many modern web features, in order to prevent cross-site scripting attacks on Jenkins users who access these files. While the specific value for the CSP header is user-configurable and can be disabled, doing so is a trade-off between security and functionality.

The Resource host option in the master provisioning configuration settings enables Jenkins to serve user-generated static resources like workspace files or archived artifacts without the need for CSP headers. If you configure this option, Jenkins redirects requests for user-created resource files to URLs constructed using the hostname you configure.

To use this option, you should keep the following things in mind:

  • The Jenkins root URL must be configured as a different URL than the resource root. It requires a different host name.

  • Jenkins only serves resource URL requests via the resource root URL. All other requests receive HTTP 404 Not Found responses.

  • The resource root URL must be equivalent to the Jenkins root URL. If there were no restrictions on responses, the resource root URL would be a valid alternative to the Jenkins root URL.

Once you have configured the URL, Jenkins redirects requests to workspaces, archived artifacts, and similar collections of files to URLs that start with the resource root URL. Instead of a path like job/name_here/ws</code>, resource URLs contain a long hexadecimal string encoding that path, the user for which the URL was created, and when the URL was created. These resource URLs access static files as if the user for which they were created was accessing them. If the user’s permission to access the files is removed, the corresponding resource URLs would not have access either.

Security considerations

You should consider the following:

  • Resource URLs do not require authentication. Users do not have a valid session for the resource root URL. Also, sharing a resource URL with another user, even one lacking Overall/Read permissions from Jenkins, grants that user access to these files until the URLs expire.

  • Resource URLs expire after 30 minutes, by default. Expired resource URLs redirect users to the equivalent Jenkins URLs so that users can authenticate again, if necessary. Then they redirect users to a new resource URL that is valid for another 30 minutes. This is generally transparent to users if they have a valid Jenkins session. If they do not have a valid session, they will have to authenticate with Jenkins again.

    The login form cannot appear in an HTML frame. If you are viewing HTML pages with frames, you must reload the top-level frame to make the login form appear.
  • Resource URLs encode the URL, the user for which they were created, and their creation timestamp. Additionally, this string contains a hash-based message authentication code (HMAC) to verify the authenticity of the URL to prevent attackers from forging URLs and obtaining access to resource files as if they were another user.

Configuring the resource host

To configure a cluster-wide resource host for your managed controllers:

  1. Configure a new DNS route with a CNAME (alias) for your resource domain to your current Jenkins domain. You can select any domain, as long as it is different from the main CloudBees CI domain.

    If you are using a wildcard DNS entry, you can skip this step.

  2. In Operations Center, browse to Manage Jenkins Configure Master Provisioning.

  3. In the Resource host field, enter the domain you want to configure as the resource host.

  4. Click Save, and then restart any existing managed controllers that use this endpoint for the change to take effect.

The resource host configuration is applied to any of the managed controllers using this provisioning endpoint, resulting in the following:

  • Each managed controller gets an additional ingress entry using the alternate domain.

  • The managed controller is configured with a matching Resource Root URL, just like you would normally configure manually for other classes of controller.