最小权限是门槛,不是感觉
最小权限是把某项明确工作需要的操作,授予正确主体,并限定资源范围与有效时间。它是一份能够验证的政策,而不是令人安心的标签。应从服务实际启动身份和依赖开始梳理;闲置权限与缺失权限是不同发现,不能用同一种处理方式解决,也不能因为一个接口暂时调用成功就认为边界已经合适。 把最小值写清楚 列出服务读取的文件、写入的目录、需要访问的网络目标以及管理操作,同时覆盖启动、日志、轮转、恢复与退出。业务数据虽然只在一个目录,服务仍可能合理地需要临时空间和共享库。一份有用清单解释每项访问为什么存在,而不是笼统宣称数据目录以外的一切都不必要,更不应遗漏低频但关键的恢复路径。 对 systemd 单元,User= 与 Group= 决定运行身份,文件权限和沙箱设置进一步约束行为。ProtectSystem=strict 使单元视图中的大部分文件系统只读,但 API 文件系统有文档规定的例外,也可能另行开放写入路径。只读不等于不可读;若目的是保护秘密内容,需要独立的访问权限或可见性约束,例如适合当前服务的 ProtectHome= 政策,不能把写入失败当作读取也被隔离的证明。 检验具体边界 不同指令解决不同问题。PrivateDevices= 限制设备暴露,NoNewPrivileges= 防止通过执行程序取得新权限,RestrictAddressFamilies= 限制套接字地址族。最后这一项不是目标地址或端口防火墙。内核支持、系统或用户服务管理器、既有描述符和其他设置,都可能影响实际效果;列出一串指令名称,并不能证明已经拥有完整沙箱。 单项 capability 可能比不受限 root 更窄,却未必是一项很小的权限,其中有些覆盖广泛管理操作。授予之前,应查看它实际允许什么,以及文件所有权、ACL 或独立受限辅助程序能否更好地满足需求。测试时要在真实服务上下文中同时执行一个应允许的操作和一个相邻但应拒绝的操作,分别记录结果,避免管理员手动验证掩盖服务自身边界。 宽权限为什么总会留下来 事件期间的临时授权经常活得比事件更久。应记录负责人、原因和到期或复核时间,使恢复权限不会悄悄成为日常权限。变更后比较线上绑定与获准政策;源码仓库中存在配置文件,并不说明正在运行的工作负载真的使用了它。临时例外需要明确归宿,而不能只靠某个人记得事后撤销。 凭据寿命属于另一项控制。范围较窄的令牌在有效期内仍可被滥用,轮换权限过大的凭据也不会自动减少权限。应使用适当限定的凭据,避免把它们复制到日志或运维手册。复核既要看它能做什么,也要看工作或人员关系结束后如何撤销;权限范围、保存方式与有效时间共同决定暴露,不能互相替代。 坏掉的样子 在 Kubernetes 中,通配动词与资源会在规则的 API 组和绑定范围内授予广泛权限,但并不自动等于跨所有组和命名空间的集群管理员。即便如此,新出现的匹配资源或动词仍可能无需再次修改政策就得到授权。判断实际权限时,需要检查主体、命名空间、资源名和全部叠加授权,不能看到一个很窄的 Role 就认为总权限也一样窄。 一段时间没有使用,只能成为复核线索,不能直接证明权限应删除。恢复操作可能很重要,却不会出现在普通一周的记录里。反过来,某个角色使用过某项动作,也不能成为给所有角色都保留它的理由。使用记录应按身份和角色关联;例外需要业务依据,不能把一份全局动作集合误当作逐角色的授权证据。 过度收紧可能阻断合法发布,并诱使人绕过正规流程。删除权限之前,应提供且验证更窄的受支持路径。身份模拟本身也受权限控制,不是加一个参数就凭空变成管理员。紧急运维流程应保留责任与记录,而不是让工作流转入秘密共享账号,再把正规路径的零授权当成安全成功。 快速验证 保存为 privilege_audit.py,运行 python3 privilege_audit.py。标准库模型回放七次合成请求,另外按每个角色独立的合成复核窗口记录比较授权与使用。它不读取凭据、不查询生产身份,也不修改任何权限,因此可以安全地观察纯集合判定,同时明确实际授权验证仍然另有工作。 ...