Skip to main content

Integrating Scribe in your Jenkins pipeline

If you are using Jenkins as your Continuous Integration tool (CI), use these instructions to integrate Scribe into your pipeline to protect your projects.

Before you begin

Acquiring credentials from Scribe Hub

Integrating Scribe Hub with Jenkins requires the following credentials that are found in the product setup dialog. (In your Scribe Hub go to Home>Products>[$product]>Setup)

  • Product Key
  • Client ID
  • Client Secret

Note that the product key is unique per product, while the client ID and secret are unique for your account.

Adding Credentials to Jenkins

  1. Go to your Jenkins Web Console.

  2. Select Dashboard> Manage Jenkins> Manage credentials (under Security options).

  3. Go to the Global Credential setup: click on any one of the clickable Global Domains in the Domain column.

  4. To add global credentials, in the Global credentials area, click + Add Credentials. A new Credentials form opens.

  5. To add the Product Key, in the Kind field, select Secret Text.

  6. Copy the Product Key provided by Scribe to the Secret field.

  7. Set the ID as scribe-product-key (lowercase).

  8. Leave Scope as Global.

  9. Add a helpful Description to manage your secrets.

  10. Click Create. A New Global credential is created, as a Secret Text (Kind). A key sign on your new credential row indicates the secret Kind.

  11. To add Client ID and Client Secret, click + Add Credentials again.

  12. In the Kind field, select Username with password.

  13. Set ID to scribe-production-auth-id (lowercase).

  14. Copy the Client ID provided by Scribe to the Username.

  15. Copy the Client Secret provided by Scribe to the Password.

  16. Leave Scope as Global.

  17. Click Create.

  18. Another Global credential is created as a Username with Password (Kind)

The final state of the secrets definition should be as shown in the following screenshot: Jenkins Credentials

Avoiding costly commits

To avoid potentially costly commits, we recommended adding the Scribe output directory to your .gitignore file. By default, add **/scribe to your .gitignore.

Procedure

Scribe installation includes Command Line Interpreter (CLI) tools. Scribe provides the following a CLI tool called Valint. This tool is used to generate evidence in the form of SBOMs as well as SLSA provenance.

Every integration pipeline is unique. Integrating Scribe's code into your pipeline varies from one case to another.

The following are examples that illustrate where to add Scribe code snippets.

The code in these examples of a workflow executes these steps:

  1. Calls valint right after checkout to collect hash value evidence of the source code files and upload the evidence.
  2. Calls valint to generate an SBOM from the final Docker image and upload the evidence.

The examples use a sample pipeline building a Mongo express project.

Jenkins over Docker

Prerequisites

Procedure

Sample integration code
pipeline {
agent any
environment {
SCRIBE_PRODUCT_KEY = credentials('scribe-product-key')
}
stages {
stage('checkout') {
steps {
cleanWs()
sh 'git clone -b v1.0.0-alpha.4 --single-branch https://github.com/mongo-express/mongo-express.git mongo-express-scm'
}
}

stage('sbom') {
agent {
docker {
image 'scribesecuriy.jfrog.io/scribe-docker-public-local/valint:latest'
reuseNode true
args "--entrypoint="
}
}
steps {
withCredentials([usernamePassword(credentialsId: 'scribe-staging-auth-id', usernameVariable: 'SCRIBE_CLIENT_ID', passwordVariable: 'SCRIBE_CLIENT_SECRET')]) {
sh '''
valint bom dir:mongo-express-scm \
--context-type jenkins \
--output-directory ./scribe/valint \
--product-key $SCRIBE_PRODUCT_KEY \
-E -U $SCRIBE_CLIENT_ID -P $SCRIBE_CLIENT_SECRET
'''
}
}
}

stage('image-bom') {
agent {
docker {
image 'scribesecuriy.jfrog.io/scribe-docker-public-local/valint:latest'
reuseNode true
args "--entrypoint="
}
}
steps {
withCredentials([usernamePassword(credentialsId: 'scribe-staging-auth-id', usernameVariable: 'SCRIBE_CLIENT_ID', passwordVariable: 'SCRIBE_CLIENT_SECRET')]) {
sh '''
valint bom mongo-express:1.0.0-alpha.4 \
--context-type jenkins \
--output-directory ./scribe/valint \
--product-key $SCRIBE_PRODUCT_KEY \
-E -U $SCRIBE_CLIENT_ID -P $SCRIBE_CLIENT_SECRET'''
}
}
}
}
}

See Also

Jenkins over Docker documentation

Jenkins over Kubernetes (K8s)

Prerequisites

Jenkins over Kubernetes installed.

Procedure

Sample integration code
pipeline {
agent {
kubernetes {
yamlFile 'jenkins/k8s/scribe-test/KubernetesPod.yaml'
}
}
environment {
SCRIBE_PRODUCT_KEY = credentials('scribe-product-key')
}
stages {
stage('checkout-bom') {
steps {
container('git') {
sh 'git clone -b v1.0.0-alpha.4 --single-branch https://github.com/mongo-express/mongo-express.git mongo-express-scm'
}

container('valint') {
withCredentials([usernamePassword(credentialsId: 'scribe-staging-auth-id', usernameVariable: 'SCRIBE_CLIENT_ID', passwordVariable: 'SCRIBE_CLIENT_SECRET')]) {
sh '''
valint bom dir:mongo-express-scm \
--context-type jenkins \
--output-directory ./scribe/valint \
-E -U $SCRIBE_CLIENT_ID -P $SCRIBE_CLIENT_SECRET \
--product-key $SCRIBE_PRODUCT_KEY'''
}
}
}
}

stage('image-bom') {
steps {
container('valint') {
withCredentials([usernamePassword(credentialsId: 'scribe-staging-auth-id', usernameVariable: 'SCRIBE_CLIENT_ID', passwordVariable: 'SCRIBE_CLIENT_SECRET')]) {
sh '''
valint bom mongo-express:1.0.0-alpha.4 \
--context-type jenkins \
--output-directory ./scribe/valint \
-E -U $SCRIBE_CLIENT_ID -P $SCRIBE_CLIENT_SECRET \
--product-key $SCRIBE_PRODUCT_KEY'''
}
}
}
}
}
}

This example uses Jenkins over k8s plugin with the Pod template defined like this:

metadata:
labels:
some-label: jsl-scribe-test
spec:
containers:
- name: jnlp
env:
- name: CONTAINER_ENV_VAR
value: jnlp
- name: valint
image: scribesecuriy.jfrog.io/scribe-docker-public-local/valint:latest
command:
- cat
tty: true
- name: git
image: alpine/git
command:
- cat
tty: true

See Also

Jenkins over Kubernetes documentation

Jenkins Vanilla (No Agent)

Prerequisites

curl installed on your build node in jenkins.

Procedure

Sample integration code
pipeline {
agent any
environment {
SCRIBE_PRODUCT_KEY = credentials('scribe-product-key')
PATH="./temp/bin:$PATH"
}
stages {
stage('install') {
steps {
cleanWs()
sh 'curl -sSfL https://raw.githubusercontent.com/scribe-security/misc/master/install.sh | sh -s -- -b ./temp/bin'
}
}
stage('checkout') {
steps {
sh 'git clone -b v1.0.0-alpha.4 --single-branch https://github.com/mongo-express/mongo-express.git mongo-express-scm'
}
}

stage('sbom') {
steps {
withCredentials([usernamePassword(credentialsId: 'scribe-staging-auth-id', usernameVariable: 'SCRIBE_CLIENT_ID', passwordVariable: 'SCRIBE_CLIENT_SECRET')]) {
sh '''
valint bom dir:mongo-express-scm \
--context-type jenkins \
--output-directory ./scribe/valint \
--product-key $SCRIBE_PRODUCT_KEY \
-E -U $SCRIBE_CLIENT_ID -P $SCRIBE_CLIENT_SECRET
'''
}
}
}

stage('image-bom') {
steps {
withCredentials([usernamePassword(credentialsId: 'scribe-staging-auth-id', usernameVariable: 'SCRIBE_CLIENT_ID', passwordVariable: 'SCRIBE_CLIENT_SECRET')]) {
sh '''
valint bom mongo-express:1.0.0-alpha.4 \
--context-type jenkins \
--output-directory ./scribe/valint \
--product-key testing \
-E -U $SCRIBE_CLIENT_ID -P $SCRIBE_CLIENT_SECRET'''
}
}
}
}
}