This is an automated email from the ASF dual-hosted git repository.
tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/artemis.git
The following commit(s) were added to refs/heads/main by this push:
new ae8778ec5e ARTEMIS-5902 optimize authn cache key creation
ae8778ec5e is described below
commit ae8778ec5efcdea543e219467d39c7441f328b5d
Author: Justin Bertram <[email protected]>
AuthorDate: Sat Feb 14 13:30:54 2026 -0600
ARTEMIS-5902 optimize authn cache key creation
Eliminate unnecessary calls to j.s.MessageDigest#getInstance(String) as
well as unnecessary bytes in hash.
Existing tests should suffice for validation.
---
.../core/security/impl/SecurityStoreImpl.java | 41 ++++++++++++++++++++--
.../artemis/core/server/ActiveMQServerLogger.java | 3 ++
.../activemq/artemis/utils/CertificateUtil.java | 8 +++--
.../core/security/impl/SecurityStoreImplTest.java | 12 +++++++
4 files changed, 59 insertions(+), 5 deletions(-)
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
index c0bb9d2874..c07d7bafef 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java
@@ -63,6 +63,8 @@ import
org.apache.activemq.artemis.utils.sm.SecurityManagerShim;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static
org.apache.activemq.artemis.utils.CertificateUtil.CERT_SUBJECT_DN_UNAVAILABLE;
+
/**
* The Apache Artemis SecurityStore implementation
*/
@@ -70,6 +72,8 @@ public class SecurityStoreImpl implements SecurityStore,
HierarchicalRepositoryC
private static final Logger logger =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private static final byte[] CACHE_KEY_SEPARATOR = new byte[]{0};
+
private final HierarchicalRepository<Set<Role>> securityRepository;
private final ActiveMQSecurityManager securityManager;
@@ -95,6 +99,8 @@ public class SecurityStoreImpl implements SecurityStore,
HierarchicalRepositoryC
private static final AtomicLongFieldUpdater<SecurityStoreImpl>
AUTHORIZATION_FAILURE_COUNT_UPDATER =
AtomicLongFieldUpdater.newUpdater(SecurityStoreImpl.class,
"authorizationFailureCount");
private volatile long authorizationFailureCount;
+ private static final MessageDigest SHA256 = getDigestInstance();
+ private static volatile boolean messageDigestCnsLogged = false;
/**
* @param notificationService can be {@code null}
@@ -568,10 +574,41 @@ public class SecurityStoreImpl implements SecurityStore,
HierarchicalRepositoryC
return granted;
}
- private String createAuthenticationCacheKey(String username, String
password, RemotingConnection connection) {
+ protected String createAuthenticationCacheKey(String username, String
password, RemotingConnection connection) {
+ MessageDigest md = getDigestClone();
+ if (username != null) {
+ md.update(username.getBytes(StandardCharsets.UTF_8));
+ }
+ md.update(CACHE_KEY_SEPARATOR);
+ if (password != null) {
+ md.update(password.getBytes(StandardCharsets.UTF_8));
+ }
+ md.update(CACHE_KEY_SEPARATOR);
+ String certSubjectDN = CertificateUtil.getCertSubjectDN(connection);
+ if (!CERT_SUBJECT_DN_UNAVAILABLE.equals(certSubjectDN)) {
+ md.update(certSubjectDN.getBytes(StandardCharsets.UTF_8));
+ }
+ return ByteUtil.bytesToHex(md.digest());
+ }
+
+ private static MessageDigest getDigestClone() {
+ try {
+ return (MessageDigest) SHA256.clone();
+ } catch (CloneNotSupportedException cns) {
+ // This should never happen, but just in case log it and fail safely.
+ if (!messageDigestCnsLogged) {
+ ActiveMQServerLogger.LOGGER.sha256CloneNotSupported(cns);
+ messageDigestCnsLogged = true;
+ }
+ return getDigestInstance();
+ }
+ }
+
+ private static MessageDigest getDigestInstance() {
try {
- return
ByteUtil.bytesToHex(MessageDigest.getInstance("SHA-256").digest((username +
password +
CertificateUtil.getCertSubjectDN(connection)).getBytes(StandardCharsets.UTF_8)));
+ return MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
+ // This should never happen. The JavaDoc for MessageDigest states
that SHA-256 is always available.
throw new RuntimeException(e);
}
}
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
index 95542dd4d9..efe46e0746 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
@@ -1529,4 +1529,7 @@ public interface ActiveMQServerLogger {
@LogMessage(id = 224158, value = "The operation {} on queue {} cannot read
more data from paging into memory and will be interrupted.", level =
LogMessage.Level.INFO)
void preventQueueManagementToFloodMemory(String operation, String queue);
+
+ @LogMessage(id = 224159, value = "Failed to clone SHA256 MessageDigest,
falling back to getInstance", level = LogMessage.Level.INFO)
+ void sha256CloneNotSupported(CloneNotSupportedException cns);
}
\ No newline at end of file
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/utils/CertificateUtil.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/utils/CertificateUtil.java
index 6e6be8aa08..9cf59b824c 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/utils/CertificateUtil.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/utils/CertificateUtil.java
@@ -40,13 +40,15 @@ public class CertificateUtil {
private static final String SSL_HANDLER_NAME = "ssl";
+ public static final String CERT_SUBJECT_DN_UNAVAILABLE = "unavailable";
+
public static String getCertSubjectDN(RemotingConnection connection) {
- String certSubjectDN = "unavailable";
X509Certificate[] certs = getCertsFromConnection(connection);
if (certs != null && certs.length > 0 && certs[0] != null) {
- certSubjectDN = certs[0].getSubjectDN().getName();
+ return certs[0].getSubjectDN().getName();
+ } else {
+ return CERT_SUBJECT_DN_UNAVAILABLE;
}
- return certSubjectDN;
}
public static X509Certificate[] getCertsFromConnection(RemotingConnection
remotingConnection) {
diff --git
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImplTest.java
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImplTest.java
index afd7ec0a96..153d12c6cb 100644
---
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImplTest.java
+++
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImplTest.java
@@ -28,6 +28,7 @@ import org.apache.activemq.artemis.core.security.CheckType;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.security.SecurityAuth;
import
org.apache.activemq.artemis.core.settings.impl.HierarchicalObjectRepository;
+import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5;
import org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal;
@@ -39,6 +40,7 @@ import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -216,4 +218,14 @@ public class SecurityStoreImplTest {
assertEquals(1, securityStore.getAuthenticationFailureCount());
assertEquals(0, securityStore.getAuthenticationCacheSize());
}
+
+ @Test
+ public void testCacheAlgorithm() throws Exception {
+ final String user = RandomUtil.randomUUIDString();
+ SecurityStoreImpl securityStore = new SecurityStoreImpl(new
HierarchicalObjectRepository<>(), securityManager, 999, true, "", null, null,
0, 0);
+ try (AssertionLoggerHandler handler = new AssertionLoggerHandler()) {
+ securityStore.createAuthenticationCacheKey(user,
RandomUtil.randomUUIDString(), null);
+ assertFalse(handler.findText("AMQ224159"));
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]