6 Using SSL to Secure Communication

Oracle Coherence supports Secure Sockets Layer (SSL) to secure TCMP communication between cluster nodes and to secure the TCP communication between Oracle Coherence*Extend clients and proxies. Oracle Coherence supports the Transport Layer Security (TLS) protocol, which superseded the SSL protocol; however, the term SSL is used in this documentation because it is the more widely recognized term.

This chapter includes the following sections:

Overview of SSL

SSL is a security protocol that secures communication between entities (typically, clients and servers) over a network. SSL works by authenticating clients and servers using digital certificates and by encrypting and decrypting communication using unique keys that are associated with authenticated clients and servers.

If you are new to SSL, then review this section prior to configuring SSL. This section is not intended to be a complete guide to SSL and only covers concepts that are used in this documentation. To learn more about SSL, see

Establishing Identity and Trust

The identity of an entity is established by using a digital certificate and public and private encryption keys. The digital certificate contains general information about the entity and also contains the public encryption key embedded within it. A digital certificate is verified by a Certificate Authority (CA) and signed using the CA's digital certificate. The CA's digital certificate establishes trust that the entity is authentic.

Encrypting and Decrypting Data

The digital certificate for an entity contains a public encryption key that is paired with a private encryption key. Certificates are passed between entities during an initial connection. Data is then encrypted using the public key. Data that is encrypted using the entity public key can only be decrypted using the entity private key. This ensures that only the entity that owns the public encryption key can decrypt the data.

Using One-Way Authentication Versus Two-Way Authentication

SSL communication between clients and servers is set up using either one-way or two-way authentication. With one-way authentication, a server is required to identify itself to a client by sending its digital certificate for authentication. The client is not required to send the server a digital certificate and remains anonymous to the server. Two-way authentication requires both the client and the server to send their respective digital certificates to each other for mutual authentication. Two-way authentication provides stronger security by assuring that the identity on each sides of the communication is known.

Generating Java SSL Artifacts

The Java keytool utility that is located in the JDK_HOME/bin directory generates and manages SSL artifacts. This activity includes: creating a keystore; generating a unique public/private key pair; creating a self-signed digital certificate that includes the public key; associating the certificate with the private key; and storing these artifacts in the keystore.

The following example creates a keystore named server.jks that is located in the /test directory. A public/private key pair is generated for the entity identified by the -dname value ("cn=administrator, ou=Coherence, o=Oracle, c=US"). A self-signed certificate is created that includes the public key and identity information. The certificate is valid for 180 days and is associated with the private key in a keystore entry referred to by the alias (admin). Both the keystore and private key must have a password.

keytool -genkeypair -keyalg RSA -keysize 2048 -dname "cn=administrator, ou=Coherence, o=Oracle, c=US" -alias admin -keypass password -keystore /test/server.jks -storepass password -validity 180

The certificate that is generated by the preceding command is adequate for development purposes. However, certificates are typically verified by a trusted CA (such as VeriSign). To have the certificate verified, use the keytool utility to generate a Certificate Signing Request (CSR) file:

keytool -certreq -file admin.csr

Send the CSR file to a CA, which returns a signed certificate. Use the keytool utility to import the returned certificate, which replaces the self-signed certificate in the keystore:

keytool -importcert -trustcacerts -file signed_admin.cer

Lastly, use the keytool utility to create a second keystore that acts as a trust keystore. The trust keystore contains digital certificates of trusted CAs. Certificates that have been verified by a CA are considered trusted only if the CA's certificate is also found in the trust keystore. For example, in a typical one-way authentication scenario, a client must have a trust keystore that contains a digital certificate of the CA that signed the server's certificate. For development purposes, a self-signed certificate can be used for both identity and trust; moreover, a single keystore can be used as both the identity store and the trust keystore.

Generating Windows SSL Artifacts

The following steps describe how to set up two-way authentication on Windows to secure Oracle Coherence*Extend .NET clients. See Configuring a .NET Client-Side Stream Provider for details on configuring .NET clients. See the Windows documentation for complete instructions on setting up SSL on Windows.

To set up two-way authentication on Windows:

  1. Run the following commands from the Visual Studio command prompt:

    c:\>makecert -pe -n "CN=Test And Dev Root Authority" -ss my -sr LocalMachine -a sha1 -sky signature -r "Test And Dev Root Authority.cer"
    
    c:\>makecert -pe -n "CN=MyServerName" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in "Test And Dev Root Authority" -is MY -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
    
    c:\>makecert -pe -n "CN=MyClient" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in "Test And Dev Root Authority" -is MY -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
    
  2. Create the certificate trusted root certification authority (for tests only).

    makecert -pe -n "CN=Test And Dev Root Authority" -ss my -sr LocalMachine -a sha1 -sky signature -r "Test And Dev Root Authority.cer"
    
  3. Copy the created certificate from the personal store to the trusted root certification authority store.

  4. Create the server certificate based on the trusted root certification.

    makecert -pe -n "CN=MyServerName" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in "Test And Dev Root Authority" -is MY -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
    
  5. From the certificate store of the trusted root certification authority (Test And Dev Root Authority), export a certificate file without a public key (.cer).

  6. From the certificate store of the trusted root certification authority (Test And Dev Root Authority), export a certificate file with a private key (.pfx).

  7. Copy the .cer file to each client computer. The location must be accessible to the sslstream client program.

  8. Copy the .pfx file to each client computer.

  9. Import the .pfx file to the trusted root certification authority certificate store of each client computer.

  10. On each client computer, delete the .pfx file. (This step ensures that the client does not communicate or export the private key.)

Using SSL to Secure TCMP Communication

Oracle Coherence supports SSL to secure communication between cluster members. The configuration examples in this section assume that valid digital certificates for all clients and servers have been created as required and that the certificates have been signed by a Certificate Authority (CA). The digital certificates must be found in an identity store, and the trust keystore must include the signing CA's digital certificate. Use self-signed certificates during development as needed.

This section includes the following topics:

Overview of Using SSL to Secure TCMP Communication

Both one-way and two-way SSL authentication are supported with TCMP. Two-way authentication is typically used more often than one-way authentication, which has fewer use cases in a cluster environment. In addition, it is important to realize that TCMP is a peer-to-peer protocol that generally runs in trusted environments where many cluster nodes are expected to remain connected with each other. Carefully consider the implications of SSL on administration and performance.

Figure 6-1 shows a conceptual view of cluster members using two-way SSL. Each cluster member includes a trust keystore and a Java keystore (JKS) that contains digital certificates that are used for mutual authentication.

Figure 6-1 Conceptual Architecture of SSL with TCMP

Description of Figure 6-1 follows
Description of "Figure 6-1 Conceptual Architecture of SSL with TCMP"

Define an SSL Socket Provider

Configure SSL for TCMP in an operational override file by overriding the <socket-provider> element within the <unicast-listener> element. The preferred approach is to use the <socket-provider> element to reference an SSL socket provider configuration that is defined within a <socket-providers> node. However, the <socket-provider> element also supports including an in-line SSL configuration. Both approaches are demonstrated in this section. See socket-provider in Developing Applications with Oracle Coherence.

Note:

The use of Well Known Addresses (WKA) is required to use SSL with TCMP. See Using Well Known Addresses in Developing Applications with Oracle Coherence.

Example 6-1 demonstrates an SSL two-way authentication setup. The setup requires both an identity store and trust keystore to be located on each node in the cluster. The example uses the default values for the <protocol> and <algorithm> element (TLS and SunX509, respectively). These are shown only for completeness; you can omit them when you use the default values. The example uses the preferred approach, in which the SSL socket provider is defined within the <socket-providers> node and referred to from within the <unicast-listener> element.

Note:

The example includes passwords that are entered as clear text. Passwords can be encrypted using a password provider. See Encrypting SSL Passwords.

Example 6-1 Sample SSL Configuration for TCMP Communication

<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
   coherence-operational-config.xsd">
   <cluster-config>
      <unicast-listener>
         <socket-provider system-property="coherence.socketprovider">
            mySSLConfig</socket-provider>
         <well-known-addresses>
            <socket-address id="1">
               <address system-property="coherence.wka">198.168.1.5
               </address>
               <port system-property="coherence.wka.port">8088</port>
            </socket-address>
         </well-known-addresses>
      </unicast-listener>

      <socket-providers>
         <socket-provider id="mySSLConfig">
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
                  <password>password</password>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
               <socket-provider>tcp</socket-provider>
            </ssl>
         </socket-provider>
      </socket-providers>
   </cluster-config>
</coherence>

As an alternative, the SSL socket provider supports in-line configuration directly in the <unicast-listener> element, as shown in Example 6-2:

Example 6-2 Sample In-line SSL Configuration for TCMP Communication

<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
   coherence-operational-config.xsd">
   <cluster-config>
      <unicast-listener>
         <socket-provider system-property="coherence.socketprovider">
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
                  <password>password</password>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
               <socket-provider>tcp</socket-provider>
            </ssl>
         </socket-provider>
         <well-known-addresses>
            <socket-address id="1">
               <address system-property="coherence.wka">198.168.1.5
               </address>
               <port system-property="coherence.wka.port">8088</port>
            </socket-address>
         </well-known-addresses>
      </unicast-listener>
   </cluster-config>
</coherence>

Using the Predefined SSL Socket Provider

Oracle Coherence includes a predefined SSL socket provider that allows for configuration of two-way SSL connections. The predefined socket provider is based on peer trust: every trusted peer resides within a single JKS keystore. The proprietary peer trust algorithm (PeerX509) works by assuming trust (and only trust) of the certificates that are in the keystore and leverages the fact that TCMP is a peer-to-peer protocol.

The predefined SSL socket provider is defined within the <socket-providers> element in the operational deployment descriptor:

...
<cluster-config>
   <socket-providers>
      <socket-provider id="ssl">
         <ssl>
            <identity-manager>
               <key-store>
                  <url system-property="coherence.security.keystore">
                     file:keystore.jks
                  </url>
                  <password system-property="coherence.security.
                     password"/>
               </key-store>
               <password system-property="coherence.security.password"/>
            </identity-manager>
            <trust-manager>
               <algorithm>PeerX509</algorithm>
               <key-store>
                  <url system-property="coherence.security.keystore">
                     file:keystore.jks
                  </url>
                  <password system-property="coherence.security.
                     password"/>
               </key-store>
            </trust-manager>
            <socket-provider>tcp</socket-provider>
         </ssl>
      </socket-provider>
   </socket-providers>
</cluster-config>
...

As configured, the predefined SSL socket provider requires a Java keystore named keystore.jks that is found on the classpath. Use an operation override file to modify any socket provider values as required. The coherence.security.keystore and coherence.security.password system properties override the keystore and password instead of using the operational override file. For example:

-Dcoherence.security.keystore=/mykeystore.jks -Dcoherence.security.password=password

Note:

Ensure that certificates for all nodes in the cluster have been imported into the keystore.

To use the predefined SSL socket provider, override the <socket-provider> element in the <unicast-listener> configuration and reference the SSL socket provider using its id attribute. The following example configures a unicast listener to use the predefined SSL socket provider.

<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
   coherence-operational-config.xsd">
   <cluster-config>
      <unicast-listener>
         <socket-provider
            system-property="coherence.socketprovider>ssl
         </socket-provider>
         <well-known-addresses>
            <socket-address id="1">
               <address system-property="coherence.wka">198.168.1.5
               </address>
               <port system-property="coherence.wka.port">8088</port>
            </socket-address>
         </well-known-addresses>
      </unicast-listener>
   </cluster-config>
</coherence>

Resolving the Socket Provider URL

Some elements in a socket provider configuration are URLs. For example, the <url> element of the <key-store> element. The following is an explanation of how the values of these elements are processed to locate the resources they refer to:

  1. The value of the XML element is first converted to a Java URI.
  2. If the value is a valid URI and has a URI scheme, for example file: or http:, then it is assumed to be a valid URI and Coherence will try to open a stream to this URI to read the data.
  3. If the value has no scheme, then Coherence treats it as a file on the file system or on the class path. Coherence will first assume that the value is a file name (either fully qualified or relative to the working directory) and try to locate that file. If this fails Coherence will try to find the same file as a resource on the class path.

Using SSL to Secure Extend Client Communication

Oracle Coherence supports SSL to secure communication between extend clients and cluster proxies. The configuration examples in this section assume that valid digital certificates for all clients and servers have been created as required and that the certificates have been signed by a Certificate Authority (CA). The digital certificates must be found in an identity store, and the trust keystore must include the signing CA's digital certificate. Use self-signed certificates during development as needed.

This section includes the following topics:

Overview of Using SSL to Secure Extend Client Communication

SSL is used to secure communication between extend clients and extend proxies. SSL requires configuration on both the client side and the cluster side. SSL is supported for both Java and .NET clients but not for C++ clients.

Figure 6-2 shows a conceptual view of extend clients using SSL to communicate with a cluster proxy. The clients and the proxy include a trust keystore and an identity keystore that contain digital certificates that are used for authentication. Extend clients typically use one-way authentication in which only proxies authenticate with clients, and clients remain anonymous to proxies.

Figure 6-2 Conceptual Architecture of SSL with Oracle Coherence*Extend

Description of Figure 6-2 follows
Description of "Figure 6-2 Conceptual Architecture of SSL with Oracle Coherence*Extend"

Configuring a Cluster-Side SSL Socket Provider

Configure SSL in the cluster-side cache configuration file by defining an SSL socket provider for a proxy service. There are two options for configuring an SSL socket provider depending on the level of granularity that is required. The socket provider can be configured per proxy service where each proxy service defines an SSL socket provider configuration or references a predefined configuration that is included in the operational configuration file. The second option is to configure all proxy services to use the same global SSL socket provider configuration. A proxy service that provides its own configuration overrides the global configuration. The global configuration can also reference a predefined configuration that is included in the operational configuration file.

This section includes the following topics:

Configure an SSL Socket Provider per Proxy Service

To configure an SSL socket provider for a proxy service, add a <socket-provider> element within the <tcp-acceptor> element of each <proxy-scheme> definition. See socket-provider in Developing Applications with Oracle Coherence.

Example 6-3 demonstrates a proxy scheme that configures an SSL socket provider that uses the default values for the <protocol> and <algorithm> elements (TLS and SunX509, respectively). These are shown only for completeness; you can omit them when you use the default values.

Example 6-3 configures both an identity keystore (server.jks) and a trust keystore (trust.jks). This is typical of two-way SSL authentication, in which both the client and proxy must exchange digital certificates and confirm each other's identity. For one-way SSL authentication, the proxy server configuration must include an identity keystore but not a trust keystore.

Note:

  • If the proxy server is configured with a trust manager, then the client must use two-way SSL authentication, because the proxy expects a digital certificate to be exchanged. Make sure a trust manager is not configured if you want to use one-way SSL authentication.

  • The example includes passwords that are entered as clear text. Passwords can be encrypted using a password provider. See Encrypting SSL Passwords.

Example 6-3 Sample Cluster-Side SSL Configuration

...
<proxy-scheme>
   <service-name>ExtendTcpSSLProxyService</service-name>
   <acceptor-config>
      <tcp-acceptor>
         <socket-provider>
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password-provider>  
          	      <class-name>com.oracle.coherence.guides.ssl.CustomPasswordProvider</class-name>
                      <init-params>
                         <init-param>
                           <param-name>type</param-name>
                           <param-value>identity-keystore</param-value>
                         </init-param>
                      </init-params>
                     </password-provider>
                    <type>JKS</type>
                  </key-store>
                  <password-provider>  
          	    <class-name>com.oracle.coherence.guides.ssl.CustomPasswordProvider</class-name>
                    <init-params>
                       <init-param>
                         <param-name>type</param-name>
                         <param-value>identity-key</param-value>
                       </init-param>
                    </init-params>
                  </password-provider>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password-provider>  
          	      <class-name>com.oracle.coherence.guides.ssl.CustomPasswordProvider</class-name>
                      <init-params>
                        <init-param>
                         <param-name>type</param-name>
                         <param-value>trust-keystore</param-value>
                        </init-param>
                      </init-params>
                     </password-provider>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
               <socket-provider>tcp</socket-provider>
            </ssl>
         </socket-provider>
         <local-address>
            <address>192.168.1.5</address>
            <port>9099</port>
         </local-address>
      </tcp-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

The following example references an SSL socket provider configuration that is defined in the <socket-providers> node of the operational deployment descriptor by specifying the id attribute (ssl) of the configuration. See socket-providers in Developing Applications with Oracle Coherence.

Note:

A predefined SSL socket provider is included in the operational deployment descriptor and is named ssl. The predefined SSL socket provider is configured for two-way SSL connections and is based on peer trust, in which every trusted peer resides within a single JKS keystore. See Using the Predefined SSL Socket Provider for details. To configure a different SSL socket provider, use an operational override file to modify the predefined SSL socket provider or to create a socket provider configuration as required.
...
<proxy-scheme>
   <service-name>ExtendTcpSSLProxyService</service-name>
   <acceptor-config>
      <tcp-acceptor>
         <socket-provider>ssl</socket-provider>
         <local-address>
            <address>192.168.1.5</address>
            <port>9099</port>
         </local-address>
      </tcp-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>
...
Configure an SSL Socket Provider for All Proxy Services

To configure a global SSL socket provider for use by all proxy services, use a <socket-provider> element within the <defaults> element of the cache configuration file. With this approach, no additional configuration is required within a proxy scheme definition. See defaults in Developing Applications with Oracle Coherence.

The following example uses the same SSL socket provider configuration from Example 6-3 and configures it for all proxy services.

Note:

The example includes passwords that are entered as clear text. Passwords can be encrypted using a password provider. See Encrypting SSL Passwords.

<?xml version='1.0'?>

<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config
   coherence-cache-config.xsd">
   <defaults>
      <socket-provider>
         <ssl>
            <protocol>TLS</protocol>
            <identity-manager>
               <algorithm>SunX509</algorithm>
               <key-store>
                  <url>file:server.jks</url>
                  <password>password</password>
                  <type>JKS</type>
               </key-store>
               <password>password</password>
            </identity-manager>
            <trust-manager>
               <algorithm>SunX509</algorithm>
               <key-store>
                  <url>file:trust.jks</url>
                  <password>password</password>
                  <type>JKS</type>
               </key-store>
            </trust-manager>
            <socket-provider>tcp</socket-provider>
         </ssl>
      </socket-provider>
   </defaults>
   ...

The following example configures a global SSL socket provider by referencing an SSL socket provider configuration that is defined in the operational deployment descriptor:

<defaults>
   <socket-provider>ssl</socket-provider>
</defaults>

Configuring a Java Client-Side SSL Socket Provider

Configure SSL in the client-side cache configuration file by defining an SSL socket provider for a remote cache scheme and, if required, for a remote invocation scheme. There are two options for configuring an SSL socket provider, depending on the level of granularity that is required. The socket provider can be configured per remote service where each remote service defines an SSL socket provider configuration or references a predefined configuration that is included in the operational configuration file. The second option is to configure all remote services to use the same global SSL socket provider configuration. A remote service that provides its own configuration overrides the global configuration. The global configuration can also reference a predefined configuration that is included in the operational configuration file.

This section includes the following topics:

Configure an SSL Socket Provider per Remote Service

To configure an SSL socket provider for a remote service, add a <socket-provider> element within the <tcp-initiator> element of a remote scheme definition. See socket-provider in Developing Applications with Oracle Coherence.

Example 6-4 demonstrates a remote cache scheme that configures a socket provider that uses SSL. The example uses the default values for the <protocol> and <algorithm> elements (TLS and SunX509, respectively). These are shown only for completeness; you can omit them when you use the default values.

Example 6-4 configures both an identity keystore (server.jks) and a trust keystore (trust.jks). This is typical of two-way SSL authentication, in which both the client and proxy must exchange digital certificates and confirm each other's identity. For one-way SSL authentication, the client configuration must include a trust keystore but need not include an identity keystore, which indicates that the client does not exchange its digital certificate to the proxy and remains anonymous. The client's trust keystore must include the CA's digital certificate that was used to sign the proxy's digital certificate.

Note:

  • If the proxy server is configured with a trust manager, then the client must use two-way SSL authentication, because the proxy expects a digital certificate to be exchanged. Remove the proxy's trust manager configuration if you want to use one-way SSL authentication.

  • The example includes passwords that are entered as clear text. Passwords can be encrypted using a password provider. See Encrypting SSL Passwords.

Example 6-4 Sample Java Client-Side SSL Configuration

<?xml version="1.0"?>

<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config
   coherence-cache-config.xsd">
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>dist-extend</cache-name>
         <scheme-name>extend-dist</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend-dist</scheme-name>
         <service-name>ExtendTcpSSLCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <socket-provider>
                  <ssl>
                     <protocol>TLS</protocol>
                     <identity-manager>
                        <algorithm>SunX509</algorithm>
                        <key-store>
                           <url>file:server.jks</url>
                           <password>password</password>
                           <type>JKS</type>
                        </key-store>
                        <password>password</password>
                     </identity-manager>
                     <trust-manager>
                        <algorithm>SunX509</algorithm>
                        <key-store>
                           <url>file:trust.jks</url>
                           <password>password</password>
                           <type>JKS</type>
                        </key-store>
                     </trust-manager>
                     <socket-provider>tcp</socket-provider>
                  </ssl>
               </socket-provider>
               <remote-addresses>
                  <socket-address>
                     <address>198.168.1.5</address>
                     <port>9099</port>
                  </socket-address>
               </remote-addresses>
               <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>

The following example references an SSL socket provider configuration that is defined in the <socket-providers> node of the operational deployment descriptor by specifying the id attribute (ssl) of the configuration. See socket-providers in Developing Applications with Oracle Coherence.

Note:

A predefined SSL socket provider is included in the operational deployment descriptor and is named ssl. The predefined SSL socket provider is configured for two-way SSL connections and is based on peer trust, in which every trusted peer resides within a single JKS keystore. See Using the Predefined SSL Socket Provider. To configure a different SSL socket provider, use an operational override file to modify the predefined SSL socket provider or to create a socket provider configuration as required.

<?xml version="1.0"?>

<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config
   coherence-cache-config.xsd">
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>dist-extend</cache-name>
         <scheme-name>extend-dist</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend-dist</scheme-name>
         <service-name>ExtendTcpSSLCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <socket-provider>ssl</socket-provider>
               <remote-addresses>
                  <socket-address>
                     <address>198.168.1.5</address>
                     <port>9099</port>
                  </socket-address>
               </remote-addresses>
               <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>
Configure an SSL Socket Provider for All Remote Services

To configure a global SSL socket provider for use by all remote services, use a <socket-provider> element within the <defaults> element of the cache configuration file. With this approach, no additional configuration is required within a remote scheme definition. See defaults in Developing Applications with Oracle Coherence.

The following example uses the same SSL socket provider configuration from Example 6-4 and configures it for all remote services.

Note:

The example includes passwords that are entered as clear text. Passwords can be encrypted using a password provider. See Encrypting SSL Passwords.

<?xml version='1.0'?>

<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config
   coherence-cache-config.xsd">
   <defaults>
      <socket-provider>
         <ssl>
            <protocol>TLS</protocol>
            <identity-manager>
               <algorithm>SunX509</algorithm>
               <key-store>
                  <url>file:server.jks</url>
                  <password>password</password>
                  <type>JKS</type>
               </key-store>
               <password>password</password>
            </identity-manager>
            <trust-manager>
               <algorithm>SunX509</algorithm>
               <key-store>
                  <url>file:trust.jks</url>
                  <password>password</password>
                  <type>JKS</type>
               </key-store>
            </trust-manager>
            <socket-provider>tcp</socket-provider>
         </ssl>
      </socket-provider>
   </defaults>
   ...

The following example configures a global SSL socket provider by referencing an SSL socket provider configuration that is defined in the operational deployment descriptor:

<defaults>
   <socket-provider>ssl</socket-provider>
</defaults>

Configuring a .NET Client-Side Stream Provider

Configure SSL in the .NET client-side cache configuration file by defining an SSL stream provider for remote services. The SSL stream provider is defined using the <stream-provider> element within the <tcp-initiator> element.

Note:

Certificates are managed on Window servers at the operating system level using the Certificate Manager. The sample configuration assumes that the Certificate Manager includes the extend proxy's certificate and the trusted CA's certificate that signed the proxy's certificate. See Generating Windows SSL Artifacts.

Example 6-5 demonstrates a remote cache scheme that configures an SSL stream provider. Refer to the cache configuration XML schema (INSTALL_DIR\config\cache-config.xsd) for details on the elements that are used to configure an SSL stream provider.

Note:

The <protocol> element support any allowed SslProtocols enumeration values as well as a comma separated list of protocol values. For example:

<protocol>Tls11,Tls12</protocol>

Ensure the protocol is specified in both the client-side and server-side configuration.

Example 6-5 Sample .NET Client-Side SSL Configuration

<?xml version="1.0"?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://schemas.tangosol.com/cache
   assembly://Coherence/Tangosol.Config/cache-config.xsd">
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>dist-extend</cache-name>
         <scheme-name>extend-dist</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend-dist</scheme-name>
         <service-name>ExtendTcpSSLCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <stream-provider>
                  <ssl>
                     <protocol>Tls12</protocol>
                     <local-certificates>
                        <certificate>
                           <url>C:\</url>
                           <password>password</password>
                           <flags>DefaultKeySet</flags>
                        </certificate>
                     </local-certificates>
                  </ssl>
               </stream-provider>
               <remote-addresses>
                  <socket-address>
                     <address>198.168.1.5</address>
                     <port>9099</port>
                  </socket-address>
               </remote-addresses>
               <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>

Using SSL to Secure Federation Communication

Oracle Coherence supports SSL to secure communication between cluster participants in a federation. Communication is secured between federated service members and requires SSL configuration on each cluster participant that requires SSL security.

It is assumed that valid digital certificates for all servers that run the federated service have been created as required and that the certificates have been signed by a Certificate Authority (CA). The digital certificates must be found in an identity store, and the trust keystore must include the signing CA's digital certificate. In addition, ensure that an SSL socket provider definition is configured in the operational override file for each cluster. See Define an SSL Socket Provider.

To use SSL to secure federation communication:

Edit the federated cache scheme on each cluster to use a SSL socket provider definition.

For example:

<federated-scheme>
   <scheme-name>federated</scheme-name>
   <service-name>federated</service-name>
   <backing-map-scheme>
      <local-scheme />
   </backing-map-scheme>
   <autostart>true</autostart>
   <socket-provider>mySSLConfig</socket-provider>
   <topologies>
      <topology>
         <name>MyTopology</name>
      </topology>
   </topologies>
</federated-scheme>

Encrypting SSL Passwords

Entering passwords in an operational override file as clear text is not recommended beyond simple development and testing scenarios. Exposed passwords are a security risk and can lead to unwanted access to sensitive data.

Coherence offers two alternatives to hard coded passwords:

Reading Passwords from a URL

To load a password from a URL, such as a file on the file system, use the <password-url> element instead of the <password> element.

Example 6-6 demonstrates an SSL socket provider configuration that reads the keystore and private key passwords from files on the file system.

In the example XML, the identity manager’s keystore password is read from the /coherence/security/server-pass.txt file. The private key used by the identity manager is read from the /coherence/security/key-pass.txt file. The keystore password used by the trust manager is read from the /coherence/security/trust-pass.txt file.

Example 6-6 Reading a Password From a File in the Configuration for SSL

<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
   coherence-operational-config.xsd">
   <cluster-config>
      <socket-providers>
         <socket-provider id="mySSLConfig">
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password-url>file:/coherence/security/server-pass.txt</password-url>
                     <type>JKS</type>
                  </key-store>
                  <password-url>file:/coherence/security/key-pass.txt</password-url>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password-url>file:/coherence/security/trust-pass.txt</password-url>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
               <socket-provider>tcp</socket-provider>
            </ssl>
         </socket-provider>
      </socket-providers>
   </cluster-config>
</coherence>

By default, the <password-url> configuration uses all the data returned from the URL as the password. You can change this behavior to use only the first line of the data returned as the password by setting the first-line-only attribute of the <password-url> element to true.

For example, if the file /secret.txt contains the password followed by additional data on subsequent lines, you can configure the <password-url> element as shown below:
<password-url first-line-only="true">file:/secret.txt</password-url>

Using Custom Password Providers

Password providers allow you to obtain the SSL passwords from any source, including using encryption.

Password providers implement the com.tangosol.net.PasswordProvider interface. The class has a get method that returns a password for use in an SSL configuration. You can create your own password provider, or you can use the predefined com.tangosol.coherence.config.xml.processor.PasswordProviderBuilderProcessor$DefaultPasswordProvider class. The predefined password provider takes a password of type string and returns a password of type char[].

Define password providers in an operational override file by overriding the <password-providers> element within the <cluster-config> element. The preferred approach is to use the <password-provider> element in an SSL configuration to reference a password provider that is defined within a <password-providers> node. However, you can also define the <password-provider> element in-line when configuring a password for an SSL socket provider. Both approaches are demonstrated in this section. See password-provider in Developing Applications with Oracle Coherence.

Example 6-7 demonstrates an SSL socket provider configuration that references a password provider that is named MyPasswordProvider and is defined within the <password-providers> element. The password provider is used to access the identity manager private key and keystore and the trust manager keystore.

Example 6-7 Sample Password Provider Configuration for SSL

<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
   coherence-operational-config.xsd">
   <cluster-config>
      <socket-providers>
         <socket-provider id="mySSLConfig">
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password-provider>
                        <name>MyPasswordProvider</name>
                        <init-params>
                           <init-param>
                              <param-name>param_1</param-name>
                              <param-value>private</param-value>
                           </init-param>
                        </init-params>
                     </password-provider>
                     <type>JKS</type>
                  </key-store>
                  <password-provider>
                     <name>MyPasswordProvider</name>
                     <init-params>
                        <init-param>
                           <param-name>param_1</param-name>
                           <param-value>private</param-value>
                        </init-param>
                     </init-params>
                  </password-provider>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password-provider>
                        <name>MyPasswordProvider</name>
                        <init-params>
                           <init-param>
                              <param-name>param_1</param-name>
                              <param-value>private</param-value>
                           </init-param>
                        </init-params>
                     </password-provider>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
               <socket-provider>tcp</socket-provider>
            </ssl>
         </socket-provider>
      </socket-providers>

      <password-providers>
          <password-provider id="MyPasswordProvider">
              <class-name>package.MyPasswordProvider</class-name>
              <init-params>
                  <init-param>
                      <param-name>param_1</param-name>
                      <param-value>password</param-value>
                  </init-param>
              </init-params>
          </password-provider>
      <password-providers>
   </cluster-config>
</coherence>

Example 6-8 shows an alternative method of defining a password provider in-line within an SSL socket provider configuration.

Example 6-8 Sample In-line Password Provider Configuration for SSL

<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
   coherence-operational-config.xsd">
   <cluster-config>
      <socket-providers>
         <socket-provider id="mySSLConfig">
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password-provider>
                        <class-name>package.MyPasswordProvider</class-name>
                        <init-params>
                           <init-param>
                              <param-name>param_1</param-name>
                              <param-value>password</param-value>
                           </init-param>
                        </init-params>
                     </password-provider>
                     <type>JKS</type>
                  </key-store>
                  <password-provider>
                     <class-name>package.MyPasswordProvider</class-name>
                     <init-params>
                        <init-param>
                           <param-name>param_1</param-name>
                           <param-value>password</param-value>
                        </init-param>
                     </init-params>
                  </password-provider>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password-provider>
                        <class-name>package.MyPasswordProvider</class-name>
                        <init-params>
                           <init-param>
                              <param-name>param_1</param-name>
                              <param-value>password</param-value>
                           </init-param>
                        </init-params>
                     </password-provider>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
               <socket-provider>tcp</socket-provider>
            </ssl>
         </socket-provider>
      </socket-providers>
   </cluster-config>
</coherence>

Controlling Cipher Suite and Protocol Version Usage

An SSL socket provider can be configured to control the use of potentially weak ciphers or specific protocol versions. To control cipher suite and protocol version usage, edit the SSL socket provider definition and include the <cipher-suites> element and the <protocol-versions> elements, respectively, and enter a list of cipher suites and protocol versions using the name element. Include the usage attribute to specify whether the cipher suites and protocol versions are allowed (value of white-list) or disallowed (value of black-list). The default value for the usage attribute if no value is specified is white-list.

For example:

<socket-provider>
   <ssl>
   ...
      <cipher-suites usage="black-list">
         <name>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</name>
      </cipher-suites>
      <protocol-versions usage="black-list">
         <name>SSLv3</name>
      </protocol-versions>
   ...
   </ssl>
</socket-provider>

Using Host Name Verification

Learn how to configure host name verification in Oracle Coherence. A host name verifier ensures that the host name in the URL to which the client connects, matches the host name in the digital certificate that the server sends back as part of the SSL connection.

A host name verifier is useful when an SSL client (for example, Coherence acting as an SSL client) connects to a cache server on a remote host. It helps to prevent man-in-the-middle attacks.

Coherence includes a default host name verifier, and provides the ability to create and use a custom host name verifier as well.

This chapter includes the following sections:

Using the Default Coherence Host Name Verifier

If you are using the default Coherence host name verifier, the host name verification passes if the host name in the certificate matches the host name to which the client tries to connect.

The default host name verifier verifies host name in two phases:
  • Verification with wildcarding.
  • Verification without wildcarding, if verification with wildcarding fails.

By default, host name verifier is not enabled for backward compatibility. To enable the default host name verifier, see the description for the <hostname-verifier> element in ssl.

Verification with Wildcarding

If the the host name in the server certificate of the SSL session supports wildcarding, the CommonName attribute must meet the following criteria:
  • Have at least two dot ('.') characters.
  • Must start with "*."
  • Have only one "*" character.

In addition, the non-wildcarded portion of the CommonName attribute must equal the domain portion of the urlhostname parameter in a case-sensitive string comparison. The domain portion of urlhostname string is the urlhostname substring that remains after the hostname substring is removed. The hostname portion of urlhostname is the substring up to and excluding the first '.' (dot) of the urlhostname parameter string.

For example:

urlhostname: mymachine.oracle.com

CommonName: *.oracle.com

.oracle.com will compare successfully with .oracle.com.

urlhostname: mymachine.uk.oracle.com

CommonName: *.oracle.com

.uk.oracle.com will not compare successfully with .oracle.com

DNSNames obtained from the server certificate's SubjectAlternativeNames extension may be wildcarded.

Verification without Wildcarding

If wildcarded host name verification fails, the default host name verifier performs non-wildcarded verification. It verifies the CommonName attribute of the server certificate's SubjectDN or the DNSNames of the server certificate's SubjectAlternativeNames extension against the host name in the client URL (urlhostname). The certificate attribute must match the urlhostname (not case sensitive) parameter. The SubjectDN CommonName attribute is verified first, and if successful, the SubjectAlternativeNames attributes are not verified.

If the server certificate does not have a SubjectDN, or the SubjectDN does not have a CommonName attribute, then the SubjectAlternativeName attributes of type DNSNames are compared to the urlhostname parameter. The verification passes upon the first successful comparison to a DNSName. For a successful verification, the urlhostname must be equal to the certificate attribute being compared.

If urlhostname is localhost, you can set the coherence.security.ssl.allowLocalhost system property to true to enable 127.0.0.1, or the default IP address of the local machine to pass.

Using a Custom Host Name Verifier

When using a custom host name verifier, the class that implements the custom host name verifier must be specified in the CLASSPATH of Coherence (when acting as an SSL client) or a standalone SSL client.

For more information about using a custom host name verifier, see the description for the <hostname-verifier> element in ssl.

Using Private Key and Certificate Files

Coherence also supports using private key and certificate files directly, instead of loading them into a keystore. The examples in Encrypting SSL Passwords used Java keystore files to store the private key and certificates used to establish trust and identity in Coherence SSL.

Note:

Out of the box, Coherence only supports file formats supported by the JDK. These are private key files in PEM format (that is, a file with a header of -----BEGIN RSA PRIVATE KEY----- or -----BEGIN ENCRYPTED PRIVATE KEY-----) and X509 certificate files (that is, a file with a header of -----BEGIN CERTIFICATE-----). Alternative formats can be read using custom loaders. See Using Custom Keystore, Private Key, and Certificate Loaders.

Configuring an Identity Manager

When configuring an <identity-manager> element of a socket provider, instead of the <keystore> element, the <key> and <cert> elements can be used to supply the private key a certificate file locations. The value for both the <key> and <cert> element is a URL from which to load the key or certificate data.

Example 6-9 shows an <identity-manager> configuration that uses a private key loaded from the /coherence/security/client.pem file and a certificate loaded from the /coherence/security/client.cert file.

Example 6-9 Sample Identity Manager Using a Private Key and a Certificate File

<socket-provider>
  <ssl>
    <identity-manager>
      <key>file:/coherence/security/client.pem</key>
      <cert>file:/coherence/security/client.cert</cert>
    </identity-manager>
  </ssl>
</socket-provider>

When configuring an <identity-manager> element, the <keystore> element, and the <key> and <cert> elements are mutually exclusive; either configure a keystore, or a key and certificate. The Coherence operational configuration XSD validation does not allow both.

Configuring a Trust Manager

When configuring a <trust-manager> element of a socket provider, instead of the <keystore> element, one or more <cert> elements can be used to supply the certificate file locations. The value for the <cert> element is a URL from which to load the certificate data.

Example 6-10 shows a <trust-manager> configuration that uses a certificate loaded from the /coherence/security/server-ca.cert file.

Example 6-10 Sample Trust Manager Using a Certificate File

<socket-provider>
  <ssl>
    <trust-manager>
      <cert>file:/coherence/security/server-ca.cert</cert>
    </trust-manager>
  </ssl>
</socket-provider>

When configuring a <trust-manager> element, the <keystore> element and the <cert> elements are mutually exclusive; either configure a keystore, or one or more certificates. The Coherence operational configuration XSD validation does not allow both.

Using Custom Keystore, Private Key, and Certificate Loaders

To support loading keystores, private keys, and certificates from sources other than simple URLS or files, and to read different data formats, Coherence provides a way to configure custom loaders to read the required data from whatever external source is required. For example, in the cloud, keys and certificates can be stored in a secrets service and loaded directly from secrets, instead of loading from files. The Coherence OCI project on GitHub includes custom keystore, key, and certificate loaders that can read data from secrets in the Oracle Cloud (OCI) Secrets Service. See Coherence OCI.

This section includes the following topics:

Using the Custom KeyStore Loader

If using Java Keystores, you can implement an instance of com.tangosol.net.ssl.KeyStoreLoader in application code and configure it in the <key-store-loader> element, which is a child of the <key-store> element. This class can load the contents of a Java KeyStore from any desired location.

Example 6-11 shows a custom implementation of the KeyStoreLoader interface.

Example 6-11 A Custom KeyStore Loader Class

package com.acme.coherence;

import com.tangosol.net.ssl.KeyStoreLoader;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;

public class CustomKeyStoreLoader
        implements KeyStoreLoader
    {
    @Override
    public KeyStore load(String sType, PasswordProvider password)
            throws GeneralSecurityException, IOException
        {
        // return a KeyStore of the required type
        }
    }

Example 6-12 shows how you can use the CustomKeyStoreLoader class in an <identity-manager> configuration.

Example 6-12 Configure an Identity Manager with a Custom KeyStore Loader Class

<socket-provider>
  <ssl>
    <identity-manager>
      <key-store>
        <key-store-loader>
          <class-name>com.acme.coherence.CustomKeyStoreLoader</class-name>
        </key-store-loader>
      </key-store>
    </identity-manager>
  </ssl>
</socket-provider>

Example 6-13 shows how you can use the CustomKeyStoreLoader class in a <trust-manager> configuration.

Example 6-13 Configure an Trust Manager with a Custom KeyStore Loader Class

<socket-provider>
  <ssl>
    <trust-manager>
      <key-store>
        <key-store-loader>
          <class-name>com.acme.coherence.CustomKeyStoreLoader</class-name>
        </key-store-loader>
      </key-store>
    </trust-manager>
  </ssl>
</socket-provider>

As with other extension points in Coherence, the <key-store-loader> is an "instance" configuration that takes a class-name or a class-factory-name and method-name parameter. Optionally, the configuration can also use <init-params> to pass parameters to the class constructor or the factory method.

Example 6-14 shows how you can refactor the CustomKeyStoreLoader class to add constructor arguments.

Example 6-14 A Custom KeyStore Loader with Parameters

package com.acme.coherence;

import com.tangosol.net.ssl.KeyStoreLoader;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;

public class CustomKeyStoreLoader
        implements KeyStoreLoader
    {
    private final String param1;

    private final String param2;

    public CustomKeyStoreLoader(String param1, String param2)
        {
        this.param1 = param1;
        this.param2 = param2;
        }

    @Override
    public KeyStore load(String sType, PasswordProvider password)
            throws GeneralSecurityException, IOException
        {
        // return a KeyStore of the required type
        }
    }

Example 6-15 shows how you can configure the parameterized CustomKeyStoreLoader class. With the example configuration, the CustomKeyStoreLoader constructor is called with the parameters foo and bar.

Example 6-15 Configure a Custom KeyStore Loader with Parameters

<socket-provider>
  <ssl>
    <identity-manager>
      <key-store>
        <key-store-loader>
          <class-name>com.acme.coherence.CustomKeyStoreLoader</class-name>
          <init-params>
            <init-param>
              <param-type>string</param-type>
              <param-value>foo</param-value>
            </init-param>
            <init-param>
              <param-type>string</param-type>
              <param-value>bar</param-value>
            </init-param>
          </init-params>
        </key-store-loader>
      </key-store>
    </trust-manager>
  </ssl>
</socket-provider>

At runtime, the CustomKeyStoreLoader class’s load method is called to load the keystore. In the configurations above, the type parameter passed to the load method is the default keystore type ("JKS"). The PasswordProvider passed to the load method is the default null implementation that returns an empty password.

Example 6-16 shows how you can configure the keystore type and password, which are passed as parameters to the custom KeyStoreLoader.load. The example shows using the <password> element, but you can also use the <password-url> or the <password-provider> elements to supply the password to the loader.

Example 6-16 Passing the Keystore Type and Password to a Custom KeyStore Loader

<socket-provider>
  <ssl>
    <identity-manager>
      <key-store>
        <key-store-loader>
          <class-name>com.acme.coherence.CustomKeyStoreLoader</class-name>
        </key-store-loader>
        <password>secret</password>
        <type>PKCS12</type>
      </key-store>
    </identity-manager>
  </ssl>
</socket-provider>

Using the Custom PrivateKey Loader

If using private keys instead of keystores, you can implement an instance of com.tangosol.net.ssl.PrivateKeyLoader in application code and configure it in the <key-loader> element. The custom loader can then load a PrivateKey from any desired location in any required format.

As with other extension points in Coherence, the <key-loader> is an "instance" configuration that takes a class-name or a class-factory-name and a method-name parameter. Optionally, the configuration can also use <init-params> to pass parameters to the class constructor or factory method.

Example 6-17 shows a custom PrivateKeyLoader class.

Example 6-17 A Custom Private Key Loader

package com.acme.coherence;

import com.tangosol.net.PasswordProvider;
import com.tangosol.net.ssl.PrivateKeyLoader;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;

public class CustomPrivateKeyLoader
        implements PrivateKeyLoader
    {
    @Override
    public PrivateKey load(PasswordProvider password)
            throws GeneralSecurityException, IOException
        {
        // return a PrivateKey (optionally encrypted with a password)
        }
    }

Example 6-18 shows how you can configure the CustomPrivateKeyLoader class in the <identity-manager> element.

Example 6-18 Configure a Custom Private Key Loader

<socket-provider>
  <ssl>
    <identity-manager>
        <key-loader>
           <class-name>com.acme.coherence.CustomPrivateKeyLoader</class-name>
        </key-loader>
    </identity-manager>
  </ssl>
</socket-provider>

At runtime, the CustomPrivateKeyLoader class’s load method is called to create the PrivateKey instance. In the example above, there is no password configured for the key, so the PasswordProvider that is passed to the load method returns an empty password (new char[0]). You can add a password by using one of the password elements allowed in the <identity-manager> elements.

Example 6-19 shows a configuration with a password. In this example, the PasswordProvider returns the contents fetched from the URL file: /coherence/security/key-pass.txt as the key password.

Example 6-19 Configure a Password for a Custom Private Key Loader

<socket-provider>
  <ssl>
    <identity-manager>
      <key-loader>
        <class-name>com.acme.coherence.CustomPrivateKeyLoader</class-name>
      </key-loader>
      <password-url>file:/coherence/security/key-pass.txt</password-url>
    </identity-manager>
  </ssl>
</socket-provider>

Using a Custom Certificate Loader

If using certificate files in the identity manager or trust manager, you can implement an instance of com.tangosol.net.ssl.CertificateLoader in application code and configure it in the <cert-loader> element. This class can load an array of Certificate instances from any desired location in the required format.

As with other extension points in Coherence, the <cert-loader> is an "instance" configuration that takes a class-name or a class-factory-name and a method-name parameter. Optionally, the configuration can also use <init-params> to pass parameters to the class constructor or the factory method.

Example 6-20 shows an example of a custom CertificateLoader class. The load method is called to load the certificates.

Example 6-20 A Custom Certificate Loader

package com.acme.coherence;

public class CustomCertificateLoader
        implements CertificateLoader
    {
    @Override
    public Certificate[] load()
            throws GeneralSecurityException, IOException
        {
        // return a Certificate array
        }
    }

Example 6-21 shows how you can configure the CustomCertificateLoader class in the identity manager.

Example 6-21 Configure a Custom Certificate Loader in an Identity Manager

<socket-provider>
  <ssl>
    <identity-manager>
      <key>server.pem</key>
      <cert-loader>
        <class-name>com.acme.coherence.CustomCertificateLoader</class-name>
      </cert-loader>
    </identity-manager>
  </ssl>
</socket-provider>

Example 6-22 shows how you can configure the CustomCertificateLoader class in the trust manager.

Example 6-22 Configure a Custom Certificate Loader in an Trust Manager

<socket-provider>
  <ssl>
    <trust-manager>
      <cert-loader>
        <class-name>com.acme.coherence.CustomCertificateLoader</class-name>
      </cert-loader>
    </trust-manager>
  </ssl>
</socket-provider>

The load() method of the CertificateLoader class returns an array of certificates; so it can load multiple certificates. You can also configure multiple <cert-loader> elements to use multiple custom loaders. All the certificates provided by all the <cert> or <cert-loader> elements are combined into a single set of certificates for the SSL context to use.

Example 6-23 shows how you can configure multiple <cert> and custom loaders in a trust manager.

Example 6-23 Configure Multiple Certificates and Loaders in a Trust Manager

<socket-provider>
  <ssl>
    <trust-manager>
      <cert>server-ca.cert</cert>
      <cert-loader>
        <class-name>com.acme.coherence.CustomCertificateLoader</class-name>
        <init-params>
          <init-param>
            <param-type>string</param-type>
            <param-value>foo</param-value>
          </init-param>
        </init-params>
      </cert-loader>
      <cert-loader>
        <class-name>com.acme.coherence.CustomCertificateLoader</class-name>
        <init-params>
          <init-param>
            <param-type>string</param-type>
            <param-value>bar</param-value>
          </init-param>
        </init-params>
      </cert-loader>
    </trust-manager>
  </ssl>
</socket-provider>

Using Refreshable KeyStores, Private Keys, and Certificates

In some environments, keys, and certs used for TLS are created with relatively short lifetimes. This means that a Coherence application should be able to renew the keys and certs, ideally without having to restart the JVM. In Coherence releases prior to 14.1.1.2206, this feature was not available because a keystore was loaded once when the socket provider was instantiated. From Coherence release 14.1.1.2206 onward, it is possible to specify a refresh period, which then schedules a refresh of the SSL context to reload any configured keystores, private keys, and certificates.

The <refresh-period> element is used to configure the refresh time. This is a child element of the ssl element, meaning that the setting applies to both the identity manager and trust manager.

Example 6-24 configures a <refresh-period> element with a value of 24h to refresh the keys and certs every 24 hours.

Example 6-24 Configure a Refresh Period

<socket-provider>
  <ssl>
    <identity-manager>
      <key>server.pem</key>
      <cert>server.cert</cert>
    </identity-manager>
    <refresh-period>24h</refresh-period>
  </ssl>
</socket-provider>

Refreshable keystores, keys, and certs can easily be combined with custom keystore loaders, private key loaders, and certificate loaders, so that the new versions of the required SSL artifacts can be pulled from an external source.

Configuring a Refresh Policy

When using refreshable keys and certs, it may sometimes be useful to have an additional check to determine whether a refresh should occur. You can perform this check by configuring a <refresh-policy> as well as a <refresh-period>.

The <refresh-policy> element is a standard Coherence instance configuration and should resolve to an instance of com.tangosol.net.ssl.RefreshPolicy. When a scheduled refresh time is reached, the policy is checked first (by calling the RefreshPolicy.shouldRefresh() method) to determine whether the refresh should go ahead.

Example 6-25 shows a custom RefreshPolicy implementation.

Example 6-25 A Custom Refresh Policy Class

package com.acme.coherence;

public class CustomRefreshPolicy
        implements RefreshPolicy
    {
    @Override
    public boolean shouldRefresh(Dependencies deps, ManagerDependencies depsIdMgr, ManagerDependencies depsTrustMgr)
        {
        // perform some custom logic to determine whether it is time to refresh
        return true;
        }
    }

Example 6-26 shows how you can configure the custom refresh policy as part of the <ssl> element alongside the <refresh-period>.

Example 6-26 Configure a Custom Refresh Policy

<socket-provider>
  <ssl>
    <identity-manager>
      <key>server.pem</key>
      <cert>server.cert</cert>
    </identity-manager>
    <refresh-period>24h</refresh-period>
    <refresh-policy>
      <class-name>com.acme.coherence.CustomRefreshPolicy</class-name>
    </refresh-policy>
  </ssl>
</socket-provider>

For some policies, it is useful to know what keystores, keys, or certs are currently in use to determine whether they need to be refreshed. There are a number of default methods on RefreshPolicy that can be overridden for this purpose.

Example 6-27 shows how you can capture the certificates used by a trust store configuration, and then use the certificates to verify whether they are close to expiry. In this example, the trustStoreLoaded method is called when the trust store is created to notify the policy of the certificates used by the trust store. In the shouldRefresh method, the certificates can then be checked to determine whether they will still be valid at the next refresh interval.

Example 6-27 A Detailed Custom Certificate Refresh Policy

import com.oracle.coherence.common.net.SSLSocketProvider.Dependencies;
import com.oracle.coherence.common.util.Duration;
import com.tangosol.coherence.config.builder.SSLSocketProviderDependenciesBuilder.ManagerDependencies;
import com.tangosol.coherence.config.unit.Seconds;
import com.tangosol.net.ssl.RefreshPolicy;

import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;

public class CustomRefreshPolicy
        implements RefreshPolicy
    {
    private Certificate[] certs;

    @Override
    public void trustStoreLoaded(Certificate[] certs)
        {
        this.certs = certs;
        }

    @Override
    public boolean shouldRefresh(Dependencies deps, ManagerDependencies depsIdMgr, ManagerDependencies depsTrustMgr)
        {
        if (certs == null)
            {
            return true;
            }

        // get the refresh period from the dependencies
        Seconds secs = deps.getRefreshPeriod();
        // calculate the next refresh time as a Date
        Date nextRefresh = new Date(System.currentTimeMillis() + secs.as(Duration.Magnitude.MILLI));

        for (Certificate certificate : certs)
            {
            try
                {
                // The certs are all X509 certs, so check their validity on the next refresh date
                ((X509Certificate) certificate).checkValidity(nextRefresh);
                }
            catch (CertificateExpiredException | CertificateNotYetValidException e)
                {
                // a cert will have expired, so we need to update now
                return true;
                }
            }

        // no certs should have expired at the next refresh check
        return false;
        }
    }

Example 6-28 shows how you can configure the CustomRefreshPolicy class in the <ssl> configuration.

Example 6-28 Configure the Custom Certificate Refresh Policy

<socket-provider>
  <ssl>
    <trust-manager>
      <ca-cert>server-ca.cert</ca-cert>
      <ca-cert>client-ca.cert</ca-cert>
    </trust-manager>
    <refresh-period>24h</refresh-period>
    <refresh-policy>
      <class-name>com.acme.coherence.CustomRefreshPolicy</class-name>
    </refresh-policy>
  </ssl>
</socket-provider>