环境变量与文件挂载,差别在哪
本实验在真正的 VM 中运行
这个环境不是 Pod,而是由 KubeVirt 启动的虚拟机。Linux 内核独立运行,systemd 真正管理服务,docker 是真正的 Docker 引擎。通过 docker run 启动的容器会成为实际进程,docker exec 和 docker logs 均可正常工作。
过去本实验在放弃全部内核权限的 Pod 中运行,无法启动容器,只能绕道解开镜像归档。现在不再需要绕路。
请了解两点:
- **首次启动约需 1 分钟。**VM 要启动并安装 Docker,比通常约 40 秒的 Pod 实验更慢。
- **没有浏览器预览。**进入 VM 的连接只开放评分端口。启动 Web 服务器后,请在 VM 内用
curl检查。
目标
分别以环境变量和文件挂载传递同一密钥,亲自测量它是否暴露于 docker inspect,以及能否在不重启的情况下轮换,并整理成比较表。最后编写简单的密钥检测脚本。
为什么重要
环境变量不是存储位置,而是传递方式。进程存活期间,/proc/<pid>/environ 始终可读;任何能访问容器守护进程的人都能通过 docker inspect 直接看到容器环境变量。因此,“加载后删除 .env 就安全了”毫无依据。轮换更加重要:环境变量在进程启动时固定,修改必须重启;文件挂载若原地覆盖同一 inode,则无需重启即可看到新值。凭据泄露后,从撤销、替换到恢复服务所需的时间,正体现团队的密钥管理水平。
步骤
- 创建
/root/sec3,在/root/sec3/app.env中写一行API_KEY=labhub-env-key-v1,再将权限改为600。 - 使用
alpine:3.20创建sec3-env容器,通过--env-file /root/sec3/app.env在后台运行。容器中的API_KEY必须与文件值相同。 - 将通过
docker inspect sec3-env读取的API_KEY值原样保存到/root/sec3/leak-proof.txt。 - 在
/root/sec3/secret.txt中写入labhub-file-key-v1,把该文件以只读绑定挂载到sec3-file容器的/run/secrets/api_key,并在后台运行。挂载源必须正好是/root/sec3/secret.txt。 sec3-file容器的环境变量中既不能有API_KEY,也不能有密钥值本身。- 不重启容器,将
/root/sec3/secret.txt原地覆盖为labhub-rotated-v2。sec3-file应看到新值,而sec3-env的环境变量仍应保留旧值。在/root/sec3/rotate.md中写明哪种方式需要重启(必须包含재시작或restart)。 - 编写可执行的
/root/sec3/find-secrets.sh。递归搜索第一个参数指定的目录;若发现以AKIA开头的访问密钥或PRIVATE KEY块,应以非 0 退出码结束并输出发现它的文件路径;若没有发现,退出码应为 0。 - 在
/root/sec3/secrets.md中比较环境变量和文件挂载,并严格包含以下四行。env_visible_in_inspect=yesmount_visible_in_inspect=noenv_needs_restart=yesmount_needs_restart=no
参考
- 修改权限使用
chmod 600 <파일>,检查权限使用stat -c %a <파일>。 - 只读挂载单个文件使用
-v /호스트/경로:/컨테이너/경로:ro格式。 - 查看容器环境变量使用
docker inspect <이름> | jq -r '.[0].Config.Env[]'。 - 第 6 步覆盖文件时,应像
printf '%s' labhub-rotated-v2 > /root/sec3/secret.txt一样进行原地覆盖。 - 常见错误 1:第 6 步使用
sed -i,或删除后重建文件,会改变 inode,使容器继续看到旧文件。 - 常见错误 2:第 4 步若同时给
sec3-file传入-e API_KEY=...,第 5 步会失败。改用文件挂载后应移除环境变量。 - 常见错误 3:第 6 步若重建
sec3-env或同时修改 app.env,会失去对照组。请保持sec3-env不变。
密钥文件与 600 权限
创建 /root/sec3,在 /root/sec3/app.env 中写一行 API_KEY=labhub-env-key-v1,再将权限改为 600。
评分重点不仅是值,还有文件权限。只有所有者可以读写,组和其他用户不能有任何权限。请先创建文件,再修改权限。
通过 env-file 注入
使用 alpine:3.20 创建 sec3-env 容器,通过 --env-file /root/sec3/app.env 在后台运行。容器中的 API_KEY 必须与文件值相同。
把值直接写在命令行会留在 Shell 历史和进程列表中。请用从文件读取并注入的选项。评分会比较容器环境变量与文件值,因此容器必须持续运行。
环境变量会直接暴露在 inspect 中
将通过 docker inspect sec3-env 读取的 API_KEY 值原样保存到 /root/sec3/leak-proof.txt。
只要能访问守护进程,即使不是容器创建者也能读取该值。不要猜测,请实际通过 docker inspect 提取并原样保存。
以文件方式挂载
在 /root/sec3/secret.txt 中写入 labhub-file-key-v1,把该文件以只读绑定挂载到 sec3-file 容器的 /run/secrets/api_key,并在后台运行。挂载源必须正好是 /root/sec3/secret.txt。
这是把一个主机文件直接挂到容器特定路径的方式。源路径和目标路径都会评分,必须准确;由于是密钥,还必须以只读方式挂载。
不要留在环境变量中
sec3-file 容器的环境变量中既不能有 API_KEY,也不能有密钥值本身。
改用文件挂载后,没有理由再通过环境变量传递同一值。两种方式并用会让密钥再次暴露在 inspect 中。请确认第 4 步容器没有混入环境变量。
无需重启地轮换
不重启容器,将 /root/sec3/secret.txt 原地覆盖为 labhub-rotated-v2。sec3-file 应看到新值,而 sec3-env 的环境变量仍应保留旧值。在 /root/sec3/rotate.md 中写明哪种方式需要重启(必须包含 재시작 或 restart)。
绑定挂载跟随 inode。原地覆盖(重定向)后容器会立即看到新值;删除再创建(某些编辑器或 sed -i)会更换 inode,使挂载继续指向旧文件。环境变量绝不能变化,它是本步骤的对照组。
密钥检测脚本
编写可执行的 /root/sec3/find-secrets.sh。递归搜索第一个参数指定的目录;若发现以 AKIA 开头的访问密钥或 PRIVATE KEY 块,应以非 0 退出码结束并输出发现它的文件路径;若没有发现,退出码应为 0。
递归搜索两种模式:以 AKIA 开头的访问密钥和 PRIVATE KEY 块头。干净时返回 0,发现时返回非 0,并输出所在文件路径。也请思考这种规则只擅长识别形态明确的值这一局限。
传递方式比较表
在 /root/sec3/secrets.md 中比较环境变量和文件挂载,并严格包含以下四行。
env_visible_in_inspect=yesmount_visible_in_inspect=noenv_needs_restart=yesmount_needs_restart=no
四行的值必须与前面亲自确认的结果一致。回顾第 3 步看到了什么、第 5 步没有看到什么,以及第 6 步哪种方式需要重启。正文还必须同时提到环境变量方式和挂载方式。