第1章 HTTP と互換性のあるバインディングのセキュリティー
概要
この章では、Apache CXF HTTP トランスポートによってサポートされるセキュリティー機能を説明します。これらのセキュリティー機能は、HTTP トランスポートの上に階層化できる Apache CXF バインディングで使用できます。
概要
このセクションでは、通常 HTTPS と呼ばれる組み合わせである SSL/TLS セキュリティーを使用するように HTTP トランスポートを設定する方法を説明します。Apache CXF では、XML 設定ファイルに設定を指定して、HTTPS セキュリティーを設定します。
SSL/TLS セキュリティーを有効にする場合は、Poodle 脆弱性 (CVE-2014-3566) に対して保護するために、SSLv3 プロトコルを明示的に無効にする必要があります。詳細は、Disabling SSLv3 in JBoss Fuse 6.x and JBoss A-MQ 6.x を参照してください。
この章では、以下のトピックを説明します。
X.509 証明書の生成
SSL/TLS セキュリティーを使用するための基本的な前提条件は、サーバーアプリケーションを識別するための X.509 証明書のコレクションと、任意でクライアントアプリケーションを特定することです。X.509 証明書は、以下のいずれかの方法で生成できます。
- 商用のサードパーティーを使用して X.509 証明書を生成および管理します。
-
無料の
openssl
ユーティリティー (http://www.openssl.org からダウンロード可能) および Javakeystore
ユーティリティーを使用して、証明書を生成します (「CA を使用した Java キーストアでの署名証明書の作成」 を参照)。
HTTPS プロトコルは URL 整合性チェック を行います。これには、サーバーがデプロイされているホスト名と一致する証明書のアイデンティティーが必要です。詳細は、「HTTPS 証明書の特別な要件」 を参照してください。
証明書の形式
Java ランタイムでは、X.509 証明書チェーンおよび信頼できる CA 証明書を Java キーストアの形式でデプロイする必要があります。詳細は、3章HTTPS の設定 を参照してください。
HTTPS の有効化
WSDL エンドポイントで HTTPS を有効にするための前提条件として、エンドポイントアドレスを HTTPS URL として指定する必要があります。エンドポイントアドレスが設定され、両方とも HTTPS URL を使用するように変更する必要がある 2 つの場所があります。
WSDL コントラクトで指定した HTTPS では、例1.1「WSDL での HTTPS の指定」 のように、WSDL 契約のエンドポイントアドレスを https: 接頭辞を持つ URL に指定する必要があります。
例1.1 WSDL での HTTPS の指定
<wsdl:definitions name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" ... > ... <wsdl:service name="SOAPService"> <wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort"> <soap:address location="https://localhost:9001/SoapContext/SoapPort"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
soap:address
要素のlocation
属性は、HTTPS URL を使用するように設定されています。SOAP 以外のバインディングの場合、http:address
要素のlocation
属性に表示される URL を編集します。サーバーコードで指定された HTTPS — 例1.2「サーバーコードでの HTTPS の指定」 で示されるように、
Endpoint.publish()
を呼び出すことでサーバーコードに公開されている URL が、https: 接頭辞で定義されていることを確認する必要があります。例1.2 サーバーコードでの HTTPS の指定
// Java package demo.hw_https.server; import javax.xml.ws.Endpoint; public class Server { protected Server() throws Exception { Object implementor = new GreeterImpl(); String address = "https://localhost:9001/SoapContext/SoapPort"; Endpoint.publish(address, implementor); } ... }
証明書のない HTTPS クライアント
たとえば、例1.3「証明書のない HTTPS クライアントのサンプル」 に示されるように、証明書のないセキュアな HTTPS クライアントの設定について考えてみましょう。
例1.3 証明書のない HTTPS クライアントのサンプル
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xsi:schemaLocation="..."> <http:conduit name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit"> <http:tlsClientParameters> <sec:trustManagers> <sec:keyStore type="JKS" password="password" file="certs/truststore.jks"/> </sec:trustManagers> <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> </http:tlsClientParameters> </http:conduit> </beans>
上記のクライアント設定については、以下で説明します。
TLS セキュリティー設定は特定の WSDL ポートで定義されます。この例では、設定される WSDL ポートには QName {http://apache.org/hello_world_soap_http}SoapPort
が設定されています。
http:tlsClientParameters
要素には、クライアントの TLS 設定の詳細がすべて含まれます。
sec:trustManagers
要素は、信頼できる CA 証明書のリストを指定するために使用されます (クライアントはこのリストを使用して、サーバー側から受信した証明書を信頼するかどうかを決定します)。
sec:keyStore
要素の file
属性は、1 つ以上の信頼できる CA 証明書が含まれる Java キーストアファイル truststore.jks
を指定します。password
属性は、キーストアへのアクセスに必要なパスワードを指定します (truststore.jks
)。「HTTPS の信頼された CA 証明書の指定」を参照してください。
file
属性の代わりに、resource
属性 (クラスパスでキーストアファイルが提供される場合) または url
属性のいずれかを使用してキーストアの場所を指定できます。特に、OSGi コンテナーにデプロイされるアプリケーションで resource
属性を使用する必要があります。信頼されていないソースからトラストストアを読み込まないように細心の注意を払う必要があります。
sec:cipherSuitesFilter
要素を使用すると、クライアントが TLS 接続に使用する暗号スイートの選択肢を絞り込むことができます。詳細は、4章HTTPS 暗号化スイートの設定 を参照してください。
証明書を含む HTTPS クライアント
独自の証明書が設定されているセキュアな HTTPS クライアントについて考えてみましょう。例1.4「証明書を使用する HTTPS クライアントの例」 は、このようなサンプルクライアントを設定する方法を示しています。
例1.4 証明書を使用する HTTPS クライアントの例
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xsi:schemaLocation="..."> <http:conduit name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit"> <http:tlsClientParameters> <sec:trustManagers> <sec:keyStore type="JKS" password="password" file="certs/truststore.jks"/> </sec:trustManagers> <sec:keyManagers keyPassword="password"> <sec:keyStore type="JKS" password="password" file="certs/wibble.jks"/> </sec:keyManagers> <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> </http:tlsClientParameters> </http:conduit> <bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl"/> </beans>
上記のクライアント設定については、以下で説明します。
sec:keyManagers
要素は、X.509 証明書と秘密鍵をクライアントに割り当てるために使用されます。keyPasswod
属性で指定されるパスワードは、証明書の秘密鍵を復号するために使用されます。
sec:keyStore
要素は、Java キーストアに保存される X.509 証明書と秘密鍵を指定するために使用されます。この例では、キーストアが Java Keystore Format (JKS) であることを宣言します。
file
属性は、キーストアファイル wibble.jks
の場所を指定します。これには、クライアントの X.509 証明書チェーンと キーエントリー の秘密鍵が含まれています。password
属性は、キーストアのコンテンツへのアクセスに必要なキーストアパスワードを指定します。
キーストアファイルにはキーエントリーが 1 つだけ含まれるため、エントリーを識別するキーエイリアスを指定する必要はありません。複数 のキーエントリーを持つキーストアファイルをデプロイする場合は、以下のように sec:certAlias
要素を http:tlsClientParameters
要素の子として追加することで、キーを指定することができます。
<http:tlsClientParameters>
...
<sec:certAlias>CertAlias</sec:certAlias>
...
</http:tlsClientParameters>
キーストアファイルの作成方法は 「CA を使用した Java キーストアでの署名証明書の作成」 を参照してください。
file
属性の代わりに、resource
属性 (クラスパスでキーストアファイルが提供される場合) または url
属性のいずれかを使用してキーストアの場所を指定できます。特に、OSGi コンテナーにデプロイされるアプリケーションで resource
属性を使用する必要があります。信頼されていないソースからトラストストアを読み込まないように細心の注意を払う必要があります。
HTTPS サーバーの設定
クライアントが X.509 証明書を提示する必要があるセキュアな HTTPS サーバーについて考えてみましょう。例1.5「HTTPS サーバーの設定例」 は、このようなサーバーを設定する方法を示しています。
例1.5 HTTPS サーバーの設定例
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xsi:schemaLocation="..."> <httpj:engine-factory bus="cxf"> <httpj:engine port="9001"> <httpj:tlsServerParameters secureSocketProtocol="TLSv1"> <sec:keyManagers keyPassword="password"> <sec:keyStore type="JKS" password="password" file="certs/cherry.jks"/> </sec:keyManagers> <sec:trustManagers> <sec:keyStore type="JKS" password="password" file="certs/truststore.jks"/> </sec:trustManagers> <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> <sec:clientAuthentication want="true" required="true"/> </httpj:tlsServerParameters> </httpj:engine> </httpj:engine-factory> </beans>
上記のサーバー設定は、以下のとおりです。
bus
属性は、関連する CXF Bus インスタンスを参照します。デフォルトでは、ID が cxf
の CXF Bus インスタンスは、Apache CXF ランタイムによって自動的に作成されます。
サーバー側では、TLS は WSDL ポートごとに設定されて いません。各 WSDL ポートを設定する代わりに、TLS セキュリティー設定が特定の TCP ポート (この例では 9001
) に適用されます。そのため、この TCP ポートを共有するすべての WSDL ポートは、同じ TLS セキュリティー設定で設定されています。
http:tlsServerParameters 要素には、サーバーの TLS 設定の詳細がすべて含まれます。
Poodle 脆弱性 (CVE-2014-3566) から保護するために、サーバー側で secureSocketProtocol を TLSv1
に設定する必要があります。
sec:keyManagers
要素は、X.509 証明書と秘密鍵をサーバーに割り当てるために使用されます。keyPasswod
属性で指定されるパスワードは、証明書の秘密鍵を復号するために使用されます。
sec:keyStore
要素は、Java キーストアに保存される X.509 証明書と秘密鍵を指定するために使用されます。この例では、キーストアが Java Keystore Format (JKS) であることを宣言します。
file
属性は、キーストアファイル cherry.jks
の場所を指定します。これには、クライアントの X.509 証明書チェーンと キーエントリー の秘密鍵が含まれています。password
属性は、キーストアのコンテンツへのアクセスに必要なキーストアパスワードを指定します。
キーストアファイルにはキーエントリーが 1 つだけ含まれるため、エントリーを識別するキーエイリアスを指定する必要はありません。複数 のキーエントリーを持つキーストアファイルをデプロイする場合は、以下のように sec:certAlias
要素を http:tlsClientParameters
要素の子として追加することで、キーを指定することができます。
<http:tlsClientParameters>
...
<sec:certAlias>CertAlias</sec:certAlias>
...
</http:tlsClientParameters>
file
属性の代わりに、resource
属性または url
属性のいずれかを使用してキーストアの場所を指定できます。信頼されていないソースからトラストストアを読み込まないように細心の注意を払う必要があります。
このようなキーストアファイルを作成する方法は、「CA を使用した Java キーストアでの署名証明書の作成」 を参照してください。
sec:trustManagers
要素は、信頼できる CA 証明書のリストを指定するために使用されます (サーバーはこのリストを使用して、クライアントが提示する証明書を信頼するかどうかを判断します)。
sec:keyStore
要素の file
属性は、1 つ以上の信頼できる CA 証明書が含まれる Java キーストアファイル truststore.jks
を指定します。password
属性は、キーストアへのアクセスに必要なパスワードを指定します (truststore.jks
)。「HTTPS の信頼された CA 証明書の指定」を参照してください。
file
属性の代わりに、resource
属性または url
属性のいずれかを使用してキーストアの場所を指定できます。
sec:cipherSuitesFilter
要素を使用すると、サーバーが TLS 接続に使用する暗号スイートの選択肢を絞り込むことができます。詳細は、4章HTTPS 暗号化スイートの設定 を参照してください。
sec:clientAuthentication
要素は、クライアント証明書の提示に対するサーバーの処理を決定します。要素には以下の属性があります。
-
want
属性 —true
(デフォルト) の場合、サーバーは TLS ハンドシェイク中に、X.509 証明書を提示するようにクライアントに要求します。false
の場合は、サーバーはクライアントに X.509 証明書の提示を 要求しません。 -
required
属性 —true
の場合、TLS ハンドシェイク中にクライアントが X.509 証明書を提示できないと、サーバーは例外を発生させます。false
(デフォルト) の場合は、クライアントが X.509 証明書を提示できなくても、サーバーは 例外を発生させません。