Jenkins, possible to set Jenkins to job to require password? - jenkins

Some of our Jenkins jobs are such that they deploy e.g. to a client acceptance test environment. It is very important that this type of jobs are not triggered by accident. Is it therefore possible to configure Jenkins to somehow require a password when triggering a specific build?

Set up Project based security, then you can restrict build access on a per-job basis.
From the help on the Jenkins configuration page:
[Project based security] is an extension to "Matrix-based security"
that allows additional ACL matrix to be defined for each project
separately (which is done on the job configuration screen.)
This allows you to say things like "Joe can access project A, B, and C
but he can't see D." See the help of "Matrix-based security" for the
concept of matrix-based security in general.
ACLs are additive, so the access rights granted below will be
effective for all the projects.*

ok.
my 5cents about this question.
Our Jenkins uses Redmine's mysql db as auth input.
in Jenkins you'll need next plugins:
Parameterized Build
Build User Vars Plugin
and after activating Password parameter, you'll be asked for it before build.
So, i figured out 2 options.
It is applicable, if your slaves has direct connection with mysql (or any DB engine).
then pre-build check:
SALT=$(mysql --defaults-extra-file="~/redmcheck.my" -B -se "select salt from redmine.users where login='${BUILD_USER}';")
HASH=$(mysql --defaults-extra-file="~/redmcheck.my" -B -se "select hashed_password from redmine.users where login='${BUILD_USER}';")
CHECK=$(sha1 -qs $SALT$(sha1 -qs $Password))
if [ $HASH != $CHECK ]
then
exit 1;
fi
It will broke build, if your entered password doesn't equal.
Second solution, is to use Rest API in Redmine.
And it allows to recheck user on remote slaves.
CODE=$(curl -X GET -u ${BUILD_USER}:${Password} --write-out "%{http_code}" -o /dev/null -s https://redmine/users/current.json);
if [ $CODE != "200" ]
then
exit 1;
fi
If it gets 200 code, so it goes build.

Related

Running sfdx force:auth:web:login on jenkins job

I have a Jenkins job to deploy metadata to a given org. This is meant to be used as a first time setup method for new metadata. I have a jenkinsfile that can run the sfdx commands, and I'm trying to run force:auth:web:login.
agent none
steps {
script {
withEnv(["HOME=${env.WORKSPACE}", "MY_TOOL_DIR=${tool name: 'sfdx', type: 'com.cloudbees.jenkins.plugins.customtools.CustomTool'}"]){
def sfdx = "SFDX_USE_GENERIC_UNIX_KEYCHAIN=true ${MY_TOOL_DIR}/sfdx"
sh "${sfdx} force:auth:web:login --setalias deployOrg"
sh "${sfdx} force:mdapi:deploy -c -d ../MetadataFiles -u deployOrg -w 10"
}
}
This runs, but it doesn't open up the prompt to do the actual login. I was trying to do this before with ant, which was running but was refusing to deploy customSite data. So I could do either or, I just have to fix one error or the other. Is there a way to authorize a regular org (not devhub) like with JWT flows, or is that fully impossible?
Any help is much appreciated.
Is there a way to authorize a regular org (not devhub) like with JWT flows, or is that fully impossible?
Yes. The JWT Flow is in no way specific to Dev Hub orgs. You can authorize those orgs using JWT and a stored certificate following the instructions in the Salesforce DX Developer Guide.

Jenkins Build rpm sign error

I am trying to copy my entire Jenkins configuration from RHEL 6.7 to RHEL 6.9 , On doing this everything looks good, but only one jenkins build is failing with below error
Enter pass phrase:
can't connect to `/usr/share/tomcat6/.gnupg/S.gpg-agent': No such file or directory
gpg: skipped "Credit": Bad passphrase
gpg: signing failed: Bad passphrase
Pass phrase check failed
The gpg private key 1.4.5 exists in jenkins configuration. Strange thing is , all other builds are able to sign rpm but only one build is failing
Anyone know how to fix it ?
RPM reads the passphrase uses getpass(3) and sends to gnupg through an additional file descriptor.
This creates two problems that need to be handled by automating signing mechanisms:
1) Some versions of rpm use getpass(3) which will use a tty (to disable echoing) and will require setting up a pseudo tty so that the automated password can be passed to RPM. Make sure you have the pty file system mounted, and expect(1) is one way to setup the pty from which the password can be read. There's another approach using /proc file descriptors that can be attempted on linux. The password is then sent to gnupg using --passphrase-fd.
2) gnupg2 can also handle persistent passwords in a separate agent process which is sometimes tricky to setup and keep running "automatically" because the detection depends on both the user/process id's. Your report seems to have an agent (which means gnupg2 or special gpg1 configuration) even though you mention 1.4.5 (which would seem to use gnupg1).
I see two separate issues in your log that need to be addressed.
can't connect to `/usr/share/tomcat6/.gnupg/S.gpg-agent': No such file
or directory
gpg-agent needs to be running as a daemon on the build host, where it will connect to a socket to listen for requests. Perhaps it is already running, but Jenkins is looking for its socket in the wrong directory because GNUPGHOME is set to some unusual value. Or perhaps gpg-agent isn't running and a new instance needs to be started.
Something like this script can be used to safely attach to an existing gpg-agent or spin up a new instance.
#!/bin/bash
# Decide whether to start gpg-agent daemon.
# Create necessary symbolic link in $GNUPGHOME/.gnupg/S.gpg-agent
SOCKET=S.gpg-agent
PIDOF=`pgrep gpg-agent`
RETVAL=$?
if [ "$RETVAL" -eq 1 ]; then
echo "Starting gpg-agent daemon."
eval `gpg-agent --daemon `
else
echo "Daemon gpg-agent already running."
fi
# Nasty way to find gpg-agent's socket file...
GPG_SOCKET_FILE=`find /tmp/gpg-* -name $SOCKET`
echo "Updating socket file link."
cp -fs $GPG_SOCKET_FILE $GNUPGHOME/.gnupg/S.gpg-agent
You may want to substitute pgrep for pidof, depending on your shell.
If you do end up starting a new agent, you can check to see that your keys have been loaded into it by running gpg --list-keys. If you don't see it listed, you'll need to add it using gpg --import. Follow the Jenkins docs for Using Credentials.
Resolving the gpg-agent issue may resolve your other issue, so check to see if your job is working before doing anything else.
References:
www.linuxquestions.org
gpg: skipped "Credit": Bad passphrase
The GPG key is protected by a passphrase. rpm is asking for this passphrase and expects it to be manually entered. Of course, Jenkins is running things non-interactively, so that's not going to be possible. We need some way to supply the passphrase to rpm so it can forward it along to gpg, or else we need to supply the passphrase to gpg directly via some sort of caching mechanism.
The Expect Method
By wrapping our rpm --addsign call in an expect script, we can use expect to enter the passphrase headlessly. This practice is fairly common. Assuming the following script named rpm_sign.exp:
#!/usr/bin/expect -f
set password [lindex $argv 0]
set files [lrange $argv 1 1]
spawn rpm --define --addsign $files
expect "Enter pass phrase:"
send -- "$password\r"
expect eof
This script can be used in a Jenkins shell step or pipeline as follows:
echo "Signing rpms ..."
sh "./rpm_sign.exp '${GPG_PASSPHRASE}' <list-of-files>"
Please note that, with some modifications, it is possible to specify which GPG identity you want to sign your RPMs with. This is done by passing --define {_gpg_name $YOUR_KEY_ID_HERE} as an argument to rpm inside the wrapper script. Note the TCL syntax. Since we're doing this on Jenkins, which may offer multiple sets of credentials, I assume this is relevant info.
References:
aaronhawley.livejournal.com
lists.fedoraproject.org
Other Methods
There are other solutions out there that may be more appropriate to your configuration. One such solution is to use RpmSignPlugin, which uses expect under the hood. Other solutions can be found in this posting on unix.stackexchange.com.

How to export credentials from one jenkins instance to another?

I am using the credentials plugin in Jenkins to manage credentials for git and database access for my team's builds. I would like to copy the credentials from one jenkins instance to another, independent jenkins instance. How would I go about doing this?
UPDATE: TL;DR Follow the link provided below in a comment by Filip Stachowiak it is the easiest way to do it. In case it doesn't work for you go on reading.
Copying the $HUDSON_HOME/credentials.xml is not the solution because Jenkins encrypts paswords and these can't be decrypted by another instance unless both share a common key.
So, either you use the same encription keys in both Jenkins instances (Where's the encryption key stored in Jenkins? ) or what you can do is:
Create the same user/password, you need to share, in the 2nd Jenkins instance so that a valid password is generated
What is really important is that user ids in both credentials.xml are the same. For that (see the credentials.xml example below) for user: Jenkins the identifier <id>c4855f57-5107-4b69-97fd-298e56a9977d</id> must be the same in both credentials.xml
<com.cloudbees.plugins.credentials.SystemCredentialsProvider plugin="credentials#1.22">
<domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash">
<entry>
<com.cloudbees.plugins.credentials.domains.Domain>
<specifications/>
</com.cloudbees.plugins.credentials.domains.Domain>
<java.util.concurrent.CopyOnWriteArrayList>
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<scope>GLOBAL</scope>
<id>c4855f57-5107-4b69-97fd-298e56a9977d</id>
<description>Para SVN</description>
<username>jenkins</username>
<password>J1ztA2vSXHbm60k5PjLl5jg70ZooSFKF+kRAo08UVts=
</password>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
</java.util.concurrent.CopyOnWriteArrayList>
</entry>
</domainCredentialsMap>
</com.cloudbees.plugins.credentials.SystemCredentialsProvider>
I was also facing the same problem. What worked for me is I copied the credentials.xml, config.xml and the secrets folder from existing jenkins to the new instance. After the restart of jenkins things worked fine.
This is what worked for me.
Create a job in Jenkins that takes the credentials and writes them to output. If Jenkins replaces the password in the output with ****, just obfuscate it first (add a space between each character, reverse the characters, base64 encode it, etc.)
I used a Powershell job to base64 encode it:
[convert]::ToBase64String([text.encoding]::Default.GetBytes($mysecret))
And then used Powershell to convert the base64 string back to a regular string:
[text.encoding]::Default.GetString([convert]::FromBase64String("bXlzZWNyZXQ="))
After trying quite a few things for several days this is the best solution I found for migrating my secrets from a Jenkins 2.176 to a new clean Jenkins 2.249.1 jenkins-cli was the best approach for me.
The process is quite simple just dump the credentials from the old instance to a local machine, or Docker pod with java installed, as a XML file (unencrypted) and then uploaded to the new instance.
Before starting you should verify the following:
Access to the credentials section on both Jenkins instances
Download the jenkins-ccli.jar from one of the instances (https://www.your-jenkins-url.com/cli/)
Have User and Password/Token at hand.
Notice: In case your jenkins uses an oAuth service you will need to
create a token for your user. Once logged into jenkins at the top
right if you click your profile you can verify both username and
generate password.
Now for the special sauce, you have to execute both parts from the same machine/pod:
Notice: If your instances are using valid Certificates and you want to
secure your connection you must remove the -noCertificateCheck
flag from both commands.
# OLD JENKINS DUMP # 
export USER=madox#example.com
export TOKEN=f561banana6ead83b587a4a8799c12c307
export SERVER=https://old-jenkins-url.com/
java -jar jenkins-cli.jar -noCertificateCheck -s $SERVER -auth $USER:$TOKEN list-credentials-as-xml "system::system::jenkins" > /tmp/jenkins_credentials.xml
# NEW JENKINS IMPORT # 
export USER=admin
export TOKEN=admin
export SERVER=https://new-jenkins-url.com/
java -jar jenkins-cli.jar -noCertificateCheck -s $SERVER -auth $USER:$TOKEN import-credentials-as-xml "system::system::jenkins" < /tmp/jenkins_credentials.xml
If you have the credentials.xml available and the old Jenkins instance still running, there is a way to decrypt individual credentials so you can enter them in the new Jenkins instance via the UI.
The approach is described over at the DevOps stackexchange by kenorb.
This does not convert all the credentials for an easy, automated migration, but helps when you have only few credentials to migrate (manually).
To summarize, you visit the /script page over at the old Jenkins instance, and use the encrypted credential from the credentials.xml file in the following line:
println(hudson.util.Secret.decrypt("{EncryptedCredentialFromCredentialsXml=}"))
To migrate all credentials to a new server, from Jenkins: Migrating credentials:
Stop Jenkins on new server.
new-server # /etc/init.d/jenkins stop
Remove the identity.key.enc file on new server:
new-server # rm identity.key.enc
Copy secret* and credentials.xml to new server.
current-server # cd /var/lib/jenkins
current-server # tar czvf /tmp/credentials.tgz secret* credentials.xml
current-server # scp credentials.tgz $user#$new-server:/tmp/
new-server # cd /var/lib/jenkins
new-server # tar xzvf /tmp/credentials.tgz -C ./
Start Jenkins.
new-server # /etc/init.d/jenkins start
Migrating users from a Jenkins instance to another Jenkins on a new server -
I tried following https://stackoverflow.com/a/35603191 which lead to https://itsecureadmin.com/2018/03/26/jenkins-migrating-credentials/. However I did not succeed in following these steps.
Further, I experimented exporting /var/lib/jenkins/users (or {JENKINS_HOME}/users) directory to the new instance on new server. After restarting the Jenkins on new server - it looks like all the user credentials are available on new server.
Additionally, I cross-checked if the users can log in to the new Jenkins instance. It works for now.
PS: This code is for redhat servers
Old server:
cd /var/lib/jeknins
or cd into wherever your Jenkins home is
tar cvzf users.tgz ./users
New server:
cd /var/lib/jeknins
scp <user>#<oldserver>:/var/lib/jenkins/user.tgz ~/var/lib/jenkins/.
sudo tar xvzf users.tgz
systemctl restart jenkins
Did you try to copy the $JENKINS_HOME/users folder and the $JENKINS_HOME/credentials.xml file to the other Jenkins instance?

jenkins-cli build on Cloudbees: "no such job"

I need to remotely trigger a Jenkins build hosted on CloudBees. Right now, I'm attempting to use jenkins-cli to no avail. Right now I am authenticating using a SSH key pair.
When I do:
$ java -jar jenkins-cli.jar -s https://... list-jobs All
I can see all the jobs, including the one I want to build. But when I do:
$ java -jar jenkins-cli.jar -s https://... build job1
No such job 'job1'
I've read about a workaround that involves adding permissions to the anonymous role. Even if I add every single permission to it, I get the same error.
If it helps, I'm using Jenkins 1.532.1.3. Thanks.
Today I ran into same problem and found the solution. The response 'no such job' comes when there is actually no such job or you don't have enough access to do requested operation.
Even when you have the access for requested operation and you are sending credentials with --username and --password arguments it still not works. Only solution I found was to use ssh authentication. So register your computer's ssh key to your jenkins and everything works fine. To register ssh key go to http://[yourjenkinsserver]/user/[username]/configure
I ran into the same error but managed to make it work by providing read permission in 'job' for anonymous user.
I encountered the same issue today on v1.621-1.1 while trying through a non-admin user which I named as 'vikas027'. In order to fix this I ticked all checkboxes under 'Job' column for user 'vikas027' and ticked 'Discover' and 'Read' (also under 'Job') for 'Anonymous' user. These settings are in http://<IP>:<port>/configureSecurity. Hope this helps someone.

How to run batch file with credentials using Jenkins

I've mkdir commands in a batch file but only admins have permissions to create directory, so how to pass credentials from Jenkins job to the batch file.
mkdir \\%%S.domain.com\c$\Test
Select the "use secret text(s) or file(s) and then add a binding. See screenshot :
Yes Daniel, it might be done using such utility tools but my organization doesn't allow me to use third party tools without approvals. So, we have configured server with WinRM that allows to connect to server remotely using credentials.
Just to add to #Marc's answer, use the secret text Bindings as suggested to store and pass the username and password as environment variables.
The set the username variable to USERNAME and Password Variable to PASSWORD, then in your batch file use the net use command like so.
net use "\\server\share" %PASSWORD% /user:%USERNAME%
\* whatever you need to do on that share, e.g. xcopy, mkdir *\
net use "\\server\share" /delete

Resources