You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2019/05/01 01:20:10 UTC
[qpid-broker-j] branch master updated: QPID-8301: [Broker-J] Expose
information about keystore certificate details
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
The following commit(s) were added to refs/heads/master by this push:
new 1b5f061 QPID-8301: [Broker-J] Expose information about keystore certificate details
1b5f061 is described below
commit 1b5f0614b849cb1149b420728cb44597465dae8d
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Fri Apr 26 23:47:17 2019 +0100
QPID-8301: [Broker-J] Expose information about keystore certificate details
This closes #26
---
.../org/apache/qpid/server/model/KeyStore.java | 7 +++
.../qpid/server/security/AbstractKeyStore.java | 21 ++++++++
.../AutoGeneratedSelfSignedKeyStoreImpl.java | 8 +++
.../qpid/server/security/FileKeyStoreImpl.java | 61 +++++++++++++++++++---
.../qpid/server/security/FileTrustStoreImpl.java | 12 +----
.../qpid/server/security/NonJavaKeyStoreImpl.java | 13 ++++-
.../transport/network/security/ssl/SSLUtil.java | 17 ++++++
.../java/resources/js/qpid/management/KeyStore.js | 18 ++++++-
.../src/main/java/resources/showStore.html | 3 ++
9 files changed, 141 insertions(+), 19 deletions(-)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java b/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java
index b48a248..0d96b3d 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java
@@ -21,8 +21,12 @@
package org.apache.qpid.server.model;
import java.security.GeneralSecurityException;
+import java.util.List;
+
import javax.net.ssl.KeyManager;
+import org.apache.qpid.server.security.CertificateDetails;
+
@ManagedObject( defaultType = "FileKeyStore" )
public interface KeyStore<X extends KeyStore<X>> extends ConfiguredObject<X>
{
@@ -46,4 +50,7 @@ public interface KeyStore<X extends KeyStore<X>> extends ConfiguredObject<X>
int getCertificateExpiryCheckFrequency();
KeyManager[] getKeyManagers() throws GeneralSecurityException;
+
+ @DerivedAttribute(description = "List of details about the certificates like validity dates, SANs, issuer and subject names, etc.")
+ List<CertificateDetails> getCertificateDetails();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java b/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java
index c970c82..1df12c9 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java
@@ -20,13 +20,18 @@
*/
package org.apache.qpid.server.security;
+import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -196,4 +201,20 @@ public abstract class AbstractKeyStore<X extends AbstractKeyStore<X>>
}
return checkFrequency;
}
+
+ @Override
+ public List<CertificateDetails> getCertificateDetails()
+ {
+ Collection<Certificate> certificates = getCertificates();
+ if (!certificates.isEmpty())
+ {
+ return certificates.stream()
+ .filter(cert -> cert instanceof X509Certificate)
+ .map(x509cert -> new CertificateDetailsImpl((X509Certificate) x509cert))
+ .collect(Collectors.toList());
+ }
+ return Collections.emptyList();
+ }
+
+ protected abstract Collection<Certificate> getCertificates();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
index 648f9fd..f5feecf 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
@@ -37,6 +37,7 @@ 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;
@@ -45,6 +46,7 @@ import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Calendar;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
@@ -313,6 +315,12 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
}
}
+ @Override
+ protected Collection<Certificate> getCertificates()
+ {
+ return Collections.singleton(_certificate);
+ }
+
private void generateKeyManagers()
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
index 50e9560..7f7408f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
@@ -30,6 +30,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
@@ -79,6 +80,8 @@ public class FileKeyStoreImpl extends AbstractKeyStore<FileKeyStoreImpl> impleme
@ManagedAttributeField
private String _password;
+ private volatile Collection<Certificate> _certificates;
+
static
{
Handler.register();
@@ -108,6 +111,40 @@ public class FileKeyStoreImpl extends AbstractKeyStore<FileKeyStoreImpl> impleme
}
@Override
+ protected void onOpen()
+ {
+ super.onOpen();
+ initialize();
+ }
+
+ @Override
+ protected void changeAttributes(final Map<String, Object> attributes)
+ {
+ super.changeAttributes(attributes);
+ if (attributes.containsKey(STORE_URL)
+ || attributes.containsKey(PASSWORD)
+ || attributes.containsKey(KEY_STORE_TYPE)
+ || attributes.containsKey(KEY_MANAGER_FACTORY_ALGORITHM))
+ {
+ initialize();
+ }
+ }
+
+ private void initialize()
+ {
+ Collection<Certificate> result;
+ try
+ {
+ result = Collections.unmodifiableCollection(SSLUtil.getCertificates(getInitializedKeyStore(this)));
+ }
+ catch (GeneralSecurityException | IOException e)
+ {
+ result = Collections.emptyList();
+ }
+ _certificates = result;
+ }
+
+ @Override
protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
{
super.validateChange(proxyForValidation, changedAttributes);
@@ -128,10 +165,7 @@ public class FileKeyStoreImpl extends AbstractKeyStore<FileKeyStoreImpl> impleme
final String loggableStoreUrl = StringUtil.elideDataUrl(fileKeyStore.getStoreUrl());
try
{
- URL url = getUrlFromString(fileKeyStore.getStoreUrl());
- String password = fileKeyStore.getPassword();
- String keyStoreType = fileKeyStore.getKeyStoreType();
- java.security.KeyStore keyStore = SSLUtil.getInitializedKeyStore(url, password, keyStoreType);
+ java.security.KeyStore keyStore = getInitializedKeyStore(fileKeyStore);
final String certAlias = fileKeyStore.getCertificateAlias();
if (certAlias != null)
@@ -190,6 +224,15 @@ public class FileKeyStoreImpl extends AbstractKeyStore<FileKeyStoreImpl> impleme
checkCertificateExpiry();
}
+ private java.security.KeyStore getInitializedKeyStore(final FileKeyStore<?> fileKeyStore)
+ throws GeneralSecurityException, IOException
+ {
+ URL url = getUrlFromString(fileKeyStore.getStoreUrl());
+ String password = fileKeyStore.getPassword();
+ String keyStoreType = fileKeyStore.getKeyStoreType();
+ return SSLUtil.getInitializedKeyStore(url, password, keyStoreType);
+ }
+
@Override
public String getStoreUrl()
{
@@ -319,8 +362,7 @@ public class FileKeyStoreImpl extends AbstractKeyStore<FileKeyStoreImpl> impleme
try
{
- URL url = getUrlFromString(_storeUrl);
- final java.security.KeyStore ks = SSLUtil.getInitializedKeyStore(url, getPassword(), _keyStoreType);
+ final java.security.KeyStore ks = getInitializedKeyStore(this);
char[] keyStoreCharPassword = getPassword() == null ? null : getPassword().toCharArray();
@@ -352,6 +394,13 @@ public class FileKeyStoreImpl extends AbstractKeyStore<FileKeyStoreImpl> impleme
}
+ @Override
+ protected Collection<Certificate> getCertificates()
+ {
+ final Collection<Certificate> certificates = _certificates;
+ return certificates == null ? Collections.emptyList() : certificates;
+ }
+
private boolean containsPrivateKey(final java.security.KeyStore keyStore) throws KeyStoreException
{
final Enumeration<String> aliasesEnum = keyStore.aliases();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
index d6a4925..c503801 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
@@ -349,17 +349,7 @@ public class FileTrustStoreImpl extends AbstractTrustStore<FileTrustStoreImpl> i
private Certificate[] createCertificates(final KeyStore ts) throws KeyStoreException
{
- final Collection<Certificate> certificates = new ArrayList<>();
-
- Enumeration<String> aliases = ts.aliases();
- while (aliases.hasMoreElements())
- {
- String alias = aliases.nextElement();
- if (ts.isCertificateEntry(alias))
- {
- certificates.add(ts.getCertificate(alias));
- }
- }
+ final Collection<Certificate> certificates = SSLUtil.getCertificates(ts);
return certificates.toArray(new Certificate[certificates.size()]);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java
index c8a4670..3a92a6c 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java
@@ -29,9 +29,12 @@ import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.SecureRandom;
+import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -82,6 +85,7 @@ public class NonJavaKeyStoreImpl extends AbstractKeyStore<NonJavaKeyStoreImpl> i
}
private volatile X509Certificate _certificate;
+ private volatile Collection<Certificate> _certificates;
@ManagedObjectFactoryConstructor
public NonJavaKeyStoreImpl(final Map<String, Object> attributes, Broker<?> broker)
@@ -212,9 +216,9 @@ public class NonJavaKeyStoreImpl extends AbstractKeyStore<NonJavaKeyStoreImpl> i
{
PrivateKey privateKey = SSLUtil.readPrivateKey(getUrlFromString(_privateKeyUrl));
X509Certificate[] certs = SSLUtil.readCertificates(getUrlFromString(_certificateUrl));
+ List<X509Certificate> allCerts = new ArrayList<>(Arrays.asList(certs));
if(_intermediateCertificateUrl != null)
{
- List<X509Certificate> allCerts = new ArrayList<>(Arrays.asList(certs));
allCerts.addAll(Arrays.asList(SSLUtil.readCertificates(getUrlFromString(_intermediateCertificateUrl))));
certs = allCerts.toArray(new X509Certificate[allCerts.size()]);
}
@@ -233,6 +237,7 @@ public class NonJavaKeyStoreImpl extends AbstractKeyStore<NonJavaKeyStoreImpl> i
kmf.init(inMemoryKeyStore, chars);
_keyManagers = kmf.getKeyManagers();
_certificate = certs[0];
+ _certificates = Collections.unmodifiableCollection(allCerts);
}
}
@@ -294,4 +299,10 @@ public class NonJavaKeyStoreImpl extends AbstractKeyStore<NonJavaKeyStoreImpl> i
return url;
}
+ @Override
+ protected Collection<Certificate> getCertificates()
+ {
+ final Collection<Certificate> certificates = _certificates;
+ return certificates == null ? Collections.emptyList() : certificates;
+ }
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java b/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java
index edb753f..0ffab92 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java
@@ -39,6 +39,7 @@ import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyStore;
+import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
@@ -55,6 +56,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
+import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -1035,6 +1037,21 @@ public class SSLUtil
}
+ public static Collection<Certificate> getCertificates(final KeyStore ks) throws KeyStoreException
+ {
+ List<Certificate> certificates = new ArrayList<>();
+ Enumeration<String> aliases = ks.aliases();
+ while (aliases.hasMoreElements())
+ {
+ String alias = aliases.nextElement();
+ if (ks.isCertificateEntry(alias))
+ {
+ certificates.add(ks.getCertificate(alias));
+ }
+ }
+ return certificates;
+ }
+
public interface KeyCertPair
{
PrivateKey getPrivateKey();
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
index 41a8fd9..97987e7 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
@@ -30,8 +30,10 @@ define(["dojo/dom",
"qpid/common/formatter",
"qpid/management/addStore",
"dojo/text!showStore.html",
+ "qpid/management/store/CertificateGridWidget",
"dojo/domReady!"],
- function (dom, parser, query, connect, registry, entities, properties, updater, util, formatter, addStore, template)
+ function (dom, parser, query, connect, registry, entities, properties, updater, util, formatter, addStore, template,
+ CertificateGridWidget)
{
function KeyStore(kwArgs)
@@ -84,6 +86,13 @@ define(["dojo/dom",
addStore.show(data, that.keyStoreUpdater.keyStoreData);
}, util.xhrErrorHandler);
});
+ var gridNode = query(".managedCertificatesGrid", contentPane.containerNode)[0];
+ that.certificatesGrid = new CertificateGridWidget({
+ management: that.management,
+ modelObj: that.modelObj
+ }, gridNode);
+ that.certificatesGrid.enableCertificateControls(false);
+ that.certificatesGrid.startup();
});
};
@@ -91,6 +100,11 @@ define(["dojo/dom",
KeyStore.prototype.close = function ()
{
updater.remove(this.keyStoreUpdater);
+ if (this.certificatesGrid)
+ {
+ this.certificatesGrid.destroy();
+ }
+
};
function KeyStoreUpdater(tabObject)
@@ -149,6 +163,8 @@ define(["dojo/dom",
callback();
}
+ that.tabObject.certificatesGrid.update(data.certificateDetails);
+
if (that.details)
{
that.details.update(that.keyStoreData);
diff --git a/broker-plugins/management-http/src/main/java/resources/showStore.html b/broker-plugins/management-http/src/main/java/resources/showStore.html
index e564726..5a0946d 100644
--- a/broker-plugins/management-http/src/main/java/resources/showStore.html
+++ b/broker-plugins/management-http/src/main/java/resources/showStore.html
@@ -36,6 +36,9 @@
</div>
<div class="clear">
</div>
+ <div class="clear">
+ <div class="managedCertificatesGrid"></div>
+ </div>
</div>
<div class="dijitDialogPaneActionBar">
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org