ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenBao 递归列表(SCAN)与列表结果过滤:从 RFC 到 API、ACL 与 CLI 的完整实战指南

OpenBao 递归列表(SCAN)与列表结果过滤:从 RFC 到 API、ACL 与 CLI 的完整实战指南 后端认证鉴权密钥管理密码学【免费下载链接】openbaoOpenBao is a software solution to manage, store, and distribute sensitive data including secrets, certificates, and keys.项目地址https://gitcode.com/GitHub_Trending/op/openbao点击查看免费下载导读OpenBao 在 v2.2.0 引入了SCAN这个全新的 HTTP 动词与 ACL 能力用于对 K/V 这类层级化存储进行递归列表随后在 v2.4.0 加入了list_scan_response_keys_filter_path策略关键字把LIST/SCAN的响应按令牌可见性动态裁剪。本篇指南以 OpenBao 官方博客《Recursive Lists (SCAN) Filtering》为主线结合 scan-operation RFC、filtering-list RFC 以及 http 请求处理、ACL 策略解析、列表过滤实现、KV 引擎 等源码讲清楚 SCAN 的 API 用法、ACL 授权模型、过滤模板语法、CLI/Go SDK 调用方式及其底层实现原理帮助你像操作LIST一样安全、高效地使用递归列表。一、背景为什么需要递归列表在层级化的 K/V 挂载点中LIST只能列出某个前缀下的直接子级。当布局嵌套很深时用户往往很难在浅层遍历中快速找到目标条目而合规审计、批量元数据盘点等场景则希望一次性拿到挂载点内的全部条目快照point-in-time snapshot例如对custom_metadata做公司策略合规检查。在 Vault 社区中递归列表支持 与 列表结果过滤 长期位居最高请求的 feature 之列。OpenBao 的解决方案是v2.2.0起支持递归列表SCAN操作v2.4.0起支持过滤列表list_scan_response_keys_filter_path策略关键字外部插件 SDKsdk/v2同时提供logical.ScanOperation操作类型与logical.ScanView(...)存储辅助函数后者对 Vault 同样适用。也就是说无论是最终用户、运维策略作者还是插件开发者都有对应的官方接口可用。二、SCAN 的设计新动词而非新端点2.1 为什么不用recursetrue或独立端点在 scan-operation RFC 中OpenBao 明确否定了两个替代方案recursetrue参数支持递归的端点通常已经支持LIST但递归需要的是logical.ScanView(...)而非storage.List(...)两种实现路径不同更关键的是如果复用LIST操作ACL 上只有list这一个能力除非配合denied_parameters[recurse]才能阻止递归策略表达既不清晰也容易误授权。独立端点如metadata-recursive/:path运维人员可能在不理解资源开销的情况下对某个额外端点意外授予了带递归的LIST缺乏系统性约束。因此 OpenBao 选择引入全新的 HTTP 动词SCAN以及等价的GET?scantrue查询参数并把scan作为一个独立的 ACL 能力。这样策略作者可以精确控制谁能递归列表、在哪个前缀下递归列表而无需关心插件的内部布局。2.2 HTTP 层实现在 internal/http/logical.go 中可以看到SCAN与?scantrue的解析逻辑请求方法为SCAN时直接走扫描路径普通GET请求解析scan查询参数若list与scan同时为真会报错二者互斥SCAN与LIST共用相同的列表响应结构keys字段以及可选的key_info元数据字段。注意SCAN与LIST的一个关键差异由于 SCAN 是递归的结果中不再显式包含目录条目。例如存储中存在a/b与c/dSCAN的响应是keys: [a/b, c/d]而不是keys: [a/, a/b, c/, c/d]。2.3 ACL 授权模型scan能力被定义在 internal/vault/policy/policy.goScanCapability scan并被加入能力的解析与校验集合见 policy.go。与所有能力一样默认是拒绝deny用户不会自动获得递归列表权限。RFC 特别强调了一个与LIST一致的语义对某个前缀拥有scan并不意味着对子路径拥有scan也不意味着对条目拥有read。例如path secrets/metadata { capabilities [scan] }持有该策略的用户可以看到 K/V 挂载下的全部条目但不能调用SCAN secrets/metadata/subpath/尽管这些子路径会出现在上一级扫描结果里也不能READ secrets/metadata/some-key。三、策略写法精确控制扫描范围由于scan是独立能力策略作者可以像这样把便宜的普通操作与昂贵的递归扫描分开# 仅允许常规操作禁止递归扫描 path secrets/* { capabilities [read, create, update, list, patch, delete] }# 全局允许扫描更昂贵需谨慎 path secrets/* { capabilities [read, create, update, list, patch, scan, delete] }# 只在特定子目录内允许扫描推荐做法 path secrets/metadata/my-app/* { capabilities [read, create, update, list, patch, scan, delete] }结合 RFC 中的建议运维人员还可以在扫描端点强制required_parameterslimit把单次扫描的返回条数约束在可控范围内使 SCAN 的性能与受限的 LIST 相当SCAN 毕竟是更昂贵的操作这一约束在 scan-operation RFC 的 Downsides 一节有明确说明。四、实战用法4.1 API 调用递归列表既可以用自定义动词也可以用查询参数回退SCAN secrets/detailed-metadata/my-app等价于适用于不支持自定义动词的客户端GET secrets/detailed-metadata/my-app?scantrue该调用返回的列表响应会附带每个 secret 的元数据key_info。这在 Vault 中通常是1N操作先列出所有 secret再逐个读取元数据而 OpenBao 在单个操作内完成并使用事务保证结果内部一致性这也是博客中与分页、事务性存储结合后成为强大的一致性工具的含义。4.2 CLI 命令bao scan通用递归扫描命令注册于 internal/command/commands.gobao kv scanK/V 专用的递归扫描命令注册于 internal/command/commands.gobao namespace scan递归扫描命名空间——bao namespace list只显示当前命名空间的直接子级而bao namespace scan会递归显示子级的子级乃至完整层级树对应命令注册见 commands.go。4.3 Go APISDKOpenBao Go API 在 api/logical.go 提供了完整的方法族client.Logical().Scan(path)/ScanWithContext(ctx, path)api/logical.go分页版本ScanPage(path, after, limit)/ScanPageWithContext(ctx, path, after, limit)api/logical.go可结合after/limit做游标式迭代。4.4 插件开发者视角外部插件可通过 SDK 实现SCAN操作logical.ScanOperation操作类型在github.com/openbao/openbao/sdk/v2/logical包中定义底层存储辅助logical.ScanView(ctx, view, cb)系列见 sdk/logical/storage.go其中ScanView默认分页大小为DefaultScanViewPageLimit 2500storage.go并提供ScanViewPaginated做批量回调。K/V 引擎已在 internal/builtin/logical/kv/path_metadata.go 与 同文件 L147 为元数据路径注册了logical.ScanOperation对应的framework.PathOperation处理器。五、列表结果过滤list_scan_response_keys_filter_path5.1 要解决的问题管理员经常通过list端点授予宽泛权限但如果用户对某些子键只有read/list权限却被授予了父级list/scan那么所有结果包括无权访问的条目都会暴露。更麻烦的是列表处理器不一定是单条读取处理器的前缀例如 PKI 的certs/列表与cert/:serial读取路径结构不同后端无差别地自动过滤很难实现。因此 filtering-list RFC 选择把映射关系交给策略作者新增策略关键字list_scan_response_keys_filter_path取值是一个text/template表达式系统据此把列表响应中的每个 key 映射成待校验路径再逐条做策略检查。5.2 过滤语义对响应中keys字段的每个条目key 以/结尾 → 在映射出的路径上检查list能力key 不以/结尾 → 在映射出的路径上检查read能力。只有通过的条目才会保留在keys以及对应的key_info中。从 request_handling_list_filtering.go 的源码可以确认这一逻辑strings.HasSuffix(key, /)决定模拟操作是ListOperation还是ReadOperation。该过滤是逐条策略检查代价相对昂贵RFC 建议与required_parameterslimit配合使用避免对成千上万甚至百万级如 PKI 证书、整挂载点递归 K/V 列表的条目逐条做策略评估。5.3 源码中的约束与校验从 internal/vault/policy/policy.go 可以看到该关键字的实现细节字段定义于ResponseKeysFilterPathHCL string hcl:list_scan_response_keys_filter_pathpolicy.go该关键字只能用在带有list能力的 path 块上否则编译报错policy.go配置的模板在编译期即被校验policy.go若模板对两个不同 key 生成了相同路径也会报错policy.go。在请求处理侧request_handling_list_filtering.gofilterListResponse只对ListOperation与ScanOperation生效要求响应数据只能包含keys与可选的key_info两个字段其余字段会报错且不能携带secret或auth。过滤时通过template.CompileTemplatePathForFiltering/template.UseTemplateForFiltering渲染模板再以不递减令牌num_usage的方式重放 ACL 检查见 request_handling_list_filtering.go因此不会产生额外的存储访问。5.4 过滤策略示例博客给出了一个完整示例宽泛地允许列出 secrets但只显示有权限查看的结果。# 允许广泛列出但只显示可见结果read 或 list path secrets/metadata/* { capabilities [list, scan] # 参考: website/content/docs/concepts/policies.mdx 的 Filtering list or scan results 一节 list_scan_response_keys_filter_path {{ .path }}{{ .key }} } # 允许读取 shared/ 下的 secrets 与 metadata path secrets/data/shared/* { capabilities [read] } path secrets/metadata/shared/* { capabilities [read] } # 但 personal/ 空间允许完整访问 path secrets/data/personal/* { capabilities [read, create, update, list, patch, scan, delete] } path secrets/metadata/personal/* { capabilities [read, create, update, list, patch, scan, delete] }在这个示例中调用扫描端点会显示shared/与personal/下的条目而private/下的条目会被过滤掉。模板中的.path是实际被请求的列表路径.key是列表响应中的条目。因为策略可能带通配符如secrets/metadata/*模板必须支持注入实际请求路径以便让.key相对该路径生效——这也是 filtering-list RFC 技术描述部分强调需要支持高级模板的原因。5.5 路径改写高级模板用法text/template允许在模板内改写路径。例如如果希望以数据访问权限而非元数据访问权限作为过滤依据可以写{{ .path | replace secrets/metadata/ secrets/data/ }}{{ .key }}因为列表/扫描端点位于/metadata/下而非/data/下所以模板先把前缀替换为secrets/data/再拼接条目 key随后系统对替换后的路径做read/list策略检查。六、安全与运维注意事项6.1 过滤的取舍默认关闭过滤是逐条策略检查的昂贵操作且可能改变消费应用的既有行为应用的某些结果将消失因此是按路径逐条 opt-in的不是全局默认行为见 filtering-list RFC 的 Security Implications 一节。参数交互限制当前实现不支持min_wrapping_ttl/max_wrapping_ttl与required_parameters等约束的组合——模拟请求不带这些参数可能导致理论上可访问的条目被过滤掉RFC 的 Parameter Interaction 一节对此有说明。跨挂载点映射list_scan_response_keys_filter_path不要求映射路径与列表路径有共同前缀策略作者可能把它指向不存在或不同的挂载点需要自行确保正确性。通配符匹配限制底层 trie 结构基于 go-radix不支持反向通配符查找因此只要前缀内任一策略允许某操作就显示该 key这类行为尚未支持RFC 的 Wildcard Matching Difficulties 一节说明这留待未来单独 RFC。6.2 与分页的交互当过滤结合分页时存在一个已知的语义问题如果一次分页结果恰好全部被过滤为空客户端会误以为迭代已结束RFC 的 Interactions with Pagination 一节详细讨论了after/limit与过滤空结果的交互以及可能的改进方向如由系统自行迭代直到返回至少一条结果。6.3 资源开销SCAN 是比 LIST 更昂贵的操作OpenBao 的缓解手段包括独立 ACL 能力scan默认拒绝独立操作处理器与 LIST 分离结合limit参数约束单次结果规模后续可能支持策略作者对limit做数值约束。七、展望更形式化的存储接口博客Looking ahead一节指出未来 OpenBao 很可能把Scan(...)与ScanWithData(...)纳入正式的存储接口让插件实现递归列表更容易、更一致。从 SDK 侧已有的ScanView/ScanViewPaginated辅助函数sdk/logical/storage.go来看底层基础设施已经具备只是尚未上升为存储接口的正式成员。参考资料与深入阅读官方 RFCSCAN operation、Restrict LIST and SCAN to only accessible paths策略概念文档Policies含 Filtering list or scan results发布说明v2.2.0递归列表、v2.4.0过滤列表API 文档KV v2 List secrets、Namespaces API命令文档namespace 命令含 scan核心源码HTTP 层 SCAN 解析、ACL 策略解析与 scan 能力、列表响应过滤实现、KV 引擎 SCAN 处理器、Go API Scan 方法、SDK ScanView 辅助测试用例ACL 策略测试、请求处理测试、KV passthrough 测试赞分享后端认证鉴权密钥管理密码学【免费下载链接】openbaoOpenBao is a software solution to manage, store, and distribute sensitive data including secrets, certificates, and keys.项目地址https://gitcode.com/GitHub_Trending/op/openbao点击查看免费下载相关推荐rclone ls 命令完全指南云存储对象列表的输出格式、递归规则与过滤实战rclone ls 命令完全指南云存储对象列表的输出格式、递归规则与过滤实战 rclone ls 是 rclone 中最常用的对象列举命令之一它以人类可读的CLI数据同步对象存储Borg repo-list 完全指南列出、过滤与格式化仓库归档列表Borg repo list 完全指南列出、过滤与格式化仓库归档列表 borg repo list 是 Borg 备份工具中用于 列出仓库repositor运维存储cuDF 列表过滤Lists FilteringAPI 完全指南retention/deletion mask 与列表内去重实现剖析cuDF 列表过滤Lists FilteringAPI 完全指南retention/deletion mask 与列表内去重实现剖析 导读 本文围绕 cu数据分析数据工程机器学习上一篇Sakura启动器教程快速部署本地Sakura翻译模型下一篇CK2中文乱码三步解决CK2DLL双字节补丁完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表