【ArgoCD】最小ではじめるプロジェクトごとのユーザ権限管理

## 本記事の概要
ArgoCDをクラスタにインストールするとまずadminユーザが作られます。
しかし、adminクラスタは権限が強く(いわゆるsuperuser)、自由にアプリケーションを更新したり削除したりできてしまいます。

マイクロサービスなどによってサービスごとに分割されたチームでは、チームごとに異なる権限を与えることが多いはずで(他チームのリソースへの権限をつけないなど)、adminユーザを共有するわけにはいきません。

とはいえ、個別にユーザを発行して権限を管理していくのも運用負荷がそれなりにかかります。
そこで本記事ではsmall teamのための最小ではじめるユーザの権限を管理を提案してみます。

## ArgoCDのユーザと権限管理
ArgoCDでは、バージョン1.5以降からユーザのRBAC機能が実装されています。
これによって、ユーザに対して細かいリソースアクセスの権限設定ができます。

- [User Management](https://argoproj.github.io/argo-cd/operator-manual/user-management/)

- [RBAC](https://argoproj.github.io/argo-cd/operator-manual/rbac/)

ドキュメントに記載している通り、ArgoCDでは直接ユーザを定義していく方法とSSOにより、GoogleやGitHubのアカウント認証を通してユーザを定義していく2通りの方法を提供しています。
SSOを使えばユーザのグルーピングなど、複雑な機能を扱えたりするのですが、小規模な運用チームでは少々過剰なので、直接ユーザを定義していくLocal usersを作成していく方針でいくことにします。

## 想定する環境
今回は、クラスタ内にいろんなチームのサービスが混在する環境ということで、
マルチテナントなクラスタを想定します。
当然TeamAの人々はTeamBのサービス群に対して権限を持ちたくないハズです。
![argocd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45875/3a20b8fb-db7b-44f4-7e1c-67736c039c1d.png)


## 提案する構成
![argocd-accounts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45875/7d44bb5a-2df7-aed6-ab2c-2752fdedb5f7.png)

ArgoCDのProjectリソースを論理的なサービスの区分けごとに定義し、
このProjectに対してのみ権限を持つユーザを定義します。

## Project & Role定義
```
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: projectA
  namespace: argocd
spec:
  description: projectA project
  sourceRepos:
    - '*'
  destinations:
    - namespace: '*'
      server: '*'
  clusterResourceWhitelist:
    - group: '*'
      kind: '*'
  roles:
    - name: viewer
      description: Read-only privileges to projectA
      policies:
        - p, proj:projectA:viewer, applications, get, projectA/*, allow
    - name: editor
      description: Edit privileges to projectA applications
      policies:
        - p, proj:projectA:editor, applications, create, projectA/*, allow
        - p, proj:projectA:editor, applications, update, projectA/*, allow
        - p, proj:projectA:editor, applications, delete, projectA/*, allow
        - p, proj:projectA:editor, applications, sync, projectA/*, allow
        - g, proj:projectA:editor, proj:projectA:viewer
```

- ここでは参照用ロールと編集用ロールを定義しています。
- pがpolicy、gがおそらくgrantです。pでどのロール、ユーザに対して、どのような操作を拒否/許可するかというルールを定義し、gで実際にロール、ユーザに対してロールをアサインできます。(ロールに対してロールをアサインできるので、上記ではeditorにviewerのポリシーも付与しています)

## Account
```
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
data:
  accounts.projectA-viewer: login,apiKey
  accounts.projectA-editor: login
```
- argocd-cmに定義することでLocal Userの追加を行うことができます。
- loginはGUIへログインして使う用途、apiKeyはCLI用にトークンを発行して使う場合に設定します。

## Roleのアサイン
```
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
data:
  policy.csv: |-
    g, projectA-viewer, proj:projectA:viewer
    g, projectA-editor, proj:projectA:editor
```
実際にロールをアサインするにはargocd-rbac-cmに記載します。
projectファイルに記載しても動作しますが、こちらに集約したほうが一見してユーザと権限の割当がわかるのでおすすめです。

## ユーザのパスワード更新
仕上げに作成したユーザがログインできるようにパスワードを更新しておきます。
```
argocd account update-password \
  --account <name> \
  --current-password <current-admin> \
  --new-password <new-user-password>
```

また、匿名ユーザや、デフォルトのロールアサインを無効にしておくとより安全だと思います。

## 結果
- 管理画面にログインしてみると、read権限がないほかのプロジェクトのサービスは見えないようになっています
- また、viewerでsyncしようとした結果

![スクリーンショット 2020-07-30 18.25.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45875/c1e1a334-8739-ddef-82c2-31fc2b912ab1.png)