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:
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.
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:
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.
See also:
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>
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>
To use the Keystore Service API in Java EE applications:
Set up the permission required for your applicant to use the API.
Start Oracle WebLogic Server.
Deploy the application.
To use the Keystore Service API in Java SE applications:
Ensure that the jps-manifest.jar
file is in your classpath.
Set up the permission required for your applicant to use the API.
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.
Run the application.
The following sections show examples of use of the API:
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(); } } }
The following examples illustrate several ways to access keystore artifacts at runtime.
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.
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 methodsload
, getKey
, getCert
inside a doPrivileged
block.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 methodsload
, getKey
, getCert
inside a doPrivileged
block.