[!TIP] to list methods on a class instance:
Copy thing . metaClass . methods *. name . sort() . unique()
to determine a class from an instance:
Copy thing . class
// or
thing . getClass()
usage
[!TIP]
CSRF Protection Explained
if you authenticate your API calls with a username and a user API token then a crumb is not required from Jenkins 2.96
to get CSRF crumb via curl
Copy $ SERVER= "https://localhost:8080"
$ COOKIEJAR= "$( mktemp )"
$ CRUMB=$(curl -u "admin:admin" -s --cookie-jar "$COOKIEJAR" "$SERVER/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)")
# to run script via curl
$ curl -d "script=System.getProperties()" \
-u "admin:admin" \
--cookie "$COOKIEJAR" \
-H "$CRUMB" \
https:// ${SERVER} /scriptText
or
Copy $ SERVER= "https://localhost:8080"
$ COOKIEJAR= "$( mktemp )"
$ CRUMB= $( curl -u "admin:admin" \
--cookie-jar "${COOKIEJAR}" \
'https://${SERVER}/crumbIssuer/api/json' |
jq -r '[.crumbRequestField, .crumb] | join(":")'
)
# verify
$ echo $CRUMB
Jenkins-Crumb:c11dc*******************************************************e463
$ curl -d "script=System.getProperties()" \
-u "admin:admin" \
-s \
--cookie "$COOKIEJAR" \
-H "$CRUMB" \
https:// ${SERVER} /scriptText
$ curl --data-urlencode "script=$( < ./script.groovy)" \
-s \
--netrc-file ~/.netrc \
--cookie "${COOKIEJAR}" \
-H "${CRUMB}" \
https:// ${SERVER} /scriptText
remote access
Copy $ curl -d "script=<your_script_here>" https://jenkins/script
# or to get output as a plain text result (no HTML)
$ curl -d "script=<your_script_here>" https://jenkins/scriptText
curl submitting groovy file
Copy $ curl --data-urlencode "script=$( < ./somescript.groovy)" https://jenkins/scriptText
via api token
Copy $ curl --user 'username:api-token' \
--data-urlencode \
"script=$( < ./somescript.groovy)" \
https://jenkins/scriptText
via python
Copy with open ( 'somescript.groovy' , 'r' ) as fd:
data = fd.read ()
r = requests.post ( 'https://jenkins/scriptText' , auth= ( 'username' , 'api-token' ) , data={ 'script' : data} )
setup system property (temporary)
[!TIP|label:references:]
timestampe
Copy System. setProperty( 'org.apache.commons.jelly.tags.fmt.timeZone' , 'America/Los_Angeles' )
shell step aborts
Copy System. setProperty( 'org.jenkinsci.plugins.durabletask.BourneShellScript.HEARTBEAT_CHECK_INTERVAL' , 36000 )
to clear property
Copy System. clearProperty( 'hudson.model.DirectoryBrowserSupport.CSP' )
to get property
Copy System. getProperty( 'hudson.model.DirectoryBrowserSupport.CSP' )
to get all properties
Copy System. getProperties()
// or
System. getProperties() . sort() . collectEntries{[ (it . key), (it . value) ]}
System. getProperties() . sort() . each { println "${it.key} ~> ${it.value}" }
System. getProperties() . sort() . collect{ "${it.key} ~> ${it.value}" } . join( '\n' )
extend built-in node executor
Copy import jenkins . model . *
jenkins.model.Jenkins. instance . setNumExecutors( 5 )
execute shell script in console
[!TIP|label:references:]
Copy println ( 'uname -a' . execute() . text )
// or
println ( 'printenv' . execute() .in. text )
result
Copy Linux devops-jenkins-685cf57df9-znfs8 4.19.12-1.el7.elrepo.x86_64 #1 SMP Fri Dec 21 11:06:36 EST 2018 x86_64 GNU/Linux
or
Copy import hudson . util . RemotingDiagnostics
import jenkins . model . Jenkins
String agentName = 'your agent name'
// groovy script you want executed on an agent
groovyScript = '''
println System.getenv("PATH")
println "uname -a".execute().text
''' . stripIndent()
String result
jenkins.model.Jenkins. instance . slaves . find { agent ->
agent . name == agentName
} . with { agent ->
result = RemotingDiagnostics. executeGroovy( groovyScript, agent . channel )
}
println result
read & write files
Copy // write
new File ( '/tmp/file.txt' ) . withWriter( 'UTF-8' ) { writer ->
try {
writer << 'hello world\n'
} finally {
writer . close()
}
}
// read
new File ( '/tmp/file.txt' ) . text
write file in agent
Copy import hudson . FilePath
import hudson . remoting . Channel
import jenkins . model . Jenkins
String agentName = 'some-agent'
String filePath = '/tmp/file.txt'
Channel agentChannel = jenkins.model.Jenkins. instance . slaves . find { agent ->
agent . name == agentName
} . channel
new FilePath ( agentChannel, filePath ) . write() . with { os ->
try {
os << 'hello world\n'
} finally {
os . close()
}
}
read file from an agent
Copy import hudson . FilePath
import hudson . remoting . Channel
import jenkins . model . Jenkins
import java . io . BufferedReader
import java . io . InputStreamReader
import java . nio . charset . StandardCharsets
import java . util . stream . Collectors
String agentName = 'some-agent'
String filePath = '/tmp/file.txt'
Channel agentChannel = jenkins.model.Jenkins. instance . slaves . find { it . name == agentName } . channel
String fileContents = ''
new FilePath (agentChannel, filePath) . read() . with { is ->
try {
fileContents = new BufferedReader (
new InputStreamReader (is, StandardCharsets. UTF_8))
.lines()
.collect( Collectors. joining( "\n" )
)
} finally {
is . close()
}
} // with
// print contents of the file from the agent
println '==='
println (fileContents)
println '==='
nslookup
[!NOTE|label:references:]
Copy if ( ! binding . hasVariable( 'domain' ) ) {
domain = 'example.com'
}
if ( ! (domain in String ) ) {
throw new Exception ( 'PARAMETER ERROR: domain must be a string.' )
}
InetAddress dnsInetAddress = InetAddress. getByName domain
println dnsInetAddress . hostAddress
jenkins system
Copy import jenkins . model . * ;
import org . jenkinsci . main . modules . sshd . * ;
jenins.model.Jenkins instance = jenkins.model.Jenkins. instance
instance . setDisableRememberMe( false )
instance . setNumExecutors( 2 )
instance . setSystemMessage( '<h2>welcome to the Jenkins Master</h2>' )
instance . setRawBuildsDir()
instance . save()
def sshd = SSHD . get()
sshd . setPort( 12345 )
sshd . save()
Copy println ( "Groovy: ${GroovySystem.version}" )
println ( "Jenkins: ${jenkins.model.Jenkins.instance.getVersion()}" )
println ( "OS: ${System.getProperty('os.name')} - ${System.getProperty('os.version')}" )
println( "Java: ${System.getProperty('java.version')} - ${System.getProperty('java.vm.vendor')} (${System.getProperty('java.vm.name')})" )
println "---"
jenkins.model.Jenkins. instance . pluginManager . plugins
.collect()
.sort { it . getShortName() }
.each {
plugin -> println ( "${plugin.getShortName()}:${plugin.getVersion()}" )
}
return
modify log level
Copy System. setProperty( 'org.apache.commons.logging.Log' , 'org.apache.commons.logging.impl.SimpleLog' );
System. setProperty( 'org.apache.commons.logging.simplelog.showdatetime' , 'true' );
System. setProperty( 'org.apache.commons.logging.simplelog.log.httpclient.wire.header' , 'error' );
System. setProperty( 'org.apache.commons.logging.simplelog.log.org.apache.http' , 'error' );
System. setProperty( 'log4j.logger.org.apache.http' , 'error' );
System. setProperty( 'log4j.logger.org.apache.http.wire' , 'error' );
System. setProperty( 'org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient' , 'error' );
check log level
Copy println System. getProperty( 'org.apache.commons.logging.Log' );
println System. getProperty( 'org.apache.commons.logging.simplelog.showdatetime' );
println System. getProperty( 'org.apache.commons.logging.simplelog.log.httpclient.wire.header' );
println System. getProperty( 'org.apache.commons.logging.simplelog.log.org.apache.http' );
println System. getProperty( 'log4j.logger.org.apache.http' );
println System. getProperty( 'log4j.logger.org.apache.http.wire' );
println System. getProperty( 'org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient' );
RABC
[!NOTE|label:references:]
jobs & builds
[!TIP|label:get more:]
list build status with percentage
get all builds status during certain start-end time
Copy hudson.FilePath workspace = hudson.model.Executor. currentExecutor() . getCurrentWorkspace()
get absolute path
Copy println ( "script directory: ${new File(__FILE__).parent.absolutePath}" )
Copy // you have to install the Shelve Project Plugin on your Jenkins Master
// the maximum value for daysBack is 365, going beyond 365 will break the script.
import org . jvnet . hudson . plugins . shelveproject . ShelveProjectTask
def daysBack = 365 ;
jenkins.model.Jenkins. instance . getAllItems( AbstractProject. class ) . each { it ->
def lastBuild = it . getLastBuild()
if ( lastBuild != null ) {
def back = Calendar. getInstance()
back . set( Calendar. DAY_OF_YEAR,back . get( Calendar. DAY_OF_YEAR) - daysBack )
if ( lastBuild . getTime() . compareTo(back . getTime()) < 0 ) {
println it . name + " was built over " + daysBack + " days ago: " + lastBuild . getTime()
if ( it instanceof AbstractProject ){
def spt = new ShelveProjectTask (it)
Hudson. getInstance() . getQueue() . schedule(spt , 0 );
} else {
println it . name + " was not shelved ----------- "
}
}
}
}
plugins
Copy jenkins.model.Jenkins. instance
.pluginManager
.plugins
.each { plugin ->
println ( "${plugin.getDisplayName()} (${plugin.getShortName()}): ${plugin.getVersion()}" )
}
list for helm-value.yaml
Copy jenkins.model.Jenkins. instance
.pluginManager
.plugins
.sort( false ) { a, b ->
a . getShortName() . toLowerCase() <=> b . getShortName() . toLowerCase()
}
.each { plugin ->
println "- ${plugin.getShortName()}:${plugin.getVersion()}"
}
"DONE"
Copy ExtensionList. lookup( UnprotectedRootAction ) . each {
println String. format( "URL: '%s/' provided by '%s' in '%s'" ,
it . urlName,
Jenkins. get() . pluginManager . whichPlugin(it . class) ?. shortName ?: "Jenkins Core" ,
it . class . name
)
}
list plugin and dependencies
Copy println jenkins.model.Jenkins. instance . pluginManager . plugins
.sort( false ) { a, b ->
a . getShortName() . toLowerCase() <=> b . getShortName() . toLowerCase()
}
.collect { plugin ->
"~~> ${plugin.shortName} : ${plugin.version} : ${plugin.displayName}" +
( plugin . dependants ? "\n\t+++ ${plugin.dependants.join('\n\t+++ ')}" : '' ) +
( plugin . dependencies ? "\n\t... ${plugin.dependencies.join('\n\t... ')}" : '' )
}
.join( '\n' )
get specific plugin dependencies
Copy List<String> keywords = [ 'jsch' ]
println jenkins.model.Jenkins. instance . pluginManager . plugins
.findAll { plugin -> keywords . any { it == plugin . shortName } }
.sort( false ) { a, b ->
a . getShortName() . toLowerCase() <=> b . getShortName() . toLowerCase()
}
.collect { plugin ->
"~~> ${plugin.shortName} : ${plugin.version} : ${plugin.displayName}" +
( plugin . dependants ? "\n\t+++ ${plugin.dependants.join('\n\t+++ ')}" : '' ) +
( plugin . dependencies ? "\n\t... ${plugin.dependencies.join('\n\t... ')}" : '' )
}
.join( '\n' )
get dependency tree
Copy import hudson . PluginWrapper
def getDependencyTree ( String keyword, Integer benchmark = 2 , Integer index = 0 ) {
String prefix = index ? '\t' + "|\t" * (index -1 ) + "|... " : ''
PluginWrapper plugin = jenkins.model.Jenkins. instance . pluginManager . plugins . find { keyword == it . shortName }
List dependencies = plugin . collect { it . dependencies } . flatten() ?: []
println prefix + "${plugin.shortName} ( ${plugin.version} )"
if ( dependencies && benchmark != index ) {
dependencies . collect{ it . shortName } . each { getDependencyTree (it, benchmark, index +1 ) }
}
}
getDependencyTree( 'jsch' , 100 )
"DONE"
result
Copy jsch ( 0.2.8-65. v052c39de79b_2 )
| .. . ssh - credentials ( 305. v8f4381501156 )
| | .. . credentials ( 1254. vb_96f366e7b_a_d )
| | | .. . structs ( 324. va_f5d6774f3a_d )
| | | | .. . javax - activation - api ( 1.2.0-6 )
| | | | .. . javax - mail - api ( 1.6.2-9 )
| | | | | .. . javax - activation - api ( 1.2.0-6 )
| | | | .. . instance - identity ( 173. va_37c494ec4e5 )
| | | | | .. . bouncycastle - api ( 2.28 )
| | | .. . configuration -as- code ( 1647. ve39ca_b_829b_42 )
| | | | .. . caffeine - api ( 3.1.6-115. vb_8b_b_328e59d8 )
| | | | .. . commons - text - api ( 1.10.0-36. vc008c8fcda_7b_ )
| | | | | .. . commons - lang3 - api ( 3.12.0-36. vd97de6465d5b_ )
| | | | | | .. . javax - activation - api ( 1.2.0-6 )
| | | | | | .. . javax - mail - api ( 1.6.2-9 )
| | | | | | | .. . javax - activation - api ( 1.2.0-6 )
| | | | | | .. . instance - identity ( 173. va_37c494ec4e5 )
| | | | | | | .. . bouncycastle - api ( 2.28 )
| | | | .. . snakeyaml - api ( 1.33-95. va_b_a_e3e47b_fa_4 )
| | .. . trilead - api ( 2.84 . v72119de229b_7 )
| | .. . instance - identity ( 173. va_37c494ec4e5 )
| | | .. . bouncycastle - api ( 2.28 )
| .. . trilead - api ( 2.84 . v72119de229b_7 )
| .. . javax - activation - api ( 1.2.0-6 )
| .. . javax - mail - api ( 1.6.2-9 )
| | .. . javax - activation - api ( 1.2.0-6 )
| .. . instance - identity ( 173. va_37c494ec4e5 )
| | .. . bouncycastle - api ( 2.28 )
others
Copy def plugins = jenkins.model.Jenkins. instance
.pluginManager
.plugins
.sort( false ) { a, b ->
a . getShortName() . toLowerCase() <=> b . getShortName() . toLowerCase()
}
println "jenkins instance : ${jenkins.model.Jenkins.instance.getComputer('').hostName} + ${jenkins.model.Jenkins.instance.rootUrl}\n" +
"installed plugins:\n=================="
plugins . each { plugin ->
println " ${plugin.getShortName()} : ${plugin.getVersion()} | ${plugin.getDisplayName()}"
}
println "\nplugins dependency tree (...: dependencies; +++: dependants) :\n======================="
plugins . each { plugin ->
println """
${plugin.getShortName()} : ${plugin.getVersion()} | ${plugin.getDisplayName()}
+++ ${plugin.getDependants()}
... ${plugin.getDependencies()}
"""
}
or
Copy def jenkins = jenkins.model.Jenkins. instance
println """
Jenkins Instance : ${jenkins.getComputer('').hostName} + ${jenkins.rootUrl}
Installed Plugins:
==================
"""
jenkins . pluginManager
.plugins
.sort( false ) { a, b ->
a . getShortName() . toLowerCase() <=> b . getShortName() . toLowerCase()
} . each { plugin ->
println "${plugin.getShortName()}: ${plugin.getVersion()} | ${plugin.getDisplayName()}"
}
println """
Plugins Dependency tree (...: dependencies; +++: dependants) :
=======================
"""
jenkins . pluginManager
.plugins
.sort( false ) { a, b ->
a . getShortName() . toLowerCase() <=> b . getShortName() . toLowerCase()
} . each { plugin ->
println """
${plugin.getShortName()} : ${plugin.getVersion()} | ${plugin.getDisplayName()}
+++ ${plugin.getDependants()}
... ${plugin.getDependencies()}
"""
}
scriptApproval
backup & restore all scriptApproval items
backup
Copy import java . lang . reflect . *
import jenkins . model . Jenkins
import jenkins . model . *
import org . jenkinsci . plugins . scriptsecurity . scripts . *
import org . jenkinsci . plugins . scriptsecurity . sandbox . whitelists . *
import static groovy . json . JsonOutput . *
scriptApproval = ScriptApproval. get()
alreadyApproved = new HashSet<> ( Arrays. asList(scriptApproval . getApprovedSignatures()))
println prettyPrint( toJson(alreadyApproved . sort()) )
restore
Copy def scriptApproval = org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get ()
String[] signs = [
'method org.jenkinsci.plugins.workflow.steps.FlowInterruptedException getCauses' ,
'method org.jenkinsci.plugins.workflow.support.steps.input.Rejection getUser'
]
for ( String sign : signs ) {
scriptApproval.approveSignature( sign )
}
scriptApproval.save ()
example
Copy import java . lang . reflect . * ;
import jenkins . model . Jenkins ;
import jenkins . model . * ;
import org . jenkinsci . plugins . scriptsecurity . scripts . * ;
import org . jenkinsci . plugins . scriptsecurity . sandbox . whitelists . * ;
import static groovy . json . JsonOutput . *
ScriptApproval scriptApproval = ScriptApproval. get()
HashSet<String> alreadyApproved = new HashSet<> ( Arrays. asList(scriptApproval . getApprovedSignatures()))
Closure approveSignature = { String signature ->
if ( ! alreadyApproved ?. contains(signature) ) scriptApproval . approveSignature( signature )
}
[
'field org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval$PendingSignature dangerous' ,
'field org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval$PendingSignature signature' ,
'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval$PendingThing getContext' ,
'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval approveSignature java.lang.String' ,
'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval getPendingScripts' ,
'method org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval getPendingSignatures' ,
'staticMethod org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval get' ,
'staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods flatten java.util.Set' ,
'method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild'
] . each { println "~~> ${it}" ; approveSignature(it) }
scriptApproval . save()
Jenkinsfile
Copy #!/usr/bin/env groovy
import org . jenkinsci . plugins . scriptsecurity . scripts . ScriptApproval
timestamps { ansiColor( 'xterm' ) {
def requester = currentBuild . rawBuild . getCause( UserIdCause. class) ?. getUserId() ?: 'jenkins'
final List<String> description = []
try {
ScriptApproval scriptApproval = ScriptApproval. get()
final LinkedHashSet<String> pendingScripts = new HashSet<>(Arrays.asList( scriptApproval.getPendingScripts() )).flatten()
final LinkedHashSet<String> pendingSignature = new HashSet<>(Arrays.asList( scriptApproval.getPendingSignatures() )).flatten()
if ( ! pendingScripts && ! pendingSignature ) {
currentBuild . description = 'NOT_BUILT: nothing can be approved'
currentBuild . rawBuild . executor . interrupt( Result. NOT_BUILT )
}
if ( pendingScripts ) {
println 'scripts pending approval ...'
pendingScripts . collect() . each { ps ->
String log = "${ps.context.user}@${ps.context.psem.fullName} : ${ps.hash} ( ${ps.language.class.simpleName} )"
description << log
println "~~> ${log}. scripts: \n ${ps.script}"
scriptApproval . approveScript( ps . hash )
}
scriptApproval . save()
} // pendingScripts
if ( pendingSignature ) {
println 'signatures pending approval ...'
pendingSignature . collect() . each { ps ->
String signature = ps . signature
if ( ! ps . dangerous ) {
description << signature
println "~~> '${signature}'"
scriptApproval . approveSignature( signature )
} else {
println "~~> '${signature}' is too dangerous to be approval automatically. contact with Jenkins administrator."
}
scriptApproval . save()
}
}
} catch (e) {
def sw = new StringWriter ()
e . printStackTrace( new PrintWriter (sw) )
echo sw . toString()
throw e
} finally {
if ( description ) {
currentBuild . description = "@${requesterId} " +
"${buildResults.isSuccess(currentBuild.currentResult) ? 'successful' : 'failed to'} " +
"approved : '${description.join('; ')}'"
}
} // try/catch/finally
}} // ansiColor | timestamps
// vim:tabstop=2:softtabstop=2:shiftwidth=2:expandtab:filetype=Jenkinsfile
automatic approval
Copy // libs.groovy
def autoAccept ( Closure body ) {
try {
body()
} catch ( org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException e ) {
String msg = "NOT_BUILT : interrupted by approval scripts or signature"
def cause = { msg as String } as CauseOfInterruption
currentBuild . rawBuild . executor . interrupt( Result. NOT_BUILT, cause )
currentBuild . description = msg
build wait: false , job: '/marslo/scriptApproval'
}
}
// jenkinsfile
libs . autoAccept() {
... content .. .
}
automatic approval all pending
list pending scriptApproval
Copy import org . jenkinsci . plugins . scriptsecurity . scripts . ScriptApproval
ScriptApproval scriptApproval = ScriptApproval. get()
scriptApproval . pendingScripts . each { scriptApproval . approveScript( it . hash ) }
job dsl support for scriptapproval
Copy import jenkins . model . Jenkins
def scriptApproval = jenkins.model.Jenkins. instance
.getExtensionList( 'org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval' )[ 0 ]
def hashesToApprove = scriptApproval . pendingScripts
.findAll{ it . script . startsWith(approvalPrefix) }
.collect{ it . getHash() }
hashesToApprove . each { scriptApproval . approveScript(it) }
[!NOTE|label:@deprecated]
file: $JENKINS_HOME/init.groovy.d/disable-script-security.groovy
Copy import javaposse . jobdsl . plugin . GlobalJobDslSecurityConfiguration
import jenkins . model . GlobalConfiguration
// disable Job DSL script approval
GlobalConfiguration. all() . get( GlobalJobDslSecurityConfiguration. class) . useScriptSecurity = false
GlobalConfiguration. all() . get( GlobalJobDslSecurityConfiguration. class) . save()