当前位置:  开发笔记 > 运维 > 正文

在代码中绕过脚本安全性插件

如何解决《在代码中绕过脚本安全性插件》经验,为你挑选了1个好方法。

我写了一些在Jenkins Pipelines中使用的常规实用方法。一个简单的例子是:

// src/org/package/utils.groovy
def remove_file(String file) {
  new File(file).delete()
}

但是,正如预期的那样,这在Jenkins Pipeline中引发了以下异常:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException:不允许脚本使用新的java.io.File java.lang.String

根据Script Security Plugin文档,我可以使用@Whitelisted方法注释绕过它:

@Whitelisted
def remove_file(String file) {
  new File(file).delete()
}

根据这个问题,我可以使用@NonCPS批注来绕过它(当然,此方法中的代码当然也不必可序列化):

@NonCPS
def remove_file(String file) {
  new File(file).delete()
}

共享库正在全局变量中使用,如下所示:

// vars/var.groovy
import org.package.utils

def method(body) {
  ...
  new utils().remove_file('file')
  ...
}

库/ var正在导入,并在Jenkinsfile中使用,如下所示:

library identifier: 'lib@master', retriever: modernSCM(
  [$class: 'GitSCMSource',
   remote: 'https://github.com/org/repo.git'])

pipeline {
  ...
  script {
    var.method {
      // body
    }
  }
  ...
}

在列出的基于代码的导入管道共享库的方法中,我上面使用的方法似乎是唯一与标准Jenkins Pipeline插件集实际兼容的方法,所以我采用了这种方法。

这两个方法都未能绕过Jenkins Pipeline抛出的安全异常。绕过使用代码的脚本安全性插件并避免手动/人为错误的解决方案(例如在GUI中修改白名单)的最佳解决方案是什么?



1> mkobit..:

我想根据您的最新评论和您对原始问题的更新,我了解发生了什么。我将尝试阐明全局共享库和“常规”共享库之间的区别。


注册图书馆

在撰写本文时,有几种不同的方法可以在Jenkins实例中注册共享库

    Jenkins安装在全球范围内 -适用于所有管道执行。

    对于Folder -文件夹中的所有项目都有可用的管道库

    自动库 -文档中提供的示例是GitHub Branch Source Plugin

库注册需要一些设置:

名称 -与library步骤和@Library注释一起使用的库名称

默认版本 -提交,分支,标签或其他一些标识符

隐式加载 -如果应隐式加载库(即,使用者不需要使用@Librarylibrary

检索方法 -如何检索SCM(例如使用Git或Mercurial)

允许覆盖默认版本 -如果使用者可以使用与默认版本不同的版本

上面提到的全局共享库绕过了安全沙箱,这意味着它们可以做任何事情。以下是一些相关文档:

由于这些库将在全球范围内可用,因此系统中的任何管道都可以利用这些库中实现的功能。

这些库被认为是“受信任的”:它们可以在Java,Groovy,Jenkins内部API,Jenkins插件或第三方库中运行任何方法。这使您可以定义将不安全的API分别封装在更高级别的包装器中的库,以供任何管道使用。请注意,任何能够将提交推送到此SCM存储库的人都可以无限制地访问Jenkins。您需要Overall/RunScripts配置这些库的权限(通常这将授予Jenkins管理员)。

这些是唯一绕过安全沙箱检查的管道库。其他类型(如文件夹库)经过安全检查,这意味着您无法执行new File(file).delete()


消费

在管道中,用户可以访问对其可用的所有共享库。从安装或文件夹中隐式加载的库(上面称为“ 隐式加载”选项)在脚本类路径上自动可用。必须使用@Library注释或library步骤来引入其他库。

例如,假设您有一个包含以下选项的库:

名称 -my-shared-lib

默认版本 -master

隐式加载 -false

检索方法 -对某些存储库的现代Git SCM设置

允许覆盖默认版本 -true

您可以从管道中提取此特定库的几种方法是:

@Library('my-shared-lib') -使用默认版本

@Library('my-shared-lib@develop') -与覆盖版本一起使用 develop

def myLib = library('my-shared-lib')-与默认版本一起使用

def myLib = library('my-shared-lib@develop') -与覆盖版本一起使用 develop

这些都将使用先前配置的库。

在您的示例中,您使用的是library步骤,但是从远程存储库动态加载,而不是使用注册版本。这就是为什么要指定retriever参数的原因。请记住,任何不是全局共享库的库 都不能绕过安全沙箱

如果要使库绕过沙箱,则需要在Jenkins安装中将其注册为全局共享库

附带说明new File(file).delete()-请小心在Jenkins管道内编写“常规” Groovy(有关原因,请参见此答案)。

推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有