21 Developing with the Keystore Service

This chapter explains how to use the Keystore Service API in your applications and includes examples of common keystore operations to access and retrieve keys at runtime.

This chapter includes the following topics:

21.1 About the Keystore Service API

A keystore is used to store keys and certificates securely, and you use the Keystore Service API to access, retrieve, and maintain data in the keystore repository. This repository type can be a file, an LDAP, or a DB.

Operations include creating, reading, updating, and deleting keys, and get handles to keystore artifacts the keystore configured properties. These operations are secured by theKeyStoreAccessPermission class that implements the fine-grained access control model used by the service.

Before using the Keystore Service API in your application:

  • Identify the application stripe and the keystore to use.

  • Provision the required policies that enable your application to access and use the keystore. For information about provisioning policies, see Setting Policy Permissions.

  • Make sure that the keystore instance is specified in the jps-config.xml file.

21.2 Setting Policy Permissions

The keystore provider configured in the domain is instantiated when the server starts. A file keystore provider specifies its content in the system-jazn-data.xml file.

You can secure keys at the application stripe level, at the keystore level, or at a single key level. To access the keystore with the Keystore Service APIs, your application must have a codesource permission that specifies the operations the application is allowed.

Oracle recommends that these permissions be restricted to specific applications and keys.

The following sections illustrate several permission examples:

21.2.1 Permission for a Keystore Example

The following example illustrates a policy that grants a codesource any action to a keystore within a stripe:

<jazn-policy>
    <grant>
        <grantee>
            <principals>...</principals>
            <!-- This is the location of the JAR as loaded with the runtime -->
            <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 to which you want to grant permissions.

  • keystoreName is the name of the keystore.

  • alias indicates the key alias within the keystore. The wild card indicates the application is granted permission for all aliases.

21.2.2 Permission for a Map Example

The following example illustrates a policy that grants a codesource read, write, and delete permissions to all keystores within a stripe:

<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>
              <actions>read,write,update,delete</actions>
        </permission>
        </permissions>
    </grant>
</jazn-policy>

21.2.3 Permission for a Key Alias Example

The following example illustrates a policy that grants a codesource read permission to a specific keystore and alias within a stripe:

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

21.3 Using the Keystore Service API in Java EE Applications

To use the Keystore Service API in Java EE applications:

  1. Set up the permission required for your applicant to use the API.

  2. Start Oracle WebLogic Server.

  3. Deploy the application.

21.4 Using the Keystore Service API in Java SE Applications

To use the Keystore Service API in Java SE applications:

  1. Ensure that the jps-manifest.jar file is in your classpath.

  2. Set up the permission required for your applicant to use the API.

  3. Set Java Virtual Machine (JVM), as appropriate:

    -Doracle.security.jps.config
    

    to specify the full path to the jps-config-jse.xml configuration file.

    -Djava.security.policy
    

    to specify the location of the weblogic.policy policy file.

    -Dcommon.components.home
    

    to specify the location of the oracle_common directory under middleware home.

    -Dopss.version
    

    to specify the version used in the environment.

    -Djava.security.debug=all
    

    to specify a debug level.

  4. Run the application.

21.5 Keystore Service API Examples

The following sections show examples of use of the API:

21.5.1 Keystore Service Management Example

The following example illustrates common keystore 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();
    }
     /*
     * because 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);
            // this call is in a doPrivileged block
            doPrivilegedKeyStoreOperation();
 
            
        } catch (JpsException je) {
            je.printStackTrace();
        }
    }
}

21.5.2 Reading Keys at Runtime Example

The following examples illustrate several ways to access keystore artifacts at runtime.

21.5.2.1 Getting a Handle to the Keystore

To access a keystore, your application must first get the keystore handle by either specifying the application stripe and keystore name as separate parameters, or by specifying the application stripe and keystore name as one parameter.

Both methods work exactly in the same way for fetching keys and certificates, the only difference is the way the keystore is loaded. The first method 1 uses OPSS APIs. The second one uses Java SE Development Kit (JDK) APIs.

21.5.2.2 Accessing Keystore Artifacts - Method 1

The following example illustrates how to get a handle to the keystore, in which you specify the application stripe and keystore as 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. 
// Method 1: Explicitly specify application stripe and keystore name as
// separate parameters. In this example, the last parameter is null because
// we are demonstrating a password-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.
Key key = keyStore.getKey("key-alias", null);
 
// Get the certificate associated with this alias
Certificate cert = keyStore.getCertificate("cert-alias");

Note:

Oracle recommends that you place calls to the methods load, getKey, getCert inside a doPrivileged block.

21.5.2.3 Accessing Keystore Artifacts - Method 2

The following example illustrates how to get a handle to the keystore, in which you specify the application stripe and keystore in one parameter using the JDK keystore URI.

// Create an object with parameters indicating the keystore to load
FarmKeyStoreLoadStoreParameter param = new FarmKeyStoreLoadStoreParameter();
param.setAppStripeName("keystoreapp");
param.setKeyStoreName("ks1");
// The password is set to null in this example because 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. because 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 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:

Oracle recommends you place calls to the methods load, getKey, getCert inside a doPrivileged block.