
你有没有遇到过这样的场景想给某个 GitHub 仓库推送代码但只允许特定的人操作其他人连git push的权限都没有或者你管理着一个包含数十个仓库的组织每次新增成员或调整权限都得在 GitHub 的 Web 界面里一个个仓库点进去设置繁琐又容易出错。传统的权限管理要么是“全有”要么是“全无”。仓库的Settings-Collaborators里你只能添加一个人并赋予他Read、Write或Admin权限。对于整个组织你可以设置团队但粒度依然很粗。如果你想实现“张三只能推送到 A 仓库李四只能推送到 B 和 C 仓库”并且这个规则能像代码一样被版本管理、被评审、被自动化执行你会发现 GitHub 原生的功能有点力不从心。最近在 Hacker News 上看到一个叫Cermet的项目它的介绍非常有意思allow github.push where owner suarezc and name cermet。这看起来不像是一段配置而像是一条SQL 语句。没错Cermet 的核心思想就是用一种类似 SQL 的声明式语言来定义谁who可以对什么资源what执行什么操作action。它把 GitHub 的权限管理从图形界面的手动点击变成了可编程、可版本控制的策略文件。这不仅仅是换了个配置方式。它背后反映了一个更深层的趋势在 DevOps 和 GitOps 实践日益普及的今天基础设施即代码IaC的理念正在从服务器、网络、容器向上渗透到“协作关系”和“权限”本身。当你的代码、部署、监控都能用代码定义时为什么管理“谁能改代码”的规则还要依赖容易出错的人工操作呢Cermet 的出现正是为了解决这个痛点。它试图成为 GitHub 权限领域的“Terraform”让你能用代码定义并自动化执行精细化的访问控制策略。接下来我们就从“为什么需要它”开始一步步拆解 Cermet 是什么、怎么工作以及在实际落地时你会遇到哪些真正的挑战和边界。1. 为什么 GitHub 原生权限管理会让人头疼在深入 Cermet 之前我们必须先理解它要解决的“原罪”。GitHub 的权限模型对于个人开发者或小团队来说足够简单直观。但随着项目规模、团队人数和仓库数量的增长它的局限性会越来越明显。1.1 权限粒度的“尴尬地带”GitHub 的权限主要在两个层面运作仓库级和组织级。仓库级权限在仓库的Settings-Collaborators中你可以直接添加用户并赋予Read、Triage、Write、Maintain或Admin角色。这很直接但想象一下你有50个仓库需要给一个新同事开通其中20个仓库的Write权限。你需要重复操作50次吗不但你可能需要创建团队。组织级与团队权限在组织内你可以创建团队如frontend-team,backend-team然后将仓库的访问权限授予整个团队。这解决了批量管理的问题。但新的问题来了团队是人员分组而不是策略分组。如果frontend-team的成员小明因为某个特殊项目需要临时拥有对某个后端仓库本属于backend-team的Write权限怎么办你只能把他个人单独加到那个后端仓库的 Collaborators 里破坏了“通过团队管理”的整洁性。如果你想实现“团队A对仓库群X有Write权限但对仓库群Y只有Read权限”你需要创建两个团队team-a-write,team-a-read吗这会导致团队爆炸管理混乱。这种模型下权限Policy和人员Identity是强耦合的。调整权限往往意味着调整团队结构或成员关系这在动态变化的项目中很不灵活。1.2 审计与变更追踪的困境“上周谁给张三开通了推送到核心库的权限” 当出现安全事件或误操作时这个问题很难回答。GitHub 有审计日志Audit Log但它是事件流。要从中梳理出“某个仓库当前所有有写权限的人及其授予时间、授予者”这样的信息非常费力。权限的变更添加/移除协作者、调整团队仓库权限没有像代码提交一样的 Pull Request 评审流程。通常是某个管理员在 Web 界面上点几下就完成了这个过程缺乏可见性、可评审性和回滚能力。1.3 无法实现“策略即代码”在现代工程实践中一切皆代码Everything as Code带来了巨大的可维护性和自动化优势。配置、部署、流水线都能用代码定义并通过 Git 进行版本管理、代码评审和自动化应用。唯独“权限”这个关键环节还停留在手动操作的“史前时代”。这导致了配置漂移Configuration Drift手动修改的权限状态可能逐渐偏离你心中设想的“黄金标准”且无法轻易重建。自动化断点你无法在 CI/CD 流水线中自动验证“新创建的仓库是否遵循了公司的权限基线策略”。知识孤岛权限规则只存在于某个管理员的头脑中或零散的文档里无法成为团队共享、可执行的知识。Cermet 瞄准的正是将这个最后的“手动堡垒”也代码化。2. Cermet 的核心用 SQL 思维定义“谁可以做什么”Cermet 的 Sloganallow github.push where owner suarezc and name cermet非常精炼地概括了它的范式。我们来拆解一下allow: 声明这是一个授权动作。github.push: 定义操作Action这里是推送到 GitHub。where ...: 定义目标资源Resource的条件。这里通过owner和name定位到一个具体的仓库。这本质上是一个策略Policy。Cermet 允许你编写许多这样的策略将它们保存在策略文件如.cermet.yml或policy.crm中。它的核心组件是一个策略引擎Policy Engine负责解析这些策略并在有访问请求时进行裁决。2.1 基本概念与模型Cermet 的模型通常包含以下几个核心实体我们可以用一张表来类比理解Cermet 概念类比 SQL说明主体 (Subject)WHERE user_id ...谁在发起请求。通常是 GitHub 用户、机器人账号、或团队。资源 (Resource)FROM repositories被操作的对象。在 GitHub 语境下主要是仓库 (github.repository)未来可能扩展到 Issue、PR 等。操作 (Action)SELECT push, pull, admin要执行的动作。如github.push,github.pull,github.admin。策略 (Policy)整个SELECT ... FROM ... WHERE ...语句一条完整的授权规则定义了“主体”对满足条件的“资源”可以执行“操作”。策略引擎SQL 查询引擎接收访问请求主体资源操作在所有策略中查找匹配的规则并返回allow或deny。2.2 一个完整的策略文件示例假设我们有一个开源项目组织awesome-org包含以下规则核心团队 (core-team) 对所有仓库拥有完整权限。贡献者 (contributors) 可以对名为docs-*的仓库进行推送但不能删除仓库。外部合作者alice只能对特定的experimental仓库进行推送。用 Cermet 的策略语言这里是一种假设的 YAML 语法基于其思想构建可能这样写# .cermet/policies.yml policies: - id: core-team-full-access description: 核心团队拥有所有权限 effect: allow actions: [github.*] # 通配符表示所有操作 resources: [github.repository:awesome-org/*] subjects: [group:core-team] - id: contributors-docs-write description: 贡献者可以编写文档 effect: allow actions: [github.push, github.pull] resources: [github.repository:awesome-org/docs-*] subjects: [group:contributors] - id: alice-experimental description: Alice 可以参与实验性项目 effect: allow actions: [github.push] resources: [github.repository:awesome-org/experimental] subjects: [user:alice] - id: default-deny description: 默认拒绝所有未明确允许的请求 effect: deny actions: [github.*] resources: [github.repository:awesome-org/*] subjects: [*] # 匹配所有主体关键点解析声明式你描述的是“应该是什么状态”核心团队能访问所有仓库而不是“如何达到这个状态”的一系列指令。细粒度可以通过通配符 (*)、前缀匹配 (docs-*) 等方式灵活地匹配一批资源。默认拒绝最后一条default-deny规则至关重要。这是安全领域的基本原则除非明确允许否则一律拒绝。这确保了策略的严密性。顺序评估策略引擎通常会按顺序评估策略找到第一个匹配的规则就返回结果。因此通常把更具体的规则放在前面通用的default-deny放在最后。2.3 它是如何工作的与 GitHub 的集成Cermet 本身是一个策略决策点。要让策略生效它需要与 GitHub 的权限执行点集成。通常有两种模式预防式Preventive集成通过 GitHub App 或 OAuth App 实现。当用户执行git push时GitHub 会向你的 Cermet 服务发起一个授权查询“用户X试图推送代码到仓库Y是否允许”Cermet 引擎根据策略文件计算返回allow或deny。GitHub 根据这个决定允许或拒绝这次推送操作。这种方式实现了真正的实时、细粒度的权限控制。补救式Remediative集成通过 GitHub API 定期例如每小时扫描组织内的所有仓库和协作者。将当前状态与 Cermet 策略定义的目标状态进行比较。如果发现不一致例如一个不在策略允许范围内的用户出现在了仓库协作者列表中则通过 API 自动移除该用户的权限并可能发送告警。这种方式不是实时阻止而是定期纠偏确保系统状态符合策略定义。它通常与预防式结合使用作为一道安全网。对于大多数团队从“补救式”开始是一个更平滑的切入点。你可以先通过定期扫描来验证和校准你的策略然后再考虑接入更复杂的实时拦截。3. 从概念到落地部署 Cermet 的实操路径与核心挑战看到这里你可能觉得用代码管理权限非常美好。但在真正引入 Cermet 或类似工具前你必须清醒地认识到这不仅仅是技术工具的切换更是工作流程和责任的变革。下面是一个从零开始落地的建议路径以及每个阶段的关键决策点。3.1 阶段一策略设计与模拟验证不触碰生产在这个阶段你的目标是“想清楚”和“写正确”而不是“马上生效”。盘点现状导出你组织当前所有仓库的权限清单可以使用 GitHub API 或ghCLI 工具。这是你的“现状基线”。识别出当前的权限分配模式哪些是团队级权限哪些是个人特殊权限有没有明显不合规的授权草拟策略基于业务逻辑开始用 Cermet 的策略语言编写你的“目标状态”。从小范围开始比如先针对某一个产品线或某一类仓库如所有库。关键原则遵循最小权限原则。先编写允许规则最后一定要加上默认拒绝规则。离线测试利用 Cermet 提供的测试工具或自己编写脚本用真实的用户和仓库信息去测试你的策略文件。构造测试用例(用户A 仓库X push动作)应该允许吗根据你的策略引擎的判断是否和预期一致这个阶段要大量测试边界情况确保策略没有漏洞比如因规则顺序错误导致权限放大。注意策略文件的编写是最大的认知挑战。你需要从“给张三加权限”的操作思维转变为“定义允许推送的条件”的规则思维。这通常需要几次迭代。3.2 阶段二只读监控与告警观察期在将策略应用于生产环境前建立一个“观察模式”的安全网。部署扫描器编写或配置一个定时任务如 GitHub Actions Cron Job定期如每天执行“补救式”集成。它的工作流是a) 从 GitHub 拉取当前所有权限状态b) 用 Cermet 策略计算期望状态c) 对比两者生成差异报告。建立告警通道将差异报告发送到团队频道如 Slack或生成工单。报告内容应该是“检测到仓库awesome-org/foo存在未授权的协作者bob根据策略P-001他不应具有写权限”。此时不进行自动修复。目的是验证你的策略是否准确以及发现那些“历史遗留”或“临时”但未记录的权限。迭代策略根据告警信息与相关管理员或负责人确认。如果这个权限是合理的但你的策略漏掉了那就补充策略如果是不合规的则手动清理并思考如何避免再次发生。这个观察期可能需要持续几周直到告警趋于稳定或为零。它帮助你建立对策略准确性的信心。3.3 阶段三渐进式实施与自动化修复当策略稳定且团队认可后可以逐步推进自动化。选择试点范围不要全组织一次性铺开。选择一个非核心的、风险可控的团队或项目群作为试点。在试点范围内可以将扫描器的动作从“仅告警”改为“自动修复”即自动移除未授权的协作者。配置预防式控制可选但高级对于试点范围可以考虑部署 GitHub App实现实时的git push拦截。这是权限控制的终极形态但复杂度也最高。你需要处理 GitHub App 的安装、权限配置、Webhook 接收、决策响应等一系列问题。确保有完善的日志记录和应急绕过机制如一个Break Glass账号。推广与流程固化将策略文件纳入主代码库像对待基础设施代码一样对其发起 Pull Request。建立策略变更的评审流程任何权限规则的修改都必须通过 PR由相关方技术负责人、安全团队、产品负责人评审后合并。将扫描/修复任务集成到主 CI/CD 流水线中确保策略的持续合规。3.4 落地过程中的核心挑战与应对策略爆炸与复杂度管理问题随着仓库和人员增多策略文件可能变得冗长难懂。应对使用策略语言的模块化、继承或组合功能。例如定义一些基础角色role:developer,role:reviewer然后在具体规则中引用这些角色。将策略按业务域或团队拆分成多个文件。“例外”的处理问题总会有临时性的、合理的例外需求如紧急故障修复需要临时授权。应对不要直接在核心策略文件中为例外开洞。可以设计一个“临时权限审批流程”该流程可以自动生成一个具有短时间失效TTL的临时策略并记录在审计日志中。或者约定使用 Break Glass 机制但事后必须严格审计和复盘。审计与责任追溯问题策略文件本身有 Git 历史但“谁因为什么原因在什么时候触发了一次权限检查”同样需要记录。应对确保 Cermet 引擎或集成层记录详细的决策日志谁、什么资源、什么操作、匹配了哪条策略、结果。将这些日志导入到你的集中式日志系统如 ELK中便于查询和告警。性能与延迟问题对于预防式集成每次git push都需要等待外部策略引擎的响应可能引入延迟。应对优化策略引擎的性能使用缓存例如缓存用户所属的团队信息。对于关键路径评估延迟是否可接受或者考虑将策略引擎部署在离 GitHub 服务区域更近的地方。4. 超越 GitHubCermet 模式的思想与未来Cermet 虽然以 GitHub 为例但其“策略即代码”和“基于属性的访问控制ABAC”的思想具有普适性。理解这一点能帮助你将这种模式应用到更广泛的场景。4.1 核心思想策略即代码与声明式安全Cermet 代表的是一种范式转移从手动操作到自动化管理权限变更不再是点击按钮而是提交代码。从隐式知识到显式规则团队的安全策略不再是口口相传或藏在文档里而是可执行、可测试的代码。从反应式到预防式可以在错误配置发生前就通过 PR 评审和策略测试拦截它而不是事后补救。这本质上是一种声明式安全Declarative Security。你声明“系统应该处于的安全状态”由自动化工具负责让现实世界对齐这个状态。4.2 关联技术与生态Cermet 并非孤立的创意它属于一个更大的技术生态Open Policy Agent (OPA)这是一个通用的策略引擎使用 Rego 语言。你可以用 OPA 来为 Kubernetes、API 网关、数据库等定义策略。Cermet 可以看作是在 GitHub 这个特定领域对 OPA 思想的应用。事实上你可以用 OPA 来实现自己的“Cermet”。基础设施即代码IaC工具如 Terraform 的github_membership,github_repository_collaborators资源。这些资源也能用代码定义 GitHub 权限但通常粒度较粗整个仓库的协作者列表且缺乏 Cermet 那种灵活的、基于属性的条件匹配能力。两者可以结合使用Terraform 管理基础资源创建仓库Cermet 管理精细策略。云原生访问控制AWS IAM、Google Cloud IAM 等都在向更细粒度的、基于属性的策略模型发展。学习 Cermet 的思维对你理解这些云服务的复杂策略语言大有裨益。4.3 适用边界与不适用场景Cermet 这类工具不是银弹它有明确的适用边界非常适合的场景拥有数十个以上 GitHub 仓库的中大型组织。团队结构复杂人员流动相对频繁。对代码安全和合规性有较高要求如金融、医疗行业。已经实践了 GitOps希望将权限管理也纳入 GitOps 流程。需要谨慎评估或不太适合的场景个人或极小团队5人过度设计维护成本可能超过收益。GitHub 原生界面完全够用。权限模型极其简单稳定如果就是“所有成员对所有仓库都有写权限”那不需要它。缺乏运维和支持能力部署和维护一个策略引擎需要一定的 DevOps 能力。如果团队连 CI/CD 都还没跑顺引入它会增加额外负担。对git push延迟极度敏感如果预防式集成引入的毫秒级延迟是你的核心业务所不能接受的则需要详细测试和架构优化。4.4 给你的行动建议如果你被 Cermet 的理念打动并认为它可能解决你团队的痛点我建议按以下顺序行动先理解问题再寻找工具花时间梳理你当前 GitHub 权限管理的真正痛点是什么是审计困难是配置容易出错还是无法满足复杂的权限需求明确问题比选择工具更重要。从小处开始实验不要试图一次性覆盖全组织。找一个有代表性的、风险可控的小项目作为试验田。按照上文提到的“阶段一”和“阶段二”先做策略设计和只读监控。评估构建与采购Cermet 是一个 Show HN 项目可能处于早期阶段。你需要评估是直接采用它还是基于 OPA 等成熟方案自建或者寻找其他商业/开源方案如 Backstage 的权限插件、GitHub 自家的 Fine-grained tokens 和 Rulesets 也在进化。核心是评估其成熟度、社区活跃度和与你们技术栈的集成难度。文化先行工具后跟推广“策略即代码”的最大障碍往往不是技术而是文化和流程。推动团队接受“权限变更需要提 PR 和评审”这一观念与引入工具本身同样重要。回到开头那个像 SQL 一样的句子allow github.push where owner suarezc and name cermet。它简洁的背后是一整套将混乱、隐性的协作规则转变为清晰、显性、可编程代码的工程哲学。这不仅仅是关于 GitHub 推送权限的小工具更是关于我们如何以一种更可靠、更自动化的方式来管理数字世界日益复杂的访问关系。无论你是否最终采用 Cermet理解并尝试这种思路都会让你在构建和维护现代软件系统的道路上多一份掌控力。