*Security & Privacy Divisionの原動力となっているバリュー、それは「By design, by default and at scale(設計で叶える、デフォルトに組み込む、スケールに対応する)」です。
Oktaのユーザーアクセス権の棚卸し作業をPlatform Security Teamに率いてほしいという依頼が寄せられました。このプロジェクトを進める中、私たちは過去の設定や慣習と向き合わなければなりませんでした。なぜなら古いやり方が残っていることで「by design」と「by default 」な管理が難しい状態だったからです。そのような状況にも関わらず、私たちは「at scale」で組織全体を網羅した検査を実施する必要がありました。
この記事では、これらの課題に私達がどのように挑んだかを説明します。
使用したテクノロジー:
- Neo4j: https://neo4j.com/
- Okta: https://www.okta.com/
- Slack: https://slack.com
概要
メルカリでは、従業員のSaaSへのアクセスのほぼすべてをOktaを使って認証しています。アクセス権とは、許可するのは簡単ですが取り消すことが難しいものです。
不要なアクセス権を一掃するため、Neo4jを使用して組織とアプリケーションへのアクセスをグラフ化し、ユーザーインターフェースにはSlackを使って調査を実施しました。
- 全社的に提供しているアプリケーション以外で、現在付与されているアクセス権がすべて必要なものかを全社員に聞き取り調査。
- その後、各マネージャーにそられのアクセス権がそれぞれの職責と照らし合わせて妥当かを確認。
- 情報を集約後、自己申告に基づいて不要なアクセス権をOkta APIを通じて直接削除。
これらをこれらを実装することで社内全体を対象とした大規模な検査を行うことができました。
これまでの道のり
メルカリは今年創業11年を迎えました。今でこそ中堅企業に成長したものの、多くの10代が思春期を通過するように、成長痛に似たいくつもの苦労を乗り越えてきました。会社の拡大に伴い新たな従業員の入退社を経験し、アクセス管理に関するニーズも変化していきました。新たに導入されるサービスもあれば、廃止されるサービスもありました。過去にアクセス権の付与を決定した根拠や理由も、現在に至る過程で失われてしまいました。
メルカリはSaaSに大きく依存しているため、IDを管理するソリューションとしてOktaとGoogle Workspaceを使用しています。今回、アクセスレビューのプロジェクトに着手した時点で、Oktaのみですでに約8000のユーザー、500のアクティブアプリケーション、1400のグループが存在していました。アクセス権の削除は退職のケースであれば比較的簡単です。しかし、社内異動の場合は細心の注意を必要とする作業です。また勤務年数の短い従業員であればアクセス権の整理も比較的簡単にできますが、勤務年数が長い場合は長年の間にアクセス権が増えてしまっており見直しが大変な場合もあります。その結果、秩序が失われ、そのせいで複雑さも増してクリーンな状態にするのが難しくなっていました。
プロジェクトの目標
Security teamの最終的な目標は、アクセス権の乱用よって引き起こされる潜在的な被害を可能な限り減らすことです。
アクセス権のクリーンアップによりさまざまな副次的効果が期待できます。
- 認証システムにおける無秩序さを減らす
- 各従業員/チームがどのようなシステムを使用しているか、より明確に理解できるようになる
- システムオーナーにその人のアクセスがまだ必要なのかについてヒアリングし、その調査結果をドキュメント化するというSecurity teamメンバーのストレスを軽減する
- どのように管理されているのか、それはなぜなのかについて理解するための時間を減らす
- もう必要ない可能性のあるSaaSを特定する
- クリーンな状態に基づいて、より優れたアカウントライフサイクル管理のパターンを作成する
- その他
考えうる戦略
「最小特権の原則」は、事故やインシデントのリスクを軽減する最善の方法のひとつであるものの、その適用と維持には相当な労力が必要であることが予想できました。
「最小特権の原則」を適用して最終目標を達成できるということは、私たちが以下のことを理解している(または把握している)という意味でもあります。
- 社内にどのようなシステムがあるか
- それらのシステムオーナーと管理者は誰か
- 誰がどのアクセス権を使ってこれらのシステムにアクセスできるか
- 各システムが処理し保存しているデータの種類は何か
- これらシステムが使用される可能性のあるビジネスプロセスは何か
- 各社員とシステム、また取り得る行動とそれに伴う結果との間にあるつながり
Oktaのデータをもとに簡単に計算してみましょう。アプリケーションは500個あり、ユーザー数は8000です。それらが直接割り当てられている、または1400のグループを通じて割り当てられています。各アプリケーションには複数のユーザーがおり、各グループにも複数のユーザーがいます。アプリケーションによっては複数のグループが存在するものもあり、それを組織体制と全ユーザーにリンクさせると、メルカリ社内には20万を超える関係性が存在するという計算になります。この段階では、各ユーザーのアクセスレベル、各システムで処理・保存されるデータの種類、ユーザーにとってどのようなアクションが可能かすらも分かりません。
仮にOktaから得られる情報のみを起点としましょう。1秒間で判断を下すために必要な情報はすべて揃っているという前提の下、1件の関係性につき1秒かかるとします。それでも前述の20万件の関係性をレビューするには丸々55時間かかってしまいます。したがって、一人の人間が全員分のアクセス状況を見ることは明らかに合理的ではありません。
では、他にも実践できそうな方法はないか見ていきましょう。
戦略1:重要なシステムのみにスコープを絞る
重要なシステムはどれなのか?どのような条件に従って決めるのか?これらの条件を定義しようとすると、考えうる要素が多すぎて誰もが容易に迷子になってしまいます。でも魔法なんて存在しないのですから、どこかしら複雑さが残るのもやむを得ないことです。もし、重要なシステムや機密性の高い情報を含むシステムを特定するという方法を選んでも、誰か(またはどこかのチーム)がすべてのシステムに目を通し、それらが何に使われ、どのようなユーザーがアクセスすべきかを理解して分類しなければなりません。
ただ同時に、私たちは社内にあるシステムを大体把握できています。とりあえず手をつけて始めてみたほうが、一通り情報をかき集めてから目の前にそびえ立つ到底登れそうにない頂に絶望するよりも理にかなうはずです。そうでもしないと、いざ山頂に辿り着いたとしても、全員が疲れ果てているか、すでに会社を辞めた後かのどちらかになっていることでしょう。
もうひとつの問題は、このレビューを行っている間も社内の環境は変化し続けるということです。レビューが完了するまでの間に新たなシステムが導入され、そこにユーザーが追加され、それらシステムは新たなユースケースのために使用されることでしょう。川の流れを止め、その間に魚を数えるようにはいかないのです。
戦略2:フルスコープ、システムオーナーに依頼する
システムオーナーに依頼するというのはどうでしょう?アプリの数は500。ユーザー数は1人の場合もあれば全従業員+業務委託が含まれる場合もあります。各システムオーナーが平均10システムを担当するとしても、50人がそれぞれ約4000件のアクセスを確認し、職務内容やサービスの性質、アクセスされるデータに基づき、これらユーザーがアクセスすべきか否かを判断をしなければならないことになります。どこかの時点で、少なくともいくつかの重要なシステムにおいては必要かもしれませんが、秩序のない初期の状態においては有効なアプローチとは言えません。
また、システムオーナーの多くはマネージャーやディレクターです。彼らの時間は貴重です。時間のない人は優先順位を意識するため、この業務はどんなに重要でも後回しにされる可能性が高いでしょう。
戦略3:まずユーザーに質問し、マネージャーにその回答を確認してもらう
他の誰かに聞く前に、まだシステムへのアクセスが必要かどうかをユーザー本人に質問することは可能です。
今回採用した方法はまさにこれで、まずは従業員に以下のように聞いてみます。
これらシステムすべて対してまだアクセス権は必要ですか?はい/いいえ/分からない
回答が集まったら(または期限が過ぎたら)、彼らのマネージャーに質問します。
各メンバーの役割と責任を考慮した上で彼らの回答をレビューし、それらアクセス権が適切かどうかを確認してください。
今回はそこまで実施しなかったものの、3段階目のレビューとしてシステムオーナーへの質問も考えました。
これらのチームはあなたの管理するシステムを使用しています。このシステムの用途を考えると、彼らがアクセスすることに問題はありませんか?
この方法の場合、アクセス権を維持するか取り消すかの判断をアクセス権を実際に使用する人に委ねることになります。また、権限の確認を全従業員に割り振ることができるという利点もあります。残念ながらマネージャーにはメンバーがアクセスの必要性を主張しているアプリケーションをすべて確認してもらわなければなりませんが、求められているのは確認だけなので検査は比較的早く終わるはずです。妥当かどうかを簡単に確認するだけなら、通常ひとり5分もかかりません。場合によってはもう少しかかるかもしれませんが、DM(ダイレクトメッセージ)で確認することが可能です。
このプロセスを通して私たちは「Security TeamのAさんが給与システムのアクセス権を持っている」といった、本来であれば例外的なケースを発見したいと思っていました。もし本人が「必要だ」と言ったとしても、少なくともマネージャーにその妥当性を確認してほしいからです。
このプロセスを実施している間、「このアクセス権が付与されているなんて知らなかった」「そもそもこのサービスってなに?」といったコメントが数多く寄せられました。
Oktaの使われ方からして、今回選択した方法が完璧とはいえないことは分かっています。ですが、私たちはOktaでアプリケーションのアクセス権を付与しています。メルカリの場合、アプリケーション内で権限を付与することはほとんどありません。そしてこれはシステムオーナーに委ねられています。このようなやり方のため、そもそも最初からアクセスできる対象を制限することでかなりの違いが出てきます。さらに追加のクリーンアップは後からでもできます。その時に、いくつか重要なシステムを優先的に対応することも可能です。
プロセスの実施方法
さて、ここまでに「なぜ検査を行うのか Why
」、「どのシステムを対象とするかWhat
、「誰が回答し、誰がレビューするのかWho
」が明確になりました。次は、「どうやって全員に質問し、回答を集めるのかHow
」です。
スプレッドシートでの検査(現実的ではありません)
- すべてのユーザー/グループ/アプリを含めると20万行になってしまいGoogleスプレッドシートには収まらないし、全員に開いてレビューするようお願いするのもばかげています。シートの完全性を確保することは可能ではあるものの、さらに多くの作業が必要となります。
Webベースでの検査(現時点では見送る)
- うまくいくとは思いつつも、少なくともこの段階では検査を実施するためのウェブページは作らないことにしました。
OktaのIdentity Governance Access Certificationキャンペーン機能(我々には有効ではありません)
- OktaにはIdentity governance access certificationという機能があります。Oktaが将来的にアクセスレビューとして使用されることを承知の上で一から設定されているのであれば、この機能を利用する方法はうまくいくでしょう。ここではオーナーは特定グループに割り当てられ、そのグループはアプリケーションに割り当てられます。キャンペーンを実施している間、グループオーナーはグループのメンバーがアクセス権を所有すべきかを確認するよう依頼されます。この方法は、グループオーナーがそのユーザーがアクセス権を持つべきかを判断できることを前提としています。グループは多くの場合チームを意味するため、メンバーの管理はマネージャーに委ねられるでしょう。そのチームグループは、アプリケーションオーナーから必要なアプリケーションに割り当ててもらう必要があります。しかし、Oktaには(現時点では)アプリケーションオーナーを定義する属性がありません。
- 通常のケースはこの方法で問題ないのですが、例外ケースの場合は他のグループを通じて管理する必要があり、その例外を理解できる人に割り当てる必要があります。
- 私たちの今の状態で考えると、グループ=チームではなく、通常(必ずではないものの)アプリケーションへのアクセスを許可するために使われているので、この方法は有効な策ではありませんでした。この状態は、これらグループにオーナーが割り当てられていないという意味でもあります。システムオーナーに
Slack + バックエンド + Neo4j(選んだ方法)
- 私たちはユーザーインターフェイスとしてSlackを、バックエンドデータベースとしてNeo4jを使うことに決めました。バックエンドにグラフデータベースを使うことで、チーム、メンバー、そのマネージャーに対する問い合わせと、彼らがどのグループを通じてどのようなアクセス権を持っているかを(比較的)簡単に照会できるからです。とりあえず今回は、アプリケーション内で付与されたアクセスのレビューは対象外にすることも決めました。
このブログ記事の残り部分では、私たちが実施したプロセスを説明します。
検査を進めるためには、いくつかのステップを経る必要がありました。
- 組織構造を復元する
- Okta上のアプリケーション、グループ、ユーザー、すべてのメンバーシップとそれらの関係を復元する
- 組織とアクセスを記したグラフを作成する
- 各チームと従業員向け:Slackのフォームを作成し、どのアクセスがまだ必要かの確認を依頼する
- ユーザーからの回答を集める
- 各マネージャー向け:Slackのフォームを作成し、メンバーが必要だと申告しているアプリに同意するかどうか質問する。ユーザーからの応答がない場合はマネージャーに決めてもらう
- マネージャーからの回答を集める
- 妥当性の確認:明らかにおかしな回答がないかレビューする
- Okta APIを通じてアプリケーションへのアクセスやグループメンバーシップを取り消す
- 変更を記録する
ステップ8を除く上記のすべての操作はコードを通じて行います。そうすればこのプロセスを確実に再現することができるからです。
組織構造とアクセス権をデータベースで表す
Oktaのユーザーは、チームとマネージャーを示す属性を持つように設定することができますが、いくつか実際の組織構造との相違点が見られたため、最終的には別のソースから完全な構造を抽出し、その構造をOktaのユーザーとリンクさせなければなりませんでした。組織構造をグラフ化することで、Okta上の関係ではなく実際の組織構造を明らかにすることができたので非常に便利でした。
その後、Oktaから特定の組織単位や チームにおけるアプリ、グループ、ユーザー間の関係を抽出することができました。
イメージ1:Oktaと人事データをNeo4jグラフデータベースに統合し、Mermaid.jsで可視化
スキーマ:組織、チーム、マネージャー、メンバー、グループ、アプリケーション間の関係性
オーバーエンジニアリングを防ぐために、少なくとも最初のうちはいくつかショートカットを採用し、各従業員の単位としてOktaUserノードを使用することにしました。現実はもっと複雑な権限が付与された対象を特定する必要があるのですが、この段階ではこれで十分でした。
イメージ2:Mermaid.jsを使って視覚化したデータベース内における関係性の概略図
Neo4jデータベースへの書き込みが終わると、組織、チーム、各チームが使用しているアプリケーションを照会できるようになりました。組織構造のグラフはこのような様子でした。
イメージ3:Neo4jのウェブインターフェイスを使って作成したメルカリの組織構造図
以下のクエリは以下のような意味を表します:
- 「Platform Security」チーム直下のメンバーで、有効なOktaアプリにアクセス権があるすべてのメンバーに対して:
- マネージャーを取得する
- 直近90日間にこれらのアプリを使用したかどうかを取得する
- ユーザー・アプリ間の関係性のOrgノード、マネージャーノード、関係性のプロパティ、最終使用のプロパティ、およびアプリノードを返す
これを元に再度、グループメンバーシップによるアプリへのアクセスを考慮します。
// Team: Platform Security
MATCH (o:OrgUnit {name: "Platform Security"})<-[:IS_MEMBER_OF]-(u:OktaUser)-[r:HAS_ACCESS_TO]->(a:OktaApp {status: "ACTIVE"})
WITH o, u, r, a
MATCH (u)-[:IS_REPORTING_TO]-(m:OktaUser)
WITH o, m, u, r, a
OPTIONAL MATCH (u)-[p:HAS_USED]->(a)
RETURN o, m, u, PROPERTIES(r) AS r, PROPERTIES(p) AS p, a
MATCH (o:OrgUnit {name: "Platform Security"})<-[:IS_MEMBER_OF]-(u:OktaUser)-[r:IS_MEMBER_OF]-(g:OktaGroup)-[:HAS_ACCESS_TO]->(a:OktaApp {status: "ACTIVE"})
WITH o, u, r, g, a
MATCH (u)-[:IS_REPORTING_TO]->(m:OktaUser)
WITH o, m, u, r, g, a
OPTIONAL MATCH (u)-[p:HAS_USED]->(a)
RETURN o, m, u, PROPERTIES(r) AS r, PROPERTIES(p) AS p, g, a
Query1:Neo4j Cypherを使用して、特定のチームのアプリケーションとグループのアクセスリストを取得
プロセスを開始する
コントローラー(アプリ)はユーザーを特定するためにチームのリストを使用しています。チームの再帰的リストは、次のようなクエリでNeo4jデータベースから簡単に抽出できます。
MATCH (t:OrgUnit)-[:IS_PART_OF*]->(o:OrgUnit) WHERE o.name = "Security & Privacy" AND t.status = "active"
RETURN t.name AS team, t.orgId AS orgId, o.name AS orgName
クエリ2:Neo4j CypherでSecurity & Privacyカテゴリの再帰的チーム階層を復元
ここからスコープ内のチームリストに基づいて、コントローラーから検査開始がマネージャーに通知されます。各チームメンバーにが作成され、SlackのDMで調査フォームが送信されます。
メンバーに調査フォームを送信する
Image 4: Sequential flow chart detailing the member campaign process, illustrated with Mermaid.js.
The assessment form sent to members is kept simple and is meant to be quick to fill. A user can click on the application name to connect to the app and confirm if they still need access to it, then select “Access needed” or “No need anymore”.
イメージ4:メンバーのキャンペーンプロセスのフローチャート
回答収集用のバックエンド
調査フォームが送られたら、あとは回答を待つだけです。バックエンドで回答を受け取り、その回答に従ってNeo4jデータベースを更新する準備は整っています。
イメージ6:調査フォームからの回答を収集する手順のフローチャート
調査を実施している間、手動でマネージャーに進捗状況を送信し、未回答の場合はチームメンバーに確認してもらうよう依頼することができます。
マネージャーによる回答のレビュー
回答の回収が済んだら、未回答・未完了のメンバーがいたとしても、マネージャーにアクセスのレビューを依頼します。メンバーからの回答は一目瞭然であり、チームに関係するアプリケーションもよく知られているはずなのでこのステップは通常すぐに終わります。
マネージャーが対応しない場合は、その上司に進捗がないことを報告することができます。
マネージャーのレビューの流れは以下です:
イメージ7:Mermaid.jsを使用して、マネージャーのレビュー作業のシーケンス図
マネージャーに送信されるフォームはユーザーに送られるフォームと似ていますが、必要だと回答されたアプリだけが表示されています。マネージャーはメンバーの回答を確認し、メンバーによりアクセスが必要だと判断されたアクセス権に対して、保持か削除を選択することができます。
イメージ8:Slack内のマネージャーレビューフォームのインターフェイスの例
不要なアクセスのクリーンアップ
この段階では、メンバーからの回答が集まり、マネージャーからの確認も回収済みです。個別のアクセスレビューではなく、チーム単位でのアクセス権付与に同意するかの確認をシステムオーナーに依頼することもできましたが、これは今後の検査に回すことにしました。
Okta APIによるアクセス取り消しフローは比較的シンプルです。
イメージ9:アクセス取り消しメカニズムに関するステップのフローチャート
まとめ
今回のプロジェクトを通して、従業員やマネージャーが正直に回答してくれると信じることで、従業員がどのアクセス権を持ち、どのアクセス権を必要としているかをレビューすることができました。多くの規格、フレームワーク、規制、ベストプラクティスでは、企業が定期的にこういったレビューを実施することが求められています。しかし、得てして複雑な組織構造や歴史的背景がからみあい、こういったレビューはすぐに手に負えなくなるものです。そこで、従業員とアプリケーション間の複雑な関係性をグラフデータベースに移行し、まず従業員にアクセス権が必要かどうかを質問することで、会社の規模に応じて検査の規模を拡大することができました。また、今回の検査は、システム分類作業に長い時間をかけることなく実施することができました。Oktaに大きく依存しているからこそ、Oktaに焦点を当てることで、大半のシステムをカバーすることができたのです。
このフローにもまだまだ改良の余地はあり、他のシステムへの拡張も可能だと考えています。アクセス許可のルールと確認をより厳格にし、プロビジョニングプロセスに組み込むこともできるかもしれません。
一方、今回私たちはすでに、アクセス中断のリスクを負うことなく、不要となった膨大な量のアクセス権を削除することができました。これは、アクセス権を取り消すか否かを判断する際に、こちらで決めたルールを使用するのではなく、従業員とマネージャーの回答に基づいて行ったからです。