如何用Open Policy Agent(OPA)结合Docker实现高效访问控制策略?

摘要:docker使用Open Policy Agent(OPA)进行访问控制,OPA 是一个开源的通用策略引擎,可以评估策略并做出决策,Rego 是一种用于编写策略的语言,是 OPA 的核心组成部分,docker安装OPA插件,启用OPA,OP
目录一.系统环境二.前言三.Open Policy Agent 简介四.Rego 语言简介五.配置基本环境六.docker安装OPA插件6.1 安装docker6.2 docker安装OPA插件6.3 启用OPA七.OPA规则7.1 使用OPA允许docker所有操作7.2 使用OPA禁止docker所有操作7.3 使用OPA禁止创建允许所有系统调用的docker容器7.4 使用OPA根据Authz-User判断用户是否具有创建pod权限八.总结 一.系统环境 本文主要基于Docker version 20.10.16和Linux操作系统Ubuntu 18.04。 服务器版本 docker软件版本 CPU架构 Ubuntu 18.04.5 LTS Docker version 20.10.16 x86_64 二.前言 在容器化技术中,Docker 已经成为广泛使用的工具。然而,随着容器数量的增加,确保容器之间的安全隔离变得越来越重要。Docker 提供了各种安全特性,但有时我们可能需要更细粒度的访问控制策略。Open Policy Agent(OPA)是一个开源的通用策略引擎,可以与 Docker 集成,以实现更灵活的访问控制。本文将介绍如何在 Docker 中使用 OPA 进行访问控制。 三.Open Policy Agent 简介 OPA 是一个开源的通用策略引擎,可以评估策略并做出决策。OPA 可以应用于各种场景,例如网络安全、访问控制、数据保护等。在 Docker 环境中,OPA 可以用于评估容器之间的访问请求,并根据预定义的策略做出决策,Open Policy Agent(OPA)的官网为:https://www.openpolicyagent.org/。 虽然 Docker 提供了各种安全特性,例如网络隔离、资源限制等,但有时我们可能需要更细粒度的访问控制策略。例如,我们可能希望限制某些容器对特定资源的访问,或根据容器的标签和属性来控制访问权限。这就是 OPA 发挥作用的地方。通过集成 OPA,我们可以实现更灵活、可扩展的访问控制策略。 一般情况下,我们使用docker执行docker命令是没有什么限制的,安装OPA插件,并启用OPA,创建了相关的OPA规则之后,使用docker执行docker命令,需要先访问OPA规则,如果OPA规则表示你有权限执行命令,则docker命令执行成功,否则执行失败。 四.Rego 语言简介 Rego 是一种用于编写策略的语言,是 OPA 的核心组成部分。它是一种声明性语言,可以描述复杂的数据结构和逻辑。Rego 语法简洁,易于理解,使得编写策略变得更加简单。在本文中,我们将使用 Rego 语言编写访问控制策略。 五.配置基本环境 本次使用一台新的Ubuntu机器(使用别的系统也行),下面给新机器配置基本环境。 查看Ubuntu系统版本。 root@localhost:~# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.5 LTS Release: 18.04 Codename: bionic 首先设置主机名。 root@localhost:~# vim /etc/hostname root@localhost:~# cat /etc/hostname ubuntuk8sclient 配置节点静态IP地址(可选)。如果您对Ubuntu系统不熟悉,请查看博客《centos系统和Ubuntu系统命令区别以及常见操作》。 root@localhost:~# vim /etc/netplan/01-netcfg.yaml root@localhost:~# cat /etc/netplan/01-netcfg.yaml network: version: 2 renderer: networkd ethernets: ens32: dhcp4: no addresses: [192.168.110.139/24] gateway4: 192.168.110.2 nameservers: addresses: [192.168.110.2,114.114.114.114] 使网卡配置生效。 root@localhost:~# netplan apply 测试机器是否可以访问网络。 root@localhost:~# ping www.baidu.com PING www.baidu.com (14.215.177.39) 56(84) bytes of data. 64 bytes from www.baidu.com (14.215.177.39): icmp_seq=1 ttl=128 time=54.3 ms 64 bytes from www.baidu.com (14.215.177.39): icmp_seq=2 ttl=128 time=44.6 ms 64 bytes from www.baidu.com (14.215.177.39): icmp_seq=3 ttl=128 time=41.3 ms 64 bytes from www.baidu.com (14.215.177.39): icmp_seq=4 ttl=128 time=37.0 ms 64 bytes from www.baidu.com (14.215.177.39): icmp_seq=5 ttl=128 time=43.7 ms ^C --- www.baidu.com ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4007ms rtt min/avg/max/mdev = 37.072/44.239/54.332/5.695 ms 查看IP。 root@localhost:~# ifconfig ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.110.139 netmask 255.255.255.0 broadcast 192.168.110.255 inet6 fe80::20c:29ff:fe97:b27b prefixlen 64 scopeid 0x20<link> ether 00:0c:29:97:b2:7b txqueuelen 1000 (Ethernet) RX packets 20269 bytes 22473377 (22.4 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 7755 bytes 544420 (544.4 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 1650 bytes 119324 (119.3 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1650 bytes 119324 (119.3 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 配置IP和主机名映射。 root@localhost:~# vim /etc/hosts root@localhost:~# cat /etc/hosts 127.0.0.1 localhost 127.0.1.1 tom 192.168.110.139 ubuntuk8sclient # The following lines are desirable for IPv6 capable hosts ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters 配置软件源。 root@ubuntuk8sclient:~# vim /etc/apt/sources.list #软件源如下,最后三行是k8s源 root@ubuntuk8sclient:~# cat /etc/apt/sources.list deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable # deb-src [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable apt-key.gpg是k8s的deb源公钥,加载k8s的deb源公钥命令为:apt-key add apt-key.gpg。 下载并加载k8s的deb源公钥命令为:curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - ; apt-get update,但是谷歌的网址访问不了,我们直接去网上下载apt-key.gpg文件。 root@ubuntuk8sclient:~# ls apt-key.gpg 加载k8s的deb源公钥。 root@ubuntuk8sclient:~# cat apt-key.gpg | apt-key add - OK 更新软件源。 root@ubuntuk8sclient:~# apt-get update 关闭防火墙。 root@ubuntuk8sclient:~# ufw disable Firewall stopped and disabled on system startup Linux swapoff命令用于关闭系统交换分区(swap area)。如果不关闭swap,就会在kubeadm初始化Kubernetes的时候报错:“[ERROR Swap]: running with swap on is not supported. Please disable swap”。 root@ubuntuk8sclient:~# swapoff -a ;sed -i '/swap/d' /etc/fstab root@ubuntuk8sclient:~# cat /etc/fstab # /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # <file system> <mount point> <type> <options> <dump> <pass> /dev/mapper/tom--vg-root / ext4 errors=remount-ro 0 1 此时基本环境就配置完毕了。 六.docker安装OPA插件 6.1 安装docker 安装docker。 root@ubuntuk8sclient:~# apt-get install docker-ce -y root@ubuntuk8sclient:~# which docker /usr/bin/docker 查看docker安装包。 root@ubuntuk8sclient:~# dpkg -l | grep docker ii docker-ce 5:20.10.16~3-0~ubuntu-bionic amd64 Docker: the open-source application container engine ii docker-ce-cli 5:20.10.16~3-0~ubuntu-bionic amd64 Docker CLI: the open-source application container engine ii docker-ce-rootless-extras 5:20.10.16~3-0~ubuntu-bionic amd64 Rootless support for Docker. ii docker-scan-plugin 0.17.0~ubuntu-bionic amd64 Docker scan cli plugin. 设置docker开机自启动并现在启动docker。 root@ubuntuk8sclient:~# systemctl enable docker --now Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable docker 查看docker状态。 root@ubuntuk8sclient:~# systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2022-05-27 17:39:41 CST; 2min 27s ago Docs: https://docs.docker.com Main PID: 2574 (dockerd) Tasks: 8 CGroup: /system.slice/docker.service └─2574 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock May 27 17:39:37 ubuntuk8sclient dockerd[2574]: time="2022-05-27T17:39:37.223612352+08:00" level=info msg="ClientConn switching balancer to \"pick_first\"" module=grpc May 27 17:39:37 ubuntuk8sclient dockerd[2574]: time="2022-05-27T17:39:37.512415652+08:00" level=warning msg="Your kernel does not support swap memory limit" May 27 17:39:37 ubuntuk8sclient dockerd[2574]: time="2022-05-27T17:39:37.512456896+08:00" level=warning msg="Your kernel does not support CPU realtime scheduler" May 27 17:39:37 ubuntuk8sclient dockerd[2574]: time="2022-05-27T17:39:37.512593678+08:00" level=info msg="Loading containers: start." May 27 17:39:40 ubuntuk8sclient dockerd[2574]: time="2022-05-27T17:39:40.261550128+08:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used t 查看docker版本。 root@ubuntuk8sclient:~# docker --version Docker version 20.10.16, build aa7e414 配置docker阿里云镜像加速器。 root@ubuntuk8sclient:~# vim /etc/docker/daemon.json root@ubuntuk8sclient:~# cat /etc/docker/daemon.json { "registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"] } 重新加载配置文件,重启docker。 root@ubuntuk8sclient:~# systemctl daemon-reload ; systemctl restart docker root@ubuntuk8sclient:~# systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2022-05-27 17:45:41 CST; 5s ago Docs: https://docs.docker.com Main PID: 4330 (dockerd) Tasks: 8 CGroup: /system.slice/docker.service └─4330 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 下载一个nginx镜像。 root@ubuntuk8sclient:~# docker pull nginx root@ubuntuk8sclient:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 4 months ago 141MB 现在创建docker容器是没有限制的,可以自由创建和删除。关于docker容器的详细操作,请查看博客《一文搞懂docker容器基础:docker镜像管理,docker容器管理》。 #使用nginx镜像创建容器 root@ubuntuk8sclient:~# docker run -dit --name=nginxweb --restart=always nginx 16d5558fbe8d8956d61714326bea89e5a86424503c323dab03e729927f71fb5b #查看容器 root@ubuntuk8sclient:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 16d5558fbe8d nginx "/docker-entrypoint.…" 16 seconds ago Up 13 seconds 80/tcp nginxweb #删除容器 root@ubuntuk8sclient:~# docker rm -f nginxweb nginxweb root@ubuntuk8sclient:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6.2 docker安装OPA插件 在安装OPA插件之前,先介绍下docker插件常用命令,Docker插件是增强Docker引擎功能的进程外扩展。docker plugin命令用于管理插件。 docker plugin create #从rootfs和配置创建一个插件。插件数据目录必须包含config.json和rootfs目录。 docker plugin disable #禁用插件 docker plugin enable #启用插件 docker plugin inspect #显示一个或多个插件的详细信息 docker plugin install #安装一个插件 docker plugin ls #列出所有插件 docker plugin push #将插件推送到注册表 docker plugin rm #删除一个或多个插件 docker plugin set #更改插件的设置 docker plugin upgrade #升级现有插件 /etc/docker/policies用来存放opa规则。 root@ubuntuk8sclient:~# mkdir -p /etc/docker/policies root@ubuntuk8sclient:~# ls /etc/docker/ daemon.json key.json policies 查看docker插件,现在没有任何插件。 root@ubuntuk8sclient:~# docker plugin list ID NAME DESCRIPTION ENABLED 下载好的docker插件会放在/var/lib/docker/plugins/目录。 root@ubuntuk8sclient:~# ls /var/lib/docker/plugins/ storage tmp 安装OPA插件。 root@ubuntuk8sclient:~# docker plugin install openpolicyagent/opa-docker-authz-v2:0.8 opa-args="-policy-file /opa/policies/authz.rego" Plugin "openpolicyagent/opa-docker-authz-v2:0.8" is requesting the following privileges: - network: [host] - mount: [/etc/docker] Do you grant the above permissions? [y/N] y 0.8: Pulling from openpolicyagent/opa-docker-authz-v2 Digest: sha256:2fbbef244625e57f2beb7967a1b21c43ce5c7e6ec823fb1c35fe1b327ae3a1c4 cb581d64bd7f: Complete Installed plugin openpolicyagent/opa-docker-authz-v2:0.8 现在OPA插件就安装好了。 root@ubuntuk8sclient:~# docker plugin list ID NAME DESCRIPTION ENABLED 20b4566c59fc openpolicyagent/opa-docker-authz-v2:0.8 A policy-enabled authorization plugin for Do… true docker OPA插件安装好之后,在/var/lib/docker/plugins/目录下。 root@ubuntuk8sclient:~# ls /var/lib/docker/plugins/ 20b4566c59fc71641bda21da72d75299405e9c5c8b4cc859f6ab636f4f19cc52 storage tmp 查看OPA属性。 注意:"-policy-file /opa/policies/authz.rego"里的/opa不是操作系统里的/opa目录,而是/etc/docker/下的opa。 docker plugin inspect 20b4566c59fc显示的Mounts选项可以看出,/etc/docker目录挂载到/opa目录了,所以访问容器/opa目录就相当于访问宿主机/etc/docker目录。 root@ubuntuk8sclient:~# docker plugin inspect 20b4566c59fc [ { "Config": { ...... #注意:"-policy-file /opa/policies/authz.rego"里的/opa不是操作系统里的/opa目录,而是/etc/docker/下的opa, #docker plugin inspect 20b4566c59fc显示的Mounts选项可以看出,/etc/docker目录挂载到/opa目录了,所以访问容器/opa目录就相当于访问宿主机/etc/docker目录 "Mounts": [ { "Description": "", "Destination": "/opa", "Name": "policy", "Options": [ "bind", "ro" ], "Settable": [ "source" ], "Source": "/etc/docker", "Type": "none" } ], ...... "Mounts": [ { "Description": "", "Destination": "/opa", "Name": "policy", "Options": [ "bind", "ro" ], "Settable": [ "source" ], "Source": "/etc/docker", "Type": "none" } ] } } ] 6.3 启用OPA 安装OPA插件之后需要启用OPA,"authorization-plugins": ["openpolicyagent/opa-docker-authz-v2:0.8"]指定OPA插件。 root@ubuntuk8sclient:~# cd /etc/docker/policies/ root@ubuntuk8sclient:/etc/docker/policies# vim /etc/docker/daemon.json root@ubuntuk8sclient:/etc/docker/policies# cat /etc/docker/daemon.json { "registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"], "authorization-plugins": ["openpolicyagent/opa-docker-authz-v2:0.8"] } 重启docker,这样就启用了OPA。 root@ubuntuk8sclient:/etc/docker/policies# systemctl daemon-reload ; systemctl restart docker 七.OPA规则 7.1 使用OPA允许docker所有操作 下面开始编写OPA规则,OPA规则使用rego语言编写,allow := true 表示允许所有操作。 root@ubuntuk8sclient:/etc/docker/policies# vim authz.rego root@ubuntuk8sclient:/etc/docker/policies# cat /etc/docker/policies/authz.rego package docker.authz allow := true 可以查看镜像及其所有操作。 root@ubuntuk8sclient:/etc/docker/policies# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 5 months ago 141MB 7.2 使用OPA禁止docker所有操作 编辑OPA规则,allow := false表示禁止所有操作。 root@ubuntuk8sclient:/etc/docker/policies# vim /etc/docker/policies/authz.rego root@ubuntuk8sclient:/etc/docker/policies# cat /etc/docker/policies/authz.rego package docker.authz allow := false 现在docker的所有操作都执行不了了。 root@ubuntuk8sclient:/etc/docker/policies# docker images Error response from daemon: authorization denied by plugin openpolicyagent/opa-docker-authz-v2:0.8: request rejected by administrative policy root@ubuntuk8sclient:/etc/docker/policies# docker ps Error response from daemon: authorization denied by plugin openpolicyagent/opa-docker-authz-v2:0.8: request rejected by administrative policy 7.3 使用OPA禁止创建允许所有系统调用的docker容器 OPA规则设置为允许所有docker请求。 root@ubuntuk8sclient:/etc/docker/policies# vim /etc/docker/policies/authz.rego root@ubuntuk8sclient:/etc/docker/policies# cat /etc/docker/policies/authz.rego package docker.authz #allow := true允许所有docker请求 allow := true 使用nginx镜像创建一个允许所有系统调用的容器,--security-opt seccomp:unconfined表示允许所有系统调用。关于系统调用的详细操作,请查看博客《在kubernetes里使用seccomp限制容器的系统调用》。 root@ubuntuk8sclient:/etc/docker/policies# docker run -dit --restart=always --name=nginxweb --security-opt seccomp:unconfined nginx 033a0e8e38c56a00400eeefe5424f55ca953e320e6d668831f4cdc580837294f root@ubuntuk8sclient:/etc/docker/policies# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 033a0e8e38c5 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 80/tcp nginxweb 查看nginxweb的属性,在docker inspect nginxweb的输出中,可以看到HostConfig.SecurityOpt[seccomp:unconfined],创建docker指定的选项都可以在docker inspect里看到。 root@ubuntuk8sclient:/etc/docker/policies# docker inspect nginxweb [ { ...... "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": [ "seccomp:unconfined" ], "UTSMode": "", ...... "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ] 删除docker容器。 root@ubuntuk8sclient:/etc/docker/policies# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 033a0e8e38c5 nginx "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 80/tcp nginxweb root@ubuntuk8sclient:/etc/docker/policies# docker rm -f nginxweb nginxweb root@ubuntuk8sclient:/etc/docker/policies# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 修改OPA规则,现在OPA规则HostConfig.SecurityOpt[_] == "seccomp:unconfined"都deny了,所以docker指定--security-opt seccomp:unconfined选项时,就运行不了了。 root@ubuntuk8sclient:/etc/docker/policies# vim /etc/docker/policies/authz.rego root@ubuntuk8sclient:/etc/docker/policies# cat /etc/docker/policies/authz.rego package docker.authz #默认拒绝 default allow = false #allow这里可以写all,表示允许所有 #表示除了拒绝之外的那些都允许 allow { not deny } #表示拒绝seccomp_unconfined deny { seccomp_unconfined } #seccomp_unconfined的详细信息 seccomp_unconfined { # This expression asserts that the string on the right-hand side is equal # to an element in the array SecurityOpt referenced on the left-hand side. input.Body.HostConfig.SecurityOpt[_] == "seccomp:unconfined" } 现在允许所有系统调用的docker容器就创建不了了,备注:--security-opt seccomp:unconfined 表示允许所有的系统调用。 root@ubuntuk8sclient:/etc/docker/policies# docker run -dit --restart=always --name=nginxweb --security-opt seccomp:unconfined nginx docker: Error response from daemon: authorization denied by plugin openpolicyagent/opa-docker-authz-v2:0.8: request rejected by administrative policy. See 'docker run --help'. 创建普通的容器就可以成功。 root@ubuntuk8sclient:/etc/docker/policies# docker run -dit --restart=always --name=nginxweb nginx 304948d90988bbba4b7c0503980c60dfd636f2dccd33e90f2158fc93b6c7c63c root@ubuntuk8sclient:/etc/docker/policies# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 304948d90988 nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 80/tcp nginxweb root@ubuntuk8sclient:/etc/docker/policies# docker rm -f nginxweb nginxweb root@ubuntuk8sclient:/etc/docker/policies# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7.4 使用OPA根据Authz-User判断用户是否具有创建pod权限 使用harbor搭建一个镜像仓库,镜像仓库里新建项目,可以设置是否允许匿名用户pull镜像,如果设置了不允许匿名用户pull镜像,则客户端必须docker login登录才行,否则docker pull拉取不了镜像,docker push的话必须登录,不能匿名用户push镜像到镜像仓库。关于harbor镜像仓库的详细操作,请查看博客《搭建docker镜像仓库(二):使用harbor搭建本地镜像仓库》。 当我们使用docker login登录harbor之后,Docker 会将 token 存储在 ~/.docker/config.json 文件中,从而作为拉取私有镜像的凭证。 root@ubuntuk8sclient:~# mkdir ~/.docker root@ubuntuk8sclient:/etc/docker/policies# cat >~/.docker/config.json <<EOF > { > "HttpHeaders": { > "Authz-User": "alice" > } > } > EOF config.json表示现在是alice登录拉取私有镜像的。 root@ubuntuk8sclient:~# cat ~/.docker/config.json { "HttpHeaders": { "Authz-User": "alice" } } 编辑OPA规则,如果用户被授予读写权限,则允许创建容器。 root@ubuntuk8sclient:~# vim /etc/docker/policies/authz.rego root@ubuntuk8sclient:~# cat /etc/docker/policies/authz.rego package docker.authz #默认拒绝 default allow = false # allow if the user is granted read/write access. #如果用户被授予读写权限,则允许 allow { user_id := input.Headers["Authz-User"] user := users[user_id] not user.readOnly } # allow if the user is granted read-only access and the request is a GET. #如果用户被授予只读访问权限并且请求是GET,则允许 allow { user_id := input.Headers["Authz-User"] users[user_id].readOnly input.Method == "GET" } # users defines permissions for the user. In this case, we define a single # attribute 'readOnly' that controls the kinds of commands the user can run. #bob用户只读,alice用户读写 users := { "bob": {"readOnly": true}, "alice": {"readOnly": false}, } 现在是"Authz-User": "alice",alice具有读写权限,成功创建容器。 root@ubuntuk8sclient:~# docker run -dit --restart=always --name=nginxweb nginx e6aeb23a91a55fbad3fd5db9d0ac87ade1be13e990d17e6a29e9f0ca83cb5424 root@ubuntuk8sclient:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e6aeb23a91a5 nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 80/tcp nginxweb root@ubuntuk8sclient:~# docker rm -f nginxweb nginxweb 表示现在是bob登录拉取私有镜像的。 root@ubuntuk8sclient:~# vim ~/.docker/config.json root@ubuntuk8sclient:~# cat ~/.docker/config.json { "HttpHeaders": { "Authz-User": "bob" } } bob只有只读权限,并且只能执行get,创建容器失败。 root@ubuntuk8sclient:~# docker run -dit --restart=always --name=nginxweb nginx docker: Error response from daemon: authorization denied by plugin openpolicyagent/opa-docker-authz-v2:0.8: request rejected by administrative policy. See 'docker run --help'. 八.总结 本文介绍了如何使用 Open Policy Agent(OPA)为 Docker 容器提供访问控制。通过使用 OPA,我们可以轻松地实现细粒度的访问控制策略,从而提高 Docker 容器的安全性。