ARTEMIS-5052 hash authentication cache keys
Existing tests should suffice to validate this change.
This commit is contained in:
parent
c8f51952f4
commit
90300285c7
|
@ -18,8 +18,11 @@ package org.apache.activemq.artemis.core.security.impl;
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
import javax.security.auth.Subject;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.AccessControlContext;
|
import java.security.AccessControlContext;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||||
|
@ -50,6 +53,7 @@ import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3;
|
||||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager4;
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager4;
|
||||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5;
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5;
|
||||||
import org.apache.activemq.artemis.spi.core.security.jaas.NoCacheLoginException;
|
import org.apache.activemq.artemis.spi.core.security.jaas.NoCacheLoginException;
|
||||||
|
import org.apache.activemq.artemis.utils.ByteUtil;
|
||||||
import org.apache.activemq.artemis.utils.CompositeAddress;
|
import org.apache.activemq.artemis.utils.CompositeAddress;
|
||||||
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
|
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
|
||||||
import org.apache.activemq.artemis.utils.collections.TypedProperties;
|
import org.apache.activemq.artemis.utils.collections.TypedProperties;
|
||||||
|
@ -100,7 +104,7 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
|
||||||
final String managementClusterPassword,
|
final String managementClusterPassword,
|
||||||
final NotificationService notificationService,
|
final NotificationService notificationService,
|
||||||
final long authenticationCacheSize,
|
final long authenticationCacheSize,
|
||||||
final long authorizationCacheSize) {
|
final long authorizationCacheSize) throws NoSuchAlgorithmException {
|
||||||
this.securityRepository = securityRepository;
|
this.securityRepository = securityRepository;
|
||||||
this.securityManager = securityManager;
|
this.securityManager = securityManager;
|
||||||
this.securityEnabled = securityEnabled;
|
this.securityEnabled = securityEnabled;
|
||||||
|
@ -185,7 +189,8 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
|
||||||
boolean check = true;
|
boolean check = true;
|
||||||
|
|
||||||
Subject subject = null;
|
Subject subject = null;
|
||||||
Pair<Boolean, Subject> cacheEntry = getAuthenticationCacheEntry(user, password, connection);
|
String authnCacheKey = createAuthenticationCacheKey(user, password, connection);
|
||||||
|
Pair<Boolean, Subject> cacheEntry = getAuthenticationCacheEntry(authnCacheKey);
|
||||||
if (cacheEntry != null) {
|
if (cacheEntry != null) {
|
||||||
if (!cacheEntry.getA()) {
|
if (!cacheEntry.getA()) {
|
||||||
// cached authentication failed previously so don't check again
|
// cached authentication failed previously so don't check again
|
||||||
|
@ -212,7 +217,7 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
|
||||||
if (securityManager instanceof ActiveMQSecurityManager5) {
|
if (securityManager instanceof ActiveMQSecurityManager5) {
|
||||||
try {
|
try {
|
||||||
subject = ((ActiveMQSecurityManager5) securityManager).authenticate(user, password, connection, securityDomain);
|
subject = ((ActiveMQSecurityManager5) securityManager).authenticate(user, password, connection, securityDomain);
|
||||||
putAuthenticationCacheEntry(user, password, connection, subject);
|
putAuthenticationCacheEntry(authnCacheKey, subject);
|
||||||
validatedUser = getUserFromSubject(subject);
|
validatedUser = getUserFromSubject(subject);
|
||||||
} catch (NoCacheLoginException e) {
|
} catch (NoCacheLoginException e) {
|
||||||
handleNoCacheLoginException(e);
|
handleNoCacheLoginException(e);
|
||||||
|
@ -435,7 +440,8 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
|
||||||
* @return the authenticated Subject with all associated role principals
|
* @return the authenticated Subject with all associated role principals
|
||||||
*/
|
*/
|
||||||
private Subject getSubjectForAuthorization(SecurityAuth auth, ActiveMQSecurityManager5 securityManager) {
|
private Subject getSubjectForAuthorization(SecurityAuth auth, ActiveMQSecurityManager5 securityManager) {
|
||||||
Pair<Boolean, Subject> cached = getAuthenticationCacheEntry(auth.getUsername(), auth.getPassword(), auth.getRemotingConnection());
|
String authnCacheKey = createAuthenticationCacheKey(auth.getUsername(), auth.getPassword(), auth.getRemotingConnection());
|
||||||
|
Pair<Boolean, Subject> cached = getAuthenticationCacheEntry(authnCacheKey);
|
||||||
|
|
||||||
if (cached == null && auth.getUsername() == null && auth.getPassword() == null && auth.getRemotingConnection() instanceof ManagementRemotingConnection) {
|
if (cached == null && auth.getUsername() == null && auth.getPassword() == null && auth.getRemotingConnection() instanceof ManagementRemotingConnection) {
|
||||||
AccessControlContext accessControlContext = AccessController.getContext();
|
AccessControlContext accessControlContext = AccessController.getContext();
|
||||||
|
@ -451,7 +457,7 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
|
||||||
if (cached == null) {
|
if (cached == null) {
|
||||||
try {
|
try {
|
||||||
Subject subject = securityManager.authenticate(auth.getUsername(), auth.getPassword(), auth.getRemotingConnection(), auth.getSecurityDomain());
|
Subject subject = securityManager.authenticate(auth.getUsername(), auth.getPassword(), auth.getRemotingConnection(), auth.getSecurityDomain());
|
||||||
putAuthenticationCacheEntry(auth.getUsername(), auth.getPassword(), auth.getRemotingConnection(), subject);
|
putAuthenticationCacheEntry(authnCacheKey, subject);
|
||||||
return subject;
|
return subject;
|
||||||
} catch (NoCacheLoginException e) {
|
} catch (NoCacheLoginException e) {
|
||||||
handleNoCacheLoginException(e);
|
handleNoCacheLoginException(e);
|
||||||
|
@ -465,22 +471,17 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
|
||||||
logger.debug("Skipping authentication cache due to exception: {}", e.getMessage());
|
logger.debug("Skipping authentication cache due to exception: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putAuthenticationCacheEntry(String user,
|
private void putAuthenticationCacheEntry(String key, Subject subject) {
|
||||||
String password,
|
|
||||||
RemotingConnection connection,
|
|
||||||
Subject subject) {
|
|
||||||
if (authenticationCache != null) {
|
if (authenticationCache != null) {
|
||||||
authenticationCache.put(createAuthenticationCacheKey(user, password, connection), new Pair<>(subject != null, subject));
|
authenticationCache.put(key, new Pair<>(subject != null, subject));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<Boolean, Subject> getAuthenticationCacheEntry(String user,
|
private Pair<Boolean, Subject> getAuthenticationCacheEntry(String key) {
|
||||||
String password,
|
|
||||||
RemotingConnection connection) {
|
|
||||||
if (authenticationCache == null) {
|
if (authenticationCache == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return authenticationCache.getIfPresent(createAuthenticationCacheKey(user, password, connection));
|
return authenticationCache.getIfPresent(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,7 +539,11 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createAuthenticationCacheKey(String username, String password, RemotingConnection connection) {
|
private String createAuthenticationCacheKey(String username, String password, RemotingConnection connection) {
|
||||||
return username + password + CertificateUtil.getCertSubjectDN(connection);
|
try {
|
||||||
|
return ByteUtil.bytesToHex(MessageDigest.getInstance("SHA-256").digest((username + password + CertificateUtil.getCertSubjectDN(connection)).getBytes(StandardCharsets.UTF_8)));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createAuthorizationCacheKey(String user, CheckType checkType) {
|
private String createAuthorizationCacheKey(String user, CheckType checkType) {
|
||||||
|
|
Loading…
Reference in New Issue