4

Open Policy Agent(OPA) 入门实践

 3 years ago
source link: https://segmentfault.com/a/1190000041076704
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

大家好,我是张晋涛。

本篇我来为你介绍一个我个人很喜欢的,通用策略引擎,名叫 OPA,全称是 Open Policy Agent。

在具体聊 OPA 之前,我们先来聊一下为什么需要一个通用策略引擎,以及 OPA 解决了什么问题。

OPA 解决了什么问题

在实际的生产环境中很多场景中都需要策略控制,比如:

  • 需要策略控制用户是否可登陆服务器或者做一些操作;
  • 需要策略控制哪些项目/哪些组件可进行部署;
  • 需要策略控制如何访问数据库;
  • 需要策略控制哪些资源可部署到 Kubernetes 中;

img

但是对于这些场景或者软件来说,配置它们的策略是需要与该软件进行耦合的,彼此是不统一,不通用的。管理起来也会比较混乱,带来了不小的维护成本。

OPA 的出现可以将各处配置的策略进行统一,极大的降低了维护成本。以及将策略与对应的软件/服务进行解耦,方便进行移植/复用。

img

OPA 的发展过程

OPA 最初是由 Styra 公司在 2016 年创建并开源的项目,目前该公司的主要产品就是提供可视化策略控制及策略执行的可视化 Dashboard 服务的。

OPA 首次进入 CNCF 并成为 sandbox 级别的项目是在 2018 年, 在 2021 年的 2 月份便已经从 CNCF 毕业,这个过程相对来说还是比较快的,由此也可以看出 OPA 是一个比较活跃且应用广泛的项目。

OPA 是什么

前面我们已经介绍过 Open Policy Agent (OPA) 是一种开源的通用策略引擎,可在整个堆栈中实现统一、上下文感知的策略控制。

OPA 可将策略决策与应用程序的业务逻辑分离(解耦),透过现象看本质,策略就是一组规则,请求发送到引擎,引擎根据规则来进行决策。

img

图 3 ,OPA 的策略解耦示例

OPA 并不负责具体任务的执行,它仅负责决策,需要决策的请求通过 JSON 的方式传递给 OPA ,在 OPA 决策后,也会将结果以 JSON 的形式返回。

OPA 中的策略是以 Rego 这种 DSL(Domain Specific Language) 来表示的。

Rego 受 Datalog(https://en.wikipedia.org/wiki...) 的启发,并且扩展了 Datalog 对于结构化文档模型的支持,方便以 JSON 的方式对数据进行处理。

Rego 允许策略制定者可以专注于返回内容的查询而不是如何执行查询。同时 OPA 中也内置了执行规则时的优化,用户可以默认使用。

Rego 允许我们使用规则(if-then)封装和重用逻辑,规则可以是完整的或者是部分的。

每个规则都是由头部和主体组成。在 Rego 中,如果规则主体对于某些变量赋值为真,那么我们说规则头为真。可以通过绝对路径引用任何加载到 OPA 中的规则来查询它的值。规则的路径总是: data.<package-path>.<rule-name> (规则生成的所有值都可以通过全局 data 变量进行查询。 例如,下方示例中的 data.example.rules.any_public_networks

  • 完整规则是将单个值分配给变量的 if-then 语句。

img

图 4 ,Rego 完整规则示例

  • 部分规则是生成一组值并将该组分配给变量的 if-then 语句。

img

图 5 ,Rego 部分规则示例

  • 逻辑或是要在 Rego 中定义多个具有相同名称的规则。(查询中将多个表达式连接在一起时,表示的是逻辑 AND)

img

图 6 ,Rego 规则或的完全规则和部分规则示例图

OPA 的使用

OPA 的使用还是比较简单的,我们来看一下。

安装 OPA

二进制方式

我们可以直接从 OPA 的 release 页面下载其二进制进行使用

➜  ~ wget -q -O ~/bin/opa https://github.com/open-policy-agent/opa/releases/download/v0.35.0/opa_linux_amd64_static 
➜  ~ chmod +x ~/bin/opa
➜  ~ opa version
Version: 0.35.0
Build Commit: a54537a
Build Timestamp: 2021-12-01T02:11:47Z
Build Hostname: 9e4cf671a460
Go Version: go1.17.3
WebAssembly: unavailable

我们可以使用其官方镜像

➜  ~ docker run --rm  openpolicyagent/opa:0.35.0 version    
Version: 0.35.0
Build Commit: a54537a
Build Timestamp: 2021-12-01T02:10:31Z
Build Hostname: 4ee9b086e5de
Go Version: go1.17.3
WebAssembly: available

OPA 交互

opa eval

最简单的命令是 opa eval ,当然我们除了能使用它进行策略的执行外,还可以用来做表达式计算。

img

图 7 , opa eval 的使用帮助

➜  ~ opa eval "6+6"
{
  "result": [
    {
      "expressions": [
        {
          "value": 12,
          "text": "6+6",
          "location": {
            "row": 1,
            "col": 1
          }
        }
      ]
    }
  ]
}

opa run

opa run 会启动一个交互式 shell ( REPL) 。我们可以使用 REPL 来试验策略并构建新的原型。

➜  ~ opa run
OPA 0.35.0 (commit a54537a, built at 2021-12-01T02:11:47Z)

Run 'help' to see a list of commands and check for updates.

> true
true
> ["Hello", "OPA"]
[
  "Hello",
  "OPA"
]
> pi := 3.14
Rule 'pi' defined in package repl. Type 'show' to see rules.
> show
package repl

pi := 3.14
> pi > 1
true

我们也可以将策略直接加载进去,或者 将 OPA 作为一个服务运行并通过 HTTP 执行查询。默认情况下,OPA 监会监听在 8181 端口。

➜  ~ opa run --server
{"addrs":[":8181"],"diagnostic-addrs":[],"level":"info","msg":"Initializing server.","time":"2021-12-07T01:12:47+08:00"}

打开浏览器也可以看到一个简单的查询窗口

img

opa 作为 go 的库使用

OPA 可以作为库嵌入到 Go 程序中。将 OPA 嵌入为库的最简单方法是导入 github.com/open-policy-agent/opa/rego 包。通过 rego.New 函数用来创建一个可以准备或评估的对象, PrepareForEval() 以获取可执行查询。

以下是一个简单的示例:

➜  opa tree 
.
├── data
├── go.mod
├── go.sum
├── input.json
├── k8s-label.rego
└── main.go

1 directory, 5 files

这里的策略文件是来校验 INPUT 中是否包含名为 domain 的 label , 以及该 label 是否以 moelove-开头。

package kubernetes.validating.existence

deny[msg] {
    not input.request.object.metadata.labels.domain
    msg := "Every resource must have a domain label"
}


deny[msg] {
    value := input.request.object.metadata.labels.domain
    not startswith(value, "moelove-")
    msg := sprintf("domain label must start with `moelove-`; found `%v`", [value])
}
  • INPUT 文件, 以 Kubernetes 的 AdmissionReview 为例
{
    "kind": "AdmissionReview",
    "request": {
        "kind": {
            "kind": "Pod",
            "version": "v1"
        },
        "object": {
            "metadata": {
                "name": "myapp",
                "labels": {
                    "domain": "opa"
                }
            },
            "spec": {
                "containers": [
                    {
                        "image": "alpine",
                        "name": "alpine"
                    }
                ]
            }
        }
    }
}
  • main.go 文件
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "os"

    "github.com/open-policy-agent/opa/rego"
)

func main() {

    ctx := context.Background()

    // Construct a Rego object that can be prepared or evaluated.
    r := rego.New(
        rego.Query(os.Args[2]),
        rego.Load([]string{os.Args[1]}, nil))

    // Create a prepared query that can be evaluated.
    query, err := r.PrepareForEval(ctx)
    if err != nil {
        log.Fatal(err)
    }

    // Load the input document from stdin.
    var input interface{}
    dec := json.NewDecoder(os.Stdin)
    dec.UseNumber()
    if err := dec.Decode(&input); err != nil {
        log.Fatal(err)
    }

    rs, err := query.Eval(ctx, rego.EvalInput(input))
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(rs)
}

执行结果如下:

➜  opa go run main.go k8s-label.rego "data" < input.json
[{[map[kubernetes:map[validating:map[existence:map[deny:[domain label must start with `moelove-`; found `opa`]]]]]] map[]}]

以上便是对于 OPA 的一个大致介绍,OPA 的应用场景有很多,后续文章中将为大家分享 OPA 在 Kubernetes 中的应用,和将 OPA 应用与 CI/CD pipeline 的场景。敬请期待。


欢迎订阅我的文章公众号【MoeLove】


Recommend

  • 41
    • 微信 mp.weixin.qq.com 4 years ago
    • Cache

    OPA Gatekeeper 策略入门

    OPA Gatekeeper 策略入门 原创...

  • 7
    • just4coding.com 4 years ago
    • Cache

    Open Policy Agent简介

    Open Policy Agent简介 发表于 2020-02-13 在应用开发中,应用程序往往需要跟据特定策略的决策...

  • 11

    【编者的话】这款云原生策略实施引擎已经被高盛、Netflix、Pinterest以及T-Mobile等组织应用于生产流程当中。 专为云原生软件构建可持续生态系统的云原生计算基金会(CNCF)今天宣布,Open Policy Agent(OPA)项目已经正式毕业。OPA不仅得到广...

  • 6
    • blog.knoldus.com 4 years ago
    • Cache

    Policy Enforcement using OPA

    Policy Enforcement using OPA Reading Time: 3 minutes Hi Guys, In this blog we are going to explore OPA and will run the sa...

  • 4

    Sponsored by Cockroach Labs What you build and where it takes you shouldn't be limited by your database. CockroachDB helps developers build and scale apps with fewer obstacles, more freedom, and greater efficiency. So you can...

  • 19

    使用 RESTful API 串接 Open Policy Agent 上一篇『初探 Open Policy Agent 實作 RBAC (Role-based access control) 權限控管』介紹了...

  • 5
    • www.openpolicyagent.org 2 years ago
    • Cache

    Open Policy Agent | WebAssembly

    What is WebAssembly (Wasm)? As described on https://webassembly.org/ WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is...

  • 6
    • qingwave.github.io 2 years ago
    • Cache

    Open Policy Agent vs Casbin

    大型项目中基本都包含有复杂的访问控制策略,特别是在一些多租户场景中,例如Kubernetes中就支持RBAC,ABAC等多种授权类型。在Golang中目前比较热门的访问控制框架有Open Policy Agent与

  • 10

    Evaluating open policy agent in rust using wasmJune 26, 2022 · 3 min readPoonaiMaintainer of inspektor

  • 3

    In my previous articles, we discussed what Policy-as-Code is, why we need it, and how to use the Open Policy Agent (OPA) tool. If you haven’t read the introduction yet, please take some time to read it first

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK