解释 AppArmor 的“帽子”机制如何限制容器文件访问

解读

国内面试官问这道题,并非要求背诵 AppArmor 源码,而是验证候选人是否能把“容器=进程”这一本质与 Linux 强制访问控制(MAC)打通。帽子(hat)是 AppArmor 的子配置文件,在容器场景下由 docker-default 或自定义 profile 动态加载,能把容器主进程及其子进程进一步细分为不同“角色”,每个角色只拿到最小文件系统视图。答出“帽子=动态切换的上下文”+“容器运行时通过 change_hat 完成域切换”+“拒绝默认读写,只允许显式白名单”这三点,就能体现安全与容器双修能力。

知识点

  1. AppArmor 基础:内核级 MAC,按路径做白名单,默认拒绝
  2. Profile 与 Hat:profile 对应完整策略;hat 是 profile 内的具名段落,通过 change_hat() 系统调用动态切换,无需创建新进程。
  3. Docker 集成:dockerd 为每个容器生成 /etc/apparmor.d/docker-default,若镜像带自定义 profile 则挂载至容器内;容器主进程先进入 docker-default 上下文,后续可按逻辑进入不同 hat
  4. 文件访问限制流程:
    • 容器启动:内核把容器主进程绑定到 docker-default 的“主域”。
    • 业务逻辑触发 change_hat("web-hat", magic_token) → 内核验证 token 合法后切到 web-hat 域。
    • web-hat 段内仅声明 /var/www/ rw, /tmp/** rwk, deny /etc/shadow r**,其他路径命中默认拒绝。
    • 若子进程尝试读 /host/sys/fs/cgroup,当前上下文无匹配规则,内核返回 EACCES,容器日志出现 denied 审计
  5. 与 Capability 区别:帽子解决“谁能访问哪段路径”,Capability 解决“谁能执行哪类特权操作”,二者互补。

答案

AppArmor 的“帽子”机制把同一容器内的不同执行阶段或子进程进一步隔离成子安全域,实现路径级最小权限。Docker 在启动容器时把主进程绑定到 docker-default profile;业务代码或入口脚本通过 change_hat("hat_name", token) 切换到对应帽子。进入帽子后,内核只放行该帽子段内显式声明的文件访问规则,未列出的路径一律拒绝。例如 web-hat 只允许读写 /var/www 与 /tmp,任何尝试越权访问宿主机 /proc、/sys 或容器内 /etc/shadow 的操作都会被内核拦截并记录,既防止容器逃逸,也限制横向移动。若需更细粒度,可在 Dockerfile 中打包自定义 profile,通过 docker run --security-opt apparmor=custom_profile 加载,实现“镜像即策略”的交付模式

拓展思考

  1. 国内金融云常要求等保 2.0 三级,帽子机制可与 seccomp、drop Cap 组合成“三合一最小权限”方案,审计日志直接对接 ELK/盘古,满足合规。
  2. 多租户平台可把租户的敏感目录挂载为只读,在 hat 里显式 deny 写操作,即使容器被提权也无法修改宿主共享库。
  3. 与 SELinux 对比:AppArmor 路径语义简单,适配 Ubuntu/国产麒麟默认内核,上线成本低;SELinux 类型强制更细,但策略编写复杂,国内政企场景需权衡运维人力
  4. 未来趋势:Kubernetes 1.30+ 已支持 AppArmorProfile CRD,可把帽子策略随 Pod YAML 一起 GitOps,实现“策略即代码”,面试可提及自己用 Kubescape 或 OPA 做静态预检,展示云原生安全闭环能力。