闭包内的 Jenkins 管道库调用导致安全异常
Jenkins pipeline library calls inside closures cause security exceptions
我们正在使用带有组织文件夹的多分支管道(Bitbucket 分支源插件)。我正在使用共享库干掉我们的管道,从 Jenkins docs 和论坛帖子中获取提示。我还向其他开发人员提供脚本,试图在那些想要一切都"just work"和那些想要定制的人之间取得平衡。
我编写了一个包含管道和默认步骤的共享库。这个库是在 Jenkins 的文件夹级别配置的。
jenkins-lib
vars
pipeline_main.groovy
pipeline_pullRequest.groovy
...
default_init.groovy
pipeline_main.groovy
进行一些初始化,如果有带有键 'init' 或 default_init
的 Map 条目,则使用用户提供的阶段,如果没有:
#!groovy
def call(Map config) {
pipeline {
agent any
...
stages {
stage ('Init') {
steps {
script {
config['init'] ? config['init'](config) : default_init(config)
}
}
}
....
}
}
}
Jenkins 文件:
@Library('repo/jenkins-lib') _
def customInit = { Map config ->
echo 'Custom Init function override'
// default_init(config) // causes security exception if uncommented
}
if (env.BRANCH_NAME ==~ /PR-\d+/ ) {
pipeline_pullRequest(maven: 'maven3.3.9')
}
else if (env.BRANCH_NAME ==~ /master|develop/ ) {
pipeline_main(maven: 'maven3.3.9', init: customInit)
}
else {
pipeline_feature(maven: 'maven3.3.9')
}
仅使用默认值时,调用库中定义的管道效果很好。
现在,注意 Jenkinsfile 中的 customInit
方法。为了进行测试,我添加了一个调试行并调用了库中的 default_init
步骤。当我 运行 使用此配置(default_init
未注释 进行测试构建时,构建失败并出现安全异常:
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object
...
如果 customInit
方法只是 echo
步骤,管道将成功执行。
我知道我可以将对 invokeMethod
的调用列入白名单,但似乎我应该遵守 Jenkins 发出的警告,拒绝请求以避免可能的安全漏洞。而且,我知道我可以在全局 Jenkins 级别定义库以使其可信;但是,如果可能的话,我更愿意坚持使用每个文件夹的方法。
我想知道的是,为什么直接从 Jenkinsfile 调用的库方法不调用安全异常,而包裹在闭包中的库方法却调用安全异常?还是我只是错过了其他东西?
P.S。 Jenkins 2.89.3,Bitbucket Branch Source 2.2.9,所有 'Pipeline: ...' 最新版本的库。
default_init.groovy
内容,如有关系:
#!groovy
import java.util.Map
def call(Map config) {
echo sh(returnStdout: true, script: 'env | sort')
}
我查看了 JENKINS-26481 和相关的 JIRA 问题。事实上,我认为这是 Jenkins 团队尚未解决的极端情况(还没有?)。
如果我在全局 Jenkins 级别定义库以使其受信任,那么它会毫无例外地按我想要的方式工作。
我们正在使用带有组织文件夹的多分支管道(Bitbucket 分支源插件)。我正在使用共享库干掉我们的管道,从 Jenkins docs 和论坛帖子中获取提示。我还向其他开发人员提供脚本,试图在那些想要一切都"just work"和那些想要定制的人之间取得平衡。
我编写了一个包含管道和默认步骤的共享库。这个库是在 Jenkins 的文件夹级别配置的。
jenkins-lib
vars
pipeline_main.groovy
pipeline_pullRequest.groovy
...
default_init.groovy
pipeline_main.groovy
进行一些初始化,如果有带有键 'init' 或 default_init
的 Map 条目,则使用用户提供的阶段,如果没有:
#!groovy
def call(Map config) {
pipeline {
agent any
...
stages {
stage ('Init') {
steps {
script {
config['init'] ? config['init'](config) : default_init(config)
}
}
}
....
}
}
}
Jenkins 文件:
@Library('repo/jenkins-lib') _
def customInit = { Map config ->
echo 'Custom Init function override'
// default_init(config) // causes security exception if uncommented
}
if (env.BRANCH_NAME ==~ /PR-\d+/ ) {
pipeline_pullRequest(maven: 'maven3.3.9')
}
else if (env.BRANCH_NAME ==~ /master|develop/ ) {
pipeline_main(maven: 'maven3.3.9', init: customInit)
}
else {
pipeline_feature(maven: 'maven3.3.9')
}
仅使用默认值时,调用库中定义的管道效果很好。
现在,注意 Jenkinsfile 中的 customInit
方法。为了进行测试,我添加了一个调试行并调用了库中的 default_init
步骤。当我 运行 使用此配置(default_init
未注释 进行测试构建时,构建失败并出现安全异常:
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object ...
如果 customInit
方法只是 echo
步骤,管道将成功执行。
我知道我可以将对 invokeMethod
的调用列入白名单,但似乎我应该遵守 Jenkins 发出的警告,拒绝请求以避免可能的安全漏洞。而且,我知道我可以在全局 Jenkins 级别定义库以使其可信;但是,如果可能的话,我更愿意坚持使用每个文件夹的方法。
我想知道的是,为什么直接从 Jenkinsfile 调用的库方法不调用安全异常,而包裹在闭包中的库方法却调用安全异常?还是我只是错过了其他东西?
P.S。 Jenkins 2.89.3,Bitbucket Branch Source 2.2.9,所有 'Pipeline: ...' 最新版本的库。
default_init.groovy
内容,如有关系:
#!groovy
import java.util.Map
def call(Map config) {
echo sh(returnStdout: true, script: 'env | sort')
}
我查看了 JENKINS-26481 和相关的 JIRA 问题。事实上,我认为这是 Jenkins 团队尚未解决的极端情况(还没有?)。
如果我在全局 Jenkins 级别定义库以使其受信任,那么它会毫无例外地按我想要的方式工作。