最新の安定バージョンについては、Spring Integration 7.1.0 を使用してください! |
Spring Integration のセキュリティ
セキュリティは、現代のエンタープライズ(またはクラウド)アプリケーションの重要な機能の 1 つです。さらに、エンタープライズ統合パターンに基づいて構築されたシステムなどの分散システムにとっても重要です。メッセージングの独立性と疎結合により、ターゲットシステムは、メッセージの payload の任意の型のデータと相互に通信できます。これらすべてのメッセージを信頼するか、「感染」メッセージからサービスを保護することができます。
バージョン 6.3 以降、spring-integration-security モジュール全体が削除され、より一般的な spring-security-messaging ライブラリによって提案された API が採用されています。 |
チャネルの保護
統合フロー内のメッセージチャネルを保護するには、それらのチャネルに AuthorizationChannelInterceptor を追加するか、対応するパターンを使用してグローバルチャネルインターセプターとして構成する必要があります。
Java
XML
@Bean
@GlobalChannelInterceptor(patterns = "secured*")
AuthorizationChannelInterceptor authorizationChannelInterceptor() {
return new AuthorizationChannelInterceptor(AuthorityAuthorizationManager.hasAnyRole("ADMIN", "PRESIDENT"));
}
<channel-interceptor pattern="securedChannel*">
<beans:bean class="org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor">
<beans:constructor-arg>
<beans:bean class="org.springframework.security.authorization.AuthorityAuthorizationManager"
factory-method="hasAnyRole">
<beans:constructor-arg>
<beans:array>
<beans:value>ADMIN</beans:value>
<beans:value>PRESIDENT</beans:value>
</beans:array>
</beans:constructor-arg>
</beans:bean>
</beans:constructor-arg>
</beans:bean>
</channel-interceptor>
詳細については、グローバルチャネルインターセプターの構成を参照してください。
セキュリティコンテキストの伝播
アプリケーションとの対話がセキュリティシステムルールに従って安全であることを確認するには、セキュリティコンテキストに認証(プリンシパル)オブジェクトを提供する必要があります。Spring Security プロジェクトは、HTTP、WebSocket、SOAP プロトコルを介してアプリケーションクライアントを認証するための柔軟で標準的なメカニズムを提供します(単純な Spring Security 拡張を備えた他の統合プロトコルで実行できます)。また、メッセージチャネルなどのアプリケーションオブジェクトの認証チェックのために SecurityContext も提供します。デフォルトでは、SecurityContext は(ThreadLocalSecurityContextHolderStrategy)を使用して現在の Thread の実行状態に関連付けられています。これは、protected メソッドの AOP(アスペクト指向プログラミング)インターセプターによってアクセスされ、呼び出しの principal がそのメソッドを呼び出すための十分な認可を持っているかどうかをチェックします。これは現在のスレッドでうまく機能します。ただし、多くの場合、処理ロジックは別のスレッド、複数のスレッド、さらには外部システムで実行できます。
アプリケーションが Spring Integration コンポーネントとそのメッセージチャネル上に構築されている場合、標準のスレッドバインド動作は簡単に構成できます。この場合、保護されたオブジェクトは、<request-handler-advice-chain> (エンドポイントへの動作の追加を参照)または MessageChannel (前述のチャネルの保護を参照)で MethodSecurityInterceptor で保護された任意のサービスアクティベーターまたはトランスフォーマーにすることができます。DirectChannel 通信を使用する場合、ダウンストリームフローは現在のスレッドで実行されるため、SecurityContext は自動的に使用可能になります。ただし、Executor を備えた QueueChannel、ExecutorChannel、PublishSubscribeChannel の場合、メッセージは、それらのチャネルの性質により、あるスレッドから別のスレッド(または複数)に転送されます。このようなシナリオをサポートするために、2 つの選択肢があります。
セキュアなオブジェクトアクセスの前に、メッセージヘッダー内で
Authenticationオブジェクトを転送し、反対側でそれを抽出して認証します。SecurityContextを、転送されたメッセージを受信するスレッドに伝播します。
これは spring-security-messaging モジュールの org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor として実装されており、任意の MessageChannel に追加したり、@GlobalChannelInterceptor として構成したりできます。このインターセプターのロジックは、現在のスレッドから (preSend() メソッドから) SecurityContext を抽出し、postReceive() (beforeHandle()) メソッドから別のスレッドに移入することに基づいています。詳細については、SecurityContextPropagationChannelInterceptor Javadoc を参照してください。
SecurityContext の増殖と増殖は作業の半分にすぎません。メッセージはメッセージフロー内のスレッドの所有者ではなく、システムは受信メッセージに対してセキュリティが確保されていることを確認する必要があるため、SecurityContext を ThreadLocal からクリーンアップする必要があります。SecurityContextPropagationChannelInterceptor は、afterMessageHandled() インターセプターメソッドの実装を提供します。呼び出しの終了時に伝播されたプリンシパルからスレッドを解放することで、操作をクリーンアップします。これは、ハンドオフされたメッセージを処理するスレッドがメッセージの処理を終了すると (成功かどうかに関係なく)、コンテキストがクリアされるため、別のメッセージを処理するときにコンテキストが誤って使用されないようになります。
非同期ゲートウェイを使用する場合は、Spring Security 並行性サポートの適切な |
データの信頼性
システム内でメッセージを介して転送されるデータの整合性が保証されない場合、有効なユーザーであっても悪意のあるデータを生成する可能性があるため、認証および認可制御だけではアプリケーションが正しく動作しない可能性があります。メッセージの送信元が信頼できない場合は、メッセージのペイロードとそのヘッダーに対して検証とフィルタリングを適用する必要があります。これは、潜在的な逆直列化ガジェットを含むヘッダーに含まれる型情報だけでなく、メッセージの宛先がそのメッセージのヘッダーから決定されるユースケースにも適用されます。これらのシナリオは、返送先 (英語) パターンに該当します。メールの返信アドレスに関連する脆弱性がいくつか特定されており、特に返信の挿入、なりすまし、不正なリダイレクトが関係しています。これらの標準メッセージヘッダー (MqttHeaders.TOPIC、RedisHeaders.KEY、MailHeaders.TO、MailHeaders.CC、MailHeaders.BCC、AvroHeaders.TYPE など) のメタデータが信頼できない外部ソースから転送 (または再マッピング) された場合は、ターゲットエンドポイントで使用される前に検証または削除する必要があります。
メタデータのなりすましを防ぐ方法の一つは、メタデータをアプリケーションに一切入れないことです。Spring Integration の受信チャネルアダプター(およびゲートウェイ)は、ソースシステムからマッピングするヘッダーをフィルタリングするための HeaderMapper 戦略を提供します。もう一つの構成要素は、フロー内の不要なヘッダーを削除する HeaderFilter です。
しかし、アプリケーションのロジックによっては、外部システムから送信されたヘッダーであっても、それらのヘッダーに依存する場合があります。そのため、これらのヘッダーの値は、たとえば MessageFilter エンドポイントや MessageSelectingInterceptor を使用して検証する必要があります。6.5.9 バージョン以降、Spring Integration はメッセージヘッダー値に単純なパターンを適用するための AllowListMessageHeaderSelector を提供しています。
@Bean
public IntegrationFlow mqttOutFlow() {
return f -> f
.intercept(new MessageSelectingInterceptor(
new AllowListMessageHeaderSelector(MqttHeaders.TOPIC, "test*", "!test*malicious*")))
.handle(new MqttPahoMessageHandler("mqttOut", pahoClientFactory()));
} 上記の例では、MqttHeaders.TOPIC には test で始まる値のみが受け入れられます。また、malicious の部分文字列を含む値(test で始まっていても)は受け入れられません。詳細については、AllowListMessageHeaderSelector の Javadoc を参照してください。
機密メタデータ
以下は、フレームワーク内部でメッセージ処理の判断に関与する標準 Spring Integration ヘッダーの一覧です。メッセージの送信元が信頼できない場合、メッセージがそれぞれの処理に送られる前に、上記の検証とフィルタリングがこれらのヘッダーに適用されることがあります。
spring-integration-corereplyChannelerrorChannelroutingSlipgatherResultChanneloriginalErrorChannelavro_typeproto_type
spring-integration-filefile_name
spring-integration-ipip_ackTo
spring-integration-jmxjmx_objectNamejmx_operationName
spring-integration-kafkakafka_topic
spring-integration-mailmail_tomail_ccmail_bcc
spring-integration-mqttmqtt_topic
spring-integration-redisredis_keyredis_mapKey
spring-integration-xmppxmpp_to
spring-integration-zipzip_entryFilename