この章の内容は次のとおりです。
IDトークンは、Extendクライアントがクラスタにアクセスするのを制限します。このトークンは、接続が試行されるたびに、Extendクライアントと拡張プロキシの間で送信されます。有効なIDトークンを渡すExtendクライアントのみに、クラスタへのアクセスが許可されます。
この項には次のトピックが含まれます:
IDトークン・セキュリティでは、IDトランスフォーマの実装を使用してIDトークンが作成され、アイデンティティ・アサータの実装を使用してIDトークンが検証されます。これらの実装は次のとおりです。
IDトランスフォーマ – SubjectまたはPrincipalを拡張プロキシに渡されるIDトークンに変換する、クライアント側のコンポーネント。IDトークンは、ID検証に便利なオブジェクトであれば、どんなタイプでもかまいません。既知のセキュリティ・タイプである必要はありません。また、クライアントは、複数のプロキシ・サーバーに接続でき、各プロキシ・サーバーに対して別々に認証を受けます。
アイデンティティ・アサータ – 拡張プロキシ・サービスをホストしているキャッシュ・サーバー上に存在する、クラスタ側のコンポーネント。アサータでは、Extendクライアント上でIDトランスフォーマによって作成されたIDトークンを検証します。アサータは、各プロキシ・サービス固有のIDトークンを検証して、複数の方法でのトークン検証に対応します。Extendクライアントで接続が開始されると、トークンが渡されます。検証が失敗すると、接続が拒否され、セキュリティ例外がスローされます。トランスフォーマとアサータは、既存の接続内で新しいチャネルが作成されたときにも起動します。
図5-1は、IDトークンを使用してクライアント・アクセスを制限する場合の概念を示しています。
IDトランスフォーマ(DefaultIdentityTransformer)およびアイデンティティ・アサータ(DefaultIdentityAsserter)が用意されており、デフォルトで有効になっています。実装では単に、IDトークンとしてSubject (Java)またはPrincipal (.NET)を使用します。カスタムのIDトランスフォーマおよびアイデンティティ・アサータを実装し、オペレーション・オーバーライド・ファイルで有効にすることにより、デフォルトの動作をオーバーライドできます。
注意:
実行時、IDトランスフォーマの実装クラスは、Extendクライアントのクラスパスに存在する必要があり、アイデンティティ・アサータの実装クラスは、拡張プロキシ・サーバーのクラスパスに存在する必要があります。
Portable Object Format (POF)で事前定義されているもの以外のセキュリティ・オブジェクト・タイプの使用方法の詳細は、「カスタム・セキュリティ・タイプの使用方法」を参照してください。
渡されたSubjectまたはPrincipalを単に返すデフォルトIDトランスフォーマの実装(DefaultIdentityTransformer)が提供されています。デフォルトの実装を使用しない場合は、独自のカスタム・トランスフォーマの実装を作成できます。
注意:
実行時、IDトークンは、既知のタイプに対して自動的にシリアライズされ、拡張接続リクエストの一部として送信されます。.NETクライアントおよびC++クライアントの場合は、POFタイプを使用する必要があります。事前定義されているPOFタイプ以外のセキュリティ・オブジェクト・タイプの使用方法の詳細は、「カスタム・セキュリティ・タイプの使用方法」を参照してください。
JavaおよびC++の場合、IdentityTransformerインタフェースを実装することで、カスタムIDトランスフォーマを作成します。C#クライアントではIIdentityTransformerインタフェースを実装します。
例5-1は、クライアントからプロキシにアクセスするためのパスワードの入力を要求することによって、クライアント・アクセスを制限するJavaの実装を示しています。この実装は、クライアントのシステム・プロパティからパスワードを取得して、それをIDトークンとして返します。
例5-1 IDトランスフォーマの実装のサンプル
import com.tangosol.net.security.IdentityTransformer;
import javax.security.auth.Subject;
import com.tangosol.net.Service;
public class PasswordIdentityTransformer
implements IdentityTransformer
{
public Object transformIdentity(Subject subject, Service service)
throws SecurityException
{
return System.getProperty("mySecretPassword");
}
}
既存のクライアント認証実装に対する可能なソリューションの1つは、Principal名がパスワードとして設定されている新しいPrincipalをSubjectに追加することです。JAAS認証時に、既存のJAASログイン・モジュールを変更するか、またはパスワードPrincipalを追加する必要なログイン・モジュールを追加することによって、パスワードPrincipalをSubjectに追加します。JAAS APIでは複数のログイン・モジュールが許可されており、それぞれがSubjectを変更します。同様に、.NETでもPrincipalにパスワードIDを追加します。クラスタ側のアサータは、PrincipalとパスワードPrincipalの両方を検証します。「カスタム・アイデンティティ・アサータの作成」を参照してください。
カスタムIDトランスフォーマの実装を有効にするには、クライアント側のtangosol-coherence-override.xmlファイルを編集し、<security-configノード内に<identity-transformer要素を追加します。この要素には、実装クラスの完全な名前を含める必要があります。次に例を示します。
<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/
coherence-operational-config coherence-operational-config.xsd">
<security-config>
<identity-transformer>
<class-name>com.my.PasswordIdentityTransformer</class-name>
</identity-transformer>
</security-config>
</coherence>
IDトークンがSubjectまたはPrincipalであることをアサートするデフォルト・アイデンティティ・アサータの実装(DefaultIdentityAsserter)が提供されています。デフォルトの実装を使用しない場合は、独自のカスタム・アサータの実装を作成できます。
JavaおよびC++の場合、IdentityAsserterインタフェースを実装することで、アイデンティティ・アサータを作成します。C#クライアントではIIdentityAsserterインタフェースを実装します。
例5-2は、セキュリティ・トークンをチェックして有効なパスワードが指定されたことを確認するJavaの実装です。この場合、パスワードは、キャッシュ・サーバーのシステム・プロパティに対してチェックされます。このアサータの実装は、例5-1のIDトランスフォーマのサンプルに固有のものです。
例5-2アイデンティティ・アサータの実装のサンプル
import com.tangosol.net.security.IdentityAsserter;
import javax.security.auth.Subject;
import com.tangosol.net.Service;
public class PasswordIdentityAsserter
implements IdentityAsserter
{
public Subject assertIdentity(Object oToken, Service service)
throws SecurityException
{
if (oToken instanceof String)
{
if (((String) oToken).equals(System.getProperty("mySecretPassword")))
{
return null;
}
}
throw new SecurityException("Access denied");
}
}
アイデンティティ・アサータを作成する際は、多数のバリエーションが考えられます。たとえば、プリンシパルのリストに基づいて接続を拒否したり、ロール・プリンシパルをチェックしたり、署名されたプリンシパル名を検証したりするアサータを作成できます。アサータは、正しいIDであることが確認できない接続試行をすべてブロックします。
カスタム・アイデンティティ・サータの実装を有効にするには、クライアント側のtangosol-coherence-override.xmlファイルを編集し、<security-configノード内に<identity-asserter要素を追加します。この要素には、実装クラスの完全な名前を含める必要があります。次に例を示します。
<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/
coherence-operational-config coherence-operational-config.xsd">
<security-config>
<identity-asserter>
<class-name>com.my.PasswordIdentityAsserter</class-name>
</identity-asserter>
</security-config>
</coherence>
セキュリティ・オブジェクトは、Extendクライアントと拡張プロキシの間で渡されるときに、Portable Object Format (POF)を使用して自動的にシリアライズまたはデシリアライズされます。POFで事前定義されているセキュリティ・オブジェクトは、構成やプログラムの変更を必要としません。ただし、POFで事前定義されていないセキュリティ・オブジェクトでは(たとえば、アプリケーションがKerberos認証を使用する場合など)、エラーが発生します。カスタム・セキュリティ・タイプに関しては、カスタム・タイプを変換するか、POFでタイプを定義する必要があります。サポートされていないタイプを使用するには、2つの方法があります。
タイプの変換
カスタムIDトランスフォーマの実装は、カスタム・セキュリティ・オブジェクト・タイプを、文字配列や文字列などPOF用に事前定義されているタイプに変換してから、オブジェクト・トークンとして返します。プロキシ・サーバーで、カスタム・アイデンティティ・サータの実装は、オブジェクトを(検証後に)Subjectに変換します。
たとえば、あるサブジェクトに、シリアライズされない資格証明が含まれているとします。IDトランスフォーマの実装は、この資格証明を抽出し、文字配列に変換して、その配列をトークンとして返します。プロキシ・サーバーで、アイデンティティ・アサータは、文字配列を適切な資格証明タイプに変換し、それを検証してから、返すSubjectを作成します。
POFでのカスタム・タイプの定義
クライアントとプロキシの両方のPOF構成ファイルでカスタム・セキュリティ・タイプを定義できます。JavaでのPOFの使用方法に関する詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。C++およびC#でのPOFの使用方法に関する詳細は、それぞれ、『Oracle Coherenceリモート・クライアントの開発』の統合オブジェクトの構築(C++)に関する項および統合オブジェクトの構築(.NET)に関する項を参照してください。
カスタムIDトークンを使用するソリューションでは、Extendクライアントから送信可能なトークンと、拡張プロキシで受信可能なトークンを常に考慮する必要があります。このことは、ローリング・アップグレードの際や、新たなカスタムIDトークンのソリューションを実装する際に、特に重要です。
Oracle Coherenceのアップグレード
アップグレード・プロセスの間に、相互運用性の問題が発生する場合があります。この場合、複数の異なるバージョンのクライアントが、複数の異なるバージョンのプロキシ・サーバーと相互運用されている可能性があります。カスタム・アイデンティティ・サータが拡張クライアントから送信されたIDトークンを処理できることを確認してください。逆に言えば、カスタムIDトランスフォーマが、拡張プロキシが処理できるトークンを送信していることを確認してください。
カスタムIDトークンのロールアウト
カスタムIDトークンのソリューションのロールアウト時に、Extendクライアントと拡張プロキシの間で相互運用性の問題が発生する場合があります。この場合、カスタム・アイデンティティ・サータを使用するために拡張プロキシが移行されるため、一部のプロキシは、ロールアウト操作が完了するまでデフォルトのアサータを引き続き使用します。同様に、カスタムIDトランスフォーマを使用するためにExtendクライアントが移行されるため、クライアントは、ロールアウト操作が完了するまでデフォルトのトランスフォーマを引き続き使用します。いずれの場合も、Extendクライアントと拡張プロキシでは、ロールアウト操作が完了するまでの間、デフォルトのトークン・タイプを処理できる必要があります。
このようなシナリオに対する1つの戦略は、クライアントの更新時に、デフォルトのトークン・タイプを一時的に受け入れるカスタム・アイデンティティ・サータを用意することです。アイデンティティ・アサータは、外部ソースをチェックして、これらのトークンが受け入れられるかどうかを示すポリシーの有無を確認します。すべてのクライアントがカスタム・トークンを使用するように更新されたら、カスタム・トークンを受け入れるようにポリシーを変更します。
サブジェクトのスコープを設定すると、クライアントに返されるリモート・キャッシュおよびリモート起動のサービス参照を、現在のセキュリティ・コンテキストのIDと関連付けできます。デフォルトでは、サブジェクトのスコープ設定は無効です。これは、リモート・キャッシュおよびリモート起動サービス参照がグローバルに共有されることを意味します。
サブジェクトのスコープ設定が有効な場合、クライアントは、プラットフォーム固有の認証APIを使用してセキュリティ・コンテキストを確立します。クライアントによってNamedCacheインスタンスおよびInvocationServiceインスタンスが作成されるたびに、SubjectまたはPrincipalが現在のセキュリティ・コンテキストから取得されます。その後、すべてのリクエストが、確立されたSubjectまたはPrincipalに対して実行されます。
注意:
POFで事前定義されているもの以外のセキュリティ・オブジェクト・タイプの使用方法の詳細は、「カスタム・セキュリティ・タイプの使用方法」を参照してください。
たとえば、trader IDを持つユーザーがCacheFactory.getCache("trade-cache")をコールし、manager IDを持つユーザーがCacheFactory.getCache("trade-cache")をコールした場合、各ユーザーは別々のリモート・キャッシュ参照オブジェクトを取得します。IDはそのリモート・キャッシュ参照に関連付けられるため、認可するかどうかは、コール元のIDに基づいて決定できます。認可の実装の詳細は、次の「Extendクライアントの認可の実装」を参照してください。
JavaおよびC++クライアントの場合、<security-configノード内の<subject-scope要素を使用して、クライアント側のtangosol-coherence-override.xmlファイルでサブジェクトのスコープを有効にします。次に例を示します。
<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/
coherence-operational-config coherence-operational-config.xsd">
<security-config>
<subject-scope>true</subject-scope>
</security-config>
</coherence>
.NETクライアントの場合、<security-configノード内の<principal-scope要素を使用して、クライアント側のtangosol-coherence-override.xmlファイルでサブジェクトのスコープを有効にします。次に例を示します。
<?xml version='1.0'?>
<coherence xmlns="http://schemas.tangosol.com/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.tangosol.com/cache
assembly://Coherence/Tangosol.Config/coherence.xsd">
<security-config>
<principal-scope>true</principal-scope>
</security-config>
</coherence>
Oracle Coherence*Extendの認可により、Extendクライアントのアクセス権に基づいて、クラスタ上で実行できる操作が制御されます。認可ロジックは実装固有であり、クラスタ・プロキシ上で有効です。
この項には次のトピックが含まれます:
この項のコード・サンプルは、Javaの認可例に基づいています。これは、製品の一部として提供される例に含まれています。この例は、クライアント・リクエストから取得したプリンシパルとロールベースのポリシーを使用して、リクエストされたサービスへの操作を許可するかどうかを決定する、基本的な認可の実装を示しています。完全な実装を確認するには、例をダウンロードしてください。
インターセプタ・クラスにより、クライアント認可の実装が可能になります。拡張プロキシがインターセプタ・クラスをコールしてから、クライアントがプロキシ設定されたリソース(キャッシュ、キャッシュ・サービスまたは起動サービス)にアクセスします。インターセプタ・クラスは実装固有のものであり、必要な認可ロジックを指定してからプロキシ設定されたリソースにリクエストを渡す必要があります。
図5-2は、Extendクライアントの認可の概念を示しています。
プロキシ設定されたキャッシュ・サービス用とプロキシ設定された起動サービス用の両方のインターセプタ・クラスを作成するには、CacheServiceインタフェースとInvocationServiceインタフェースをそれぞれ実装します。または、より一般的には、com.tangosol.net.WrapperCacheService (およびcom.tangosol.net.cache.WrapperNamedCache)とcom.tangosol.net.WrapperInvocationServiceという一連のラッパー・クラスを拡張します。ラッパー・クラスは、それぞれのインタフェースに委任します。これにより、ラップされたインタフェース・メソッドにアクセス制御を適用するインターセプタ・クラスを便利な方法で作成できます。
例5-3は、Oracle Coherenceの例からの抜粋であり、WrapperInvocationServiceを拡張することによってプロキシ設定された起動サービスの認可インターセプタ・クラスを作成する方法を示しています。InvocationServiceメソッドはすべてプロキシ上でラップされ、Extendクライアントから渡されたSubjectに基づいてアクセス制御が適用されます。この実装では、指定したロール名を持つPrincipalのみが、InvocationServiceメソッドにアクセスできます。
例5-3 認可用WrapperCacheServiceクラスの拡張
public class EntitledCacheService
extends WrapperCacheService
{
public EntitledCacheService(CacheService service)
{
super(service);
}
public NamedCache ensureCache(String sName, ClassLoader loader)
{
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_READER);
return new EntitledNamedCache(super.ensureCache(sName, loader));
}
public void releaseCache(NamedCache map)
{
if (map instanceof EntitledNamedCache)
{
EntitledNamedCache cache = (EntitledNamedCache) map;
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_READER);
map = cache.getNamedCache();
}
super.releaseCache(map);
}
public void destroyCache(NamedCache map)
{
if (map instanceof EntitledNamedCache)
{
EntitledNamedCache cache = (EntitledNamedCache) map;
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_ADMIN);
map = cache.getNamedCache();
}
super.destroyCache(map);
}
}
EntitledCacheServiceクラスには、名前付きキャッシュ実装が必要です。WrapperNamedCacheクラスが拡張され、NamedCacheインスタンスの各メソッドをラップします。これにより、様々なキャッシュ操作にアクセス制御を適用できます。
注意:
WrapperNamedCacheクラスで提供される機能の多くは、StorageAccessAuthorizerインタフェースにも含まれ、改良された簡便な方法でクラスタ操作を認可できます。詳細は、サーバー側操作へのアクセスの許可を参照してください。
例5-4は、Oracle Coherenceの例から抜粋されたコードです。この例は、NamedCacheメソッドをオーバーライドし、メソッドの実行を許可する前にアクセス・チェックを適用する方法を示しています。クラスの詳細は、例を参照してください。
例5-4 認可用WrapperNamedCacheクラスの拡張
public class EntitledNamedCache
extends WrapperNamedCache
{
public EntitledNamedCache(NamedCache cache)
{
super(cache, cache.getCacheName());
}
public Object put(Object oKey, Object oValue, long cMillis)
{
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_WRITER); return super.put(oKey, oValue, cMillis);
}
public Object get(Object oKey)
{
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_READER);
return super.get(oKey);
}
public void destroy()
{
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_ADMIN);
super.destroy();
}
...
例5-5は、Oracle Coherenceの例からの抜粋です。WrapperCacheServiceクラスを拡張することによってプロキシ設定されたキャッシュ・サービスの認可インターセプタ・クラスを作成する方法を示しています。CacheServiceメソッドはすべてプロキシ上でラップされ、Extendクライアントから渡されたSubjectに基づいてアクセス制御が適用されます。この実装では、指定したロールを持つPrincipalのみが、CacheServiceメソッドにアクセスできます。
例5-5 認可用WrapperInvocationServiceクラスの拡張
public class EntitledInvocationService
extends WrapperInvocationService
{
public EntitledInvocationService(InvocationService service)
{
super(service);
}
public void execute(Invocable task, Set setMembers, InvocationObserver
observer)
{
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_WRITER)
super.execute(task, setMembers, observer);
}
public Map query(Invocable task, Set setMembers)
{
SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_WRITER)
return super.query(task, setMembers);
}
}
クライアントでリモート起動サービスを使用しようとすると、プロキシは、プロキシ設定されたInvocationServiceインスタンスではなく、EntitledInvocationServiceクラスでquery()メソッドをコールします。EntitledInvocationServiceクラスによって、コールを許可するか拒否するかが決定されます。コールが許可されると、プロキシは、プロキシ設定されたInvocationServiceインスタンスでquery()メソッドをコールします。
プロキシ設定されたキャッシュ・サービスおよびプロキシ設定された起動サービスのインターセプタ・クラスを有効にするには、プロキシ・スキーム定義を編集し、<cache-service-proxy要素および<invocation-service-proxy要素をそれぞれ追加します。<class-name要素を使用して、インターセプタ・クラスの完全修飾名を入力します。<init-params要素を使用して、初期化パラメータを指定します。これらの要素の使用方法に関する詳細は、『Oracle Coherenceでのアプリケーションの開発』のcache-service-proxyに関する項およびinvocation-service-proxyに関する項を参照してください。
次の例は、プロキシ設定されたキャッシュ・サービスとプロキシ設定された起動サービスの両方のインターセプタ・クラスを有効にする方法を示しています。この例では、例5-3と例5-5のインターセプタ・クラスを使用しています。
<proxy-scheme>
...
<proxy-config>
<cache-service-proxy>
<class-name>
com.tangosol.examples.security.EntitledCacheService
</class-name>
<init-params>
<init-param>
<param-type>com.tangosol.net.CacheService</param-type>
<param-value>{service}</param-value>
</init-param>
</init-params>
</cache-service-proxy>
<invocation-service-proxy>
<class-name>
com.tangosol.examples.security.EntitledInvocationService
</class-name>
<init-params>
<init-param>
<param-type>com.tangosol.net.InvocationService</param-type>
<param-value>{service}</param-value>
</init-param>
</init-params>
</invocation-service-proxy>
</proxy-config>