如何禁用 Jenkins 管道构建的安全检查

How can I disable security checks for Jenkins pipeline builds

我在本地可信环境中 运行ning Jenkins,我正在尝试 运行 此管道。此 Jenkinsfile 已签入 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()
}

前几次我 运行 构建,我需要手动批准更改(Jenkins->Mange Jenkins-> In-process Script Approval)。现在我得到了这个例外,没有什么可以批准的。我只想解析一个 XML 文件。管道构建是否可以完全绕过这些安全检查?

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.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[=11=]1(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.call(SandboxContinuable.java:32)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.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[=11=]0(CpsThreadGroup.java:78)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.call(CpsThreadGroup.java:185)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.call(CpsThreadGroup.java:183)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService.call(CpsVmExecutorService.java:47)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService.run(SingleLaneExecutorService.java:112)
    at jenkins.util.ContextResettingExecutorService.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

目前不可以。这个问题有一个开放的工单https://issues.jenkins-ci.org/browse/JENKINS-28178

尝试以下 jenkins 插件:https://wiki.jenkins-ci.org/display/JENKINS/Permissive+Script+Security+Plugin 它禁用沙箱。适合我。

正如上面的回答:在较新的 Jenkins 版本中,脚本安全性得到了加强。然而,对于从 Maven 的 pom.xml 读取一个版本的特定用例,可以使用 Pipeline Utility Steps Plugin:

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

Whosebug question 中还有一些其他解决方案。

您可以通过以下步骤解决问题:

  1. 安装 Permissive Script Security 插件(0.3 或更新版本)
  2. 如果您使用的是管道脚本,请确保选中 Use Groovy Sandbox。这可以在作业的配置中完成。
  3. 向 Jenkins master 添加 permissive-script-security.enabled 命令行参数,值为:
  • true 如果您想禁用批准脚本的需要,但将记录潜在危险的签名:

          -Dpermissive-script-security.enabled=true
    
  • no_security 如果您想禁用批准脚本的需要并禁用潜在危险签名的记录:

          -Dpermissive-script-security.enabled=no_security
    

我想提供一个 hack,我在网上搜索解决方案并尝试了此处提出的一些解决方案后最终实施了该 hack。

关于我的设置的一些背景知识:

  • 詹金斯大师(无奴隶)
  • 带有 jenkins_home 目录的持久卷的 Dockerized Jenkins 实例
  • Jenkins 作业是通过 Jenkins Job DSL 插件交付的,作业是用 .groovy
  • 编写的

我的场景: 任何时候有人修改现有的 Jenkins 管道(通过 groovy)并引入使用某些自定义 groovy 的新功能,Jenkins 都会失败并标记代码片段以供批准。批准是手动且乏味的。

我已经尝试了上面发布的解决方案,但它们对我不起作用。所以我的技巧是创建一个运行 shell 作业的 Jenkins 作业,该作业获取需要批准的签名列表,然后将它们添加到 /var/jenkins_home/scriptApproval.xml 文件中。

一些陷阱:

  • 这个有问题的工作我还要失败一次才能find/copy这个有问题的code/signature
  • 要使更改生效,您不能“从磁盘重新加载”来获取文件。您必须重新启动 Jenkins 进程(在我们的例子中,删除容器并将其重新启动)。这对我来说不是什么大问题,因为 Jenkins 每天早上都会重新启动。
  • 在我们的世界中,我们信任修改我们 Jenkins 作业的开发人员,因此他们可以根据需要自由添加需要批准的签名。另外,该作业在源代码管理中,因此我们可以看到谁添加了什么。
  • 我的 Jenkins 容器也有 xmlstarlet,所以我的 shell 工作使用它来更新文件

我的 Jenkins 作业的 shell 命令示例:

#!/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"