从源头上采取合理的安全政策
作者:Luc Perkins
关于OPA(Open Policy Agent,开放政策代理),我最喜欢的一点是它可以与其他系统互操作。任何生成JSON的东西 — 现在大多数系统都可以 — 都可以为OPA提供呈现政策判断的输入。由于这种互操作性,你可以将OPA与基于容器的开发工具(如Docker)、基础设施配置工具(如Terraform)、容器编排平台(如Kubernetes)一起使用,而这还只是皮毛。
OPA和持续集成
因为OPA可以与任何东西集成,所以现代软件“堆栈”的几乎每个部分都可以由政策驱动,包括持续集成。使用OPA,你可以创建政策来控制允许构建哪些构件,从而提供一个强大的杠杆来防止潜在的恶意工作和服务在你的系统上运行(确保这些作业和服务也受OPA政策控制!)
像最近event-stream这样的事件 — 以及其他许多事件 — 证明了这些保护措施是多么必要。如果你对自己的生产环境成为比特币矿工、密码窃取者和脚本小子们的天堂感到很酷,那么这就是你的选择。否则,政策驱动的CI可能是你想要探索的内容。
https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident
实际上,你可能已经在CI级别上应用了政策,但是通过松散的脚本组合以一种特殊的方式进行应用。OPA为使这些隐式政策转为显式和声明性提供了一个很好的平台。在下一节中,我将为政策驱动的CI提供一个直观的示例。
依赖的黑名单
例如,假设我是一个开发者,在一个大型组织中使用Node.js服务器。该组织使用用OPA的政策语言Rego编写的政策执行CI政策。CI的供应者是GitHub Actions,示例可以很容易地移植到其他CI的供应者。这个示例的代码位于GitHub上的lucperkins/opa-ci-example存储库中。
https://github.com/lucperkins/opa-ci-example/
package ci
# The package.json is presumed faulty
default allow = false
# Packages that aren't allowed
blacklist = {
"event-stream",
"left-pad"
}
# Records dependencies that are on the blacklist
violations[pkg] {
input.dependencies[pkg]
blacklist[pkg]
}
# Returns true only if there are no violations
allow {
count(violations) == 0
}
这是存储库中的ci.rego政策文件
Rego政策管理package.json的依赖
此政策接受每个项目的package.json文件作为输入,并将政策应用于该文件(请注意input.dependencies)。关于这项政策,有两点需要注意:
这就涵盖了依赖关系政策。现在让我们进入GitHub Actions工作流定义:
workflow "OPA evaluation" {
on = "push"
resolves = ["install"]
}
action "evaluate" {
uses = "docker://openpolicyagent/opa:0.11.0"
args = ["eval", "--fail-defined", "data.ci.violations[pkg]", "--input", "package.json", "--data", "ci.rego", "--format", "pretty"]
}
action "install" {
uses = "nuxt/actions-yarn@master"
args = "install"
needs = "evaluate"
}
这个应用程序的GitHub Actions工作流
该工作流中有两个操作:evaluate和install(在更充实的场景中,可能还有其他阶段,比如build-container或deploy-to-k8s)。evaluate操作使用openpolicyagent/opa:0.11.0的Docker镜像运行以下脚本:
opa eval \
--fail-defined 'data.ci.violations[pkg]' \
--input package.json \
--data ci.rego \
--format pretty
只要满足了violations[pkg]指令,OPA就会评估失败,也就是说,只要依赖项同时位于package.json的dependencies块中,并在包黑名单上。--format pretty标志让失败输出包含这样一个具有视觉吸引力的表:
+----------------+-------------------------+
| pkg | data.ci.violations[pkg] |
+----------------+-------------------------+
| "dependency-1" | "dependency-1" |
| "dependency-2" | "dependency-2" |
+----------------+-------------------------+
如果我是从事这个项目的开发者,我将在CI输出中直接得到关于政策违反的高可读性、可操作的反馈。那么我的构建目前进展如何?
结果
不太好。在我当前的开发分支上,我的package.json文件是这样的:
{
"private": true,
"dependencies": {
"event-stream": "^4.0.1",
"express": "^4.17.1",
"left-pad": "^1.3.0"
}
}
注定要失败的package.json
我在这里包含了两个依赖项 — event-stream和left-pad — 它们显然违反了黑名单。你可以在这里看到CI失败的结果。让我们解决这个问题!
https://github.com/lucperkins/opa-ci-example/runs/142848310
这个拉取请求完成了任务。它从package.json中删除了有问题的依赖项。从evaluate操作的结果可以看出,opa eval…命令返回未定义的值,而不是列出违规的表。因为evaluate操作已经通过,所以install操作已经成功调用。
https://github.com/lucperkins/opa-ci-example/pull/1
https://github.com/lucperkins/opa-ci-example/runs/142848310
你可以在开放政策代理游乐场中看到失败的政策和输入。来更正你的输入以修复构建!
https://play.openpolicyagent.org/p/kipUorP7ui
相关工作:测试Kubernetes配置
另一个使用OPA作为构建管道的一部分的完整示例,我强烈建议在2019巴塞罗那的KubeCon + CloudNativeCon欧洲Gareth Rushgrove展示的使用开放政策代理单元测试Kubernetes配置。
腾讯视频:
胶片:
尽管Gareth的项目与我的目标不同,但它提供了一个很好的例子,说明了如何使用OPA通过审查Kubernetes配置来防止在生产环境中出现某些类型的问题。
如果你有其他的例子 - 博客文章、代码片段、任何东西 - 请随时添加评论来分享你的工作!
意义
我在这里所展示的只是一些可能性的小尝试。你可以使用OPA来构建一个更加健壮的CI检查系统。举几个例子,你可以编写以下政策:
使你的生产系统政策驱动是最重要的,这必须包括在可能的情况下对这些系统的输入进行消毒清理。OPA非常简单地提供了开源世界中最健壮和最灵活的平台。
感谢Torin Sandall。