使用容器镜像仓库存储OPA策略

Posted by 梁远鹏 on 2023-04-05 | 阅读 |,阅读约 4 分钟

TOC

使用容器镜像仓库存储OPA策略

注意,目前 OPA(0.52.0) 只会去 OCI 镜像仓库下载这三种格式的内容:

application/vnd.oci.image.layer.v1.tar+gzip
application/vnd.oci.image.manifest.v1+json
application/vnd.oci.image.config.v1+json

简单来说就是基于应用容器镜像的格式来做的,未来我相信会迭代为 OCI artifact 的方式,拥有OPA自己的 mediaType. 例如application/vnd.cncf.opa.config.v1+json,一个简单的参考是,helm 的OCI chart mediaType是application/vnd.cncf.helm.config.v1+json.

添加下面文件:

.manifest

{
    "roots": ["policies"],
    "metadata": {
      "required_builtins": {
          "builtin1": [
          ],
      }
    }
}

data.json

{}

policies/hello.rego

package policies.play

default hello = false

hello {
    m := input.message
    m == "world"
}

config.json

{}

使用以下命令构建策略.

opa build src

构建好策略后,使用 oras 命令推送到容器镜像仓库,这里使用的是 ghcr.io

 oras push -u你的账号 -p你的token或密码 ghcr.io/{你的账号}/policy-hello:1.0.0 --config config.json:application/vnd.oci.image.config.v1+json bundle.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip

先使用以下命令来尝试看看 OPA 是否能从 OCI registry 下载策略并且正常使用其中的内容:

lan@lan:~/work/lanactions/lanactions/oparun$ opa run -c configuration.yaml 
{"level":"error","msg":"Failed to load bundle from disk: bundle read failed: archive read failed: EOF","name":"authz","plugin":"bundle","time":"2023-04-05T08:36:14Z"}
{"level":"info","msg":"Starting bundle loader.","name":"authz","plugin":"bundle","time":"2023-04-05T08:36:14Z"}
OPA 0.51.0 (commit 1f52ea1908181bf2ffa4a742f87f4838f1403728, built at 2023-03-31T13:44:46Z)

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

> {"level":"info","msg":"Bundle loaded and activated successfully. Etag updated to 653156df2068ed4c8f6bef67c515883d5331b291f1449160abef39a35163a1cd.","name":"authz","plugin":"bundle","time":"2023-04-05T08:36:14Z"}
> data
{
 "policies": {
   "play": {
     "hello": false
   }
 }
}

可以看到 OPA 启动后从 OC registry 下载了策略,然后输入data可以看到正是上述构建好的策略内容.

现在让我们来尝试一下使用这种方式的情况下能否为数据正常执行策略:

首先退出刚才的程序,我这里使用 Ctrl+D ,然后使用以下命令启动 OPA server:

OPA 的配置文件:

configuration.yaml

services:
  ghcr-registry:
    url: https://ghcr.io
    type: oci
    # credentials:
    #   bearer:
    #     scheme: "Bearer"
    #     token: "你的token"

bundles:
  authz:
    service: ghcr-registry
    resource: ghcr.io/liangyuanpeng/policy-hello:1.0.0
    persist: true
    polling:
      min_delay_seconds: 30
      max_delay_seconds: 120
opa run --server --set default_decision=policies -c configuration.yaml

这时我们打开另一个窗口来请求数据:

lan@lan:~/work/lanactions/lanactions$ curl localhost:8181 -i -d '{ "message":"world"}' -H 'Content-Type:application/json'
.HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 05 Apr 2023 08:40:08 GMT
Content-Length: 24

{"play":{"hello":true}}
lan@lan:~/work/lanactions/lanactions$ curl localhost:8181 -i -d '{ "message":"world2"}' -H 'Content-Type:application/json'
HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 05 Apr 2023 08:40:14 GMT
Content-Length: 25

{"play":{"hello":false}}

可以看到,内容完全符合策略的执行情况: 只有当 message=world 时, 策略才会返回 hello=true

OPCR项目

可以看到我们在将 OPA 策略推到容器镜像仓库时需要做两步:

  1. 使用 OPA 命令打包策略
  2. 使用 oras 命令推送策略到容器镜像仓库

而有一个 CNCF sandbox 项目专门为了处理 “OPA 策略镜像”,这个项目就是 OPCR.你可以用这个工具就向操作普通容器镜像一样操作 OPA 策略镜像.

同时 OPCR 还提供了 github action 用于构建和推送 OPA 策略镜像产物.

从这个链接下载 OPCR 的命令行工具:https://github.com/opcr-io/policy/releases/download/v0.2.0/policy0.2.0_linux_x86_64.zip

本文使用的是一个较早的 0.2.0 版本,当你看到这篇文章时 OPCR 可能更新了很多内容,因此你可以打开OPCR仓库查看最新发布的版本是哪一个,下载最新版本来食用,但我推荐你首先在本文的基础上基于 0.2.0 版本浅尝一下,因为版本更新意味着可能不兼容,也许新版本的命令不适用于本文后续的命令操作.

如果你发现了,欢迎你在下方评论区说明一下,对我或者对其他阅读本文的同学都是非常有帮助的,提前感谢你:)

开始尝试

首先 opcr 命令行有个 template 的概念,目的是创建一个新项目的时候生成一些通用的内容,默认情况下有 两个 CI 的模板和一个 policy 的模板.

下面我使用 policy 的模板生成了一个 opcr 项目.

lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ policy templates list

Fetching templates 

  NAME             KIND    DESCRIPTION                    
  github           cicd    GitHub policy CI/CD template.  
  gitlab           cicd    GitLab policy CI/CD template.  
  policy-template  policy  Minimal policy template.       
lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ policy templates apply policy-template

Processing template 'policy-template' 

Generating files .

The template 'policy-template' was created successfully.
lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ tree .
.
├── README.md
└── src
    └── policies
        └── hello-rego.rego

2 directories, 2 files

可以看到生成的内容也很简单,就一个 README.md 描述文件以及一个 hello 的 opa 策略文件.

接下来体验一下使用 policy 命令完成前面的流程:将 OPA 策略打包成容器并且推送到容器注册中心.

lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ policy  build . -t ghcr.io/liangyuanpeng/policy-hello:1.0.1

Created new image.
digest: sha256:1786513bf6de470983dad0ca37da6d1e9f0301f974586643dd275e00f820818b

Tagging image.
reference: ghcr.io/liangyuanpeng/policy-hello:1.0.1
lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ policy  push ghcr.io/liangyuanpeng/policy-hello:1.0.1

Resolved ref [ghcr.io/liangyuanpeng/policy-hello:1.0.1].
digest: sha256:1786513bf6de470983dad0ca37da6d1e9f0301f974586643dd275e00f820818b

Pushed ref [ghcr.io/liangyuanpeng/policy-hello:1.0.1].
digest: sha256:1786513bf6de470983dad0ca37da6d1e9f0301f974586643dd275e00f820818b

从上述内容可以看到首先构建策略,然后将策略 push 到容器镜像仓库.

相对于前面需要分开使用两个命令行工具并且命令需要特别配置参数,使用 opcr 的 policy 工具行就显得轻松很多.

可以简单的理解为 policy 命令行就是将 opa 命令行和 oras 命令的一些内容整合到了一起,形成了一个新的专注于 opa 策略容器化的命令行工具.

同样的,既然有 push 自然会有 pull,下面是一个将 opa 策略从容器镜像中下载到本地的,同时使用 polcy save 命令将策略从容器镜像中导出到本地文件系统.

见下面的命令行执行内容:

lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ policy pull ghcr.io/liangyuanpeng/policy-hello:1.0.0

Pulling.
ref: ghcr.io/liangyuanpeng/policy-hello:1.0.0

Pulled ref [ghcr.io/liangyuanpeng/policy-hello:1.0.0].
digest: sha256:4d89484b74914fb3aad47dc603dd51926375a384ebc956491eeb885317e55f86
lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ policy save ghcr.io/liangyuanpeng/policy-hello:1.0.0

Resolved ref [ghcr.io/liangyuanpeng/policy-hello:1.0.0].
digest: sha256:653156df2068ed4c8f6bef67c515883d5331b291f1449160abef39a35163a1cd
lan@lan:~/repo/git/liangyuanpeng.github.io/tmp$ ls
bundle.tar.gz  README.md  src

可以通过 policy images 命令来查看本地的 opa 策略镜像:

lan@lan:~$ policy images 

  REPOSITORY                  TAG    IMAGE ID      CREATED               SIZE  
  liangyuanpeng/policy-hello  1.0.1  1786513bf6de  2023-04-17T01:53:42Z  766B  
  liangyuanpeng/policy-hello  1.0.0  4d89484b7491  2023-04-05T08:16:30Z  538B 

有一个注意的点是,opcr 下载后的镜像使用 docker 命令是看不到的,这是因为 opcr 将镜像存在到了单独的~/.policy目录下,在本文示例中对应到绝对目录就是/home/lan/.policy.

lan@lan:~$ ls /home/lan/.policy/
config.json  default-domain.cfg  policies-root

会有三部分内容:

  • config.json 存放认证相关内容
  • default-domain.cfg 默认情况下的容器镜像中心,在本文中它是 ghcr.io
  • policies-root 目录,存放策略镜像内容.

最后

在 OCI 盛行的今天,将 artifact 存储到容器镜像内已经不是一件罕见的事情了,例如:

  • helm 早已支持将 OCI 注册中心存放 helm chart
  • cosign 将签名写入到容器镜像内
  • tekton 将 task/pipeline 打包成容器镜像

甚至 OCI 规范推出了 1.1 版本,因此来规范处理非容器应用环境下容器镜像的使用情况.

这对使用者来说也是一件好事,不必去了解每一种软件对应的工件中心,减少了学习成本.

微信公众号

扫描下面的二维码关注我们的微信公众号,第一时间查看最新内容。同时也可以关注我的Github,看看我都在了解什么技术,在页面底部可以找到我的Github。

wechat-qrcode