【書き起こし】メルペイチームが考える「ゼロトラスト」をベースとした認証・認可の在り方と課題 #merpay_techtalk

2021年11月5日に、メルペイ・メルコインのエンジニアたちによる「Tech Talk 〜 ゼロトラストをベースとした安定的なシステム稼働の取り組み〜」を開催しました。

現在のメルペイサービスにおける認証・認可の仕組みや、セキュリティ対策に欠かせない「ゼロトラスト」と認証・認可の関係、それらを踏まえたメルカリグループの現状と課題をご紹介します

アーカイブはこちら! https://www.youtube.com/watch?v=gXxd75iBXzE

登壇者紹介

竹井 悠人(@yuto)/ 株式会社メルコイン Securityチーム Manager
スタートアップを渡り歩いてきたソフトウェア エンジニア。2016年に暗号資産交換業者 (取引所) に入社して以後、最高情報セキュリティ責任者 (CISO) とブロックチェーン開発部長を歴任。2019年には暗号資産ブロックチェーンのデータ分析アルゴリズムを開発する Bassetを創業、業界全体のコンプライアンス向上や、金融犯罪の排除を目指してきた。今年7月にメルカリ グループに参画して、再び取引所のセキュリティを固める立場に。Microsoft MVP for Azure としてクラウド技術の普及啓蒙活動も行う。

伊藤 雄貴(@mrno110)/ 株式会社メルペイ Architectチーム Backend Engineer
事業立ち上げ時期の 2018年3月にメルペイに参画し、テックリードとしてマイクロサービスの開発に携わる。その後、2019年3月に現在所属している Architect チームにジョインし、組織横断的な課題を解決するために Kubernetes や Istio、Envoy などの技術動向を追っている。また、Microservices Platform チームの一員としてCI/CD環境の整備にも携わっている。

狩野 達也(@kokukuma)/ 株式会社メルペイ IDPチーム Backend Engineer
2018年にメルカリに入社し、メルカリのmicroservices化に携わる。2019年からIDPチームに入り、認証・認可の楽しさに目覚める。現在は同チームにて、日々RFCを漁りつつ、メルカリ・メルペイのID関連の話題に首を突っ込んでいる。今後も暫くこの方向でやっていく予定。

メルペイのマイクロサービスにおける認証・認可の仕組み

@yuto:まず最初に、@kokukumaさんより、現在のメルペイのマイクロサービスでの認証・認可の仕組みを紹介いただければと思います。

@kokukuma:はい。まずはこちらの図をご覧ください。認証・認可の仕組みとしては、まずエンドユーザーがウェブやネイティブのクライアントを使用して、メルカリのサーバーにつないでいる状態です。サーバー側は、マイクロサービスと呼ばれる細かいサービスにわかれています。

それぞれのマイクロサービスではAPIが外部に公開されており、そのAPIが他のマイクロサービスから呼ばれる仕組みです。ただし、クライアント側へAPIを公開する際はゲートウェイを使用して、APIを公開するか否かを判断します。公開して良いと判断されれば、リクエストを各マイクロサービスにプロキシする流れです。

各マイクロサービスは、必要があればそこからマイクロサービスを呼んでレスポンスを受け、自身のレスポンスとあわせてクライアント側に返します。なお、マイクロサービス自体もゲートウェイと同様、「リクエストを通していいか」を判断をしています。

@yuto:ゲートウェイの横にはAuthorityというモジュールがありますが、このシステムにおけるゲートウェイとAuthorityのそれぞれの役割は何でしょうか。

@kokukuma:一番大事なところを説明し忘れましたね(笑)。リクエストを受けると図の中にあるExternal Tokenが検証され、Internal Tokenに変換されます。ゲートウェイの代わりに、Authorityがこの役割を担っています。

@yuki.ito:マイクロサービスでリクエストを受けた際に行うべき認証・認可を、Authorityという別のマイクロサービスに切り出している状態です。これは一般的に STS(Security Token Service)と呼ばれるパターンですね。ゲートウェイで認証した情報をTokenに詰めてマイクロサービスに伝播させて、それをもとに認証・認可を行う仕組みです。

ゼロトラストと認証・認可は切り離せない関係

@yuto:STS (Security Token Service)というお話がありましたが、ゼロトラストと認証・認可の関係はどのように考えればいいでしょうか。

@kokukuma:難しいですね。一概には言えないかもしれませんが、個人的には「一つの何かに依存して、すべてを許可するのをやめること」と理解しています。ひとつのTokenをゲットしてしまえば何でもできる状況を、極力減らしていく取り組みですね。

ゲートウェイを通過すればどのマイクロサービスもアクセスできる状況ですと、仮に開発者が闇堕ちして何かを企てたときに、その人が何でもできる状態になってしまうんですよ。ただ、マイクロサービスはひとりの人間が管理できるほど小さいものではありません。だから、各マイクロサービスで認証・認可をして、想定内のリクエストしか受け入れない仕組みにしようという意味だと考えています。ゼロトラストと認証・認可は切り離せない関係です。

@yuki.ito:Googleさんが発表している「BeyondProd」という、「ゼロトラストの姿勢でどうやってクラウドネイティブなワークロードを運用していくか」といった取り組みが参考になります。ゲートウェイで認証・認可した後、ALTS(Application Layer Transport Security)のような仕組みで、ワークロードを認証・認可しています。

TLS(Transport Layer Security)よりもALTSを使った方が、よりシンプルにセキュアな認証・認可を実装できるのだと思います。発行したCertificateをアプリケーションレイヤーで受けて、信用の有無を調べる仕組みですね。

これに関するホワイトペーパーが面白いんですよ。Google内部だけの取り組みではなく、gRPCのクレデンシャルを作る部分でもALTSを使えるようになっています。このような仕組みを作れることができれば、我々もgRPCで認証・認可を実行できるかもしれませんね。

@yuto:ありがとうございます。だいぶ深入りしてしまいましたね(笑)。今の話をまとめますと、ゼロトラストの部分は「マイクロサービスごとに分業して、内部のモジュールでお互いに認証する仕組み」だと思います。@yuki.itoさんからはALTSの話がありましたが、これはGoogleが社内用のクラスターを管理していたBorgの中で、 Borglets同士の認証を自動的行う仕組みだと理解しました。

ところで、先ほど「対内部脅威ということですか?それ以外にもありますか」という質問がありました。

@yuki.ito:認証・認可についてですかね。当然内部脅威についても考えています。例えばコンテナが乗っ取られて内部ネットワークに侵入されたとき、認証・認可をしていなければ当然他のマイクロサービスも攻撃が可能になります。ただ、お互いにワークロードを認証していれば被害の範囲が狭くて済むので、当然両方を考慮しています。

@yuto:ありがとうございます。続いて、「ゲートウェイ直下のマイクロサービスはその下の2つのマイクロサービスと役割が違いますか?Tokenを見て何か振り分けをするようなマイクロサービスなのでしょうか?」という質問をいただきました。

@yuki.ito:認証・認可の観点ではあまり違いはないと思いますが、アーキテクチャー的には違いますね。

弊社では、ゲートウェイレイヤーの直下のマイクロサービスには「クライアントにどうレスポンスを返すか」というBFF(Backend For Frontend)の役割を任せることが多いです。BFF自体はデータベースを持たず、さらに下にあるマイクロサービスにいろいろなマイクロサービスをコールして、データをアグリゲートして返します。

@kokukuma:ごく一部のAPIでは、Tokenを見てどのマイクロサービスを使うかを判断することもあります。例えばOIDC(OpenID Connect)では、スコープの種類によってEメールまで返すのか、住所まで返すのかといった内容を決めています。ですが、ほとんどの場合、Tokenの情報はAPIを実行させるかどうかの判断のみにしか使われません。

今後のメルカリグループの課題は、内部における認可

@yuto:続いて、今後メルカリグループとしてやっていきたいことを聞きたいと思います。まず、現在のメルペイで実現できていない点はどういうところですか?

@yuki.ito:内部における認可です。Internal Tokenをマイクロサービスが受け取って検証し、リクエストを実行していいかどうかを判断すると説明しましたが、それを実現できているマイクロサービスはまだあまり多くありません。Internal Tokenがあるかどうかだけを検証して、APIを実行するケースがほとんどです。

現状としてできているのは、Internal Tokenに紐づいているユーザーのデータを使って、該当のデータにしか触らないようにするくらいですね。その状況だとInternal Tokenがあれば何でもできる状態になってしまうので、対策を進めたいと思っています。

@yuto:Internal Tokenの発行の主体はゲートウェイだという話がありましたね。一方で、認可についてはどのように進めていく予定ですか。

@yuki.ito:まさにそこは議論中です。すべてのマイクロサービスに対してIDPチームで働きかけることは厳しいんですよね。とはいえみんなが無尽蔵にスコープを作ると、訳がわからなくなってしまいます。誰がイニシアチブをもってスコープを定義するのか、などチームで話し合っています。

@kokukuma:内部での認可をスコープで実行する場合、マイクロサービスがスコープを定義して、ユーザーとなるマイクロサービスにそのスコープをつけたTokenを使ってもらうことになります。ユーザーとなるマイクロサービスをさらに別のマイクロサービスが使用する場合、使用するマイクロサービスはもちろん、そのマイクロサービスがさらに使用しているマイクロサービスのスコープも芋づる式に全てTokenに含めることになります。ここが内部での認可の難しい部分で、まだあまり踏み込めていない状態ですね。

@yuto:ゼロトラストの考えを採用すると、マイクロサービスが自身の権限を公開して、そのマイクロサービスを使う別のマイクロサービスが、使われる側のスコープを知っておかなければいけないですよね。そうすると、先のスコープまで全部考慮しなければいけない点が難しいなと思いました。

先ほど「Authority部分が認証・認可どちらも担っているということでしょうか。」という質問をいただきました。厳密に言うと認証はできているけれど、認可では課題が大きいという形で大丈夫ですか?

@kokukuma:内部の認可と外部の認可は分けて考えるといいと思います。AuthorityでのTokenの検証は、基本的に外部の認可が対象です。特定の範囲のAPIに絞ったTokenを発行して、Authorityで「Tokenが許可されている範囲のエンドポイントにアクセスしようとしているか」を検証する方法をとっています。

一方、内部の認可は外部とは構造が異なるので、外部での認可の内容を内部の認可に活用しようとするとネストしてしまうことがあります。そのため、まだ実行できていない状態です。

バッチ処理や非同期処理における認証について

@yuto:視聴者の方から「バッチ処理や非同期処理など エンドユーザー以外からのリクエストに関しては、どのようにサービス間の認証を行っているんでしょうか?」という質問を頂いています。

@yuki.ito:バッチのようなワークロードが動いたときは、 Google サービスアカウントで特定したワークロードのアイデンティティをもとに、STS (Security Token Service) で発行したTokenによって内部の認証・認可をしています。

ワークロードはGoogle Cloudがマネージドサービスとして提供しているKubernetes環境である GKE(Google Kubernetes Engine)で動かされ、Pod間で認証・認可される形ですね。

各PodはKubernetesのサービスアカウントを持っていて、Googleのサービスアカウントと変換できる機構があるんです。Googleのサービスアカウントでワークロードのアイデンティティを取得し、それをもとにAuthorityが内部のTokenを発行します。

@kokukuma:最近社内でよくワークロードアイデンティティの話をよく聞きますが、今の話もそれに関連するのでしょうか。

@yuki.ito:はい。Googleのサービスアカウントに対して作った鍵をKubernetesのPodにマウントし、サービスアカウントとして振舞わせる方法が一般的でした。その場合、課題になるのが「鍵の管理」ですね。

そこで、鍵を取得するのではなく、Googleのサービスアカウントとして振るまえる機構(GKEのワークロードアイデンティティ)を利用することが、Google でも推奨されています。ワークロードはKubernetesのサービスアカウントで特定できるので、その性質をベースとしています。

@kokukuma:Kubernetesにデプロイしたらサービスアカウントが払い出されるので、Google のサービスに紐づく Google サービスアカウントを使っていろいろなサービスが使えるようになるイメージでしょうか。今のマイクロサービスでは、Google サービスアカウントを自分でセットする必要はないのですか。

@yuki.ito:そうですね。

@yuki.ito:話が逸れますが、ワークロードアイデンティティは良い仕組みだなと思います。AWSやGCP(Google Cloud Platform)もクラウドプロバイダーとして STS を実装しています。最近流行っているものですと、GitHub ActionsがOIDCのフェデレーションに対応していますね。方法としては同じくサービスアカウントを作成して鍵をダウンロードして、GitHub ActionsのシークレットでマウントしてGoogle サービスアカウントとして振る舞う形を取っていました。

鍵の管理という課題に対して最近GitHub Actionsがサポートし始めたのが、GitHub ActionsとしてTokenを払いだして、Google の STS でクレデンシャルを交換する方法です。キーレスでGitHub ActionsからGCPのサービスにアクセスすることが可能になりました。

「いかに鍵を管理せず、ワークロードの一つとしてCI/CDのパイプラインを認証・認可していくか」は考えていくべきだなと思っています。

サプライチェーンにおいても「署名が入ったコンテナしかデプロイできないようにする」「コンテナをエスケーピングできないようにする」など、諸々ゼロトラストやBeyondProd の思想に近い考えがあります。「いろいろなフェーズ・ものを明示的に信頼できないものと捉えて、どうサービスを構築していくか」というトピックが面白いです。

BeyondProd というより、BeyondCorp(Google が実装したゼロトラストモデル)が近いですね。ワークロードはお客さまのトラフィックだけではなく、従業員のマシーンなどにも関係します。その場合一般的には、VPNからのリクエストは明示的にゲートウェイに入ってから許可されるパターンが多いです。一方でBeyondCorpでは、 VPN の境界に入ればOKではなく、社員としてのワークロードのアイデンティティを特定したうえで信頼するような取り組みをしています。我々はこれを完全に実現できているわけではないのですが、そういう考えに近づけていきたいです。

@yuto:当初の質問としては、 GCPの機能にバインドするので、GCP上の IAM(Identity and Access Management)に依存します。当社の場合はSRE部門で権限を管理していて、運用とは別になっていますね。

なおかつその IAM とコンテナのアカウントが1対1になるよう、自動でキーレスで払い出される仕組みになっているので、認証は担保されていますという話ですよね。

ゼロトラストの定義や脅威、BeyondCorpの考え方

@yuto:事前質問で「ゼロトラストの定義はどのように考えられていますか」という話もありました。それは先ほど@yuki.itoさんがおっしゃっていた通り、「何も明示的に信用しない」「マイクロサービスであっても内部サービスであっても、あらゆるアイデンティティ・サブジェクトに信頼を与えない」といったことですよね。

BeyondCorpでは、1回認証したからといってその後すべての認証をバイパスできるようにするのは論外で、必ず境界を通るたびにTokenを提示して、正当な権限を持っているサービス・ユーザー・コンピューターだと証明する形をとる。それらを全てひっくるめてBeyondCorp の考え方なのかなと思います。

@yuto:続いて、「外部からのDDoS攻撃対策みたいなものはしていますでしょうか?Gatewayの負荷をどのように見ているのか気になりました。」という質問をいただきました。まず質問の前半について回答しますが、外部からのDDoS攻撃対策はもちろんしています。当社の場合、CDNなどのサーバーを組み合わせてトラフィックを捌いていますね。それ以降のクリーンなトラフィックについては、@yuki.itoさん、回答いただけますか。

@yuki.ito:セキュリティではなくスケールの観点から言うと、Kubernetesの仕組みを利用して、トラフィックが増えたときに自動でPodが増えるので、それをいい感じにスケールさせていきます。

@yuto:ありがとうございます。もう一つ、「ゼロトラスト特有の脅威についてどのように対応していきますでしょうか?」という質問が来ています。これはおそらくIPAが日本語訳を公開している米国NISTのSP800-207(ゼロトラストについて記載されているドキュメント)を指しているかと思います。

例えばゼロトラスト上の脅威として「資格情報が盗まれてしまったらどうするのか」「システムが落ちた場合、ファシリティはどうなるのか」などが考えられます。

基本的に、権限は必要な人に必要な分だけ与えます。ただし、「緊急事態の場合にはプロセスに従って緊急の権限が与えられるようにしよう」というのは、メルコイン側でも考えていています。メルペイ側でも課題として挙がっていますね。

@yuki.ito:そうですね。基本的に開発者が本番の DB を任意のタイミングで操作することはないのですが、本番障害が起きたときは調査が必要になりますよね。その際、然るべきプロセスを踏んだことを確認した上で、短期間だけ権限を払い出す仕組みを作るのは重要だと思います。これは、弊社のマイクロサービスプラットフォームチームが、Developer Experience向上の一環として考えていることです。

とはいえ、例えば夜中に障害が起きて1人しか開発者がいない等のケースではどうオーディットするかなどは、話し合わなければと思っています。

「システムの分離と統合された体験」「認証におけるUX」メルコインの課題は?

@yuto:終盤に差し掛かってきたので、そろそろメルコインの話もしようと思います。メルコインのシステムアーキテクチャーにおける課題について教えていただけますか。

@yuki.ito:いかにシステム的なアイソレーションを保ちつつ、お客さまに統合された体験を提供するかが課題だと思います。

セキュリティの観点から、メルコインはメルカリ・メルペイとのシステムの分離性を高めなければなりません。とはいえ、メルカリ・メルペイで培ってきた体験の一部をお客さまに提供するという意味では、当然インテグレーションのポイントも必要です。

例えば、Kubernetesクラスターは分離させるとします。ただし、お互いにワークロードは認証・認可しないといけません。そこで「Authorityというコンポーネントをどう拡張して、クラスター間の通信をセキュアな形で実現できるのか」といったことを考えています。

他にも「コンテナのエスケープを防ぐgVisorのような仕組みを取り入れる」など、いろいろと進めるべきことがあると思います。既存の認証・認可のベストプラクティスを参考にしつつ、我々のシステムにどう落とし込んで行くかを考えたいです。求められるセキュリティの水準が高いので、いろいろな新しい技術要素を組み合わせることでどう担保するかはエンジニアリング的には面白いと思います。

@yuto:前提として、メルコインはメルペイのシステムに相乗りしてはいけないという考えがあるので、セキュリティ的な観点から、メルペイとメルコインのほとんどのシステムが分離されています。

例えば我々が使っている社内サービスのシステムはすべて別環境で走っていますし、これからお客さま向けに展開されるクラスターも分割されています。先ほど@yuki.itoさんからお話がありましたが、メルコインからメルペイに移る場合に改めて認証をしなければいけません。

ここで気になるのが、お客さまはサービスを使うために毎回認証するのは大変だということです。いわゆるUXの部分ですね。それを踏まえて、将来的に認証方法をどう設計すべきだと思いますか。

@kokukuma:「ログイン時でないとメルコインを使えない」「一定時間経過すると再度認証を要求される」などの仕組みを作る必要があると思います。

現在はIDやパスワード、SNSの2段階認証によってユーザーを認証し、Tokenを発行する方法を取っています。一般的な形ではありますけど、フィッシング耐性があるとは言えない状態ですね。ユーザーのIDやパスワードが盗まれる、ユーザーに送られたSNSコードで2段階認証を突破されるなどの懸念があります。

一方で、過剰に認証すると、今度はUXが悪くなってしまう可能性もあります。必要のない認証はしない、UXのいい形で認証できるようにするなどの対策が必要です。

@yuto:生体認証やFIDO認証などを組み合わせて、ユーザーにストレスがかからない認証方法で進めるということなんでしょうね。

拾いきれていない質問もあるのですが、本日のイベントは以上になります。パネルディスカッションをご覧いただき、ありがとうございました!

 最後に

メルカリグループは Tech Talk をはじめとしたエンジニア向けのイベントを定期的に開催しています。イベント開催案内を受け取りたい方は、connpassグループのメンバーになってくださいね!

メルカリ/Mercari – connpass

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加