继续我们的云原生技术走马观花的旅途,这一次我聊一下规则管理Open Policy Agent。相比较来说,这个概念及使用可能并不广范,大多数情况下并无必要使用这个东西,因为它增加了架构与部署的复杂度。
不过凡事都有但是,对于安全非常在意思的一些组织或企业来说,它是一个很有价值的工具。
这篇文章,我将试图在概念上给大家理清楚:
- • 什么是Policy及Policy Engine
- • 什么是Open Policy Agent
- • 如何在K8S中使用OPA
Policy及Policy Engine
什么是Policy
Policy这个英文单词是政策,策略或规则的意思,我在这把它翻译成了规则
。那什么是规则,应该还是比较好理解的,Policy某种程度上可以说是允许
,约束
及限制
,它与安全
密切相关联的。
那在编程的世界中,哪些属于Policy呢,举例说明:
- • 限制内网IP才允许SSH远程登录到服务器,其它则禁止
- • 允许超级管理员任意修改用户的密码,其它禁止
- • 只允许从公司镜像仓储拉取镜像,其它则禁止
上面的这些都是Policy,所以Policy大多是一些允许,约束或限制,它是为了强化架构或业务上的安全。
Policy其实有非常多种,比如上述中的超级管理员的Policy,是属于业务
级别,而镜像拉取
Policy则属于部署及运维层面。对于业务级别的Policy,当然我们只能用代码来实现,比如RBAC权限模型或领域中的约束与限制等。
什么是Policy Engine
理解了Policy之后,那下一个我们需要关心的问题就是:怎么来定义及存储Policy,又如何来验证Policy。而实现了定义存储Policy,又支持验证Policy的,我们就称之为Policy Engine。
以大家所熟知的RBAC模型及实现为例,我们会通过代码级,支持在UI上定义角色及资源等,将这些定义存储在类似MySQL的数据库中,再在代码中进行验证,不符合权限的抛出异常。这是一个Policy Engine。
理解了Policy Engine之后,那就可以开始正式讲到今天的主角了,OPA
什么是Open Policy Agent (OPA)
OPA就是一个Policy Engine实现,而且是一个独立的,不耦合特定平台与服务的Policy Engine,可应用于系统Linux或K8S,甚至是SQL等非常多的场景,支持Policy的定义与管理,验证与约束等。
OPA的优势是:
- 1. 架构上的独立与耦合,不与特定的技术或场景耦合,适合K8S及其它场景下的Policy的实现与管理
- 2. 在K8S这种分布式部署中,可以统一的管理整个部署中的Policy,简单方便
- 3. 可拔插的定义与管理,灵活性强,可随时修改规则
比如,使用OPA,你可以轻松的做到:
- • 所有部署的镜像必须来源于公司内网指定镜像,禁止从外网拉取镜像进行部署
- • 所有Pod必须指定资源限制(包括CPU,内存等),不指定资源限制的不允许部署
所以,在一些对安全比较在意的企业或部署管理中,OPA还是非常有价值的。
OPA的简介
OPA架构
OPA是一个独立的服务,可嵌入许多平台或框架中,做到Policy的Query以及Decision,总体来说,OPA主要是由Input,Policy以及Query等几个部分来组成。
Input
Input可理解为OPA的原始数据源,你可以理解为对现状的描述。它的格式是JSON。根据OPA应用的实际不同,Input产生的方式也并不一样。
举例说明,你部署了一个web
与db
服务,web服务支持http,https,而db则是tcp
我们可以用如下的Input来表达这个描述
代码语言:javascript复制{
"servers": [
{
"id": "db",
"protocols": ["tcp"]
},
{
"id": "web",
"protocols": ["http","https"]
}
]
}
这就是一个Input,我们用JSON定义了一个Input源,Input是描述。
Policy
Policy是策略,在OPA中,使用的是一个声明式语言Rego,通过Rego来定义Policy
我们定义如下的Policy:
- • 任意一个服务,如果开放了http协议,则认为不安全,禁止
使用Rego来编写这个Policy
代码语言:javascript复制package example
import future.keywords.every
# 如果violation的结果是0,则allow为true
allow := true {
count(violation) == 0
}
# 这个Policy表达了:如果任何protocols包括了http,则是violation的
violation[server.id] {
some server in input.servers
"http" in server.protocols
}
这就是一个Policy文件定义,它使用的是Rego语言来定义,意味着如果你想写好OPA,学习Rego是必不可少的
使用OPA来执行与运行这个Policy与Input
代码语言:javascript复制./opa eval -i input.json -d example.rego
得到的结果是
代码语言:javascript复制{
"violation": [
"web"
]
}
这是OPA运行后得出的结果,然后可以根据这个结果来进行决策,是允许还是禁止。
总结
所以,现在你理解OPA是一个什么样的Policy Engine了吧,它非常灵活,与特定的技术或平台并不耦合。定义Policy使用的是声明式的Rego
OPA与K8S
OPA并非只能用到K8S中,它的适用面非常广,比如你可以在Linux上配置并使用OPA,对SSH进行Policy控制;甚至可以对SQL运行配置OPA使用,限制不同的人能访问不同的表等,它非常灵活。
当然,做为CNCF中的一个项目,它肯定是支持K8S的。
OPA集成到K8S中主要有两种方式:
- • OPA kube-mgmt的模式
- • Gatekeeper
这两种方式都是OPA官方提供的方式,只不过前面一种比较原始,而Gatekeeper则是基于OPA之上,提供了更多的一些附加能力而已。
但是,不管是哪种方式,都是基于K8S提供的Admission Controllers(控制准入)基础能力之上实现的。
Admission Controllers
K8S所有的部署命令,无论是通过API方式,或是通过API封装提供的kubectl
,在执行任何一个部署命令时,都会触发 Admission Controllers,也就是控制准入的流程。
K8S本身包括很多控制准入的内置的一些能力,但这里要讲的主要是MutatingAdmissionWebhook
与ValidatingAdmissionWebhook
- • MutatingAdmissionWebhook:这个Webhook会对命令的数据进行修改,添加其它信息等
- • ValidatingAdmissionWebhook: 这个Webhook会对命令进行验证,如果不符合一些条件(比如超出限额配置),执行会被禁止。
而OPA集成到K8S,靠的就是ValidatingAdmissionWebhook。集成到K8S时,扩展了ValidatingAdmissionWebhook的能力,然后每次执行命令,会调用OPA进行验证。
至于OPA究竟如何集成到K8S中,这个就是后续需要深入进一步学习需要做的事了。
结论
OPA的应用可能并不普通,大多数情况下,可能并不会在自己的架构上再加一层OPA,这增加了复杂度,而且需要学习一个Rego的声明式语法,也需要付出成本。
但对于部署有较高的要求,比如有许多人能执行部署,在安全性的要求下,考虑使用OPA是一个不错的方案。它可以在技术层面避免一些错误及不允许的操作。
但凡能依赖技术的,就不要依赖人手动来做,这是技术世界不变的法则。
比如你的企业希望限制部署的镜像来源,与其通过文件规定或不停的向开发运维人员传达规定或事后检查等,还不如定义一个OPA来的更直接,简单及持续有效,并且没有人能违反规定。
是不是挺有价值的?