ArgoCDでのGWSのグループによる権限管理

# はじめに
ArgoCDで、GWSのグループによる各プロジェクトの権限管理を行なったため、そのための手順について記述した。

基本的に設定方法については、ArgoCDの公式ドキュメントの[Google - Argo CD - Declarative GitOps CD for Kubernetes](https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/google/)の通りのため、より詳しく知りたい方は、そちらを参照することを推奨する。

# OpenID Connect plus Google Groups using Dexの設定
ArgoCDで、GWSのグループによる各プロジェクトの権限管理を行うためには、OpenID Connect plus Google Groups using Dexの設定を行う必要がある。
この設定を行うことで、ArgoCDに、GWSのアカウントを用いてSSOでログインすることができ、かつログインしたGWSのアカウントが属するGWSのグループの情報を権限管理の設定で利用できるようになる。


## OAuth同意画面の構成
1. [GCPのOAuth同意画面](https://console.cloud.google.com/apis/credentials/consent)に移動し、まだ作成していない場合は、内部または外部を選択し、作成ボタンをクリックする
2. アプリ名とユーザーサポートメールの欄を埋める
3. 承認済みドメインにArgoCDへのログインを許可するドメインを追加する
    - 例) example.comを追加した場合
        - @example.comのアドレスを持つすべてのGoogle Workspaceユーザがログインできるようになる
4. 保存して、スコープのセクションに移る
5. 「スコープを追加または削除」を押し、`.../auth/userinfo.profile`と`openid`のスコープを追加する
6. 保存し、変更の概要を確認して終了する

## 新しいOAuthクライアントIDの構成
1. [GCPの認証情報](https://console.cloud.google.com/apis/credentials)の画面に移動する
2. 「CREATE CREDENTIALS」のボタンをクリックし、「OAuthクライアントID」を選択する
3. 「アプリケーションの種類」のドロップダウンメニューから「Webアプリケーション」選択し、アプリの名前(例: ArgoCD)を入力する
4. 承認済みの JavaScript 生成元の「URIを追加」をクリックし、ArgoCDのURLを入力する
    - 例) https://argocd.example.com
5. 承認済みのリダイレクト URIの「URIを追加」をクリックし、ArgoCDのURLの後ろに`/api/dex/callback`を加えたものを入力する
    - 例) https://argocd.example.com/api/dex/callback
6. 作成ボタンをクリックし、後で使用するため、「クライアントID」と「クライアントシークレット」を保存しておく

## ディレクトリAPIアクセスの設定
1. [GCPのサービスアカウント](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts)の画面に移動し、プロジェクトを選択する用に促されたら今まで設定していたプロジェクトを選択する
2. 「サービスアカウントを作成」ボタンをクリックし、サービスアカウント名やサービスアカウントIDの項目を埋め、「作成して続行」ボタンをクリックする
3. 必要があれば、「このサービスアカウントにプロジェクトへのアクセスを許可する」の項目の設定を行う、必要がなければ「続行」ボタンをクリックする
4. 必要があれば、「ユーザーにこのサービス アカウントへのアクセスを許可」の項目の設定を行う、必要がなければ「完了」ボタンをクリックする
5. 作成したサービスアカウント名をクリックし、作成したサービスアカウントの画面に移動する
6. 後で使うため、「一意のID」を保存しておく
7. 詳細設定のドロップダウンをクリックし、「ドメイン全体の委任」の「GOOGLE WORKSPACE管理コンソールを表示」をクリックする
8. Google Workspace ドメインの管理コンソールから、[>セキュリティ>アクセスとデータ管理>APIの制御](https://admin.google.com/ac/owl)の画面に移動する
9. 「ドメイン全体の委任」の「ドメイン全体の委任を管理」ボタンをクリックする
10. 「新しく追加」ボタンをクリックし、6の手順で保存したサービスアカウントの「一意のID」をクライアントIDに入力する
11. OAuthスコープに`https://www.googleapis.com/auth/admin.directory.group.readonly`を追加して、承認ボタンをクリックする
12. 元の作成したサービスアカウントの画面に戻り、キーのタブをクリックする
13. 「鍵を追加」ボタンをクリックし、「新しい鍵を作成」を選択する
14. キーのタイプは、JSONを選択し、作成ボタンをクリックする
15. 保存されたJSON形式のキーは後で使用するため、安全な場所に保管しておく

## Dexの構成
1. 次のように、先ほど作成したサービスアカウントのキーのjsonファイルの内容を、base64でエンコードし、それを使用してSecretを作成します。
    ```yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: argocd-google-groups-json
      namespace: argocd
    data:
      googleAuth.json: JSON_FILE_BASE64_ENCODED
    ```
2. `argocd-dex-server`のdeploymentを編集し、先ほどのSecretをファイルとしてマウントするようにする
    - 以下のように、`/spec/template/spec/containers/0/volumeMounts/`にvolumeMountsを追加します。この時、initコンテナではないことに注意すること
    ```yaml
    volumeMounts:
    - mountPath: /shared
      name: static-files
    - mountPath: /tmp
      name: dexconfig
    - mountPath: /tmp/oidc
      name: google-json
      readOnly: true
    ```
    - 以下のように、`/spec/template/spec/volumes/`にvolumesを追加する
    ```yaml
    volumes:
    - emptyDir: {}
      name: static-files
    - emptyDir: {}
      name: dexconfig
    - name: google-json
      secret:
        defaultMode: 420
        secretName: argocd-google-groups-json
    ```
3. 以下のように、`argocd-cm`の`dex.config`を編集する。この時、clientIdとclientSecretを前に保存したOAuthクライアントIDの値に置き換え、adminEmailを偽装する管理者ユーザのアドレスに置き換える
    ```
    dex.config: |
      connectors:
      - config:
          redirectURI: https://argocd.example.com/api/dex/callback
          clientID: XXXXXXXXXXXXX.apps.googleusercontent.com
          clientSecret: XXXXXXXXXXXXX
          serviceAccountFilePath: /tmp/oidc/googleAuth.json
          adminEmail: admin-email@example.com
        type: google
        id: google
        name: Google
    ```
4. `argocd-dex-server`のdeploymentを再起動し、最新の構成が使用されていることを確認する
5. ArgoCDにログインし、UserInfoの画面に移動すると、所属しているグループが表示されるようになる

## RBAC権限の設定
1. `argocd-rbac-cm.yaml`の`scopes`を以下のように、email, groupsに設定する
    ```yaml
    scopes: '[email, groups]'
    ```
2. あとは権限に応じて、`policy.default`と`policy.csv`の値を変更する
    - 例)
        - default
            - 特別な権限なし
        - developer@example.comのメンバー
            - adminプロジェクトのアプリケーションは表示できない
            - それ以外のrepositories、logs、certificates、applicationsの情報は表示できる
            - developプロジェクトのアプリケーションは同期できる
        - infra@example.comのメンバー
            - buildinされているadmin権限を継承
    ```yaml
    policy.csv: |
        p, role:developer, repositories, get, *, allow
        p, role:developer, logs, get, */*, allow
        p, role:developer, certificates, get, *, allow
        p, role:developer, applications, get, */*, allow
        p, role:developer, applications, get, admin/*, deny
        p, role:developer, applications, sync, develop/*, allow
        g, developers@example.com, role:developer
        g, infra@example.com, role:admin

    policy.default: ''
    ```

# 参考サイト
- [Google - Argo CD - Declarative GitOps CD for Kubernetes](https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/google/)