Ravindra BagaleCourses & study guides मराठी

Chapter 21: Jenkins Pipeline and Jenkinsfile

21.6 Optional: bind a credential by id (pattern only)

Why: the problem

Every real pipeline needs a secret. A token to push an image. A password for a database test. An SSH key for a server. Think of PhonePe. If one token leaks in a build log, an attacker can push a bad image to production. So the rule is strict. The secret lives only in Jenkins credentials, encrypted. The Jenkinsfile only knows the credential ID, a plain name like registry-login. At run time Jenkins puts the secret in an environment variable for a short time and hides it in the log with stars. In this lesson you will create three kinds of credentials, use them with withCredentials and with the credentials() helper, and prove that the log never shows the value. All values in this lesson are fake lab values.

What we will build

You will add a secret text, a username and password, and an SSH key in Jenkins. You will write three stages that use them safely. You will try to print a secret and see Jenkins mask it. You will learn the Groovy string trap that leaks secrets.

What: every term in plain English

  • Credential — A secret stored by Jenkins, like a token, password or key.
  • Credential ID — The plain name you use in the Jenkinsfile. Not secret.
  • Secret text — One secret string, like an API token.
  • Username with password — A pair, like a registry login.
  • SSH Username with private key — A key to log in to servers.
  • withCredentials — A step that puts a secret in a variable only inside its block.
  • credentials() — A helper in environment that binds a credential to a variable.
  • Masking — Jenkins replaces the secret with **** in the log.
Add a secret text Add a username and password Add an SSH key Install the plugin Use them Check the log
Credential ID to masked variable inside a block

How: step by step

  1. Add a secret text

    Manage Jenkins > Credentials > System > Global > Add > Kind: Secret text > Secret: lab-fake-token-123 > ID: api-token
    

    What it does: Stores a fake lab token.

    Output

    api-token created
    
  2. Add a username and password

    Add > Username with password > Username: ci-bot > Password: lab-fake-pass > ID: registry-login
    

    What it does: A fake registry login.

    Output

    registry-login created
    
  3. Add an SSH key

    Add > SSH Username with private key > Username: deploy > Key: paste lab key > ID: lab-ssh
    

    What it does: A key for the lab server.

    Output

    lab-ssh created
    
  4. Install the plugin

    Manage Jenkins > Plugins > Credentials Binding, SSH Agent
    

    What it does: Gives withCredentials and sshagent.

    Output

    Success
    
  5. Use them

    Write the Jenkinsfile from the examples
    

    What it does: Each stage binds only what it needs.

    Output

    (file saved)
    
  6. Check the log

    Console Output
    

    What it does: Secrets show as ****.

    Output

    curl -H Authorization: Bearer ****
    

Example 1: Secret text with withCredentials

Stack. Credentials Binding plugin

Goal. Secret text with withCredentials.

Jenkinsfile

pipeline {
  agent any
  stages {
    stage('Call API') {
      steps {
        withCredentials([string(credentialsId: 'api-token', variable: 'TOKEN')]) {
          sh 'curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $TOKEN" https://httpbin.org/bearer'
          sh 'echo "token is $TOKEN"'
        }
      }
    }
  }
}

What each line does

  • withCredentials([...]) — Opens a block where the secret exists.
  • string(credentialsId: 'api-token', variable: 'TOKEN') — Secret text into the TOKEN variable.
  • sh '...$TOKEN...' — Single quotes: the shell reads TOKEN. Groovy never sees the value.
  • echo token — Even a print is masked.

Green output

[Pipeline] withCredentials
Masking supported pattern matches of $TOKEN
+ curl -s -o /dev/null -w %{http_code} -H Authorization: Bearer **** https://httpbin.org/bearer
200
+ echo token is ****
token is ****
Finished: SUCCESS

Expected result. The value was used and never shown.

Example 2: Username and password with credentials() in environment

Stack. Jenkins, Docker

Goal. Username and password with credentials() in environment.

Jenkinsfile

pipeline {
  agent any
  environment {
    REG = credentials('registry-login')
  }
  stages {
    stage('Login') {
      steps {
        sh 'echo "user is $REG_USR"'
        sh 'echo "$REG_PSW" | docker login registry.example.com -u "$REG_USR" --password-stdin'
      }
    }
  }
  post { always { sh 'docker logout registry.example.com || true' } }
}

What each line does

  • credentials('registry-login') — Binds the pair to REG.
  • REG_USR and REG_PSW — Jenkins makes these two extra variables.
  • --password-stdin — Password goes in through a pipe, not the command line.
  • docker logout — Removes the saved login after the build.

Green output

+ echo user is ****
user is ****
+ echo ****
+ docker login registry.example.com -u **** --password-stdin
Login Succeeded
+ docker logout registry.example.com
Removing login credentials for registry.example.com

Expected result. Even the username is masked, because it is part of the credential.

Example 3: The Groovy string trap, and SSH key use

Stack. SSH Agent plugin

Goal. The Groovy string trap, and SSH key use.

Jenkinsfile (bad and good)

pipeline {
  agent any
  stages {
    stage('Bad') {
      steps {
        withCredentials([string(credentialsId: 'api-token', variable: 'TOKEN')]) {
          sh "curl -H 'Authorization: Bearer ${TOKEN}' https://httpbin.org/bearer"
        }
      }
    }
    stage('SSH') {
      steps {
        sshagent(credentials: ['lab-ssh']) {
          sh 'ssh -o StrictHostKeyChecking=accept-new deploy@10.0.1.20 "hostname && uptime"'
        }
      }
    }
  }
}

What each line does

  • sh "...${TOKEN}..." — Double quotes: Groovy puts the secret into the command text. Jenkins warns.
  • Fix — Use single quotes and $TOKEN so the shell reads it.
  • sshagent(credentials: ['lab-ssh']) — Loads the key into an SSH agent only for this block.
  • accept-new — Trusts a new host once, then checks it later.

Green output

Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
         Affected argument(s) used the following variable(s): [TOKEN]
[Pipeline] stage (SSH)
[ssh-agent] Using credentials deploy (lab-ssh)
+ ssh -o StrictHostKeyChecking=accept-new deploy@10.0.1.20 hostname && uptime
lab-web-01
 10:52:11 up 3 days,  2:10,  0 users,  load average: 0.04, 0.03, 0.00
Finished: SUCCESS

Expected result. Read the warning. Always use single quotes with secrets.

Example 4: Secret file credential for a kubeconfig

Stack. Credentials Binding, kubectl

Goal. Secret file credential for a kubeconfig.

Jenkinsfile

pipeline {
  agent any
  stages {
    stage('Cluster check') {
      steps {
        withCredentials([file(credentialsId: 'lab-kubeconfig', variable: 'KUBECONFIG')]) {
          sh 'kubectl get nodes -o wide'
          sh 'ls -l "$KUBECONFIG"'
        }
        sh 'echo "after block: ${KUBECONFIG:-gone}"'
      }
    }
  }
}

What each line does

  • file(credentialsId: ...) — A Secret file credential. Jenkins writes it to a temp file.
  • variable KUBECONFIG — kubectl reads this variable to find its config.
  • ls -l — Shows the temp path, masked.
  • after block — The temp file is deleted and the variable is gone.

Green output

+ kubectl get nodes -o wide
NAME        STATUS   ROLES           AGE   VERSION
lab-node1   Ready    control-plane   12d   v1.30.2
+ ls -l ****
-r-------- 1 jenkins jenkins 5521 Oct 25 10:58 ****
+ echo after block: gone
after block: gone
Finished: SUCCESS

Expected result. Files like kubeconfig or a service account JSON work the same way. They exist only inside the block.

Verify: did it work?

  1. Search the log for secrets

    curl -s -u admin:API_TOKEN http://localhost:8080/job/badge-scm/lastBuild/consoleText | grep -c lab-fake
    

    What it does: Counts raw secret hits in the log. Must be 0.

    Output

    0
    
  2. List credential IDs

    Manage Jenkins > Credentials
    

    What it does: Shows IDs, never values.

    Output

    api-token, registry-login, lab-ssh
    

When it is red 1

ERROR: Could not find credentials entry with ID 'api-tokn'

Cause. The ID is misspelled or in another folder scope.

Fix, step by step

  1. Copy the ID from the Credentials page.
  2. Check folder credentials.

When it is red 2

Warning: A secret was passed to "sh" using Groovy String interpolation

Cause. Double quotes with a secret.

Fix, step by step

  1. Switch to single quotes.
  2. Use $VAR not ${VAR} in Groovy.

When it is red 3

No such DSL method 'sshagent' found

Cause. SSH Agent plugin missing.

Fix, step by step

  1. Install it.
  2. Restart Jenkins.

When it is red 4

Permission denied (publickey)

Cause. Wrong key or the public key is not on the server.

Fix, step by step

  1. Add the public key to authorized_keys.
  2. Check the username.

Cleanup

  1. Delete lab credentials

    Manage Jenkins > Credentials > api-token > Delete (repeat)
    

    What it does: Removes the fake lab secrets.

    Output

    Deleted
    
  2. Rotate real tokens

    Make a new token at the provider, update the credential, revoke the old one
    

    What it does: Rotation limits damage if a token leaks.

    Output

    Token revoked
    

Ravindra Bagale's Tip

Jenkinsfile madhe fakt ID. Secret sathi single quotes. Double quotes mhanje dhoka. Lakshat theva!

Practice tasks

Easy Add three credentials

Why: Every pipeline needs them.

What to do: Create the three fake ones.

How:
  1. Use clear IDs.

Check: All three listed.

Medium Use with single quotes

Why: Avoid the leak.

What to do: Write the API stage.

How:
  1. Check for ****.

Check: No raw value in log.

Hard Find the warning

Why: Spot leaks in reviews.

What to do: Use double quotes once.

How:
  1. Read the warning.

Check: You can explain it.

Easy Say credentials in a Jenkinsfile in two lines

Why: If you can say it simply, you understand it. Juniors and interviewers want the short version first.

What to do: Write two short lines about credentials in a Jenkinsfile for a fresher who knows only Linux basics.

How:
  1. Write what problem it solves.
  2. Write the one command or menu you use for it.
  3. Read it aloud to a friend.

Check: A fresher understands it without asking a question.

Easy Start a fresh lab Jenkins

Why: Practice needs a throwaway Jenkins. If you break it, you delete it and start again.

What to do: Run Jenkins LTS in Docker with a named volume.

How:
  1. docker volume create jenkins_home
  2. docker run -d --name jenkins -p 8080:8080 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk17
  3. docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Check: The Jenkins unlock page opens on localhost:8080.

Medium Break it on purpose

Why: You must know the red message by face. During an outage there is no time to read slowly.

What to do: Cause one error from the "When it is red" part of this lesson and fix it.

How:
  1. Follow the error section.
  2. Copy the exact message into your notes.
  3. Write the fix in one line.

Check: You fixed it using only the steps, without searching the web.

Medium Write a one-page runbook

Why: At 2 a.m. nobody remembers where a file lives. A short page saves the on-call person.

What to do: Write a runbook page for this lesson.

How:
  1. Title, when to use, exact command, how to check, how to undo.

Check: A teammate can follow it alone.

Medium Repeat it on a cloud VM

Why: A laptop is not a server. Real Jenkins runs on EC2 or a company VM.

What to do: Do the main steps of this lesson again on a small Ubuntu 22.04 EC2 instance.

How:
  1. Launch t3.small with 20 GB disk.
  2. Open port 22 only to your IP.
  3. Repeat the steps and compare the output.

Check: Same green output on the VM as on your laptop.

Hard Explain it like an interview

Why: Interviewers want real stories, not definitions.

What to do: Record a 60 second answer about this lesson.

How:
  1. Say the problem, the command you ran, and one error you hit.

Check: Your answer has a real command and a real error message.

Hard Draw the flow top to bottom

Why: A drawing shows who talks to whom and in what order.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at the developer push, go through the controller and agent, end at the result.

Check: Each box matches a real thing you saw on screen.

Homework: try at home

Try at home

At home, add a fake secret text, use it with withCredentials in single quotes, then try double quotes and read the warning. Screenshot both.

Recap

  • Secrets live in Jenkins credentials.
  • The Jenkinsfile only has the ID.
  • Use withCredentials or credentials().
  • Always single quotes in sh.
  • Rotate tokens and log out after use.

FAQ

Is masking enough?

No. A script can still leak a secret by encoding it. Limit who can edit Jenkinsfiles.

Folder or global credentials?

Folder credentials limit a secret to one team.

Can I use a vault?

Yes, with plugins for HashiCorp Vault or AWS Secrets Manager.

Why not environment variables on the agent?

They are not masked and anyone on the agent can read them.

What about cloud keys?

Prefer IAM roles on the agent instead of stored keys.

Interview questions

  1. How do you use secrets in a Jenkinsfile?

    Store them as credentials and bind by ID with withCredentials or credentials(), using single quoted sh.

  2. What is the Groovy interpolation risk?

    Double quoted strings put the secret value into the command text, which can leak in process lists.

  3. How do you log in to a registry safely?

    Pipe the password with --password-stdin and log out in post always.

  4. How do you SSH from Jenkins?

    sshagent with an SSH key credential and host key checking.

  5. A token leaked in a log. What now?

    Revoke it, rotate it, delete the build log, find the cause.

Quick quiz

Q1. What goes in the Jenkinsfile, the secret or the ID?

The ID.

Q2. Which quotes are safe with secrets in sh?

Single quotes.

Q3. What variables does credentials() make for a username and password?

NAME_USR and NAME_PSW.

Q4. How does Jenkins hide secrets?

It masks them with ****.

Q5. Which step loads an SSH key?

sshagent.

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards