Oracle® Fusion Middleware Application Security Guide 11g Release 1 (11.1.1) Part Number E10043-10 |
|
|
PDF · Mobi · ePub |
This chapter explains how to utilize the Keystore Service when developing applications.
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:
enables you to manage keys and certificates securely
provides an API for storage, retrieval, and maintenance of keys and certificates in different back-end repositories
supports file, database, LDAP-based keystore management
Critical (create, update, delete) functions provided by the Keystore Service API include:
creating keystores
deleting keystores
obtaining a handle to the domain trust store
obtaining a handle to a keystore
obtaining the configured properties for a keystore
obtaining a list of the keystores within an application stripe
Operations on a KeyStore
are secured by KeyStoreAccessPermission
, which implements the fine-grained access control model utilized by the Keystore Service.
Knowledge of the following areas is helpful in getting your applications to work with the Keystore Service:
Determining appropriate application stripe and keystore names to use.
Provisioning Java security policies.
Policy permissions are set in the policy store, which can be file-based (system-jazn-data.xml
) or LDAP-based. Setting appropriate permissions to enable application usage without compromising the security of your data requires careful consideration of permission settings.
See Also:
Section 9.1, "Managing the Policy Store".Defining the Keystore Service instance in jps-config.xml
.
You will need to define the service instance in jps-config.xml
only if manually crafting the configuration file.
Note:
The file-based provider is already configured by default, and can be changed to an LDAP-based provider. See Section 8.6, "Migrating the OPSS Security Store".Steps to take in setting up the environment.
The steps are different for stand-alone applications and those that operate in an Oracle WebLogic Server environment.
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:
at the application stripe level,
at the keystore level, or
with finer granularity for specific <application stripe, keystore, key>
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 isAppName.jar
.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.
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 key store name in use.
alias
indicates the key alias within the key store.
Note:
The wildcard indicates the application is granted permission for all aliases.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>
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>
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:
jps-config.xml
for Oracle WebLogic Server
jps-config-jse.xml
for Java SE
You can use the Keystore Service within Oracle WebLogic Server or in a standalone environment.
The steps for using the API in a standalone environment are:
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".
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".
Run the application.
Command-line options include:
-Doracle.security.jps.config
specifies the full path to the configuration file
-Djava.security.policy
specifies the location of the OPSS/Oracle WebLogic Server policy file
-Djava.security.debug=all
is helpful for debugging purposes
Take these steps to use the API in an Oracle WebLogic Server environment:
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.
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".
Start Oracle WebLogic Server.
Deploy and test the application.
This section provides an example of using the key store service APIs. It contains these topics:
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.internal.policystore.JavaPolicyProvider; 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 { static { java.security.Policy.setPolicy(new JavaPolicyProvider()); } 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(); } /* * 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 { 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(); } } }
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 key store from the store. The file defines the permissions for different combinations of application stripe and key store name. Other combinations, or attempts to access the store beyond the permissions defined here, will be disallowed.
Note:
The default policy store to which this grant is added is$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>
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>
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);
In a clustered environment, 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.