この章では、次のセキュリティ機能について説明します。
Coherenceのセキュリティ・フレームワークは、クラスタ・アクセス・コントローラの概念に基づいており、構成可能なパラメータまたはコマンドライン属性を使用してオン(アクティブ)にできます。
この項は、次のトピックで構成されています。
アクセス・コントローラは、クラスタ・サービスやクラスタ・キャッシュなどのクラスタ・リソースへのアクセスを管理し、次のような(ただしこれに限定されない)操作を制御します。
新しいクラスタ・キャッシュまたはクラスタ・サービスの作成
既存のクラスタ・キャッシュまたはクラスタ・サービスへの参加
既存のクラスタ・キャッシュの破棄
アクセス・コントローラの用途は次のとおりです。
コール元の権限に基づいて、保護されているクラスタ・リソースへのアクセスを付与または拒否
コール元のプライベート資格証明に基づいて送信通信を暗号化
コール元のパブリック資格証明に基づいて受信通信を復号化
Coherenceでは、ローカルのログイン・モジュール(詳細は、JAASリファレンス・ガイドを参照)を使用して、1つ以上のクラスタ・ノードでコール元およびアクセス・コントローラを認証し、コール元のアクセス権を検証します。
アクセス・コントローラは、Coherenceデプロイメント・ディスクリプタtangosol-coherence.xml
で宣言可能なプラッガブル・コンポーネントです。指定されたクラスは、com.tangosol.net.security.AccessController
インタフェースを実装する必要があります。
Coherenceでは、Sun社のJDKの標準部品として出荷されている、キー管理インフラストラクチャに基づくデフォルトのアクセス・コントローラ実装が提供されています。「デフォルトのアクセス・コントローラ実装の有効化」を参照してください。
Coherenceのクラスタ・サービスごとに、上位のサービス・メンバー(クラスタ・ノード)の概念が維持されており、これが特定のサービスの制御エージェントの役割を果たしています。上位メンバーはクラスタ・リソースにアクセスするときに他のメンバーに連絡する必要はありませんが、下位ノードがそのサービスに参加する場合は、上位メンバーにリクエストして確認を受ける必要があります。上位メンバーはその後、他のすべてのクラスタ・ノードに対して、参加ノードに関する通知を送信します。
Coherenceは、分散されたデータ管理およびコンピューティングを提供するシステムであるため、セキュリティ・サブシステムは、ある程度の耐環境性を意図して設計されています。2つのクラスタ・ノード間でデータが共有されている場合、そのいずれかのノードが悪質である、つまり、クラスタ・サービスに参加したり、クラスタ・リソースにアクセスするのに十分な資格証明がない可能性があると仮定します。
標準以外の方法でクラスタ・リソースに不正にアクセスしようとするクラスタ・ノードを、悪質なノードと呼ぶことにします。このようなアクセスには、リフレクションを使用したprotectedまたはprivateクラス・データの取得から、分散されているクラス(coherence.jar
またはその他のアプリケーション・バイナリ)の置換、カスタム・クラス・ローダーを使用したオンザフライのクラス変更まで、様々な種類があります。一方、標準以外の方法でクラスタ・リソースに不正アクセスしようとしないクラスタ・ノードを、信頼できるノードと呼びます。信頼できるノードであっても、十分な権限なしでリソースにアクセスしようとする場合がありますが、その際には、公開されている標準のAPIを使用して標準的な方法で行います。
ファイル・システム・メカニズム(Javaランタイム・ライブラリの整合性を保護するメカニズムと同じ)および標準のJavaセキュリティ・ポリシーを使用すると、特定の単一ノードの信頼性に関する問題を解決できます。ノード間通信の場合は、次の2つの考慮すべき危険性があります。
悪質なノードがローカル・アクセス・チェックを迂回して、クラスタ・サービスに参加したり、信頼できるノードが管理しているクラスタ・リソースにアクセスしたりしようとします。
悪質なノードがクラスタ・サービスまたはクラスタ・リソースを作成し、そのコントローラになります。
これら2つの状況が発生しないように、Coherenceでは双方向の暗号化アルゴリズムを使用します。そうすることで、すべてのクライアント・リクエストにIDの証明が付加され、すべてのサービス・レスポンスには信頼性の証明が付加されます。
アクティブなアクセス・コントローラの場合は、クライアント・コードで次の構造を使用してコール元を認証し、必要なアクションを実行できます。
import com.tangosol.net.security.Security; import java.security.PrivilegedAction; import javax.security.auth.Subject; ... Subject subject = Security.login(sName, acPassword); PrivilegedAction action = new PrivilegedAction() { public Object run() { // all processing here is taking place with access // rights assigned to the corresponding Subject ... } }; Security.runAs(subject, action);
login
コール時に、コール元のノードで実行されているJAASを使用してコール元が認証されます。認証に成功すると、ローカル・アクセス・コントローラを使用して次の処理を行います。
ローカルのコール元に、保護されているクラスタ・リソースにアクセスできる権限があるかどうかを確認します(ローカル・アクセス・チェック)。
認証フェーズで取得したコール元のプライベート資格証明を使用して、リソースへのアクセスに関する送信通信を暗号化します。
リクエスタのパブリック資格証明を使用して、リモート・チェックの結果を復号化します。
アクセスが承認された場合は、レスポンダに十分な権限があったかどうかを検証します。
前述の暗号化の手順では、レスポンダのIDが証明されます。これにより、悪質なノードがローカル・アクセス・チェック・フェーズをパスしたかのように偽装する事態を防げます。
クライアント認証情報は、次の2つの方法でも提供できます。まず、CallbackHandler
に対する参照を、ユーザー名とパスワードのかわりに渡すことができます。また、以前に認証したサブジェクトを使用できます。これは、認証されたサブジェクトをアプリケーション・コンテナから取得するJava EEアプリケーションでCoherenceが使用される場合に便利です。
コール元のリクエストを認証コンテキストなしで受信した場合、Coherenceオペレーション・ディスクリプタで宣言されているCallbackHandler
実装をインスタンス化およびコールして、適切な資格証明を取得します。ただし、この遅延アプローチは非常に非効率的です。外部で定義されたコール・スコープがないと、保護されているクラスタ・リソースにアクセスするたびに、認証コールが強制的に繰り返し実行されるためです。
Coherence内のクラスタ・リソースはすべて、明示的なAPIコールによって作成されます。上位のサービス・メンバーは、このコール時に提示されたプライベート資格証明を、信頼性の証明として保持します。上位のサービス・メンバーは、保護されているクラスタ・リソースに対するアクセス・リクエストを受信すると、ローカル・アクセス・コントローラを使用して次の処理を行います。
リモートのコール元のパブリック資格証明を使用して、受信通信を復号化します。
サービスのプライベート資格証明を使用して、アクセス・チェックのレスポンスを暗号化します。
リモートのコール元に、保護されているクラスタ・リソースにアクセスできる権限があるかどうかを確認します(リモート・アクセス・チェック)。
リクエスタがレスポンスを有効なものとして受け入れるのは復号化後のみであるため、このサイクルの最後の手順では、リクエスタの信頼性が証明されます。これにより、悪質なノードが有効な上位サービスであるかのように偽装する事態を防げます。
Coherenceには、標準的なJavaキーストアを使用するデフォルトのアクセス・コントローラ実装が同梱されています。実装クラスはcom.tangosol.net.security.DefaultController
クラスで、Coherenceオペレーション・デプロイメント・ディスクリプタで構成されます。
<security-config> <enabled system-property="tangosol.coherence.security">false</enabled> <login-module-name>Coherence</login-module-name> <access-controller> <class-name>com.tangosol.net.security.DefaultController</class-name> <init-params> <init-param id="1"> <param-type>java.io.File</param-type> <param-value>./keystore.jks</param-value> </init-param> <init-param id="2"> <param-type>java.io.File</param-type> <param-value>./permissions.xml</param-value> </init-param> </init-params> </access-controller> <callback-handler> <class-name/> </callback-handler> </security-config>
デフォルトのアクセス・コントローラ実装は、デフォルトでは有効になっていません。デフォルトの実装を有効化するには、オペレーション・オーバーライド・ファイルの<security-config>
ノード内の<enabled>
要素をオーバーライドし、true
に設定します。例:
<coherence> <security-config> <enabled>true</enabled> </security-config> </coherence>
デフォルトのアクセス・コントローラ実装は、tangosol.coherence.security
システム・プロパティをtrue
に設定しても有効にできます。
注意: Coherenceセキュリティが有効になっている場合、CacheFactory.getCache() またはConfigurableCacheFactory.ensureCache() APIへのコールごとにセキュリティの確認が発生します。これらのコールが頻繁に実行されると、これはアプリケーションのパフォーマンスに悪影響を及ぼす可能性があります。ベスト・プラクティスは、アプリケーションがキャッシュ参照を保持し、セキュリティの確認が初期コール時にのみ実行されるようにそれを再使用することです。この方法を使用すると、それらの参照が認可された方法でのみ使用されていることをアプリケーション側で確認されます。 |
<login-module-name>
要素は、ログイン構成ファイル内でアプリケーション名の役割を果たします(詳細は、JAASリファレンス・ガイドを参照)。Coherenceには、coherence-login.jar
に含まれている、Javaキーストア(JKS)ベースのログイン・モジュールが同梱されています。これは、標準的なJavaランタイム・クラスにのみ依存しており、JREのlib/ext
(標準拡張)ディレクトリに配置できます。対応するログイン・モジュール宣言は次のようになります。
// LoginModule Configuration for Oracle Coherence(TM) Coherence { com.tangosol.security.KeystoreLogin required keyStorePath="${user.dir}${/}keystore.jks"; };
<access-controller>
要素は、次の2つのインスタンス化パラメータを指定するアクセス・コントローラ実装を定義します。
1つ目のパラメータは、コントローラとログイン・モジュールの両方で使用される同じキーストアのパスです。
2つ目のパラメータは、アクセス権限ファイルのパスです(後述の説明を参照)。
<callback-handler>
は、javax.security.auth.callback.CallbackHandler
インタフェースのカスタム実装を定義するオプションの要素です。他のすべての方法を試した後に、クライアントの認証用にインスタンス化および使用されます。
さらに2つの手順を実行する必要があり、次の手順でアプリケーションでデフォルトのアクセス・コントローラ実装を使用可能にします。
必要なプリンシパルを持つキーストアを作成します。
対応するプリンシパルへのアクセス権を宣言するpermissions
ファイルを作成します。
次の例では、3つのプリンシパルを作成します。admin
はJavaセキュリティ・フレームワークで使用し、manager
およびworker
はCoherenceで使用します。
keytool -genkey -v -keystore ./keystore.jks -storepass password -alias admin -keypass password -dname CN=Administrator,O=MyCompany,L=MyCity,ST=MyState keytool -genkey -v -keystore ./keystore.jks -storepass password -alias manager -keypass password -dname CN=Manager,OU=MyUnit keytool -genkey -v -keystore ./keystore.jks -storepass password -alias worker -keypass password -dname CN=Worker,OU=MyUnit
次の例では、Manager
プリンシパルにはすべての権限を、名前の先頭にcommon
が付いているキャッシュのWorker
プリンシパルにはjoin
の権限のみを、invocation
という名前の起動サービスのWorker
プリンシパルにはすべての権限を割り当てます。
<?xml version='1.0'?> <permissions> <grant> <principal> <class>javax.security.auth.x500.X500Principal</class> <name>CN=Manager,OU=MyUnit</name> </principal> <permission> <target>*</target> <action>all</action> </permission> </grant> <grant> <principal> <class>javax.security.auth.x500.X500Principal</class> <name>CN=Worker,OU=MyUnit</name> </principal> <permission> <target>cache=common*</target> <action>join</action> </permission> <permission> <target>service=invocation</target> <action>all</action> </permission> </grant> </permissions>
セキュリティ・マネージャがインストールされているアプリケーションで作業する際には、次の手順を実行します。
ポリシー・ファイルに最低限の権限セットを入力します。
Coherenceの機能に最低限必要とされる権限セットは、security.policy
ファイル内で指定されています。これは、Coherenceインストールの一部として同梱されています。このファイルは、COHERENCE_HOME
/lib/security/security.policy
にあります。
ポリシー・ファイルの形式の詳細は、Java SEセキュリティ・ガイドを参照してください。次のURLを参照してください。
http://java.sun.com/j2se/1.4.2/docs/guide/security/spec/security-spec.doc3.html#20128
例:
grant codeBase "file:${coherence.home}/lib/coherence.jar" { permission java.security.AllPermission; };
次のように、JDK jarsigner
ツールを使用してバイナリに署名します。
jarsigner -keystore ./keystore.jks -storepass password coherence.jar admin
さらに、次のようにポリシー・ファイルで保護することもできます。
grant SignedBy "admin" codeBase "file:${coherence.home}/lib/coherence.jar" { permission java.security.AllPermission; };
オペレーティング・システムのメカニズムを使用して、ポリシー形式、Coherenceバイナリ、権限などすべての関連ファイルを悪質な改ざんから保護します。
Coherenceには、Coherence*Extendクライアントとプロキシ間のTCP通信と同様、クラスタ・ノード間のTCMP通信を保護するために使用できるSecure Socket Layer(SSL)実装が用意されています。Coherenceでは、SSL 3.0プロトコルの次のバージョンのTransport Layer Security(TLS)1.0プロトコルがサポートされています。しかし、SSLの方が広く認識されている用語であるため、このドキュメントではSSLという用語を使用します。
この項は、次のトピックで構成されています。
注意: この項では、クラスタ・ノード間のTCMPにSSLを使用する手順のみを記載しています。Coherence*ExtendでのSSLの使用方法は、『Oracle Coherenceクライアント・ガイド』の「クライアントの通信を保護するためのSSLの使用方法」を参照してください。 |
この項では、このドキュメントで使用されている一般的なSSLの概念について概要を簡単に説明します。SSLの詳細については述べません。SSLに慣れていない方は、http://www.ietf.org
で入手できる正式な仕様、およびhttp://java.sun.com/javase/technologies/security/index.jsp
にあるJava SEセキュリティのリソースを参照してください。SSLについて精通している場合は、この項を省略できます。
SSLは、ネットワーク上のエンティティ間(通常、クライアントとサーバー)の通信を保護するために使用されるセキュリティ・プロトコルです。SSLは、クライアントとサーバーをデジタル証明書を使用して認証し、認証済のクライアントとサーバーに関連付けられた一意のキーを使用して通信を暗号化/復号化することにより機能してます。
識別と信頼の確立
エンティティの識別は、デジタル証明書を公開および秘密の暗号化鍵とともに使用することで確立されます。デジタル証明には、エンティティに関する一般情報と、それに埋め込まれた公開の暗号化鍵が含まれています。デジタル証明は認証局(CA)によって検証され、CAのデジタル証明を使用して署名されています。CAのデジタル証明により、エンティティが本物であるという信頼が確立されます。
データの暗号化および復号化
エンティティのデジタル証明には、エンティティの秘密の暗号化鍵と対になった公開の暗号化鍵が含まれています。証明書は、初期接続の際にエンティティ間で渡されます。そのとき、データは公開鍵を使用して暗号化されます。エンティティの公開鍵を使用して暗号化されたデータは、そのエンティティの秘密鍵でのみ復号化されます。これにより、公開の暗号化鍵を所有するエンティティのみがそのデータを復号化できるのです。
一方向の認証と双方向の認証の使用
クライアントとサーバー間のSSL通信は、一方向または双方向のいずれの認証を使用しても設定できます。一方向の認証では、サーバーは認証用のデジタル証明を送信して、クライアントに対してそのサーバー自体を識別する必要があります。クライアントはサーバーにデジタル証明を送信する必要はなく、サーバーに対して匿名のままです。双方向の認証では、クライアントとサーバーの両方がそれぞれのデジタル証明を相互の認証のために送信する必要があります。双方向の認証では、通信の両サイドで識別の認識が確認されることによって、より強いセキュリティが提供されます。
SSLアーティファクトの生成
JDK_HOME
/bin
ディレクトリに置かれたJava keytool
ユーティリティは、SSLアーティファクトを生成および管理する際に使用できます。これには、キー・ストアの作成、一意の公開/秘密鍵ペアの生成、公開鍵を含む自己署名付きデジタル証明書の作成、証明書の秘密鍵への関連付け、キー・ストアへのこれらのアーティファクトの格納などが含まれます。
次の例では、/test
ディレクトリに置かれているserver.jks
という名前のキー・ストアを作成します。公開鍵と秘密鍵のペアは、-dname
値("cn=administrator, ou=Coherence, o=Oracle, c=US"
)によって識別されるエンティティに対して生成されます。公開鍵と識別情報を含む自己署名付き証明書が作成されます。この証明書は180
日間有効で、別名(admin
)が参照するキー・ストア・エントリの秘密鍵と関連付けられています。パスワードは、キー・ストアと秘密鍵の両方に対して入力する必要があります。
keytool -genkeypair -dname "cn=administrator, ou=Coherence, o=Oracle, c=US" -alias admin -keypass password -keystore /test/server -storepass password -validity 180
このコマンドで生成される証明書は、開発目的を十分に果たしています。しかし、証明書は通常VeriSignなどの信頼されるCAによって検証されます。証明書が検証されるためには、keytool
ユーティリティを使用して証明書の署名リクエスト(CSR: Certificate Signing Request)ファイルを生成します。
keytool -certreq -file admin.csr
このCSRファイルをCAに送信する必要があり、CAからは署名付きの証明書が返されます。keytool
ユーティリティを使用して、キー・ストア内の自己署名付き証明書に置き換わる返された証明書をインポートします。
keytool -importcert -trustcacerts -file signed_admin.cer
最後に、keytool
を使用して、トラスト・ストアとして機能する2つ目のキー・ストアを作成します。トラスト・ストアには信頼できるCAのデジタル証明書が保管されます。CAが検証した証明書は、CAの証明書がトラスト・ストアにも格納されている場合にのみ、信頼できると見なされます。たとえば、通常の一方向の認証では、クライアントはサーバーの証明書に署名したCAのデジタル証明書が格納されたトラスト・ストアを持っている必要があります。開発目的の場合、自己署名付き証明書は識別と信頼の両方に使用できます。さらに、1つのキーストアが識別ストアと信頼ストアの両方として使用できます。
Coherenceクラスタは、TCMPでSSLを使用するように構成できます。一方向と双方向の認証がサポートされています。通常、双方向の認証を使用する方が一方向の認証よりも多く、クラスタ環境では一方向の認証は双方向の認証ほど使用されません。さらに、TCMPではpeer-to-peerプロトコルであることを認識する必要があります。peer-to-peerプロトコルは、通常、多くのクラスタ・ノードを相互に接続したままであることが想定される信頼できる環境で動作します。管理およびパフォーマンスに関してSSLが受ける可能性のある影響について、慎重に考慮する必要があります。
TCMP用のSSLは、オペレーション・オーバーライド・ファイルで<unicast-listener>
要素内の<socket-provider>
要素をオーバーライドして構成します。<socket-provider>
要素を使用して、<socket-providers>
ノード内で定義されたSSLソケット・プロバイダ構成を参照する方法をお薦めします。<socket-provider>
要素は、<unicast-listener>
要素内の完全な構成の定義にも使用できます。次に両方の方法を示します。<socket-provider>
要素の詳細は、「socket-provider」を参照してください。
注意: クラスタは、TCMPでSSLを使用できるように既知のアドレスを使用して構成する必要があります。 |
例30-1は、SSL双方向の認証設定を示しています。これには、識別ストアと信頼ストアの両方をクラスタの各ノード上に配置する必要があります。この例では、<protocol>
および<algorithm>
要素(それぞれTLS
およびSunX509
)にデフォルト値を使用しています。これらは完全を期して示しますが、デフォルト値使用の際には省略されることがあります。例では、SSLソケット・プロバイダが<socket-providers>
ノード内で定義され、<unicast-listener>
要素内から参照される推奨方法を使用しています。
例30-1 TCMP通信に対するSSLのサンプル構成
<coherence> <cluster-config> <unicast-listener> <well-known-addresses> <socket-address id="1"> <address>198.168.1.5</address> <port>8088</port> </socket-address> </well-known-addresses> <socket-provider>mySSLConfig</socket-provider> </unicast-listener> <socket-providers> <socket-provider id="mySSLConfig"> <ssl> <protocol>TLS</protocol> <identity-manager> <algorithm>SunX509</algorithm> <key-store> <url>file:server.jks</url> <password>password</password> <type>JKS</type> </key-store> <password>password</password> </identity-manager> <trust-manager> <algorithm>SunX509</algorithm> <key-store> <url>file:trust.jks</url> <password>password</password> <type>JKS</type> </key-store> </trust-manager> </ssl> </socket-provider> </socket-providers> </cluster-config> </coherence>
代替案としては次に示すように、SSLソケット・プロバイダを<unicast-listener>
要素内で直接定義することも可能です。
<coherence> <cluster-config> <unicast-listener> <well-known-addresses> <socket-address id="1"> <address>198.168.1.5</address> <port>8088</port> </socket-address> </well-known-addresses> <socket-provider> <ssl> <protocol>TLS</protocol> <identity-manager> <algorithm>SunX509</algorithm> <key-store> <url>file:server.jks</url> <password>password</password> <type>JKS</type> </key-store> <password>password</password> </identity-manager> <trust-manager> <algorithm>SunX509</algorithm> <key-store> <url>file:trust.jks</url> <password>password</password> <type>JKS</type> </key-store> </trust-manager> </ssl> </socket-provider> </unicast-listener> </cluster-config> </coherence>
出荷の際には事前定義済SSLソケット・プロバイダが組み込まれており、信頼できるピアが単一JKSキー・ストア内に存在するピアの信頼に基づいて、双方向のSSL接続を構成できます。専用のピアの信頼アルゴリズム(PeerX509)は、キー・ストア内にある証明書の信頼(信頼のみ)を前提として機能します。TCMPがpeer-to-peerプロトコルであるという事実を活用すると、ピア・アルゴリズムによりSSLのパフォーマンスを向上できます。
事前定義済SSLソケット・プロバイダは、オペレーション・デプロイメント・ディスクリプタの<socket-providers>
要素内に配置されています。
... <socket-providers> ... <socket-provider id="ssl"> <ssl> <identity-manager> <key-store> <url system-property="tangosol.coherence.security.keystore"> file:keystore.jks </url> <password system-property="tangosol.coherence.security.password"/> </key-store> <password system-property="tangosol.coherence.security.password"/> </identity-manager> <trust-manager> <algorithm>PeerX509</algorithm> <key-store> <url system-property="tangosol.coherence.security.keystore"> file:keystore.jks </url> <password system-property="tangosol.coherence.security.password"/> </key-store> </trust-manager> </ssl> </socket-provider> </socket-providers> ...
構成では、事前定義済SSLソケット・プロバイダには、クラスパスにあるkeystore.jks
というJavaキー・ストアが必要です。この名前は、違うキー・ストアを指定する際に、tangosol.coherence.security.keystore
システム・プロパティを使用してオーバーライドできます。さらに、tangosol.coherence.security.password
システム・プロパティを使用して、そのキー・ストアと証明書に必要なパスワードを指定できます。代替案として、オペレーション・オーバーライド・ファイルを使用して、必要に応じて事前定義済SSLソケット・プロバイダを変更できます。
注意: クラスタ内のすべてのノードに対する証明書がキー・ストアにインポートされていることを確認してください。 |
事前定義済SSLソケット・プロバイダを使用するには、<unicast-listener>
構成の<socket-provider>
要素をオーバーライドして、SSLソケット・プロバイダのid
属性を使用してSSLソケット・プロバイダを参照します。次の例では、事前定義済SSLソケット・プロバイダを使用するためにユニキャスト・リスナーを構成しています。
<coherence>
<cluster-config>
<unicast-listener>
<well-known-addresses>
<socket-address id="1">
<address>198.168.1.5</address>
<port>8088</port>
</socket-address>
</well-known-addresses>
<socket-provider>ssl</socket-provider>
</unicast-listener>
</cluster-config>
</coherence>