Groovy Hook Script and Jenkins Configuration as Code
This post discusses Groovy Hook Scripts and how to use them for full configuration-as-code in Jenkins with Docker, Pipeline.
This can help us to set up local environment for developing Jenkins Pipeline libraries and to evaluate various Jenkins features.
Groovy Hook Scripts
These scripts are written in Groovy, and get executed inside the same JVM as Jenkins, allowing full access to the domain model of Jenkins.
For a given hook HOOK, the following locations are searched:
1234
WEB-INF/HOOK.groovy in jenkins.war
WEB-INF/HOOK.groovy.d/*.groovy in the lexical order in jenkins.war
$JENKINS_HOME/HOOK.groovy
$JENKINS_HOME/HOOK.groovy.d/*.groovy in the lexical order
The init is the most commonly used hook (i.e., HOOK=init).
The following sections show how some of the most common tasks and configurations in Jenkins can be achieved by using such Groovy scripts.
For example, in this project, many of such scripts are added into a Dockerized Jenkins master and executed when
starting a container to replicate configurations of the Jenkins instance in production.
It will give us ability to quickly spin up local Jenkins instances for development or troubleshooting issues in production Jenkins.
For importing GlobalMatrixAuthorizationStrategy class, make sure that matrix-auth plugin is installed.
For full list of standard permissions in the matrix, see this code snippet.
Note that the matrix can be different if different plugins are installed.
For example, the “Replay” permission for Runs is not simply hudson.model.Run.REPLAY since there is no such static constant.
Such permission is only available after Workflow CPS plugin is installed.
Therefore, we can only set “Replay” permission for Runs with the following:
In addition to enable authorization strategy, we should also set some basic configurations for hardening Jenkins.
Those includes various options that you see in Jenkins UI when going to Manage Jenkins > Configure Global Security.
importhudson.security.csrf.DefaultCrumbIssuerimportjenkins.model.Jenkinsimportjenkins.model.JenkinsLocationConfigurationimportjenkins.security.s2m.AdminWhitelistRuleimportorg.kohsuke.stapler.StaplerProxyimporthudson.tasks.Mailerprintln("--- Configuring Remoting (JNLP4 only, no Remoting CLI)")Jenkins.instance.getDescriptor("jenkins.CLI").get().setEnabled(false)Jenkins.instance.agentProtocols=newHashSet<String>(["JNLP4-connect"])println("--- Enable Slave -> Master Access Control")Jenkins.instance.getExtensionList(StaplerProxy.class).get(AdminWhitelistRule.class).masterKillSwitch=falseprintln("--- Checking the CSRF protection")if(Jenkins.instance.crumbIssuer==null){println"CSRF protection is disabled, Enabling the default Crumb Issuer"Jenkins.instance.crumbIssuer=newDefaultCrumbIssuer(true)}println("--- Configuring Quiet Period")// We do not wait for anythingJenkins.instance.quietPeriod=0Jenkins.instance.save()println("--- Configuring Email global settings")JenkinsLocationConfiguration.get().adminAddress="admin@non.existent.email"Mailer.descriptor().defaultSuffix="@non.existent.email"
Some are not working for versions before 2.46, according to this.
For disabling Jenkins CLI, you can simply add the java argument -Djenkins.CLI.disabled=true on Jenkins startup.
Adding Credentials to a new, local Jenkins for development or troubleshooting can be a daunting task.
However, with the following scripts and the right setup (NEVER commit your secrets into VCS), developers can automate adding the required Credentials into the new Jenkins.
// Text filedefsecret='''Hi,This is the content of the file.'''defsecretBytes=SecretBytes.fromBytes(secret.getBytes())defsecretFile=newFileCredentialsImpl(CredentialsScope.GLOBAL,'text-secret-file','description','file.txt',secretBytes)store.addCredentials(domain,secretFile)// Binary filePathfileLocation=Paths.get("/path/to/some/file.tar");defsecretBytes=SecretBytes.fromBytes(Files.readAllBytes(fileLocation))defsecretFile=newFileCredentialsImpl(CredentialsScope.GLOBAL,'binary-secret-file','description','file.tar',secretBytes)store.addCredentials(domain,secretFile)
importjenkins.model.*definstance=Jenkins.getInstance()// set emaildeflocation_config=JenkinsLocationConfiguration.get()location_config.setAdminAddress("jenkins@skynet.net")