how to change compromised jenkins node "secret"? - jenkins

When my jenkins slave starts on its node, the command is run locally from that server:
/bin/java -jar /usr/local/jenkins/slave.jar \
-jnlpUrl https://example.com/computer/foo/slave-agent.jnlp \
-secret <big long hex id>
The "big long hex id" found its way into a git repository and is now compromised. How do I tell my jenkins master to change it?

If you delete the Slave from Jenkins, then re-add it, it should have a new ID assigned to it.

I am guessing that this is using the JNLP protocol and not JNLP4. The classes that generate the secrets: JNLPJnlpSlaveAgentProtocol/JnlpAgentReceiver uses a HMAC which uses the hostname as one input and a secret key as the other input. The secret input is fetched from the "DefaultConfidentialStore" which generates and stores a file in $JENKINS_HOME/secrets/. The name for the file in this case is probably: $JENKINS_HOME/secrets/jenkins.slaves.JnlpSlaveAgentProtocol.secret
To get a different result you either need to change the hostname or remove that file (a new one will be auto generated).
Links:
https://javadoc.jenkins-ci.org/jenkins/security/DefaultConfidentialStore.html
https://javadoc.jenkins-ci.org/jenkins/slaves/JnlpAgentReceiver.html

Related

Generating SSH-KEYGEN automatically and copying it from gcp instance to another?

How to create automatically run a SSH-KEYGEN ? We need to generate key automatically and copy from one gcp instance to another.
For that we need to ssh within that instance and make changes within sshd_config file and change the parameter "permitrootlogin=yes , and passwordauthentication=yes"
How can we do this changes so automatically while creating an GCP Instance?
You can use startup scripts to generate SSH keys.
If you to simplify things you can create a script like this:
#! /bin/bash
ssh-keygen -b 2048 -t rsa -f /tmp/sshkey -q -N ""
Upload your script into a storage bucket (create new or use existing one) and change file permissions in a way, that It will be readable by everyone; click on "edit permissions" and "add a new item" and fill the rest as below;
Then you can create a VM instance with your startup script:
gcloud compute instances create test-instance1 --scopes storage-ro --metadata startup-script-url=https://storage.cloud.google.com/cfb1/my.script
You can run commands copying your newly created ssh keys onto other GCP machines too in the same way.
But - if all the VM instances are in the same VPC and region (both conditions have to apply) you can login from one to another without creating any additional SSH keys or doing anything. Compute Engine takes care of everything and you can just ssh to one and type: ssh my-vm2 and you're in.
Unless you have something else in mind (like VM's in different VPC's)

Jenkis CLI does not work: WARNING: No header 'X-SSH-Endpoint' returned by Jenkins

I have Jenkins ver. 2.205 in Windows 10 and I have the following situation
Configure Global Security has Enable security checked.
I created the id_rsa_jenkins and id_rsa_jenkins.pub keys. The value of the public key was added to Jenkins for my account in SSH Public Keys.
I have the jenkins-cli.jar file, downloaded from http://localhost:9090/cli/
CLI
When I execute the following (split in multiple lines for presentation purposes):
java -jar jenkins-cli.jar
-s http://localhost:9090/
-i C:\Users\windowsusername/.ssh/id_rsa_jenkins
-ssh
-user jenkinsusername
help
Appears:
Enter passphrase for C:\Users\windowsusername\.ssh\id_rsa_jenkins:
Problem
I write the valid passphrase and then appears the following:
Nov 23, 2019 11:28:22 AM org.apache.sshd.common.util.security.AbstractSecurityProviderRegistrar getOrCreateProvider
INFO: getOrCreateProvider(EdDSA) created instance of net.i2p.crypto.eddsa.EdDSASecurityProvider
Nov 23, 2019 11:28:22 AM hudson.cli.SSHCLI sshConnection
WARNING: No header 'X-SSH-Endpoint' returned by Jenkins
As shown above, does not appear the expected data
It happens for any Jenkins CLI command, such as:
help
who-am-i
list-jobs
etc.
What is missing or wrong?
For the audience:
The instructions provided in the original post are mandatory. But the following instructions are mandatory too:
Have installed the SSH plugin
In Configure Global Security, in the SSH Server section (in the bottom), proceed to enable it, in this case I use the Fixed value option.
Note seems the random option is only useful for the jenkins-cli.jar case. It because through the SSH connection (i.e: ssh -l jenkinsusername -p 2020 localhost list-jobs) is mandatory know the port, in this case 2020.
Therefore Fixed or Random is viable for jenkins-cli.jar (it does not ask for use a port number) but for SSH connection is mandatory know the port number (here Fixed is need it)
Furthemore in Jenkins SSH indicates:
Configuration
By default, Jenkins will listen on a random available port, so as not to break
existing deployments. But this is most likely not very useful, so the administrator
is encouraged to change this from the global security configuration page by assigning
a fixed port. This configuration UI will also allow you to disable this feature.
Was very valuable this video:
Jenkins in Telugu part 17 | Jenkins CLI (with ssh)

Possible bug is Jenkins Swarm plugin - fsroot to set Remote root directory relative vs full path

I have latest Jenkins and it's Swarm plugin client jar (2.0).
I downloaded the swarm-client jar and I ran the following command to create the slave: (Note: : I'm using user Anonymous to connect to Jenkins master without requiring username/password and have provided Create Slave permission in Global Roles, and all access in Slave section under Slave roles by creating a new role with pattern swarm.*). Jenkins Swarm client: https://wiki.jenkins-ci.org/display/JENKINS/Swarm+Plugin
A user can provide a valid username/password if that user has Create Slave (Global Roles) and other access like connect, delete, etc in Slave Roles in Jenkins under Manage Roles).
$ which swarm-client.jar
~/tools/bin/swarm-client.jar
$ pwd
/home/confman/slaves
$ ~/tools/jdk1.7.0_60/bin/java -jar `which swarm-client.jar` -name "swarm_`hostname -a`" -fsroot "~/slaves/swarm_`hostname -a`" -master http://jenkins_master.srvr.company.com:8083 -username Anonymous -description "`hostname -a` " -executors 5 -labels "ANSIBLE_CENTOS CENTOS" -mode 'exclusive' -showHostName -t java=~/tools/jdk1.8.0_45 -t gradle=~/tools/gradle-2.3 -t Maven=~/tools/apache-maven-3.3.3 -t Groovy2=~/tools/groovy-2.4.5 --showHostName -retry 0 -disableClientsUniqueId &
But, instead of the above command setting Slave's Remote Root Directory to ~/slaves/swarm_jmeter01, it's setting the remote root path including the folder as prefix/relative to from where I ran the above command (as shown below). In my case, hostname command value is jmeter01.
The documentation doesn't mention that this paramter is relative to the current folder (where you'd run the java -jar slave-client jar command).
Has anyone found a solution for this i.e. it can ignore the current folder and set it to ~/slaves/swarm_01 or something like that?
Obviously In my automation to resolve this issue, I can first "cd" (change directory) to the correct folder ~/slaves and then just pass -fsroot "swarm_`hostname -a`" to get remote directory path value set as: ~/slaves/swarm_jmeter01 (in that case, it'll work fine).
~ is shell expansion ... if this not works, then use $HOME instead

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?

ant & cvs prompting password although password should come from PageAnt

I have ant build file, that should take cvs checkouts when called. I can call it ok, but when ant uses cvs to connect to cvs repo, the repo prompts for password and obviously ant command fails.
I have CVSROOT environment variable pointing to same location where I took the initial checkout for the project with TortoiseCVS, having ssh as protocol.
I also have putty's pageant running and an environment variable CVS_RSH pointing to plink.exe of putty. That combination should make the connection via putty, 'cause from pageAnt menu the connection opens without prompts.
My operation system is Windows 8.
Question here is, that why ant build fails on cvs server password prompt, although PageAnt otherwise is enabling promptless access via ssh+cvs?
Ant cvs task invokes cvs.exe command line from PATH so if everything works properly from command line, there is (almost) no reason it will fail from Ant.
Here is a checklist with points to verify:
CVSROOT must contain username and specify ext protocol, :ext:username#cvserver.domain.ldt:/path/to/repository
CVS_RSH must point to plink.exe with absolute file path and you have to ensure it will use SSH protocol
Your SSH private key must have been loaded into Pageant for the same user session as the user running Ant script
If it does not help, please provide more details about your cvs task options and your workstation setup.
When running without any user session opened and Pageant cannot help, often for continuous integration tools, a better option is to pass all arguments like username and private key file to plink directly in CVS_RSH variable:
CVS_RSH="C:\path\to\plink.exe -batch -ssh -l username -i C:\path\user\ssh-privatekey.ppk"
Of course, in such a case, your private key file must not be protected with a passphrase.

Resources