ArgoCDのユーザー管理(ローカルユーザー方式)

## Overview
ArgoCD を Kubernetesにインストールすると、同時に admin ユーザが作成されます。
しばらくは一人運用だったので、この admin ユーザーを使用していましたが、

- 他のSREチームのメンバーも argoCD の運用に参加させたい
- 運用負荷軽減のために、アプリケーションチームに ArgoCD の特定の操作を委任したい

等の要件要望が出てきました。もちろん admin ユーザを共有するわけにはいかないので、ArgoCD のユーザー管理をしていきます。
ArgoCD のユーザー管理は、現状 GUI から操作できないので、CUI 操作とマニフェストの更新で実現します。


## 方針
### ローカルユーザー方式か? SSO統合方式か?
ローカルユーザー方式は ArgoCD 自体でユーザー管理をする方式です。 ArgoCD のユーザー管理は、グループ、ログイン履歴などの高度な機能は持っていません。そのため高度な管理をしたい場合は SSO 統合方式を選択をしたほうがよさそうです。
ただ私のプロジェクトでは、ArgoCD を使用する人数も少なく高度な管理は必要ないので `ローカルユーザー方式を採用`しました。

### ユーザーの単位(個人?共有?)
ローカルユーザー方式ではログイン履歴機能などが無いので、個人単位でユーザーを作る意味は無いように思えます。また、個別にユーザを発行して権限を管理していくのも運用負荷がそれなりにかかります。 そのため`権限ごとに共有ユーザーを作成する方針`としました。

### 離任時の運用
共有ユーザー方針だと、共有ユーザーを使用しているある個人が離任した際にパスワードを変更しなければなりません。(そうしないと離任後もログインできてしまうため)
ただ ArgoCD では、ユーザーが自分で自分のパスワードの変更をすることができず、admin ユーザーでしかパスワードの変更ができないようです。それだと管理者の運用負荷が高いので、個人個人のユーザー管理は ALB にくっつけているCognito で管理し、離任した際は ArogCD の共有ユーザーはなにも変更せず`Cognito 上の個人ユーザーを削除`することで、セキュリティと運用負荷のバランスを取ることにしました。

※本記事ではCognito に関する内容は記載しません。

まあここまでするんだったら**「Cognito と SSO 統合すればいいじゃん。バカじゃないの?」**と思う人も多いと思います。

ええ、本当にその通りです。
あんまり OAuth 詳しくないのでひよっちゃいました。時間があればそっちを検討しようと思います。できたらまた記事書きます。


### 具体的に
最初から用意されている`default`プロジェクトと、任意に作成した`hoge`プロジェクトがあるとします。

|プロジェクト|用途|
|:--|:--|
|default|SREチームの管轄。主にkube-systemに入れるようなアプリケーションを想定|
|hoge|アプリケーションチームの管轄。|

SREチームについては、本当は良くないのですが全員 admin ユーザーを使う方針とします。
アプリケーションチーム用として、以下のユーザーを作成することにします。

|ユーザー名|権限|
|:--|:--|
|hoge-power|hogeプロジェクト内でなんでもできる|
|hoge-readonly|hogeプロジェクト内はなんでも見れる|
|hoge-sync|hogeプロジェクト内はなんでも見れるしsyncもできる|
 

## 作業
### 1. ArgoCD へ CLIでログインする
基本的にはマニフェスト更新で設定をしますが、一部 CLI 操作が必要な作業もあるため、ログインしておきます。

まずは ArgoCD にアクセスするために ポートフォワードします。

```bash:port-foward
$ kubectl port-forward svc/argocd-server -n argocd 8080:443
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
```

ポートフォワードしたターミナルとは別のターミナルを開いてログインします。

```bash:login
$ argocd login localhost:8080
WARNING: server is not configured with TLS. Proceed (y/n)? y
Username: admin
Password: <パスワードを入力します>
'admin' logged in successfully
Context 'localhost:8080' updated
```

### 2.新規ユーザーを作成する
`argocd-cm`にユーザーを定義することで、ローカルユーザーを追加することができます。

```yaml:argocd-cm
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
data:
  accounts.hoge-power: login,apikey
  accounts.hoge-sync: login
  accounts.hoge-readonly: login

```
`login` はGUIへのログイン許可。`apiKey`はCLIのトークン発行許可を意味しています。
なおこの状態でユーザーリストを取得すると、ユーザーが作成されていることが確認できます。

```bash:ユーザーリストの取得
$ argocd account list
NAME             ENABLED  CAPABILITIES
admin            true     login
hoge-power       true     login
hoge-readonly    true     login
hoge-sync        true     login
```

各ユーザーに対してパスワードを設定します。
パスワード変更が必要な際も同じ手順となります。

```bash:ユーザーのパスワードを設定する
$ argocd account update-password \
  --account <name> \
  --current-password <current-admin-password> \
  --new-password <new-user-password>
```

パスワードの設定ができたので、これで各ユーザーでログインすることが可能です。
しかしこの段階では何の権限も付与していないため、リポジトリやアプリケーションなど、何も見ることができません。


### 3.ロール(権限)を定義する
対象プロジェクトの`AppProject`マニフェストで、各ロールを定義します。

```yaml:AppProject(hogeプロジェクト用)
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: hoge
  namespace: argocd
spec:
  description: hoge Project
  sourceRepos:
    - '*'
  destinations:
    - namespace: '*'
      server: '*'
  clusterResourceWhitelist:
    - group: '*'
      kind: '*'
  roles:
    - name: power
      description: Power privileges to project hoge.
      policies:
        - p, proj:hoge:sync, applications, get, hoge/*, allow
        - p, proj:hoge:sync, applications, create, hoge/*, allow
        - p, proj:hoge:sync, applications, update, hoge/*, allow
        - p, proj:hoge:sync, applications, delete, hoge/*, allow
        - p, proj:hoge:sync, applications, sync, hoge/*, allow
        - p, proj:hoge:sync, applications, override, hoge/*, allow
        - p, proj:hoge:sync, applications, action, hoge/*, allow
    - name: readonly
      description: Read-only privileges to project hoge.
      policies:
        - p, proj:hoge:readonly, applications, get, hoge/*, allow
    - name: sync
      description: Sync privileges to project hoge.
      policies:
        - p, proj:hoge:sync, applications, get, hoge/*, allow
        - p, proj:hoge:sync, applications, sync, hoge/*, allow
        - p, proj:hoge:sync, applications, action, hoge/*, allow

```

## ユーザーとロールを紐付ける
`argocd-rbac-cm`マニフェストで、ユーザーとロールを紐付けます。

```yaml:argocd-rbac-cm
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-rbac-cm
    app.kubernetes.io/part-of: argocd
data:
 #policy.default: role:readonly
  policy.csv: |
    g, hoge-power, proj:hoge:power
    g, hoge-readonly, proj:hoge:readonly
    g, hoge-sync, proj:hoge:sync

```
なお`policy.default`にて、ロールが設定されていないユーザーや、匿名ユーザーのデフォルトの権限を設定することも可能です。
`role:readonly`は標準で用意されている権限ですが、プロジェクトに限定されず、全てのリソースが閲覧可能となるためここではコメントアウトしています。


# 付録


```bash:ユーザーリストを取得する
$ argocd account list
```

```bash:特定のユーザーの詳細を取得する
$ argocd account get <username>
```

```bash:ユーザーのパスワードを設定する
$ argocd account update-password \
  --account <name> \
  --current-password <current-admin-password> \
  --new-password <new-user-password>
```

```bash:認証トークンを生成する
# --account を省略した場合、現在のユーザーのトークンを生成します
argocd account generate-token --account <username> 
```