:IAM 策略、内置角色模板与 SSE-KMS 数据面强制详解)
RustFS 每密钥 KMS 授权Per-key KMS AuthorizationIAM 策略、内置角色模板与 SSE-KMS 数据面强制详解【免费下载链接】rustfs2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting migration and coexistence with other S3-compatible platforms such as MinIO and Ceph.项目地址: https://gitcode.com/GitHub_Trending/rus/rustfs本篇技术指南以 RustFS 操作文档 docs/operations/kms-per-key-authorization.md 为主体结合 crates/policy 与 rustfs/src/admin/route_policy.rs 源码系统讲解 RustFS 如何基于身份策略identity policy对 KMS 密钥做细粒度授权包括 KMS 资源 ARN 语法、内置 KMS 角色模板、管理端点与 SSE-KMS 数据路径两层强制执行以及从全集群共享密钥权限平滑迁移到每密钥授权的落地步骤。读者读完后可以独立编写限定到指定密钥的 IAM 策略、正确组合内置 KMS 角色并安全地开启RUSTFS_KMS_ENFORCE_SSE_KEY_POLICY数据面强制。RustFS 的 KMS 授权建立在身份策略之上一条 Statement 可以声明它作用于哪些密钥因此kms:DisableKey这样的授权不再隐含集群内所有密钥一次 SSE-KMS 请求也会被拿实际解析到的密钥来校验。本文覆盖资源语法、内置角色模板、两层强制执行平面管理端点 SSE-KMS 数据路径以及迁移路径。关于各后端主密钥master key材料存放位置参见 KMS 后端安全属性管理 API 的完整端点矩阵见 KMS 管理 API 契约。KMS 资源语法KMS 资源使用与 S3 资源相同的空账户empty-accountARN 形式即arn:aws:kms:::之后直接跟资源段。下表为基本匹配规则模式匹配范围arn:aws:kms:::key/key_id精确匹配该密钥arn:aws:kms:::key/app-*匹配所有以app-开头的 key idarn:aws:kms:::*匹配所有密钥arn:aws:kms:::alias/name预留在别名解析alias resolution落地前不匹配任何请求以上语法并非文档层面的约定而是 crates/policy/src/policy/resource.rs 中Resource::KMS_PREFIX、KMS_KEY_SEGMENT与KMS_ALIAS_SEGMENT三个常量定义的硬性规则请求侧 KMS 资源串总是key/key_id形式与这些模式逐一对齐alias/段虽可解析、可校验但请求总是按key/key_id求值因此在别名解析功能落地前arn:aws:kms:::alias/*永远不会匹配任何请求源码注释与测试kms alias never matches key均印证了这一点。该模块对 KMS 资源还做了严格的格式校验Validator for Resource裸*合法key/之后的 id 不能为空、不能包含/或\各 KMS 后端会拒绝含分隔符的密钥名alias/之后的名称不能为空、不能包含\但允许嵌套如alias/aws/s3。带 region 与 account 的标准 AWS 形式如arn:aws:kms:us-east-1:123456789012:key/mykey会被拒绝——RustFS 使用空账户形式与 S3 资源保持一致。写策略之前需要知道的规则一条 Statement 若混用kms:动作与s3:动作会被拒绝。KMS 授权必须放在独立 Statement 中。一条 Statement 若携带 KMS 资源却配非 KMS 动作会被拒绝。KMS Statement不写资源时匹配所有密钥——这是遗留形式且保持有效因此已有策略的效果不会改变。KMS Statement 的资源写成 S3 ARN 时属于早于 KMS 资源支持的旧策略。它仍可加载但 S3 模式从未真正约束过密钥访问求值时会忽略这些资源、把 Statement 当作未限定范围unscoped处理并打印告警日志。建议用真正的 KMS 资源重写这些策略。PutBucketPolicy会拒绝任何携带kms:动作或 KMS 资源的 Statement——KMS 授权只属于身份identity不属于桶策略。在此检查之前已存储的桶策略仍可加载求值时跳过其纯 KMS Statement 并告警。与其他所有场景一致Deny优先对arn:aws:kms:::key/payroll-*的Deny会覆盖对arn:aws:kms:::*的Allow。参与匹配的 key id 是请求中直接指名的那个在别名解析之前。资源匹配采用通配符算法实现*、?等模式与 S3 资源共用同一套匹配逻辑路径遍历类输入如key/mykey/../otherkey会被 clean 后拒绝匹配。完整的正反例可见 resource.rs 中的test_resource_is_match与test_kms_resource_parse测试。内置 KMS 角色模板RustFS 在readwrite、readonly、writeonly、diagnostics与consoleAdmin之外还随附三套 KMS 预置策略定义于 crates/policy/src/policy/policy.rs策略授予动作面向对象KMSKeyAdministratorkms:DescribeKey、kms:ListKeys、kms:EnableKey、kms:DisableKey、kms:RotateKey、kms:DeleteKey负责密钥生命周期治理的团队KMSKeyUserkms:GenerateDataKey、kms:Decrypt、kms:DescribeKey读写 SSE-KMS 对象的工作负载KMSAuditorkms:DescribeKey、kms:ListKeys只需可见性、无需其他能力的审计人员这三套模板体现了职责分离separation of dutiesKMSKeyAdministrator可以禁用或删除密钥但永远无法用它加解密KMSKeyUser可以使用密钥但永远无法改变其状态。该约束由 policy.rs 中的模板测试逐一断言例如KMSKeyAdministrator不允许kms:GenerateDataKey/kms:DecryptKMSKeyUser不允许kms:EnableKey/kms:DisableKey/kms:RotateKey/kms:DeleteKey。三个模板都不授予kms:Configure、kms:ServiceControl、kms:ClearCache、kms:Backup或kms:Restore。这些动作作用于 KMS 服务本身或一次性波及所有密钥的材料属于集群管理权限而非密钥管理权限因此仍归consoleAdmin所有。密钥创建目前与kms:Configure共享后端配置动作所以创建密钥同样是consoleAdmin操作——这一点与 KMS 管理 API 契约 中POST /kms/keys映射到kms:Configure的端点矩阵一致。模板本身不带任何 S3 或 admin 授权因此需要与数据面策略组合使用。策略映射policy mapping接受逗号分隔列表例如将KMSKeyUser与readwrite一并挂到某个用户PUT /rustfs/admin/v3/set-user-or-group-policy?policyNamereadwrite,KMSKeyUseruserOrGroupapp-writerisGroupfalse三个模板默认也是未限定范围的arn:aws:kms:::*与其他预置策略行为一致。要实现最小权限应复制一份并按工作负载收窄例如{ Version: 2012-10-17, Statement: [ { Effect: Allow, Action: [s3:*], Resource: [arn:aws:s3:::reports, arn:aws:s3:::reports/*] }, { Effect: Allow, Action: [kms:GenerateDataKey, kms:Decrypt, kms:DescribeKey], Resource: [arn:aws:kms:::key/reports-*] } ] }注意这里的 KMS 与 S3 授权被拆成了两条独立 Statement——这正是前述KMS 动作不得与 S3 动作混用规则的实际体现。KMS 动作全集含kms:Rekey批量重封装等定义在 crates/policy/src/policy/action.rs 的KmsAction枚举中kms:*通配同样可用。两层强制执行平面RustFS 的每密钥授权在两个平面上生效管理端点和 SSE-KMS 数据路径。前者始终开启、无需迁移后者默认关闭、需要显式开启并先做准备。管理端点Admin endpoints所有指名密钥的/rustfs/admin/v3/kms/...端点都针对该密钥做授权。密钥标识取自请求体中的key_id缺失时回退到keyId查询参数。不指名密钥的端点例如GET /rustfs/admin/v3/kms/keys则与从前一样匹配策略中的任意 KMS 资源。哪些路由是 per-key即按它指名的密钥授权、哪些是集群级匹配任意 KMS 资源在 rustfs/src/admin/route_policy.rs 中逐一登记GET /kms/keys/{key_id}、DELETE /kms/keys/delete、POST /kms/keys/{enable|disable|rotate|cancel-deletion|update-description|tag|untag}、POST /kms/generate-data-key等属于 per-key而kms:Configureconfigure/reconfigure/keys 创建、kms:ServiceControlstart/stop/reload/status、kms:ClearCache、kms:Backup、kms:Restore、kms:Rekey均为集群级动作与 KMS 管理 API 契约 的端点矩阵一一对应。该映射由route_registration_test等测试断言保护。这一平面始终开启无需迁移从未提及 KMS 资源的策略依然匹配所有密钥行为不变。SSE-KMS 数据路径在数据路径上一次 SSE-KMS 写入额外要求调用方具备kms:GenerateDataKey一次 SSE-KMS 读取额外要求kms:Decrypt两者都以发起请求的身份、针对请求实际解析到的密钥求值。这堵住了混淆代理人confused deputy缺口此前服务器以自身权限代表任意持有s3:PutObject的调用方调用 KMS调用方本人却不需要任何 KMS 授权。实现层面开关定义于 crates/config/src/constants/app.rs环境变量RUSTFS_KMS_ENFORCE_SSE_KEY_POLICY默认值DEFAULT_KMS_ENFORCE_SSE_KEY_POLICY false求值与告警逻辑位于 rustfs/src/storage/sse.rs。范围与豁免细节如下仅限 SSE-KMS。SSE-S3 的数据密钥由服务器持有的密钥包裹、调用方从不指名SSE-C 则根本不触达 KMS。两者都豁免与 AWS 行为一致。校验的是实际解析到的密钥而非请求头。桶默认加密规则指名的 KMS 密钥与显式x-amz-server-side-encryption-aws-kms-key-id请求头走完全相同的授权路径。匿名请求一律拒绝。匿名调用方没有身份策略、自然没有任何kms授权因此开启强制后对 SSE-KMS 对象的每次匿名读写都会以AccessDenied失败——即使桶策略已将该桶设为公开与 AWS 一致同时堵住了在公开桶上丢弃凭证的绕过路径。因此对外提供 SSE-KMS 对象的公开桶与强制模式不兼容——公开内容要么不加密要么改用 SSE-S3。在强制关闭默认时匿名访问 SSE-KMS 对象仅由桶策略管辖。服务器在每个进程首次发生匿名拒绝时告警一次逐请求的拒绝会出现在审计条目中kmsOutcomefailure、kmsErrorClassaccess_denied、空 requester identity并记录在 debug 级别。内部工作流豁免。复制replication、生命周期转换lifecycle transitions、修复healing与扫描器scanner都以系统主体system principal身份运行不受影响。授权先于密钥状态检查。一次拒绝无法被用来探测密钥是否存在、是否被禁用或处于待删除状态——响应一律是AccessDenied。分片上传在创建时授权。会话数据密钥session data key在创建时生成并授权后续 Part 上传与 Complete 复用该信封envelope不会针对目标密钥重复授权。Copy 在两端都校验。源对象密钥要求kms:Decrypt目标密钥要求kms:GenerateDataKeyUploadPartCopy对源读取的授权方式相同。迁移到每密钥授权数据路径强制默认关闭因为它会改变当前成功请求的结果现在仅持有s3:PutObject的身份也能用任意密钥加密。不先准备策略就开启会导致正常工作的负载直接报AccessDenied。RUSTFS_KMS_ENFORCE_SSE_KEY_POLICYtrue服务器会在启动时记录一次当前配置的模式在强制关闭状态下启动会给出告警。强制保持 opt-in目前没有反转默认值的路线图。推荐迁移顺序保持强制关闭。盘点哪些身份在读写 SSE-KMS 对象、各自使用哪些密钥——S3 审计条目上的 KMS 字段sseType、kmsKeyId、kmsOutcome会报告每次请求实际使用的密钥。为这些身份挂载KMSKeyUser或按其收窄的副本。强制关闭时这是无操作no-op因此可以提前铺开。在单节点上开启强制确认工作负载仍然成功。集群范围铺开。如果在第 3 步之后某个工作负载在 SSE-KMS 对象上开始报AccessDenied说明该身份在审计条目指名的密钥上缺少kms:GenerateDataKey写或kms:Decrypt读。相关资源本文主体 docs/operations/kms-per-key-authorization.md资源语法与校验实现 crates/policy/src/policy/resource.rs动作全集KmsAction crates/policy/src/policy/action.rs内置 KMS 角色模板与测试 crates/policy/src/policy/policy.rs管理路由到动作/风险的映射 rustfs/src/admin/route_policy.rs强制开关默认值与读取 crates/config/src/constants/app.rsSSE-KMS 数据路径强制实现 rustfs/src/storage/sse.rs管理 API 端点矩阵与密钥分页契约 docs/operations/kms-admin-contract.mdKMS 后端安全属性主密钥轮换/保留/销毁顺序 docs/operations/kms-backend-security.md批量重封装Rekey契约 docs/architecture/kms-bulk-rekey-contract.md【免费下载链接】rustfs2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting migration and coexistence with other S3-compatible platforms such as MinIO and Ceph.项目地址: https://gitcode.com/GitHub_Trending/rus/rustfs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考