Configuring Keystore dynamically in WebServices using Metro

    In most secure webservice scenarios we configure keystore using the keystore confuguration tag in the service policy file.But at times we may want to configure the keystore dynamically at run time as to which keystore to use basing on some condition.
In such cases we can use another variant of keystore configuration where we can specify the callback handler that can be used to select and load the keystore.

<sc:Keystore
   alias={the certificate alias from the  keystore to be used for Signatures}
   aliasSelector={the fully qualified classname of a class implementing com.sun.xml.wss.AliasSelector interface}?
   callbackHandler={fully qualified classname of a class implementing javax.security.auth.callback.CallbackHandler, should be able to handle  com.sun.xml.wss.impl.callback.KeyStoreCallback and  com.sun.xml.wss.impl.callback.PrivateKeyCallback}
/>

For more information refer to Dynamic KeyStore configuration section in Kumar's blog.

Here is a short description of such as case.

   1. Create a simple webservice using Netbeans.
   2. Now configure it to be a secure service.If you aren't aware of how to configure webservice security , refer to metro guide.Here I configured the service to use UserName authentication with Symmetric Key.
   3. Now open the service policy file and try to find the Keystore configuration tag:(similar to the one below)

<sc:KeyStore wspp:visibility="private" location="/space/Sreekanth/servers/glassfishv3/glassfish/domains/domain1 /config/keystore.jks" type="JKS" storepass="changeit" alias="xws-security-server"/>

   4. Now modify that keystore configuration to use "callbackhandler" attribute as below:
<sc:KeyStore wspp:visibility="private" type="JKS"   alias="bob" callbackHandler="simple.server.MyKeyStoreCallbackHandler"/>
   5. Write your own CallbackHandler to handle KeystoreCallback and PrivateKey call back.This is how handle() method of my callbackhandler looks like:

public class MyKeyStoreCallbackHandler implements CallbackHandler {

...

       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

        for (Callback callback : callbacks) {

            if (callback instanceof KeyStoreCallback) {

                java.io.FileInputStream fis = null;

                try {

                    keystore = KeyStore.getInstance(KeyStore.getDefaultType());

                    String AS_HOME = System.getProperty("com.sun.aas.installRoot");

                    System.out.println("AS_HOme..." + AS_HOME);

                    fis = new java.io.FileInputStream(AS_HOME + "/xws-security/etc/server-keystore.jks");

                    keystore.load(fis, "changeit".toCharArray());

                    System.out.println("Keystore loaded..");

                    ((KeyStoreCallback) callback).setKeystore(keystore);

                } catch (NoSuchAlgorithmException nsae) {

                    System.out.println("Exception : " + nsae.getMessage());

                    nsae.printStackTrace();

                } catch (KeyStoreException kse) {

                    System.out.println("Exception : " + kse.getMessage());

                    kse.printStackTrace();

                } catch (CertificateException ce) {

                    System.out.println("Exception : " + ce.getMessage());

                    ce.printStackTrace();

                } finally {

                    if (fis != null) {

                        fis.close();

                    }

                }

            } else if (callback instanceof PrivateKeyCallback) {

               PrivateKey privateKey = null;

                Properties properties = new Properties();

                this.keyStorePassword = properties.getProperty("keystore.password");

                Certificate certs[] = null;

                try {

                    privateKey = (PrivateKey) keystore.getKey("bob", "changeit".toCharArray());

                    certs = keystore.getCertificateChain("bob");

                } catch (KeyStoreException ex) {

                    System.out.println("KeyStoreException : " + ex.getMessage());

                    ex.printStackTrace();

                } catch (NoSuchAlgorithmException nsae) {

                    System.out.println("NoSuchAlgorithmException : " + nsae.getMessage());

                    nsae.printStackTrace();

                } catch (UnrecoverableKeyException uke) {

                    System.out.println("UnrecoverableKeyException : " + uke.getMessage());

                    uke.printStackTrace();

                }          

                ((PrivateKeyCallback) callback).setKey(privateKey);

                System.out.println("Private Key callback Handled...");

            }

        }

}
   6. Now deploy your service
   7. Create a sample webservice client and invoke the client.
   8. Now you see the keystore is loaded from the callback handler we wrote.
   9. If you deploy a jsr109 webservice, then metro will try to search for the default keystores in glassfish server.Try using non 109 app.





Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

This is my personal blog.All the information here reflects my own thoughts and feelings and should not be taken as official information from Oracle.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today