• docker使用Open Policy Agent(OPA)进行访问控制


    一.系统环境

    本文主要基于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).
    #
    #                
    /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 < {
    >     "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 容器的安全性。

  • 相关阅读:
    D. Yet Another Problem
    盘点几种常用加密算法
    10. Spring源码篇之BeanPostProcessor
    kickstarter数据采集
    远程桌面软件是否支持远程访问远程网络监控系统
    爬虫是什么?爬虫的原理及应用
    【for lovelier】IDEA + LeetCode Editor 最佳实践
    软件测试周刊(第78期):你对未来越有信心,你对现在越有耐心。
    Python之函数详解
    Node-Web模块的用法
  • 原文地址:https://www.cnblogs.com/renshengdezheli/p/18233300