CloudBees CI and Jenkins – Exploiting the Enterprise Pipeline

March 18, 2022 | 3 min read

BlueVoyant

Many organizations use CloudBees CI or Jenkins to orchestrate the Continuous Integration (CI) and Continuous Delivery (CD) process using an Enterprise Pipeline. The Enterprise Pipeline is a concept developed in shared libraries to allow businesses to write their process “as-code”. The Enterprise Pipeline is a combination of various scripts and integrations to glue the process together from idea to production.

This blog aims to educate DevOps teams on using secure patterns to enforce the use of the Enterprise Pipeline for CloudBees CI and Jenkins. A common pattern that is used at organizations allow developers to circumvent the Enterprise Pipeline. In the article below, we’ll walk-through two different patterns and how to remediate that vulnerability.

If you are exposing the Jenkinsfile to the development teams, you have a process that is ready to be exploited! The Jenkinsfile is not a properties file, it is the file that defines how the “Jenkins Job” interacts with the Pipeline Framework. In most circumstances, the developers will read the documentation provided by the DevOps team and leverage the Enterprise Pipeline to take advantage of the thought-out process. However, in rare cases, developers complain the Enterprise Pipeline limits them and their unique development practices. They feel the pipeline slows them down, and their "best practices" are the right way. This is when developers or teams go rogue and attempt to write their own CI/CD process. In many cases, they can succeed, but it requires in-depth knowledge of Jenkins, Pipeline, and the integrations.

The first pattern will expose the Jenkinsfile which allows the developers to interact with the shared library and write their own pipeline. Each pattern provides an example of a developer and their interactions with the pipeline. The first example, “Good Developer”, shows how most developers interact with the Enterprise Pipeline. The second example, “Clever Developer”, shows how a developer can alter the behavior of the Enterprise Pipeline. The second pattern will show how we can create a centralized Enterprise Pipeline remediating the vulnerability from the first pattern.

Pattern 1

The "PipelineInsecure.groovy" file is a sample shared library that uses the developer’s Jenkinsfile to modify the shared library behavior in a predictable way. The developers will provide key-value pairs in the application repo’s Jenkinsfile. In the examples below, you will see two examples that interact with the “PipelineInsecure.groovy” file.

Example 1 “Good Developer”:

In this example, the developer enables the build stage and sets the build tool to maven. They have all the capabilities of the shared library and are following the Enterprise Pipeline. The developer has included the shared library and invoked the “PipelineInsecure.groovy” on line 3 by providing the necessary parameters.

Example 2 “Clever Developer”:

In this example, the developer has included the shared library in the Jenkinsfile. The developer has decided to customize the Jenkinsfile and not invoke the approved library functions. The developer has complete control over the Jenkinsfile allowing them to interact with the controller, modify the pipeline, and enable different tools in a manner that is acceptable to them. This would allow them to circumvent the Enterprise Pipeline and potentially gain elevated permissions on the Jenkins or CloudBees CI controller. Allowing access to non-approved libraries provides risk of introducing malicious code to the application. Please review the Jenkinsfile and the build log below to see this in action.

Pattern 2

From my experience, one way is to use a properties file while centralizing the Jenkinsfile to prevent misuse. The Jenkinsfile below is in the shared library, forcing the developers to use a properties file. In the example below, I have used the "Pipeline Utility Steps" plugin to use the property file functionality. Looking at the build log below, you see the Pipeline ran similarly to the "Good Developer" example. I prefer this pattern because we eliminate a vulnerability while enforcing a secure Enterprise Pipeline.

The developers will only create a “Jenkinsfile.yaml”

Conclusion

We have reviewed two common patterns that the DevOps Engineers use to implement Enterprise Pipelines. The first pattern can be exploited by a developer being able to pass the Jenkinsfile in from their code repository. This allows the developer to interact with the controller, modify the pipeline, and enable non-approved tools in alternative ways. The second Enterprise Pipeline pattern provides a property file to the developers using the “Pipeline Utility Steps” plugin. This prevents the developers from interacting with the Jenkinsfile and allowed us to centralize and secure the Enterprise Pipeline.

If you found this blog interesting and need help architecting, implementing, or auditing your Enterprise Pipeline, we can help! We get code to production faster by improving process efficiency, reducing release anxiety, and enhancing the customer experience.