shellless 容器、binaryless 容器以及 distroless 容器

大家可能对 rootless 容器有一定的了解,rootless 容器说的是不要以 root 用户启动容器,以便简单 限制一下容器内进程的权限,一方面更符合安全上对权限控制的要求, 另一方面也可以抵御部分容器逃逸问题。

这里要介绍另一个容器安全方面的建议,那就是,应当尽可能的使用 shellless/shell-less 容器, 或使用 binaryless/binary-less 容器,甚至是使用 distroless 容器。

shellless/shell-less 容器

shellless 或者说 shell-less 容器, 顾名思义指的是 容器内不包含 shell

因为容器内不包含 shell,所以 shell-less 容器可以免疫部分的 get shell 攻击和 部分利用任意命令执行漏洞进行的攻击。

binaryless/binary-less 容器

binaryless 或者说 binary-less 容器,在 shell-less 容器的基础上更进一步, 容器内不包含除用户业务程序外的任何其他二进制可执行文件和脚本

因为不包含任何额外的二进制可执行文件,所以 binary-less 容器比 shell-less 容器能够免疫更多的利用任意命令执行漏洞进行的攻击。

distroless 容器

distroless 容器在 binary-less 容器的基础上又跟进了一步, 容器内不包含除用户业务程序及业务程序的运行时依赖外的任何其他程序、库以及非必须的系统文件

因为只包含业务程序及其依赖,所以 distroless 容器又比 binary-less 容器能免疫更多的漏洞攻击。

实现方案

目前社区使用的两类容器方案可以实现 shell-less 、 binary-less 或 distroless 容器:

  • 一类是使用 scratch 作为基础镜像,并且通过多阶段构建的方式 COPY 业务所需的内容,类似下面这样:

    FROM golang:1.16 as builder
    # ...
    RUN go build xxx
    
    FROM scratch
    COPY --from=builder /path/to/buld-files  /path/to/save
    # ...
    
  • 另一类是使用 https://github.com/GoogleContainerTools/distroless 项目提供的镜像作为基础镜像,并且通过多阶段构建的方式 COPY 业务所需的内容,类似下面这样:

    FROM gcr.io/distroless/base-debian10
    # ...
    RUN go build xxx
    
    FROM scratch
    COPY --from=builder /path/to/buld-files  /path/to/save
    # ...
    

当然,也可以其他方法实现类似 scratchgcr.io/distroless 这样的 shell-less 、 binary-less 或 distroless 的基础镜像, 然后按照类似上面的方法使用这些基础镜像来构建相应的业务镜像。

大家下次构建镜像的时候,推荐构建一个 shell-less 或 binary-less 的镜像,也可以尝试 distroless 镜像。 我后面也会根据自己的实践维护一个类似 https://github.com/GoogleContainerTools/distroless 的项目, 提供一些 binary-less 的基础镜像,以及相应的各个场景下使用 binary-less 可能会面临的一些问题的可行的解决方法。


Comments

comments powered by Disqus