web-dev-qa-db-ja.com

SOA /マイクロサービス:サービス間通信で承認を処理する方法は?

前景

モノリシックプラットフォームからよりサービス指向のアーキテクチャに移行しています。非常に基本的なDDD原則を適用し、さまざまな境界コンテキストにドメインを分割しています。各ドメインは分散され、Web API(REST)を介してサービスを公開します。

ビジネスの性質上、BookingsServicesお客様製品など.

Identity Server(Thinktecture Identity Server 3に基づく)もセットアップしました。その主な役割は次のとおりです。

  • 認証の一元化(トークンを発行する所定の資格情報)
  • 次のようなトークンにクレームを追加します。クライアントのスコープ(クライアントごとに私は要求を実行するアプリケーションを意味します)、顧客識別子(顧客ごとに私はアプリケーションを使用する人を意味します)

また、サービスへの外部アクセスを一元化するAPI Gatewayの役割も紹介しました。 API Gatewayは、次のような内部ドメインの深い知識を必要としない機能を提供します。

  • リバースプロキシ:着信要求を適切な内部サービスにルーティングします
  • バージョン管理:API Gatewayのバージョンは、内部サービスの異なるバージョンにマップされます
  • 認証:クライアント要求にはIdentity Serverによって発行されたトークンが含まれ、API Gatewayはトークンを検証します(ユーザーが本人であることを確認してください)
  • スロットル:クライアントあたりのリクエスト数を制限する

認証

承認に関係するものは、これはAPI Gatewayではなく、内部サービス自体で管理されます。現在、次の2つのタイプの承認を行っています。

  • クライアントスコープに基づく承認。例:クライアント(APIを使用する外部アプリケーション)は、BookingsサービスAPIエンドポイントにアクセスするためにスコープ「bookings」を必要とします
  • 顧客に基づく承認。例:顧客(アプリケーションを使用する実際の担当者)が予約の参加者である場合のみBookingsサービスからエンドポイントGET/bookingsにアクセスできます

内部サービスで承認を処理できるようにするために、API Gatewayは、クライアント(要求を実行するアプリケーション)と顧客に関する両方の情報を含むトークンを(内部サービスに要求をルーティングするときに)転送します。人がクライアントアプリケーションにログインしている場合)。

問題の説明

これまでのところ、サービス間通信を導入するまでは良好です(一部のサービスは他のサービスと通信してデータを取得できます)。

質問

サービス間通信の認可にどのように取り組むべきですか?

考慮されるオプション

さまざまなオプションについて説明するために、次のサンプルシナリオを使用します。

  • ExternalAppという外部アプリケーションがあり、API(ExternalAppにアクセスできます)予約フローを構築するためにクライアント)と見なされる
  • ExternalAppBookingsサービスにアクセスする必要があるため、ExternalAppスコープ「bookings」
  • 内部的には(これはExternalAppに対して完全に透過的なものです))BookingsサービスServicesサービスにアクセスして、フライト、保険、レンタカーなどの予約のデフォルトサービスを取得します。

この問題について内部で話し合うと、いくつかのオプションがポップアップしましたが、どのオプションが最適かはわかりません。

  1. BookingsServicesと通信する場合、元のトークンを転送するだけです。 API Gatewayから受信した(クライアントがExternalAppであることを示す)
    • 影響:許可されるべきではないスコープをExternalAppに許可する必要がある場合があります。例:ExternalAppは「bookings」スコープと「services」の両方のスコープを持つ必要がある場合がありますが、「bookings」スコープのみで十分でした。
  2. BookingsServicesと通信するとき、クライアントを示すトークンを転送しますBookingsになっています(ExternalAppの代わりに)+クレームを追加しますBookingsが元のクライアントを偽装していることを示すExternalApp
    • 元のクライアントがExternalAppであるという情報も含めることにより、Servicesサービスは、元の呼び出し元に応じて一部のサービスを除外するなどのロジックを実行することもできます(たとえば、内部アプリの場合はすべての戦いを返す必要があり、外部アプリの場合は一部のみ)
  3. サービスは相互に通信すべきではありません(したがって、この問題に直面することはできません)

ご協力いただき、ありがとうございます。

20
Josep Serra

内部マイクロサービス間の通信チャネルを用意することをお勧めします。

たとえば、いくつかのRabbitMQのようなメッセージブローカーの内部からsend/receiveまたはpublish/subscribeを使用して、マイクロサービス間のメッセージを送信します。

次に、最初のエンドユーザー向けサービス「この例では予約サービス」がトークンの検証を担当し、IdentityServerと通信することによって、この特定の操作を行うことを顧客に許可します。

次に、メッセージブローカーを介してサービスサービスと通信します。その場合、トークンを再度検証する必要はありません。

このモデルはシンプルになり、パフォーマンスが向上すると思います。

3
Wahid Bitar