16

I'm running Jenkins in a local trusted environment where I'm trying to run this pipeline. This Jenkinsfile is checked into git.

#!groovy
node('master') {
    def ver = pomVersion()
    echo "Building version $ver"
}

def pomVersion(){
    def pomtext = readFile('pom.xml')
    def pomx = new XmlParser().parseText(pomtext)
    pomx.version.text()
}

The first few times I ran the build, I needed to manually approve changes (Jenkins->Mange Jenkins-> In-process Script Approval). Now I get this Exception and there is nothing to approve. All I want to do is parse an XML file. Can these security checks be bypassed completely for pipeline builds?

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: unclassified field groovy.util.Node version
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.unclassifiedField(SandboxInterceptor.java:367)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:363)
    at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:23)
    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:17)
    at WorkflowScript.pomVersion(WorkflowScript:10)
    at WorkflowScript.run(WorkflowScript:3)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:62)
    at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:54)
    at sun.reflect.GeneratedMethodAccessor479.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
    at com.cloudbees.groovy.cps.Next.step(Next.java:58)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:154)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:32)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:29)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:29)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:164)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:276)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$000(CpsThreadGroup.java:78)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:185)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:183)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:47)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Finished: FAILURE
Gary
  • 6,357
  • 5
  • 30
  • 36

5 Answers5

15

Currently it is not possible. There is an open ticket for this problem https://issues.jenkins-ci.org/browse/JENKINS-28178

Andre
  • 475
  • 3
  • 6
  • 3
    Five years later and the issue is still open. Maybe someone can explain in layman's terms why there is such a big difference between a pipeline script entered in the Jenkins GUI and a pipeline script loaded from SCM? – andreee Jul 23 '20 at 09:03
9

You can solve the problem by following steps:

  1. install Permissive Script Security plugin (version 0.3 or newer)
  2. if you are using a pipeline script, make sure Use Groovy Sandbox is checked. This can be done in the configuration of the job.
  3. add permissive-script-security.enabled command line parameter to Jenkins master with value:
    • true if you want to disable the need to approve scripts, but potentially dangerous signatures will be logged:

         -Dpermissive-script-security.enabled=true
      
    • no_security if you want to disable the need to approve scripts and disable also logging of the potentially dangerous signatures:

         -Dpermissive-script-security.enabled=no_security
      
agabrys
  • 8,728
  • 3
  • 35
  • 73
  • Could you please explain how you have done "command line parameter to Jenkins master"? @SSF – Ponsuyambu Oct 04 '19 at 14:26
  • 1
    You can make the configuration in the Jenkins Java arguments. You may find it in the '/etc/sysconfig/jenkins' file (that is if you are running a centOs based OS). – SSF Oct 05 '19 at 01:43
  • @Ponsuyambu You can do it by passing the parameter to the java command line while starting Jenkins. See: https://www.jenkins.io/doc/book/managing/system-properties/ – bluesman80 Nov 24 '22 at 13:24
5

Try the following jenkins plugin: https://wiki.jenkins-ci.org/display/JENKINS/Permissive+Script+Security+Plugin It disables the sandbox. Works for me.

ruediste
  • 2,434
  • 1
  • 21
  • 30
  • Also didn't work for me (0.3 with Jenkins 2.133). Someone asked about how to get it to work at https://stackoverflow.com/questions/51133633/permissive-script-security-plugin-not-working-in-jenkins – Ben Creasy Jul 20 '18 at 06:53
  • We're using jenkins 2.46.2, plugin version 0.1 – ruediste Jul 21 '18 at 15:03
  • It works fine on Jenkins v2.249 and plugin version 0.6 Look at the answer below https://stackoverflow.com/a/48104262/3438276 – vikas027 Jul 28 '20 at 02:35
3

I'd like to offer up a hack that I ended up implementing after scouring the interwebs for a solution and trying some of the solutions proposed here.

A little background on my setup:

  • Jenkins master (no slaves)
  • Dockerized Jenkins instance with a persistent volume for the jenkins_home directory
  • Jenkins jobs are delivered via the Jenkins Job DSL plugin with jobs written in .groovy

My scenario: Anytime someone modified an existing Jenkins pipeline (via groovy) and introduced new functionality that used some custom groovy, Jenkins would fail the job and flag the code snippet for approval. Approval was manual and tedious.

I have tried the solutions posted above and they did not work for me. So my hack was to create a Jenkins job that runs a shell job that takes the list of signatures that need approved and then adds them to the /var/jenkins_home/scriptApproval.xml file.

Some gotchas:

  • The offending job still has to fail once for me to find/copy the offending code/signature
  • To get the change to take effect, you cant "reload from disk" for the file to get picked up. You have to restart the Jenkins process (in our case delete the container and bring it back up). This was not a big pain for me since Jenkins is restarted every morning.
  • In our world, we trust the devs who modify our Jenkins jobs so they are free to add signatures that need approval as needed. Plus the job is in source control so we can see who added what.
  • My Jenkins container also has xmlstarlet baked in so my shell job uses that for the updating of the file

Example of my Jenkins job's shell command:

#!/bin/bash
echo ""

#default location of the Jenkins approval file
APPROVE_FILE=/var/jenkins_home/scriptApproval.xml

#creating an array of the signatures that need approved
SIGS=(
'method hudson.model.ItemGroup getItem java.lang.String'
'staticMethod jenkins.model.Jenkins getInstance'
)

#stepping through the array
for i in "${SIGS[@]}"; do
   echo "Adding :"
   echo "$i"
   echo "to $APPROVE_FILE"
   echo ""
   #checking the xml file to see if it has already been added, then deleting. this is a trick to keep xmlstarlet from creatine duplicates
   xmlstarlet -q ed --inplace -d "/scriptApproval/approvedSignatures/string[text()=\"$i\"]" $APPROVE_FILE

   #adding the entry
   xmlstarlet -q ed --inplace -s /scriptApproval/approvedSignatures -t elem -n string -v "$i" $APPROVE_FILE
   echo ""
done

echo "##### Completed updating "$APPROVE_FILE", displaying file: #####"
cat "$APPROVE_FILE"
JuanD
  • 391
  • 1
  • 6
  • 13
2

As answered above: in the newer Jenkins versions Script Security has been tightened. However for the specific use case of reading a version from Maven's pom.xml one could use readMavenPom from the Pipeline Utility Steps Plugin:

pom = readMavenPom file: 'pom.xml'
pom.version

With some other solutions in this StackOverflow question as well.

Joep Weijers
  • 1,844
  • 12
  • 19