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

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

Https://github.com/jenkinsci/pipeline-plugin/blob/master/tutorial.md

这个例子表明:

Full Jenkins Pipeline with problematic function circled

似乎存在访问文件系统的一些安全问题,但我不知道它给出了什么(或者为什么)这个问题:

我只是做了一点不同于这个例子的事情:

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$1.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

304933 次浏览

您必须在作业配置中禁用 Groovy 的沙箱。

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

快速解决方案:

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

  1. 导航到 jenkins > Manage jenkins > In-process Script Approval
  2. 有一个未决的命令,我必须批准。

In process approval link in Jenkins 2.61



备选方案1: 禁用沙箱

正如这个 文章深入解释的那样,在默认情况下,groovy 脚本是以沙箱模式运行的。这意味着允许一部分 groovy 方法在没有管理员批准的情况下运行。也可以不在沙箱模式下运行脚本,这意味着整个脚本需要立即得到管理员的批准。这会阻止用户在同一时间批准每一行。

不使用沙箱运行脚本可以通过在脚本下面的项目配置中取消选中这个复选框来完成: enter image description here

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

正如此 文章解释的那样,完全禁用脚本安全性也是可能的。首先安装 允许脚本安全插件,然后更改 jenkins.xml 文件,添加以下参数:

- 允许-脚本-安全。启用 = 真

所以 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 Command(而不是 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执行。只要 使用 Groovy Sandbox不是 检查过了,沙箱就会被抑制。

当我将 userInput 中的用户输入参数从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
...
}
}

我遇到的问题是 Groovy 对象没有我试图调用的函数。根据我的理解,如果 Groovy 找不到这个函数,那么 Groovy 就会开始对寻找未定义对象的对象进行自省,这就导致了这个错误。

因此,请检查以确保您试图调用的函数确实存在。