第6章 Quarkus CXF セキュリティーガイド


この章では、Quarkus CXF エクステンションを使用する際のセキュリティーに関する情報を提供します。

6.1. セキュリティーガイド

セキュリティーガイドには、Quarkus CXF のセキュリティーに関連するさまざまな側面が記載されています。

6.1.1. SSL、TLS、および HTTPS

このセクションでは、SSL、TLS、HTTPS に関連するさまざまなユースケースを説明します。

注記

このセクションで使用されているサンプルコードスニペットは、Quarkus CXF のソースツリーにある WS-SecurityPolicy インテグレーションテスト からのものです。

6.1.1.1. クライアント SSL 設定

クライアントが、クライアントのオペレーティングシステムによって SSL 証明書が信頼されていないサーバーと通信する場合は、クライアント用にカスタムトラストストアを設定する必要があります。

トラストストアの作成と維持には、openssl や Java keytool などのツールがよく使用されます。

Quarkus CXF ソースツリーには、両方のツールの例があります。

トラストストアを準備したら、それを使用するようにクライアントを設定する必要があります。

6.1.1.1.1. application.properties にクライアントトラストストアを設定する

これは、最も簡単にクライアントトラストストアを設定できる方法です。次のプロパティーには、重要な役割があります。

以下に例を示します。

application.properties

# Client side SSL
quarkus.cxf.client.hello.client-endpoint-url = https://localhost:${quarkus.http.test-ssl-port}/services/hello
quarkus.cxf.client.hello.service-interface = io.quarkiverse.cxf.it.security.policy.HelloService
1
quarkus.cxf.client.hello.trust-store-type = pkcs12
2
quarkus.cxf.client.hello.trust-store = client-truststore.pkcs12
quarkus.cxf.client.hello.trust-store-password = client-truststore-password

1
pkcs12jks は、よく使用される 2 つのキーストア形式です。PKCS12 は、Java 9 以降の デフォルトの Java キーストア形式 です。PKCS12 はより強力な暗号化アルゴリズムを提供し、拡張可能で、標準化されており、言語に中立で、広くサポートされているため、JKS ではなく PKCS12 を使用することを推奨します。
2
参照される client-truststore.pkcs12 ファイルは、クラスパスまたはファイルシステムのいずれかで使用可能である必要があります。

6.1.1.2. サーバー SSL 設定

HTTPS プロトコル経由でサービスを利用できるようにするには、まずサーバーキーストアを設定する必要があります。サーバーの SSL 設定は、Quarkus の HTTP レイヤーである Vert.x によって実行されます。Quarkus HTTP ガイド では、設定オプションに関する情報が提供されています。

以下に基本的な例を示します。

application.properties

# Server side SSL
quarkus.tls.key-store.p12.path = localhost-keystore.pkcs12
quarkus.tls.key-store.p12.password = localhost-keystore-password
quarkus.tls.key-store.p12.alias = localhost
quarkus.tls.key-store.p12.alias-password = localhost-keystore-password

6.1.1.3. 相互 TLS (mTLS) 認証

これまでは、サーバーのみが SSL 証明書を通じてアイデンティティーを証明し、クライアントがその証明書を信頼するように設定する必要がある単純なケース、つまり片側だけのケースを説明しました。相互 TLS 認証では、クライアントにも同じ公開鍵暗号化手段を使用してアイデンティティーを証明させます。

したがって、相互 TLS (mTLS) 認証の場合、上記のようにサーバーキーストアとクライアントトラストストアをセットアップすることに加えて、クライアント側のキーストアとサーバー側のトラストストアをセットアップする必要があります。

ストアを作成および維持するためのツールは同じであり、使用する設定プロパティーは Simple TLS の場合に使用されるものとほぼ類似しています。

Quarkus CXF ソースツリーの mTLS インテグレーションテスト は、適切なスタートポイントになります。

キーストアとトラストストアは、openssl (または Java Java keytool) を使用して作成されます。

application.properties ファイルは次のとおりです。

application.properties

# Server keystore for Simple TLS
quarkus.tls.localhost-pkcs12.key-store.p12.path = localhost-keystore.pkcs12
quarkus.tls.localhost-pkcs12.key-store.p12.password = localhost-keystore-password
quarkus.tls.localhost-pkcs12.key-store.p12.alias = localhost
quarkus.tls.localhost-pkcs12.key-store.p12.alias-password = localhost-keystore-password
# Server truststore for Mutual TLS
quarkus.tls.localhost-pkcs12.trust-store.p12.path = localhost-truststore.pkcs12
quarkus.tls.localhost-pkcs12.trust-store.p12.password = localhost-truststore-password
# Select localhost-pkcs12 as the TLS configuration for the HTTP server
quarkus.http.tls-configuration-name = localhost-pkcs12

# Do not allow any clients which do not prove their indentity through an SSL certificate
quarkus.http.ssl.client-auth = required

# CXF service
quarkus.cxf.endpoint."/mTls".implementor = io.quarkiverse.cxf.it.auth.mtls.MTlsHelloServiceImpl

# CXF client with a properly set certificate for mTLS
quarkus.cxf.client.mTls.client-endpoint-url = https://localhost:${quarkus.http.test-ssl-port}/services/mTls
quarkus.cxf.client.mTls.service-interface = io.quarkiverse.cxf.it.security.policy.HelloService
quarkus.cxf.client.mTls.key-store = target/classes/client-keystore.pkcs12
quarkus.cxf.client.mTls.key-store-type = pkcs12
quarkus.cxf.client.mTls.key-store-password = client-keystore-password
quarkus.cxf.client.mTls.key-password = client-keystore-password
quarkus.cxf.client.mTls.trust-store = target/classes/client-truststore.pkcs12
quarkus.cxf.client.mTls.trust-store-type = pkcs12
quarkus.cxf.client.mTls.trust-store-password = client-truststore-password

# Include the keystores in the native executable
quarkus.native.resources.includes = *.pkcs12,*.jks

6.1.1.4. WS-SecurityPolicy を通じて SSL を強制する

クライアントが HTTPS 経由で接続するための要件は、ポリシーで定義できます。

この機能は、quarkus-cxf-rt-ws-security エクステンションにより提供されます。

以下は、ポリシーファイルの例です。

https-policy.xml

<?xml version="1.0" encoding="UTF-8"?>
<wsp:Policy wsp:Id="HttpsSecurityServicePolicy"
            xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <wsp:ExactlyOne>
        <wsp:All>
            <sp:TransportBinding>
                <wsp:Policy>
                    <sp:TransportToken>
                        <wsp:Policy>
                            <sp:HttpsToken RequireClientCertificate="false" />
                        </wsp:Policy>
                    </sp:TransportToken>
                    <sp:IncludeTimestamp />
                    <sp:AlgorithmSuite>
                        <wsp:Policy>
                            <sp:Basic128 />
                        </wsp:Policy>
                    </sp:AlgorithmSuite>
                </wsp:Policy>
            </sp:TransportBinding>
        </wsp:All>
    </wsp:ExactlyOne>
</wsp:Policy>

ポリシーは、サービスエンドポイントインターフェイス (SEI) から参照される必要があります。

HttpsPolicyHelloService.java

package io.quarkiverse.cxf.it.security.policy;

import jakarta.jws.WebMethod;
import jakarta.jws.WebService;

import org.apache.cxf.annotations.Policy;

/**
 * A service implementation with a transport policy set
 */
@WebService(serviceName = "HttpsPolicyHelloService")
@Policy(placement = Policy.Placement.BINDING, uri = "https-policy.xml")
public interface HttpsPolicyHelloService extends AbstractHelloService {

    @WebMethod
    @Override
    public String hello(String text);

}

このセットアップを行うと、HTTP 経由で配信されるすべてのリクエストは PolicyVerificationInInterceptor によって拒否されます。

ERROR [org.apa.cxf.ws.pol.PolicyVerificationInInterceptor] Inbound policy verification failed: These policy alternatives can not be satisfied:
 {http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}TransportBinding: TLS is not enabled
 ...

6.1.2. 認証および認可

注記

このセクションに示されているサンプルコードは、Quarkus CXF のソースツリーにある Client and server integration test からの抜粋です。これは、実行可能な例として使用できます。

6.1.2.1. クライアント HTTP Basic 認証

quarkus-cxf エクステンションによって提供される次のクライアント設定オプションを使用して、HTTP Basic 認証のユーザー名とパスワードを渡します。

以下に例を示します。

application.properties

quarkus.cxf.client.basicAuth.wsdl = http://localhost:${quarkus.http.test-port}/soap/basicAuth?wsdl
quarkus.cxf.client.basicAuth.client-endpoint-url = http://localhost:${quarkus.http.test-port}/soap/basicAuth
quarkus.cxf.client.basicAuth.username = bob
quarkus.cxf.client.basicAuth.password = bob234

6.1.2.1.1. Basic 認証で保護された WSDL へのアクセス

デフォルトでは、quarkus.cxf.client."client-name".secure-wsdl-accesstrue に設定しない限り、Quarkus CXF によって作成されたクライアントは Authorization ヘッダーを送信しません。

application.properties

quarkus.cxf.client.basicAuthSecureWsdl.wsdl = http://localhost:${quarkus.http.test-port}/soap/basicAuth?wsdl
quarkus.cxf.client.basicAuthSecureWsdl.client-endpoint-url = http://localhost:${quarkus.http.test-port}/soap/basicAuthSecureWsdl
quarkus.cxf.client.basicAuthSecureWsdl.username = bob
quarkus.cxf.client.basicAuthSecureWsdl.password = ${client-server.bob.password}
quarkus.cxf.client.basicAuthSecureWsdl.secure-wsdl-access = true

6.1.2.2. 相互 TLS (mTLS) 認証

SSL、TLS、HTTPS ガイドの 相互 TLS (mTLS) 認証 セクションを参照してください。

6.1.2.3. サービスエンドポイントの保護

特に以下の点において、サーバー側の認証と認可は Quarkus Security によって実行されます。

具体的な例は、Client and server integration test を参照してください。主に以下が含まれます。

  • アイデンティティープロバイダーとしての io.quarkus:quarkus-elytron-security-properties-file 依存関係
  • Basic 認証の有効化と、application.properties でロールが設定されているユーザー。

    application.properties

    quarkus.http.auth.basic = true
    quarkus.security.users.embedded.enabled = true
    quarkus.security.users.embedded.plain-text = true
    quarkus.security.users.embedded.users.alice = alice123
    quarkus.security.users.embedded.roles.alice = admin
    quarkus.security.users.embedded.users.bob = bob234
    quarkus.security.users.embedded.roles.bob = app-user

  • @RolesAllowed アノテーションによって強制されるロールベースのアクセス制御。

BasicAuthHelloServiceImpl.java

package io.quarkiverse.cxf.it.auth.basic;

import jakarta.annotation.security.RolesAllowed;
import jakarta.jws.WebService;

import io.quarkiverse.cxf.it.HelloService;

@WebService(serviceName = "HelloService", targetNamespace = HelloService.NS)
@RolesAllowed("app-user")
public class BasicAuthHelloServiceImpl implements HelloService {
    @Override
    public String hello(String person) {
        return "Hello " + person + "!";
    }
}

6.1.3. WS-SecurityPolicy によって強制される認証

クライアントサービス に対して、相互 TLS と Basic HTTP 認証の代わりに、WS-SecurityPolicy を通じて認証を強制できます。

WS-SecurityPolicy を通じて認証を強制するには、次の手順に従います。

  1. WSDL コントラクトのエンドポイントにサポートトークンポリシーを追加します。
  2. サーバー側では、認証コールバックハンドラーを実装し、application.properties または環境変数を介してエンドポイントに関連付けます。クライアントから受信した認証情報は、コールバックハンドラーによって認証されます。
  3. クライアント側では、application.properties 内の設定または環境変数を通じて認証情報を提供します。または、認証コールバックハンドラーを実装して認証情報を渡すこともできます。

6.1.3.1. 認証ポリシーの指定

サービスエンドポイントで認証を強制する場合は、サポートトークン ポリシーアサーションを関連するエンドポイントバインディングに関連付け、その下に 1 つ以上の トークンアサーション を指定します。

サポートトークンポリシーアサーションにはいくつかの種類があり、その XML 要素名はすべて SupportingTokens で終わります (たとえば、SupportingTokensSignedSupportingTokens など)。完全なリストは、WS-SecurityPolicy 仕様の Supporting Tokens のセクションを参照してください。

6.1.3.2. UsernameToken ポリシーアサーションの例

ヒント

このセクションで使用されるサンプルコードスニペットは、Quarkus CXF のソースツリーにある WS-SecurityPolicy インテグレーションテスト からのものです。これは、実行可能な例として使用できます。

次のリストは、WS-Security UsernameToken (ユーザー名/パスワードの認証情報を含む) をセキュリティーヘッダーに含めることを要求するポリシーの例を示しています。

username-token-policy.xml

<?xml version="1.0" encoding="UTF-8"?>
<wsp:Policy
        wsp:Id="UsernameTokenSecurityServicePolicy"
        xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
    xmlns:sp13="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200802"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <wsp:ExactlyOne>
        <wsp:All>
            <sp:SupportingTokens>
                <wsp:Policy>
                    <sp:UsernameToken
                        sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
                        <wsp:Policy>
                            <sp:WssUsernameToken11 />
                            <sp13:Created />
                            <sp13:Nonce />
                        </wsp:Policy>
                    </sp:UsernameToken>
                </wsp:Policy>
            </sp:SupportingTokens>
        </wsp:All>
    </wsp:ExactlyOne>
</wsp:Policy>

このポリシーファイルをサービスエンドポイントに関連付けるには、次の 2 つの方法があります。

  • 次のように、サービスエンドポイントインターフェイス (SEI) のポリシーを参照します。

    UsernameTokenPolicyHelloService.java

    @WebService(serviceName = "UsernameTokenPolicyHelloService")
    @Policy(placement = Policy.Placement.BINDING, uri = "username-token-policy.xml")
    public interface UsernameTokenPolicyHelloService extends AbstractHelloService {
        ...
    }

  • WSDL 契約に ポリシーを含め、PolicyReference 要素 を介して参照します。

ポリシーを設定したら、サービスエンドポイントとクライアントで認証情報を設定します。

application.properties

# A service with a UsernameToken policy assertion
quarkus.cxf.endpoint."/helloUsernameToken".implementor = io.quarkiverse.cxf.it.security.policy.UsernameTokenPolicyHelloServiceImpl
quarkus.cxf.endpoint."/helloUsernameToken".security.callback-handler = #usernameTokenPasswordCallback

# These properties are used in UsernameTokenPasswordCallback
# and in the configuration of the helloUsernameToken below
wss.user = cxf-user
wss.password = secret

# A client with a UsernameToken policy assertion
quarkus.cxf.client.helloUsernameToken.client-endpoint-url = https://localhost:${quarkus.http.test-ssl-port}/services/helloUsernameToken
quarkus.cxf.client.helloUsernameToken.service-interface = io.quarkiverse.cxf.it.security.policy.UsernameTokenPolicyHelloService
quarkus.cxf.client.helloUsernameToken.security.username = ${wss.user}
quarkus.cxf.client.helloUsernameToken.security.password = ${wss.password}

上記のリストでは、usernameTokenPasswordCallback は、javax.security.auth.callback.CallbackHandler を実装する @jakarta.inject.Named Bean の名前です。Quarkus CXF は、CDI コンテナー内でこの 名前 の Bean を検索します。

以下は Bean の実装例です。

UsernameTokenPasswordCallback.java

package io.quarkiverse.cxf.it.security.policy;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Named;

import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@ApplicationScoped
@Named("usernameTokenPasswordCallback") /* We refer to this bean by this name from application.properties */
public class UsernameTokenPasswordCallback implements CallbackHandler {

    /* These two configuration properties are set in application.properties */
    @ConfigProperty(name = "wss.password")
    String password;
    @ConfigProperty(name = "wss.user")
    String user;

    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        if (callbacks.length < 1) {
            throw new IllegalStateException("Expected a " + WSPasswordCallback.class.getName()
                    + " at possition 0 of callbacks. Got array of length " + callbacks.length);
        }
        if (!(callbacks[0] instanceof WSPasswordCallback)) {
            throw new IllegalStateException(
                    "Expected a " + WSPasswordCallback.class.getName() + " at possition 0 of callbacks. Got an instance of "
                            + callbacks[0].getClass().getName() + " at possition 0");
        }
        final WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
        if (user.equals(pc.getIdentifier())) {
            pc.setPassword(password);
        } else {
            throw new IllegalStateException("Unexpected user " + user);
        }
    }

}

セットアップ全体をテストするには、単純な @QuarkusTest を作成します。

UsernameTokenTest.java

package io.quarkiverse.cxf.it.security.policy;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

import io.quarkiverse.cxf.annotation.CXFClient;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class UsernameTokenTest {

    @CXFClient("helloUsernameToken")
    UsernameTokenPolicyHelloService helloUsernameToken;

    @Test
    void helloUsernameToken() {
        Assertions.assertThat(helloUsernameToken.hello("CXF")).isEqualTo("Hello CXF from UsernameToken!");
    }
}

mvn test -Dtest=UsernameTokenTest でテストを実行すると、UsernamePassword を含む Security ヘッダーを含む SOAP メッセージがログに記録されます。

UsernameTokenTest のログ出力

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soap:mustUnderstand="1">
      <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-bac4f255-147e-42a4-aeec-e0a3f5cd3587">
        <wsse:Username>cxf-user</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">secret</wsse:Password>
        <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">3uX15dZT08jRWFWxyWmfhg==</wsse:Nonce>
        <wsu:Created>2024-10-02T17:32:10.497Z</wsu:Created>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <ns2:hello xmlns:ns2="http://policy.security.it.cxf.quarkiverse.io/">
      <arg0>CXF</arg0>
    </ns2:hello>
  </soap:Body>
</soap:Envelope>

6.1.3.3. SAML v1 および v2 ポリシーアサーションの例

WS-SecurityPolicy インテグレーションテスト には、SAML v1 および SAML v2 アサーションを使用した類似の例も含まれています。

Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.