You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kw...@apache.org on 2017/01/08 21:41:55 UTC

svn commit: r1777915 - in /qpid/java/trunk: broker-core/src/main/java/org/apache/qpid/server/security/ broker-core/src/test/java/org/apache/qpid/server/security/ broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecif...

Author: kwall
Date: Sun Jan  8 21:41:55 2017
New Revision: 1777915

URL: http://svn.apache.org/viewvc?rev=1777915&view=rev
Log:
QPID-7311: [Java Broker] [SiteSpecificTrustStore] Timeout the downloading of the certificate if the server peer does not respond within a configurable time period

* Added unit tests
* Exposed the refresh certificate button in the UI

Added:
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SiteSpecificTrustStoreTest.java
Modified:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStore.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js
    qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStore.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStore.java?rev=1777915&r1=1777914&r2=1777915&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStore.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStore.java Sun Jan  8 21:41:55 2017
@@ -24,6 +24,7 @@ import java.util.Date;
 
 import org.apache.qpid.server.model.DerivedAttribute;
 import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedContextDefault;
 import org.apache.qpid.server.model.ManagedObject;
 import org.apache.qpid.server.model.ManagedOperation;
 import org.apache.qpid.server.model.TrustStore;
@@ -34,6 +35,14 @@ public interface SiteSpecificTrustStore<
 {
     String CERTIFICATE = "certificate";
 
+    String TRUST_STORE_SITE_SPECIFIC_CONNECT_TIMEOUT = "qpid.trustStore.siteSpecific.connectTimeout";
+    @ManagedContextDefault(name = TRUST_STORE_SITE_SPECIFIC_CONNECT_TIMEOUT)
+    int DEFAULT_TRUST_STORE_SITE_SPECIFIC_CONNECT_TIMEOUT = 60000;
+
+    String TRUST_STORE_SITE_SPECIFIC_READ_TIMEOUT = "qpid.trustStore.siteSpecific.readTimeout";
+    @ManagedContextDefault(name = TRUST_STORE_SITE_SPECIFIC_READ_TIMEOUT)
+    int DEFAULT_TRUST_STORE_SITE_SPECIFIC_READ_TIMEOUT = 60000;
+
     @ManagedAttribute(immutable = true, description = "The URL from which to obtain the trusted certificate. Example: https://example.com or https://example.com:8443")
     String getSiteUrl();
 

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java?rev=1777915&r1=1777914&r2=1777915&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java Sun Jan  8 21:41:55 2017
@@ -22,6 +22,7 @@ package org.apache.qpid.server.security;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.GeneralSecurityException;
@@ -35,6 +36,9 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
@@ -44,13 +48,16 @@ import javax.net.ssl.TrustManagerFactory
 import javax.net.ssl.X509TrustManager;
 import javax.xml.bind.DatatypeConverter;
 
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.SettableFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.configuration.updater.Task;
 import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.logging.messages.TrustStoreMessages;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
@@ -90,7 +97,8 @@ public class SiteSpecificTrustStoreImpl
 
     private volatile TrustManager[] _trustManagers = new TrustManager[0];
 
-
+    private volatile int _connectTimeout;
+    private volatile int _readTimeout;
     private volatile X509Certificate _x509Certificate;
 
     @ManagedObjectFactoryConstructor
@@ -109,6 +117,14 @@ public class SiteSpecificTrustStoreImpl
     }
 
     @Override
+    protected void onOpen()
+    {
+        super.onOpen();
+        _connectTimeout = getContextValue(Integer.class, TRUST_STORE_SITE_SPECIFIC_CONNECT_TIMEOUT);
+        _readTimeout = getContextValue(Integer.class, TRUST_STORE_SITE_SPECIFIC_READ_TIMEOUT);
+    }
+
+    @Override
     protected void postResolve()
     {
         super.postResolve();
@@ -222,84 +238,117 @@ public class SiteSpecificTrustStoreImpl
     @StateTransition(currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE)
     protected ListenableFuture<Void> doActivate()
     {
+        final SettableFuture<Void> result = SettableFuture.create();
         if(_x509Certificate == null)
         {
-            downloadCertificate();
-        }
-        if(_x509Certificate != null)
-        {
-            generateTrustManagers();
+            final String currentCertificate = getCertificate();
+
+            final ListenableFuture<X509Certificate> certFuture = downloadCertificate(getSiteUrl());
+            addFutureCallback(certFuture, new FutureCallback<X509Certificate>()
+            {
+                @Override
+                public void onSuccess(final X509Certificate cert)
+                {
+                    _x509Certificate = cert;
+                    attributeSet(CERTIFICATE, currentCertificate, _x509Certificate);
+                    generateTrustAndSetState(result);
+                }
+
+                @Override
+                public void onFailure(final Throwable t)
+                {
+                    _trustManagers = new TrustManager[0];
+                    setState(State.ERRORED);
+                    result.setException(t);
 
-            setState(State.ACTIVE);
+                }
+            }, getTaskExecutor());
+            return result;
         }
         else
         {
-            setState(State.ERRORED);
+            generateTrustAndSetState(result);
         }
-        return Futures.immediateFuture(null);
+        return result;
     }
 
-    private void downloadCertificate()
+    private void generateTrustAndSetState(final SettableFuture<Void> result)
     {
+        State state = State.ERRORED;
         try
         {
+            generateTrustManagers();
+            state = State.ACTIVE;
+            result.set(null);
+        }
+        catch(IllegalConfigurationException e)
+        {
+            result.setException(e);
+        }
+        finally
+        {
+            setState(state);
+            result.set(null);
+        }
+    }
 
-            URL url = new URL(getSiteUrl());
-            SSLContext sslContext = SSLUtil.tryGetSSLContext();
-            sslContext.init(new KeyManager[0], new TrustManager[] {new AlwaysTrustManager()}, null);
-
-            final int port = url.getPort() == -1 ? url.getDefaultPort() : url.getPort();
-            try(SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket(url.getHost(), port))
+    private ListenableFuture<X509Certificate> downloadCertificate(final String url)
+    {
+        final ListeningExecutorService workerService = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(
+                getThreadFactory("download-certificate-worker-" + getName())));
+        try
+        {
+            return workerService.submit(new Callable<X509Certificate>()
             {
-                socket.startHandshake();
-                final Certificate[] certificateChain = socket.getSession().getPeerCertificates();
-                if (certificateChain != null && certificateChain.length != 0 && certificateChain[0] instanceof X509Certificate)
+
+                @Override
+                public X509Certificate call()
                 {
-                    runTask(new Task<Void, RuntimeException>()
+                    try
                     {
-                        @Override
-                        public Void execute() throws RuntimeException
-                        {
-                            _x509Certificate = (X509Certificate) certificateChain[0];
-
-                            final String certificate = getCertificate();
-                            attributeSet(CERTIFICATE, certificate, certificate);
-                            return null;
-                        }
-
-                        @Override
-                        public String getObject()
-                        {
-                            return SiteSpecificTrustStoreImpl.this.getName();
-                        }
-
-                        @Override
-                        public String getAction()
+                        final URL siteUrl = new URL(url);
+                        final int port = siteUrl.getPort() == -1 ? siteUrl.getDefaultPort() : siteUrl.getPort();
+                        SSLContext sslContext = SSLUtil.tryGetSSLContext();
+                        sslContext.init(new KeyManager[0], new TrustManager[]{new AlwaysTrustManager()}, null);
+                        try (SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket())
                         {
-                            return "downloadCertificate";
+                            socket.setSoTimeout(_readTimeout);
+                            socket.connect(new InetSocketAddress(siteUrl.getHost(), port), _connectTimeout);
+                            socket.startHandshake();
+                            final Certificate[] certificateChain = socket.getSession().getPeerCertificates();
+                            if (certificateChain != null
+                                && certificateChain.length != 0
+                                && certificateChain[0] instanceof X509Certificate)
+                            {
+                                final X509Certificate x509Certificate = (X509Certificate) certificateChain[0];
+                                LOGGER.debug("Successfully downloaded X509Certificate with DN {} certificate from {}",
+                                             x509Certificate.getSubjectDN(), url);
+                                return x509Certificate;
+                            }
+                            else
+                            {
+                                throw new IllegalConfigurationException(String.format("TLS handshake for '%s' from '%s' "
+                                                                                      + "did not provide a X509Certificate",
+                                                                                     getName(),
+                                                                                     url));
+                            }
                         }
-
-                        @Override
-                        public String getArguments()
-                        {
-                            return null;
-                        }
-                    });
-                }
-                else
-                {
-                    LOGGER.info("No valid certificates available from " + getSiteUrl());
+                    }
+                    catch (IOException | GeneralSecurityException e)
+                    {
+                        throw new IllegalConfigurationException(String.format("Unable to get certificate for '%s' from '%s'",
+                                                                              getName(),
+                                                                              url), e);
+                    }
                 }
-            }
-
+            });
         }
-        catch (GeneralSecurityException | IOException e)
+        finally
         {
-            LOGGER.info("Unable to download certificate from " + getSiteUrl(), e);
+            workerService.shutdown();
         }
     }
 
-
     private void decodeCertificate()
     {
         byte[] certificateEncoded = Strings.decodeBase64((String) getActualAttributes().get(CERTIFICATE));
@@ -361,13 +410,13 @@ public class SiteSpecificTrustStoreImpl
         return _x509Certificate == null ? null : _x509Certificate.getIssuerX500Principal().toString();
     }
 
-
     @Override
     public String getCertificateSubject()
     {
         return _x509Certificate == null ? null : _x509Certificate.getSubjectX500Principal().toString();
     }
 
+
     @Override
     public String getCertificateSerialNumber()
     {
@@ -386,7 +435,6 @@ public class SiteSpecificTrustStoreImpl
         return _x509Certificate == null ? null : _x509Certificate.getNotBefore();
     }
 
-
     @Override
     public Date getCertificateValidUntilDate()
     {
@@ -396,7 +444,26 @@ public class SiteSpecificTrustStoreImpl
     @Override
     public void refreshCertificate()
     {
-        downloadCertificate();
+        logOperation("refreshCertificate");
+        final String currentCertificate = getCertificate();
+        final ListenableFuture<X509Certificate> certFuture = downloadCertificate(getSiteUrl());
+        final ListenableFuture<Void> modelFuture = doAfter(certFuture, new CallableWithArgument<ListenableFuture<Void>, X509Certificate>()
+        {
+            @Override
+            public ListenableFuture<Void> call(final X509Certificate cert) throws Exception
+            {
+                _x509Certificate = cert;
+                attributeSet(CERTIFICATE, currentCertificate, _x509Certificate);
+                return Futures.immediateFuture(null);
+            }
+        });
+        doSync(modelFuture);
+    }
+
+    @Override
+    protected void logOperation(final String operation)
+    {
+        _broker.getEventLogger().message(TrustStoreMessages.OPERATION(operation));
     }
 
     private static class AlwaysTrustManager implements X509TrustManager
@@ -407,7 +474,6 @@ public class SiteSpecificTrustStoreImpl
         {
 
         }
-
         @Override
         public void checkServerTrusted(final X509Certificate[] chain, final String authType)
                 throws CertificateException
@@ -422,10 +488,22 @@ public class SiteSpecificTrustStoreImpl
         }
     }
 
-
-    @Override
-    protected void logOperation(final String operation)
+    private ThreadFactory getThreadFactory(final String name)
     {
-        _broker.getEventLogger().message(TrustStoreMessages.OPERATION(operation));
+        return new ThreadFactory()
+        {
+            @Override
+            public Thread newThread(final Runnable r)
+            {
+
+                final Thread thread = Executors.defaultThreadFactory().newThread(r);
+                if (!thread.isDaemon())
+                {
+                    thread.setDaemon(true);
+                }
+                thread.setName(name);
+                return thread;
+            }
+        };
     }
 }

Added: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SiteSpecificTrustStoreTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SiteSpecificTrustStoreTest.java?rev=1777915&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SiteSpecificTrustStoreTest.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/security/SiteSpecificTrustStoreTest.java Sun Jan  8 21:41:55 2017
@@ -0,0 +1,277 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security;
+
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocketFactory;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObjectFactory;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestSSLConstants;
+
+public class SiteSpecificTrustStoreTest extends QpidTestCase
+{
+    private static final String EXPECTED_SUBJECT = "CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown";
+    private static final String EXPECTED_ISSUER = "CN=MyRootCA, O=ACME, ST=Ontario, C=CA";
+    private final Broker<?> _broker = mock(Broker.class);
+    private final TaskExecutor _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+    private final Model _model = BrokerModel.getInstance();
+    private final ConfiguredObjectFactory _factory = _model.getObjectFactory();
+    private TestPeer _testPeer;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        setTestSystemProperty(SiteSpecificTrustStore.TRUST_STORE_SITE_SPECIFIC_CONNECT_TIMEOUT, "100");
+        setTestSystemProperty(SiteSpecificTrustStore.TRUST_STORE_SITE_SPECIFIC_READ_TIMEOUT, "100");
+
+        when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+        when(_broker.getChildExecutor()).thenReturn(_taskExecutor);
+        when(_broker.getModel()).thenReturn(_model);
+        when(_broker.getEventLogger()).thenReturn(new EventLogger());
+        when(((Broker) _broker).getCategoryClass()).thenReturn(Broker.class);
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            super.tearDown();
+        }
+        finally
+        {
+            if (_testPeer != null)
+            {
+                _testPeer.close();
+            }
+        }
+    }
+
+    public void testMalformedSiteUrl() throws Exception
+    {
+        Map<String,Object> attributes = new HashMap<>();
+        attributes.put(SiteSpecificTrustStore.NAME, "mySiteSpecificTrustStore");
+        attributes.put(SiteSpecificTrustStore.TYPE, "SiteSpecificTrustStore");
+        attributes.put("siteUrl", "notaurl:541");
+
+        try
+        {
+            _factory.create(TrustStore.class, attributes, _broker);
+            fail("Exception not thrown");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            // PASS
+        }
+    }
+
+    public void testSiteUrlDoesNotSupplyHostPort() throws Exception
+    {
+        Map<String,Object> attributes = new HashMap<>();
+        attributes.put(SiteSpecificTrustStore.NAME, "mySiteSpecificTrustStore");
+        attributes.put(SiteSpecificTrustStore.TYPE, "SiteSpecificTrustStore");
+        attributes.put("siteUrl", "file:/not/a/host");
+
+        try
+        {
+            _factory.create(TrustStore.class, attributes, _broker);
+            fail("Exception not thrown");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            // PASS
+        }
+    }
+
+    public void testUnresponsiveSite() throws Exception
+    {
+        _testPeer = new TestPeer();
+        _testPeer.setAccept(false);
+        int listeningPort = _testPeer.start();
+
+        Map<String, Object> attributes = getTrustStoreAttributes(listeningPort);
+
+        try
+        {
+            _factory.create(TrustStore.class, attributes, _broker);
+            fail("Exception not thrown");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            // PASS
+        }
+    }
+
+    public void testValidSiteUrl() throws Exception
+    {
+        _testPeer = new TestPeer();
+        int listeningPort = _testPeer.start();
+
+        Map<String, Object> attributes = getTrustStoreAttributes(listeningPort);
+
+        final SiteSpecificTrustStore trustStore =
+                (SiteSpecificTrustStore) _factory.create(TrustStore.class, attributes, _broker);
+
+        assertEquals("Unexpected certificate subject", EXPECTED_SUBJECT, trustStore.getCertificateSubject());
+        assertEquals("Unexpected certificate issuer", EXPECTED_ISSUER, trustStore.getCertificateIssuer());
+    }
+
+    public void testRefreshCertificate() throws Exception
+    {
+        _testPeer = new TestPeer();
+        int listeningPort = _testPeer.start();
+
+        Map<String, Object> attributes = getTrustStoreAttributes(listeningPort);
+
+        final SiteSpecificTrustStore trustStore =
+                (SiteSpecificTrustStore) _factory.create(TrustStore.class, attributes, _broker);
+
+        assertEquals("Unexpected certificate subject", EXPECTED_SUBJECT, trustStore.getCertificateSubject());
+        assertEquals("Unexpected certificate issuer", EXPECTED_ISSUER, trustStore.getCertificateIssuer());
+
+        trustStore.refreshCertificate();
+
+        assertEquals("Unexpected certificate subject", EXPECTED_SUBJECT, trustStore.getCertificateSubject());
+        assertEquals("Unexpected certificate issuer", EXPECTED_ISSUER, trustStore.getCertificateIssuer());
+    }
+
+    private Map<String, Object> getTrustStoreAttributes(final int listeningPort)
+    {
+        Map<String,Object> attributes = new HashMap<>();
+        attributes.put(SiteSpecificTrustStore.NAME, "mySiteSpecificTrustStore");
+        attributes.put(SiteSpecificTrustStore.TYPE, "SiteSpecificTrustStore");
+        attributes.put("siteUrl", String.format("https://localhost:%d", listeningPort));
+        return attributes;
+    }
+
+    private class TestPeer implements Closeable
+    {
+        private final ExecutorService _socketAcceptExecutor = Executors.newSingleThreadExecutor();
+        private ServerSocket _serverSocket;
+        private final AtomicBoolean _shutdown = new AtomicBoolean();
+        private boolean _accept = true;
+
+        public void setAccept(final boolean accept)
+        {
+            _accept = accept;
+        }
+
+        public int start() throws Exception
+        {
+            _serverSocket = createTestSSLServerSocket();
+            if (_accept)
+            {
+                _socketAcceptExecutor.execute(new AcceptingRunnable());
+            }
+
+            return _serverSocket.getLocalPort();
+        }
+
+        @Override
+        public void close() throws IOException
+        {
+            _shutdown.set(true);
+            try
+            {
+                if (_serverSocket != null)
+                {
+                    _serverSocket.close();
+                }
+            }
+            finally
+            {
+                _socketAcceptExecutor.shutdown();
+            }
+        }
+
+        private ServerSocket createTestSSLServerSocket() throws Exception
+        {
+            char[] keyPassword = TestSSLConstants.KEYSTORE_PASSWORD.toCharArray();
+            try(InputStream inputStream = getClass().getResourceAsStream("/java_broker_keystore.jks"))
+            {
+                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+                KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+                keyStore.load(inputStream, keyPassword);
+                keyManagerFactory.init(keyStore, keyPassword);
+                KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
+                SSLContext sslContext = SSLContext.getInstance("SSL");
+                sslContext.init(keyManagers, null, new SecureRandom());
+                SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();
+                ServerSocket serverSocket = socketFactory.createServerSocket(0);
+                serverSocket.setSoTimeout(100);
+
+                return serverSocket;
+            }
+        }
+
+        private class AcceptingRunnable implements Runnable
+        {
+            @Override
+            public void run()
+            {
+                do
+                {
+                    try (Socket sock = _serverSocket.accept())
+                    {
+                        final InputStream inputStream = sock.getInputStream();
+                        while (inputStream.read() != -1)
+                        {
+                        }
+                    }
+                    catch (IOException e)
+                    {
+                        // Ignore
+                    }
+                }
+                while (!_shutdown.get());
+            }
+        }
+    }
+}
\ No newline at end of file

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js?rev=1777915&r1=1777914&r2=1777915&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js Sun Jan  8 21:41:55 2017
@@ -17,8 +17,8 @@
  * under the License.
  */
 
-define(["dojo/query", "qpid/common/util", "dojox/grid/DataGrid", "qpid/common/UpdatableStore", "dojo/domReady!"],
-    function (query, util, DataGrid, UpdatableStore)
+define(["dojo/_base/lang", "dojo/query", "dijit/registry", "dojo/_base/connect", "dojo/_base/event", "qpid/common/util", "dojox/grid/DataGrid", "qpid/common/UpdatableStore", "dojo/domReady!"],
+    function (lang, query, registry, connect, event, util, DataGrid, UpdatableStore)
     {
 
         function SiteSpecificTrustStore(data)
@@ -26,6 +26,7 @@ define(["dojo/query", "qpid/common/util"
             var that = this;
             this.fields = [];
             this.management = data.parent.management;
+            this.modelObj = data.parent.modelObj;
             this.dateTimeFormatter = function (value)
             {
                 return value ? that.management.userPreferences.formatDateTime(value, {
@@ -38,13 +39,33 @@ define(["dojo/query", "qpid/common/util"
             {
                 this.fields.push(name);
             }
-            util.buildUI(data.containerNode, data.parent, "store/sitespecifictruststore/show.html", this.fields, this);
+            util.buildUI(data.containerNode, data.parent, "store/sitespecifictruststore/show.html", this.fields, this,
+                function ()
+                {
+                    var refreshCertificateButton = query(".refreshCertificateButton", data.containerNode)[0];
+                    var refreshCertificateWidget = registry.byNode(refreshCertificateButton);
+                    connect.connect(refreshCertificateWidget, "onClick", function (evt)
+                    {
+                        event.stop(evt);
+                        that.refreshCertificate();
+                    });
+                });
         }
 
         SiteSpecificTrustStore.prototype.update = function (data)
         {
             util.updateUI(data, this.fields, this, {datetime: this.dateTimeFormatter});
-        }
+        };
+
+        SiteSpecificTrustStore.prototype.refreshCertificate = function ()
+        {
+            var modelObj = this.modelObj;
+            this.management.update({
+                parent: modelObj,
+                name: "refreshCertificate",
+                type: modelObj.type
+            }, {}).then(lang.hitch(this, this.update));
+        };
 
         return SiteSpecificTrustStore;
     });

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html?rev=1777915&r1=1777914&r2=1777915&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html Sun Jan  8 21:41:55 2017
@@ -49,5 +49,8 @@
 
 
     <div class="clear"></div>
+    <div class="dijitDialogPaneActionBar">
+        <button data-dojo-type="dijit.form.Button" class="refreshCertificateButton" type="button">Refresh Certificate</button>
+    </div>
 </div>
 



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org