点了同步却毫无反应——用文件判定策略
目标
亲手编写 argocd-rbac-cm 的 policy.csv,并用 argocd admin settings rbac 在没有服务器的情况下检查语法和判定。完成后,就可以把“这个人应该能做这件事”的表与策略一起放进仓库,并作为回归检查来运行。
为什么重要
Argo CD 的权限与 Kubernetes RBAC 是另一张表。在集群里没有任何权限的人,只要有 Argo CD 账号,就能以 Argo CD 所拥有的权限同步任何东西——所以真正的边界是由 policy.csv 划定的。然而这个文件在部署之后由人点击试过之前,很难知道写得对不对。argocd admin settings rbac 能仅凭本地文件完成这一判定。把策略当作代码处理,并在每次修改时运行期望表,也因此成为可能。权限一旦放宽,就没有人会去收紧——如果没有留下表作为收紧的依据,就更是如此。
步骤
- 创建
/root/ga-rbac/policy.csv。其中有两行p,让role:dev能对dev项目的应用执行get和sync;还有一行g,把alice绑定到该角色。argocd admin settings rbac validate --policy-file /root/ga-rbac/policy.csv必须通过。 - 在
/root/ga-rbac/can-basic.txt中写四行。每行有<주체> <동작> <객체> <답>(占位符依次为主体、操作、对象、答案)四个字段,以空格分隔。要询问的四项是alice get dev/web、alice sync dev/web、alice sync prod/web、bob sync dev/web,答案直接写argocd admin settings rbac can <주체> <동작> applications <객체> --policy-file(占位符依次为主体、操作、对象)输出的Yes或No。 - 在
/root/ga-rbac/broken.csv中写一份故意出错的策略——去掉p行最后的allow/deny字段即可。把argocd admin settings rbac validate --policy-file /root/ga-rbac/broken.csv的输出连同标准错误一起保存到/root/ga-rbac/broken.txt。该文件中必须包含说明策略无效的句子。 - 创建
/root/ga-rbac/deny.csv。role:oncall可以对prod/*执行sync,唯独prod/payments是deny。把 deny 行写在 allow 行之前,并把carol绑定到该角色。然后在/root/ga-rbac/deny.txt中写两行——prod/web <답>和prod/payments <답>(占位符为答案)。 - 把
/root/ga-rbac/argocd-rbac-cm.yaml写成 ConfigMap 的样子。名称是argocd-rbac-cm,命名空间是argocd,data.policy.default是role:readonly,data.policy.csv原样包含第 1 步的三行。这个文件同样可以直接传给--policy-file——用不属于任何角色的zoe分别询问get和sync,确认两者的差别。 - 用
rbac can询问一个不存在的资源名称(workloads)和一个不存在的操作(deploy),把两次输出连同标准错误一起追加到/root/ga-rbac/strict.txt。接着对同样的问题加上--strict=false,把结果保存到/root/ga-rbac/loose.txt。策略文件使用第 1 步的policy.csv。 - 在 kwok 集群的
argocd命名空间中创建 AppProjectga-team-a(先保存为/root/ga-rbac/appproject.yaml,再应用)。在spec.roles中放入名称为deployer的角色,并写入一行策略p, proj:ga-team-a:deployer, applications, sync, ga-team-a/*, allow和组ga-team-a-oncall。把同样的策略行和g, dana, proj:ga-team-a:deployer也写到/root/ga-rbac/project-role.csv中,并用rbac can确认判定相同。 - 在
/root/ga-rbac/matrix.tsv中写至少六行,以制表符分隔——格式为<주체>\t<동작>\t<자원>\t<객체>\t<기대>(占位符依次为主体、操作、资源、对象、期望值),期望值是Yes或No。Yes 和 No 都必须至少出现一行。/root/ga-rbac/check-rbac.sh逐行读取这张表,针对/root/ga-rbac/argocd-rbac-cm.yaml运行rbac can,匹配则输出OK …,不匹配则输出MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到/root/ga-rbac/matrix-result.txt。
参考
argocd admin settings rbac validate --policy-file <파일>(占位符为文件名)只检查语法。含义是否正确,由rbac can回答。rbac can的参数顺序是<주체> <동작> <자원> [<객체>](占位符依次为主体、操作、资源、对象)。对象采用<프로젝트>/<앱>(占位符依次为项目、应用)的写法。- 策略文件既可以是纯 CSV,也可以直接使用 argocd-rbac-cm ConfigMap 的 YAML。
- 常见错误:漏掉 p 行最后的
allow/deny字段。这会被当作语法错误检查出来。 - 常见错误:对象只写应用名称,比如
web——必须像dev/web那样连项目一起写才对。 - 参考:https://argo-cd.readthedocs.io/en/stable/operator-manual/rbac/
写一份策略并检查语法
创建 /root/ga-rbac/policy.csv。其中有两行 p,让 role:dev 能对 dev 项目的应用执行 get 和 sync;还有一行 g,把 alice 绑定到该角色。argocd admin settings rbac validate --policy-file /root/ga-rbac/policy.csv 必须通过。
p 行有 p, <주체>, <자원>, <동작>, <객체>, allow|deny(占位符依次为主体、资源、操作、对象)六个字段。资源是 applications,对象采用 <프로젝트>/<앱이름>(占位符依次为项目、应用名称)的写法,所以整个 dev 项目写作 dev/*。g 行有 g, <사용자>, <역할>(占位符依次为用户、角色)三个字段。
直接向策略提问
在 /root/ga-rbac/can-basic.txt 中写四行。每行有 <주체> <동작> <객체> <답>(占位符依次为主体、操作、对象、答案)四个字段,以空格分隔。要询问的四项是 alice get dev/web、alice sync dev/web、alice sync prod/web、bob sync dev/web,答案直接写 argocd admin settings rbac can <주체> <동작> applications <객체> --policy-file(占位符依次为主体、操作、对象)输出的 Yes 或 No。
命令的最后一行就是 Yes 或 No。退出码也会一并告知——Yes 为 0,No 为 1。想一想:bob 没有被绑定到任何角色。
字段不足的行会怎样暴露出来
在 /root/ga-rbac/broken.csv 中写一份故意出错的策略——去掉 p 行最后的 allow/deny 字段即可。把 argocd admin settings rbac validate --policy-file /root/ga-rbac/broken.csv 的输出连同标准错误一起保存到 /root/ga-rbac/broken.txt。该文件中必须包含说明策略无效的句子。
要同时保存输出和错误,使用 > 파일 2>&1(占位符为文件名)。策略有误时,这条命令会给出非 0 的退出码,因此在参考答案脚本里也要小心,别让它因失败而中断。
deny 与行的顺序无关,总是获胜
创建 /root/ga-rbac/deny.csv。role:oncall 可以对 prod/* 执行 sync,唯独 prod/payments 是 deny。把 deny 行写在 allow 行之前,并把 carol 绑定到该角色。然后在 /root/ga-rbac/deny.txt 中写两行——prod/web <답> 和 prod/payments <답>(占位符为答案)。
casbin 并不是采用首条匹配规则的方式,而是只要有一条 deny 命中就拒绝。所以调换顺序后结果也一样——请亲自确认。
对不属于任何角色的人,给他什么权限
把 /root/ga-rbac/argocd-rbac-cm.yaml 写成 ConfigMap 的样子。名称是 argocd-rbac-cm,命名空间是 argocd,data.policy.default 是 role:readonly,data.policy.csv 原样包含第 1 步的三行。这个文件同样可以直接传给 --policy-file——用不属于任何角色的 zoe 分别询问 get 和 sync,确认两者的差别。
policy.default 是用于没有命中策略的请求的角色。role:readonly 是 Argo CD 默认自带的内置角色,所以即使不写进 policy.csv 也存在。ConfigMap 的多行值用 | 块来写。
不存在的资源名称和操作,在提问阶段就会被拦下
用 rbac can 询问一个不存在的资源名称(workloads)和一个不存在的操作(deploy),把两次输出连同标准错误一起追加到 /root/ga-rbac/strict.txt。接着对同样的问题加上 --strict=false,把结果保存到 /root/ga-rbac/loose.txt。策略文件使用第 1 步的 policy.csv。
rbac can 默认是 strict——它会把资源和操作名称与 Argo CD 已知的列表比对,遇到不认识的名称就立即停下。这比把写错的策略部署出去之后才发现要好。加上 --strict=false 会跳过比对,直接判定。
创建只在项目内部生效的角色
在 kwok 集群的 argocd 命名空间中创建 AppProject ga-team-a(先保存为 /root/ga-rbac/appproject.yaml,再应用)。在 spec.roles 中放入名称为 deployer 的角色,并写入一行策略 p, proj:ga-team-a:deployer, applications, sync, ga-team-a/*, allow 和组 ga-team-a-oncall。把同样的策略行和 g, dana, proj:ga-team-a:deployer 也写到 /root/ga-rbac/project-role.csv 中,并用 rbac can 确认判定相同。
项目角色的主体名称格式是 proj:<프로젝트>:<역할>(占位符依次为项目、角色)。语法与全局 policy.csv 相同,所以可以用同一个工具检查——不同的是,这一行存在于 AppProject 内部,因此该项目的管理员可以直接修改。
先做好表,每次策略变化时都运行
在 /root/ga-rbac/matrix.tsv 中写至少六行,以制表符分隔——格式为 <주체>\t<동작>\t<자원>\t<객체>\t<기대>(占位符依次为主体、操作、资源、对象、期望值),期望值是 Yes 或 No。Yes 和 No 都必须至少出现一行。/root/ga-rbac/check-rbac.sh 逐行读取这张表,针对 /root/ga-rbac/argocd-rbac-cm.yaml 运行 rbac can,匹配则输出 OK …,不匹配则输出 MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到 /root/ga-rbac/matrix-result.txt。
表中的期望值以第 5 步的 ConfigMap 为准——alice 可以同步 dev,不属于任何角色的人借助 policy.default 只能读取。如果脚本自己去写文件,评分器再次运行时就会覆盖学员的产出文件。只输出到标准输出,重定向由人来做。