Author: rgodfrey Date: Sat Nov 21 22:25:52 2015 New Revision: 1715586 URL: http://svn.apache.org/viewvc?rev=1715586&view=rev Log: QPID-6876 : Provide a mechanism to extract the certificate of an auto generated self signed key
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStore.java qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/autogeneratedselfsigned/show.js qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/add.html qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/show.html Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStore.java URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStore.java?rev=1715586&r1=1715585&r2=1715586&view=diff ============================================================================== --- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStore.java (original) +++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStore.java Sat Nov 21 22:25:52 2015 @@ -20,11 +20,16 @@ */ package org.apache.qpid.server.security; +import java.util.Collection; + +import org.apache.qpid.server.logging.LogRecord; +import org.apache.qpid.server.model.Content; import org.apache.qpid.server.model.DerivedAttribute; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.ManagedAttribute; import org.apache.qpid.server.model.ManagedObject; import org.apache.qpid.server.model.ManagedOperation; +import org.apache.qpid.server.model.Param; @ManagedObject( category = false, type = "AutoGeneratedSelfSigned" ) public interface AutoGeneratedSelfSignedKeyStore<X extends AutoGeneratedSelfSignedKeyStore<X>> extends KeyStore<X> @@ -51,4 +56,12 @@ public interface AutoGeneratedSelfSigned @ManagedOperation void regenerateCertificate(); + + @ManagedOperation(nonModifying = true, description = "Extract a Java KeyStore containing the certificate for the autogenerated key. The KeyStore can be used as a trust store by a JAva client connecting to the broker") + Content getClientTrustStore(@Param(name="password", defaultValue = "", description = "The password to use to secure the keystore (by default the empt string is used).") String password); + + @ManagedOperation(nonModifying = true, description = "Extract a PEM file containing the certificate for the autogenerated key.") + Content getCertificate(); + + } Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java?rev=1715586&r1=1715585&r2=1715586&view=diff ============================================================================== --- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java (original) +++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java Sat Nov 21 22:25:52 2015 @@ -22,6 +22,9 @@ package org.apache.qpid.server.security; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -31,9 +34,12 @@ import java.net.NetworkInterface; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.SecureRandom; +import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -50,6 +56,7 @@ import java.util.Set; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManagerFactory; import javax.xml.bind.DatatypeConverter; import com.google.common.util.concurrent.Futures; @@ -60,10 +67,13 @@ import org.apache.qpid.server.logging.Ev import org.apache.qpid.server.logging.messages.KeyStoreMessages; import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Content; +import org.apache.qpid.server.model.CustomRestHeaders; import org.apache.qpid.server.model.IntegrityViolationException; import org.apache.qpid.server.model.ManagedAttributeField; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.RestContentHeader; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.transport.network.security.ssl.SSLUtil; @@ -411,4 +421,128 @@ public class AutoGeneratedSelfSignedKeyS generatePrivateKeyAndCertificate(); saveDerivedAttributesIfNecessary(); } + + @Override + public Content getClientTrustStore(String password) + { + + try + { + KeyStore inMemoryKeyStore = + KeyStore.getInstance(KeyStore.getDefaultType()); + + inMemoryKeyStore.load(null, null); + inMemoryKeyStore.setCertificateEntry(getName(), _certificate); + + return new TrustStoreContent(inMemoryKeyStore, getName(), password == null ? new char[0] : password.toCharArray()); + } + catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException e) + { + throw new IllegalArgumentException(e); + } + } + + + @Override + public Content getCertificate() + { + try + { + return new CertificateContent(_certificate, getName()); + } + catch (CertificateEncodingException e) + { + throw new IllegalArgumentException("Cannot decode encode the certificate"); + } + + } + + private static class TrustStoreContent implements Content, CustomRestHeaders + { + private final KeyStore _keyStore; + private final char[] _password; + private final String _disposition; + + public TrustStoreContent(final KeyStore inMemoryKeyStore, + final String name, final char[] password) + { + _keyStore = inMemoryKeyStore; + _password = password; + _disposition = "attachment; filename=\"" + name + ".jks\""; + } + + @Override + public void write(final OutputStream outputStream) throws IOException + { + try + { + _keyStore.store(outputStream, _password); + } + catch (KeyStoreException | NoSuchAlgorithmException | CertificateException e) + { + throw new IllegalArgumentException(e); + } + } + + @RestContentHeader("Content-Type") + public String getContentType() + { + return "application/octet-stream"; + } + + @RestContentHeader("Content-Disposition") + public String getContentDisposition() + { + return _disposition; + } + + } + + private static class CertificateContent implements Content, CustomRestHeaders + { + + private final String _disposition; + private final String _certString; + + public CertificateContent(final X509Certificate certificate, final String name) + throws CertificateEncodingException + { + _disposition = "attachment; filename=\"" + name + ".pem\""; + StringBuffer certStringBuffer = new StringBuffer("-----BEGIN CERTIFICATE-----\n"); + String cert = DatatypeConverter.printBase64Binary(certificate.getEncoded()); + int offset = 0; + while(cert.length()-offset > 64) + { + certStringBuffer.append(cert.substring(offset, offset+64)); + offset+=64; + certStringBuffer.append("\n"); + } + certStringBuffer.append(cert.substring(offset)); + certStringBuffer.append("\n-----END CERTIFICATE-----\n"); + _certString = certStringBuffer.toString(); + } + + @Override + public void write(final OutputStream outputStream) throws IOException + { + Writer w = new OutputStreamWriter(outputStream); + w.write(_certString); + w.flush(); + } + + @RestContentHeader("Content-Type") + public String getContentType() + { + return "text/plain"; + } + + @RestContentHeader("Content-Disposition") + public String getContentDisposition() + { + return _disposition; + } + + } + + } Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/autogeneratedselfsigned/show.js URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/autogeneratedselfsigned/show.js?rev=1715586&r1=1715585&r2=1715586&view=diff ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/autogeneratedselfsigned/show.js (original) +++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/autogeneratedselfsigned/show.js Sat Nov 21 22:25:52 2015 @@ -17,26 +17,64 @@ * under the License. */ -define(["qpid/common/util", "dojo/domReady!"], - function (util) +define(["qpid/common/util", + "dojo/query", + "dijit/registry", + "dojo/_base/connect", + "dojo/_base/event", + "dojo/domReady!"], + function (util, query, registry, connect, event) { function AutoGeneratedSelfSignedKeyStoreProvider(data) { this.fields = []; + this.management = data.parent.management; + this.modelObj = data.parent.modelObj; var attributes = data.parent.management.metadata.getMetaData("KeyStore", "AutoGeneratedSelfSigned").attributes; for(var name in attributes) { this.fields.push(name); } - util.buildUI(data.containerNode, data.parent, "store/autogeneratedselfsigned/show.html", this.fields, this); + var that = this; + + util.buildUI(data.containerNode, data.parent, "store/autogeneratedselfsigned/show.html", this.fields, this, function() { + var getCertificateButton = query(".getCertificateButton", data.containerNode)[0]; + var getCertificateWidget = registry.byNode(getCertificateButton); + connect.connect(getCertificateWidget, "onClick", + function (evt) { + event.stop(evt); + that.getCertificate(); + }); + var getClientTrustStoreButton = query(".getClientTrustStoreButton", data.containerNode)[0]; + var getClientTrustStoreWidget = registry.byNode(getClientTrustStoreButton); + connect.connect(getClientTrustStoreWidget, "onClick", + function (evt) { + event.stop(evt); + that.getClientTrustStore(); + }); + }); } AutoGeneratedSelfSignedKeyStoreProvider.prototype.update = function(data) + { + util.updateUI(data, this.fields, this); + }; + + AutoGeneratedSelfSignedKeyStoreProvider.prototype.getCertificate = function() { - util.updateUI(data, this.fields, this); - } + var modelObj = this.modelObj; + this.management.download({ parent: modelObj, name: "getCertificate", type: modelObj.type}) + }; + + + AutoGeneratedSelfSignedKeyStoreProvider.prototype.getClientTrustStore = function() + { + var modelObj = this.modelObj; + this.management.download({ parent: modelObj, name: "getClientTrustStore", type: modelObj.type}) + }; + - return AutoGeneratedSelfSignedKeyStoreProvider; + return AutoGeneratedSelfSignedKeyStoreProvider; } ); Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/add.html URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/add.html?rev=1715586&r1=1715585&r2=1715586&view=diff ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/add.html (original) +++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/add.html Sat Nov 21 22:25:52 2015 @@ -46,7 +46,7 @@ </div> </div> <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell clear">Signature algorithm:</div> + <div class="formLabel-labelCell tableContainer-labelCell clear">Key Length:</div> <div class="formLabel-controlCell tableContainer-valueCell"> <input type="text" id="addStore.keyLength" data-dojo-type="dijit/form/ValidationTextBox" @@ -58,7 +58,7 @@ </div> </div> <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell clear">Signature algorithm:</div> + <div class="formLabel-labelCell tableContainer-labelCell clear">Duration:</div> <div class="formLabel-controlCell tableContainer-valueCell"> <input type="text" id="addStore.durationInMonths" data-dojo-type="dijit/form/ValidationTextBox" Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/show.html URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/show.html?rev=1715586&r1=1715585&r2=1715586&view=diff ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/show.html (original) +++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/autogeneratedselfsigned/show.html Sat Nov 21 22:25:52 2015 @@ -35,5 +35,9 @@ <div><span class="durationInMonths" ></span></div> </div> <div class="clear"></div> + <div class="dijitDialogPaneActionBar"> + <button data-dojo-type="dijit.form.Button" class="getCertificateButton" type="button">Download Certificate</button> + <button data-dojo-type="dijit.form.Button" class="getClientTrustStoreButton" type="button">Download Client Trust Store</button> + </div> </div> --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org