Jenkins CI 管道脚本不允许使用方法 groovy.lang.GroovyObject

Jenkins CI Pipeline Scripts not permitted to use method groovy.lang.GroovyObject

我正在使用 Jenkins 2 编译 Java 项目,我想从 pom.xml 中读取版本,我正在关注这个例子:

https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md

示例建议:

访问文件系统似乎存在一些安全问题,但我无法弄清楚它给出的是什么(或为什么)这个问题:

我只是做了一些与示例不同的事情:

def version() {
    String path = pwd();
    def matcher = readFile("${path}/pom.xml") =~ '<version>(.+)</version>'
    return matcher ? matcher[0][1] : null
}

运行 'version' 方法时出现的错误:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object (org.codehaus.groovy.runtime.GStringImpl call org.codehaus.groovy.runtime.GStringImpl)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.StaticWhitelist.rejectMethod(StaticWhitelist.java:165)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:117)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:103)
    at org.kohsuke.groovy.sandbox.impl.Checker.call(Checker.java:149)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:146)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:15)
    at WorkflowScript.run(WorkflowScript:71)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:55)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
    at sun.reflect.GeneratedMethodAccessor408.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:100)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
    at sun.reflect.GeneratedMethodAccessor408.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
    at sun.reflect.GeneratedMethodAccessor408.invoke(Unknown Source)

我正在使用这些版本: 插件管道 2.1 詹金斯 2.2

您必须在作业配置中为 Groovy 禁用沙盒。

目前,对于 groovy 脚本来自 scm 的多分支项目,这是不可能的。有关详细信息,请参阅 https://issues.jenkins-ci.org/browse/JENKINS-28178

快速修复解决方案:

我有类似的问题,我通过以下方式解决了它

  1. 导航到 jenkins > 管理 jenkins > 进程中脚本批准
  2. 有一个待处理的命令,我必须批准它。



备选方案 1:禁用沙箱

正如此 article 所深入解释的那样,groovy 脚本在默认情况下 运行 处于沙盒模式。这意味着 groovy 方法的子集可以 运行 无需管理员批准。 运行 脚本也可以不在沙盒模式下,这意味着整个脚本需要立即由管理员批准。这会阻止用户同时批准每一行。

运行 没有沙箱的脚本可以通过在脚本下方的项目配置中取消选中此复选框来完成:

备选方案 2:禁用脚本安全性

如此 article explains it also possible to disable script security completely. First install the permissive script security plugin 然后更改您的 jenkins.xml 文件添加此参数:

-Dpermissive-script-security.enabled=true

所以你 jenkins.xml 看起来像这样:

<executable>..bin\java</executable>
<arguments>-Dpermissive-script-security.enabled=true -Xrs -Xmx4096m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%\jenkins.war" --httpPort=80 --webroot="%BASE%\war"</arguments>

如果你实施这个,请确保你知道你在做什么!

为了绕过 SCM 存储的 Groovy 脚本的沙盒,我建议 运行 将脚本作为 Groovy 命令(而不是 Groovy脚本文件):

import hudson.FilePath
final GROOVY_SCRIPT = "workspace/relative/path/to/the/checked/out/groovy/script.groovy"

evaluate(new FilePath(build.workspace, GROOVY_SCRIPT).read().text)

在这种情况下,groovy 脚本从工作区传输到 Jenkins Master,在那里它可以作为 system Groovy Script 执行。只要 Use Groovy Sandbox 未被 checked.

,沙盒就会被抑制
当我将 userInput 中的 user-input 参数的数量从 3 个减少到 1 个时,我

我 运行 变成了这个。这将 userInput 的变量输出类型从数组更改为原始类型。

示例:

myvar1 = userInput['param1']
myvar2 = userInput['param2']

至:

myvar = userInput

要获取maven项目的版本,我通常在sh块中使用mvn二进制,如下所示。无需管理员权限。

stage("Compile") {
    steps {
       sh """
         mvn help:evaluate -Dexpression=project.version -q -DforceStdout > version.txt
       """
    }
}

按照@JavaTechnical的回答,可以将Maven项目的版本分配给一个变量:

stage("getPomProjectVersion") {
    steps {
       ...
       def pomProjectVersion = sh script: 'mvn help:evaluate -Dexpression=project.version -q -DforceStdout', returnStdout: true
       ...
    }
}