Jenkins mask passwords use in "Execute system Groovy script" - jenkins

im trying to undeploy/deploy an application to a Tomcat via jenkins using "system Groovy script".
For the undeploy/deploy i need credentials.
These i masked in the jenkins job via "mask passwords" (user and password)
Im not able to use these variables in my "system Groovy script" properly.
when i use the credentials in the script directly it works fine.
This is my "system Groovy script":
def ant = new AntBuilder()
//def user = build.getEnvVars()['user']
//def password = build.getEnvVars()['password']
ant.taskdef( name: 'deploy', classname: 'org.apache.catalina.ant.DeployTask' )
ant.taskdef( name: 'undeploy', classname: 'org.apache.catalina.ant.UndeployTask' )
ant.undeploy(
url:deployURL,
username:"${user}",
password:"${password}",
path:deployPath,
failonerror:true)
ant.deploy(
url:deployURL,
username:"${user}",
password:"${password}",
path:deployPath
war:warfile)

Jenkins Credentials Store Access via Groovy
I used the solution from the link above in the following way:
def credentials_store = jenkins.model.Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider')
credentials_store[0].credentials.each { ThisJenkins ->
if (ThisJenkins instanceof com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl) {
if (ThisJenkins.username == "MyUser") {
user = ThisJenkins.username
password = ThisJenkins.password
}
}
}
later on i used the "user" and "password" for my deployment:
ant.undeploy(
url:'MyServer',
username: user,
password: password,
path:'/MyTool',
failonerror:false)

Related

Jenkins: how to configure initial admin with ssh publickey by script?

I have this groovy script to initialize my Jenkins server:
def hudsonRealm = new HudsonPrivateSecurityRealm(false) ;
hudsonRealm.createAccount('admin','admin')
instance.setSecurityRealm(hudsonRealm)
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
This will create a "admin/admin" user at initial startup of my Jenkins instance.
How do I complete this to add my SSH public key to the user "admin"?
The objective is to be able to use the "ssh admin#jenkins" to run commands after the config, like explained here: https://www.jenkins.io/doc/book/managing/cli/#ssh
PS: I know I can do it manually through the web interface, I am looking for a mean to do that by script.
I found this set of scripts here: https://gist.github.com/nigimaster/6a014c62b444fe7a7744304d66881451
I post here the full commands with comments:
//
// Create initial admin with username/password = admin/password
//
// thanks to https://gist.github.com/hayderimran7/50cb1244cc1e856873a4
//
def hudsonRealm = new HudsonPrivateSecurityRealm(false) ;
hudsonRealm.createAccount('admin','password')
instance.setSecurityRealm(hudsonRealm)
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
//
// Add ssh key to admin
//
// thanks to #nigimaster https://gist.github.com/nigimaster/6a014c62b444fe7a7744304d66881451
//
def user = hudson.model.User.get('admin')
user.addProperty(new org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl(
/** your public key content: ssh-rsa AA... */
))
user.save()
//
// Allow connection over ssh
//
// thanks to https://github.com/jenkins-infra/jenkins-infra/blob/staging/dist/profile/files/buildmaster/enable-ssh-port.groovy
//
def sshConfig = instance.getDescriptor('org.jenkinsci.main.modules.sshd.SSHD')
sshConfig.port = 22
sshConfig.save()
This file is saved at /usr/share/jenkins/ref/init.groovy.d/customize.groovy (at least in the docker file).
Security advice: you should parametrize your groovy file to not have the passwords stored in it. Public key should not be a problem.
Using "Configuration as code", this is possible with this config:
jenkins:
authorizationStrategy:
loggedInUsersCanDoAnything:
allowAnonymousRead: false
securityRealm:
local:
allowsSignup: false
users:
- id: admin
name: ${ADMIN_USER}
password: ${ADMIN_PASSWORD}
properties:
- sshPublicKey:
authorizedKeys: ${readFile:/conf/generated/authorized_keys}
security:
sSHD:
port: 22
See https://github.com/jenkinsci/configuration-as-code-plugin

How to pass environment variable or string parameter in a Windows VM using jenkins as code using declarative syntax

pipeline {
agent {
node {
label 'xxx'
}
}
environment {
TESTPASSWORD_PSW = "${TESTPASSWORD}"
}
stages {
stage("My Environemnt Pipeline")
{
steps {
withCredentials([usernamePassword(credentialsId: 'MYCREDENTIAL',
passwordVariable: 'TESTPASS', usernameVariable: 'TESTUSER')]) {
echo "Have a look at ${TESTPASS}"
echo "Have a look at ${TESTUSER}"
}
}
}
}
}
I tried using properties where I have defined the string and put the default value as the username above but on my Windows server VM in XXX, there is no variable such as that
even I tried the option of defining a variable in the environment with the value of this credential but the SET command in command prompt didn't list out any environment variable
How can I pass one password credentials to be used in Windows VM and use it in my code. Thanks for the help

How to use jenkins plugin for username with password in dsl?

I'm new to jenkins and I'm trying to use the credentials in a dsl using the credentials plugin
template.xml
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<scope>GLOBAL</scope>
<id>PROD</id>
<description>prod credentials</description>
<username>prod</username>
<password>{{ encrypted_password_prod }}</password
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
I have defined the credentials in jenkins as username with password . the above encrypted value is saved in ansible.
My question is how should i call them in my dsl
Map credentials = [:]
credentialsBinding {
credentials.each { key, value ->
string("${key}", "${value}")
}
.credentials(["TF_VAR_username": "PROD" ,"TF_VAR_password" : "password_prod"])
Error:
22:11:16 FATAL: Credentials 'PROD' is of type 'Username with password'
where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was
expected
You can put credentials in Jenkins keystore (Jenkins -> Credentials -> System -> Global credentials -> Add Credentials), and then refer to them in your pipeline using withCredentials block like this:
node {
withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
sh '''
set +x
curl -u "$USERPASS" https://private.server/ > output
'''
}
}
More info here: https://jenkins.io/doc/pipeline/steps/credentials-binding/

How to read log file from within pipeline?

I have a pipeline job that runs a maven build. In the "post" section of the pipeline, I want to get the log file so that I can perform some failure analysis on it using some regexes. I have tried the following:
def logContent = Jenkins.getInstance()
.getItemByFullName(JOB_NAME)
.getBuildByNumber(
Integer.parseInt(BUILD_NUMBER))
.logFile.text
Error for the above code
Scripts not permitted to use staticMethod jenkins.model.Jenkins
getInstance
currentBuild.rawBuild.getLogFile()
Error for the above code
Scripts not permitted to use method hudson.model.Run getLogFile
From my research, when I encounter these, I should be able to go to the scriptApproval page and see a prompt to approve these scripts, but when I go to that page, there are no new prompts.
I've also tried loading the script in from a separate file and running it on a different node with no luck.
I'm not sure what else to try at this point, so that's why I'm here. Any help is greatly appreciated.
P.S. I'm aware of the BFA tool, and I've tried manually triggering the analysis early, but in order to do that, I need to be able to access the log file, so I run into the same issue.
You can use pipeline step httpRequest from here
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Test fetch build log'
}
post {
always {
script {
def logUrl = env.BUILD_URL + 'consoleText'
def response = httpRequest(
url: logUrl,
authentication: '<credentialsId of jenkins user>',
ignoreSslErrors: true
)
def log = response.content
echo 'Build log: ' + log
}
}
}
}
}
}
If your jenkins job can run on linux machine, you can use curl to archive same goal.
pipeline {
agent any
stages {
stage('Build') {
environment {
JENKINS_AUTH = credentials('< credentialsId of jenkins user')
}
steps {
sh 'pwd'
}
post {
always {
script {
def logUrl = env.BUILD_URL + 'consoleText'
def cmd = 'curl -u ${JENKINS_AUTH} -k ' + logUrl
def log = sh(returnStdout: true, script: cmd).trim()
echo 'Build log: ' +
echo log
}
}
}
}
}
}
Above two approaches both require the credentials is Username and password format. More detail about what is it and how to add in Jenkins, please look at here
Currently this is not possible via the RunWrapper object that is made available. See https://issues.jenkins.io/browse/JENKINS-46376 for a request to add this.
So the only options are:
explicitly whitelisting the methods
read the log via the URL as described in the other answer, but this requires either anonymous read access or using proper credentials.

Hiding passwords in Jenkins Pipeline log output without using WithCredentials

I have a parametrized Jenkins pipeline based on a Jenkinsfile. Some of the parameters contain sensitive passwords that I don't want to appear in the job's build logs.
So my question is: can I somehow register a String within the Jenkinsfile that is then replaced - by let's say ********** - whenever it appears in the log output?
I am aware of the withCredentials step, but I can't use it, since the credentials are not stored in the Jenkins credentials store (but provided as parameters at runtime).
I found this answer here https://stackoverflow.com/a/42372859/1549950 and tried it like this:
def secrets = [
[password: firstPassword, var: 'SECRET'],
[password: secondPassword, var: 'SECRET'],
[password: thirdPassword, var: 'SECRET']
]
node() {
wrap([$class: 'MaskPasswordsBuildWrapper', varPasswordPairs: secrets]) {
// my stages containing steps...
}
}
Where firstPassword, secondPassword, thirdPassword are variables containing my passwords. But still I get the content of firstPassword... displayed plain text in the log output.
I have the Mask Password plugin installed on my Jenkins in version 2.12.0.
Basically I am searching for something like this: https://issues.jenkins-ci.org/browse/JENKINS-27486 - ticket is resolved, but no sample snippet of final implementation is given.
Actually I don't know why this didn't work in the first place, but here is the solution to the problem.
Define an array with secrets that you want to hide like this:
def splunkPassword = 'verySecretPa55w0rd'
def basicAuthPassword = 'my8asicAuthPa55w0rd'
def getSecrets() {
[
[password: splunkPassword, var: 'SECRET'],
[password: basicAuthPassword, var: 'SECRET']
]
}
Disclaimer: I don't know whether the SECRET value has an important role, copy and pasted it from some snippet and it works as expected :)
Afterwards, you can wrap any calls in your scripted pipeline like this:
node {
wrap([$class: 'MaskPasswordsBuildWrapper', varPasswordPairs: getSecrets()]) {
stage 'First Stage' { ... }
stage 'Second Stage' { ... }
}
}
All passwords provided in the getSecrets() array will then be masked like this in your build output:
SPLUNK_PASSWORD: ********
BASIC_AUTH_ADMIN_PASSWORD: ********
I think you are looking for JENKINS-36007?
Update 26 May 2020
The workaround below stopped working for me recently. My guess is that something changed in a recent Jenkins update. I was trying to avoid installing another plugin, but I eventually gave up and installed the Mask Passwords plugin.
I used the following syntax for use with parameters:
parameters {
string(name: 'USERNAME', defaultValue: '', description: 'Username')
password(name: 'PASSWORD', defaultValue: '', description: 'Password')
}
Then in the build stage:
steps {
script {
wrap([$class: 'MaskPasswordsBuildWrapper',
varPasswordPairs: [
[password: "${USERNAME}", var: 'USR'],
[password: "${PASSWORD}", var: 'PSW']
]
]) {
sh '''
echo "Username: ${USERNAME}"
echo "Password: ${PASSWORD}"
'''
}
}
}
The original workaround is below, in case anyone else tries to go down the same path.
I've discovered a workaround that is a bit of a hack, but seems to work well. The trick is to use withCredentials, but override the variable with a parameter.
Here's an example which uses the environment directive's credentials() helper method to populate an environment variable, then overrides the two additional environment variables that are automatically defined (and masked in the logs).
First, create a dummy Username with password Credentials. The Username and Password values don't matter, we just need a Credential to use as a placeholder. Enter an ID such as dummy-credentials.
Then define an environment variable using the dummy credentials, and override the automatically defined variables with the parameters (MYUSERNAME and MYPASSWORD in this example):
environment {
MY_CREDS = credentials('dummy-credentials')
MY_CREDS_USR = "${params.MYUSERNAME}"
MY_CREDS_PSW = "${params.MYPASSWORD}"
}
Use the MY_CREDS_USR and MY_CREDS_PSW environment variables wherever you need to reference the secrets. Their contents will be masked in the console log.
sh '''
echo "Username: ${MY_CREDS_USR}"
echo "Password: ${MY_CREDS_PSW}"
'''
You might have a look at https://github.com/jenkinsci/log-file-filter-plugin
This plugin allows filtering Jenkins' console output by means of regular expressions. If some pattern matches the matched string is replaced by a string that can be specified for each pattern in the configuration.
Currently the plugin doesn't support adding filter-patterns from a jenkinsfile but only from the Jenkins global settings.
Highly brutish workaround.
Write a simple script, e.g. bash, and echo the parameter credentials into some file of arbitrary format, down to your echoing approach.
E.g. basic shell script:
$ cat executor/obfuscate.sh
#!/bin/bash
echo "PASSWORD: ${AWX_PW}" > ./executor/credential.yml
In your pipeline then:
stages {
stage('Placing') {
steps {
**sh './executor/obfuscate.sh'** }
[...]
< something reading credential.yml>
}
}
Outcome, nothing showing up in console:

Resources