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