Skip Headers
Oracle® Fusion Middleware Application Security Guide
11g Release 1 (11.1.1)

Part Number E10043-11
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

27 Developing with the Keystore Service

This chapter explains how to utilize the Keystore Service when developing applications.

Beginning with a survey of the Keystore Service API, the chapter describes what you need to know when invoking the service in your applications; explains how to configure the service; and presents examples of common keystore operations and ways to retrieve keys at runtime.

This chapter contains the following topics:

27.1 About the Keystore Service API

A keystore is used for secure storage of and access to keys and certificates. The Keystore Service API is used to access and perform operations on the keystores.

The Keystore Service:

Critical (create, update, delete) functions provided by the Keystore Service API include:

Operations on a KeyStore are secured by KeyStoreAccessPermission, which implements the fine-grained access control model utilized by the Keystore Service.

27.2 Overview of Application Development with the Keystore Service

Knowledge of the following areas is helpful in getting your applications to work with the Keystore Service:

27.3 Setting the Java Security Policy Permission

The Oracle Platform Security Services keystore provider is set when the server is started. When the provider is file-based, the data is stored in system-jazn-data.xml.

Keystore Service supports securing keys:

Notes:

  • To properly access the Keystore Service APIs, you need to grant Java permissions in the policy store.

  • The code invoking Keystore Service APIs needs code source permission. The permissions are typically for specific code jars and not for the complete application.

This section provides guidelines for permission grants to keystore objects, along with several examples:

Note:

In the examples, the application jar file name is AppName.jar.

27.3.1 Guidelines for Granting Permissions

The Keystore Service relies on Java permissions to grant permissions to keystore or key objects. It is highly recommended that only the requisite permissions be granted, and no more.

WARNING:

It is risky and inadvisable to grant unnecessary permissions, particularly permissions to all application stripes and/or keystores.

27.3.2 Permissions Grant Example 1

The Keystore Service stores objects in a hierarchy:

application stripe -> keystore(s) -> key(s)/certificate(s)

See Also:

Section 11.1.1 for details about the object hierarchy in the Keystore Service.

This example grants permissions for a specific application stripe and a specific keystore name within that stripe.

<jazn-policy>
    <grant>
        <grantee>
            <principals>...</principals>
            <!-- This is the location of the jar -->
            <!-- as loaded with the run-time -->
            <codesource>
      <url>file:${oracle.deployed.app.dir}/<MyApp>${oracle.deployed.app.ext}</url>
            </codesource>
        </grantee>
        <permissions>
            <permission>
               <class>oracle.security.jps.service.keystore.
                      KeyStoreAccessPermission</class>
               <name>stripeName=keystoreapp,keystoreName=ks1,alias=*</name>
              <!-- All actions are granted -->
              <actions>*</actions>
            </permission>
        </permissions>
    </grant>
</jazn-policy>

where:

  • stripeName is the name of the application stripe (typically the name of the application) for which you want to grant these permissions (read, write, update, and delete permissions denoted by the wildcarded actions).

  • keystoreName is the keystore name in use.

  • alias indicates the key alias within the keystore.

    Note:

    The wildcard indicates the application is granted permission for all aliases.

27.3.3 Permissions Grant Example 2

In this example, permissions are granted for a specific application stripe name and all its keystores.

<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.keystore.
                     KeyStoreAccessPermission</class>
              <name>stripeName=keystoreapp,keystoreName=*,alias=*</name>
              <!-- Certain actions are explicitly specified -->
              <!-- Compare to wild-card grant in previous example -->
              <actions>read,write,update,delete</actions>
        </permission>
        </permissions>
    </grant>
</jazn-policy>

27.3.4 Permissions Grant Example 3

In this example, read permissions are granted for a specific key alias within an application stripe name and a keystore.

<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.keystore.
                     KeyStoreAccessPermission</class>
              <name>stripeName=keystoreapp,keystoreName=ks1,alias=orakey</name>
              <actions>read</actions>
        </permission>
        </permissions>
    </grant>
</jazn-policy>

27.4 Configuring the Keystore Service

You need to define the Keystore Service instance in a configuration file which contains information about the location of the keystore and the provider classes. Configuration files are located in:

$DOMAIN_HOME/config/fmwconfig

and are named as follows:

27.5 Using the Keystore Service API

You can use the Keystore Service within Oracle WebLogic Server or in a standalone environment.

27.5.1 Using the Keystore Service API in Java SE Applications

To use the keystore service API in Java SE applications, proceed as follows:

  1. Set up the classpath. Ensure that the jps-manifest.jar file is in your classpath. For details, see Required JAR in Classpath in Section 1.5.3, "Scenario 3: Securing a Java SE Application".

  2. Set up the policy; to provide access to the Keystore Service APIs, you need to configure the access permissions in the reference policy store. For examples, see Section 27.3, "Setting the Java Security Policy Permission".

  3. Set JVM command-options. See details below.

  4. Run the application.

Command-line options include:

  • -Doracle.security.jps.config
    

    specifies the full path to the configuration file jps-config.xml, typically located in the directory domain_home/config/fmwconfig.

  • -Djava.security.policy
    

    specifies the location of the OPSS/Oracle WebLogic Server policy file weblogic.policy, typically located in the directory wl_home/server/lib.

  • -Dcommon.components.home
    

    specifies the location of the oracle_common directory under middleware home.

  • -Djrf.version
    

    specifies the version used in the environment; its value is 11.1.1.

  • -Djava.security.debug=all
    

    is helpful for debugging purposes

27.5.2 Using the Keystore Service API in Java EE Applications

To use the API in Java EE applications, proceed as follows:

  1. Out-of-the-box, the keystore service provider section of the jps-config.xml file is configured in the following directory:

    $DOMAIN_HOME/config/fmwconfig
    

    If needed, reassociate to an LDAP or database store.

  2. Set up the policy. To provide access to the Keystore Service APIs, you need to configure the access permissions in the reference policy store. For examples, see Section 27.3, "Setting the Java Security Policy Permission".

  3. Start Oracle WebLogic Server.

  4. Deploy and test the application.

27.6 Example of Keystore Service API Usage

This section provides an example of using the Keystore Service APIs. It contains these topics:

27.6.1 Java Program for Keystore Service Management Operations

The following Java code demonstrates common Keystore Service operations:

import oracle.security.jps.JpsContext;
import oracle.security.jps.JpsContextFactory;
import oracle.security.jps.JpsException;
import oracle.security.jps.service.keystore.KeyStoreProperties;
import oracle.security.jps.service.keystore.KeyStoreService;
import oracle.security.jps.service.keystore.KeyStoreServiceException;
 
import java.security.AccessController;
import java.security.PrivilegedAction;
 
public class KeyStoreTest {
 
    private static KeyStoreService ks = null;
 
 
    public KeyStoreTest() {
        super();
    }
 
    /*
     * This method performs a non-privileged operation. Either all code
     * in the call stack must have KeyStoreAccessPermission
     * OR
     * the caller must have the KeyStoreAccessPermission only and
     * invoke this operation in doPrivileged block
     */
    public static void doKeyStoreOperation() {
        doOperation();
    }

     /*
     * Since this method performs a privileged operation, only current class or
     * jar containing this class needs KeyStoreAccessPermission
     */
    public static void doPrivilegedKeyStoreOperation() {
        AccessController.doPrivileged(new PrivilegedAction<String>() {
            public String run() {
                doOperation();
                return "done";
            }
        });
    }
 
    private static void doOperation() {
        try {
            ks.deleteKeyStore("keystoreapp", "ks1", null);
        } catch(KeyStoreServiceException e) {
            e.printStackTrace();
        }

 public static void main(String args[]) throws Exception {
 
        try {
            new JpsStartup().start();
            JpsContext ctx = JpsContextFactory.getContextFactory().getContext();
            ks = ctx.getServiceInstance(KeyStoreService.class);
            
            // #1 - this call is in a doPrivileged block
            // #1 - this should succeed.
            doPrivilegedKeyStoreOperation();
 
            // #2 - this will also pass since granted all application
            // code necessary permission
            // NOTE: Since this call is not in a doPrivileged block,
            // this call would have failed if KeyStoreAccessPermission
            // wasn't granted to this class.
 
            /*
            doKeyStoreOperation();
            */
            
        } catch (JpsException je) {
            je.printStackTrace();
        }
 
    }
}

See Also:

Keystore API documentation at http://docs.oracle.com/javase/6/docs/api/index.html

27.6.2 Reading Keys at Runtime

This section explains ways an application can access keystore artifacts at runtime. It contains these topics:

27.6.2.1 Getting the Keystore Handle

To access a keystore at runtime and retrieve keys and certificates, an application must first get the keystore handle from the Keystore Service.

There are two approaches to this task:

  1. Obtain the handle by explicitly specifying the application stripe and keystore name as separate parameters

  2. Obtain the handle by specifying the application stripe and the keystore name as one parameter

Applications are free to use either method. Both methods work exactly in the same way for fetching keys and certificates, the only difference is the way the key store is loaded. Method 1 uses OPSS APIs while method 2 uses JDK KeyStore APIs.

27.6.2.2 Accessing Keystore Artifacts - Method 1

This example demonstrates the first method, in which the application stripe and keystore name are separate parameters.

// First get the KeyStoreService handle from JpsContext

JpsContext ctx = JpsContextFactory.getContextFactory().getContext();
KeyStoreService kss = ctx.getServiceInstance(KeyStoreService.class);
 
// Now get the keystore handle from KeyStoreService. There are two ways to 
// do this:
// Method 1: Explicitly specify application stripe and keystore name as
// separate parameters. In this example, the last parameter is null since
// we are demonstrating a permission-protected keystore. 

java.security.KeyStore keyStore = kss.getKeyStore("keystoreapp", "ks1", null);

// If this keystore is password-protected, provide the keystore password as the
// last parameter.
// java.security.KeyStore.ProtectionParameter pwd = new

java.security.KeyStore.PasswordProtection("password".toCharArray());

// java.security.KeyStore keyStore = kss.getKeyStore("keystoreapp", "ks1", pwd);
 
 
// Method 2: Specify application stripe and keystore name as one parameter
// using KSS URI. The last parameter is the keystore password, which is
// set to null in this example due to permission protected keystore.
// For password-protected keystore, set it to the keystore password.
// Since we are demonstrating Method 1 in this
// example, method 2 is commented out
 
// java.security.KeyStore keyStore kss.getKeyStore("kss://keystoreapp/ks1", null);
 
// Now you have a handle to the JDK KeyStore object. Use this handle to get
// key(s) and/or certificate(s)
 
// Get the private key or secret key associated with this alias. Pass the
// key password as the second parameter. In this case, it is null due to
// permission protected keystore.

Key key = keyStore.getKey("key-alias", null);
 
// Get the certificate associated with this alias

Certificate cert = keyStore.getCertificate("cert-alias");

Note:

Although this code fragment does not show this, calls to load, getKey, getCert are all privileged operations, and they should therefore be wrapped in a doPrivileged() block.

27.6.2.3 Accessing Keystore Artifacts - Method 2

This example demonstrates a method in which the application stripe and keystore name are provided as one parameter using the JDK Keystore URI.

// Create an object with parameters indicating the keystore to be loaded
FarmKeyStoreLoadStoreParameter param = new FarmKeyStoreLoadStoreParameter();
param.setAppStripeName("keystoreapp");
param.setKeyStoreName("ks1");
// The password is set to null in this example since it assumes this is a 
// permission protected keystore.
param.setProtectionParameter(null);
// If the keystore is password protected, use the following lines instead
// java.security.KeyStore.ProtectionParameter pwd = new java.security.KeyStore.PasswordProtection("password".toCharArray());
// param.setProtectionParameter(pwd);
 
// Initialize the keystore object by setting keystore type and provider
java.security.KeyStore keyStore = KeyStore.getInstance("KSS", new FarmKeyStoreProvider());
 
// Load the keystore. There are two ways to do this:
// Method 1: Explicitly specify application stripe and keystore name as
// separate parameters in param object
// keyStore.load(param);
 
// Method 2: Specify application stripe and keystore name as one parameter
// using KSS URI. Since we demonstrate method 2, in this
// example, method 1 is commented out
 
FarmKeyStoreLoadStoreParameter param = new FarmKeyStoreLoadStoreParameter();
param.setKssUri("kss://keystoreapp/ks1");
param.setProtectionParameter(null);
keyStore.load(param);
 
// Now you have a handle to JDK KeyStore object. Use this handle to get
// key(s) and/or certificate(s)
 
// Get the private key or secret key associated with this alias
Key key = keyStore.getKey("key-alias", null);
// Get the certificate associated with this alias
Certificate cert = keyStore.getCertificate("cert-alias");

Note:

Although this code fragment does not show it, calls to load, getKey, getCert are all privileged operations, and they should therefore be wrapped in a doPrivileged() block.

27.6.3 Policy Store Setup

For illustration, the example uses an XML-based policy store file (system-jazn-data.xml) which has the appropriate permissions needed to access the given keystore from the store. The file defines the permissions for different combinations of application stripe and keystore name. Other combinations, or attempts to access the store beyond the permissions defined here, will be disallowed.

Note:

This grant is added to the default policy store in
$DOMAIN_HOME/config/fmwconfig/system-jazn-data.xml
.

Here the system property projectsrc.home is set to point to the directory containing the Java SE application, and clientApp.jar is the application jar file which is present in sub-directory dist.

The corresponding policy grant looks like this:

<grant>
   <grantee>
      <codesource>
         <url>file:${projectsrc.home}/dist/clientApp.jar</url>
      </codesource>
   </grantee>
   <permissions>
      <permission>
         <class>oracle.security.jps.service.keystore.KeyStoreAccessPermission
         </class>
         <name>stripeName=keystoreapp,keystoreName=ks1,alias=*</name>
         <actions>*</actions>
      </permission>
   </permissions>
</grant>

27.6.4 Configuration File

Here is a sample configuration file (jps-config-jse.xml). The keystore.file.path property of the keystore service shows the directory containing the keystores.xml file:

Note:

For the complete configuration file see the default file shipped with the distribution at $DOMAIN_HOME/config/fmwconfig/jps-config-jse.xml.

<jpsConfig>
 ...
    <serviceInstances>
        <serviceInstance name="keystore_file_instance"
                         provider="keystore_file_provider">
            <property name="keystore.file.path" value="store" />
            <property name="keystore.provider.type" value="file" />
        </serviceInstance>
    </serviceInstances>
 ...
</jpsConfig>

27.6.5 About Using the Keystore Service in the Java SE Environment

In the Java SE environment, the following calls are equivalent:

KeyStoreService store = JpsServiceLocator.getServiceLocator().lookup(KeyStoreService.class);

and:

KeyStoreService store = JpsContextFactory.getContextFactory().getContext().getServiceInstance

(KeyStoreService.class); 

27.7 Best Practices

In a clustered environment and when the store is file-based, use the Keystore Service Mbean API over the Keystore Service API to create, retrieve, update, and delete keys for an application.

If you are simply reading keys, however, either API can be used.