TT Lab
はじめる
学ぶ 学習パス コース

GitOpsとArgo CD

同期ボタンを押しても何も起きなかった — ポリシーをファイルで判定する

TT Labで続きを見る

目標

argocd-rbac-cmのpolicy.csvを自分で書いて、argocd admin settings rbacで文法と判定をサーバーなしで確認します。終わると、「この人はこれをできるはずだ」という表を、ポリシーと一緒にリポジトリに置いて、回帰チェックとして実行できます。

なぜ重要なのか

Argo CDの権限は、Kubernetes RBACとは別の表です。クラスターで何の権限もない人でも、Argo CDのアカウントさえあれば、Argo CDが持つ権限で何でも同期できます。そのため、実際の境界はpolicy.csvが引きます。ところがこのファイルは、デプロイして人が押してみるまで、正しいかどうかがわかりにくいものでした。argocd admin settings rbacは、この判定をローカルのファイルだけで行ってくれます。ポリシーをコードとして扱い、変更のたびに期待値表を実行してみることが、これで可能になります。権限は一度広げると、誰も絞りません。絞る根拠が表として残っていなければ、なおさらです。

ステップ

  1. /root/ga-rbac/policy.csvを作ってください。role:devがdevプロジェクトのアプリケーションをgetとsyncできるようにするpの行2つと、aliceをそのロールに結び付けるgの行1つです。argocd admin settings rbac validate --policy-file /root/ga-rbac/policy.csvが通る必要があります。
  2. /root/ga-rbac/can-basic.txtに4行を書いてください。各行は<주체> <동작> <객체> <답>の4つの欄を、空白で区切ります。尋ねる4つは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をそのまま書きます(プレースホルダーは、順に主体、アクション、オブジェクト、答えです)。
  3. /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に保存してください。そのファイルには、ポリシーが有効ではないという文が入っている必要があります。
  4. /root/ga-rbac/deny.csvを作ってください。role:oncallはprod/*をsyncできますが、prod/paymentsだけはdenyです。denyの行をallowの行より先に書き、carolをそのロールに結び付けてください。そのあと/root/ga-rbac/deny.txtに、2行、つまりprod/web <답>とprod/payments <답>を書きます(プレースホルダーは答えです)。
  5. /root/ga-rbac/argocd-rbac-cm.yamlを、ConfigMapの形で書いてください。名前はargocd-rbac-cm、ネームスペースはargocd、data.policy.defaultはrole:readonlyで、data.policy.csvにはステップ1の3行をそのまま入れます。このファイルも--policy-fileでそのまま渡せます。どのロールにもいないzoeでgetとsyncを尋ねて、違いを確認してください。
  6. rbac canに、存在しないリソース名(workloads)と存在しないアクション(deploy)を尋ねてみて、2つの出力を標準エラー出力まで合わせて、/root/ga-rbac/strict.txtに追記してください。続けて、同じ質問に--strict=falseを付けた結果を/root/ga-rbac/loose.txtに保存してください。ポリシーファイルは、ステップ1のpolicy.csvを使います。
  7. kwokクラスターのargocdネームスペースに、AppProjectga-team-aを作ってください(/root/ga-rbac/appproject.yamlとして保存してから適用)。spec.rolesに、名前がdeployerのロールを置いて、ポリシーの1行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で判定が同じかを確認してください。
  8. /root/ga-rbac/matrix.tsvに、6行以上をタブで区切って書いてください。<주체>\t<동작>\t<자원>\t<객체>\t<기대>で、期待値はYesまたはNoです。YesとNoが、どちらも1行以上ある必要があります。/root/ga-rbac/check-rbac.shは、この表を1行ずつ読んで/root/ga-rbac/argocd-rbac-cm.yamlに対してrbac canを実行し、合っていればOK …、違っていればMISMATCH …を標準出力にだけ出力して、1行でも違えば0以外のコードで終了する必要があります。その出力を/root/ga-rbac/matrix-result.txtに保存してください(プレースホルダーは、順に主体、アクション、リソース、オブジェクト、期待値です)。

参考

ポリシー1枚を書いて文法を検査する

/root/ga-rbac/policy.csvを作ってください。role:devがdevプロジェクトのアプリケーションをgetとsyncできるようにするpの行2つと、aliceをそのロールに結び付けるgの行1つです。argocd admin settings rbac validate --policy-file /root/ga-rbac/policy.csvが通る必要があります。

pの行は、p, <주체>, <자원>, <동작>, <객체>, allow|denyの6つの欄です。リソースはapplications、オブジェクトは<프로젝트>/<앱이름>の表記なので、devプロジェクト全体はdev/*です。gの行は、g, <사용자>, <역할>の3つの欄です(プレースホルダーは、順に主体、リソース、アクション、オブジェクト、プロジェクト、アプリ名、ユーザー、ロールです)。

ポリシーに直接尋ねる

/root/ga-rbac/can-basic.txtに4行を書いてください。各行は<주체> <동작> <객체> <답>の4つの欄を、空白で区切ります。尋ねる4つは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に、2行、つまりprod/web <답>とprod/payments <답>を書きます(プレースホルダーは答えです)。

casbinは、最初の一致のルールを使う方式ではなく、denyが1つでも当てはまれば拒否します。そのため、順序を入れ替えて書いても結果が同じです。自分で確認してみてください。

どのロールにもいない人に何を与えるか

/root/ga-rbac/argocd-rbac-cm.yamlを、ConfigMapの形で書いてください。名前はargocd-rbac-cm、ネームスペースはargocd、data.policy.defaultはrole:readonlyで、data.policy.csvにはステップ1の3行をそのまま入れます。このファイルも--policy-fileでそのまま渡せます。どのロールにもいないzoeでgetとsyncを尋ねて、違いを確認してください。

policy.defaultは、ポリシーに当てはまらないリクエストに適用するロールです。role:readonlyは、Argo CDがデフォルトで持っている組み込みのロールなので、policy.csvに書かなくてもあります。ConfigMapの複数行の値は、|ブロックで書きます。

存在しないリソース名・存在しないアクションは、尋ねる段階で引っかかる

rbac canに、存在しないリソース名(workloads)と存在しないアクション(deploy)を尋ねてみて、2つの出力を標準エラー出力まで合わせて、/root/ga-rbac/strict.txtに追記してください。続けて、同じ質問に--strict=falseを付けた結果を/root/ga-rbac/loose.txtに保存してください。ポリシーファイルは、ステップ1のpolicy.csvを使います。

rbac canは、デフォルトがstrictです。リソースとアクションの名前を、Argo CDが知っている一覧と照合して、知らない名前ならすぐに止まります。綴りを間違えたポリシーをデプロイしたあとで気づくより、ずっとよいです。--strict=falseを与えると、照合を飛ばして、そのまま判定します。

プロジェクトの中でだけ通用するロールを作る

kwokクラスターのargocdネームスペースに、AppProjectga-team-aを作ってください(/root/ga-rbac/appproject.yamlとして保存してから適用)。spec.rolesに、名前がdeployerのロールを置いて、ポリシーの1行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に、6行以上をタブで区切って書いてください。<주체>\t<동작>\t<자원>\t<객체>\t<기대>で、期待値はYesまたはNoです。YesとNoが、どちらも1行以上ある必要があります。/root/ga-rbac/check-rbac.shは、この表を1行ずつ読んで/root/ga-rbac/argocd-rbac-cm.yamlに対してrbac canを実行し、合っていればOK …、違っていればMISMATCH …を標準出力にだけ出力して、1行でも違えば0以外のコードで終了する必要があります。その出力を/root/ga-rbac/matrix-result.txtに保存してください(プレースホルダーは、順に主体、アクション、リソース、オブジェクト、期待値です)。

表の期待値は、ステップ5のConfigMapが基準です。aliceはdevを同期でき、どのロールにもいない人は、policy.defaultのおかげで読み取りだけができます。スクリプトがファイルを直接書くと、採点ツールが再実行するときに、学習者の成果物を上書きしてしまいます。標準出力にだけ出して、リダイレクトは人が行ってください。