Skip to content

Instantly share code, notes, and snippets.

@rtyler
Last active October 12, 2018 18:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rtyler/cd3a3f759c46f308bf7151819f5538a0 to your computer and use it in GitHub Desktop.
Save rtyler/cd3a3f759c46f308bf7151819f5538a0 to your computer and use it in GitHub Desktop.
Determine whether there are passphrase-protected ed25519 keys in a Jenkins instance
import com.cloudbees.hudson.plugins.folder.*
import com.cloudbees.hudson.plugins.folder.properties.*
import com.cloudbees.hudson.plugins.folder.properties.FolderCredentialsProvider.FolderCredentialsProperty
import com.cloudbees.plugins.credentials.*
import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey
/* Let's see if the key is ed25518 */
boolean checkKey(def key) {
boolean found = false
if ((key instanceof SSHUserPrivateKey) && (key.passphrase)) {
key.privateKeys.each { privateKey ->
if (privateKey =~ '----BEGIN OPENSSH PRIVATE KEY-----') {
println ""
println "The SSH key (${CredentialsNameProvider.name(key)}) may cause failures with the 2.73.1 upgrade!"
found = true
}
}
}
return found
}
/* Find all globally defined SSH Keys with a passphrase */
SystemCredentialsProvider.instance.store.domains.each { domain ->
SystemCredentialsProvider.instance.store.getCredentials(domain).each { key ->
if (checkKey(key)) {
println "(in the global scope, under the domain ${domain.name})"
}
}
}
/* Find all Folder-defined SSH keys with a passphrase */
Jenkins.instance.getAllItems(AbstractFolder).each { folder ->
def p = folder.properties.get(FolderCredentialsProperty)
p?.store.domains.each { domain ->
p.store.getCredentials(domain).each { key ->
if (checkKey(key)) {
println "(in the folder ${folder.displayName}, under the domain ${domain})"
}
}
}
}
return null
@jglick
Copy link

jglick commented Sep 15, 2017

My suggestions FTR:

  • skip Base64 stuff, and just look for -----BEGIN OPENSSH PRIVATE KEY-----
  • better to check for the interface SSHUserPrivateKey rather than hard-coding the standard impl class BasicSSHUserPrivateKey
  • use CredentialsNameProvider.name(key) for display purposes
  • safer to use .privateKeys (a list).

@jglick
Copy link

jglick commented Sep 15, 2017

  • factor out domain / credentials / key iteration into a helper method to reduce duplication

@dgeissl
Copy link

dgeissl commented Sep 19, 2017

As this script is listed in the Upgrade Guide, I ll leave the comment here that it fails with the following error on Jenkins LTS 2.60.1.
Happens on a folder that does not seem to have any properties (println the folder.properties in line 35 outputs 'null').

ava.lang.NullPointerException: Cannot get property 'domains' on null object
	at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60)
	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174)
	at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:47)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
	at Script1$_run_closure2.doCall(Script1.groovy:35)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027)
	at groovy.lang.Closure.call(Closure.java:414)
	at groovy.lang.Closure.call(Closure.java:430)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2030)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2015)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2056)
	at org.codehaus.groovy.runtime.dgm$162.invoke(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:274)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	...

@briancurt
Copy link

I'm having the same issue as @dgeissl. Any idea?

@jacksgt
Copy link

jacksgt commented Oct 2, 2017

Same issue as @dgeissl, I'm on Jenkins 2.60.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment