Avoid printing passwords in Jenkins console - jenkins

We have Jenkins stage which is calling a "GetVMPassword" function from library. The function returns credential and it will be used to login remote server. We dont want to print the "ssh command" and "calling a funtion command" and its reponse on stage logs. So we used ā€˜#!/bin/sh -e \nā€™ before every command. Because if we print, this could reveal the remote server credentials in the stage log. This was working when we don't use "parallel execution" block.
When we include "ssh command" and "calling a function command" inside "parallel execution" block, passwords are printed in stage logs.
How can we avoid printing in stage logs the library command and its response when we use "parallel execution" block ?
This is snippet of my stage and parallel execution block.
Jenkins Version: 2.235.3
#Library ('MyLib_API') _
pipeline{
agent {
label 'master'
}
stages{
stage('BuildAll'){
steps{
script{
def executions = APPSERVERS.split(',').collectEntries {APPS ->
["Execution ${APPS}": {
stage(APPS) {
APP_USERNAME = "ubuntu"
response = getPassword("${APPS}","${APP_USERNAME}")
sh '#!/bin/sh -e \n' + "sshpass -p '${response}' ssh -o StrictHostKeyChecking=no ${APP_USERNAME}#${APPS} 'ls'"
sleep 2
}
}]
}
parallel executions
}
}
}
}
}
"getPassword" is the function in library used to get the vm password dynamically.
"APPSERVERS" values we are getting from Active choice parameters option.This has list of IP's of servers.
Please help me to hide those library commands and responses from stage logs.
We have tried below options.
Used set +x and it is not worked for us.
Password masking plugin will not work. Since response from the command will get print for our case.
We tried routing all the execution of commands to file and tried fetching it from there. In this option, also while parsing the file logs are printed in stage logs.

Try starting your script with set +x, if not use password masking plugins
as mentioned here - https://issues.jenkins.io/browse/JENKINS-36007

You can use input to pass the credential and mask it in log.
Here is a detailed answer stackoverflow credentials masking
you can use this as well it works for me.
node('Node Name'){
println('Please enter the username')
def userName = input(
id: 'userName', message: 'VPN Username', parameters: [
[$class: 'hudson.model.TextParameterDefinition', defaultValue :'', name: 'Username', description: 'Please enter your username']
])
println('Please enter the password')
def userPassword = input(
id: 'userPassword', message: 'VPN Password', parameters: [
[$class: 'hudson.model.PasswordParameterDefinition', defaultValue :'', name: 'Password', description: 'Please enter your password']
])
connectToClient = bat(returnStdout: true, script: 'start Forticlient connect -h v3 -u ' + userName+ ':' + userPassword)
stage('Deploy (Test)'){
withCredentials([usernamePassword(credentialsId: 'IH_IIS_JENKINS', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
bat"msdeploy command"
}
}
}

Related

Jenkins - Hide sensitive data from pipeline steps page (flowGraphTable)

I am writing a sensitive data to a .yml file as a string in my Jenkins groovy file. I have attached the .groovy file which would show what I am trying to achieve but it reveals the data in Pipeline steps which is also attached. Nothing shows in the console log. Value from AWS Parameter store is retrieved and passed as a string to a .yml file and this string value is shown in the pipeline steps. I am looking for a way to hide this from being shown in the Pipeline steps. I have tried using set +x but it is not hiding the string value in the pipeline steps. Any thoughts on how this can be achieved would be of great help.Screenshot
#!/usr/bin/env groovy
properties([
parameters([
string(name:'NODE_NAME', defaultValue: 'node', description: 'Node Name')
])
])
nodeName = params.NODE_NAME
node("${nodeName}") {
def AWS_REGION = "eu-west-2"
def paramPath = "path"
def paramName = "PASSWORD"
stage("Data from SSM") {
param = sh (script: "aws ssm get-parameter --name ${paramPath} --with-decryption --region ${AWS_REGION} | /var/jenkins_home/tools/jq .Parameter.Value | tr -d '\"'", returnStdout: true).trim()
sh('#!/bin/sh -e\n' + "echo '${paramName}: ${param}' >> vars.yml")
}
}
You can make use of credentials in jenkins. Go to Jenkins -> credentials -> global -> add credentials
Select either 'Username with password'/'secret text' depending on your need
This will generate a secret in jenkins
Then in your groovy file you can use the credentials as env variables which will not be printed by jenkins
withCredentials([usernamePassword(credentialsId: 'Your-Credential-ID', passwordVariable: 'pwdToken', usernameVariable: 'userToken')]){
//Use pwdToken as a variable here which will not be printed
}

Jenkins Pipeline Displays Password in Plaintex

I am retrieving the username password from the credentials plugin.
The values are then saved as environmental variables. I am using the password in later stages of the pipeline, in sh block as an argument for curl.
At this point the password is displayed in plaintext in the build logs. Is there a way to avoid this? I assumed by using the credentials plugin the password will be masked.
pipeline {
stages {
stage ('One') {
steps {
withCredentials([userNamePassword(credentialsId: 'my_cred', userNameVariable: 'User_Name', passwordVariable: 'Password')]){
env.User_Name = User_Name
env.Password = Password
}
}
}
stage ('Two') {
sh '''
curl -v -u ${User_Name}:${Password} ...
'''
}
}
}
Note: I am using the curl to upload a file to a remote host.
Thats true. The password will be displayed in plaintext.
The best way for your request, ist to use the HTTP Request Plugin.
You can pass credentials in "Authorization" in the Header inestead of URL.
I ended up using the curl inside the withCredentialsblock.
withCredentials([userNamePassword(credentialsId: 'my_cred', userNameVariable: 'User_Name', passwordVariable: 'Password')]){
sh '''
curl -v -u ${User_Name}:${Password} ...
'''
}

Need to get user email id as input and send logs in jenkins

I have a shell script wil runs on taking user inputs and send logs to users when fails syntax I use: ./script.sh env usecase emailid
Now am doing a jenkins build and not sure on how to get user input for email id . I am currently getting 2 inputs using choice parameter.
I want user to give email id and its passed as a parameter .
#Library('Shared#release/v1')
import jenkins.BuildSupport
properties([parameters([choice(choices: ['dev''uat', 'prod'], description: 'Select the Environment', name: 'ENVIRONMENT'), choice(choices: ['a1','a2','all'], description: 'Select the Service', name: 'SERVICENAME')])])
node{
WORKSPACE = pwd()
//checkout code from shared library
stage ('Code Checkout'){
codeCheckout
}
//post build work
stage('Executing Health Check') {
withEnv(["WORKSPACE=${WORKSPACE}","ENVIRONMENT=${params.ENVIRONMENT}","SERVICENAME=${params.SERVICENAME}",]) {
sh '''
set +x
ls -l
./script.sh ${ENVIRONMENT} ${SERVICENAME}
'''
}
}
}
I need the script.sh to take 3rd parameter which will be the email id entered by user
So couple of things going on here. First, you need to add a string parameter to ask the user for input, then you need to pass that to the shell script, and then you need to make sure the shell script can use it.
I don't see the need for withEnv, you can pass variables to a script without that.
Just make sure your shell script is getting the EMAIL_ADDRESS from $3
#!groovy
#Library('Shared#release/v1')
import jenkins.BuildSupport
properties([parameters([string(name: 'EMAIL_ADDRESS', description: 'Enter the email address'), choice(choices: ['dev','uat','prod'], description: 'Select the Environment', name: 'ENVIRONMENT'), choice(choices: ['a1','a2','all'], description: 'Select the Service', name: 'SERVICENAME')])])
node{
WORKSPACE = pwd()
//checkout code from shared library
stage ('Code Checkout'){
codeCheckout
}
//post build work
stage('Executing Health Check') {
sh '''
set +x
ls -l
./script.sh $ENVIRONMENT $SERVICENAME $EMAIL_ADDRESS
'''
}
}
Example of sending email from Jenkins scripted pipeline/ Groovy
stage('Email the results') {
emailext attachLog: true,
attachmentsPattern: '*',
to: "${EMAIL_ADDRESS}",
subject: "${currentBuild.currentResult} - ${ENVIRONMENT} ${SERVICE}",
body: """
Blah blah blah
"""
}

How to run Ansible playbook with user input within Jenkins?

I have a playbook with section "pause" and prompt. If I create job within Jenkins with Pipeline plugin and run this job I get
[WARNING]: Not waiting from prompt as stdin is not interactive
and job is failed. The question is how I can run job in interactive mode or how I can pause playbook within exact task and push combination Ctrl+c+c (because ansible module 'pause' is working only like that)? I have googled a few time and tried to do that with
def userInput = input(
id: 'Password', message: 'input your input: ', ok: 'ok',
parameters: [string(defaultValue: '', description: '.....', name: 'INPUT_TEST')])
But I can't push keys combination and can't understand how I can pause jenkins job on specific ansible task within playbook.
Pipeline example:
pipeline {
agent { label 'master' }
environment {
WORKDIR = '/home/jenkins/'
}
stages {
stage('Checkout') {
agent { label 'master' }
steps {
sh '''cd $WORKDIR
ansible-playbook -vvvv manual_playbooks/test.yml'''
}
}
stage ('Echo') {
agent { label 'master' }
steps {
sh 'echo something'
}
}
}
}
Playbook example:
---
- name: test
hosts: localhost
tasks:
- name: Echo start
shell: echo 'start playbook'
- pause:
prompt: "do you want to continue?"
echo: yes
private: no
register: prompt_status
- name: Continue tasks
shell: echo 'Continue full flow'
register: reset_account_response
when: prompt_status.user_input is defined and
prompt_status.user_input == "yes"
- fail:
msg: "Unexpected user input while prompting approval"
when: prompt_status.user_input is defined and
prompt_status.user_input != "yes"
Many thanks.
Why not put a when clause on your pause task to check for the existence of some other variable and then pass that in using Ansible's -e option when running the playbook through Jenkins.

How to restrict the users that can run jenkinsfile tests in pull requests?

I have deployed the pipeline-as-code docker demo with multibranch.
It works alright. I added my github username as the organization and when I make a pull request, the tests are run.
However, when some other user makes a pull request, their tests are also run. I would like to manually approve which pull requests from external contributors are good to run in my jenkins server. Is there a way to do that?
I can do it with ghprb, but it is not compatible with pipelines, and I want to migrate my jobs to pipelines.
please try adding these lines in your pipeline script:
node('slaveName') {
properties([
parameters([
string(
defaultValue: 'whitelisted1#gmail.com,whitelisted2#gmail.com',
description: 'comma separated whitelisted emails',
name: 'WHITELIST'
)
])
])
def authorEmail
stage('Git') {
authorEmail = sh([
// git log format docs here: https://git-scm.com/docs/pretty-formats
script : "git log -1 --format='%aE'",
returnStdout: true
]).trim()
boolean allowRun = isWhitelisted(env.WHITELIST, authorEmail)
if (allowRun) {
echo "email ${authorEmail} is whitelisted, proceed execution"
} else {
echo "email ${authorEmail} is not in whitelist ${env.WHITELIST}, proceed jenkins job?"
input message: 'Proceed?'
// or just abort build with non-zero shell exit
// currentBuild.result = 'FAILURE'
// sh "exit 10"
}
}
}
}
#NonCPS
boolean isWhitelisted(whitelist, email) {
def res = whitelist.tokenize(" ,;").find { white -> white == email }
return null != res
}

Resources