Coherence*Extendには、Extendクライアントと拡張プロキシ間の通信を保護するために使用する一連の追加機能が含まれています。Coherence*Extendクライアントの作成の詳細は、『Oracle Coherenceクライアント・ガイド』を参照してください。
この章には次の項が含まれます:
IDトークンを使用して、クラスタにアクセスしないようにExtendクライアントを制限できます。このトークンは、接続が試行されるたびに、Extendクライアントと拡張プロキシの間で送信されます。有効なIDトークンを渡すExtendクライアントのみに、クラスタへのアクセスが許可されます。
Extendクライアントでは、IDトランスフォーマによってIDトークンが作成され、接続リクエストの一部として送信されます。クラスタ側では、IDアサータを使用してIDトークンを検証してから、接続を受け入れます。Coherence*Extendに含まれるデフォルトのIDトランスフォーマ(DefaultIdentityTransformer)およびIDアサータ(DefaultIdentityAsserter)では、サブジェクト(Java)またはプリンシパル(.NET)をIDトークンに使用します。カスタムのIDトランスフォーマおよびIDアサータを実装し、Coherenceオペレーション・オーバーライド・ファイルで有効にすることにより、デフォルト動作をオーバーライドできます。
|
注意:
|
この項には、次のトピックが含まれます:
IDトランスフォーマは、サブジェクトまたはプリンシパルを拡張プロキシに引渡し可能なIDトークンに変換する、クライアント側のコンポーネントです。IDトークンは、ID検証に便利なオブジェクトであれば、どんなタイプでもかまいません。既知のセキュリティ・タイプである必要はありません。さらに、IDトークンは、複数のプロキシ・サーバーに接続するクライアントをサポートし、独自の方法で各プロキシ・サーバーに認証を与えるリモート・サービスに対して固有にできます。実行時に、トークンはシリアライズされ、拡張接続リクエストの一部として送信されます。
|
注意: Coherenceでシリアライズ可能なタイプのIDトークンは自動的にシリアライズされます。.NETクライアントおよびC++クライアントの場合は、POFタイプを使用する必要があります。POFで事前定義されているもの以外のセキュリティ・オブジェクト・タイプの使用方法の詳細は、「カスタム・セキュリティ・タイプの使用方法」を参照してください。 |
JavaおよびC++の場合、IDトランスフォーマではIdentityTransformerインタフェースを実装する必要があります。C#クライアントではIIdentityTransformerインタフェースを実装します。
例4-1は、クライアントからプロキシにアクセスするためのパスワード入力を要求することによって、クライアント・アクセスを制限するJavaの実装です。IdentityTransformerは、クライアントのシステム・プロパティからパスワードを取得して、それをIDトークンとして返します。
例4-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");
}
}
クライアント認証が完了している場合は、プリンシパル名をパスワードとして、新しいプリンシパルをサブジェクトに追加できます。Principalというパスワードをサブジェクトに追加するには、JAAS認証時に、既存のJAASログイン・モジュールを変更するか、またはPrincipalというパスワードを追加する必要なログイン・モジュールを追加します。JAASには、それぞれサブジェクトを変更できる複数のログイン・モジュールを含めることができます。同様に、.NETでもパスワードIDをプリンシパルに追加できます。その後、クラスタ側のアサータで、通常のプリンシパルを検証し、さらにPrincipalというパスワードを検証します。「カスタムIDアサータの作成」を参照してください。
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アサータは、拡張プロキシ・サービスをホストしているキャッシュ・サーバー上に存在する、クラスタ側のコンポーネントです。アサータでは、Extendクライアント上でIDトランスフォーマによって作成されたIDトークンを検証します。アサータは、各プロキシ・サービス固有のIDトークンを検証して、複数のトークン検証の方法をサポートできます。
Extendクライアントで接続が開始されると、トークンが渡されます。検証が失敗すると、接続が拒否され、セキュリティ例外がスローされます。トランスフォーマとアサータは、既存の接続内で新しいチャネルが作成されたときにも起動します。JavaおよびC++の場合、IDアサータではIdentityAsserterインタフェースを実装する必要があります。C#クライアントではIIdentityAsserterインタフェースを実装します。
例4-2は、セキュリティ・トークンをチェックして有効なパスワードが指定されたことを確認するJavaの実装です。この場合、パスワードは、キャッシュ・サーバーのシステム・プロパティに対してチェックされます。このアサータの実装は、例4-1のIDトランスフォーマのサンプルで使用されています。
例4-2 IDアサータの実装のサンプル
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アサータを作成する際は、多数のバリエーションが考えられます。たとえば、アサータでは、プリンシパルのリストに基づいて接続を拒否する、プリンシパルのロールをチェックする、署名付きのプリンシパル名を検証する、などの処理が可能です。アサータは、正しいIDであることを証明しない接続の試行をすべてブロックできます。
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でタイプを定義するかを、アプリケーションで選択できます。
タイプを変換する場合
この方法では、カスタムIDトランスフォーマで、カスタム・セキュリティ・オブジェクト・タイプを、文字配列や文字列などPOF用に事前定義されているタイプに変換してから、オブジェクト・トークンとして返します。プロキシ・サーバーでは、カスタムIDアサータによって、検証後にサブジェクトに再度変換されます。
たとえば、あるサブジェクトに、シリアライズされない資格証明が含まれているとします。IDトランスフォーマでは、この資格証明を抽出し、文字配列に変換して、その配列をトークンとして返します。プロキシ・サーバーでは、IDアサータによって文字配列を適切な資格証明タイプに変換し、検証してから、サブジェクトを構成して返します。
POFでカスタム・タイプを定義する場合
この方法では、POF構成ファイルでカスタム・セキュリティ・タイプを定義します。タイプは、クライアントのPOF構成ファイルとプロキシ・サーバー上のPOF構成ファイルの両方で定義する必要があります。
Javaを使用したPOFの使用の詳細は、『Oracle Coherence開発者ガイド』を参照してください。C++を使用したPOFの使用の詳細は、『Oracle Coherenceクライアント・ガイド』を参照してください。C#を使用したPOFの詳細は、『Oracle Coherenceクライアント・ガイド』を参照してください。
カスタムIDトークンを使用するソリューションでは、Extendクライアントから送信可能なトークンと、拡張プロキシで受信可能なトークンを常に考慮する必要があります。このことは、ローリング・アップグレードの際や、カスタムIDトークンのソリューションをロールアウトする際に、特に重要です。
Coherenceのアップグレード
Coherenceをアップグレードする際に、相互運用性の問題が発生する場合があります。この場合、複数の異なるバージョンのクライアントが、複数の異なるバージョンのプロキシ・サーバーと相互運用されている可能性があります。詳細は次のとおりです。
3.5 Extendクライアントが3.6拡張プロキシに接続する場合、拡張プロキシに実装されているカスタムIDアサータでは、3.5 Extendクライアントから送信されたIDトークンを処理できる必要があります。3.5 Extendクライアントでは、nullトークンまたはSubjectが送信されます。カスタムIDアサータには、これらのトークン・タイプと、3.6 Extendクライアントからのカスタム・トークンの両方を処理する準備が必要です。
逆に、3.6 Extendクライアントが3.5拡張プロキシに接続する場合、クライアントでは、3.5拡張プロキシで処理できないトークンを送信するカスタムIDトランスフォーマを使用しないでください。クライアントはnullトークンかSubjectのいずれかを送信する必要があります。
カスタムIDトークンのロールアウト
カスタムIDトークンのソリューションをロールアウトする際に、Extendクライアントと拡張プロキシの間で相互運用性の問題が発生する場合があります。この場合、カスタムIDアサータを使用するために拡張プロキシが移行されるため、ロールアウトが完了するまで、デフォルトのアサータを引き続き使用するプロキシがあります。同様に、カスタムIDトランスフォーマを使用するためにExtendクライアントが移行されるため、ロールアウトが完了するまで、デフォルトのトランスフォーマを引き続き使用するクライアントがあります。いずれの場合も、Extendクライアントと拡張プロキシでは、ロールアウトが完了するまでの間、nullトークンまたはSubjectを処理できる必要があります。
このようなシナリオに対する戦略として、クライアントの更新時に、nullトークンまたはSubjectトークンを一時的に受け入れるカスタムIDアサータを用意することが考えられます。IDアサータは、外部ソースをチェックして、これらのトークンが受け入れられるかどうかを示すポリシーの有無を確認できます。すべてのクライアントがカスタム・トークンを使用するように更新されたら、ポリシーを変更すれば、IDアサータでこれらのトークンが受け入れられなくなります。
サブジェクトのスコープを設定すると、クライアントに返されるリモート・キャッシュおよびリモート起動のサービス参照を、現在のセキュリティ・コンテキストのIDと関連付けできます。デフォルトでは、サブジェクトのスコープ設定は無効です。これは、リモート・キャッシュおよびリモート起動サービス参照がグローバルに共有されることを意味します。
サブジェクトのスコープ設定が有効な場合、クライアントは、プラットフォーム固有の認証APIを使用してセキュリティ・コンテキストを確立します。クライアントでNamedCacheインスタンスおよびInvocationServiceインスタンスが作成されるたびに、サブジェクトまたはプリンシパルが、現在のセキュリティ・コンテキストから取得されます。その後、すべてのリクエストが、確立されたサブジェクトまたはプリンシパルに対して実行されます。
たとえば、"trader"ユーザーがCacheFactory.getCache("trade-cache")をコールし、"manager"ユーザーが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'?>
<cache-config 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>
認可は、特定のユーザーがそのアクセス制御権限に基づいて実行可能なアクションを制御するために使用されます。Coherence*Extendでは、認可はインターセプタ・クラスを使用して実装されます。拡張プロキシがインターセプタ・クラスをコールしてから、クライアントがプロキシ設定されたリソース(キャッシュ、キャッシュ・サービスまたは起動サービス)にアクセスします。インターセプタ・クラスは実装に固有であり、必要な認可ロジックを指定してからプロキシ設定されたリソースにリクエストを渡す必要があります。
この項には、次のトピックが含まれます:
この項のコード・サンプルは、Javaの認可例に基づいています。これは、ドキュメント・ライブラリの一部であるCoherenceの例に含まれています。この例は、クライアント・リクエストから取得したプリンシパルとロールベースのポリシーを使用して、リクエストされたサービスへの操作を許可するかどうかを決定する、基本的な認可の実装を示しています。完全な実装を確認するには、例をダウンロードしてください。
CacheServiceインタフェースとInvocationServiceインタフェースを実装することにより、プロキシ設定されたキャッシュ・サービス用とプロキシ設定された起動サービス用の両方のインターセプタ・クラスをそれぞれ作成できます。ただし、一連のラッパー・クラスは、通常は認可を実装するときに拡張されます(com.tangosol.net.WrapperCacheService(com.tangosol.net.cache.WrapperNamedCacheを使用)およびcom.tangosol.net.WrapperInvocationService)。ラッパー・クラスは、それぞれのインタフェースに委任します。これにより、ラップされたインタフェース・メソッドにアクセス制御を適用するインターセプタ・クラスを便利な方法で作成できます。
例4-3は、Coherenceの例からの抜粋であり、WrapperCacheServiceを拡張することによってプロキシ設定されたキャッシュ・サービスの認可インターセプタ・クラスを作成する方法を示しています。CacheServiceメソッドはすべてプロキシ上でラップされ、Extendクライアントから渡されたサブジェクトに基づいてアクセス制御が適用されます。この実装では、指定したロールを持つプリンシパルのみが、ラップされたCacheServiceにアクセスできます。
例4-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);
}
}
このクラスには、名前付きキャッシュ実装が必要です。この例では、WrapperNamedCacheクラスが拡張され、NamedCacheインスタンスの各メソッドをラップします。これにより、様々なキャッシュ操作にアクセス制御を適用できます。例4-4は、Coherenceの例から抜粋したコードであり、NamedCacheメソッドをオーバーライドしてアクセス・チェックを適用してからメソッドの実行を許可する方法を示しています。クラスの詳細は、Coherenceの例を参照してください。
例4-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();
}
...
例4-5は、Coherenceの例からの抜粋であり、WrapperInvocationServiceを拡張することによってプロキシ設定された起動サービスの認可インターセプタ・クラスを作成する方法を示しています。InvocationServiceメソッドはすべてプロキシ上でラップされ、Extendクライアントから渡されたサブジェクトに基づいてアクセス制御が適用されます。この実装では、指定したロール名のプリンシパルのみが、ラップされたInvocationServiceにアクセスできます。
例4-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に関する項を参照してください。
次の例は、プロキシ設定されたキャッシュ・サービスとプロキシ設定された起動サービスの両方のインターセプタ・クラスを有効にする方法を示しています。この例では、例4-3と例4-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>