G Suite APIsを使ってChatOpsでアカウント管理をする

G Suiteあらため Google Workspaceとなりましたが、現時点では[API](https://developers.google.com/gsuite/aspects/apis/overview?hl=ja)はG Suite APIsのままなので、APIは G Suite APIsと呼んで書き進めたいと思います。

Google Workspace（旧称 G Suite）はGoogleが提供しているビジネス向けのグループウェアで、メール・カレンダー・ビデオ会議・ドキュメント・ドライブなどが独自ドメイン運用で利用できます。

弊社では2011年の震災を機に自前のオンプレ環境からGoogle Workspaceに移行し、9年間運用を続けています。

その間、管理者を数名体制にしてメンバーの入れ替えもあり、マルチドメイン運用をしておりドメイン間の設定も存在している中で、手順書をWikiに書いて秘伝のタレのように育ってきました。

その環境下で生まれた課題に向き合った対策をして、APIを使いChatOps化した事について書きます。

## 漠然とあった課題感

### 延々と続くメンテナンス

Wikiは間違いなくわかりやすいようにという心配りからか、見ればだいたいわかることも画面キャプチャまでとって明示的に記載していたため、何スクロール分にもなる量に肥大化していました。

これがあったから引き継ぎで困ることもほとんどありませんでした。

ただ、長年同じサービスを使っているとUIのリニューアルが定期的に発生する問題があり、Wikiを追従させてメンテナンスしないといけないという手間が時々発生し、これが面倒でUI変更がある度に億劫になっていました。

### 作業の抜け漏れ

手順書に従って作業をしていても何工程にも重なる手順では時には抜け漏れが発生します。
慣れ・不慣れで確認漏れや誤認したり理解不足を生むこともあります。

作業の抜け漏れが発生した場合、実際にそのアカウントを使う人が気づくか、設定が微妙に異なったまま使い続けられることも十分ありえます。

すぐに気づきたいですよね。

## そこでChatOps

チャットの中でオペーレーションして、処理を自動化してログをChatに残せば、状況が見える化され抜け漏れも発生しません。

GSuite APIsを使ってハマったことや仕組み化したことをご紹介します。

## 利用しているサービス

GSuiteアカウントのライフサイクルで手順書にある設定が必要なGSuiteサービスは以下の通りです。

- Gmail
    - メールで利用
- Google カレンダー
    - クロスドメインでカレンダーを共有
- Google ドライブ
    - 共有ファイルストレージとして利用
- Google グループ
    - メールエイリアスとメーリングリストを利用
- Google ドキュメント
    - 作業ログをスプレッドシートに残す

## ドキュメント精査

ドキュメントは基本的には[こちらの](https://developers.google.com/gsuite/aspects/apis/overview?hl=ja)オフィシャルドキュメントを読めばいいのですが、トップで紹介されているAPIだけでは足りず[詳細ページ](https://developers.google.com/gsuite/products?hl=ja)も参照して全サービスAPIから用途にあったAPIを探す必要がありました。

かなり細かく分かれており、手順書で実施いていた内容がどのAPIと対応しているかマッピングしてきます。
例えば、ドメインのユーザ管理を行うには [Directory API](https://developers.google.com/admin-sdk/directory?hl=ja)で操作します。名前は `Directory` ですが、ネームスペースでいうとAdminDirectoryとなっており、命名規則を把握しておくと精査する作業が効率的になりました。

そうやって、ひとつずつ手順に照らし合わせて利用するAPIを精査した結果がこちらです。

- google/apis/admin_datatransfer
- google/apis/admin_directory
- google/apis/groupssettings
- google/apis/calendar
- google/apis/sheets

dataransferはアカウントを削除した時に管理者にデータを移譲する時に利用します。
GoogleドライブのAPIとは違ったという事実を知るまでチョイはまりしたのでした...

### ドキュメントと合わせてSDKのソースを把握

SDKを使ってAPIを利用することになりますが、SDKはほぼ自動生成で作成されており言語がことなっていてもメソッド名は共通しています。挙動や何がAPIができるかはドキュメントよりSDKを見ている時間の方が長かったです。
一通りSDKは見ておくのがおすすめです。

SDKは[GitHubで公開](https://github.com/googleapis/)されており、ほぼ主要な言語は揃っています。

- [Google API Client（Java）](https://github.com/googleapis/google-api-java-client/)
- [Google API Client（Python）](https://github.com/googleapis/google-api-python-client/)
- [Google API Client（Ruby）](https://github.com/googleapis/google-api-ruby-client/)
- [Google API Client（Node）](https://github.com/googleapis/google-api-nodejs-client/)
- ...

その中でも[Service](https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google/apis/admin_directory_v1/service.rb)と[Class](https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google/apis/admin_directory_v1/classes.rb)の実装ソースが仕様の把握に役立ちました。

## APIを使うための準備

APIは使うためには
[この手順](https://developers.google.com/identity/protocols/oauth2)のとおり、アクセス認証コードを発行してURLを生成し、ログインを経てトークン取得してAPIを利用できる状態にしておく必要があります。

また、利用したいAPIのスコープもこの時に指定する必要があるので用意しておきます。

```
Google::Apis::GroupssettingsV1::AUTH_APPS_GROUPS_SETTINGS, Google::Apis::AdminDatatransferV1::AUTH_ADMIN_DATATRANSFER, Google::Apis::AdminDirectoryV1::AUTH_ADMIN_DIRECTORY_USER,Google::Apis::AdminDirectoryV1::AUTH_ADMIN_DIRECTORY_GROUP,Google::Apis::CalendarV3::AUTH_CALENDAR,Google::Apis::SheetsV4::AUTH_SPREADSHEETS
```

手続きやSDKの使い方はドキュメントを見るとして、こういう初期設定って再発行や有効期限が切れる頃には手順を忘れてしまいがちなんですよね。

そういう時にもチャットで対話的に操作できるように、以下のようなコマンドを用意し初期設定系もできる限りChatOps化しました。
SDKはトークンの保持・読み込みはファイルと[Redisに対応](https://googleapis.dev/ruby/googleauth/latest/Google/Auth/Stores/RedisTokenStore.html)していたので、Redisを利用しました。

```
/googleapi-authorization-url
  GoogleAPI利用を認証しトークン発行するためコードを取得するURLをお伝えします。
/googleapi-store-credentials
  ブラウザ認証後のコードを使ってGoogleAPIのトークン情報をストアします。
```

## ChatOpsで対話的な操作

アカウントの存在確認・生成・停止・削除をChatOpsで対話的に行えるように以下のコマンドを作成しました。

サービス毎にコマンドは分けずに、契機毎にコマンド1回で済むようにしました。

```
/account-is-exists
/account-create-request
/account-create-exec
/account-suspend-request
/account-suspend-exec
/account-remove-request
/account-remove-exec
```

こうすることで、作業をしている様子も見える化（メッセージとしてチャットに流れてくる）されるので、冒頭で書いた課題を解消することができ、完了後に生成されたアカウントのユニークIDをパラメータにしたURLを踏んで目視チェックするだけとなったので、抜け漏れもなくなりました。

## ハマった事

実装中にはまったことも紹介しておきます。

- Googleカレンダーは登録完了から反映までに数十秒かかり存在チェックを行うタイミングの時間調整が必要となった
- Googleカレンダーのcidはbase64でエンコーディングされた値である
- Googleグループ設定で新規にグループを作りメンバー登録してpatch_groupを実行するとAuthorizationErrorが発生した
    - patch_groupで先に設定をした後にinsert_memberすること

他にも色々あったはずなんですけど、ハマりどころはAPIの仕様が把握できてきた状態だと少なかったように覚えてます。


## 最後に

複数のAPIを順序よく叩いていけば画面でできることは、ほぼAPIで実現できることがわかりました。
今までこのアカウント作成系のタスクは数十分の確保と集中力が必要で億劫でしたが、
この仕組み化を実運用したら、すぐに着手できるようになり圧倒的な速度で終わらせて快適なリズムを刻むことができるようになりました。

ツールは時代に合わせて変わっていきますが、いい感じで付き合っていけるといいですね。