Hello again.
After some debug and source code research, I found solution. It is not so
beautiful and seems to be workaround, but it works. Well, I hope it would be
useful not only for me.
What have I found.
JaasSecurityDomain realy updates keystores, but only in itself. Ssl
JBossImplementation in server.xml used only to create and return
JBossSocketFactory. Factory gets SecurityDomain by JNDI to init and create
socket. But... There is so called SSLContext, that takes care about keystore
usage and ssl-handshakes, and it uses SecurityDomain only in initialisation.
So, after socket building SSLContext use cached keystores.
Well, my solution.
I wrote custom implementation of 3 classes
org.jboss.net.ssl.JBossReloadableImplementation
| package org.jboss.net.ssl;
|
| import org.apache.tomcat.util.net.ServerSocketFactory;
|
| public class JBossReloadableImplementation extends JBossImplementation {
|
| public JBossReloadableImplementation() throws ClassNotFoundException {
| super();
| }
|
| public String getImplementationName() {
| return "JBossReloadable";
| }
|
| public ServerSocketFactory getServerSocketFactory() {
| return new JBossReloadableSocketFactory();
| }
| }
|
as I said, it used only to provide new JBossReloadableSocketFactory
org.jboss.security.plugins.JaasSecurityDomainReloadable
| package org.jboss.security.plugins;
|
|
|
| import javax.security.auth.callback.CallbackHandler;
|
|
|
| import org.jboss.net.ssl.JBossReloadableSocketFactory;
|
|
|
| public class JaasSecurityDomainReloadable extends JaasSecurityDomain {
|
|
|
| public JaasSecurityDomainReloadable() {
|
| super();
|
| }
|
| public JaasSecurityDomainReloadable(String securityDomain) {
|
| super(securityDomain);
|
| }
|
| public JaasSecurityDomainReloadable(String securityDomain,
CallbackHandler handler){
|
| super(securityDomain, handler);
|
| }
|
|
|
| @Override
|
| public void reloadKeyAndTrustStore() throws Exception {
|
| super.reloadKeyAndTrustStore();
|
| //if keystores reloaded successfully, reload them in socket
factory
|
| socketFactory.reload();
|
| }
|
|
|
| //Socket factory, where we want to reload keystores
|
| private JBossReloadableSocketFactory socketFactory;
|
| public void setSocketFactory(JBossReloadableSocketFactory
socketFactory) {
|
| this.socketFactory = socketFactory;
|
| }
|
|
|
|
|
| }
|
|
in this class I added method setSocketFactory to post SocketFactory to
SecurityDomain, and changed method reloadKeyAndTrustStore. Now it executes
SessionFactories method reload() to reload keystores in SSLContext.
org.jboss.net.ssl.JBossReloadableSocketFactory
| package org.jboss.net.ssl;
|
|
|
| import java.io.IOException;
|
| import java.net.InetAddress;
|
| import java.net.ServerSocket;
|
| import java.security.KeyManagementException;
|
| import java.security.SecureRandom;
|
|
|
| import javax.naming.InitialContext;
|
| import javax.naming.NamingException;
|
| import javax.net.ssl.KeyManagerFactory;
|
| import javax.net.ssl.SSLContext;
|
| import javax.net.ssl.TrustManagerFactory;
|
|
|
| import org.jboss.security.SecurityDomain;
|
| import org.jboss.security.plugins.JaasSecurityDomainReloadable;
|
|
|
| public class JBossReloadableSocketFactory extends JBossSocketFactory {
|
|
|
| @Override
|
| public void setSecurityDomainName(String jndiName) throws
NamingException, IOException {
|
| super.setSecurityDomainName(jndiName);
|
|
|
| //We can'n get parents securityDomain, cause it's private. Get
it from JNDI.
|
| InitialContext iniCtx = new InitialContext();
|
| SecurityDomain securityDomain = (SecurityDomain)
iniCtx.lookup(jndiName);
|
|
|
| //If we use reloadable domain, set socket factory (when mbeans
reloadKeyAndTrustStore method invokes, we reload keystores in factory)
|
| if (securityDomain instanceof JaasSecurityDomainReloadable) {
|
| ((JaasSecurityDomainReloadable)
securityDomain).setSocketFactory(this);
|
| }
|
| }
|
|
|
|
|
| //Changed init() method from JSSESocketFactory (we can't override cause
it is default)
|
| static String defaultProtocol = "TLS";
|
| static String defaultKeystoreType = "JKS";
|
| private SSLContext context = null;
|
| void initSsl() throws IOException {
|
| try {
|
| String clientAuthStr = (String)
attributes.get("clientauth");
|
| if("true".equalsIgnoreCase(clientAuthStr) ||
|
| "yes".equalsIgnoreCase(clientAuthStr)) {
|
| requireClientAuth = true;
|
| } else if("want".equalsIgnoreCase(clientAuthStr)) {
|
| wantClientAuth = true;
|
| }
|
|
|
| String protocol = (String) attributes.get("protocol");
|
| if (protocol == null) {
|
| protocol = defaultProtocol;
|
| }
|
|
|
| String algorithm = (String) attributes.get("algorithm");
|
| if (algorithm == null) {
|
| algorithm =
KeyManagerFactory.getDefaultAlgorithm();;
|
| }
|
|
|
| String keystoreType = (String)
attributes.get("keystoreType");
|
| if (keystoreType == null) {
|
| keystoreType = defaultKeystoreType;
|
| }
|
|
|
| String trustAlgorithm =
(String)attributes.get("truststoreAlgorithm");
|
| if( trustAlgorithm == null ) {
|
| trustAlgorithm =
TrustManagerFactory.getDefaultAlgorithm();
|
| }
|
|
|
| //Changes - we use only one SSLContext. If it is not
null use old (just load new keystores in init method)
|
| if (context==null) context =
SSLContext.getInstance(protocol);
|
| context.init(getKeyManagers(keystoreType, algorithm,
(String) attributes.get("keyAlias")),
|
| getTrustManagers(keystoreType, trustAlgorithm),
|
| new SecureRandom());
|
| sslProxy = context.getServerSocketFactory();
|
|
|
| String requestedCiphers =
(String)attributes.get("ciphers");
|
| enabledCiphers = getEnabledCiphers(requestedCiphers,
sslProxy.getSupportedCipherSuites());
|
|
|
| //Set initialized = true to avoid execution of init()
method from JSSESocketFactory
|
| initialized = true;
|
| } catch(Exception e) {
|
| if( e instanceof IOException ) throw (IOException)e;
|
| throw new IOException (e.getMessage());
|
| }
|
| }
|
|
|
| public void reload() throws KeyManagementException, Exception {
|
| initSsl();
|
| }
|
|
|
| //Updated methods createSocket (use initSsl() instead of init())
|
| @Override
|
| public ServerSocket createSocket(int port) throws IOException {
|
| if(!initialized) initSsl();
|
| return super.createSocket(port);
|
| }
|
| @Override
|
| public ServerSocket createSocket(int port, int backlog) throws
IOException {
|
| if(!initialized) initSsl();
|
| return super.createSocket(port, backlog);
|
| }
|
| @Override
|
| public ServerSocket createSocket(int port, int backlog, InetAddress
ifAddress) throws IOException {
|
| if(!initialized) initSsl();
|
| return super.createSocket(port, backlog, ifAddress);
|
| }
|
| }
|
|
here I created methods initSsl() and reload(), overrode 3 createSocket methods
(to use my initSsl instead of default init) and remembered SSLContext, using by
our sockets (to update keystores in it)
I have packed these classes in jar and put it to my
[path-to-jboss-default]/deploy/jboss-web.deployer (JBoss AS 4.2.3).
Now configuration:
SSL connector in [path-to-jboss-default]/deploy/jboss-web.deployer/server.xml
| <Connector port="443" address="${jboss.bind.address}"
| protocol="HTTP/1.1" SSLEnabled="true"
| maxThreads="100" strategy="ms" maxHttpHeaderSize="8192"
| emptySessionPath="true"
| scheme="https" secure="true" clientAuth="true"
| securityDomain="java:/jaas/portal-ssl"
|
SSLImplementation="org.jboss.net.ssl.JBossReloadableImplementation"
| sslProtocol="TLS" />
|
SecurityDomain mbean in
[path-to-jboss-default]/deploy/jboss-web.deployer/META-INF/jboss-service.xml
| <mbean code="org.jboss.security.plugins.JaasSecurityDomainReloadable"
| name="jboss.security:service=JaasSecurityDomain,domain=portal-ssl">
| <depends>jboss.security:service=JaasSecurityManager</depends>
| <constructor>
| <arg type="java.lang.String" value="portal-ssl" />
| </constructor>
|
| <attribute
name="ManagerServiceName">jboss.security:service=JaasSecurityManager</attribute>
| <attribute name="KeyStoreURL">D:/server.keystore</attribute>
| <attribute name="KeyStorePass">server</attribute>
| <attribute name="TrustStoreURL">D:/trusted.keystore</attribute>
| <attribute name="TrustStorePass">trusted</attribute>
| </mbean>
|
And finally, I use mbeans reloadKeyAndTrustStore method invocation from
previous post. You may also invoke this method from jmx-console.
Hope this post will help someone )))
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4189909#4189909
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4189909
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user