退職処理を可能な限り自動化する

技術部 SRE グループの id:itkq です。2019 夏アニメで一番好きな作品は Re:ステージ!ドリームデイズ♪ です。この記事では SRE が運用している退職処理の自動化について説明します。

退職処理とは

入社後に業務のための様々なアカウントを作成するのと反対に、退職時にはそれらのアカウントを無効化する必要があります。これを退職処理と呼んでいます。SRE が管轄している典型的な例では、SSO に対応していない SaaS のログインアカウント・AWS の IAM User・データベースの個人ログインユーザなどが該当します。これらのアカウントは社員によって要否が異なったり必要な権限が異なるため、入社時に一括で用意せず必要に応じて申請してもらう形をとっています。一方で退職時にはそれらのアカウントをすべて無効化する必要があります。 退職処理は繰り返され、自動化の余地のあるタスクです。また、SRE 以外でも退職処理を行うチームがあることは分かっていたため、退職処理の自動化のための共通の仕組みを考えることにしました。自動化のための第一歩として、退職のイベントを扱いやすい形で発生させる必要があります。

退職イベントを発生させる

クックパッドでは、ヘルプデスク1が社内 IT のアカウントを管理しており、退職時はヘルプデスクが退職者の Active Directory (以降 AD と略記) アカウントを無効化します。入社時のアカウントの作成は人事システム経由で自動化されている一方で、退職時は退職者によってタイミングなどが複雑であることがしばしばあるため、「人間による無効化」によって退職処理を開始させるようにしています。 AD とは別に、SSH や GitHub Enterprise ログインなどに使う目的で OpenLDAP によるアカウント管理も運用しています。これまでヘルプデスクと SRE でそれぞれ AD, OpenLDAP を運用してきましたが、手を取り合って AD に一本化する計画を進めています。移行期間中は AD と OpenLDAP 間で齟齬が起きることが予想されたため、AD と OpenLDAP 間で属性を同期し、パスワード変更時は AD と OpenLDAP 間で同時に変更させることで、将来の統合を楽にする目的の pasuwado というシステム (id:sora_h 作) が稼働しています。 pasuwado は AD と OpenLDAP 間の属性の同期をバッチ処理で行っています。AD のアカウントを無効化情報を pasuwado に管理させることは、本来の責務から外れすぎず、同じようなバッチ処理で実装できる見込みがあったたため、AD アカウントの無効化タイミングを保存しつつ退職イベントを扱いやすい形で発生させる機能を pasuwado に組み込みました。実運用では、誤って AD アカウントを無効化してしまうヒューマンエラーや、アカウントの無効化やリソースの削除を遅らせたい要求があることを考慮する必要があります。そこで「無効化が発見された直後」、「無効化を発見してから 3 日後」、… のようにいくつかのタイミングでイベントを発生させ、受け取る側では都合のいいようにフィルタする設計にしました。SRE では「無効化を発見してから 3 日後」のタイミングで退職が確定したとみなすようにしています。このイベントは pub/sub メッセージングサービスである Amazon SNS に送信します。次に示すのは SNS に送信されるメッセージの例です。detected_at は pasuwado のバッチが AD アカウントのサスペンドを発見した時刻、elapsed はサスペンドを発見してから経過したおおよその秒数です。

 {
    "name": "mana-shikimiya",
    "detected_at": "2019-04-23T00:00:00+09:00",
    "elapsed": 0
 }

退職イベントを受け取り自動処理する

退職イベントが送信される SNS を購読することで、自動化する退職処理のトリガーにすることができます。SNS を使うことで購読方法は選択肢の中から好きなものを選ぶことができ、また自動化処理同士を独立させられます。実際に自動化されている処理について例を挙げながら説明します。

例1: GitHub に issue を立て Slack に通知する

AD アカウント無効化直後のイベントを受け取ると、退職処理をまとめる GitHub リポジトリに issue を立てるジョブを実装しました。この issue は他の退職処理の結果をコメントしていき、スタックする用途のものです。また、誤って AD アカウントを無効化してしまったことに気づきやすいように Slack への通知も同時に行っています。 このジョブは barbeque2 ジョブとして実装しています。barbeque は ECS を基盤とする非同期ジョブ実行環境で、ジョブのリトライなどの管理を任せながら、SNS を購読し ECS で動作するジョブの実装を少ない手間で行うことができます。次の図は pasuwado から barbeque ジョブまでの動作フローです。

f:id:itkq:20191009220409p:plain
pasuwado から barbeque ジョブ実行までの動作フロー

例2: IAM User を削除する

AWS の IAM User は miam という IaC ツールで Git 管理しています。master ブランチが更新されると CI が走り AWS 上のリソースが変更されます。 無効化から 3 日後のイベントを受け取ると退職が確定したとみなし、IAM を管理するリポジトリをクローンし、退職者の IAM User を発見したらそれを削除する Pull Request を出しマージするジョブを同様に barbeque ジョブとして実装しました。この Pull Request は、例1 で述べた issue に紐づけています。

その他

上で挙げた例以外に、SRE が持つ稼働中の自動化ジョブは以下のものがあります。

  • MySQL 個人ログインユーザの削除
  • GitHub Enterprise アカウントのサスペンド
  • PagerDuty のユーザーをチームから削除
  • Amazon SNS Topic の個人 email subscription の削除
  • github.com のアカウントを cookpad organization から削除

また、他のチームの利用事例として、DWH チームによる Redshift の個人ログインユーザの削除・個人スキーマの削除があります。

自動化による SRE の退職処理運用の変化

退職処理の自動化によって、運用がどう変わったかについて説明します。

自動化以前

週次で SRE のうち一人がアサインされ、スプレッドシートに記録された退職者のアカウント情報を元に手動で処理していました。具体的には、SRE が管理するサービスのアカウントやリソースに該当アカウントがないかチェックし、見つかればそれを削除したり無効化してスプレッドシートに作業内容を記録していました。SRE 管轄のアカウントはそれなりに量があるため、場合によっては面倒な作業でした。

自動化以後

退職処理を伴う退職者が存在したかどうか週ベースで自動チェックし、存在した場合は SRE のうち一人がアサインされます。アサインされる issue には、退職処理済みのアカウントに対応する、例1 で述べた issue が紐付けられています。この issue には、自動処理の結果と自動化しきれず手動で行うべき処理が書かれており、これを手動で行ったら issue をクローズし、紐付けられたすべての issue をクローズしたら作業完了です。 元々あったスプレッドシートの運用は、作業内容を誰がいつ行ったかを記録する目的のものだったため、それが issue 上で行われるようになった現在では不要となりました。また、自動化できない処理とは例えば、SaaS のアカウントを無効化したいが無効化を行う API が無いなどです。いい感じの API が生えてくれることを願っています。

まとめ

SRE で運用している退職処理自動化の仕組みについて説明しました。汎用的な仕組みとして設計したため、この仕組みを活用して退職処理を自動化している SRE 以外のチームもあります。 繰り返される自動化可能なタスクを可能な限り自動化していくことにより、本質的な作業にかける時間を増やすことができます。この仕組みを導入してから 1 年以上が経過しており、自動化を実装する時間と比較しても退職処理にかける時間をだいぶ省けている実感があります。退職処理が面倒だと感じている方はこの記事で述べたような自動化の仕組みを検討してみてはいかがでしょうか。


  1. 通称。正式にはコーポレートエンジニアリング部サービスデスク・インフラグループ

  2. https://techlife.cookpad.com/entry/2016/09/09/235007 を参照

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/