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 2020/09/02 19:32:47 UTC
[qpid-broker-j] branch 7.1.x updated (54d2a9f -> 627ce9d)
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a change to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git.
from 54d2a9f [maven-release-plugin] prepare for next development iteration
new 55bab0d NO-JIRA: Fix Kerberos tests
new 6ed3dd8 NO-JIRA: remove links etc from the documentation, missed from removal in QPID 7487
new aa93436 QPID-8460: [Broker-j] Do not expose private information to exception message (#55)
new 1c04466 QPID-8458: [Broker-J] Removed RewriteServlet from HTTP management
new 351f449 QPID-8459: [Broker-J] AnonymousInteractiveAuthenticator uses request.getRequestDispatcher().forward() instead of parsing request URL
new ee2293f QPID-8461: [Broker-J] Repace Random with SecureRandom
new ec885c0 QPID-8455: [Broker-J] Add allow/deny list alternatives for existing black/whilte list attributes and context variables
new d547af8 QPID-8454:[Broker-J] Add Prometheus integration
new f7f5145 QPID-8454:[Broker-J] Update documentation
new 627ce9d QPID-8454:[Broker-J] Add missing license
The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../dependency-verification/DEPENDENCIES_REFERENCE | 6 +
.../server/configuration/CommonProperties.java | 5 +
.../server/model/AbstractConfiguredObject.java | 15 +
.../java/org/apache/qpid/server/model/Broker.java | 80 +++--
.../qpid/server/model/BrokerAttributeInjector.java | 20 +-
.../org/apache/qpid/server/model/BrokerLogger.java | 4 +-
.../server/model/ConfiguredAutomatedAttribute.java | 3 +-
.../model/ConfiguredObjectInjectedStatistic.java | 20 +-
.../model/ConfiguredObjectMethodStatistic.java | 12 +
.../server/model/ConfiguredObjectStatistic.java | 4 +
.../org/apache/qpid/server/model/Connection.java | 14 +-
.../org/apache/qpid/server/model/Consumer.java | 4 +-
.../org/apache/qpid/server/model/Exchange.java | 10 +-
.../apache/qpid/server/model/ManagedStatistic.java | 2 +
.../java/org/apache/qpid/server/model/Port.java | 17 +
.../java/org/apache/qpid/server/model/Queue.java | 36 +--
.../java/org/apache/qpid/server/model/Session.java | 2 +-
.../qpid/server/model/VirtualHostLogger.java | 4 +-
.../qpid/server/model/port/AbstractPort.java | 32 +-
.../apache/qpid/server/model/port/AmqpPort.java | 12 +-
...ObjectRegistration.java => ContentFactory.java} | 9 +-
.../AbstractScramAuthenticationManager.java | 24 +-
.../manager/SimpleLDAPAuthenticationManager.java | 16 +
.../SimpleLDAPAuthenticationManagerImpl.java | 32 +-
.../oauth2/OAuth2AuthenticationProvider.java | 18 ++
.../oauth2/OAuth2AuthenticationProviderImpl.java | 32 +-
.../crammd5/CramMd5Base64HashedNegotiator.java | 25 +-
.../sasl/crammd5/CramMd5Base64HexNegotiator.java | 33 +-
...oudFoundryDashboardManagementGroupProvider.java | 14 +
...oundryDashboardManagementGroupProviderImpl.java | 37 ++-
.../apache/qpid/server/util/ConnectionBuilder.java | 24 ++
.../org/apache/qpid/server/util/StringUtil.java | 4 +-
.../java/org/apache/qpid/server/util/Strings.java | 24 +-
.../virtualhost/QueueManagingVirtualHost.java | 28 +-
.../qpid/server/model/port/AmqpPortImplTest.java | 87 +++++
.../hierarchy/InjectedAttributeTest.java | 16 +-
.../testmodels/hierarchy/TestAbstractCarImpl.java | 21 ++
.../hierarchy/TestAbstractEngineImpl.java | 7 +
.../hierarchy/TestAbstractInstrumentPanelImpl.java | 2 +
.../hierarchy/TestAbstractSensorImpl.java | 9 +
.../server/model/testmodels/hierarchy/TestCar.java | 14 +
.../model/testmodels/hierarchy/TestEngine.java | 6 +
.../model/testmodels/hierarchy/TestSensor.java | 5 +
.../hierarchy/TestTemperatureSensorImpl.java | 9 +
.../manager/KerberosAuthenticationManagerTest.java | 79 ++---
.../SimpleLDAPAuthenticationManagerTest.java | 86 ++++-
.../auth/manager/SpnegoAuthenticatorTest.java | 61 ++--
.../OAuth2AuthenticationProviderImplTest.java | 91 +++++-
.../qpid/server/test/EmbeddedKdcResource.java | 29 +-
.../apache/qpid/server/test/KerberosUtilities.java | 196 ++++++++++-
broker-core/src/test/resources/login.ibm.config | 51 +++
broker-plugins/management-http/pom.xml | 5 +
.../server/management/plugin/HttpManagement.java | 29 +-
.../plugin/HttpManagementConfiguration.java | 5 +
.../server/management/plugin/RewriteServlet.java | 55 ----
.../auth/AnonymousInteractiveAuthenticator.java | 88 +++--
.../auth/BasicAuthPreemptiveAuthenticator.java | 24 +-
.../auth/UsernamePasswordInteractiveLogin.java | 17 +-
.../management/plugin/servlet/ContentServlet.java | 95 ++++++
.../plugin/servlet/rest/AbstractServlet.java | 21 +-
.../plugin/servlet/rest/ApiDocsServlet.java | 64 ++--
.../pom.xml | 40 +--
.../IncludeDisabledStatisticPredicate.java | 27 +-
.../server/prometheus/IncludeMetricPredicate.java | 31 +-
.../prometheus/PrometheusContentFactory.java | 105 ++++++
.../qpid/server/prometheus/QpidCollector.java | 257 +++++++++++++++
.../prometheus/PrometheusContentFactoryTest.java | 176 ++++++++++
.../qpid/server/prometheus/QpidCollectorTest.java | 359 +++++++++++++++++++++
.../docbkx/Java-Broker-Initial-Configuration.xml | 11 +-
.../src/docbkx/Java-Broker-Management-Channels.xml | 1 +
.../channels/Java-Broker-Management-Metrics.xml | 49 +++
pom.xml | 20 ++
.../java/org/apache/qpid/test/utils/JvmVendor.java | 25 +-
.../org/apache/qpid/test/utils/UnitTestBase.java | 18 +-
.../PreemptiveAuthenticationTest.java | 4 +-
.../BrokerMetricsAuthenticationTest.java} | 35 +-
.../qpid/tests/http/metrics/BrokerMetricsTest.java | 100 ++++++
.../qpid/tests/http/metrics/TestMetricsHelper.java | 93 ++++++
.../tests/http/metrics/VirtualHostMetricsTest.java | 20 +-
.../qpid/systests/admin/SpawnBrokerAdmin.java | 26 +-
.../qpid/systests/admin/SpawnBrokerAdminTest.java | 16 +-
81 files changed, 2602 insertions(+), 605 deletions(-)
copy broker-core/src/main/java/org/apache/qpid/server/plugin/{ConfiguredObjectRegistration.java => ContentFactory.java} (81%)
create mode 100644 broker-core/src/test/resources/login.ibm.config
delete mode 100644 broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/RewriteServlet.java
create mode 100644 broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/ContentServlet.java
copy broker-plugins/{amqp-1-0-jdbc-store => prometheus-exporter}/pom.xml (68%)
copy broker-core/src/test/java/org/apache/qpid/server/store/MessageCounter.java => broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeDisabledStatisticPredicate.java (62%)
copy broker-core/src/test/java/org/apache/qpid/server/store/MessageCounter.java => broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeMetricPredicate.java (63%)
create mode 100644 broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/PrometheusContentFactory.java
create mode 100644 broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/QpidCollector.java
create mode 100644 broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/PrometheusContentFactoryTest.java
create mode 100644 broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/QpidCollectorTest.java
create mode 100644 doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml
copy systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/{query/QueryBrokerTest.java => metrics/BrokerMetricsAuthenticationTest.java} (51%)
create mode 100644 systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java
create mode 100644 systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/TestMetricsHelper.java
copy broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementUtilTest.java => systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/VirtualHostMetricsTest.java (57%)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 03/10: QPID-8460: [Broker-j] Do not expose private
information to exception message (#55)
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit aa934369a6313dd26b501ed50405c4c200bd346b
Author: vavrtom <cz...@tiscali.cz>
AuthorDate: Thu Aug 6 23:41:42 2020 +0200
QPID-8460: [Broker-j] Do not expose private information to exception message (#55)
Co-authored-by: Tomas Vavricka <to...@deutsche-boerse.com>
(cherry picked from commit 734fb3994f74ae066b587d3563322f10e47e6727)
---
.../server/model/ConfiguredAutomatedAttribute.java | 3 +-
.../AbstractScramAuthenticationManager.java | 24 +++++++++-------
.../crammd5/CramMd5Base64HashedNegotiator.java | 25 +++++++---------
.../sasl/crammd5/CramMd5Base64HexNegotiator.java | 33 +++++++++-------------
.../java/org/apache/qpid/server/util/Strings.java | 24 +++++++++++++---
.../auth/BasicAuthPreemptiveAuthenticator.java | 24 ++++++++--------
6 files changed, 70 insertions(+), 63 deletions(-)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java
index a5b3598..d98a96f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java
@@ -255,7 +255,8 @@ public class ConfiguredAutomatedAttribute<C extends ConfiguredObject, T> extend
Type returnType = getGetter().getGenericReturnType();
String simpleName = returnType instanceof Class ? ((Class) returnType).getSimpleName() : returnType.toString();
- throw new IllegalArgumentException("Cannot convert '" + value
+ throw new IllegalArgumentException("Cannot convert '" +
+ (isSecure() ? AbstractConfiguredObject.SECURED_STRING_VALUE : value)
+ "' into a " + simpleName
+ " for attribute " + getName()
+ " (" + iae.getMessage() + ")", iae);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
index e8bb81e..abc6cbf 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
@@ -159,17 +159,18 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram
final String[] passwordFields = user.getPassword().split(",");
if (passwordFields.length == 2)
{
- byte[] saltedPassword = Strings.decodeBase64(passwordFields[PasswordField.SALTED_PASSWORD.ordinal()]);
+ final byte[] saltedPassword = Strings.decodePrivateBase64(passwordFields[PasswordField.SALTED_PASSWORD.ordinal()],
+ "user '" + user.getName() + "' salted password");
try
{
- byte[] clientKey = computeHmac(saltedPassword, "Client Key");
+ final byte[] clientKey = computeHmac(saltedPassword, "Client Key");
- byte[] storedKey = MessageDigest.getInstance(getDigestName()).digest(clientKey);
+ final byte[] storedKey = MessageDigest.getInstance(getDigestName()).digest(clientKey);
- byte[] serverKey = computeHmac(saltedPassword, "Server Key");
+ final byte[] serverKey = computeHmac(saltedPassword, "Server Key");
- String password = passwordFields[PasswordField.SALT.ordinal()] + ","
+ final String password = passwordFields[PasswordField.SALT.ordinal()] + ","
+ "," // remove previously insecure salted password field
+ Base64.getEncoder().encodeToString(storedKey) + ","
+ Base64.getEncoder().encodeToString(serverKey) + ","
@@ -183,7 +184,7 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram
}
else if (passwordFields.length == 4)
{
- String password = passwordFields[PasswordField.SALT.ordinal()] + ","
+ final String password = passwordFields[PasswordField.SALT.ordinal()] + ","
+ "," // remove previously insecure salted password field
+ passwordFields[PasswordField.STORED_KEY.ordinal()] + ","
+ passwordFields[PasswordField.SERVER_KEY.ordinal()] + ","
@@ -296,7 +297,7 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram
@Override
public SaltAndPasswordKeys getSaltAndPasswordKeys(final String username)
{
- ManagedUser user = getUser(username);
+ final ManagedUser user = getUser(username);
final byte[] salt;
final byte[] storedKey;
@@ -318,9 +319,12 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram
{
updateStoredPasswordFormatIfNecessary(user);
final String[] passwordFields = user.getPassword().split(",");
- salt = Strings.decodeBase64(passwordFields[PasswordField.SALT.ordinal()]);
- storedKey = Strings.decodeBase64(passwordFields[PasswordField.STORED_KEY.ordinal()]);
- serverKey = Strings.decodeBase64(passwordFields[PasswordField.SERVER_KEY.ordinal()]);
+ salt = Strings.decodePrivateBase64(passwordFields[PasswordField.SALT.ordinal()],
+ "user '" + user.getName() + "' salt");
+ storedKey = Strings.decodePrivateBase64(passwordFields[PasswordField.STORED_KEY.ordinal()],
+ "user '" + user.getName() + "' stored key");
+ serverKey = Strings.decodePrivateBase64(passwordFields[PasswordField.SERVER_KEY.ordinal()],
+ "user '" + user.getName() + "' server key");
iterationCount = Integer.parseInt(passwordFields[PasswordField.ITERATION_COUNT.ordinal()]);
exception = null;
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java
index 3d3a551..91c9daa 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HashedNegotiator.java
@@ -27,21 +27,16 @@ import org.apache.qpid.server.util.Strings;
public class CramMd5Base64HashedNegotiator extends AbstractCramMd5Negotiator
{
public static final String MECHANISM = "CRAM-MD5-HASHED";
- private static final PasswordTransformer BASE64_PASSWORD_TRANSFORMER =
- new PasswordTransformer()
- {
- @Override
- public char[] transform(final char[] passwordData)
- {
- byte[] passwordBytes = Strings.decodeBase64(new String(passwordData));
- char[] password = new char[passwordBytes.length];
- for (int i = 0; i < passwordBytes.length; i++)
- {
- password[i] = (char) passwordBytes[i];
- }
- return password;
- }
- };
+ private static final PasswordTransformer BASE64_PASSWORD_TRANSFORMER = passwordData ->
+ {
+ final byte[] passwordBytes = Strings.decodePrivateBase64(new String(passwordData), "CRAM MD5 hashed password");
+ final char[] password = new char[passwordBytes.length];
+ for (int i = 0; i < passwordBytes.length; i++)
+ {
+ password[i] = (char) passwordBytes[i];
+ }
+ return password;
+ };
public CramMd5Base64HashedNegotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
final String localFQDN,
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java
index 22fc95c..edcbff5 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CramMd5Base64HexNegotiator.java
@@ -27,26 +27,19 @@ import org.apache.qpid.server.util.Strings;
public class CramMd5Base64HexNegotiator extends AbstractCramMd5Negotiator
{
public static final String MECHANISM = "CRAM-MD5-HEX";
- private static final PasswordTransformer BASE64_HEX_PASSWORD_TRANSFORMER =
- new PasswordTransformer()
- {
- private final char[] HEX_CHARACTERS =
- {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
- @Override
- public char[] transform(final char[] passwordData)
- {
- byte[] passwordBytes = Strings.decodeBase64(new String(passwordData));
- char[] password = new char[passwordBytes.length * 2];
-
- for (int i = 0; i < passwordBytes.length; i++)
- {
- password[2 * i] = HEX_CHARACTERS[(((int) passwordBytes[i]) & 0xf0) >> 4];
- password[(2 * i) + 1] = HEX_CHARACTERS[(((int) passwordBytes[i]) & 0x0f)];
- }
- return password;
- }
- };
+ private static final char[] HEX_CHARACTERS =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ private static final PasswordTransformer BASE64_HEX_PASSWORD_TRANSFORMER = passwordData ->
+ {
+ final byte[] passwordBytes = Strings.decodePrivateBase64(new String(passwordData), "CRAM MD5 hex password");
+ final char[] password = new char[passwordBytes.length * 2];
+ for (int i = 0; i < passwordBytes.length; i++)
+ {
+ password[2 * i] = HEX_CHARACTERS[(((int) passwordBytes[i]) & 0xf0) >> 4];
+ password[(2 * i) + 1] = HEX_CHARACTERS[(((int) passwordBytes[i]) & 0x0f)];
+ }
+ return password;
+ };
public CramMd5Base64HexNegotiator(final PasswordCredentialManagingAuthenticationProvider<?> authenticationProvider,
final String localFQDN,
diff --git a/broker-core/src/main/java/org/apache/qpid/server/util/Strings.java b/broker-core/src/main/java/org/apache/qpid/server/util/Strings.java
index 0e468fb..b62fe7f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/util/Strings.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/util/Strings.java
@@ -21,7 +21,6 @@
package org.apache.qpid.server.util;
import java.io.UnsupportedEncodingException;
-import java.io.Writer;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Base64;
@@ -129,17 +128,34 @@ public final class Strings
return resolver;
}
+ public static byte[] decodePrivateBase64(String base64String, String description)
+ {
+ if (isInvalidBase64String(base64String))
+ {
+ // do not add base64String to exception message as it can contain private data
+ throw new IllegalArgumentException("Cannot convert " + description +
+ " string to a byte[] - it does not appear to be base64 data");
+ }
+
+ return Base64.getDecoder().decode(base64String);
+ }
+
public static byte[] decodeBase64(String base64String)
{
- base64String = base64String.replaceAll("\\s","");
- if(!base64String.matches("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"))
+ if (isInvalidBase64String(base64String))
{
- throw new IllegalArgumentException("Cannot convert string '"+ base64String+ "'to a byte[] - it does not appear to be base64 data");
+ throw new IllegalArgumentException("Cannot convert string '" + base64String +
+ "' to a byte[] - it does not appear to be base64 data");
}
return Base64.getDecoder().decode(base64String);
}
+ private static boolean isInvalidBase64String(String base64String)
+ {
+ return !base64String.replaceAll("\\s", "").matches("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$");
+ }
+
public static interface Resolver
{
String resolve(String variable, final Resolver resolver);
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java
index 76353f8..c79d4bd 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java
@@ -45,16 +45,16 @@ public class BasicAuthPreemptiveAuthenticator implements HttpRequestPreemptiveAu
@Override
public Subject attemptAuthentication(final HttpServletRequest request, final HttpManagementConfiguration managementConfiguration)
{
- String header = request.getHeader("Authorization");
+ final String header = request.getHeader("Authorization");
final Port<?> port = managementConfiguration.getPort(request);
final AuthenticationProvider<?> authenticationProvider = managementConfiguration.getAuthenticationProvider(request);
- SubjectCreator subjectCreator = port.getSubjectCreator(request.isSecure(), request.getServerName());
+ final SubjectCreator subjectCreator = port.getSubjectCreator(request.isSecure(), request.getServerName());
if (header != null && authenticationProvider instanceof UsernamePasswordAuthenticationProvider)
{
- UsernamePasswordAuthenticationProvider<?> namePasswdAuthProvider = (UsernamePasswordAuthenticationProvider<?>)authenticationProvider;
+ final UsernamePasswordAuthenticationProvider<?> namePasswdAuthProvider = (UsernamePasswordAuthenticationProvider<?>)authenticationProvider;
- String[] tokens = header.split("\\s");
+ final String[] tokens = header.split("\\s");
if (tokens.length >= 2 && "BASIC".equalsIgnoreCase(tokens[0]))
{
boolean isBasicAuthSupported = false;
@@ -68,19 +68,17 @@ public class BasicAuthPreemptiveAuthenticator implements HttpRequestPreemptiveAu
}
if (isBasicAuthSupported)
{
- String base64UsernameAndPassword = tokens[1];
- String[] credentials = (new String(Strings.decodeBase64(base64UsernameAndPassword),
- StandardCharsets.UTF_8)).split(":", 2);
+ final String base64UsernameAndPassword = tokens[1];
+ final String[] credentials = new String(Strings.decodePrivateBase64(base64UsernameAndPassword,
+ "basic authentication credentials"), StandardCharsets.UTF_8).split(":", 2);
if (credentials.length == 2)
{
- String username = credentials[0];
- String password = credentials[1];
- AuthenticationResult authenticationResult = namePasswdAuthProvider.authenticate(username, password);
- SubjectAuthenticationResult result = subjectCreator.createResultWithGroups(authenticationResult);
+ final String username = credentials[0];
+ final String password = credentials[1];
+ final AuthenticationResult authenticationResult = namePasswdAuthProvider.authenticate(username, password);
+ final SubjectAuthenticationResult result = subjectCreator.createResultWithGroups(authenticationResult);
return result.getSubject();
-
-
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 08/10: QPID-8454:[Broker-J] Add Prometheus
integration
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit d547af8d35306a22207d6ae25af3ff94cd7c6893
Author: Dedeepya T <de...@yahoo.co.in>
AuthorDate: Tue Aug 25 15:11:50 2020 +0100
QPID-8454:[Broker-J] Add Prometheus integration
(cherry picked from commit e9794802df6ee22bd3b9dc55faffc26d74459c71)
---
.../dependency-verification/DEPENDENCIES_REFERENCE | 6 +
.../java/org/apache/qpid/server/model/Broker.java | 80 +++--
.../qpid/server/model/BrokerAttributeInjector.java | 20 +-
.../org/apache/qpid/server/model/BrokerLogger.java | 4 +-
.../model/ConfiguredObjectInjectedStatistic.java | 20 +-
.../model/ConfiguredObjectMethodStatistic.java | 12 +
.../server/model/ConfiguredObjectStatistic.java | 4 +
.../org/apache/qpid/server/model/Connection.java | 14 +-
.../org/apache/qpid/server/model/Consumer.java | 4 +-
.../org/apache/qpid/server/model/Exchange.java | 10 +-
.../apache/qpid/server/model/ManagedStatistic.java | 2 +
.../java/org/apache/qpid/server/model/Queue.java | 36 +--
.../java/org/apache/qpid/server/model/Session.java | 2 +-
.../qpid/server/model/VirtualHostLogger.java | 4 +-
.../apache/qpid/server/model/port/AmqpPort.java | 12 +-
.../apache/qpid/server/plugin/ContentFactory.java} | 13 +-
.../virtualhost/QueueManagingVirtualHost.java | 28 +-
.../hierarchy/InjectedAttributeTest.java | 16 +-
.../testmodels/hierarchy/TestAbstractCarImpl.java | 21 ++
.../hierarchy/TestAbstractEngineImpl.java | 7 +
.../hierarchy/TestAbstractInstrumentPanelImpl.java | 2 +
.../hierarchy/TestAbstractSensorImpl.java | 9 +
.../server/model/testmodels/hierarchy/TestCar.java | 14 +
.../model/testmodels/hierarchy/TestEngine.java | 6 +
.../model/testmodels/hierarchy/TestSensor.java | 5 +
.../hierarchy/TestTemperatureSensorImpl.java | 9 +
broker-plugins/management-http/pom.xml | 5 +
.../server/management/plugin/HttpManagement.java | 18 ++
.../plugin/HttpManagementConfiguration.java | 5 +
.../management/plugin/servlet/ContentServlet.java | 95 ++++++
.../plugin/servlet/rest/AbstractServlet.java | 21 +-
broker-plugins/prometheus-exporter/pom.xml | 70 ++++
.../IncludeDisabledStatisticPredicate.java | 26 +-
.../server/prometheus/IncludeMetricPredicate.java | 26 +-
.../prometheus/PrometheusContentFactory.java | 105 ++++++
.../qpid/server/prometheus/QpidCollector.java | 257 +++++++++++++++
.../prometheus/PrometheusContentFactoryTest.java | 176 ++++++++++
.../qpid/server/prometheus/QpidCollectorTest.java | 359 +++++++++++++++++++++
.../src/docbkx/Java-Broker-Management-Channels.xml | 1 +
.../channels/Java-Broker-Management-Metrics.xml | 48 +++
pom.xml | 20 ++
.../metrics/BrokerMetricsAuthenticationTest.java | 52 +++
.../qpid/tests/http/metrics/BrokerMetricsTest.java | 80 +++++
.../qpid/tests/http/metrics/TestMetricsHelper.java | 93 ++++++
.../tests/http/metrics/VirtualHostMetricsTest.java | 25 +-
45 files changed, 1712 insertions(+), 130 deletions(-)
diff --git a/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE b/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE
index c50e39d..d92150c 100644
--- a/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE
+++ b/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE
@@ -27,6 +27,10 @@ Apache Qpid Broker-J Bundles
From: 'an unknown organization'
- Guava: Google Core Libraries for Java (https://github.com/google/guava/guava) com.google.guava:guava:bundle:27.0-jre
License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
+ - Prometheus Java Simpleclient (http://github.com/prometheus/client_java/simpleclient) io.prometheus:simpleclient:bundle:0.9.0
+ License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
+ - Prometheus Java Simpleclient Common (http://github.com/prometheus/client_java/simpleclient_common) io.prometheus:simpleclient_common:bundle:0.9.0
+ License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
- dgrid (http://webjars.org) org.webjars.bower:dgrid:jar:1.2.1
License: BSD 3-Clause (https://spdx.org/licenses/BSD 3-Clause#licenseText)
- dstore (http://webjars.org) org.webjars.bower:dstore:jar:1.1.2
@@ -111,6 +115,8 @@ From: 'The Apache Software Foundation' (https://www.apache.org/)
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Qpid Broker-J Memory Message Store Plug-in (http://qpid.apache.org/components/broker-plugins/qpid-broker-plugins-memory-store) org.apache.qpid:qpid-broker-plugins-memory-store:jar
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
+ - qpid-broker-plugins-prometheus-exporter (http://qpid.apache.org/components/broker-plugins/qpid-broker-plugins-prometheus-exporter) org.apache.qpid:qpid-broker-plugins-prometheus-exporter:jar
+ License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
- Apache Qpid Broker-J WebSocket Plug-in (http://qpid.apache.org/components/broker-plugins/qpid-broker-plugins-websocket) org.apache.qpid:qpid-broker-plugins-websocket:jar
License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
index 62e2519..24bdccb 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -189,36 +189,52 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL
String getModelVersion();
@SuppressWarnings("unused")
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Inbound",
- description = "Total size of all messages received by the Broker.")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE,
+ units = StatisticUnit.BYTES,
+ label = "Inbound",
+ description = "Total size of all messages received by the Broker.",
+ metricName = "inbound_bytes_count")
long getBytesIn();
@SuppressWarnings("unused")
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Outbound",
- description = "Total size of all messages delivered by the Broker.")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE,
+ units = StatisticUnit.BYTES,
+ label = "Outbound",
+ description = "Total size of all messages delivered by the Broker.",
+ metricName = "outbound_bytes_count")
long getBytesOut();
@SuppressWarnings("unused")
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Inbound",
- description = "Total number of messages received by the Broker.")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE,
+ units = StatisticUnit.MESSAGES,
+ label = "Inbound",
+ description = "Total number of messages received by the Broker.",
+ metricName = "inbound_messages_count")
long getMessagesIn();
@SuppressWarnings("unused")
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Outbound",
- description = "Total number of messages delivered by the Broker.")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE,
+ units = StatisticUnit.MESSAGES,
+ label = "Outbound",
+ description = "Total number of messages delivered by the Broker.",
+ metricName = "outbound_messages_count")
long getMessagesOut();
@SuppressWarnings("unused")
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES,
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE,
+ units = StatisticUnit.MESSAGES,
label = "Transacted Inbound",
- description = "Total number of messages delivered by the Broker within a transaction.")
+ description = "Total number of messages delivered by the Broker within a transaction.",
+ metricName = "inbound_transacted_messages_count")
long getTransactedMessagesIn();
@SuppressWarnings("unused")
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES,
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE,
+ units = StatisticUnit.MESSAGES,
label = "Transacted Outbound",
- description = "Total number of messages received by the Broker within a transaction.")
+ description = "Total number of messages received by the Broker within a transaction.",
+ metricName = "outbound_transacted_messages_count")
long getTransactedMessagesOut();
@ManagedOperation(nonModifying = true,
@@ -249,37 +265,44 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME,
- units = StatisticUnit.COUNT,
- label = "Live threads",
- description = "Number of live threads")
+ units = StatisticUnit.COUNT,
+ label = "Live threads",
+ description = "Number of live threads",
+ metricName = "live_threads_total",
+ metricDisabled = true)
int getNumberOfLiveThreads();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME,
- units = StatisticUnit.BYTES,
- label = "Used Heap Memory Size",
- description = "Size of used heap memory")
+ units = StatisticUnit.BYTES,
+ label = "Used Heap Memory Size",
+ description = "Size of used heap memory",
+ metricDisabled = true)
long getUsedHeapMemorySize();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME,
- units = StatisticUnit.BYTES,
- label = "Used Direct Memory Size",
- description = "Size of used direct memory")
+ units = StatisticUnit.BYTES,
+ label = "Used Direct Memory Size",
+ description = "Size of used direct memory",
+ metricDisabled = true)
long getUsedDirectMemorySize();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME,
- units = StatisticUnit.BYTES,
- label = "Direct Memory Total Capacity",
- description = "Total capacity of direct memory allocated for the Broker process")
+ units = StatisticUnit.BYTES,
+ label = "Direct Memory Total Capacity",
+ description = "Total capacity of direct memory allocated for the Broker process",
+ metricName = "direct_memory_capacity_bytes_total",
+ metricDisabled = true)
long getDirectMemoryTotalCapacity();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME,
- units = StatisticUnit.COUNT,
- label = "Number Of Object Pending Finalization",
- description = "Number of objects pending finalization")
+ units = StatisticUnit.COUNT,
+ label = "Number Of Object Pending Finalization",
+ description = "Number of objects pending finalization",
+ metricDisabled = true)
int getNumberOfObjectsPendingFinalization();
@SuppressWarnings("unused")
@@ -300,7 +323,8 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME,
units = StatisticUnit.BYTES,
label = "Maximum recorded size of inbound messages",
- description = "Maximum size of messages published into the Broker since start-up.")
+ description = "Maximum size of messages published into the Broker since start-up.",
+ metricName = "inbound_message_size_high_watermark")
long getInboundMessageSizeHighWatermark();
@ManagedOperation(nonModifying = true,
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerAttributeInjector.java b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerAttributeInjector.java
index 61be55f..a80a041 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerAttributeInjector.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerAttributeInjector.java
@@ -167,7 +167,9 @@ public class BrokerAttributeInjector implements ConfiguredObjectAttributeInjecto
_typeValidator,
StatisticUnit.BYTES,
StatisticType.POINT_IN_TIME,
- memoryPoolMXBean.getName() + " Memory Used");
+ memoryPoolMXBean.getName() + " Memory Used",
+ null,
+ true);
statistics.add(injectedStatistic);
}
catch (NoSuchMethodException e)
@@ -195,7 +197,9 @@ public class BrokerAttributeInjector implements ConfiguredObjectAttributeInjecto
StatisticUnit.COUNT,
StatisticType.CUMULATIVE,
garbageCollectorMXBean.getName()
- + " GC Collection Time");
+ + " GC Collection Time",
+ null,
+ true);
statistics.add(injectedStatistic);
}
catch (NoSuchMethodException e)
@@ -218,7 +222,9 @@ public class BrokerAttributeInjector implements ConfiguredObjectAttributeInjecto
StatisticUnit.COUNT,
StatisticType.CUMULATIVE,
garbageCollectorMXBean.getName()
- + " GC Collection Count");
+ + " GC Collection Count",
+ null,
+ true);
statistics.add(injectedStatistic);
}
catch (NoSuchMethodException e)
@@ -263,7 +269,9 @@ public class BrokerAttributeInjector implements ConfiguredObjectAttributeInjecto
StatisticUnit.TIME_DURATION,
StatisticType.CUMULATIVE,
_operatingSystemMXBeanClass.getName()
- + " Process CPU Time");
+ + " Process CPU Time",
+ "process_cpu_time_nanoseconds",
+ true);
statistics.add(injectedStatistic);
}
@@ -308,7 +316,9 @@ public class BrokerAttributeInjector implements ConfiguredObjectAttributeInjecto
StatisticUnit.COUNT,
StatisticType.POINT_IN_TIME,
_operatingSystemMXBean.getName()
- + " Process CPU Load");
+ + " Process CPU Load",
+ null,
+ true);
statistics.add(injectedStatistic);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerLogger.java b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerLogger.java
index 07e61cd..8c4ad5b 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerLogger.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerLogger.java
@@ -28,9 +28,9 @@ public interface BrokerLogger<X extends BrokerLogger<X>> extends ConfiguredObjec
void stopLogging();
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Errors")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Errors", metricName = "errors_count")
long getErrorCount();
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Warnings")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Warnings", metricName = "warnings_count")
long getWarnCount();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java
index 95c8507..f1d9c6b 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java
@@ -41,6 +41,8 @@ final public class ConfiguredObjectInjectedStatistic<C extends ConfiguredObject,
private final StatisticType _type;
private final String _label;
private final Object[] _staticParams;
+ private final String _metricName;
+ private final boolean _metricDisabled;
public ConfiguredObjectInjectedStatistic(final String name,
final Method method,
@@ -49,7 +51,9 @@ final public class ConfiguredObjectInjectedStatistic<C extends ConfiguredObject,
final TypeValidator typeValidator,
final StatisticUnit units,
final StatisticType type,
- final String label)
+ final String label,
+ final String metricName,
+ final boolean metricDisabled)
{
super(name,
(Class<T>) AttributeValueConverter.getTypeFromMethod(method), method.getGenericReturnType(), typeValidator);
@@ -57,6 +61,8 @@ final public class ConfiguredObjectInjectedStatistic<C extends ConfiguredObject,
_type = type;
_label = label;
_staticParams = staticParams == null ? new Object[0] : staticParams;
+ _metricName = metricName;
+ _metricDisabled = metricDisabled;
if(!(method.getParameterTypes().length == 1 + _staticParams.length
&& ConfiguredObject.class.isAssignableFrom(method.getParameterTypes()[0])
&& Modifier.isStatic(method.getModifiers())
@@ -147,4 +153,16 @@ final public class ConfiguredObjectInjectedStatistic<C extends ConfiguredObject,
}
}
+
+ @Override
+ public String getMetricName()
+ {
+ return _metricName;
+ }
+
+ @Override
+ public boolean isMetricDisabled()
+ {
+ return _metricDisabled;
+ }
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java
index 2cc2fe9..528d80e 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java
@@ -66,4 +66,16 @@ public final class ConfiguredObjectMethodStatistic<C extends ConfiguredObject, T
{
return _annotation.label();
}
+
+ @Override
+ public String getMetricName()
+ {
+ return _annotation.metricName();
+ }
+
+ @Override
+ public boolean isMetricDisabled()
+ {
+ return _annotation.metricDisabled();
+ }
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
index cc22d62..4585b42 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
@@ -29,4 +29,8 @@ public interface ConfiguredObjectStatistic<C extends ConfiguredObject, T extends
StatisticType getStatisticType();
String getLabel();
+
+ String getMetricName();
+
+ boolean isMetricDisabled();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java b/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
index 62cefc1..0638e53 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
@@ -117,24 +117,24 @@ public interface Connection<X extends Connection<X>> extends ConfiguredObject<X>
// See also QPID-7689: https://issues.apache.org/jira/browse/QPID-7689?focusedCommentId=16022923#comment-16022923
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Inbound",
- description = "Total size of all messages received by this connection.")
+ description = "Total size of all messages received by this connection.", metricName = "inbound_bytes_count")
long getBytesIn();
// currently this reports outbound message content size without header.
// See also QPID-7689: https://issues.apache.org/jira/browse/QPID-7689?focusedCommentId=16022923#comment-16022923
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Outbound",
- description = "Total size of all messages delivered by this connection.")
+ description = "Total size of all messages delivered by this connection.", metricName = "outbound_bytes_count")
long getBytesOut();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Inbound",
- description = "Total number of messages delivered by this connection.")
+ description = "Total number of messages delivered by this connection.", metricName = "inbound_messages_count")
long getMessagesIn();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Outbound",
- description = "Total number of messages received by this connection.")
+ description = "Total number of messages received by this connection.", metricName = "outbound_messages_count")
long getMessagesOut();
@SuppressWarnings("unused")
@@ -162,7 +162,7 @@ public interface Connection<X extends Connection<X>> extends ConfiguredObject<X>
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Sessions",
- description = "Current number of sessions belonging to this connection.")
+ description = "Current number of sessions belonging to this connection.", metricName = "sessions_total")
int getSessionCount();
@SuppressWarnings("unused")
@@ -188,12 +188,12 @@ public interface Connection<X extends Connection<X>> extends ConfiguredObject<X>
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Transacted Inbound",
- description = "Total number of messages delivered by this connection within a transaction.")
+ description = "Total number of messages delivered by this connection within a transaction.", metricName = "transacted_inbound_messages_count")
long getTransactedMessagesIn();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Transacted Outbound",
- description = "Total number of messages received by this connection within a transaction.")
+ description = "Total number of messages received by this connection within a transaction.", metricName = "transacted_outbound_messages_count")
long getTransactedMessagesOut();
//children
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java b/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
index 9db4b21..240d8a6 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
@@ -70,10 +70,10 @@ public interface Consumer<X extends Consumer<X,T>, T extends ConsumerTarget> ext
+ "consumers. Priority 2147483647 is the highest priority.")
int getPriority();
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Outbound")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Outbound", metricName = "outbound_bytes_count")
long getBytesOut();
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Outbound")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Outbound", metricName = "outbound_messages_count")
long getMessagesOut();
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.BYTES, label = "Prefetch")
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java b/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java
index 800f57c..5e2d68f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java
@@ -88,27 +88,27 @@ public interface Exchange<X extends Exchange<X>> extends ConfiguredObject<X>, Me
// Statistics
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Bindings",
- description = "Current number of bindings to this exchange.")
+ description = "Current number of bindings to this exchange.", metricName = "bindings_total")
long getBindingCount();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Dropped",
- description = "Total size of all unroutable messages dropped by this exchange.")
+ description = "Total size of all unroutable messages dropped by this exchange.", metricName = "dropped_bytes_count")
long getBytesDropped();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Inbound",
- description = "Total size of messages received by this exchange.")
+ description = "Total size of messages received by this exchange.", metricName = "inbound_bytes_count")
long getBytesIn();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Dropped",
- description = "Number of unroutable messages dropped by this exchange.")
+ description = "Number of unroutable messages dropped by this exchange.", metricName = "dropped_messages_count")
long getMessagesDropped();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Inbound",
- description = "Number of messages received by this exchange.")
+ description = "Number of messages received by this exchange.", metricName = "inbound_messages_count")
long getMessagesIn();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ManagedStatistic.java b/broker-core/src/main/java/org/apache/qpid/server/model/ManagedStatistic.java
index d9bb129..1bcd52e 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ManagedStatistic.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ManagedStatistic.java
@@ -33,4 +33,6 @@ public @interface ManagedStatistic
String label() default "";
StatisticUnit units();
StatisticType statisticType();
+ String metricName() default "";
+ boolean metricDisabled() default false;
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java b/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
index 3920a14..bfb7e16 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
@@ -370,17 +370,17 @@ public interface Queue<X extends Queue<X>> extends ConfiguredObject<X>,
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Bindings",
- description = "Current number of bindings to this queue.")
+ description = "Current number of bindings to this queue.", metricName = "bindings_total")
int getBindingCount();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Consumers",
- description = "Current number of consumers attached to this queue.")
+ description = "Current number of consumers attached to this queue.", metricName = "consumers_total")
int getConsumerCount();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Consumers with credit",
- description = "Current number of consumers attached to this queue with credit")
+ description = "Current number of consumers attached to this queue with credit", metricName = "consumers_with_credit_total")
int getConsumerCountWithCredit();
@SuppressWarnings("unused")
@@ -405,42 +405,42 @@ public interface Queue<X extends Queue<X>> extends ConfiguredObject<X>,
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.BYTES, label = "Queue Depth",
- description = "Current size of all messages enqueued by this queue.")
+ description = "Current size of all messages enqueued by this queue.", metricName = "depth_bytes_total")
long getQueueDepthBytes();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.MESSAGES, label = "Queue Depth",
- description = "Current number of messages enqueued by this queue.")
+ description = "Current number of messages enqueued by this queue.", metricName = "depth_messages_total")
int getQueueDepthMessages();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Delivered",
- description = "Total size of all messages delivered by this queue.")
+ description = "Total size of all messages delivered by this queue.", metricName = "dequeued_bytes_count")
long getTotalDequeuedBytes();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Delivered",
- description = "Total number of messages delivered by this queue.")
+ description = "Total number of messages delivered by this queue.", metricName = "dequeued_messages_count")
long getTotalDequeuedMessages();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Enqueued",
- description = "Total size of all messages received by this queue.")
+ description = "Total size of all messages received by this queue.", metricName = "enqueue_bytes_count")
long getTotalEnqueuedBytes();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Enqueued",
- description = "Total number of messages received by this queue.")
+ description = "Total number of messages received by this queue.", metricName = "enqueued_messages_count")
long getTotalEnqueuedMessages();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Expired",
- description = "Total size of all messages expired by message time-to-live on this queue.")
+ description = "Total size of all messages expired by message time-to-live on this queue.", metricName = "expired_bytes_count")
long getTotalExpiredBytes();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Expired",
- description = "Total number of messages expired by message time-to-live on this queue.")
+ description = "Total number of messages expired by message time-to-live on this queue.", metricName = "expired_messages_count")
long getTotalExpiredMessages();
@@ -466,37 +466,37 @@ public interface Queue<X extends Queue<X>> extends ConfiguredObject<X>,
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.BYTES, label = "Available HWM",
- description = "Maximum recorded size of available messages.")
+ description = "Maximum recorded size of available messages.", metricName = "available_bytes_high_water_mark")
long getAvailableBytesHighWatermark();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.MESSAGES, label = "Available HWM",
- description = "Maximum recorded number of available messages.")
+ description = "Maximum recorded number of available messages.", metricName = "available_messages_high_water_mark")
int getAvailableMessagesHighWatermark();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.BYTES, label = "Queue Depth HWM",
- description = "Maximum recorded size of enqueued messages.")
+ description = "Maximum recorded size of enqueued messages.", metricName = "depth_bytes_high_water_mark")
long getQueueDepthBytesHighWatermark();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.MESSAGES, label = "Queue Depth HWM",
- description = "Maximum recorded number of enqueued messages.")
+ description = "Maximum recorded number of enqueued messages.", metricName = "depth_messages_high_water_mark")
int getQueueDepthMessagesHighWatermark();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.TIME_DURATION, label = "Oldest Message",
- description = "Current age of oldest message on the queue.")
+ description = "Current age of oldest message on the queue.", metricName = "oldest_message_age_milliseconds")
long getOldestMessageAge();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Malformed",
- description = "Total size of enqueued malformed messages.")
+ description = "Total size of enqueued malformed messages.", metricName = "malformed_bytes_count")
long getTotalMalformedBytes();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Malformed",
- description = "Total number of enqueued malformed messages.")
+ description = "Total number of enqueued malformed messages.", metricName = "malformed_messages_count")
long getTotalMalformedMessages();
@ManagedOperation(description = "move messages from this queue to another", changesConfiguredObjectState = false)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Session.java b/broker-core/src/main/java/org/apache/qpid/server/model/Session.java
index af1084e..343e5ba 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Session.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Session.java
@@ -55,7 +55,7 @@ public interface Session<X extends Session<X>> extends ConfiguredObject<X>
boolean isProducerFlowBlocked();
- @ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Consumers")
+ @ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Consumers", metricName = "consumers_total")
long getConsumerCount();
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.MESSAGES, label = "Prefetched")
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostLogger.java b/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostLogger.java
index c30f6a7..6599a0f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostLogger.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostLogger.java
@@ -25,9 +25,9 @@ public interface VirtualHostLogger <X extends VirtualHostLogger<X>> extends Conf
{
void stopLogging();
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Errors")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Errors", metricName = "errors_count")
long getErrorCount();
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Warnings")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Warnings", metricName = "warnings_count")
long getWarnCount();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java b/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
index f88b99a..530d603 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
@@ -159,12 +159,16 @@ public interface AmqpPort<X extends AmqpPort<X>> extends Port<X>
@ManagedAttribute( defaultValue = "${" + PORT_MAX_OPEN_CONNECTIONS + "}" )
int getMaxOpenConnections();
- @ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Open Connections",
- description = "Current number of connections made through this port")
+ @ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT,
+ label = "Open Connections",
+ description = "Current number of connections made through this port",
+ metricName = "open_connections_total")
int getConnectionCount();
- @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Total Connections",
- description = "Total number of connections made through this port since broker startup")
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT,
+ label = "Total Connections",
+ description = "Total number of connections made through this port since broker startup",
+ metricName = "aggregate_connection_count")
long getTotalConnectionCount();
@DerivedAttribute(description = "Maximum time allowed for a new connection to send a protocol header."
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestSensor.java b/broker-core/src/main/java/org/apache/qpid/server/plugin/ContentFactory.java
similarity index 75%
copy from broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestSensor.java
copy to broker-core/src/main/java/org/apache/qpid/server/plugin/ContentFactory.java
index 41e07f2..bc0ad33 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestSensor.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/plugin/ContentFactory.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -18,13 +17,15 @@
* under the License.
*
*/
-package org.apache.qpid.server.model.testmodels.hierarchy;
+
+package org.apache.qpid.server.plugin;
+
+import java.util.Map;
import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.Content;
-@ManagedObject( defaultType = TestTemperatureSensorImpl.TEST_TEMPERATURE_SENSOR_TYPE)
-public interface TestSensor<X extends TestSensor<X>> extends ConfiguredObject<X>
+public interface ContentFactory extends Pluggable
{
-
+ Content createContent(ConfiguredObject<?> object, Map<String, String[]> filter);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueManagingVirtualHost.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueManagingVirtualHost.java
index 9f1b318..4cd276a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueManagingVirtualHost.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueManagingVirtualHost.java
@@ -210,69 +210,69 @@ public interface QueueManagingVirtualHost<X extends QueueManagingVirtualHost<X>>
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Queues",
- description = "Current number of queues on this virtualhost.")
+ description = "Current number of queues on this virtualhost.", metricName = "queues_total")
long getQueueCount();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Exchanges",
- description = "Current number of exchanges on this virtualhost.")
+ description = "Current number of exchanges on this virtualhost.", metricName = "exchanges_total")
long getExchangeCount();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT, label = "Connections",
- description = "Current number of messaging connections made to this virtualhost.")
+ description = "Current number of messaging connections made to this virtualhost.", metricName = "connections_total")
long getConnectionCount();
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT, label = "Total Connections",
- description = "Total number of messaging connections made to this virtualhost since broker startup")
+ description = "Total number of messaging connections made to this virtualhost since broker startup", metricName = "aggregate_connection_count")
long getTotalConnectionCount();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Inbound",
- description = "Total size of all messages received by this virtualhost.")
+ description = "Total size of all messages received by this virtualhost.", metricName = "inbound_bytes_count")
long getBytesIn();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.BYTES, label = "Outbound",
- description = "Total size of all messages delivered by this virtualhost.")
+ description = "Total size of all messages delivered by this virtualhost.", metricName = "outbound_bytes_count")
long getBytesOut();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Inbound",
- description = "Total number of messages received by this virtualhost.")
+ description = "Total number of messages received by this virtualhost.", metricName = "inbound_messages_count")
long getMessagesIn();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES, label = "Outbound",
- description = "Total number of messages delivered by this virtualhost.")
+ description = "Total number of messages delivered by this virtualhost.", metricName = "outbound_messages_count")
long getMessagesOut();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES,
label = "Transacted Inbound",
- description = "Total number of messages delivered by this virtualhost within a transaction.")
+ description = "Total number of messages delivered by this virtualhost within a transaction.", metricName = "inbound_transacted_messages_count")
long getTransactedMessagesIn();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.MESSAGES,
label = "Transacted Outbound",
- description = "Total number of messages received by this virtualhost within a transaction.")
+ description = "Total number of messages received by this virtualhost within a transaction.", metricName = "outbound_transacted_messages_count")
long getTransactedMessagesOut();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.BYTES, label = "Queue Depth",
- description = "Current size of all messages enqueued by this virtualhost.")
+ description = "Current size of all messages enqueued by this virtualhost.", metricName = "queue_depth_bytes_total")
long getTotalDepthOfQueuesBytes();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.MESSAGES, label = "Queue Depth",
- description = "Current number of messages enqueued by this virtualhost.")
+ description = "Current number of messages enqueued by this virtualhost.", metricName = "queue_depth_messages_total")
long getTotalDepthOfQueuesMessages();
@SuppressWarnings("unused")
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.BYTES, label = "In-Memory Message Bytes",
- description="Current size of all messages cached in-memory.")
+ description="Current size of all messages cached in-memory.", metricName = "in_memory_message_size_bytes_total")
long getInMemoryMessageSize();
@SuppressWarnings("unused")
@@ -284,7 +284,7 @@ public interface QueueManagingVirtualHost<X extends QueueManagingVirtualHost<X>>
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME,
units = StatisticUnit.BYTES,
label = "Maximum recorded size of inbound messages",
- description = "Maximum size of message published into the Virtual Host since start-up.")
+ description = "Maximum size of message published into the Virtual Host since start-up.", metricName = "inbound_message_size_high_water_mark")
long getInboundMessageSizeHighWatermark();
@Override
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
index 90ce83e..8afa95e 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
@@ -292,14 +292,16 @@ public class InjectedAttributeTest extends UnitTestBase
TYPE_VALIDATOR,
StatisticUnit.COUNT,
StatisticType.POINT_IN_TIME,
- "What is 6 x 9?");
+ "What is 6 x 9?",
+ null,
+ false);
TestModel model = new TestModel(null, new TestInjector(statInjector));
TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);
final Map<String, Object> statistics = testCar.getStatistics();
- assertEquals("incorrect number of statistics", (long) 1, (long) statistics.size());
+ assertEquals("incorrect number of statistics", (long) 3, (long) statistics.size());
assertEquals("incorrect statistic value", 42, statistics.get("meaningOfLife"));
}
@@ -317,7 +319,9 @@ public class InjectedAttributeTest extends UnitTestBase
TYPE_VALIDATOR,
StatisticUnit.COUNT,
StatisticType.POINT_IN_TIME,
- "One");
+ "One",
+ null,
+ false);
final ConfiguredObjectInjectedStatistic<?, ?> statInjector2 =
new ConfiguredObjectInjectedStatistic<TestCar<?>, Integer>("whatISent2",
method,
@@ -325,13 +329,15 @@ public class InjectedAttributeTest extends UnitTestBase
TYPE_VALIDATOR,
StatisticUnit.COUNT,
StatisticType.POINT_IN_TIME,
- "Two");
+ "Two",
+ null,
+ false);
TestModel model = new TestModel(null, new TestInjector(statInjector1, statInjector2));
TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);
final Map<String, Object> statistics = testCar.getStatistics();
- assertEquals("incorrect number of statistics", (long) 2, (long) statistics.size());
+ assertEquals("incorrect number of statistics", (long) 4, (long) statistics.size());
assertEquals("incorrect statistic value", 1, statistics.get("whatISent1"));
assertEquals("incorrect statistic value", 2, statistics.get("whatISent2"));
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractCarImpl.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractCarImpl.java
index 447c324..f01a6a4 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractCarImpl.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractCarImpl.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.model.testmodels.hierarchy;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
@@ -37,6 +38,8 @@ public abstract class TestAbstractCarImpl<X extends TestAbstractCarImpl<X>> exte
@ManagedAttributeField
private Colour _interiorColour;
+ private AtomicInteger _mileage = new AtomicInteger();
+
private volatile boolean _rejectStateChange;
public TestAbstractCarImpl(final Map<String, Object> attributes)
@@ -102,4 +105,22 @@ public abstract class TestAbstractCarImpl<X extends TestAbstractCarImpl<X>> exte
{
_rejectStateChange = rejectStateChange;
}
+
+ @Override
+ public int getMileage()
+ {
+ return _mileage.get();
+ }
+
+ @Override
+ public int move(final int value)
+ {
+ return _mileage.addAndGet(value);
+ }
+
+ @Override
+ public int getAge()
+ {
+ return 0;
+ }
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractEngineImpl.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractEngineImpl.java
index 722ddc8..5e84a12 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractEngineImpl.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractEngineImpl.java
@@ -34,6 +34,7 @@ import org.apache.qpid.server.model.StateTransition;
public class TestAbstractEngineImpl<X extends TestAbstractEngineImpl<X>> extends AbstractConfiguredObject<X> implements TestEngine<X>
{
+ public static final int TEST_TEMPERATURE = 50;
@ManagedAttributeField
private ListenableFuture<Void> _beforeCloseFuture = Futures.immediateFuture(null);
@@ -109,4 +110,10 @@ public class TestAbstractEngineImpl<X extends TestAbstractEngineImpl<X>> extends
setState(State.ACTIVE);
return (ListenableFuture<Void>) _stateChangeFuture;
}
+
+ @Override
+ public int getTemperature()
+ {
+ return TEST_TEMPERATURE;
+ }
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractInstrumentPanelImpl.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractInstrumentPanelImpl.java
index 5ef7001..73db9d3 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractInstrumentPanelImpl.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractInstrumentPanelImpl.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model.testmodels.hierarchy;
import java.util.Map;
+import java.util.Random;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -51,4 +52,5 @@ public class TestAbstractInstrumentPanelImpl<X extends TestAbstractInstrumentPan
setState(State.ACTIVE);
return Futures.immediateFuture(null);
}
+
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractSensorImpl.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractSensorImpl.java
index dc41c23..00ff611 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractSensorImpl.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestAbstractSensorImpl.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model.testmodels.hierarchy;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -33,6 +34,8 @@ public class TestAbstractSensorImpl<X extends TestAbstractSensorImpl<X>> extends
implements TestSensor<X>
{
+ private AtomicInteger _alertCount;
+
protected TestAbstractSensorImpl(final TestInstrumentPanel<?> parent,
final Map<String, Object> attributes)
{
@@ -51,4 +54,10 @@ public class TestAbstractSensorImpl<X extends TestAbstractSensorImpl<X>> extends
setState(State.ACTIVE);
return Futures.immediateFuture(null);
}
+
+ @Override
+ public int getNumberOfAlerts()
+ {
+ return _alertCount.getAndIncrement();
+ }
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestCar.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestCar.java
index a184227..8588d60 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestCar.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestCar.java
@@ -25,7 +25,10 @@ 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.ManagedStatistic;
import org.apache.qpid.server.model.Param;
+import org.apache.qpid.server.model.StatisticType;
+import org.apache.qpid.server.model.StatisticUnit;
@ManagedObject( defaultType = TestStandardCarImpl.TEST_STANDARD_CAR_TYPE)
public interface TestCar<X extends TestCar<X>> extends ConfiguredObject<X>
@@ -60,4 +63,15 @@ public interface TestCar<X extends TestCar<X>> extends ConfiguredObject<X>
void setRejectStateChange(boolean b);
+ @ManagedStatistic(statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT)
+ int getMileage();
+
+ @ManagedStatistic(metricName = "age",
+ statisticType = StatisticType.CUMULATIVE,
+ units = StatisticUnit.TIME_DURATION,
+ metricDisabled = true)
+ int getAge();
+
+ @ManagedOperation(changesConfiguredObjectState = false)
+ int move(@Param(name = "mileage", mandatory = true) int mileage);
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestEngine.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestEngine.java
index d5284cb..97229b2 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestEngine.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestEngine.java
@@ -25,6 +25,9 @@ import com.google.common.util.concurrent.ListenableFuture;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedAttribute;
import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedStatistic;
+import org.apache.qpid.server.model.StatisticType;
+import org.apache.qpid.server.model.StatisticUnit;
@ManagedObject(category = true, defaultType = TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE)
public interface TestEngine<X extends TestEngine<X>> extends ConfiguredObject<X>
@@ -52,4 +55,7 @@ public interface TestEngine<X extends TestEngine<X>> extends ConfiguredObject<X>
Object getStateChangeException();
void setStateChangeException(RuntimeException exception);
+ @ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.COUNT)
+ int getTemperature();
+
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestSensor.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestSensor.java
index 41e07f2..c2bbc79 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestSensor.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestSensor.java
@@ -22,9 +22,14 @@ package org.apache.qpid.server.model.testmodels.hierarchy;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedStatistic;
+import org.apache.qpid.server.model.StatisticType;
+import org.apache.qpid.server.model.StatisticUnit;
@ManagedObject( defaultType = TestTemperatureSensorImpl.TEST_TEMPERATURE_SENSOR_TYPE)
public interface TestSensor<X extends TestSensor<X>> extends ConfiguredObject<X>
{
+ @ManagedStatistic(metricName = "alert_count", statisticType = StatisticType.CUMULATIVE, units = StatisticUnit.COUNT)
+ int getNumberOfAlerts();
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestTemperatureSensorImpl.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestTemperatureSensorImpl.java
index f2c176b..96f1fcf 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestTemperatureSensorImpl.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestTemperatureSensorImpl.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model.testmodels.hierarchy;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
@@ -32,9 +33,17 @@ public class TestTemperatureSensorImpl extends TestAbstractSensorImpl<TestTemper
public static final String TEST_TEMPERATURE_SENSOR_TYPE = "temperature";
+ private AtomicInteger _alertCount = new AtomicInteger();
+
@ManagedObjectFactoryConstructor
protected TestTemperatureSensorImpl(final Map<String, Object> attributes,final TestInstrumentPanel<?> parent)
{
super(parent, attributes);
}
+
+ @Override
+ public int getNumberOfAlerts()
+ {
+ return _alertCount.getAndIncrement();
+ }
}
diff --git a/broker-plugins/management-http/pom.xml b/broker-plugins/management-http/pom.xml
index 9fa84d0..fa5a233 100644
--- a/broker-plugins/management-http/pom.xml
+++ b/broker-plugins/management-http/pom.xml
@@ -101,6 +101,11 @@
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-broker-plugins-prometheus-exporter</artifactId>
+ </dependency>
+
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index 39709df..43da9db 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -90,6 +90,7 @@ import org.apache.qpid.server.management.plugin.filter.RewriteRequestForUncompre
import org.apache.qpid.server.management.plugin.portunification.TlsOrPlainConnectionFactory;
import org.apache.qpid.server.management.plugin.servlet.FileServlet;
import org.apache.qpid.server.management.plugin.servlet.RootServlet;
+import org.apache.qpid.server.management.plugin.servlet.ContentServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.ApiDocsServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.BrokerQueryServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.JsonValueServlet;
@@ -119,6 +120,8 @@ import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.adapter.AbstractPluginAdapter;
import org.apache.qpid.server.model.port.HttpPort;
import org.apache.qpid.server.model.port.PortManager;
+import org.apache.qpid.server.plugin.ContentFactory;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.transport.PortBindFailureException;
import org.apache.qpid.server.transport.network.security.ssl.SSLUtil;
import org.apache.qpid.server.util.DaemonThreadFactory;
@@ -412,6 +415,21 @@ public class HttpManagement extends AbstractPluginAdapter<HttpManagement> implem
root.addServlet(new ServletHolder(new TimeZoneServlet()), "/service/timezones");
+ final Iterable<ContentFactory> contentFactories = new QpidServiceLoader().instancesOf(ContentFactory.class);
+ contentFactories.forEach(f->{
+ ServletHolder metricsServlet = new ServletHolder(new ContentServlet(f));
+ String path = f.getType().toLowerCase();
+ root.addServlet(metricsServlet, "/" + path);
+ root.addServlet(metricsServlet, "/" + path + "/*");
+
+ if (getContextValue(Boolean.class, HTTP_MANAGEMENT_ENABLE_CONTENT_AUTHENTICATION))
+ {
+ root.addFilter(restAuthorizationFilter, "/" + path, EnumSet.of(DispatcherType.REQUEST));
+ root.addFilter(restAuthorizationFilter, "/" + path + "/*", EnumSet.of(DispatcherType.REQUEST));
+ }
+
+ });
+
root.getSessionHandler().getSessionCookieConfig().setName(JSESSIONID_COOKIE_PREFIX + lastPort);
root.getSessionHandler().getSessionCookieConfig().setHttpOnly(true);
root.getSessionHandler().setMaxInactiveInterval(getSessionTimeout());
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
index a5aadae..d33f2b8 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
@@ -85,6 +85,11 @@ public interface HttpManagementConfiguration<X extends HttpManagementConfigurati
@ManagedContextDefault( name = SASL_EXCHANGE_EXPIRY_CONTEXT_NAME)
long DEFAULT_SASL_EXCHANGE_EXPIRY = 60000L;
+ String HTTP_MANAGEMENT_ENABLE_CONTENT_AUTHENTICATION = "qpid.httpManagement.enableMetricContentAuthentication";
+ @SuppressWarnings("unused")
+ @ManagedContextDefault(name = HTTP_MANAGEMENT_ENABLE_CONTENT_AUTHENTICATION)
+ boolean DEFAULT_HTTP_MANAGEMENT_ENABLE_CONTENT_AUTHENTICATION = false;
+
AuthenticationProvider getAuthenticationProvider(HttpServletRequest request);
Port<?> getPort(HttpServletRequest request);
}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/ContentServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/ContentServlet.java
new file mode 100644
index 0000000..36ea0a7
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/ContentServlet.java
@@ -0,0 +1,95 @@
+/*
+ * 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.management.plugin.servlet;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.management.plugin.servlet.rest.AbstractServlet;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
+import org.apache.qpid.server.model.Content;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.plugin.ContentFactory;
+
+public class ContentServlet extends AbstractServlet
+{
+ private static final long serialVersionUID = 1L;
+ private final ContentFactory _contentFactory;
+
+ public ContentServlet(final ContentFactory contentFactory)
+ {
+ super();
+ _contentFactory = contentFactory;
+ }
+
+ @Override
+ public void doGet(HttpServletRequest request,
+ HttpServletResponse response,
+ final ConfiguredObject<?> managedObject) throws IOException
+ {
+
+ ConfiguredObject root = managedObject;
+ String pathInfo = request.getPathInfo();
+ if (managedObject instanceof Broker && null != pathInfo && !pathInfo.isEmpty())
+ {
+ final ConfiguredObjectFinder finder = getConfiguredObjectFinder(managedObject);
+ final ConfiguredObject virtualHost = finder.findObjectFromPath(pathInfo.substring(1), VirtualHost.class);
+ if (null == virtualHost)
+ {
+ sendError(response, HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
+ else
+ {
+ root = virtualHost;
+ }
+ }
+ else if (managedObject instanceof VirtualHost && null != pathInfo && !pathInfo.isEmpty())
+ {
+ sendError(response, HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ final Map<String, String[]> parameters = request.getParameterMap();
+ Content content = _contentFactory.createContent(root, parameters);
+ try
+ {
+ writeContent(content, request, response);
+ }
+ finally
+ {
+ content.release();
+ }
+ }
+
+ @Override
+ protected void doPost(final HttpServletRequest req,
+ final HttpServletResponse resp,
+ final ConfiguredObject<?> managedObject)
+ throws IOException
+ {
+ doGet(req, resp, managedObject);
+ }
+
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
index 76d87f1..e324c7a 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
@@ -284,8 +284,22 @@ public abstract class AbstractServlet extends HttpServlet
protected void writeTypedContent(Content content, HttpServletRequest request, HttpServletResponse response)
throws IOException
{
- Map<String, Object> headers = getResponseHeaders(content);
+ try
+ {
+ writeContent(content, request, response);
+ }
+ catch (IOException e)
+ {
+ LOGGER.warn("Unexpected exception processing request", e);
+ sendJsonErrorResponse(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+ }
+ }
+ protected void writeContent(final Content content,
+ final HttpServletRequest request,
+ final HttpServletResponse response) throws IOException
+ {
+ Map<String, Object> headers = new HashMap<>(getResponseHeaders(content));
try (OutputStream os = getOutputStream(request, response, headers))
{
response.setStatus(HttpServletResponse.SC_OK);
@@ -295,11 +309,6 @@ public abstract class AbstractServlet extends HttpServlet
}
content.write(os);
}
- catch (IOException e)
- {
- LOGGER.warn("Unexpected exception processing request", e);
- sendJsonErrorResponse(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
- }
}
private OutputStream getOutputStream(final HttpServletRequest request,
diff --git a/broker-plugins/prometheus-exporter/pom.xml b/broker-plugins/prometheus-exporter/pom.xml
new file mode 100644
index 0000000..9f9885f
--- /dev/null
+++ b/broker-plugins/prometheus-exporter/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ ~
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>qpid-broker-parent</artifactId>
+ <groupId>org.apache.qpid</groupId>
+ <version>7.1.9-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>qpid-broker-plugins-prometheus-exporter</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-broker-codegen</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-broker-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.prometheus</groupId>
+ <artifactId>simpleclient</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.prometheus</groupId>
+ <artifactId>simpleclient_common</artifactId>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-test-utils</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-broker-core</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+</project>
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeDisabledStatisticPredicate.java
similarity index 59%
copy from broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
copy to broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeDisabledStatisticPredicate.java
index cc22d62..f675e55 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
+++ b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeDisabledStatisticPredicate.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -18,15 +17,26 @@
* under the License.
*
*/
-package org.apache.qpid.server.model;
-public interface ConfiguredObjectStatistic<C extends ConfiguredObject, T extends Object> extends ConfiguredObjectAttributeOrStatistic<C,T>
-{
- String getDescription();
+package org.apache.qpid.server.prometheus;
+
+import java.util.function.Predicate;
- StatisticUnit getUnits();
+import org.apache.qpid.server.model.ConfiguredObjectStatistic;
+
+public class IncludeDisabledStatisticPredicate implements Predicate<ConfiguredObjectStatistic<?,?>>
+
+{
+ private final boolean _includeDisabled;
- StatisticType getStatisticType();
+ IncludeDisabledStatisticPredicate(final boolean includeDisabled)
+ {
+ _includeDisabled = includeDisabled;
+ }
- String getLabel();
+ @Override
+ public boolean test(final ConfiguredObjectStatistic s)
+ {
+ return _includeDisabled || !s.isMetricDisabled();
+ }
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeMetricPredicate.java
similarity index 60%
copy from broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
copy to broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeMetricPredicate.java
index cc22d62..e921352 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
+++ b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/IncludeMetricPredicate.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -18,15 +17,26 @@
* under the License.
*
*/
-package org.apache.qpid.server.model;
-public interface ConfiguredObjectStatistic<C extends ConfiguredObject, T extends Object> extends ConfiguredObjectAttributeOrStatistic<C,T>
-{
- String getDescription();
+package org.apache.qpid.server.prometheus;
- StatisticUnit getUnits();
+import java.util.Set;
+import java.util.function.Predicate;
+
+public class IncludeMetricPredicate implements Predicate<String>
+{
+ private final Set<String> _allowedNames;
+ private final boolean _isEmpty;
- StatisticType getStatisticType();
+ public IncludeMetricPredicate(final Set<String> allowedNames)
+ {
+ _allowedNames = allowedNames;
+ _isEmpty = _allowedNames.isEmpty();
+ }
- String getLabel();
+ @Override
+ public boolean test(final String name)
+ {
+ return _isEmpty || _allowedNames.contains(name);
+ }
}
diff --git a/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/PrometheusContentFactory.java b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/PrometheusContentFactory.java
new file mode 100644
index 0000000..af98978
--- /dev/null
+++ b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/PrometheusContentFactory.java
@@ -0,0 +1,105 @@
+/*
+ * 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.prometheus;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+
+import io.prometheus.client.exporter.common.TextFormat;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Content;
+import org.apache.qpid.server.model.RestContentHeader;
+import org.apache.qpid.server.plugin.ContentFactory;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class PrometheusContentFactory implements ContentFactory
+{
+ static final String INCLUDE_DISABLED = "includeDisabled";
+ static final String INCLUDE_METRIC = "name[]";
+ static final String INCLUDE_DISABLED_CONTEXT_VARIABLE = "qpid.metrics.includeDisabled";
+
+ @Override
+ public Content createContent(final ConfiguredObject<?> object, final Map<String, String[]> filter)
+ {
+ final String[] includeDisabledValues = filter.get(INCLUDE_DISABLED);
+ boolean includeDisabled = includeDisabledValues!= null && includeDisabledValues.length == 1 && Boolean.parseBoolean(includeDisabledValues[0]);
+ if (!includeDisabled)
+ {
+ Boolean val = object.getContextValue(Boolean.class, INCLUDE_DISABLED_CONTEXT_VARIABLE);
+ if (val != null)
+ {
+ includeDisabled = val;
+ }
+ }
+
+ final String[] includedMetricNames = filter.get(INCLUDE_METRIC);
+
+ final IncludeMetricPredicate metricIncludeFilter =
+ new IncludeMetricPredicate(includedMetricNames == null || includedMetricNames.length == 0
+ ? Collections.emptySet()
+ : new HashSet<>(Arrays.asList(includedMetricNames)));
+ final QpidCollector qpidCollector = new QpidCollector(object,
+ new IncludeDisabledStatisticPredicate(includeDisabled),
+ metricIncludeFilter);
+
+ return new Content()
+ {
+ @Override
+ public void write(final OutputStream outputStream) throws IOException
+ {
+ try (final Writer writer = new OutputStreamWriter(outputStream))
+ {
+ TextFormat.write004(writer, Collections.enumeration(qpidCollector.collect()));
+ writer.flush();
+ }
+ }
+
+ @Override
+ public void release()
+ {
+
+ }
+
+ @SuppressWarnings("unused")
+ @RestContentHeader("Content-Type")
+ public String getContentType()
+ {
+ return TextFormat.CONTENT_TYPE_004;
+ }
+
+ };
+
+ }
+
+ @Override
+ public String getType()
+ {
+ return "metrics";
+ }
+}
diff --git a/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/QpidCollector.java b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/QpidCollector.java
new file mode 100644
index 0000000..3997700
--- /dev/null
+++ b/broker-plugins/prometheus-exporter/src/main/java/org/apache/qpid/server/prometheus/QpidCollector.java
@@ -0,0 +1,257 @@
+/*
+ * 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.prometheus;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+
+import io.prometheus.client.Collector;
+import io.prometheus.client.CounterMetricFamily;
+import io.prometheus.client.GaugeMetricFamily;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectStatistic;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.StatisticType;
+import org.apache.qpid.server.model.StatisticUnit;
+
+public class QpidCollector extends Collector
+{
+ private final static MetricFamilySamples IGNORED = new MetricFamilySamples(null, null, null, null);
+ static final String COUNT_SUFFIX = "count";
+ static final String TOTAL_SUFFIX = "total";
+ private final Predicate<ConfiguredObjectStatistic<?,?>> _includeStatisticFilter;
+ private final Predicate<String> _includeMetricFilter;
+ private ConfiguredObject<?> _root;
+ private Model _model;
+
+
+ QpidCollector(final ConfiguredObject<?> root,
+ final Predicate<ConfiguredObjectStatistic<?,?>> includeStatisticFilter,
+ final Predicate<String> includeMetricFilter)
+ {
+ _root = root;
+ _model = _root.getModel();
+ _includeStatisticFilter = includeStatisticFilter;
+ _includeMetricFilter = includeMetricFilter;
+ }
+
+ @Override
+ public List<MetricFamilySamples> collect()
+ {
+ final List<MetricFamilySamples> metricFamilySamples = new ArrayList<>();
+ addObjectMetrics(_root, Collections.emptyList(), new HashMap<>(), metricFamilySamples);
+ addChildrenMetrics(metricFamilySamples, _root, Collections.singletonList("name"));
+ return metricFamilySamples;
+ }
+
+ private void addObjectMetrics(final ConfiguredObject<?> object,
+ final List<String> labelNames,
+ final Map<String, MetricFamilySamples> metricFamilyMap,
+ final List<MetricFamilySamples> metricFamilySamples)
+ {
+ final Map<String, Object> statsMap = object.getStatistics();
+ for (final Map.Entry<String, Object> entry : statsMap.entrySet())
+ {
+ MetricFamilySamples family = metricFamilyMap.get(entry.getKey());
+ if (family == null)
+ {
+ family = createMetricFamilySamples(entry.getKey(), object, labelNames);
+ metricFamilyMap.put(entry.getKey(), family);
+ if (family != IGNORED)
+ {
+ metricFamilySamples.add(family);
+ }
+ }
+ if (family != IGNORED)
+ {
+ final List<String> labelsValues = buildLabelValues(object);
+ final double doubleValue = toDoubleValue(entry.getValue());
+ family.samples.add(new MetricFamilySamples.Sample(family.name, labelNames, labelsValues, doubleValue));
+ }
+ }
+ }
+
+ private MetricFamilySamples createMetricFamilySamples(final String statisticName,
+ final ConfiguredObject<?> object,
+ final List<String> labelNames)
+ {
+ final ConfiguredObjectStatistic<?, ?> configuredObjectStatistic =
+ findConfiguredObjectStatistic(statisticName, object.getTypeClass());
+ if (configuredObjectStatistic == null || !_includeStatisticFilter.test(configuredObjectStatistic))
+ {
+ return IGNORED;
+ }
+ final StatisticType type = configuredObjectStatistic.getStatisticType();
+ final String familyName = getFamilyName(object.getCategoryClass(), configuredObjectStatistic);
+
+ if (!_includeMetricFilter.test(familyName))
+ {
+ return IGNORED;
+ }
+
+ if (type == StatisticType.CUMULATIVE)
+ {
+ return new CounterMetricFamily(familyName, configuredObjectStatistic.getDescription(), labelNames);
+ }
+ else
+ {
+ return new GaugeMetricFamily(familyName, configuredObjectStatistic.getDescription(), labelNames);
+ }
+ }
+
+ private ConfiguredObjectStatistic<?, ?> findConfiguredObjectStatistic(final String statisticName,
+ final Class<? extends ConfiguredObject> typeClass)
+ {
+ final Collection<ConfiguredObjectStatistic<?, ?>> statisticsDefinitions =
+ _model.getTypeRegistry().getStatistics(typeClass);
+ return statisticsDefinitions.stream()
+ .filter(s -> statisticName.equals(s.getName()))
+ .findFirst()
+ .orElse(null);
+ }
+
+ private List<String> buildLabelValues(final ConfiguredObject<?> object)
+ {
+ final List<String> labelsValues = new ArrayList<>();
+ ConfiguredObject o = object;
+ while (o != null && o != _root)
+ {
+ labelsValues.add(o.getName());
+ o = o.getParent();
+ }
+ return labelsValues;
+ }
+
+ private void addChildrenMetrics(final List<MetricFamilySamples> metricFamilySamples,
+ final ConfiguredObject<?> object,
+ final List<String> childLabelNames)
+ {
+ final Class<? extends ConfiguredObject> category = object.getCategoryClass();
+ for (final Class<? extends ConfiguredObject> childClass : _model.getChildTypes(category))
+ {
+ final Collection<? extends ConfiguredObject> children = object.getChildren(childClass);
+ if (children != null && !children.isEmpty())
+ {
+ final Map<String, MetricFamilySamples> childrenMetricFamilyMap = new HashMap<>();
+ for (final ConfiguredObject<?> child : children)
+ {
+ addObjectMetrics(child, childLabelNames, childrenMetricFamilyMap, metricFamilySamples);
+ final List<String> labelNames = new ArrayList<>(childLabelNames);
+ final String label = String.format("%s_name", toSnakeCase(childClass.getSimpleName()));
+ labelNames.add(label);
+ addChildrenMetrics(metricFamilySamples, child, labelNames);
+ }
+ }
+ }
+ }
+
+ static String toSnakeCase(final String simpleName)
+ {
+ final StringBuilder sb = new StringBuilder();
+ final char[] chars = simpleName.toCharArray();
+ for (int i = 0; i < chars.length; i++)
+ {
+ final char ch = chars[i];
+ if (Character.isUpperCase(ch))
+ {
+ if (i > 0)
+ {
+ sb.append('_');
+ }
+ sb.append(Character.toLowerCase(ch));
+ }
+ else
+ {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ private double toDoubleValue(final Object value)
+ {
+ if (value instanceof Number)
+ {
+ return ((Number) value).doubleValue();
+ }
+ return 0;
+ }
+
+ static String getFamilyName(final Class<? extends ConfiguredObject> categoryClass,
+ ConfiguredObjectStatistic<?, ?> statistics)
+ {
+ String metricName = statistics.getMetricName();
+ if (metricName == null || metricName.isEmpty())
+ {
+ metricName = generateMetricName(statistics);
+ }
+
+ return String.format("qpid_%s_%s",
+ toSnakeCase(categoryClass.getSimpleName()),
+ metricName);
+ }
+
+ private static String generateMetricName(final ConfiguredObjectStatistic<?, ?> statistics)
+ {
+ String metricName = toSnakeCase(statistics.getName());
+ String suffix;
+ switch (statistics.getStatisticType())
+ {
+ case CUMULATIVE:
+ suffix = generateMetricSuffix(statistics, COUNT_SUFFIX, metricName);
+ break;
+ case POINT_IN_TIME:
+ suffix = generateMetricSuffix(statistics, TOTAL_SUFFIX, metricName);
+ break;
+ default:
+ suffix = "";
+ }
+
+ return metricName + suffix;
+ }
+
+ private static String generateMetricSuffix(final ConfiguredObjectStatistic<?, ?> statistics,
+ final String typeSuffix,
+ final String metricName)
+ {
+ String suffix = "";
+ if (!statistics.getName().toLowerCase().contains(typeSuffix)
+ && statistics.getUnits() != StatisticUnit.ABSOLUTE_TIME
+ && statistics.getUnits() != StatisticUnit.TIME_DURATION)
+ {
+ if (statistics.getUnits() == StatisticUnit.MESSAGES || statistics.getUnits() == StatisticUnit.BYTES)
+ {
+ final String units = statistics.getUnits().toString() + "s";
+ if (!metricName.contains(units))
+ {
+ suffix = "_" + units;
+ }
+ }
+ suffix = suffix + "_" + typeSuffix;
+ }
+ return suffix;
+ }
+}
diff --git a/broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/PrometheusContentFactoryTest.java b/broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/PrometheusContentFactoryTest.java
new file mode 100644
index 0000000..7959a77
--- /dev/null
+++ b/broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/PrometheusContentFactoryTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.prometheus;
+
+import static org.apache.qpid.server.prometheus.PrometheusContentFactory.INCLUDE_DISABLED;
+import static org.apache.qpid.server.prometheus.PrometheusContentFactory.INCLUDE_METRIC;
+import static org.apache.qpid.server.prometheus.PrometheusContentFactory.INCLUDE_DISABLED_CONTEXT_VARIABLE;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Content;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestCar;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestKitCarImpl;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestModel;
+
+public class PrometheusContentFactoryTest
+{
+ public static final String QPID_TEST_CAR_MILEAGE_COUNT = "qpid_test_car_mileage_count";
+ public static final String QPID_TEST_CAR_AGE = "qpid_test_car_age";
+ public static final String PROMETHEUS_COMMENT = "#";
+ private ConfiguredObject _root;
+ private PrometheusContentFactory _prometheusContentFactory;
+
+ @Before
+ public void setUp()
+ {
+ final Model model = TestModel.getInstance();
+ final Map<String, Object> carAttributes = new HashMap<>();
+ carAttributes.put(ConfiguredObject.NAME, "MyPrometheusCar");
+ carAttributes.put(ConfiguredObject.TYPE, TestKitCarImpl.TEST_KITCAR_TYPE);
+
+ @SuppressWarnings("unchecked") final TestCar<?> car =
+ model.getObjectFactory().create(TestCar.class, carAttributes, null);
+ _root = car;
+ _prometheusContentFactory = new PrometheusContentFactory();
+ }
+
+ @Test
+ public void testCreateContent() throws Exception
+ {
+ final Content content = _prometheusContentFactory.createContent(_root, Collections.emptyMap());
+ assertThat(content, is(notNullValue()));
+ Collection<String> metrics;
+ try (final ByteArrayOutputStream output = new ByteArrayOutputStream())
+ {
+ content.write(output);
+ metrics = getMetricLines(output.toByteArray());
+ }
+ assertThat(metrics, is(notNullValue()));
+
+ assertThat(metrics.size(), is(equalTo(1)));
+ String metric = metrics.iterator().next();
+ assertThat(metric, startsWith(QPID_TEST_CAR_MILEAGE_COUNT));
+ }
+
+ @Test
+ public void testCreateContentIncludeDisabled() throws Exception
+ {
+ final Content content = _prometheusContentFactory.createContent(_root, Collections.singletonMap(INCLUDE_DISABLED, new String[]{"true"}));
+ assertThat(content, is(notNullValue()));
+ Collection<String> metrics;
+ try (final ByteArrayOutputStream output = new ByteArrayOutputStream())
+ {
+ content.write(output);
+ metrics = getMetricLines(output.toByteArray());
+ }
+ assertThat(metrics, is(notNullValue()));
+
+ assertThat(metrics.size(), is(equalTo(2)));
+ Map<String, String> metricsMap = convertMetricsToMap(metrics);
+ assertThat(metricsMap.containsKey(QPID_TEST_CAR_MILEAGE_COUNT), equalTo(Boolean.TRUE));
+ assertThat(metricsMap.containsKey(QPID_TEST_CAR_AGE), equalTo(Boolean.TRUE));
+ }
+
+ @Test
+ public void testCreateContentIncludeDisabledUsingContextVariable() throws Exception
+ {
+ _root.setContextVariable(INCLUDE_DISABLED_CONTEXT_VARIABLE, "true");
+ final Content content = _prometheusContentFactory.createContent(_root, Collections.emptyMap());
+ assertThat(content, is(notNullValue()));
+ Collection<String> metrics;
+ try (final ByteArrayOutputStream output = new ByteArrayOutputStream())
+ {
+ content.write(output);
+ metrics = getMetricLines(output.toByteArray());
+ }
+ assertThat(metrics, is(notNullValue()));
+ assertThat(metrics.size(), is(equalTo(2)));
+ Map<String, String> metricsMap = convertMetricsToMap(metrics);
+ assertThat(metricsMap.containsKey(QPID_TEST_CAR_MILEAGE_COUNT), equalTo(Boolean.TRUE));
+ assertThat(metricsMap.containsKey(QPID_TEST_CAR_AGE), equalTo(Boolean.TRUE));
+ }
+
+ @Test
+ public void testCreateContentIncludeName() throws Exception
+ {
+ final Map<String, String[]> filter = new HashMap<>();
+ filter.put(INCLUDE_DISABLED, new String[]{"true"});
+ filter.put(INCLUDE_METRIC, new String[]{QPID_TEST_CAR_AGE});
+ final Content content = _prometheusContentFactory.createContent(_root, filter);
+ assertThat(content, is(notNullValue()));
+ Collection<String> metrics;
+ try (final ByteArrayOutputStream output = new ByteArrayOutputStream())
+ {
+ content.write(output);
+ metrics = getMetricLines(output.toByteArray());
+ }
+ assertThat(metrics, is(notNullValue()));
+
+ assertThat(metrics.size(), is(equalTo(1)));
+ String metric = metrics.iterator().next();
+ assertThat(metric, startsWith(QPID_TEST_CAR_AGE));
+ }
+
+ private static Collection<String> getMetricLines(final byte[] metricsBytes) throws IOException
+ {
+ final List<String> results = new ArrayList<>();
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(metricsBytes))))
+ {
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ if (!(line.startsWith(PROMETHEUS_COMMENT) || line.isEmpty()))
+ {
+ results.add(line);
+ }
+ }
+ }
+ return results;
+ }
+
+ private Map<String, String> convertMetricsToMap(final Collection<String> metrics)
+ {
+ return metrics.stream().map(m -> m.split(" ")).collect(Collectors.toMap(m -> m[0], m -> m[1]));
+ }
+
+}
diff --git a/broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/QpidCollectorTest.java b/broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/QpidCollectorTest.java
new file mode 100644
index 0000000..5efbc59
--- /dev/null
+++ b/broker-plugins/prometheus-exporter/src/test/java/org/apache/qpid/server/prometheus/QpidCollectorTest.java
@@ -0,0 +1,359 @@
+/*
+ * 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.prometheus;
+
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.closeTo;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import io.prometheus.client.Collector;
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectStatistic;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.StatisticType;
+import org.apache.qpid.server.model.StatisticUnit;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestAbstractEngineImpl;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestCar;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestDigitalInstrumentPanelImpl;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestElecEngineImpl;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestEngine;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestInstrumentPanel;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestKitCarImpl;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestModel;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestPetrolEngineImpl;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestSensor;
+import org.apache.qpid.server.model.testmodels.hierarchy.TestTemperatureSensorImpl;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class QpidCollectorTest extends UnitTestBase
+{
+ private static final String CAR_NAME = "myCar";
+ private static final String ELECTRIC_ENGINE_NAME = "myEngine";
+ private static final String INSTRUMENT_PANEL_NAME = "instrumentPanel";
+ private static final String PETROL_ENGINE_NAME = "myPetrolModel";
+ private static final String SENSOR = "sensor";
+ private static final int DESIRED_MILEAGE = 100;
+ private static final String QPID_TEST_CAR_MILEAGE_COUNT = "qpid_test_car_mileage_count";
+ private static final String QPID_TEST_ENGINE_TEMPERATURE_TOTAL = "qpid_test_engine_temperature_total";
+ private static final String QPID_TEST_SENSOR_ALERT_COUNT = "qpid_test_sensor_alert_count";
+ private static final String QPID_TEST_CAR_AGE_COUNT = "qpid_test_car_age";
+
+ private TestCar<?> _root;
+ private QpidCollector _qpidCollector;
+ private static final StatisticUnit[] UNITS = new StatisticUnit[]{
+ StatisticUnit.BYTES,
+ StatisticUnit.MESSAGES,
+ StatisticUnit.COUNT,
+ StatisticUnit.ABSOLUTE_TIME,
+ StatisticUnit.TIME_DURATION};
+ private static final String[] UNIT_SUFFIXES = new String[]{"_bytes", "_messages", "", "", ""};
+
+ @Before
+ public void setUp()
+ {
+ final Model model = TestModel.getInstance();
+ final Map<String, Object> carAttributes = new HashMap<>();
+ carAttributes.put(ConfiguredObject.NAME, CAR_NAME);
+ carAttributes.put(ConfiguredObject.TYPE, TestKitCarImpl.TEST_KITCAR_TYPE);
+
+ @SuppressWarnings("unchecked") final TestCar<?> car =
+ model.getObjectFactory().create(TestCar.class, carAttributes, null);
+ _root = car;
+ _qpidCollector = new QpidCollector(_root, new IncludeDisabledStatisticPredicate(false), s->true);
+ }
+
+ @Test
+ public void testCollectForHierarchyOfTwoObjects()
+ {
+ createTestEngine(ELECTRIC_ENGINE_NAME, TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE);
+ _root.move(DESIRED_MILEAGE);
+
+ final List<Collector.MetricFamilySamples> metrics = _qpidCollector.collect();
+
+ final String[] expectedFamilyNames = {QPID_TEST_CAR_MILEAGE_COUNT, QPID_TEST_ENGINE_TEMPERATURE_TOTAL};
+ final Map<String, Collector.MetricFamilySamples> metricsMap =
+ convertMetricFamilySamplesIntoMapAndAssert(metrics, expectedFamilyNames);
+
+ final Collector.MetricFamilySamples carMetricFamilySamples = metricsMap.get(QPID_TEST_CAR_MILEAGE_COUNT);
+ assertMetricFamilySamplesSize(carMetricFamilySamples, 1);
+ final Collector.MetricFamilySamples.Sample carSample = carMetricFamilySamples.samples.get(0);
+ assertThat(carSample.value, closeTo(DESIRED_MILEAGE, 0.01));
+ assertThat(carSample.labelNames.size(), is(equalTo(0)));
+
+ final Collector.MetricFamilySamples engineMetricFamilySamples = metricsMap.get(
+ QPID_TEST_ENGINE_TEMPERATURE_TOTAL);
+ assertMetricFamilySamplesSize(engineMetricFamilySamples, 1);
+ final Collector.MetricFamilySamples.Sample engineSample = engineMetricFamilySamples.samples.get(0);
+ assertThat(engineSample.labelNames, is(equalTo(Collections.singletonList("name"))));
+ assertThat(engineSample.labelValues, is(equalTo(Collections.singletonList(ELECTRIC_ENGINE_NAME))));
+ assertThat(engineSample.value, Matchers.closeTo(TestAbstractEngineImpl.TEST_TEMPERATURE, 0.01));
+ }
+
+ @Test
+ public void testCollectForHierarchyOfThreeObjects()
+ {
+ final TestInstrumentPanel instrumentPanel = getTestInstrumentPanel();
+ createTestSensor(instrumentPanel);
+
+ final List<Collector.MetricFamilySamples> metrics = _qpidCollector.collect();
+
+ final String[] expectedFamilyNames =
+ {QPID_TEST_CAR_MILEAGE_COUNT, QPID_TEST_SENSOR_ALERT_COUNT};
+ final Map<String, Collector.MetricFamilySamples> metricsMap =
+ convertMetricFamilySamplesIntoMapAndAssert(metrics, expectedFamilyNames);
+
+ final Collector.MetricFamilySamples carMetricFamilySamples = metricsMap.get(QPID_TEST_CAR_MILEAGE_COUNT);
+ assertMetricFamilySamplesSize(carMetricFamilySamples, 1);
+ final Collector.MetricFamilySamples.Sample carSample = carMetricFamilySamples.samples.get(0);
+ assertThat(carSample.labelNames.size(), is(equalTo(0)));
+ assertThat(carSample.labelValues.size(), is(equalTo(0)));
+ assertThat(carSample.value, closeTo(0, 0.01));
+
+ final Collector.MetricFamilySamples sensorlMetricFamilySamples =
+ metricsMap.get(QPID_TEST_SENSOR_ALERT_COUNT);
+ assertMetricFamilySamplesSize(sensorlMetricFamilySamples, 1);
+ final Collector.MetricFamilySamples.Sample sensorSample = sensorlMetricFamilySamples.samples.get(0);
+ assertThat(sensorSample.labelNames, is(equalTo(Arrays.asList("name", "test_instrument_panel_name"))));
+ assertThat(sensorSample.labelValues, is(equalTo(Arrays.asList(SENSOR, INSTRUMENT_PANEL_NAME))));
+ }
+
+ @Test
+ public void testCollectForSiblingObjects()
+ {
+ createTestEngine(ELECTRIC_ENGINE_NAME, TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE);
+ createTestEngine(PETROL_ENGINE_NAME, TestPetrolEngineImpl.TEST_PETROL_ENGINE_TYPE);
+
+ final List<Collector.MetricFamilySamples> metrics = _qpidCollector.collect();
+
+ final String[] expectedFamilyNames = {QPID_TEST_CAR_MILEAGE_COUNT, QPID_TEST_ENGINE_TEMPERATURE_TOTAL};
+ final Map<String, Collector.MetricFamilySamples> metricsMap =
+ convertMetricFamilySamplesIntoMapAndAssert(metrics, expectedFamilyNames);
+
+ final Collector.MetricFamilySamples carMetricFamilySamples = metricsMap.get(QPID_TEST_CAR_MILEAGE_COUNT);
+ assertMetricFamilySamplesSize(carMetricFamilySamples, 1);
+ final Collector.MetricFamilySamples.Sample carSample = carMetricFamilySamples.samples.get(0);
+ assertThat(carSample.labelNames.size(), is(equalTo(0)));
+ assertThat(carSample.labelValues.size(), is(equalTo(0)));
+
+ final Collector.MetricFamilySamples engineMetricFamilySamples = metricsMap.get(
+ QPID_TEST_ENGINE_TEMPERATURE_TOTAL);
+ assertMetricFamilySamplesSize(engineMetricFamilySamples, 2);
+ final String[] engineNames = {PETROL_ENGINE_NAME, ELECTRIC_ENGINE_NAME};
+ for (String engineName : engineNames)
+ {
+ final Collector.MetricFamilySamples.Sample sample =
+ findSampleByLabelValue(engineMetricFamilySamples, engineName);
+ assertThat(sample.labelNames, is(equalTo(Collections.singletonList("name"))));
+ assertThat(sample.labelValues, is(equalTo(Collections.singletonList(engineName))));
+ assertThat(sample.value, Matchers.closeTo(TestAbstractEngineImpl.TEST_TEMPERATURE, 0.01));
+ }
+ }
+
+ @Test
+ public void testCollectWithFilter(){
+ createTestEngine(ELECTRIC_ENGINE_NAME, TestElecEngineImpl.TEST_ELEC_ENGINE_TYPE);
+ _root.move(DESIRED_MILEAGE);
+
+ _qpidCollector = new QpidCollector(_root,
+ new IncludeDisabledStatisticPredicate(true),
+ new IncludeMetricPredicate(Collections.singleton(QPID_TEST_CAR_AGE_COUNT)));
+ final List<Collector.MetricFamilySamples> metrics = _qpidCollector.collect();
+
+ final String[] expectedFamilyNames = {QPID_TEST_CAR_AGE_COUNT};
+ final Map<String, Collector.MetricFamilySamples> metricsMap =
+ convertMetricFamilySamplesIntoMapAndAssert(metrics, expectedFamilyNames);
+
+
+ final Collector.MetricFamilySamples engineMetricFamilySamples = metricsMap.get(QPID_TEST_CAR_AGE_COUNT);
+ assertMetricFamilySamplesSize(engineMetricFamilySamples, 1);
+ final Collector.MetricFamilySamples.Sample engineSample = engineMetricFamilySamples.samples.get(0);
+ assertThat(engineSample.labelNames, is(equalTo(Collections.emptyList())));
+ assertThat(engineSample.labelValues, is(equalTo(Collections.emptyList())));
+ assertThat(engineSample.value, Matchers.closeTo(0.0, 0.01));
+
+ }
+
+
+ private Collector.MetricFamilySamples.Sample findSampleByLabelValue(final Collector.MetricFamilySamples metricFamilySamples,
+ final String nameLabelValue)
+ {
+ final List<Collector.MetricFamilySamples.Sample> found = metricFamilySamples.samples
+ .stream()
+ .filter(s -> s.labelValues != null
+ && s.labelValues.size() > 0
+ && nameLabelValue.equals(s.labelValues.get(0)))
+ .collect(Collectors.toList());
+ assertThat(found.size(), is(equalTo(1)));
+ return found.get(0);
+ }
+
+ private void createTestEngine(final String engineName, final String engineType)
+ {
+ final Map<String, Object> engineAttributes = new HashMap<>();
+ engineAttributes.put(ConfiguredObject.NAME, engineName);
+ engineAttributes.put(ConfiguredObject.TYPE, engineType);
+ _root.createChild(TestEngine.class, engineAttributes);
+ }
+
+ private void createTestSensor(final TestInstrumentPanel instrumentPanel)
+ {
+ final Map<String, Object> sensorAttributes = new HashMap<>();
+ sensorAttributes.put(ConfiguredObject.NAME, SENSOR);
+ sensorAttributes.put(ConfiguredObject.TYPE, TestTemperatureSensorImpl.TEST_TEMPERATURE_SENSOR_TYPE);
+ instrumentPanel.createChild(TestSensor.class, sensorAttributes);
+ }
+
+ private TestInstrumentPanel getTestInstrumentPanel()
+ {
+ final Map<String, Object> instrumentPanelAttributes = new HashMap<>();
+ instrumentPanelAttributes.put(ConfiguredObject.NAME, INSTRUMENT_PANEL_NAME);
+ instrumentPanelAttributes.put(ConfiguredObject.TYPE,
+ TestDigitalInstrumentPanelImpl.TEST_DIGITAL_INSTRUMENT_PANEL_TYPE);
+ return _root.createChild(TestInstrumentPanel.class, instrumentPanelAttributes);
+ }
+
+ private Map<String, Collector.MetricFamilySamples> convertMetricFamilySamplesIntoMap(List<Collector.MetricFamilySamples> metricFamilySamples)
+ {
+ Map<String, Collector.MetricFamilySamples> result = new HashMap<>();
+ for (Collector.MetricFamilySamples metricFamilySample : metricFamilySamples)
+ {
+ final String name = metricFamilySample.name;
+
+ if (result.put(name, metricFamilySample) != null)
+ {
+ fail(String.format("Duplicate family name : %s", name));
+ }
+ }
+ return result;
+ }
+
+ private void assertMetricFamilySamples(final Collector.MetricFamilySamples metricFamilySamples)
+ {
+ assertThat(metricFamilySamples, is(notNullValue()));
+ assertThat(metricFamilySamples.samples, is(notNullValue()));
+
+ for (final Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples)
+ {
+ assertThat(sample, is(notNullValue()));
+ assertThat(sample.name, is(equalTo(metricFamilySamples.name)));
+ }
+ }
+
+
+ private void assertMetricFamilySamplesSize(final Collector.MetricFamilySamples metricFamilySamples,
+ final int expectedSamplesSize)
+ {
+ assertThat(metricFamilySamples.samples.size(), equalTo(expectedSamplesSize));
+ }
+
+ private Map<String, Collector.MetricFamilySamples> convertMetricFamilySamplesIntoMapAndAssert(final List<Collector.MetricFamilySamples> metrics,
+ final String[] expectedFamilyNames)
+ {
+ assertThat(metrics.size(), equalTo(expectedFamilyNames.length));
+ final Map<String, Collector.MetricFamilySamples> metricsMap = convertMetricFamilySamplesIntoMap(metrics);
+
+ for (String expectedFamily : expectedFamilyNames)
+ {
+ assertMetricFamilySamples(metricsMap.get(expectedFamily));
+ }
+ return metricsMap;
+ }
+
+ @Test
+ public void testToSnakeCase()
+ {
+ assertThat(QpidCollector.toSnakeCase("carEngineOilChanges"), is(equalTo("car_engine_oil_changes")));
+ }
+
+ @Test
+ public void getFamilyNameForCumulativeStatistic()
+ {
+ for (int i = 0; i < UNITS.length; i++)
+ {
+ final ConfiguredObjectStatistic<?, ?> statistics = mock(ConfiguredObjectStatistic.class);
+ when(statistics.getUnits()).thenReturn(UNITS[i]);
+ when(statistics.getStatisticType()).thenReturn(StatisticType.CUMULATIVE);
+ when(statistics.getName()).thenReturn("diagnosticData");
+ final String familyName = QpidCollector.getFamilyName(TestCar.class, statistics);
+ final String expectedName =
+ String.format("qpid_test_car_diagnostic_data%s%s", UNIT_SUFFIXES[i], getSuffix(UNITS[i],QpidCollector.COUNT_SUFFIX));
+ assertThat(String.format("unexpected metric name for units %s", UNITS[i]),
+ familyName,
+ is(equalTo(expectedName)));
+ }
+ }
+
+ @Test
+ public void getFamilyNameForCumulativeStatisticContainingCountInName()
+ {
+ final ConfiguredObjectStatistic<?, ?> statistics = mock(ConfiguredObjectStatistic.class);
+ when(statistics.getUnits()).thenReturn(StatisticUnit.BYTES);
+ when(statistics.getStatisticType()).thenReturn(StatisticType.CUMULATIVE);
+ when(statistics.getName()).thenReturn("CountOfDiagnosticData");
+ final String familyName = QpidCollector.getFamilyName(TestCar.class, statistics);
+ assertThat(familyName, is(equalTo("qpid_test_car_count_of_diagnostic_data")));
+ }
+
+ @Test
+ public void getFamilyNameForPointInTimeStatistic()
+ {
+ for (int i = 0; i < UNITS.length; i++)
+ {
+ final ConfiguredObjectStatistic<?, ?> statistics = mock(ConfiguredObjectStatistic.class);
+ when(statistics.getUnits()).thenReturn(UNITS[i]);
+ when(statistics.getStatisticType()).thenReturn(StatisticType.POINT_IN_TIME);
+ when(statistics.getName()).thenReturn("diagnosticData");
+ final String familyName = QpidCollector.getFamilyName(TestCar.class, statistics);
+
+ final String expectedName =
+ String.format("qpid_test_car_diagnostic_data%s%s", UNIT_SUFFIXES[i], getSuffix(UNITS[i],QpidCollector.TOTAL_SUFFIX));
+ assertThat(String.format("unexpected metric name for units %s", UNITS[i]),
+ familyName,
+ is(equalTo(expectedName)));
+ }
+ }
+
+ String getSuffix(final StatisticUnit unit,final String requiredSuffix)
+ {
+ String suffix = "_" + requiredSuffix;
+ if(unit.equals(StatisticUnit.ABSOLUTE_TIME) || unit.equals(StatisticUnit.TIME_DURATION)){
+ suffix = "";
+ }
+ return suffix;
+ }
+}
diff --git a/doc/java-broker/src/docbkx/Java-Broker-Management-Channels.xml b/doc/java-broker/src/docbkx/Java-Broker-Management-Channels.xml
index 9211056..13e7fa2 100644
--- a/doc/java-broker/src/docbkx/Java-Broker-Management-Channels.xml
+++ b/doc/java-broker/src/docbkx/Java-Broker-Management-Channels.xml
@@ -37,5 +37,6 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="management/channels/Java-Broker-Management-Channel-HTTP.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="management/channels/Java-Broker-Management-Channel-Web-Console.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="management/channels/Java-Broker-Management-Channel-REST-API.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="management/channels/Java-Broker-Management-Metrics.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="management/channels/Java-Broker-Management-Channel-AMQP-Intrinsic.xml"/>
</chapter>
diff --git a/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml
new file mode 100644
index 0000000..c8aeb9d
--- /dev/null
+++ b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+ ~ 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.
+ ~
+ -->
+
+<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="Java-Broker-Management-Metrics">
+ <title>Prometheus Metrics</title>
+ <para>This section describes the metrics endpoints exposing broker statistics in
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://prometheus.io/">Prometheus format</link>.
+ The metrics endpoint is intended for scraping by Prometheus server to collect the Broker telemetry.</para>
+ <para>The Prometheus metric endpoints are mapped under /metrics path and /metrics/*.
+ The latter allows to get the Virtual Host statistics by specify the path to the virtual host as
+ /metrics/<virtual host node name>/< virtual host name>.
+ The former allow to get all Broker statistics or Virtual Host statistics when called with HOST header
+ set to the Virtual Host name</para>
+ <para>
+ The metrics endpoints allow anonymous access by default. If required, an authentication can be enabled for the
+ metrics endpoints by setting http management context variable
+ <literal>qpid.httpManagement.enableMetricContentAuthentication</literal> to <literal>true</literal>.
+ </para>
+
+ <para>The Broker JVM statistics are disabled by default. The metrics endpoints can be called with parameter
+ <literal>includeDisabled</literal> set to <literal>true</literal> to include JVM broker metrics into endpoint
+ output.
+ </para>
+ <note>
+ <para>For more information about Prometheus, check out the
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://prometheus.io/docs/introduction/overview/">prometheus documentation</link>.
+ </para>
+ </note>
+
+</section>
diff --git a/pom.xml b/pom.xml
index 274b957..c49bcb8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -154,6 +154,7 @@
<h2.version>1.4.199</h2.version>
<apache-directory-version>2.0.0-M23</apache-directory-version>
<kerby-version>1.0.1</kerby-version>
+ <prometheus-client-version>0.9.0</prometheus-client-version>
</properties>
<modules>
@@ -179,6 +180,7 @@
<module>broker-plugins/websocket</module>
<module>broker-plugins/amqp-1-0-bdb-store</module>
<module>broker-plugins/amqp-1-0-jdbc-store</module>
+ <module>broker-plugins/prometheus-exporter</module>
<module>tools</module>
<module>qpid-systests-parent</module>
@@ -469,6 +471,12 @@
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-broker-plugins-prometheus-exporter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
<!-- External dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
@@ -750,6 +758,18 @@
<scope>test</scope>
<version>${kerby-version}</version>
</dependency>
+
+ <!-- prometheus client dependencies -->
+ <dependency>
+ <groupId>io.prometheus</groupId>
+ <artifactId>simpleclient</artifactId>
+ <version>${prometheus-client-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.prometheus</groupId>
+ <artifactId>simpleclient_common</artifactId>
+ <version>${prometheus-client-version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
diff --git a/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsAuthenticationTest.java b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsAuthenticationTest.java
new file mode 100644
index 0000000..fcfca5e
--- /dev/null
+++ b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsAuthenticationTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.tests.http.metrics;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.HttpManagement;
+import org.apache.qpid.tests.http.HttpRequestConfig;
+import org.apache.qpid.tests.http.HttpTestBase;
+import org.apache.qpid.tests.http.HttpTestHelper;
+import org.apache.qpid.tests.utils.ConfigItem;
+
+@HttpRequestConfig(useVirtualHostAsHost = false)
+@ConfigItem(name = HttpManagement.HTTP_MANAGEMENT_ENABLE_CONTENT_AUTHENTICATION, value = "true")
+public class BrokerMetricsAuthenticationTest extends HttpTestBase
+{
+ @Test
+ public void testBrokerMetricsForAuthenticatedUser() throws Exception
+ {
+ getHelper().submitRequest("/metrics", "GET", HttpServletResponse.SC_OK);
+ }
+
+ @Test
+ public void testBrokerMetricsForUnauthenticatedUser() throws Exception
+ {
+ final HttpTestHelper helper = new HttpTestHelper(getBrokerAdmin(), null);
+ helper.setUserName(null);
+ helper.setPassword(null);
+ helper.submitRequest("/metrics", "GET", HttpServletResponse.SC_UNAUTHORIZED);
+ }
+
+}
diff --git a/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java
new file mode 100644
index 0000000..7423588
--- /dev/null
+++ b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java
@@ -0,0 +1,80 @@
+package org.apache.qpid.tests.http.metrics;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.qpid.tests.http.metrics.TestMetricsHelper.QUEUE_NAME;
+import static org.apache.qpid.tests.http.metrics.TestMetricsHelper.assertMetricsInclusion;
+import static org.apache.qpid.tests.http.metrics.TestMetricsHelper.assertVirtualHostHierarchyMetrics;
+import static org.apache.qpid.tests.http.metrics.TestMetricsHelper.createQueueMetricPattern;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.Collection;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+
+import org.apache.qpid.tests.http.HttpRequestConfig;
+import org.apache.qpid.tests.http.HttpTestBase;
+
+@HttpRequestConfig(useVirtualHostAsHost = false)
+public class BrokerMetricsTest extends HttpTestBase
+{
+ private static final String[] EXPECTED_BROKER_METRIC_NAMES =
+ new String[]{"qpid_broker_inbound_bytes_count", "qpid_broker_outbound_bytes_count"};
+
+ @Test
+ public void testBrokerMetrics() throws Exception
+ {
+ final String[] unexpectedMetricNames =
+ {"qpid_broker_live_threads_total", "qpid_broker_direct_memory_capacity_bytes_total"};
+
+ final byte[] metricsBytes = getHelper().getBytes("/metrics");
+ final String metricsString = new String(metricsBytes, UTF_8);
+ assertMetricsInclusion(metricsString, EXPECTED_BROKER_METRIC_NAMES, true);
+ assertMetricsInclusion(metricsString, unexpectedMetricNames, false);
+
+ final byte[] metricsBytesIncludingDisabled = getHelper().getBytes("/metrics?includeDisabled=true");
+ final String metricsStringIncludingDisabled = new String(metricsBytesIncludingDisabled, UTF_8);
+ assertMetricsInclusion(metricsStringIncludingDisabled, unexpectedMetricNames, true);
+ assertMetricsInclusion(metricsStringIncludingDisabled, EXPECTED_BROKER_METRIC_NAMES, true);
+ }
+
+ @Test
+ public void testQueueMetrics() throws Exception
+ {
+ getBrokerAdmin().createQueue(QUEUE_NAME);
+ final byte[] metricsBytes = getHelper().getBytes("/metrics");
+ final String metricsString = new String(metricsBytes, UTF_8);
+
+ final Pattern[] expectedMetricPattens = {createQueueMetricPattern("qpid_queue_consumers_total"),
+ createQueueMetricPattern("qpid_queue_depth_messages_total")};
+
+ assertMetricsInclusion(metricsString, expectedMetricPattens, true);
+ }
+
+ @Test
+ public void testQueueMetricsIncludeOnlyMessageDepth() throws Exception
+ {
+ getBrokerAdmin().createQueue(QUEUE_NAME);
+ final byte[] metricsBytes = getHelper().getBytes("/metrics?name[]=qpid_queue_depth_messages_total&name[]=qpid_queue_depth_bytes_total");
+ Collection<String> metricLines = TestMetricsHelper.getMetricLines(metricsBytes);
+ assertThat(metricLines.size(), is(equalTo(2)));
+
+ final String metricsString = new String(metricsBytes, UTF_8);
+ final Pattern[] expectedMetricPattens = {createQueueMetricPattern("qpid_queue_depth_bytes_total"),
+ createQueueMetricPattern("qpid_queue_depth_messages_total")};
+
+ assertMetricsInclusion(metricsString, expectedMetricPattens, true);
+ }
+
+ @Test
+ public void testMappingForVirtualHost() throws Exception
+ {
+ getBrokerAdmin().createQueue(QUEUE_NAME);
+ final byte[] metricsBytes =
+ getHelper().getBytes(String.format("/metrics/%s/%s", getVirtualHostNode(), getVirtualHost()));
+
+ assertVirtualHostHierarchyMetrics(metricsBytes);
+ }
+}
diff --git a/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/TestMetricsHelper.java b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/TestMetricsHelper.java
new file mode 100644
index 0000000..fa9b679
--- /dev/null
+++ b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/TestMetricsHelper.java
@@ -0,0 +1,93 @@
+/*
+ * 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.tests.http.metrics;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+class TestMetricsHelper
+{
+ static final String QUEUE_NAME = "foo";
+
+ static void assertMetricsInclusion(final String metricsString,
+ final String[] metricNames,
+ final boolean inclusionFlag)
+ {
+ for (String expected : metricNames)
+ {
+ assertThat(metricsString.contains(expected), equalTo(inclusionFlag));
+ }
+ }
+
+ static void assertMetricsInclusion(final String metricsString,
+ final Pattern[] expectedMetricPattens,
+ final boolean inclusionFlag)
+ {
+ for (Pattern expected : expectedMetricPattens)
+ {
+ assertThat(expected.matcher(metricsString).find(), equalTo(inclusionFlag));
+ }
+ }
+
+ static Pattern createQueueMetricPattern(final String metricName)
+ {
+ return Pattern.compile(String.format("%s\\s*\\{.*name\\s*=\\s*\"%s\"\\s*,.*\\}\\s*0\\.0",
+ metricName,
+ QUEUE_NAME));
+ }
+
+ static void assertVirtualHostHierarchyMetrics(final byte[] metricsBytes) throws IOException
+ {
+ final Predicate<String> unexpectedMetricPredicate = line -> !(line.startsWith("qpid_virtual_host")
+ || line.startsWith("qpid_queue")
+ || line.startsWith("qpid_exchange"));
+ getMetricLines(metricsBytes).stream().filter(unexpectedMetricPredicate)
+ .findFirst().ifPresent(found -> fail("Unexpected metric: " + found));
+ }
+
+ static Collection<String> getMetricLines(final byte[] metricsBytes) throws IOException
+ {
+ final List<String> results = new ArrayList<>();
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(metricsBytes))))
+ {
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ if (!(line.startsWith("#") || line.isEmpty()))
+ {
+ results.add(line);
+ }
+ }
+ }
+ return results;
+ }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/VirtualHostMetricsTest.java
similarity index 54%
copy from broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
copy to systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/VirtualHostMetricsTest.java
index cc22d62..bd06588 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
+++ b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/VirtualHostMetricsTest.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -18,15 +17,25 @@
* under the License.
*
*/
-package org.apache.qpid.server.model;
-public interface ConfiguredObjectStatistic<C extends ConfiguredObject, T extends Object> extends ConfiguredObjectAttributeOrStatistic<C,T>
-{
- String getDescription();
+package org.apache.qpid.tests.http.metrics;
- StatisticUnit getUnits();
+import static org.apache.qpid.tests.http.metrics.TestMetricsHelper.QUEUE_NAME;
+import static org.apache.qpid.tests.http.metrics.TestMetricsHelper.assertVirtualHostHierarchyMetrics;
- StatisticType getStatisticType();
+import org.junit.Test;
- String getLabel();
+import org.apache.qpid.tests.http.HttpRequestConfig;
+import org.apache.qpid.tests.http.HttpTestBase;
+
+@HttpRequestConfig
+public class VirtualHostMetricsTest extends HttpTestBase
+{
+ @Test
+ public void testVirtualHostMetrics() throws Exception
+ {
+ getBrokerAdmin().createQueue(QUEUE_NAME);
+ final byte[] metricsBytes = getHelper().getBytes("/metrics");
+ assertVirtualHostHierarchyMetrics(metricsBytes);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 09/10: QPID-8454:[Broker-J] Update documentation
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit f7f5145132e67a4aead14a2156907834830160c8
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Tue Sep 1 21:54:50 2020 +0100
QPID-8454:[Broker-J] Update documentation
(cherry picked from commit 2c071a3ee3ebd43b8655f9e42f8c986dd15ea68c)
---
.../src/docbkx/management/channels/Java-Broker-Management-Metrics.xml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml
index c8aeb9d..a75ec05 100644
--- a/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml
+++ b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Metrics.xml
@@ -37,7 +37,8 @@
<para>The Broker JVM statistics are disabled by default. The metrics endpoints can be called with parameter
<literal>includeDisabled</literal> set to <literal>true</literal> to include JVM broker metrics into endpoint
- output.
+ output. If required, the JVM metrics could be enabled by setting context variable
+ <literal>qpid.metrics.includeDisabled</literal> to <literal>true</literal>.
</para>
<note>
<para>For more information about Prometheus, check out the
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 10/10: QPID-8454:[Broker-J] Add missing license
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit 627ce9dc00421c39abbf229fe38a5ac14206385d
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Wed Sep 2 20:31:12 2020 +0100
QPID-8454:[Broker-J] Add missing license
(cherry picked from commit 59b25c8dc7f6caaf12981dff46f46db4bb02a746)
---
.../qpid/tests/http/metrics/BrokerMetricsTest.java | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java
index 7423588..a86188f 100644
--- a/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java
+++ b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/metrics/BrokerMetricsTest.java
@@ -1,3 +1,23 @@
+/*
+ * 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.tests.http.metrics;
import static java.nio.charset.StandardCharsets.UTF_8;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 04/10: QPID-8458: [Broker-J] Removed RewriteServlet
from HTTP management
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit 1c0446625a438569d27f7a401fadefebd253de55
Author: Tomas Vavricka <to...@deutsche-boerse.com>
AuthorDate: Tue Aug 4 14:09:27 2020 +0000
QPID-8458: [Broker-J] Removed RewriteServlet from HTTP management
(cherry picked from commit 370fb357b766c2c5d3e3016a274601650181cd1a)
---
.../server/management/plugin/HttpManagement.java | 11 +---
.../server/management/plugin/RewriteServlet.java | 55 -------------------
.../plugin/servlet/rest/ApiDocsServlet.java | 64 ++++++++++------------
3 files changed, 32 insertions(+), 98 deletions(-)
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index c6bed8a..39709df 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -382,10 +382,10 @@ public class HttpManagement extends AbstractPluginAdapter<HttpManagement> implem
ServletHolder apiDocsServlet = new ServletHolder(new ApiDocsServlet());
- final ServletHolder rewriteSerlvet = new ServletHolder(new RewriteServlet("^(.*)$", "$1/"));
- for(String path : new String[]{"/apidocs", "/apidocs/latest", "/apidocs/"+getLatestSupportedVersion()})
+ final String version = "v" + BrokerModel.MODEL_VERSION;
+ for (final String path : new String[]{"/apidocs", "/apidocs/latest", "/apidocs/" + version})
{
- root.addServlet(rewriteSerlvet, path);
+ root.addServlet(apiDocsServlet, path);
root.addServlet(apiDocsServlet, path + "/");
}
@@ -763,11 +763,6 @@ public class HttpManagement extends AbstractPluginAdapter<HttpManagement> implem
root.addServlet(versionsServletHolder, "/api/");
}
- private String getLatestSupportedVersion()
- {
- return "v"+String.valueOf(BrokerModel.MODEL_VERSION);
- }
-
private void logOperationalListenMessages()
{
for (Map.Entry<HttpPort<?>, ServerConnector> portConnector : _portConnectorMap.entrySet())
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/RewriteServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/RewriteServlet.java
deleted file mode 100644
index c222662..0000000
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/RewriteServlet.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * 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.management.plugin;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public class RewriteServlet extends HttpServlet
-{
- private static final long serialVersionUID = 1L;
-
- private final String _pattern;
- private final String _replacement;
-
- public RewriteServlet(final String pattern, final String replacement)
- {
- _pattern = pattern;
- _replacement = replacement;
-
- }
-
- @Override
- protected void service(final HttpServletRequest req, final HttpServletResponse resp)
- throws ServletException, IOException
- {
- String location = req.getRequestURI().replaceAll(_pattern, _replacement);
- if(req.getQueryString() != null)
- {
- location += "?" + req.getQueryString();
- }
- resp.sendRedirect(location);
- }
-}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java
index 6e5bddc..ca1c9d2 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java
@@ -18,17 +18,24 @@ package org.apache.qpid.server.management.plugin.servlet.rest;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectAttribute;
import org.apache.qpid.server.model.ConfiguredObjectAttributeOrStatistic;
@@ -45,23 +52,12 @@ public class ApiDocsServlet extends AbstractServlet
{
private static final long serialVersionUID = 1L;
- private static final Logger LOGGER = LoggerFactory.getLogger(ApiDocsServlet.class);
-
private static final Set<Character> VOWELS = new HashSet<>(Arrays.asList('a','e','i','o','u'));
public static final Comparator<Class<? extends ConfiguredObject>> CLASS_COMPARATOR =
- new Comparator<Class<? extends ConfiguredObject>>()
- {
- @Override
- public int compare(final Class<? extends ConfiguredObject> o1,
- final Class<? extends ConfiguredObject> o2)
- {
- return o1.getSimpleName().compareTo(o2.getSimpleName());
- }
-
- };
+ Comparator.comparing(Class::getSimpleName);
- private transient final ConcurrentMap<Class<? extends ConfiguredObject>, List<Class<? extends ConfiguredObject>>> _typeSpecialisations = new ConcurrentHashMap<>();
+ private final transient ConcurrentMap<Class<? extends ConfiguredObject>, List<Class<? extends ConfiguredObject>>> _typeSpecialisations = new ConcurrentHashMap<>();
public ApiDocsServlet()
{
@@ -71,9 +67,9 @@ public class ApiDocsServlet extends AbstractServlet
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response,
- final ConfiguredObject<?> managedObject) throws ServletException, IOException
+ final ConfiguredObject<?> managedObject) throws IOException
{
- ConfiguredObjectFinder finder = getConfiguredObjectFinder(managedObject);
+ final ConfiguredObjectFinder finder = getConfiguredObjectFinder(managedObject);
final Class<? extends ConfiguredObject> configuredClass;
@@ -81,7 +77,7 @@ public class ApiDocsServlet extends AbstractServlet
final String[] servletPathParts = request.getServletPath().split("/");
final Model model = managedObject.getModel();
- if(servletPathParts.length < 4)
+ if (servletPathParts.length < 4)
{
configuredClass = null;
hierarchy = null;
@@ -100,10 +96,10 @@ public class ApiDocsServlet extends AbstractServlet
sendError(response, HttpServletResponse.SC_NOT_FOUND);
return;
}
- if(!_typeSpecialisations.containsKey(configuredClass))
+ if (!_typeSpecialisations.containsKey(configuredClass))
{
- List<Class<? extends ConfiguredObject>> types = new ArrayList<>(model
- .getTypeRegistry().getTypeSpecialisations(configuredClass));
+ final List<Class<? extends ConfiguredObject>> types =
+ new ArrayList<>(model.getTypeRegistry().getTypeSpecialisations(configuredClass));
_typeSpecialisations.putIfAbsent(configuredClass, types);
}
}
@@ -111,12 +107,12 @@ public class ApiDocsServlet extends AbstractServlet
response.setStatus(HttpServletResponse.SC_OK);
- PrintWriter writer = response.getWriter();
+ final PrintWriter writer = response.getWriter();
writePreamble(writer);
writeHead(writer, hierarchy, configuredClass);
- if(hierarchy == null)
+ if (hierarchy == null)
{
writer.println("<table class=\"api\">");
writer.println("<thead>");
@@ -127,23 +123,21 @@ public class ApiDocsServlet extends AbstractServlet
writer.println("</tr>");
writer.println("</thead>");
writer.println("<tbody>");
- SortedSet<Class<? extends ConfiguredObject>> managedCategories = new TreeSet<>(CLASS_COMPARATOR);
+ final SortedSet<Class<? extends ConfiguredObject>> managedCategories = new TreeSet<>(CLASS_COMPARATOR);
managedCategories.addAll(finder.getManagedCategories());
- String pathStem = "/" + servletPathParts[1] + "/" + (servletPathParts.length == 2 ? "latest" : servletPathParts[2]) + "/";
- for(Class<? extends ConfiguredObject> category : managedCategories)
+ final String pathStem = "/" + servletPathParts[1] + "/" + (servletPathParts.length == 2 ? "latest" : servletPathParts[2]) + "/";
+ for (final Class<? extends ConfiguredObject> category : managedCategories)
{
- Class<? extends ConfiguredObject> objClass = category;
- String path = pathStem + category.getSimpleName().toLowerCase();
+ final String path = pathStem + category.getSimpleName().toLowerCase();
writer.println("<tr>");
- writer.println("<td class=\"type\"><a href=" + ((servletPathParts.length == 2) ? "\"latest/" : "")+ objClass.getSimpleName().toLowerCase()+"\">"+objClass.getSimpleName()+"</a></td>");
+ writer.println("<td class=\"type\"><a href=" + path + ">" + category.getSimpleName() + "</a></td>");
writer.println("<td class=\"path\">" + path + "</td>");
- writer.println("<td class=\"description\">"+
- objClass.getAnnotation(ManagedObject.class).description()+"</td>");
+ writer.println("<td class=\"description\">" +
+ category.getAnnotation(ManagedObject.class).description()+"</td>");
writer.println("</tr>");
}
writer.println("</tbody>");
writer.println("</table>");
-
}
else
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 01/10: NO-JIRA: Fix Kerberos tests
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit 55bab0d6d226faf9077a6590cecb439f6c2071d8
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Fri Nov 29 13:08:51 2019 +0000
NO-JIRA: Fix Kerberos tests
---
.../manager/KerberosAuthenticationManagerTest.java | 79 +++++----
.../SimpleLDAPAuthenticationManagerTest.java | 17 +-
.../auth/manager/SpnegoAuthenticatorTest.java | 61 +++----
.../qpid/server/test/EmbeddedKdcResource.java | 29 +--
.../apache/qpid/server/test/KerberosUtilities.java | 196 +++++++++++++++++++--
broker-core/src/test/resources/login.ibm.config | 51 ++++++
.../java/org/apache/qpid/test/utils/JvmVendor.java | 25 ++-
.../org/apache/qpid/test/utils/UnitTestBase.java | 18 +-
8 files changed, 338 insertions(+), 138 deletions(-)
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java
index e24d56c..9211710 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerTest.java
@@ -19,19 +19,22 @@
package org.apache.qpid.server.security.auth.manager;
-import static org.apache.commons.codec.CharEncoding.UTF_8;
import static org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager.GSSAPI_MECHANISM;
-import static org.hamcrest.Matchers.not;
+import static org.apache.qpid.server.test.KerberosUtilities.ACCEPT_SCOPE;
+import static org.apache.qpid.server.test.KerberosUtilities.CLIENT_PRINCIPAL_FULL_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.CLIENT_PRINCIPAL_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.HOST_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.LOGIN_CONFIG;
+import static org.apache.qpid.server.test.KerberosUtilities.REALM;
+import static org.apache.qpid.server.test.KerberosUtilities.SERVER_PROTOCOL;
+import static org.apache.qpid.server.test.KerberosUtilities.SERVICE_PRINCIPAL_NAME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
-import java.net.URL;
-import java.net.URLDecoder;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Base64;
@@ -45,13 +48,10 @@ import javax.security.auth.login.LoginContext;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
-import org.ietf.jgss.GSSException;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.AuthenticationProvider;
@@ -62,26 +62,20 @@ import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
import org.apache.qpid.server.security.auth.sasl.SaslSettings;
import org.apache.qpid.server.test.EmbeddedKdcResource;
import org.apache.qpid.server.test.KerberosUtilities;
-import org.apache.qpid.test.utils.JvmVendor;
+import org.apache.qpid.server.util.StringUtil;
import org.apache.qpid.test.utils.SystemPropertySetter;
import org.apache.qpid.test.utils.UnitTestBase;
public class KerberosAuthenticationManagerTest extends UnitTestBase
{
- private static final Logger LOGGER = LoggerFactory.getLogger(KerberosAuthenticationManagerTest.class);
- private static final String LOGIN_CONFIG = "login.config";
- private static final String REALM = "QPID.ORG";
- private static final String SERVER_NAME = "localhost";
- private static final String SERVER_PROTOCOL = "AMQP";
- private static final String SERVICE_PRINCIPAL_NAME = SERVER_PROTOCOL + "/" + SERVER_NAME;
- private static final String SERVER_PRINCIPAL_FULL_NAME = SERVICE_PRINCIPAL_NAME + "@" + REALM;
- private static final String CLIENT_PRINCIPAL_NAME = "client";
- private static final String CLIENT_PRINCIPAL_FULL_NAME = CLIENT_PRINCIPAL_NAME + "@" + REALM;
private static final KerberosUtilities UTILS = new KerberosUtilities();
@ClassRule
- public static final EmbeddedKdcResource KDC = new EmbeddedKdcResource(REALM);
+ public static final EmbeddedKdcResource KDC = new EmbeddedKdcResource(HOST_NAME,
+ 0,
+ "QpidTestKerberosServer",
+ REALM);
@ClassRule
public static final SystemPropertySetter SYSTEM_PROPERTY_SETTER = new SystemPropertySetter();
@@ -94,21 +88,15 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
@BeforeClass
public static void createKeyTabs() throws Exception
{
- assumeThat(getJvmVendor(), not(JvmVendor.IBM));
- KDC.createPrincipal("broker.keytab", SERVER_PRINCIPAL_FULL_NAME);
- _clientKeyTabFile = KDC.createPrincipal("client.keytab", CLIENT_PRINCIPAL_FULL_NAME);
- final URL resource = KerberosAuthenticationManagerTest.class.getClassLoader().getResource(LOGIN_CONFIG);
- LOGGER.debug("JAAS config:" + resource);
- assertNotNull(resource);
- SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config", URLDecoder.decode(resource.getPath(), UTF_8));
- SYSTEM_PROPERTY_SETTER.setSystemProperty("javax.security.auth.useSubjectCredsOnly", "false");
+ UTILS.prepareConfiguration(HOST_NAME, SYSTEM_PROPERTY_SETTER);
+ _clientKeyTabFile = UTILS.prepareKeyTabs(KDC);
}
@Before
public void setUp() throws Exception
{
Map<String, String> context = Collections.singletonMap(KerberosAuthenticationManager.GSSAPI_SPNEGO_CONFIG,
- "com.sun.security.jgss.accept");
+ ACCEPT_SCOPE);
final Map<String, Object> attributes = new HashMap<>();
attributes.put(AuthenticationProvider.NAME, getTestName());
attributes.put(AuthenticationProvider.CONTEXT, context);
@@ -123,7 +111,7 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
public void testCreateSaslNegotiator() throws Exception
{
final SaslSettings saslSettings = mock(SaslSettings.class);
- when(saslSettings.getLocalFQDN()).thenReturn(SERVER_NAME);
+ when(saslSettings.getLocalFQDN()).thenReturn(HOST_NAME);
final SaslNegotiator negotiator = _kerberosAuthenticationProvider.createSaslNegotiator(GSSAPI_MECHANISM,
saslSettings,
null);
@@ -163,7 +151,7 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
public void testCreateKerberosAuthenticationProvidersWithNonExistingJaasLoginModule()
{
when(_broker.getChildren(AuthenticationProvider.class)).thenReturn(Collections.emptySet());
- SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config",
+ SYSTEM_PROPERTY_SETTER.setSystemProperty(LOGIN_CONFIG,
"config.module." + System.nanoTime());
final Map<String, Object> attributes = Collections.singletonMap(AuthenticationProvider.NAME, getTestName());
final KerberosAuthenticationManager kerberosAuthenticationProvider =
@@ -180,10 +168,11 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
}
@Test
- public void testAuthenticateUsingNegotiationToken() throws GSSException
+ public void testAuthenticateUsingNegotiationToken() throws Exception
{
- final String token =
- Base64.getEncoder().encodeToString(UTILS.buildToken(CLIENT_PRINCIPAL_NAME, SERVICE_PRINCIPAL_NAME));
+ byte[] negotiationTokenBytes =
+ UTILS.buildToken(CLIENT_PRINCIPAL_NAME, _clientKeyTabFile, SERVICE_PRINCIPAL_NAME);
+ final String token = Base64.getEncoder().encodeToString(negotiationTokenBytes);
final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
final AuthenticationResult result = _kerberosAuthenticationProvider.authenticate(authenticationHeader);
@@ -197,19 +186,30 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
final LoginContext lc = UTILS.createKerberosKeyTabLoginContext(getTestName(),
CLIENT_PRINCIPAL_FULL_NAME,
_clientKeyTabFile);
+
+ Subject clientSubject = null;
try
{
lc.login();
- final Subject clientSubject = lc.getSubject();
+ clientSubject = lc.getSubject();
+ debug("LoginContext subject {}", clientSubject);
final SaslClient saslClient = createSaslClient(clientSubject);
return performNegotiation(clientSubject, saslClient, negotiator);
}
finally
{
- lc.logout();
+ if (clientSubject != null)
+ {
+ lc.logout();
+ }
}
}
+ private void debug(String message, Object... args)
+ {
+ UTILS.debug(message, args);
+ }
+
private AuthenticationResult performNegotiation(final Subject clientSubject,
final SaslClient saslClient,
final SaslNegotiator negotiator)
@@ -223,6 +223,7 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
if (!initiated)
{
initiated = true;
+ debug("Sending initial challenge");
response = Subject.doAs(clientSubject, (PrivilegedExceptionAction<byte[]>) () -> {
if (saslClient.hasInitialResponse())
{
@@ -230,19 +231,25 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
}
return null;
});
+ debug("Initial challenge sent");
}
+ debug("Handling response: {}", StringUtil.toHex(response));
result = negotiator.handleResponse(response);
byte[] challenge = result.getChallenge();
+
if (challenge != null)
{
+ debug("Challenge: {}", StringUtil.toHex(challenge));
response = Subject.doAs(clientSubject,
(PrivilegedExceptionAction<byte[]>) () -> saslClient.evaluateChallenge(
challenge));
}
}
while (result.getStatus() == AuthenticationResult.AuthenticationStatus.CONTINUE);
+
+ debug("Result {}", result.getStatus());
return result;
}
@@ -256,7 +263,7 @@ public class KerberosAuthenticationManagerTest extends UnitTestBase
return Sasl.createSaslClient(new String[]{GSSAPI_MECHANISM},
null,
SERVER_PROTOCOL,
- SERVER_NAME,
+ HOST_NAME,
props,
null);
});
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
index 3f6efa5..ed33947 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
@@ -20,7 +20,7 @@ package org.apache.qpid.server.security.auth.manager;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.qpid.server.security.auth.manager.CachingAuthenticationProvider.AUTHENTICATION_CACHE_MAX_SIZE;
-import static org.hamcrest.Matchers.not;
+import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
@@ -31,8 +31,6 @@ import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
-import java.net.URL;
-import java.net.URLDecoder;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.security.Principal;
@@ -49,7 +47,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
-import org.apache.commons.codec.CharEncoding;
import org.apache.directory.api.ldap.model.constants.SupportedSaslMechanisms;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
@@ -91,6 +88,7 @@ import org.apache.qpid.server.security.auth.SocketConnectionPrincipal;
import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
import org.apache.qpid.server.security.auth.sasl.SaslSettings;
import org.apache.qpid.test.utils.JvmVendor;
+import org.apache.qpid.server.test.KerberosUtilities;
import org.apache.qpid.test.utils.SystemPropertySetter;
import org.apache.qpid.test.utils.TestFileUtils;
import org.apache.qpid.test.utils.UnitTestBase;
@@ -147,9 +145,9 @@ public class SimpleLDAPAuthenticationManagerTest extends UnitTestBase
private static final String HOSTNAME = "localhost";
private static final String BROKER_PRINCIPAL = "service/" + HOSTNAME;
private static final String LINE_SEPARATOR = System.lineSeparator();
- private static final String LOGIN_CONFIG = "login.config";
private static final String LOGIN_SCOPE = "ldap-gssapi-bind";
private static final AtomicBoolean KERBEROS_SETUP = new AtomicBoolean();
+ private static final KerberosUtilities UTILS = new KerberosUtilities();
@ClassRule
public static CreateLdapServerRule LDAP = new CreateLdapServerRule();
@@ -400,14 +398,11 @@ public class SimpleLDAPAuthenticationManagerTest extends UnitTestBase
createPrincipal("Service", "LDAP Service", "ldap", UUID.randomUUID().toString(), servicePrincipalName);
}
- private void setUpJaas() throws LdapException, IOException
+ private void setUpJaas() throws Exception
{
createKeyTab(BROKER_PRINCIPAL);
- final URL resource = SimpleLDAPAuthenticationManagerTest.class.getClassLoader().getResource(LOGIN_CONFIG);
- LOGGER.debug("JAAS config:" + resource);
- assertNotNull(resource);
- SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config", URLDecoder.decode(resource.getPath(), CharEncoding.UTF_8));
- SYSTEM_PROPERTY_SETTER.setSystemProperty("sun.security.krb5.debug", "true");
+
+ UTILS.prepareConfiguration(KerberosUtilities.HOST_NAME, SYSTEM_PROPERTY_SETTER);
}
private String createKrb5Conf(final int port) throws IOException
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java
index d3f8342..bbd65a4 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SpnegoAuthenticatorTest.java
@@ -19,52 +19,45 @@
package org.apache.qpid.server.security.auth.manager;
-import static org.apache.commons.codec.CharEncoding.UTF_8;
-import static org.hamcrest.Matchers.not;
+import static org.apache.qpid.server.test.KerberosUtilities.ACCEPT_SCOPE;
+import static org.apache.qpid.server.test.KerberosUtilities.HOST_NAME;
+import static org.apache.qpid.server.test.KerberosUtilities.REALM;
+import static org.apache.qpid.server.test.KerberosUtilities.SERVICE_PRINCIPAL_NAME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import java.net.URL;
-import java.net.URLDecoder;
+import java.io.File;
import java.security.Principal;
import java.util.Base64;
import java.util.Map;
-import org.ietf.jgss.GSSException;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.apache.qpid.server.security.TokenCarryingPrincipal;
import org.apache.qpid.server.security.auth.AuthenticationResult;
import org.apache.qpid.server.test.EmbeddedKdcResource;
import org.apache.qpid.server.test.KerberosUtilities;
-import org.apache.qpid.test.utils.JvmVendor;
import org.apache.qpid.test.utils.SystemPropertySetter;
import org.apache.qpid.test.utils.UnitTestBase;
public class SpnegoAuthenticatorTest extends UnitTestBase
{
- private static final Logger LOGGER = LoggerFactory.getLogger(SpnegoAuthenticatorTest.class);
- private static final String CLIENT_NAME = "client";
- private static final String SERVER_NAME = "AMQP/localhost";
- private static final String ANOTHER_SERVICE = "foo/localhost";
- private static final String REALM = "QPID.ORG";
- private static final String LOGIN_CONFIG = "login.config";
- private static final KerberosUtilities UTILS = new KerberosUtilities();;
+ private static final String ANOTHER_SERVICE = "foo/" + HOST_NAME;
+ private static final String ANOTHER_SERVICE_FULL_NAME = ANOTHER_SERVICE + "@" + REALM;
+ private static final KerberosUtilities UTILS = new KerberosUtilities();
@ClassRule
- public static final EmbeddedKdcResource KDC = new EmbeddedKdcResource(REALM);
+ public static final EmbeddedKdcResource KDC = new EmbeddedKdcResource(HOST_NAME, 0, "QpidTestKerberosServer", REALM);
@ClassRule
public static final SystemPropertySetter SYSTEM_PROPERTY_SETTER = new SystemPropertySetter();
+ private static File _clientKeyTab;
private SpnegoAuthenticator _spnegoAuthenticator;
private KerberosAuthenticationManager _kerberosAuthenticationManager;
@@ -72,31 +65,25 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
@BeforeClass
public static void createKeyTabs() throws Exception
{
- assumeThat(getJvmVendor(), not(JvmVendor.IBM));
- KDC.createPrincipal("broker.keytab", SERVER_NAME + "@" + REALM);
- KDC.createPrincipal("client.keytab", CLIENT_NAME + "@" + REALM);
- KDC.createPrincipal("another.keytab", ANOTHER_SERVICE + "@" + REALM);
- final URL resource = KerberosAuthenticationManagerTest.class.getClassLoader().getResource(LOGIN_CONFIG);
- LOGGER.debug("JAAS config:" + resource);
- assertNotNull(resource);
- SYSTEM_PROPERTY_SETTER.setSystemProperty("java.security.auth.login.config", URLDecoder.decode(resource.getPath(), UTF_8));
- SYSTEM_PROPERTY_SETTER.setSystemProperty("javax.security.auth.useSubjectCredsOnly", "false");
+ KDC.createPrincipal("another.keytab", ANOTHER_SERVICE_FULL_NAME);
+ UTILS.prepareConfiguration(HOST_NAME, SYSTEM_PROPERTY_SETTER);
+ _clientKeyTab = UTILS.prepareKeyTabs(KDC);
}
@Before
public void setUp()
{
_kerberosAuthenticationManager = mock(KerberosAuthenticationManager.class);
- when(_kerberosAuthenticationManager.getSpnegoLoginConfigScope()).thenReturn("com.sun.security.jgss.accept");
+ when(_kerberosAuthenticationManager.getSpnegoLoginConfigScope()).thenReturn(ACCEPT_SCOPE);
when(_kerberosAuthenticationManager.isStripRealmFromPrincipalName()).thenReturn(true);
_spnegoAuthenticator = new SpnegoAuthenticator(_kerberosAuthenticationManager);
}
@Test
- public void testAuthenticate() throws GSSException
+ public void testAuthenticate() throws Exception
{
- final String token = Base64.getEncoder().encodeToString(buildToken(SERVER_NAME));
+ final String token = Base64.getEncoder().encodeToString(buildToken(SERVICE_PRINCIPAL_NAME));
final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
final AuthenticationResult result = _spnegoAuthenticator.authenticate(authenticationHeader);
@@ -105,7 +92,7 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
assertEquals(AuthenticationResult.AuthenticationStatus.SUCCESS, result.getStatus());
final Principal principal = result.getMainPrincipal();
assertTrue(principal instanceof TokenCarryingPrincipal);
- assertEquals(CLIENT_NAME, principal.getName());
+ assertEquals(KerberosUtilities.CLIENT_PRINCIPAL_NAME, principal.getName());
final Map<String, String> tokens = ((TokenCarryingPrincipal)principal).getTokens();
assertNotNull(tokens);
@@ -121,9 +108,9 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
}
@Test
- public void testAuthenticateNoNegotiatePrefix() throws GSSException
+ public void testAuthenticateNoNegotiatePrefix() throws Exception
{
- final String token = Base64.getEncoder().encodeToString(buildToken(SERVER_NAME));
+ final String token = Base64.getEncoder().encodeToString(buildToken(SERVICE_PRINCIPAL_NAME));
final AuthenticationResult result = _spnegoAuthenticator.authenticate(token);
assertNotNull(result);
assertEquals(AuthenticationResult.AuthenticationStatus.ERROR, result.getStatus());
@@ -148,10 +135,10 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
}
@Test
- public void testAuthenticateWrongConfigName() throws GSSException
+ public void testAuthenticateWrongConfigName() throws Exception
{
when(_kerberosAuthenticationManager.getSpnegoLoginConfigScope()).thenReturn("foo");
- final String token = Base64.getEncoder().encodeToString(buildToken(SERVER_NAME));
+ final String token = Base64.getEncoder().encodeToString(buildToken(SERVICE_PRINCIPAL_NAME));
final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
final AuthenticationResult result = _spnegoAuthenticator.authenticate(authenticationHeader);
@@ -160,7 +147,7 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
}
@Test
- public void testAuthenticateWrongServer() throws GSSException
+ public void testAuthenticateWrongServer() throws Exception
{
final String token = Base64.getEncoder().encodeToString(buildToken(ANOTHER_SERVICE));
final String authenticationHeader = SpnegoAuthenticator.NEGOTIATE_PREFIX + token;
@@ -170,8 +157,8 @@ public class SpnegoAuthenticatorTest extends UnitTestBase
assertEquals(AuthenticationResult.AuthenticationStatus.ERROR, result.getStatus());
}
- private byte[] buildToken(final String anotherService) throws GSSException
+ private byte[] buildToken(final String anotherService) throws Exception
{
- return UTILS.buildToken(CLIENT_NAME, anotherService);
+ return UTILS.buildToken(KerberosUtilities.CLIENT_PRINCIPAL_NAME, _clientKeyTab, anotherService);
}
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java b/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java
index cda31a8..8224189 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/test/EmbeddedKdcResource.java
@@ -21,11 +21,11 @@ package org.apache.qpid.server.test;
import java.io.File;
import java.io.IOException;
-import java.net.InetAddress;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
@@ -46,11 +46,6 @@ public class EmbeddedKdcResource extends ExternalResource
private final List<File> _createdFiles = new ArrayList<>();
private volatile File _kdcDirectory;
- public EmbeddedKdcResource(final String realm)
- {
- this(InetAddress.getLoopbackAddress().getCanonicalHostName(), 0, "QpidTestKerberosServer", realm);
- }
-
public EmbeddedKdcResource(final String host, final int port, final String serviceName, final String realm)
{
_realm = realm;
@@ -80,6 +75,7 @@ public class EmbeddedKdcResource extends ExternalResource
_simpleKdcServer.setWorkDir(_kdcDirectory);
_simpleKdcServer.init();
_simpleKdcServer.start();
+ LOGGER.info("SimpleKdcServer started on port {}, realm '{}'", getPort(), getRealm());
}
@Override
@@ -149,7 +145,8 @@ public class EmbeddedKdcResource extends ExternalResource
public File createPrincipal(String keyTabFileName, String... principals)
throws Exception
{
- final File ketTabFile = createFile(keyTabFileName);
+ final Path ketTabPath = Paths.get("target", keyTabFileName);
+ final File ketTabFile = ketTabPath.toFile();
_createdFiles.add(ketTabFile);
createPrincipal(ketTabFile, principals);
return ketTabFile;
@@ -175,22 +172,4 @@ public class EmbeddedKdcResource extends ExternalResource
}
}
- private static File createFile(final String keyTabFile) throws IOException
- {
- final File target = FileSystems.getDefault().getPath("target").toFile();
- final File file = new File(target, keyTabFile);
- if (file.exists())
- {
- if (!file.delete())
- {
- throw new IOException(String.format("Cannot delete existing file '%s'", keyTabFile));
- }
- }
- if (!file.createNewFile())
- {
- throw new IOException(String.format("Cannot create file '%s'", keyTabFile));
- }
- return file;
- }
-
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java b/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java
index 182df06..88fe2db 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/test/KerberosUtilities.java
@@ -20,8 +20,20 @@
package org.apache.qpid.server.test;
import static java.lang.Boolean.TRUE;
+import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -38,6 +50,7 @@ import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
+import com.google.common.io.ByteStreams;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
@@ -47,22 +60,112 @@ import org.ietf.jgss.Oid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.qpid.test.utils.JvmVendor;
+import org.apache.qpid.test.utils.SystemPropertySetter;
+
public class KerberosUtilities
{
+ public static final String REALM = "QPID.ORG";
+ public static final String HOST_NAME = InetAddress.getLoopbackAddress().getCanonicalHostName();
+ public static final String CLIENT_PRINCIPAL_NAME = "client";
+ public static final String CLIENT_PRINCIPAL_FULL_NAME = CLIENT_PRINCIPAL_NAME + "@" + REALM;
+ public static final String SERVER_PROTOCOL = "AMQP";
+ public static final String SERVICE_PRINCIPAL_NAME = SERVER_PROTOCOL + "/" + HOST_NAME;
+ public static final String ACCEPT_SCOPE = isIBM() ? "com.ibm.security.jgss.krb5.accept" : "com.sun.security.jgss.accept";
+ private static final String USE_SUBJECT_CREDS_ONLY = "javax.security.auth.useSubjectCredsOnly";
+ public static final String LOGIN_CONFIG = "java.security.auth.login.config";
+
+ private static final String INITIATE_SCOPE = isIBM() ? "com.ibm.security.jgss.krb5.initiate" : "com.sun.security.jgss.initiate";
private static final Logger LOGGER = LoggerFactory.getLogger(KerberosUtilities.class);
private static final String IBM_LOGIN_MODULE_CLASS = "com.ibm.security.auth.module.Krb5LoginModule";
private static final String SUN_LOGIN_MODULE_CLASS = "com.sun.security.auth.module.Krb5LoginModule";
- public static final String KERBEROS_LOGIN_MODULE_CLASS =
- System.getProperty("java.vendor").contains("IBM") ? IBM_LOGIN_MODULE_CLASS : SUN_LOGIN_MODULE_CLASS;
+ private static final String KERBEROS_LOGIN_MODULE_CLASS = isIBM() ? IBM_LOGIN_MODULE_CLASS : SUN_LOGIN_MODULE_CLASS;
+ private static final String LOGIN_CONFIG_RESOURCE = "login.config";
+ private static final String LOGIN_IBM_CONFIG_RESOURCE = "login.ibm.config";
+ private static final String SERVICE_PRINCIPAL_FULL_NAME = SERVICE_PRINCIPAL_NAME + "@" + REALM;
+ private static final String BROKER_KEYTAB = "broker.keytab";
+ private static final String CLIENT_KEYTAB = "client.keytab";
+
+
+ public File prepareKeyTabs(final EmbeddedKdcResource kdc) throws Exception
+ {
+ final File clientKeyTabFile;
+ kdc.createPrincipal(BROKER_KEYTAB, SERVICE_PRINCIPAL_FULL_NAME);
+ clientKeyTabFile = kdc.createPrincipal(CLIENT_KEYTAB, CLIENT_PRINCIPAL_FULL_NAME);
+ return clientKeyTabFile;
+ }
+
+ public void prepareConfiguration(final String hostName, final SystemPropertySetter systemPropertySetter)
+ throws IOException
+ {
+ final Path loginConfig = transformLoginConfig(hostName);
+ systemPropertySetter.setSystemProperty(LOGIN_CONFIG,
+ URLDecoder.decode(loginConfig.toFile().getAbsolutePath(), UTF_8.name()));
+ systemPropertySetter.setSystemProperty(USE_SUBJECT_CREDS_ONLY, "false");
+ }
+
+ public byte[] buildToken(String clientPrincipalName, File clientKeyTabFile, String targetServerPrincipalName)
+ throws Exception
+ {
+ final LoginContext lc = createKerberosKeyTabLoginContext("test",
+ clientPrincipalName,
+ clientKeyTabFile);
+
+ Subject clientSubject = null;
+ String useSubjectCredsOnly = System.getProperty(USE_SUBJECT_CREDS_ONLY);
+ try
+ {
+ debug("Before login");
+ lc.login();
+ clientSubject = lc.getSubject();
+ debug("LoginContext subject {}", clientSubject);
+ System.setProperty(USE_SUBJECT_CREDS_ONLY, "true");
+ return Subject.doAs(clientSubject,
+ (PrivilegedExceptionAction<byte[]>) () -> buildTokenWithinSubjectWithKerberosTicket(
+ clientPrincipalName,
+ targetServerPrincipalName));
+ }
+ finally
+ {
+ if (useSubjectCredsOnly == null)
+ {
+ System.clearProperty(USE_SUBJECT_CREDS_ONLY);
+ }
+ else
+ {
+ System.setProperty(USE_SUBJECT_CREDS_ONLY, useSubjectCredsOnly);
+ }
+ if (clientSubject != null)
+ {
+ lc.logout();
+ }
+ }
+ }
- public byte[] buildToken(String clientPrincipalName, String targetServerPrincipalName) throws GSSException
+ private byte[] buildTokenWithinSubjectWithKerberosTicket(String clientPrincipalName,
+ String targetServerPrincipalName) throws GSSException
{
+ debug("Building token for client principal '{}' and server principal '{}'",
+ clientPrincipalName,
+ targetServerPrincipalName);
+
final GSSManager manager = GSSManager.getInstance();
final GSSName clientName = manager.createName(clientPrincipalName, GSSName.NT_USER_NAME);
- final GSSCredential credential = manager.createCredential(clientName,
- GSSCredential.DEFAULT_LIFETIME,
- new Oid("1.2.840.113554.1.2.2"),
- GSSCredential.INITIATE_ONLY);
+ final GSSCredential credential;
+ try
+ {
+ credential = manager.createCredential(clientName,
+ GSSCredential.DEFAULT_LIFETIME,
+ new Oid("1.2.840.113554.1.2.2"),
+ GSSCredential.INITIATE_ONLY);
+ }
+ catch (GSSException e)
+ {
+ debug("Failure to create credential for {}", clientName, e);
+ throw e;
+ }
+
+ debug("Client credential '{}'", credential);
final GSSName serverName = manager.createName(targetServerPrincipalName, GSSName.NT_USER_NAME);
final Oid spnegoMechOid = new Oid("1.3.6.1.5.5.2");
@@ -70,11 +173,20 @@ public class KerberosUtilities
spnegoMechOid,
credential,
GSSContext.DEFAULT_LIFETIME);
+
+ debug("Requesting ticket using initiator's credentials");
+
try
{
clientContext.requestCredDeleg(true);
+ debug("Requesting ticket");
return clientContext.initSecContext(new byte[]{}, 0, 0);
}
+ catch (GSSException e)
+ {
+ debug("Failure to request token", e);
+ throw e;
+ }
finally
{
clientContext.dispose();
@@ -166,10 +278,19 @@ public class KerberosUtilities
{
final Map<String, String> options = new HashMap<>();
options.put("principal", principalName);
- options.put("useKeyTab", TRUE.toString());
- options.put("keyTab", keyTabFile.getAbsolutePath());
- options.put("refreshKrb5Config", TRUE.toString());
- options.put("doNotPrompt", TRUE.toString());
+
+ if (isIBM())
+ {
+ options.put("useKeytab", keyTabFile.getAbsolutePath());
+ options.put("credsType", "both");
+ }
+ else
+ {
+ options.put("keyTab", keyTabFile.getAbsolutePath());
+ options.put("useKeyTab", TRUE.toString());
+ options.put("doNotPrompt", TRUE.toString());
+ options.put("refreshKrb5Config", TRUE.toString());
+ }
_entry = new AppConfigurationEntry(KERBEROS_LOGIN_MODULE_CLASS,
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
options);
@@ -186,4 +307,57 @@ public class KerberosUtilities
return new AppConfigurationEntry[0];
}
}
+
+ public void debug(String message, Object... args)
+ {
+ LOGGER.debug(message, args);
+ if (Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty("sun.security.krb5.debug")))
+ {
+ System.out.println(String.format(message.replace("{}", "%s"), args));
+ }
+ }
+
+ private Path transformLoginConfig(String hostName) throws IOException
+ {
+ final String resourceName = isIBM() ? LOGIN_IBM_CONFIG_RESOURCE : LOGIN_CONFIG_RESOURCE;
+ final URL resource = KerberosUtilities.class.getClassLoader().getResource(resourceName);
+ if (resource == null)
+ {
+ throw new IllegalArgumentException(String.format("Unknown resource '%s'", resourceName));
+ }
+ final String config;
+ try (InputStream is = resource.openStream())
+ {
+ config = new String(ByteStreams.toByteArray(is), UTF_8);
+ }
+ catch (IOException e)
+ {
+ throw new IOException(String.format("Failed to load resource '%s'", resource.toExternalForm()), e);
+ }
+ final String newConfig = config.replace("AMQP/localhost", "AMQP/" + hostName)
+ .replace("target/" + BROKER_KEYTAB, toAbsolutePath(BROKER_KEYTAB))
+ .replace("target/" + CLIENT_KEYTAB, toAbsolutePath(CLIENT_KEYTAB));
+
+ final Path file = Paths.get("target", LOGIN_CONFIG_RESOURCE);
+ Files.write(file,
+ newConfig.getBytes(UTF_8),
+ StandardOpenOption.WRITE,
+ StandardOpenOption.CREATE,
+ StandardOpenOption.TRUNCATE_EXISTING);
+ return file.toRealPath(LinkOption.NOFOLLOW_LINKS);
+ }
+
+ private String toAbsolutePath(String fileName)
+ {
+ final Path path = Paths.get("target", fileName)
+ .toAbsolutePath()
+ .normalize();
+ return path.toUri().getPath();
+ }
+
+ private static boolean isIBM()
+ {
+ return JvmVendor.getJvmVendor() == JvmVendor.IBM;
+ }
+
}
diff --git a/broker-core/src/test/resources/login.ibm.config b/broker-core/src/test/resources/login.ibm.config
new file mode 100644
index 0000000..6e85f6e
--- /dev/null
+++ b/broker-core/src/test/resources/login.ibm.config
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+ldap-gssapi-bind {
+ com.ibm.security.auth.module.Krb5LoginModule required
+ credsType="both"
+ principal="service/localhost@QPID.ORG"
+ useKeytab="target/kerberos.keytab";
+};
+
+ldap-gssapi-bind-broken {
+ com.ibm.security.auth.module.Krb5LoginModule required
+ credsType="both"
+ principal="service/localhost@QPID.ORG"
+ useKeytab="target/kerberos-non-existing.keytab";
+};
+
+qpid-broker-j {
+ com.ibm.security.auth.module.Krb5LoginModule required
+ credsType="both"
+ principal="service/localhost@QPID.ORG"
+ useKeytab="target/kerberos.keytab";
+};
+
+com.ibm.security.jgss.krb5.accept {
+ com.ibm.security.auth.module.Krb5LoginModule required
+ credsType="acceptor"
+ principal="AMQP/localhost@QPID.ORG"
+ useKeytab="target/broker.keytab";
+};
+
+com.ibm.security.jgss.krb5.initiate {
+ com.ibm.security.auth.module.Krb5LoginModule required
+ credsType="both"
+ principal="client@QPID.ORG"
+ useKeytab="target/client.keytab";
+};
diff --git a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java
index bd176d7..9ed7c28 100644
--- a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java
+++ b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/JvmVendor.java
@@ -20,10 +20,33 @@
package org.apache.qpid.test.utils;
+import com.google.common.base.StandardSystemProperty;
+
public enum JvmVendor
{
ORACLE,
IBM,
OPENJDK,
- UNKNOWN
+ UNKNOWN;
+
+ public static JvmVendor getJvmVendor()
+ {
+ final String property = String.valueOf(System.getProperty(StandardSystemProperty.JAVA_VENDOR.key())).toUpperCase();
+ if (property.contains("IBM"))
+ {
+ return JvmVendor.IBM;
+ }
+ else if (property.contains("ORACLE"))
+ {
+ return JvmVendor.ORACLE;
+ }
+ else if (property.contains("OPENJDK"))
+ {
+ return JvmVendor.OPENJDK;
+ }
+ else
+ {
+ return JvmVendor.UNKNOWN;
+ }
+ }
}
diff --git a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java
index 4dcfab0..4d71700 100644
--- a/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java
+++ b/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/UnitTestBase.java
@@ -77,23 +77,7 @@ public class UnitTestBase
public static JvmVendor getJvmVendor()
{
- final String property = String.valueOf(System.getProperty(StandardSystemProperty.JAVA_VENDOR.key())).toUpperCase();
- if (property.contains("IBM"))
- {
- return JvmVendor.IBM;
- }
- else if (property.contains("ORACLE"))
- {
- return JvmVendor.ORACLE;
- }
- else if (property.contains("OPENJDK"))
- {
- return JvmVendor.OPENJDK;
- }
- else
- {
- return JvmVendor.UNKNOWN;
- }
+ return JvmVendor.getJvmVendor();
}
public VirtualHostNodeStoreType getVirtualHostNodeStoreType()
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 07/10: QPID-8455: [Broker-J] Add allow/deny list
alternatives for existing black/whilte list attributes and context
variables
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit ec885c06e367739e5741d15d12ea6124c30e199d
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Wed Sep 2 17:11:55 2020 +0100
QPID-8455: [Broker-J] Add allow/deny list alternatives for existing black/whilte list attributes and context variables
---
.../server/configuration/CommonProperties.java | 5 ++
.../server/model/AbstractConfiguredObject.java | 15 ++++
.../java/org/apache/qpid/server/model/Port.java | 17 ++++
.../qpid/server/model/port/AbstractPort.java | 32 +++++++-
.../manager/SimpleLDAPAuthenticationManager.java | 16 ++++
.../SimpleLDAPAuthenticationManagerImpl.java | 32 +++++++-
.../oauth2/OAuth2AuthenticationProvider.java | 18 +++++
.../oauth2/OAuth2AuthenticationProviderImpl.java | 32 +++++++-
...oudFoundryDashboardManagementGroupProvider.java | 14 ++++
...oundryDashboardManagementGroupProviderImpl.java | 37 ++++++++-
.../apache/qpid/server/util/ConnectionBuilder.java | 24 ++++++
.../qpid/server/model/port/AmqpPortImplTest.java | 87 +++++++++++++++++++++
.../SimpleLDAPAuthenticationManagerTest.java | 69 ++++++++++++++++
.../OAuth2AuthenticationProviderImplTest.java | 91 +++++++++++++++++++---
.../qpid/systests/admin/SpawnBrokerAdmin.java | 26 ++++---
.../qpid/systests/admin/SpawnBrokerAdminTest.java | 16 +++-
16 files changed, 490 insertions(+), 41 deletions(-)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/configuration/CommonProperties.java b/broker-core/src/main/java/org/apache/qpid/server/configuration/CommonProperties.java
index 600f985..171d897 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/configuration/CommonProperties.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/configuration/CommonProperties.java
@@ -64,6 +64,11 @@ public class CommonProperties
public static final String QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST = "qpid.security.tls.cipherSuiteBlackList";
public static final String QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST_DEFAULT = "";
+ public static final String QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST = "qpid.security.tls.protocolAllowList";
+ public static final String QPID_SECURITY_TLS_PROTOCOL_DENY_LIST = "qpid.security.tls.protocolDenyList";
+ public static final String QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST = "qpid.security.tls.cipherSuiteAllowList";
+ public static final String QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST = "qpid.security.tls.cipherSuiteDenyList";
+
private static final String MANIFEST_HEADER_IMPLEMENTATION_BUILD = "Implementation-Build";
/** Defines the name of the version suffix property. */
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index 267356c..38d7135 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -3498,6 +3498,21 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
return converter.convert("${" + propertyName + "}", this);
}
+ protected <T> T getContextValue(final Class<T> clazz, final Type type, final String propertyName, final String fallbackName)
+ {
+ final Set<String> keys = getContextKeys(false);
+ String name;
+ if (keys.contains(propertyName))
+ {
+ name = propertyName;
+ }
+ else
+ {
+ name = fallbackName;
+ }
+ return getContextValue(clazz, type, name);
+ }
+
@Override
public Set<String> getContextKeys(final boolean excludeSystem)
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
index 510d4d5..a5aac32 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
@@ -90,18 +90,35 @@ public interface Port<X extends Port<X>> extends ConfiguredObject<X>
@ManagedAttribute
Collection<TrustStore> getTrustStores();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolBlackList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteBlackList();
+ @DerivedAttribute
+ List<String> getTlsProtocolAllowList();
+
+ @DerivedAttribute
+ List<String> getTlsProtocolDenyList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteAllowList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteDenyList();
+
+
@ManagedAttribute(defaultValue = "*",
description = "The network interface this port binds to expressed as an IP address or a"
+ "hostname. If null or * then bind to all interfaces.")
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
index a5fb3d2..f8d0b05 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
@@ -109,10 +109,10 @@ public abstract class AbstractPort<X extends AbstractPort<X>> extends AbstractCo
protected void onOpen()
{
super.onOpen();
- _tlsProtocolWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
- _tlsProtocolBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
- _tlsCipherSuiteWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
- _tlsCipherSuiteBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
+ _tlsProtocolWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
+ _tlsProtocolBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
+ _tlsCipherSuiteWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
+ _tlsCipherSuiteBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
}
@Override
@@ -447,6 +447,30 @@ public abstract class AbstractPort<X extends AbstractPort<X>> extends AbstractCo
}
@Override
+ public List<String> getTlsProtocolAllowList()
+ {
+ return getTlsProtocolWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsProtocolDenyList()
+ {
+ return getTlsProtocolBlackList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteAllowList()
+ {
+ return getTlsCipherSuiteWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteDenyList()
+ {
+ return getTlsCipherSuiteBlackList();
+ }
+
+ @Override
public KeyStore getKeyStore()
{
return _keyStore;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
index fe650f7..8c0e0f7 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
@@ -104,16 +104,32 @@ public interface SimpleLDAPAuthenticationManager<X extends SimpleLDAPAuthenticat
defaultValue = LOGIN_CONFIG_SCOPE_DEFAULT)
String getLoginConfigScope();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolBlackList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteBlackList();
+ @DerivedAttribute
+ List<String> getTlsProtocolAllowList();
+
+ @DerivedAttribute
+ List<String> getTlsProtocolDenyList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteAllowList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteDenyList();
+
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
index 7a18c6c..704b649 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
@@ -189,10 +189,10 @@ public class SimpleLDAPAuthenticationManagerImpl
{
super.onOpen();
- _tlsProtocolWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
- _tlsProtocolBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
- _tlsCipherSuiteWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
- _tlsCipherSuiteBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
+ _tlsProtocolWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
+ _tlsProtocolBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
+ _tlsCipherSuiteWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
+ _tlsCipherSuiteBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
Integer cacheMaxSize = getContextValue(Integer.class, AUTHENTICATION_CACHE_MAX_SIZE);
Long cacheExpirationTime = getContextValue(Long.class, AUTHENTICATION_CACHE_EXPIRATION_TIME);
@@ -793,6 +793,30 @@ public class SimpleLDAPAuthenticationManagerImpl
return _tlsCipherSuiteBlackList;
}
+ @Override
+ public List<String> getTlsProtocolAllowList()
+ {
+ return getTlsProtocolWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsProtocolDenyList()
+ {
+ return getTlsProtocolBlackList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteAllowList()
+ {
+ return getTlsCipherSuiteWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteDenyList()
+ {
+ return getTlsCipherSuiteBlackList();
+ }
+
private void closeSafely(InitialDirContext ctx)
{
try
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProvider.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProvider.java
index 9cbbcdf..1a9c95d 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProvider.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProvider.java
@@ -102,18 +102,36 @@ public interface OAuth2AuthenticationProvider<T extends OAuth2AuthenticationProv
@DerivedAttribute( description = "Default OAuth access token scope passed to the authorization endpoint")
String getDefaultScope();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolBlackList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteBlackList();
+ @DerivedAttribute
+ List<String> getTlsProtocolAllowList();
+
+ @DerivedAttribute
+ List<String> getTlsProtocolDenyList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteAllowList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteDenyList();
+
+
+
int getConnectTimeout();
int getReadTimeout();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java
index 6854bd5..583263c 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImpl.java
@@ -130,10 +130,10 @@ public class OAuth2AuthenticationProviderImpl
super.onOpen();
String type = getIdentityResolverType();
_identityResolverService = new QpidServiceLoader().getInstancesByType(OAuth2IdentityResolverService.class).get(type);
- _tlsProtocolWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
- _tlsProtocolBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
- _tlsCipherSuiteWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
- _tlsCipherSuiteBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
+ _tlsProtocolWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
+ _tlsProtocolBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
+ _tlsCipherSuiteWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
+ _tlsCipherSuiteBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
_connectTimeout = getContextValue(Integer.class, AUTHENTICATION_OAUTH2_CONNECT_TIMEOUT);
_readTimeout = getContextValue(Integer.class, AUTHENTICATION_OAUTH2_READ_TIMEOUT);
@@ -520,6 +520,30 @@ public class OAuth2AuthenticationProviderImpl
}
@Override
+ public List<String> getTlsProtocolAllowList()
+ {
+ return getTlsProtocolWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsProtocolDenyList()
+ {
+ return getTlsProtocolBlackList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteAllowList()
+ {
+ return getTlsCipherSuiteWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteDenyList()
+ {
+ return getTlsCipherSuiteBlackList();
+ }
+
+ @Override
public int getConnectTimeout()
{
return _connectTimeout;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProvider.java b/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProvider.java
index fd1c5a0..2a7dd73 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProvider.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProvider.java
@@ -51,12 +51,26 @@ public interface CloudFoundryDashboardManagementGroupProvider<X extends CloudFou
@ManagedAttribute( description = "A service instance id to qpid management group mapping. If the CloudFoundry endpoint grants a user permission to manage a service instance the user will be associated with the corresponding management group.", mandatory = true )
Map<String, String> getServiceToManagementGroupMapping();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsProtocolBlackList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteWhiteList();
+ @Deprecated
@DerivedAttribute
List<String> getTlsCipherSuiteBlackList();
+
+ @DerivedAttribute
+ List<String> getTlsProtocolAllowList();
+ @DerivedAttribute
+ List<String> getTlsProtocolDenyList();
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteAllowList();
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteDenyList();
+
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProviderImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProviderImpl.java
index 88659b5..7818e89 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProviderImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/group/cloudfoundry/CloudFoundryDashboardManagementGroupProviderImpl.java
@@ -21,8 +21,12 @@
package org.apache.qpid.server.security.group.cloudfoundry;
import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST;
+import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST;
+import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST;
import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST;
import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST;
+import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST;
+import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST;
import static org.apache.qpid.server.configuration.CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST;
import static org.apache.qpid.server.util.ParameterizedTypes.LIST_OF_STRINGS;
@@ -106,10 +110,10 @@ public class CloudFoundryDashboardManagementGroupProviderImpl extends AbstractCo
public void onOpen()
{
super.onOpen();
- _tlsProtocolWhiteList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
- _tlsProtocolBlackList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
- _tlsCipherSuiteWhiteList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
- _tlsCipherSuiteBlackList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
+ _tlsProtocolWhiteList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
+ _tlsProtocolBlackList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
+ _tlsCipherSuiteWhiteList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
+ _tlsCipherSuiteBlackList = getContextValue(List.class, LIST_OF_STRINGS, QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
_connectTimeout = getContextValue(Integer.class, QPID_GROUPPROVIDER_CLOUDFOUNDRY_CONNECT_TIMEOUT);
_readTimeout = getContextValue(Integer.class, QPID_GROUPPROVIDER_CLOUDFOUNDRY_READ_TIMEOUT);
}
@@ -313,4 +317,29 @@ public class CloudFoundryDashboardManagementGroupProviderImpl extends AbstractCo
return _tlsCipherSuiteBlackList;
}
+ @Override
+ public List<String> getTlsProtocolAllowList()
+ {
+ return getTlsProtocolWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsProtocolDenyList()
+ {
+ return getTlsProtocolBlackList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteAllowList()
+ {
+ return getTlsCipherSuiteWhiteList();
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteDenyList()
+ {
+ return getTlsCipherSuiteBlackList();
+ }
+
+
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/util/ConnectionBuilder.java b/broker-core/src/main/java/org/apache/qpid/server/util/ConnectionBuilder.java
index a418e76..f00d8d6 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/util/ConnectionBuilder.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/util/ConnectionBuilder.java
@@ -77,30 +77,54 @@ public class ConnectionBuilder
return this;
}
+ @Deprecated
public ConnectionBuilder setTlsProtocolWhiteList(final List<String> tlsProtocolWhiteList)
{
_tlsProtocolWhiteList = tlsProtocolWhiteList;
return this;
}
+ @Deprecated
public ConnectionBuilder setTlsProtocolBlackList(final List<String> tlsProtocolBlackList)
{
_tlsProtocolBlackList = tlsProtocolBlackList;
return this;
}
+ @Deprecated
public ConnectionBuilder setTlsCipherSuiteWhiteList(final List<String> tlsCipherSuiteWhiteList)
{
_tlsCipherSuiteWhiteList = tlsCipherSuiteWhiteList;
return this;
}
+ @Deprecated
public ConnectionBuilder setTlsCipherSuiteBlackList(final List<String> tlsCipherSuiteBlackList)
{
_tlsCipherSuiteBlackList = tlsCipherSuiteBlackList;
return this;
}
+ public ConnectionBuilder setTlsProtocolAllowList(final List<String> tlsProtocolAllowList)
+ {
+ return setTlsProtocolWhiteList(tlsProtocolAllowList);
+ }
+
+ public ConnectionBuilder setTlsProtocolDenyList(final List<String> tlsProtocolDenyList)
+ {
+ return setTlsProtocolBlackList(tlsProtocolDenyList);
+ }
+
+ public ConnectionBuilder setTlsCipherSuiteAllowList(final List<String> tlsCipherSuiteAllowList)
+ {
+ return setTlsCipherSuiteWhiteList(tlsCipherSuiteAllowList);
+ }
+
+ public ConnectionBuilder setTlsCipherSuiteDenyList(final List<String> tlsCipherSuiteDenyList)
+ {
+ return setTlsCipherSuiteBlackList(tlsCipherSuiteDenyList);
+ }
+
public HttpURLConnection build() throws IOException
{
HttpURLConnection connection = (HttpURLConnection) _url.openConnection();
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java b/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
index 4775334..21c0b8d 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
@@ -19,8 +19,11 @@
package org.apache.qpid.server.model.port;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
@@ -37,6 +40,7 @@ import java.security.Principal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -44,6 +48,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.apache.qpid.server.configuration.CommonProperties;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
@@ -327,6 +332,88 @@ public class AmqpPortImplTest extends UnitTestBase
assertFalse(_port.canAcceptNewConnection(new InetSocketAddress("example.org", 0)));
}
+ @Test
+ public void testTlProtocolsAndCypherSuitesUsingAllowDenyListContextVariable()
+ {
+ final Map<String, String> brokerContext = new HashMap<>();
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, "[\"TLSv1.3\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.2\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, "[\"(TLS|SSL)_AES_128_GCM_SHA256\", \"(TLS|SSL)_AES_256_GCM_SHA384\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, "[\".*CBC.*\"]");
+
+ when(_broker.getContext()).thenReturn(brokerContext);
+
+ _port = createPort(getTestName());
+ final List<String> expectedAllowedTlsProtocols = Collections.singletonList("TLSv1.3");
+ final List<String> expectedDeniedTlsProtocols = Arrays.asList("Ssl.*","TLSv1","TLSv1.1","TLSv1.2");
+ final List<String> expectedAllowedTlsCypherSuites = Arrays.asList("(TLS|SSL)_AES_128_GCM_SHA256", "(TLS|SSL)_AES_256_GCM_SHA384");
+ final List<String> expectedDeniedTlsCypherSuites = Collections.singletonList(".*CBC.*");
+ assertThat(_port.getTlsProtocolAllowList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_port.getTlsProtocolWhiteList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_port.getTlsProtocolDenyList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_port.getTlsProtocolBlackList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_port.getTlsCipherSuiteAllowList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteWhiteList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteDenyList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteBlackList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ }
+
+ @Test
+ public void testTlProtocolsAndCypherSuitesUsingWhiteBlackListContextVariable()
+ {
+ final Map<String, String> brokerContext = new HashMap<>();
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST, "[\"TLSv1.3\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.2\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST, "[\"(TLS|SSL)_AES_128_GCM_SHA256\", \"(TLS|SSL)_AES_256_GCM_SHA384\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST, "[\".*CBC.*\"]");
+
+ when(_broker.getContext()).thenReturn(brokerContext);
+
+ _port = createPort(getTestName());
+ final List<String> expectedAllowedTlsProtocols = Collections.singletonList("TLSv1.3");
+ final List<String> expectedDeniedTlsProtocols = Arrays.asList("Ssl.*","TLSv1","TLSv1.1","TLSv1.2");
+ final List<String> expectedAllowedTlsCypherSuites = Arrays.asList("(TLS|SSL)_AES_128_GCM_SHA256", "(TLS|SSL)_AES_256_GCM_SHA384");
+ final List<String> expectedDeniedTlsCypherSuites = Collections.singletonList(".*CBC.*");
+ assertThat(_port.getTlsProtocolAllowList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_port.getTlsProtocolWhiteList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_port.getTlsProtocolDenyList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_port.getTlsProtocolBlackList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_port.getTlsCipherSuiteAllowList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteWhiteList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteDenyList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteBlackList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ }
+
+ @Test
+ public void testTlProtocolsAndCypherSuitesUsingAllowDenyAndWhiteBlackListContextVariable()
+ {
+ final Map<String, String> brokerContext = new HashMap<>();
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, "[\"TLSv1.3\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.2\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, "[\"(TLS|SSL)_AES_128_GCM_SHA256\", \"(TLS|SSL)_AES_256_GCM_SHA384\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, "[\".*CBC.*\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST, "[\"TLSv1.2\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.3\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST, "[\".*CBC.*\"]");
+ brokerContext.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST, "[\".*GCM.*\"]");
+
+ when(_broker.getContext()).thenReturn(brokerContext);
+
+ _port = createPort(getTestName());
+ final List<String> expectedAllowedTlsProtocols = Collections.singletonList("TLSv1.3");
+ final List<String> expectedDeniedTlsProtocols = Arrays.asList("Ssl.*","TLSv1","TLSv1.1","TLSv1.2");
+ final List<String> expectedAllowedTlsCypherSuites = Arrays.asList("(TLS|SSL)_AES_128_GCM_SHA256", "(TLS|SSL)_AES_256_GCM_SHA384");
+ final List<String> expectedDeniedTlsCypherSuites = Collections.singletonList(".*CBC.*");
+ assertThat(_port.getTlsProtocolAllowList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_port.getTlsProtocolWhiteList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_port.getTlsProtocolDenyList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_port.getTlsProtocolBlackList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_port.getTlsCipherSuiteAllowList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteWhiteList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteDenyList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ assertThat(_port.getTlsCipherSuiteBlackList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ }
+
private AmqpPortImpl createPort(final String portName)
{
return createPort(portName, Collections.emptyMap());
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
index ed33947..17e6eb8 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerTest.java
@@ -20,9 +20,12 @@ package org.apache.qpid.server.security.auth.manager;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.qpid.server.security.auth.manager.CachingAuthenticationProvider.AUTHENTICATION_CACHE_MAX_SIZE;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeThat;
import static org.mockito.Mockito.mock;
@@ -36,6 +39,7 @@ import java.nio.file.Path;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -80,6 +84,7 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.qpid.server.configuration.CommonProperties;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.BrokerTestHelper;
@@ -330,6 +335,70 @@ public class SimpleLDAPAuthenticationManagerTest extends UnitTestBase
assertEquals(USER_1_DN, result.getMainPrincipal().getName());
}
+ @Test
+ public void testTlProtocolsAndCypherSuitesUsingAllowDenyListContextVariable()
+ {
+ if (_authenticationProvider != null)
+ {
+ _authenticationProvider.close();
+ }
+
+ final Map<String, String> context = new HashMap<>();
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, "[\"TLSv1.3\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.2\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, "[\"(TLS|SSL)_AES_128_GCM_SHA256\", \"(TLS|SSL)_AES_256_GCM_SHA384\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, "[\".*CBC.*\"]");
+
+ final Map<String, Object> attributes =
+ Collections.singletonMap(SimpleLDAPAuthenticationManager.CONTEXT, context);
+ _authenticationProvider = createAuthenticationProvider(attributes);
+
+ final List<String> expectedAllowedTlsProtocols = Collections.singletonList("TLSv1.3");
+ final List<String> expectedDeniedTlsProtocols = Arrays.asList("Ssl.*", "TLSv1", "TLSv1.1", "TLSv1.2");
+ final List<String> expectedAllowedTlsCypherSuites = Arrays.asList("(TLS|SSL)_AES_128_GCM_SHA256", "(TLS|SSL)_AES_256_GCM_SHA384");
+ final List<String> expectedDeniedTlsCypherSuites = Collections.singletonList(".*CBC.*");
+ assertThat(_authenticationProvider.getTlsProtocolAllowList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolWhiteList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolDenyList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolBlackList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteAllowList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteWhiteList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteDenyList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteBlackList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ }
+
+ @Test
+ public void testTlProtocolsAndCypherSuitesUsingBlackWhiteListContextVariable()
+ {
+ if (_authenticationProvider != null)
+ {
+ _authenticationProvider.close();
+ }
+
+ final Map<String, String> context = new HashMap<>();
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST, "[\"TLSv1.3\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.2\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST, "[\"(TLS|SSL)_AES_128_GCM_SHA256\", \"(TLS|SSL)_AES_256_GCM_SHA384\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST, "[\".*CBC.*\"]");
+
+ final Map<String, Object> attributes =
+ Collections.singletonMap(SimpleLDAPAuthenticationManager.CONTEXT, context);
+ _authenticationProvider = createAuthenticationProvider(attributes);
+
+ final List<String> expectedAllowedTlsProtocols = Collections.singletonList("TLSv1.3");
+ final List<String> expectedDeniedTlsProtocols = Arrays.asList("Ssl.*", "TLSv1", "TLSv1.1", "TLSv1.2");
+ final List<String> expectedAllowedTlsCypherSuites = Arrays.asList("(TLS|SSL)_AES_128_GCM_SHA256", "(TLS|SSL)_AES_256_GCM_SHA384");
+ final List<String> expectedDeniedTlsCypherSuites = Collections.singletonList(".*CBC.*");
+ assertThat(_authenticationProvider.getTlsProtocolAllowList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolWhiteList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolDenyList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolBlackList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteAllowList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteWhiteList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteDenyList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteBlackList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ }
+
private SimpleLDAPAuthenticationManagerImpl createAuthenticationProvider()
{
return createAuthenticationProvider(Collections.emptyMap());
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImplTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImplTest.java
index f4348dd..8d960dd 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImplTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/oauth2/OAuth2AuthenticationProviderImplTest.java
@@ -20,14 +20,19 @@
*/
package org.apache.qpid.server.security.auth.manager.oauth2;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
@@ -41,6 +46,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.apache.qpid.server.configuration.CommonProperties;
import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.model.Broker;
@@ -50,6 +56,7 @@ import org.apache.qpid.server.model.NamedAddressSpace;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.security.auth.AuthenticationResult;
import org.apache.qpid.server.security.auth.manager.CachingAuthenticationProvider;
+import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
import org.apache.qpid.server.security.auth.manager.oauth2.cloudfoundry.CloudFoundryOAuth2IdentityResolverService;
import org.apache.qpid.server.security.auth.sasl.SaslNegotiator;
import org.apache.qpid.server.security.auth.sasl.oauth2.OAuth2Negotiator;
@@ -93,6 +100,20 @@ public class OAuth2AuthenticationProviderImplTest extends UnitTestBase
_server = new OAuth2MockEndpointHolder();
_server.start();
+ _authProvider = createAuthenticationProvider(Collections.emptyMap());
+
+ assertEquals("Could not successfully open authProvider", State.ACTIVE, _authProvider.getState());
+
+ final TrustManager[] trustingTrustManager = new TrustManager[] {new TrustingTrustManager() };
+
+ final SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, trustingTrustManager, new java.security.SecureRandom());
+ HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+ HttpsURLConnection.setDefaultHostnameVerifier(new BlindHostnameVerifier());
+ }
+
+ private OAuth2AuthenticationProvider<?> createAuthenticationProvider(Map<String, Object> attributes)
+ {
Broker broker = BrokerTestHelper.createBrokerMock();
TaskExecutor taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
when(broker.getTaskExecutor()).thenReturn(taskExecutor);
@@ -125,18 +146,13 @@ public class OAuth2AuthenticationProviderImplTest extends UnitTestBase
TEST_POST_LOGOUT_PATH));
authProviderAttributes.put("scope", TEST_SCOPE);
authProviderAttributes.put("trustStore", TEST_TRUST_STORE_NAME);
+ authProviderAttributes.putAll(attributes);
setTestSystemProperty(CachingAuthenticationProvider.AUTHENTICATION_CACHE_MAX_SIZE, "0");
- _authProvider = new OAuth2AuthenticationProviderImpl(authProviderAttributes, broker);
- _authProvider.open();
- assertEquals("Could not successfully open authProvider", State.ACTIVE, _authProvider.getState());
-
- final TrustManager[] trustingTrustManager = new TrustManager[] {new TrustingTrustManager() };
-
- final SSLContext sc = SSLContext.getInstance("SSL");
- sc.init(null, trustingTrustManager, new java.security.SecureRandom());
- HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
- HttpsURLConnection.setDefaultHostnameVerifier(new BlindHostnameVerifier());
+ final OAuth2AuthenticationProviderImpl authenticationProvider =
+ new OAuth2AuthenticationProviderImpl(authProviderAttributes, broker);
+ authenticationProvider.open();
+ return authenticationProvider;
}
@After
@@ -250,6 +266,61 @@ public class OAuth2AuthenticationProviderImplTest extends UnitTestBase
assertFailure(authenticationResult, "invalid_token");
}
+ @Test
+ public void testTlProtocolsAndCypherSuitesUsingAllowDenyListContextVariable()
+ {
+ final Map<String, String> context = new HashMap<>();
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST, "[\"TLSv1.3\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.2\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST, "[\"(TLS|SSL)_AES_128_GCM_SHA256\", \"(TLS|SSL)_AES_256_GCM_SHA384\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST, "[\".*CBC.*\"]");
+
+ final Map<String, Object> attributes =
+ Collections.singletonMap(SimpleLDAPAuthenticationManager.CONTEXT, context);
+ final OAuth2AuthenticationProvider<?> _authenticationProvider = createAuthenticationProvider(attributes);
+
+ final List<String> expectedAllowedTlsProtocols = Collections.singletonList("TLSv1.3");
+ final List<String> expectedDeniedTlsProtocols = Arrays.asList("Ssl.*", "TLSv1", "TLSv1.1", "TLSv1.2");
+ final List<String> expectedAllowedTlsCypherSuites = Arrays.asList("(TLS|SSL)_AES_128_GCM_SHA256", "(TLS|SSL)_AES_256_GCM_SHA384");
+ final List<String> expectedDeniedTlsCypherSuites = Collections.singletonList(".*CBC.*");
+ assertThat(_authenticationProvider.getTlsProtocolAllowList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolWhiteList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolDenyList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolBlackList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteAllowList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteWhiteList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteDenyList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteBlackList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ }
+
+ @Test
+ public void testTlProtocolsAndCypherSuitesUsingBlackWhiteListContextVariable()
+ {
+ final Map<String, String> context = new HashMap<>();
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST, "[\"TLSv1.3\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST, "[\"Ssl.*\",\"TLSv1\",\"TLSv1.1\",\"TLSv1.2\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST, "[\"(TLS|SSL)_AES_128_GCM_SHA256\", \"(TLS|SSL)_AES_256_GCM_SHA384\"]");
+ context.put(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST, "[\".*CBC.*\"]");
+
+ final Map<String, Object> attributes =
+ Collections.singletonMap(SimpleLDAPAuthenticationManager.CONTEXT, context);
+ final OAuth2AuthenticationProvider<?> _authenticationProvider = createAuthenticationProvider(attributes);
+
+ final List<String> expectedAllowedTlsProtocols = Collections.singletonList("TLSv1.3");
+ final List<String> expectedDeniedTlsProtocols = Arrays.asList("Ssl.*", "TLSv1", "TLSv1.1", "TLSv1.2");
+ final List<String> expectedAllowedTlsCypherSuites = Arrays.asList("(TLS|SSL)_AES_128_GCM_SHA256", "(TLS|SSL)_AES_256_GCM_SHA384");
+ final List<String> expectedDeniedTlsCypherSuites = Collections.singletonList(".*CBC.*");
+ assertThat(_authenticationProvider.getTlsProtocolAllowList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolWhiteList(), is(equalTo(expectedAllowedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolDenyList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsProtocolBlackList(), is(equalTo(expectedDeniedTlsProtocols)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteAllowList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteWhiteList(), is(equalTo(expectedAllowedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteDenyList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ assertThat(_authenticationProvider.getTlsCipherSuiteBlackList(), is(equalTo(expectedDeniedTlsCypherSuites)));
+ }
+
+
private void assertSuccess(final AuthenticationResult authenticationResult)
{
assertEquals("Authentication was not successful: " + authenticationResult.getCause(),
diff --git a/systests/qpid-systests-spawn-admin/src/main/java/org/apache/qpid/systests/admin/SpawnBrokerAdmin.java b/systests/qpid-systests-spawn-admin/src/main/java/org/apache/qpid/systests/admin/SpawnBrokerAdmin.java
index c5a076c..9fa9235 100644
--- a/systests/qpid-systests-spawn-admin/src/main/java/org/apache/qpid/systests/admin/SpawnBrokerAdmin.java
+++ b/systests/qpid-systests-spawn-admin/src/main/java/org/apache/qpid/systests/admin/SpawnBrokerAdmin.java
@@ -732,8 +732,6 @@ public class SpawnBrokerAdmin implements BrokerAdmin, Closeable
List<String> jvmArguments = new ArrayList<>();
jvmArguments.add("java");
- jvmArguments.add("-cp");
- jvmArguments.add(classpath);
jvmArguments.add("-Djava.io.tmpdir=" + escape(System.getProperty("java.io.tmpdir")));
jvmArguments.add("-Dlogback.configurationFile=default-broker-logback.xml");
jvmArguments.add("-Dqpid.tests.mms.messagestore.persistence=true");
@@ -766,7 +764,9 @@ public class SpawnBrokerAdmin implements BrokerAdmin, Closeable
String[] cmd = jvmArguments.toArray(new String[jvmArguments.size()]);
LOGGER.debug("command line:" + String.join(" ", jvmArguments));
- return new ProcessBuilder(cmd);
+ ProcessBuilder ps = new ProcessBuilder(cmd);
+ ps.environment().put("CLASSPATH", classpath);
+ return ps;
}
private String escape(String value)
@@ -824,16 +824,18 @@ public class SpawnBrokerAdmin implements BrokerAdmin, Closeable
private void doWindowsKill()
{
- try
+ if (_pid != null)
{
-
- Process p;
- p = Runtime.getRuntime().exec(new String[]{"taskkill", "/PID", Integer.toString(_pid), "/T", "/F"});
- consumeAllOutput(p);
- }
- catch (IOException e)
- {
- LOGGER.error("Error whilst killing process " + _pid, e);
+ try
+ {
+ Process p;
+ p = Runtime.getRuntime().exec(new String[]{"taskkill", "/PID", Integer.toString(_pid), "/T", "/F"});
+ consumeAllOutput(p);
+ }
+ catch (IOException e)
+ {
+ LOGGER.error("Error whilst killing process " + _pid, e);
+ }
}
}
diff --git a/systests/qpid-systests-spawn-admin/src/test/java/org/apache/qpid/systests/admin/SpawnBrokerAdminTest.java b/systests/qpid-systests-spawn-admin/src/test/java/org/apache/qpid/systests/admin/SpawnBrokerAdminTest.java
index c6a9164..05956ba 100644
--- a/systests/qpid-systests-spawn-admin/src/test/java/org/apache/qpid/systests/admin/SpawnBrokerAdminTest.java
+++ b/systests/qpid-systests-spawn-admin/src/test/java/org/apache/qpid/systests/admin/SpawnBrokerAdminTest.java
@@ -34,10 +34,8 @@ import static org.junit.Assert.fail;
import static org.junit.Assume.assumeThat;
import java.io.File;
-import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.file.Files;
-import java.util.Arrays;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
@@ -157,7 +155,8 @@ public class SpawnBrokerAdminTest extends UnitTestBase
@Test
public void afterTestClass() throws Exception
{
- try (SpawnBrokerAdmin admin = new SpawnBrokerAdmin())
+ SpawnBrokerAdmin admin = new SpawnBrokerAdmin();
+ try
{
admin.beforeTestClass(SpawnBrokerAdminTest.class);
admin.beforeTestMethod(SpawnBrokerAdminTest.class, getClass().getMethod("afterTestClass"));
@@ -180,6 +179,17 @@ public class SpawnBrokerAdminTest extends UnitTestBase
{
// pass
}
+ finally
+ {
+ admin = null;
+ }
+ }
+ finally
+ {
+ if (admin != null)
+ {
+ admin.close();
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 05/10: QPID-8459: [Broker-J]
AnonymousInteractiveAuthenticator uses
request.getRequestDispatcher().forward() instead of parsing request URL
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit 351f4497b3ff64624170fbc63153d07655a86d3d
Author: Tomas Vavricka <to...@deutsche-boerse.com>
AuthorDate: Wed Aug 5 06:13:28 2020 +0000
QPID-8459: [Broker-J] AnonymousInteractiveAuthenticator uses request.getRequestDispatcher().forward() instead of parsing request URL
(cherry picked from commit 6676f224ff7e9149d077bddec1931ac5a9f46546)
---
.../auth/AnonymousInteractiveAuthenticator.java | 88 ++++++++++------------
.../auth/UsernamePasswordInteractiveLogin.java | 17 +----
.../PreemptiveAuthenticationTest.java | 4 +-
3 files changed, 42 insertions(+), 67 deletions(-)
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/AnonymousInteractiveAuthenticator.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/AnonymousInteractiveAuthenticator.java
index f165974..c0ad0ab 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/AnonymousInteractiveAuthenticator.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/AnonymousInteractiveAuthenticator.java
@@ -20,10 +20,13 @@
package org.apache.qpid.server.management.plugin.auth;
+import java.io.IOException;
import java.security.AccessControlException;
import javax.security.auth.Subject;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,45 +57,9 @@ public class AnonymousInteractiveAuthenticator implements HttpRequestInteractive
final HttpManagementConfiguration configuration)
{
final Port<?> port = configuration.getPort(request);
- if(configuration.getAuthenticationProvider(request) instanceof AnonymousAuthenticationManager)
+ if (configuration.getAuthenticationProvider(request) instanceof AnonymousAuthenticationManager)
{
- return response ->
- {
- AnonymousAuthenticationManager authenticationProvider =
- (AnonymousAuthenticationManager) configuration.getAuthenticationProvider(request);
- AuthenticationResult authenticationResult = authenticationProvider.getAnonymousAuthenticationResult();
- try
- {
- SubjectAuthenticationResult result = port.getSubjectCreator(request.isSecure(), request.getServerName()).createResultWithGroups(authenticationResult);
- Subject original = result.getSubject();
-
- if (original == null)
- {
- throw new SecurityException("Only authenticated users can access the management interface");
- }
- Subject subject = HttpManagementUtil.createServletConnectionSubject(request, original);
- Broker broker = (Broker) authenticationProvider.getParent();
- HttpManagementUtil.assertManagementAccess(broker, subject);
- HttpManagementUtil.saveAuthorisedSubject(request, subject);
-
- String originalRequestUri = getOriginalRequestUri(request);
- LOGGER.debug("Successful login. Redirect to original resource {}", originalRequestUri);
- response.sendRedirect(originalRequestUri);
- }
- catch (SecurityException e)
- {
- if (e instanceof AccessControlException)
- {
- LOGGER.info("User '{}' is not authorised for management", authenticationResult.getMainPrincipal());
- response.sendError(403, "User is not authorised for management");
- }
- else
- {
- LOGGER.info("Authentication failed", authenticationResult.getCause());
- response.sendError(401);
- }
- }
- };
+ return response -> getLoginHandler(request, response, configuration, port);
}
else
{
@@ -100,6 +67,39 @@ public class AnonymousInteractiveAuthenticator implements HttpRequestInteractive
}
}
+ private void getLoginHandler(HttpServletRequest request, HttpServletResponse response,
+ HttpManagementConfiguration configuration, Port<?> port) throws ServletException, IOException
+ {
+ final AnonymousAuthenticationManager authenticationProvider =
+ (AnonymousAuthenticationManager) configuration.getAuthenticationProvider(request);
+ final AuthenticationResult authenticationResult = authenticationProvider.getAnonymousAuthenticationResult();
+ try
+ {
+ final SubjectAuthenticationResult result = port.getSubjectCreator(request.isSecure(), request.getServerName()).createResultWithGroups(authenticationResult);
+ final Subject original = result.getSubject();
+
+ if (original == null)
+ {
+ throw new SecurityException("Only authenticated users can access the management interface");
+ }
+ final Subject subject = HttpManagementUtil.createServletConnectionSubject(request, original);
+ final Broker broker = (Broker) authenticationProvider.getParent();
+ HttpManagementUtil.assertManagementAccess(broker, subject);
+ HttpManagementUtil.saveAuthorisedSubject(request, subject);
+ request.getRequestDispatcher(HttpManagement.DEFAULT_LOGIN_URL).forward(request, response);
+ }
+ catch (AccessControlException e)
+ {
+ LOGGER.info("User '{}' is not authorised for management", authenticationResult.getMainPrincipal());
+ response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not authorised for management");
+ }
+ catch (SecurityException e)
+ {
+ LOGGER.info("Authentication failed", authenticationResult.getCause());
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+
@Override
public LogoutHandler getLogoutHandler(final HttpServletRequest request,
final HttpManagementConfiguration configuration)
@@ -119,16 +119,4 @@ public class AnonymousInteractiveAuthenticator implements HttpRequestInteractive
{
return ANONYMOUS;
}
-
- private String getOriginalRequestUri(final HttpServletRequest request)
- {
- StringBuffer originalRequestURL = request.getRequestURL();
- final String queryString = request.getQueryString();
- if (queryString != null)
- {
- originalRequestURL.append("?").append(queryString);
- }
- return originalRequestURL.toString();
- }
-
}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/UsernamePasswordInteractiveLogin.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/UsernamePasswordInteractiveLogin.java
index 4f7b98b..541ee43 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/UsernamePasswordInteractiveLogin.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/UsernamePasswordInteractiveLogin.java
@@ -20,11 +20,7 @@
*/
package org.apache.qpid.server.management.plugin.auth;
-import java.io.IOException;
-
-import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import org.apache.qpid.server.management.plugin.HttpManagement;
import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
@@ -35,16 +31,7 @@ import org.apache.qpid.server.security.auth.manager.UsernamePasswordAuthenticati
@PluggableService
public class UsernamePasswordInteractiveLogin implements HttpRequestInteractiveAuthenticator
{
- private static final String DEFAULT_LOGIN_URL = "/index.html";
-
- private static final LogoutHandler LOGOUT_HANDLER = new LogoutHandler()
- {
- @Override
- public void handleLogout(final HttpServletResponse response) throws IOException
- {
- response.sendRedirect(HttpManagement.DEFAULT_LOGOUT_URL);
- }
- };
+ private static final LogoutHandler LOGOUT_HANDLER = response -> response.sendRedirect(HttpManagement.DEFAULT_LOGOUT_URL);
@Override
public AuthenticationHandler getAuthenticationHandler(final HttpServletRequest request,
@@ -52,7 +39,7 @@ public class UsernamePasswordInteractiveLogin implements HttpRequestInteractiveA
{
if(configuration.getAuthenticationProvider(request) instanceof UsernamePasswordAuthenticationProvider)
{
- return response -> request.getRequestDispatcher(DEFAULT_LOGIN_URL).forward(request, response);
+ return response -> request.getRequestDispatcher(HttpManagement.DEFAULT_LOGIN_URL).forward(request, response);
}
else
{
diff --git a/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/authentication/PreemptiveAuthenticationTest.java b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/authentication/PreemptiveAuthenticationTest.java
index ded03df..47b0971 100644
--- a/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/authentication/PreemptiveAuthenticationTest.java
+++ b/systests/qpid-systests-http-management/src/test/java/org/apache/qpid/tests/http/authentication/PreemptiveAuthenticationTest.java
@@ -124,7 +124,7 @@ public class PreemptiveAuthenticationTest extends HttpTestBase
assumeThat(canGenerateCerts(), is(true));
HttpTestHelper helper = configForClientAuth("CN=foo");
- HttpURLConnection authenticateConnection = helper.openManagementConnection("/index.html", "GET");
+ HttpURLConnection authenticateConnection = helper.openManagementConnection(HttpManagement.DEFAULT_LOGIN_URL, "GET");
authenticateConnection.setInstanceFollowRedirects(false);
int status = authenticateConnection.getResponseCode();
@@ -133,7 +133,7 @@ public class PreemptiveAuthenticationTest extends HttpTestBase
assertThat(status, is(equalTo(HttpURLConnection.HTTP_MOVED_TEMP)));
- authenticateConnection = helper.openManagementConnection("/index.html", "GET");
+ authenticateConnection = helper.openManagementConnection(HttpManagement.DEFAULT_LOGIN_URL, "GET");
authenticateConnection.setRequestProperty("Cookie", cookies);
status = authenticateConnection.getResponseCode();
authenticateConnection.disconnect();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 06/10: QPID-8461: [Broker-J] Repace Random with
SecureRandom
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit ee2293f09fb27262995daf7e0853a5d161be6635
Author: YYTVicky <61...@users.noreply.github.com>
AuthorDate: Wed Apr 29 22:07:25 2020 -0400
QPID-8461: [Broker-J] Repace Random with SecureRandom
(cherry picked from commit be89e42fb6cd1629d17fae8ddb35a9efeeda85c3)
---
broker-core/src/main/java/org/apache/qpid/server/util/StringUtil.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/util/StringUtil.java b/broker-core/src/main/java/org/apache/qpid/server/util/StringUtil.java
index 8f785d1..a93ec9c 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/util/StringUtil.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/util/StringUtil.java
@@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
+import java.security.SecureRandom;
public class StringUtil
{
@@ -33,7 +34,8 @@ public class StringUtil
private static final char[] CHARACTERS = (NUMBERS + LETTERS + LETTERS.toUpperCase() + OTHERS).toCharArray();
private static final char[] HEX = "0123456789ABCDEF".toCharArray();
- private Random _random = new Random();
+
+ private Random _random = new SecureRandom();
public static String elideDataUrl(final String path)
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[qpid-broker-j] 02/10: NO-JIRA: remove links etc from the
documentation, missed from removal in QPID 7487
Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit 6ed3dd885a50d5fee676f3a9db77977d8ee34349
Author: Robbie Gemmell <ro...@apache.org>
AuthorDate: Wed Aug 5 13:09:14 2020 +0100
NO-JIRA: remove links etc from the documentation, missed from removal in QPID 7487
(cherry picked from commit 7ba6bbeef8d402b2e55ced9ca0a83bd71648e1ff)
---
.../src/docbkx/Java-Broker-Initial-Configuration.xml | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/doc/java-broker/src/docbkx/Java-Broker-Initial-Configuration.xml b/doc/java-broker/src/docbkx/Java-Broker-Initial-Configuration.xml
index 3a99393..82ab64a 100644
--- a/doc/java-broker/src/docbkx/Java-Broker-Initial-Configuration.xml
+++ b/doc/java-broker/src/docbkx/Java-Broker-Initial-Configuration.xml
@@ -68,8 +68,7 @@
<para>Broker startup involves two configuration related items, the 'Initial Configuration'
and the Configuration Store. When the broker is started, if a Configuration Store does
not exist at the current <link linkend="Java-Broker-Initial-Configuration-Location">store location</link> then one will be initialised with the current <link linkend="Java-Broker-Initial-Configuration-Initial-Config-Location">'Initial
- Configuration'</link>. Unless otherwise requested to <link linkend="Java-Broker-Initial-Configuration-Location">overwrite the configuration
- store</link> then subsequent broker restarts will use the existing configuration
+ Configuration'</link>. Subsequent broker restarts will use the existing configuration
store and ignore the contents of the 'Initial Configuration'. </para>
</section>
@@ -103,8 +102,7 @@ $ ./qpid-server -icp ./my-initial-configuration.json
</screen>
<para> If a Configuration Store already exists at the current <link linkend="Java-Broker-Initial-Configuration-Location">store location</link> then the
- current 'Initial Configuration' will be ignored unless otherwise requested to <link linkend="Java-Broker-Initial-Configuration-Location">overwrite the configuration
- store</link>
+ current 'Initial Configuration' will be ignored.
</para>
</section>
@@ -247,9 +245,8 @@ $ ./qpid-server -prop "qpid.amqp_port=10000" -prop "qpid.http_port=10001"
<para> In the example above, property used to set the port number of the default AMQP port
is specified with the value 10000, overriding the default value of 5672, and similarly
the value 10001 is used to override the default HTTP port number of 8080. When using the
- 'Initial Configuration' to initialise a new Configuration Store (either at first broker
- startup, when requesting to <link linkend="Java-Broker-Initial-Configuration-Location">overwrite the configuration store</link>) these new values will be used for the
- port numbers instead. </para>
+ 'Initial Configuration' to initialise a new Configuration Store at first broker
+ startup these new values will be used for the port numbers instead. </para>
<para> NOTE: When running the broker on Windows and starting it via the qpid-server.bat
file, the "name=value" argument MUST be quoted. </para>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org