最近在研究容器镜像加密,发现国内对容器镜像这部分的博客好像不太多,在看了一些人的博客后,跟着他们的步骤进行了containerd imgcrypt的实践,期间出现了一些错误,决定记录一下,其他的博客链接第一篇,第二篇对容器镜像加密有兴趣的可以看一下。
- 1. 安装containerd imgcrypt
- 2. 运行containerd进程
- 3. 加密镜像
- 3.1 通过openssl创建密钥
- 3.2 拉取镜像,用于加密
- 3.3 加密镜像
- 3.4 仓库操作
- 3.5 运行容器
- 3.6 注意
首先还是需要golang环境,可以根据我安装skopeo这篇文章的安装go环境部分,然后开始安装containerd imgcrypt,如果make和make install命令出错可以加上sudo。
$ git clone https://github.com/containerd/imgcrypt.git $GOPATH/src/github.com/containerd/imgcrypt $ cd $GOPATH/src/github.com/containerd/imgcrypt && make && make install
安装后会在/usr/lcoal/bin/目录下出现ctr-enc和ctd-decoder: 1. ctr-enc:一个类似container ctr的CLI工具,但是内置了加密镜像的标注 2. ctd-decoder:一种处理二进制文件的流,用于处理加密层输入流的解密2. 运行containerd进程
这个进程主要是用来接收ctr-enc对容器操作的请求,同时在启动containerd进程的时候要指定遇见加密mediatype的镜像层的时候交给ctd-decoder处理,需要修改的配置文件为/etc/containerd/config.toml,在第一文章中,博主直接在~/目录下创建config.toml,运行时指定该文件为containerd的配置文件,但是我尝试的时候出现了如下错误,所以还是配置/etc/containerd/config.toml里面吧。也有人出现这个错误是因为虚拟机的内存过小,可以设置大一些
出现错误:
ctr: dial unix /run/containerd/s/93a997343d64b0d227f3d75dcd0ed893d2e6d255ab41c328a621128b206c54d8: connect: connection refused: unknown
安装containerd:
$ wget https://github.com/containerd/containerd/releases/download/v1.3.0/containerd-1.3.0.linux-amd64.tar.gz $ tar -xzf containerd-1.3.0.linux-amd64.tar.gz $ ls bin/ containerd containerd-shim containerd-shim-runc-v1 containerd-shim-runc-v2 containerd-stress ctr
在/etc/containerd/config.toml文件中配置如下
disable_plugins = ["cri"]
root = "/tmp/var/lib/containerd"
state = "/tmp/run/containerd"
[grpc]
address = "/tmp/run/containerd/mycontainerd.sock"
uid = 0
gid = 0
[stream_processors]
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
returns = "application/vnd.oci.image.layer.v1.tar+gzip"
path = "/usr/local/bin/ctd-decoder"
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
returns = "application/vnd.oci.image.layer.v1.tar"
path = "/usr/local/bin/ctd-decoder"
启动containerd进程,并指定配置文件
$ sudo containerd -c /etc/containerd/config.toml3. 加密镜像 3.1 通过openssl创建密钥
下面的命令将创建一个公钥和私钥
$ openssl genrsa --out mykey.pem Generating RSA private key, 2048 bit long modulus (2 primes) ...............................................+++++ ............................+++++ e is 65537 (0x010001) $ openssl rsa -in mykey.pem -pubout -out mypubkey.pem writing RSA key3.2 拉取镜像,用于加密
$ sudo ctr-enc images pull --all-platforms docker.io/library/bash:latest
可以通过ctr-enc image layerinfo来查看image的信息或者ctr-enc image list来查看所有的镜像
$ sudo ctr-enc images layerinfo --platform linux/amd64 docker.io/library/bash:latest $ sudo ctr-enc images list3.3 加密镜像
$ sudo ctr-enc images encrypt --recipient jwe:mypubkey.pem --platform linux/amd64 docker.io/library/bash:latest bash.enc:latest Encrypting docker.io/library/bash:latest to bash.enc:latest
参数解析: --recipient jwe:mypubkey.pem:表示我们使用刚才生成的公钥来加密镜像,jwe代表使用JSON Web加密方案 --platform linux/amd64:表示仅加密linux/amd64平台的镜像 docker.io/library/bash:latest:要加密的镜像 bash.enc:latest:加密后生成的镜像的tag 可以使用--layer参数来选择仅加密某些layer3.4 仓库操作
将镜像push到仓库,删除本地镜像然后再拉取,仓库为本地仓库,可以通过docker来创建,仓库的版本需要高于2.7.1,文章中写道Docker Hub还不支持加密的镜像,但是IBM Container Registry支持,我没有进行尝试。
# 创建本地仓库 $ sudo docker run -d -p 5000:5000 --restart=always --name registry registry:2.7.1 # 可以使用sudo docker ps 来查看容器创建情况 $ sudo docker ps
# 为加密容器创建另一个tag $ sudo ctr-enc images tag bash.enc:latest localhost:5000/bash.enc:latest # 将镜像push到仓库中,如果镜像没有push,可以加上--plain-http参数试试看 $ sudo ctr-enc images push localhost:5000/bash.enc:latest # 将本地两个加密的镜像删除 $ sudo ctr-enc images rm localhost:5000/bash.enc:latest bash.enc:latest # 拉取加密镜像,如果镜像没有pull,可以加上--plain-http参数试试看 $ sudo ctr-enc images pull localhost:5000/bash.enc:latest3.5 运行容器
对比有私钥和没有私钥的差别
# 没有私钥,无法运行 $ sudo ctr-enc run --rm localhost:5000/bash.enc:latest test echo 'Hello World!' ctr: you are not authorized to use this image: missing private key needed for decryption # 带上公钥,可以运行 $ sudo ctr-enc run --rm --key mykey.pem localhost:5000/bash.enc:latest test echo 'Hello World!' Hello World!3.6 注意
另外一点,可以直接使用私钥对镜像进行解密,然后使用解密后的镜像运行容器
$ sudo ctr-enc images decrypt --key mykey.pem --platform linux/amd64 localhost:5000/bash.enc:latest localhost:5000/bash.dec:latest



