2

Question: why are some functions disallowed if called in a Jenkinsfile, but allowed if called in a shared library that is imported by that same Jenkinsfile?

This question is not specific to directory-creation, but I will use it as an example, since that is the context in which I discovered this behavior:

The following Jenkins pipeline succeeds in creating a directory:

@Library('my-shared-libs') _

pipeline {
  agent any
  stages {
    stage( "1" ) {
      steps {
        script {
          utils.MkDir("/home/user/workspace/prj/foo")
        }
      }
    }
  }
}
// vars/utils.groovy
import java.io.File

def MkDir(the_dir) {
  def f = new File(the_dir)
  if ( ! f.mkdirs() ) { echo "Failed creating ${the_dir}" }
  else { echo "Succeeded creating ${the_dir}" }
}

But the following pipeline:

pipeline {
  agent any
  stages {
    stage( "1" ) {
      steps {
        script {
          def the_dir = "/home/user/workspace/prj/bar"
          def f = new File(the_dir)
          if ( ! f.mkdirs() ) { echo "Failed creating ${the_dir}" }
          else { echo "Succeeded creating ${the_dir}" }
        }
      }
    }
  }
}

...fails with this error:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use new java.io.File java.lang.String

Why is the directory-creation unsuccessful when called from the Jenkinsfile, but successful when called from the shared-library that is imported from that same Jenkinsfile?

The broader question this raises: what is the underlying "distinction" between a Jenkinsfile and shared libraries that it uses? There is some kind of "delineation" or "distinction" between Jenkinsfile declarative-syntax scripts and Groovy, and shared libraries, that isn't quite gelling in my mind. I'd be grateful if someone could help me understand.


Following @injecteer's suggestion, I tried the following modification to the second Jenkinsfile:

def the_dir = "/home/user/workspace/prj/bar"
def u = new URL( "file://${the_dir}" ).toURI()
def f = new File(u)
if ( ! f.mkdirs() ) { echo "Failed creating ${the_dir}" }
else { echo "Succeeded creating ${the_dir}" }

...which resulted in this error:

Scripts not permitted to use method java.net.URL toURI. Administrators can decide whether to approve or reject this signature.

It's not an option for me to do (or have done) this administrative approval, so this suggestion can't be an option for me, unfortunately.

StoneThrow
  • 5,314
  • 4
  • 44
  • 86
  • what if you call the constuctor: `new File(URI uri)`? – injecteer Jul 22 '21 at 22:40
  • @injecteer - sorry, I think I don't understand how to implement your suggestion. If my original code is `def f = new File("/path/to/my/dir")`, what do I need to do to use `new File(URI uri)`? – StoneThrow Jul 23 '21 at 16:51
  • I'm not sure if it's gonna work, but your exception said that `new File( String )` is not allowed. The `File` class has another constructor with `URI` as arg. Something like `new File( new URL( 'file:///home/user/workspace/prj/bar' ).toURI() )` – injecteer Jul 23 '21 at 20:29
  • @injecteer - apology for the slow response. I tried your suggestion, but got the error `Scripts not permitted to use method java.net.URL toURI`. We don't have the option for administrative approval for this function, so I have to rule out this workaround :(. I'll leave this question open because I think it has value to the community, but its priority for my personal need is reduced because the workaround, i.e. using `utils.MkDir()` from the shared library, is acceptable. Would still be valuable to understand why this odd difference between pipeline and shared lib ability to run same function. – StoneThrow Jul 30 '21 at 18:10
  • ok, was worth trying anyway. I'm no jenkins expert, and cannot help you further sorry. – injecteer Jul 30 '21 at 19:50
  • Have you looked at https://stackoverflow.com/questions/42654875/jenkins-pipeline-create-directory? – Shane Bishop Aug 02 '21 at 15:33
  • @ShaneBishop - thank you, I had not seen that, and the information is useful. However my question is slightly different than that one. My question is somewhat "academic" in the sense I'm just wanting to understand for the sake of understanding, in spite of having a working workaround. I.e. _why_ is it that a function is allowed if called from a shared library (which is imported by the Jenkinsfile) but not allowed if called directly from the Jenkinsfile. Seems like an odd restriction; I can't intuit the intent behind that (presumably) intentional design choice by the creators of Jenkins/Groovy. – StoneThrow Aug 03 '21 at 16:45
  • 1
    @StoneThrow As your question is worded now, everything about creating a directory will draw potential answerers away from what you really want to know. I would suggest you edit your question to be generically about why functions are forbidden in pipelines/jobs but not in shared libraries. I think this change would increase your odds of getting a good answer. – Shane Bishop Aug 03 '21 at 20:53
  • 1
    @ShaneBishop - probably lost some number of potential answers due to original wording, and delay in updating. I hope the new wording is clearer - please feel free to edit if you think it can be improved. I will keep the question open, since as far as I can tell, this is an "interesting" behavior/design choice on the part of Jenkins/Groovy that the community might benefit from having a Q&A on it. Good suggestion on improving the wording: thank you. – StoneThrow Aug 19 '21 at 12:46

0 Answers0