この章では、次のセキュリティ機能について説明します。
Transport Layer Securityの詳細は、「暗号化フィルタ」を参照してください。
Coherenceのセキュリティ・フレームワークは、クラスタ・アクセス・コントローラの概念に基づいており、構成可能なパラメータまたはコマンドライン属性を使用してオン(アクティブ)にできます。
アクセス・コントローラは、クラスタ・サービスやクラスタ・キャッシュなどのクラスタ・リソースへのアクセスを管理し、次のような(ただしこれに限定されない)操作を制御します。
新しいクラスタ・キャッシュまたはクラスタ・サービスの作成
既存のクラスタ・キャッシュまたはクラスタ・サービスへの参加
既存のクラスタ・キャッシュの破棄
アクセス・コントローラの用途は次のとおりです。
コール元の権限に基づいて、保護されているクラスタ・リソースへのアクセスを付与または拒否
コール元のプライベート資格証明に基づいて送信通信を暗号化
コール元のパブリック資格証明に基づいて受信通信を復号化
Coherenceでは、ローカルのLoginModule(詳細は、『JAAS Reference Guide』を参照)を使用して、1つ以上のクラスタ・ノードでコール元およびアクセス・コントローラを認証し、コール元のアクセス権を検証します。
アクセス・コントローラは、Coherenceデプロイメント・ディスクリプタtangosol-coherence.xmlで宣言可能なプラッガブル・コンポーネントです。指定したクラスは、com.tangosol.net.security.AccessControllerインタフェースを実装する必要があります。
Coherenceでは、Sun社のJDKの標準部品として出荷されている、キー管理インフラストラクチャに基づくデフォルトのアクセス・コントローラ実装が提供されています。
Coherenceのクラスタ・サービスごとに、上位のサービス・メンバー(クラスタ・ノード)の概念が維持されており、これが特定のサービスの制御エージェントの役割を果たしています。上位メンバーはクラスタ・リソースにアクセスするときに他のメンバーに連絡する必要はありませんが、下位ノードがそのサービスに参加する場合は、上位メンバーにリクエストして確認を受ける必要があります。上位メンバーはその後、他のすべてのクラスタ・ノードに対して、参加ノードに関する通知を送信します。
Coherenceは、分散されたデータ管理およびコンピューティングを提供するシステムであるため、セキュリティ・サブシステムは、ある程度の耐環境性を意図して設計されています。2つのクラスタ・ノード間でデータが共有されている場合、そのいずれかのノードが悪質である、つまり、クラスタ・サービスに参加したり、クラスタ・リソースにアクセスするのに十分な資格証明がない可能性があると仮定します。
標準以外の方法でクラスタ・リソースに不正にアクセスしようとするクラスタ・ノードを、悪質なノードと呼ぶことにします。このようなアクセスには、リフレクションを使用したprotectedまたはprivateクラス・データの取得から、分散されている(coherence.jarまたはその他のアプリケーション・バイナリで)クラスの置換、カスタムClassLoader(s)を使用したオンザフライのクラス変更まで、様々な種類があります。一方、標準以外の方法でクラスタ・リソースに不正アクセスしようとしないクラスタ・ノードを、信頼できるノードと呼びます。信頼できるノードであっても、十分な権限なしでリソースにアクセスしようとする場合がありますが、その際には、公開されている標準の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);
ログイン・コール時に、コール元のノードで実行されているJAASを使用してコール元が認証されます。認証に成功すると、ローカル・アクセス・コントローラを使用して次の処理を行います。
ローカルのコール元に、保護されているクラスタ・リソースにアクセスできる権限があるかどうかを確認します(ローカル・アクセス・チェック)。
認証フェーズで取得したコール元のプライベート資格証明を使用して、リソースへのアクセスに関する送信通信を暗号化します。
リクエスタのパブリック資格証明を使用して、リモート・チェックの結果を復号化します。
アクセスが承認された場合は、レスポンダに十分な権限があったかどうかを検証します。
前述の手順2では、レスポンダのIDが証明されます。これにより、悪質なノードがローカル・アクセス・チェック・フェーズをパスしたかのように偽装する事態を防げます。
クライアント認証情報は、次の2つの方法でも提供できます。まず、CallbackHandlerに対する参照を、ユーザー名とパスワードのかわりに渡すことができます。また、以前に認証したサブジェクトを使用できます。これは、認証されたサブジェクトをアプリケーション・コンテナから取得するJava EEアプリケーションでCoherenceが使用される場合に便利です。
コール元のリクエストを認証コンテキストなしで受信した場合、Coherenceオペレーション・ディスクリプタで宣言されているCallbackHandler実装をインスタンス化およびコールして、適切な資格証明を取得します。ただし、この遅延アプローチは非常に非効率的です。外部で定義されたコール・スコープがないと、保護されているクラスタ・リソースにアクセスするたびに、認証コールが強制的に繰り返し実行されるためです。
Coherence内のクラスタ・リソースはすべて、明示的なAPIコールによって作成されます。上位のサービス・メンバーは、このコール時に提示されたプライベート資格証明を、信頼性の証明として保持します。上位のサービス・メンバーは、保護されているクラスタ・リソースに対するアクセス・リクエストを受信すると、ローカル・アクセス・コントローラを使用して次の処理を行います。
リモートのコール元のパブリック資格証明を使用して、受信通信を復号化します。
リモートのコール元に、保護されているクラスタ・リソースにアクセスできる権限があるかどうかを確認します(リモート・アクセス・チェック)。
サービスのプライベート資格証明を使用して、アクセス・チェックのレスポンスを暗号化します。
リクエスタがレスポンスを有効なものとして受け入れるのは復号化後のみであるため、このサイクルの手順3では、リクエスタの信頼性が証明されます。これにより、悪質なノードが有効な上位サービスであるかのように偽装する事態を防げます。
Coherenceには、標準的なJavaキーストアを使用するアクセス・コントローラ実装が同梱されています。この実装クラスは、com.tangosol.net.security.DefaultControllerです。Coherenceオペレーション・ディスクリプタでは、次の箇所でデフォルトの実装を構成します。
<security-config>
<enabled system-property="tangosol.coherence.security">true</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>
login-module-name要素は、ログイン・コンフィギュレーション・ファイル内でアプリケーション名の役割を果たします(詳細は、『JAAS Reference Guide1』を参照)。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つのインスタンス化パラメータを指定するAccessController実装を定義します。
1つ目のパラメータは、コントローラとログイン・モジュールの両方で使用される同じキーストアのパスです。
2つ目のパラメータは、アクセス権限ファイルのパスです(後述の説明を参照)。
callback-handlerは、javax.security.auth.callback.CallbackHandlerインタフェースのカスタム実装を定義するオプションの要素です。他のすべての方法を試した後に、クライアントの認証用にインスタンス化および使用されます。
さらに2つの手順を実行する必要があります。アプリケーションでデフォルトのアクセス・コントローラ実装を使用可能にするには、次の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>
ポリシー・ファイルの形式の詳細は、『Java SE Security Guide』を参照してください。次に例を示します。
grant codeBase "file:${coherence.home}/lib/coherence.jar"
{
permission java.security.AllPermission;
};
Coherenceの機能に最低限必要とされる権限セットは、security.policyファイル内で指定されています。これは、Coherenceインストールの一部として同梱されています。このファイルは、coherence/lib/security/security.policyにあります。
バイナリには、次のように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バイナリや権限などの、すべての関連ファイルをオペレーティング・システムのメカニズムで保護し、悪質な改ざんを回避する必要があります。