18 資格証明ストア・フレームワークを使用した開発
この章の内容は次のとおりです。
資格証明ストア・フレームワークAPIについて
Credential Store Framework APIは、資格証明ストアに格納されている資格証明へのアクセス、取得および管理に使用します。このAPIを使用すると、次の操作が可能です。
-
資格証明マップまたはマップとキーのどちらが資格証明ストアに格納されているかのチェック。
-
マップまたはマップとキーに関連付けられている資格証明の取得。
-
マップまたはマップとキーへの資格証明の割当て。
-
マップまたはマップとキーの資格証明の削除。
資格証明ストアに対する操作は、資格証明フレームワークで使用されるファイングレイン制御を実装するクラスであるCredentialAccessPermission
クラスによって保護されます。
関連項目:
資格証明ストア・フレームワークAPIの使用のガイドライン
資格証明ストア・フレームワークAPIを使用するアプリケーションを開発する際には、必ず次のようにします。
-
アプリケーションによる資格証明へのアクセスを可能にするセキュリティ・ポリシーをプロビジョニングします。
-
特に、複数のアプリケーションが同じ資格証明ストアを使用する環境では、使用する適切なマップとキー名を決定します。
-
必ず
jps-config.xml
ファイルで資格証明ストア・インスタンスを定義し、適切に構成します。
マップとキー名について
各アプリケーションには、資格証明ストア内で一意のマップ名が関連付けられている必要があります。これにより、ストア内のマップおよびキーの様々な名前の間で競合が発生せず、マップ名によってアプリケーションが一義的に特定されることが保証されます。アプリケーションは、特定のマップの中に、それぞれが同様に一意の名前を持っている複数のキーを格納できるため、マップ名/キー名のペアによって資格証明ストア内でただ1つのキーが特定されます。
アクセス・パーミッションのプロビジョニング
資格証明フレームワークにより、マップ、マップ内のすべてのキーおよびマップ内の特定のキーへのアクセスが保護されます。資格証明ストア・フレームワークAPIを使用するには、アプリケーションでAPIを使用できるようにするアクセス・パーミッションを指定する必要があります。さらに、このAPIをコールするコードにもコードソース・パーミッションが必要ですが、これらのパーミッションは通常、特定のJarのみに制限されます。すべてのマップおよびキーに対してアクセス・パーミッションを定義することはお薦めしません。
次の各項では、アクセス・パーミッションの定義について説明します。
1つのキーにアクセスするためのパーミッションの例
次の例では、マップ内の特定のキーに対してアクションを実行するソース・コードに対してのアクセス・パーミッションを示しています。
<jazn-policy> <grant> <grantee> <principals>...</principals> <codesource> <url>file:${oracle.deployed.app.dir}/<MyApp>${oracle.deployed.app.ext}</url> </codesource> </grantee> <permissions> <permission> <class>oracle.security.jps.service.credstore. CredentialAccessPermission</class> <name>context=SYSTEM,mapName=myMap,keyName=myKey</name> <actions>*</actions> </permission> </permissions> </grant> </jazn-policy>
マップにアクセスするためのパーミッションの例
次の例では、マップとそのマップ内のすべてのキーに対して特定のアクションを実行するソース・コードに対してのアクセス・パーミッションを示しています。
<jazn-policy> <grant> <grantee> <principals>...</principals> <codesource> <url>file:${oracle.deployed.app.dir}/<MyApp>${oracle.deployed.app.ext}</url> </codesource> </grantee> <permissions> <permission> <class>oracle.security.jps.service.credstore. CredentialAccessPermission</class> <name>context=SYSTEM,mapName=myMap,keyName=*</name> <actions>read,write,update,delete</actions> </permission> </permissions> </grant> </jazn-policy>
資格証明ストア・フレームワークAPIの使用
次の各項では、Java SEアプリケーションおよびJava EEアプリケーションでこのフレームワークを使用する方法について説明します。
資格証明ストア・フレームワークAPIの例
次の各例では、資格証明ストア操作で必要なアクセス・パーミッションを使用する方法を示します。
資格証明ストア・フレームワーク操作の例
次の例では、他の例で使用されている資格証明ストア・フレームワークAPI操作を示します。
package demo.util; import java.security.AccessController; import java.security.PrivilegedAction; import oracle.security.jps.JpsException; import oracle.security.jps.service.credstore.Credential; import oracle.security.jps.service.credstore.CredentialAlreadyExistsException; import oracle.security.jps.service.credstore.CredentialFactory; import oracle.security.jps.service.credstore.CredentialStore; import oracle.security.jps.service.credstore.PasswordCredential; public class CsfUtil { final CredentialStore store; public CsfUtil(CredentialStore store) { super(); this.store = store; } private void doOperation() { try { PasswordCredential pc = null; try { // this call requires read privilege pc = (PasswordCredential)store.getCredential("pc_map", "pc_key"); if (pc == null) { // key not found, create one pc = CredentialFactory.newPasswordCredential("jdoe", "password".toCharArray()); // this call requires write privilege store.setCredential("pc_map", "pc_key", pc); System.out.print("Created "); } else { if (pc instanceof PasswordCredential){ System.out.print("Found "); } else { System.out.println("Unexpected credential type found"); } System.out.println("password credential: Name=" + pc.getName() + ",Password=" + new String(pc.getPassword())); } catch (CredentialAlreadyExistsException e) { // ignore because credential already exists. System.out.println("Credential already exists for <pc_map, pc_key>: " + pc.getName() + ":" + new String(pc.getPassword())); } try { // permission corresponding to // "context=SYSTEM,mapName=gc_map,keyName=gc_key" byte[] secret = new byte[] { 0x7e, 0x7f, 0x3d, 0x4f, 0x10, 0x20, 0x30 }; Credential gc = CredentialFactory.newGenericCredential(secret); store.setCredential("gc_map", "gc_key", gc); System.out.println("Created generic credential"); } catch (CredentialAlreadyExistsException e) { // ignore because credential already exists. System.out.println("Generic credential already exists for <gc_map,gc_key>"); } try { //no permission for pc_map2 & pc_key2 to perform //operation on store Credential pc2 = CredentialFactory.newPasswordCredential("pc_jode2", "pc_password".toCharArray()); store.setCredential("pc_map2", "pc_key2", pc2); } catch (Exception expected) { //CredentialAccess Exception expected here. Not enough permission System.out.println("This is expected :" + expected.getLocalizedMessage()); } } catch (JpsException e) { e.printStackTrace(); } } /* * This method performs a non-privileged operation. all code * in the call stack must have CredentialAccessPermission * OR * the caller must have the CredentialAccessPermission only and * invoke this operation in doPrivileged block */ public void doCredOperation() { doOperation(); } /* * because the following performs a privileged operation, only * jar containing this class needs CredentialAccessPermission */ public void doPrivilegedCredOperation() { AccessController.doPrivileged(new PrivilegedAction<String>() { public String run() { doOperation(); return "done"; } }; } }
ファイル資格証明を使用するJava SEアプリケーションの例
この項の例では、$DOMAIN_HOME/config/fmwconfig/system-jazn-data.xml
ファイルで表されるファイル資格証明ストアを使用するJava SEアプリケーションを示します。
この例では、システム・プロパティprojectsrc.home
はJava SEアプリケーションを格納しているディレクトリを指し、clientApp.jar
はdist
ディレクトリに存在するアプリケーションJARファイルです。
次の権限付与は、アクセス・パーミッションを示しています。
<grant> <grantee> <codesource> <url>file:${projectsrc.home}/dist/clientApp.jar</url> </codesource> </grantee> <permissions> <permission> <class>oracle.security.jps.service.credstore.CredentialAccessPermission </class> <name>context=SYSTEM,mapName=pc_map,keyName=*</name> <actions>read,write</actions> </permission> <permission> <class>oracle.security.jps.service.credstore.CredentialAccessPermission </class> <name>context=SYSTEM,mapName=gc_map,keyName=gc_key</name> <actions>write</actions> </permission> </permissions> </grant>
mapName=pc_map2,keyName=pc_key2
にはパーミッションが付与されないため、そのマップおよびキーのsetCredential
へのコールは失敗します。
アプリケーションで使用される資格証明ストアは、jps-config-jse.xml
に指定します。
<serviceInstances> <serviceInstance name="credstore_file_instance" provider="credstore_file_provider"> <property name="location" value="store" /> </serviceInstance> </serviceInstances>
次に、プログラムをコールするJava SEコードを示します。
package demo; import java.io.ByteArrayInputStream; import java.security.AccessController; import java.security.PrivilegedAction; import oracle.security.jps.JpsContext; import oracle.security.jps.JpsStartup; import oracle.security.jps.JpsContextFactory; import oracle.security.jps.JpsException; import oracle.security.jps.jaas.JavaPolicy; import oracle.security.jps.service.credstore.Credential; import oracle.security.jps.service.credstore.CredentialAlreadyExistsException; import oracle.security.jps.service.credstore.CredentialFactory; import oracle.security.jps.service.credstore.CredentialStore; import oracle.security.jps.service.credstore.PasswordCredential; import oracle.security.jps.service.policystore.PolicyStore; import oracle.security.jps.service.policystore.PolicyStoreException; import demo.util.CsfUtil; public class CsfApp { public CsfApp() { super(); } public static void main(String[] a) { // perform operation as privileged code JpsContextFactory ctxFactory; try { new JpsStartup().start(); ctxFactory = JpsContextFactory.getContextFactory(); JpsContext ctx = ctxFactory.getContext(); CredentialStore store = ctx.getServiceInstance(CredentialStore.class); CsfUtil csf = new CsfUtil(store); // next call is in a doPrivileged block and should succeed csf.doPrivilegedCredOperation(); // because next call is not in a doPrivileged block, // it fails if CredentialAccessPermission is not granted to this class csf.doCredOperation(); } catch (JpsException e) { e.printStackTrace(); } } }
ファイル資格証明を使用するJava EEアプリケーションの例
この例では、資格証明ストア・フレームワークAPIをコールするファイル資格証明を使用するJava EEアプリケーションを示します。jazn-data.xml
ファイルでは、適切なアクセス・パーミッション、コードソース・パーミッション、マップとキーの様々な組合せで必要なパーミッションを定義します。
次の権限付与は、アクセス・パーミッションを示しています。
<grant> <grantee> <codesource> <url>file:${oracle.deployed.app.dir}/<MyApp>${oracle.deployed.app.ext}</url> </codesource> </grantee> <permissions> <permission> <class>oracle.security.jps.service.credstore.CredentialAccessPermission </class> <name>context=SYSTEM,mapName=pc_map,keyName=*</name> <actions>read,write</actions> </permission> <permission> <class>oracle.security.jps.service.credstore.CredentialAccessPermission </class> <name>context=SYSTEM,mapName=gc_map,keyName=gc_key</name> <actions>write</actions> </permission> </permissions> </grant>
アプリケーションで使用される資格証明ストアは、jps-config.xml
に指定します。
<serviceProviders> <serviceProvider type="CREDENTIAL_STORE" name="credstoressp" class="oracle.security.jps.internal.credstore.ssp.SspCredentialStoreProvider"> <description>SecretStore-based CSF provider</description> </serviceProvider> </serviceProviders> <serviceInstances> <serviceInstance name="credstore" provider="credstoressp"> <property name="location" value="./" /> </serviceInstance> </serviceInstances> <jpsContexts default="default"> <jpsContext name="default"> ... <serviceInstanceRef ref="credstore"/> ... </jpsContext> </jpsContexts>
location
プロパティでは、cwallet.sso
ファイルの場所を指定します。
次に、このような構成を使用する例を示します。
package demo; import demo.util.CsfUtil; import java.io.IOException; import java.io.PrintWriter; import java.net.URL; import java.util.Date; import javax.servlet.*; import javax.servlet.http.*; import oracle.security.jps.JpsException; import oracle.security.jps.service.JpsServiceLocator; import oracle.security.jps.service.credstore.CredentialStore; public class CsfDemoServlet extends HttpServlet { private static final String CONTENT_TYPE = "text/html; charset=windows-1252"; public void init(ServletConfig config) throws ServletException { super.init(config); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); //ServletOutputStream out = response.getOutputStream(); try { response.setContentType("text/html"); out.println("<html><body bgcolor=\"#FFFFFF\">"); out.println("<b>Current Time: </b>" + new Date().toString() + "<br><br>"); //get hold of app-level CSF service store //Outside app context, it returns the domain CSF store final CredentialStore store = JpsServiceLocator.getServiceLocator().lookup(CredentialStore.class); CsfUtil csf = new CsfUtil(store); csf.doPrivilegedCredOperation(); out.println("Credential operations completed using privileged code."); } catch (JpsException e) { e.printStackTrace(out); } } }
作成操作は、権限が付与されたブロックの中に実装されます。Java SE環境では、次の2つのコールは同等です。
CredentialStore store = JpsServiceLocator.getServiceLocator().lookup(CredentialStore.class); CredentialStore store = JpsContextFactory.getContextFactory().getContext().getServiceInstance(CredentialStore.class);
LDAPストアを使用するJava EEアプリケーションの例
次の例では、ファイル資格証明を使用するJava EEアプリケーションの例で使用されている同じアプリケーションを使用していますが、資格証明ストアはここではファイルではなくLDAPです。
次に、LDAPストア構成の例を示します。
<serviceProviders> <serviceProvider name="ldap.credentialstore.provider" class="oracle.security.jps.internal.credstore.ldap.LdapCredentialStoreProvider"> <description>Prototype LDAP CSF provider</description> </serviceProvider> </serviceProviders> <serviceInstances> <serviceInstance provider="ldap.credentialstore.provider" name="credstore.ldap"> <property value="bootstrap" name="bootstrap.security.principal.key"/> <property value="cn=wls-jrfServer" name="oracle.security.jps.farm.name"/> <property value="cn=jpsTestNode" name="oracle.security.jps.ldap.root.name"/> <property value="ldap://mynode.us.mycorp.com:1234" name="ldap.url"/> </serviceInstance> </serviceInstances> <jpsContexts default="appdefault"> <jpsContext name="appdefault"> <serviceInstanceRef ref="credstore.ldap"/> </jpsContext> </jpsContexts>
DBストアを使用するJava EEアプリケーションの例
次の例では、ファイル資格証明を使用するJava EEアプリケーションの例で使用されている同じアプリケーションを使用していますが、資格証明ストアはここではファイルではなくデータベースです。
次に、DBストア構成の例を示します。
<serviceProviders> <serviceProvider type="CREDENTIAL_STORE" name="db.credentialstore.provider" class="oracle.security.jps.internal.credstore.rdbms.DbmsCredentialStoreProvider"/> <description>DB CSF provider</description> </serviceProvider> </serviceProviders> <serviceInstances> <serviceInstance provider="db.credentialstore.provider" name="credstore.db"> <property value="bootstrap" name="bootstrap.security.principal.key"/> <property value="cn=wls-jrfServer" name="oracle.security.jps.farm.name"/> <property value="cn=jpsTestNode" name="oracle.security.jps.ldap.root.name"/> <property name="jdbc.url" value="jdbc:oracle:thin:@localhost:5521:ldapoid"/> <property name="jdbc.driver" value="oracle.jdbc.OracleDriver"/> <property name="datasource.jndi.name" value="jdbc/OpssDS"/> </serviceInstance> </serviceInstances> <jpsContexts default="appdefault"> <jpsContext name="appdefault"> <serviceInstanceRef ref="credstore.db"/> </jpsContext> </jpsContexts>