secure your pipeline

CI/CD Servers Know All Your Plumbing Secrets

How to Secure Your CI/CD Pipeline Secrets with the Conjur Credentials Plugin for Jenkins Pipelines

The DevOps culture shift and the move to continuous integration and deployment have required different tooling and utilities than previous development methodologies. One of the emerging heroes in this movement has been Jenkins. Many organizations have chosen to use Jenkins to manage their build and deployment pipelines.

In this article, we’re going to be talking about security considerations around using Jenkins, and we’ll identify ways to protect sensitive information, authorization credentials, and other secrets. We’ll introduce you to the Conjur plugin for Jenkins which allows you to remove secrets from your pipeline altogether and better manage and protect your enterprise systems.

Securing Jenkins and Managing Your Secrets

Jenkins is a versatile tool for build systems and CI/CD pipelines. As a tool, it is highly configurable and supports the use of plugins to extend its functionality further. Unfortunately, those advantages also make it challenging to secure, and moreover, find the right combination of who can use Jenkins, what Jenkins can do, and where Jenkins can deploy its artifacts.

Your Jenkins installation includes a central credentials store where you can enter and manage different credentials for your pipelines to use. Jenkins jobs can access these credentials at runtime, and the server obscures their usage in the output from each job. Unfortunately, since jobs and plugins can access the credentials on the Jenkins server, they are at risk of exposure due to accidental or malicious actions on the server.

An additional challenge with credentials stored on your Jenkins server is that you need to manage them on each Jenkins instance. For large organizations, this creates a maintenance and management nightmare. The solution for this is to use a central security service to manage sensitive credentials, and support identity management, encrypting, and role-based access control.

Conjur is an open source security service which meets these requirements and is backed by CyberArk, an industry leader in privileged access management, according to a 2018 report by Gartner Inc. Among the open source offerings related to Conjur, CyberArk has provided a Jenkins plugin which you can use to provide credentials to your Jenkins jobs at runtime. The plugin retrieves the credentials from the central Conjur service, which enhances the ability of the organization to secure and manage its secrets.

Installing the Conjur Credentials Plugin

The Conjur Credentials Plugin is managed in a GitHub repository. You can download and build the plugin from the source using Maven, or download the latest binary. You’ll need to log into the Jenkins server with an administrator account and navigate to Manage Jenkins > Manage Plugins.

Manage Jenkins Plugins

Click on the Advanced tab, and then upload the plugin file in the Upload Plugin section. Once you’ve uploaded the plugin, you’ll need to restart your server for the installation to complete and for the plugin to be available for your jobs to access.

Upload plugin to Jenkins

Supporting Jenkins from Conjur

Before we can connect the Jenkins server to the Conjur service, we need to set up a couple of things. First, we’ll need to add the Jenkins server as a host within Conjur.  We can do this with a policy similar to the one shown below. If you’d like to learn more about how Conjur uses policies to define and organize resources and establish their access rules, the Policy Documentation is a great place to start.

- !host

id: feature-team-jenkins-server

owner: !group devops-admin

annotations:

description: Jenkins CI/CD Server

After executing the host policy, Conjur returns the identifier for the host, and an API key in a format similar to the one below, which we’ll use to establish the connection from the Jenkins server.

{

"devops:host:jenkins/feature-team-jenkins-server": "33f0ppq87sy3gh16900b2mguvth2126nms278bk2qy3hrwdmna86qw"

}

We aren’t required to create any secrets at this point, but we’ll create a couple to save us from having to come back later and add them.  The policy below creates a pair of variables into which we can load access credentials from the AWS account.

Conjur also allows us to manage dynamic credentials such as those available from the AWS Secure Token Service (STS). Using dynamic tokens, such as those generated by STS, further secures your environment.

- !variable aws-access-key-id

- !variable aws-secret-access-key

 

- !permit

role: !host feature-team-jenkins-server

privileges:

- read

resource: !variable aws-access-key-id

resource: !variable aws-secret-access-key

We don’t want to include secret values in policy documents, so the values for these secrets are updated through an API call. You can learn more about the process of managing secrets through the API in the Conjur API documentation.

Connecting the Plugin to Conjur

Let’s go back to the Jenkins server, and use the host identifier and API key to connect Jenkins to Conjur. Log into the administrator account and navigate to Credentials > System and then click on the Global credentials store.

System credentials UI

We’ll Add Credentials of Kind Username with password. The username and password are the identifier and API key, which Conjur returned when we created the host.

add credentials to Jenkins

Return to the Jenkins home page and navigate to Manage Jenkins > Configure System. Scroll down to the section which configures the Conjur Appliance. You’ll need the name of your Conjur account, and the URL for the Conjur service. The credentials are those we defined above. If your Conjur system uses an SSL certificate, you can upload it and include it in the SSL Certificate field.

configure Jenkins UI

Using Secrets in Your Jenkins Project

The final step before we can use a secret from Conjur in a Jenkins project is to define the variable explicitly. Navigate to Credentials > System and then click on the Global credentials store again. We are going to Add Credentials of Kind Conjur Secret Credential. The Variable Path is the name of the variable which we defined in Conjur, and the ID is how you identify it on this Jenkins instance.

add credentials

You can now reference this secret in your Jenkins jobs and pipeline scripts as needed. The secrets themselves are managed and stored within the Conjur appliance, and the Conjur plugin facilitates sharing the value as required.

The following snippet from a pipeline script demonstrates how to access the secret we defined above.

node {

stage('Deploy') {

withCredentials([

conjurSecretCredential(

credentialsId: 'AWS_ACCESS_KEY', variable: 'ACCESS_KEY'),

conjurSecretCredential(

credentialsId: 'AWS_SECRET_KEY', variable: 'SECRET_KEY')

])

{

...

Next Steps

If you would like to find out more about Conjur Open Source, I’ve found the resources in the Getting Started and Documentation sections of the website to be invaluable. They also provide a collection of Tutorials on Conjur policy language, and on integrations and libraries which you can use to integrate your systems with Conjur.