In Jenkins, I've only every seen one method for storing a private ssh key credential.
This method is recommended by everybody: Open the Jenkins server web portal in a web browser, go to Credentials
, and under Add Credentials
, select SSH Username with private key
, paste the private key into the web page, and hit ok
.
This, I assume, uses an HTML form to send the private key in a POST request over HTTPS to the Jenkins server, which then saves the private key locally on the server's disk.
The problem: The top voted answer to the question "How to securely send private keys?" states that a private ssh key can only be secured by not transmitting it at all.
My question: is pasting a private key into the Jenkins web portal and transmitting them over HTTPS actually secure? If not, what is the best way to get a private key into the Jenkins credentials?
in situ
Using the web UI for this is probably secure enough for almost every use case, and is hard to beat with respect to convenience.
Nevertheless, generating private keys where they are needed is certainly good advice, and is definitely possible with Jenkins. One approach:
In this example, on the Jenkins server both $HOME
and $JENKINS_HOME
point to /var/jenkins_home
, and the keys are generated in ~/temp
.
Generate the key on Jenkins server
ssh [email protected]
mkdir ~/temp
cd ~/temp
ssh-keygen -t rsa -b 4096 -C "some-meaningful-label" -f "./my-in-situ-key"
This creates my-in-situ-key
and my-in-situ-key.pub
in /var/jenkins_home/temp
.
Create the Jenkins credential
In Jenkins script console:
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey
import com.cloudbees.plugins.credentials.CredentialsScope
import com.cloudbees.plugins.credentials.domains.Domain
def domain = Domain.global()
def store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
def privateKeyString = new File('/var/jenkins_home/temp/my-in-situ-key').text
def keySource = new BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(privateKeyString)
def privateKeyCredential = new BasicSSHUserPrivateKey(
CredentialsScope.GLOBAL,
"temp-stack-overflow-key", // id
"jenkins", // username
keySource, // private key
"", // passphrase
"Temporary Demo Key" // description
)
store.addCredentials(domain, privateKeyCredential)
"Credential Added"
Test the credential before cleaning up.
Clean up
Grab the public key and be sure to delete the private key on your way out the door.
cat ~/temp/my-in-situ-key.pub
rm -rf ~/temp
Relevant Javadoc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With