AppArmor 是一个 Linux 内核安全模块,可用于限制主机操作系统上运行的进程的功能。每个进程都可以拥有自己的安全配置文件。安全配置文件用来允许或禁止特定功能,例如网络访问或文件读/写/执行权限。
您可以将 AppArmor 与在 Container-Optimized OS 实例上运行的 Docker 容器配合使用。对于任何给定容器,您可以应用 Docker 附带的默认 AppArmor 安全配置文件,也可以应用自己提供的自定义安全配置文件。
使用默认的 Docker AppArmor 安全配置文件
在 Container-Optimized OS 实例上启动容器时,系统会自动应用 docker-default
安全配置文件。以下命令演示了使用 docker-default
安全配置文件运行容器:
docker run --rm -it debian:jessie bash -i
要测试 docker-default
安全配置文件,可以尝试使用 cat
命令读取 /proc/sysrq-trigger
文件,如下所示:
root@88cef496c1a5:/# cat /proc/sysrq-trigger
输出应包含“没有权限”错误,如下所示:
cat: /proc/sysrq-trigger: Permission denied
应用自定义安全配置文件
要应用其他安全配置文件,请在运行容器时使用 apparmor=<profile-name>
命令行选项。以下命令演示了使用安全配置文件 no-ping
运行容器:
docker run --rm -i --security-opt apparmor=no-ping debian:jessie bash -i
有关创建示例中指定的 no-ping
配置文件的详细信息,请参阅本主题后文中的创建自定义安全配置文件。
您还可以将 apparmor
选项指定为 unconfined
,以表示要在没有安全配置文件的情况下运行容器,如下例所示:
docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i
查看活跃的 AppArmor 安全配置文件
您可以通过检查 /proc/<pid>/attr/current
文件来查看系统将哪个 AppArmor 配置文件(如果有)应用于 Container-Optimized OS 实例上的进程,其中 <pid>
是进程 ID。
假设实例上运行有以下进程(通过 ps -ef | grep '[b]ash -i'
命令显示):
root 1903 1897 0 21:58 pts/3 00:00:00 docker run --rm -it debian:jessie bash -i
root 1927 1913 0 21:58 pts/4 00:00:00 bash -i
root 1978 1001 0 22:01 pts/0 00:00:00 docker run --rm -it --security-opt apparmor=unconfined debian:jessie bash -i
root 2001 1988 0 22:01 pts/2 00:00:00 bash -i
如果检查 /proc/1927/attr/current
,您将看到以下输出,表示该进程 (pid 1927
) 使用默认 Docker 安全配置文件运行:
# cat /proc/1927/attr/current
docker-default (enforce)
如果检查 /proc/2001/attr/current
,您将看到以下输出,表示在没有安全配置文件的情况下(使用选项 apparmor=unconfined
)运行进程 (pid 2001
):
# cat /proc/2001/attr/current
unconfined
创建自定义安全配置文件
如果进程需要 docker-default
外的其他安全配置文件,您可以编写自己的自定义配置文件。要使用自定义配置文件,您必须创建配置文件,然后将该文件加载到 AppArmor 中。
例如,假设您需要一个禁止所有原始网络流量的安全配置文件。以下脚本演示了在 /etc/apparmor.d/no_raw_net
下创建名为 no-ping
的安全配置文件:
cat > /etc/apparmor.d/no_raw_net <<EOF
#include <tunables/global>
profile no-ping flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network inet tcp,
network inet udp,
network inet icmp,
deny network raw,
deny network packet,
file,
mount,
}
EOF
创建安全配置文件后,可以使用 apparmor_parser
将配置文件加载到 AppArmor 中:
/sbin/apparmor_parser --replace --write-cache /etc/apparmor.d/no_raw_net
加载 no-ping
配置文件后,您可以使用以下命令对配置文件进行测试:
$ docker run --rm -i --security-opt apparmor=no-ping debian:jessie ping -c3 8.8.8.8
该命令创建了使用 no-ping
安全配置文件的容器,并尝试在容器中运行 ping
。安全配置文件会禁止该流量,从而导致如下错误:
ping: Lacking privilege for raw socket.
要确保启动 Container-Optimized OS 实例时存在自定义安全配置文件,且配置文件在重新启动后仍然存在,可以使用 cloud-init
在 /etc/apparmor.d
中安装该配置文件。要执行此操作,请将 cloud-config
脚本添加到实例的元数据中,作为 user-data
键的值。
以下 cloud-config
脚本演示了将 no-ping
配置文件添加到 /etc/apparmor.d
中:
#cloud-configs
write_files:
- path: /etc/apparmor.d/no_raw_net
permissions: 0644
owner: root
content: |
#include <tunables/global>
profile no-ping flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network inet tcp,
network inet udp,
network inet icmp,
deny network raw,
deny network packet,
file,
mount,
}
要确保您的服务文件能将自定义配置文件加载到 AppArmor 并告知 Docker 使用该配置文件,请在您的实例上运行以下命令:
ExecStartPre=/sbin/apparmor_parser -r -W /etc/apparmor.d/no_raw_net
ExecStart=/usr/bin/docker run --security-opt apparmor=no-ping ...
运行命令后,重新启动实例,然后便可以运行受自定义 AppArmor 配置文件约束的容器。