プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle Platform Security Servicesによるアプリケーションの保護
12c (12.2.1)
E72537-01
  目次へ移動
目次

前
 
次
 

18 資格証明ストア・フレームワークを使用した開発

この章では、アプリケーションでの資格証明ストア・フレームワークの使用方法と、資格証明ストア構成のガイドラインについて説明します。

この章の内容は次のとおりです。

18.1 資格証明ストア・フレームワークAPIについて

CFS APIは、資格証明ストアに格納されている資格証明へのアクセス、取得および管理に使用します。このAPIを使用すると、次の操作が可能です。

  • 資格証明マップまたはマップとキーのどちらが資格証明ストアに格納されているかのチェック。

  • マップまたはマップとキーに関連付けられている資格証明の取得。

  • マップまたはマップとキーへの資格証明の割当て。

  • マップまたはマップとキーの資格証明の削除。

資格証明ストアに対する操作は、資格証明フレームワークで使用されるファイングレイン制御を実装するクラスであるCredentialAccessPermissionクラスによって保護されます。

18.2 資格証明ストア・フレームワークAPIの使用のガイドライン

資格証明ストア・フレームワークAPIを使用するアプリケーションを開発する際には、必ず次のようにします。

  • アプリケーションによる資格証明へのアクセスを可能にするセキュリティ・ポリシーをプロビジョニングします。

  • 特に、複数のアプリケーションが同じ資格証明ストアを使用する環境では、使用する適切なマップとキー名を決定します。

  • 必ずjps-config.xmlファイルで資格証明ストア・インスタンスを定義し、適切に構成します。

18.3 マップとキー名について

各アプリケーションには、資格証明ストア内で一意のマップ名が関連付けられている必要があります。これにより、ストア内のマップおよびキーの様々な名前の間で競合が発生せず、マップ名によってアプリケーションが一義的に特定されることが保証されます。アプリケーションは、特定のマップの中に、それぞれが同様に一意の名前を持っている複数のキーを格納できるため、マップ名/キー名のペアによって資格証明ストア内でただ1つのキーが特定されます。

18.4 アクセス・パーミッションのプロビジョニング

資格証明フレームワークにより、マップ、マップ内のすべてのキーおよびマップ内の特定のキーへのアクセスが保護されます。資格証明ストア・フレームワークAPIを使用するには、アプリケーションでAPIを使用できるようにするアクセス・パーミッションを指定する必要があります。さらに、このAPIをコールするコードにもコードソース・パーミッションが必要ですが、これらのパーミッションは通常、特定のJarのみに制限されます。すべてのマップおよびキーに対してアクセス・パーミッションを定義することはお薦めしません。

次の各項では、アクセス・パーミッションの定義について説明します。

18.4.1 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>

18.4.2 マップにアクセスするためのパーミッションの例

次の例では、マップとそのマップ内のすべてのキーに対して特定のアクションを実行するソース・コードに対してのアクセス・パーミッションを示しています。

<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>

18.5 資格証明ストア・フレームワークAPIの使用

次の各項では、Java SEアプリケーションおよびJava EEアプリケーションでこのフレームワークを使用する方法について説明します。

18.5.1 Java SEアプリケーションでの資格証明ストア・フレームワークAPIの使用

Java SEアプリケーションで資格証明ストア・フレームワークAPIを使用するには、次の手順を実行します。

  1. jps-manifest.jarファイルがクラスパスに含まれていることを確認します。

  2. 資格証明ストア・フレームワークAPIにアクセスするためのパーミッションを指定します。

  3. Java仮想マシン(JVM)オプションを適宜設定します。次のようなオプションがあります。

    • -Doracle.security.jps.config
      

      デフォルトの場所($DOMAIN_HOME/config/fmwconfig/jps-config-jse.xml)とは異なる場合に、jps-config-jse.xmlファイルへのフルパスを指定します。

    • -Djava.security.policy
      

      デフォルトの場所($WL_HOME/server/lib)とは異なる場合に、weblogic.policyファイルの場所を指定します。

    • -Dcommon.components.home
      

      ミドルウェア・ホームの下にあるoracle_commonディレクトリの場所を指定します。

    • -Dopss.version
      

      環境で使用されるバージョンを指定します。

18.5.2 Java EEアプリケーションでの資格証明ストア・フレームワークAPIの使用

資格証明ストア・フレームワークAPIをJava EEアプリケーションで使用するには、アプリケーションをOracle WebLogic Serverにデプロイする前に、動作に必要なアクセス・パーミッションを指定します。

18.6 資格証明ストア・フレームワークAPIの例

次の各例では、資格証明ストア操作で必要なアクセス・パーミッションを使用する方法を示します。

18.6.1 資格証明ストア・フレームワーク操作の例

次の例では、他の例で使用されている資格証明ストア・フレームワーク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";
                }
        };
    }
}

18.6.2 ファイル資格証明を使用するJava SEアプリケーションの例

この項の例では、$DOMAIN_HOME/config/fmwconfig/system-jazn-data.xmlファイルで表されるファイル資格証明ストアを使用するJava SEアプリケーションを示します。

この例では、システム・プロパティprojectsrc.homeはJava SEアプリケーションを格納しているディレクトリを指し、clientApp.jardistディレクトリに存在するアプリケーション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();
        }
   }
}

18.6.3 ファイル資格証明を使用する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); 

18.6.4LDAPストアを使用する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>

18.6.5 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>