Skip to content

Commit

Permalink
ARTEMIS-4297 allow regex in no-cache exception config
Browse files Browse the repository at this point in the history
  • Loading branch information
jbertram authored and clebertsuconic committed May 31, 2023
1 parent 40425d4 commit e7de2c7
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
Expand Down Expand Up @@ -263,12 +264,26 @@ public boolean commit() throws LoginException {

private LoginException handleException(LoginException e) {
Throwable rootCause = ExceptionUtils.getRootCause(e);
if (noCacheExceptions.contains(rootCause.getClass().getName())) {
return (NoCacheLoginException) new NoCacheLoginException(rootCause.getClass().getName() + (rootCause.getMessage() == null ? "" : ": " + rootCause.getMessage())).initCause(e);
String rootCauseClass = rootCause.getClass().getName();

// try to match statically first
if (noCacheExceptions.contains(rootCauseClass)) {
return getNoCacheLoginException(e, rootCause);
} else {
// if no static matches are found try regex
for (String match : noCacheExceptions) {
if (Pattern.matches(match, rootCauseClass)) {
return getNoCacheLoginException(e, rootCause);
}
}
}
return e;
}

private NoCacheLoginException getNoCacheLoginException(LoginException e, Throwable rootCause) {
return (NoCacheLoginException) new NoCacheLoginException(rootCause.getClass().getName() + (rootCause.getMessage() == null ? "" : ": " + rootCause.getMessage())).initCause(e);
}

private void clear() {
username = null;
userAuthenticated = false;
Expand Down
23 changes: 12 additions & 11 deletions docs/user-manual/en/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -834,17 +834,18 @@ system. It is implemented by
previous role search. This option must always be set to enable role expansion
because it has no default value. Example value: `(member={0})`.

- `noCacheExceptions` - comma separated list of class names of exceptions which
may be thrown during communication with the LDAP server; default is empty.
Typically any failure to authenticate will be stored in the authentication cache
so that the underlying security data store (e.g. LDAP) is spared any unnecessary
traffic. For example, an application with the wrong password attempting to login
multiple times in short order might adversely impact the LDAP server. However, in
cases where the failure is, for example, due to a temporary network outage and
the `security-invalidation-interval` is relatively high then _not_ caching such
failures would be better. Users can enumerate any relevant exceptions which the
cache should ignore (e.g. `java.net.ConnectException`). The name of the exception
should be the **root cause** from the relevant stack-trace. Users can confirm
- `noCacheExceptions` - comma separated list of class names or regular expressions
to match exceptions which may be thrown during communication with the LDAP
server; default is empty. Typically any failure to authenticate will be stored in
the authentication cache so that the underlying security data store (e.g. LDAP)
is spared any unnecessary traffic. For example, an application with the wrong
password attempting to login multiple times in short order might adversely impact
the LDAP server. However, in cases where the failure is, for example, due to a
temporary network outage and the `security-invalidation-interval` is relatively
high then _not_ caching such failures would be better. Users can enumerate any
relevant exceptions which the cache should ignore (e.g.
`java.net.ConnectException`). The name of the exception or the regular expression
should match the **root cause** from the relevant stack-trace. Users can confirm
the configured exceptions are being skipped by enabling debug logging for
`org.apache.activemq.artemis.core.security.impl.SecurityStoreImpl`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,21 @@ public void testNoCacheNamingException() throws Exception {
internalTestNoCacheException("BrokenLDAPLoginNamingException");
}

@Test
public void testNoCacheNamingExceptionRegex() throws Exception {
internalTestNoCacheException("BrokenLDAPLoginNamingExceptionRegex");
}

@Test
public void testNoCacheConnectException() throws Exception {
internalTestNoCacheException("BrokenLDAPLoginConnectException");
}

@Test
public void testNoCacheConnectExceptionRegex() throws Exception {
internalTestNoCacheException("BrokenLDAPLoginConnectExceptionRegex");
}

private void internalTestNoCacheException(String ldapConfigName) throws Exception {
ActiveMQJAASSecurityManager securityManager = new ActiveMQJAASSecurityManager(ldapConfigName);
ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(createDefaultInVMConfig().setSecurityEnabled(true), ManagementFactory.getPlatformMBeanServer(), securityManager, false));
Expand Down
40 changes: 40 additions & 0 deletions tests/integration-tests/src/test/resources/login.config
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,26 @@ BrokenLDAPLoginNamingException {
;
};

BrokenLDAPLoginNamingExceptionRegex {
org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
debug=true
initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
connectionURL="ldap://localhost:1024"
connectionUsername="uid=admin,ou=system"
connectionPassword=""
connectionProtocol=s
authentication=simple
userBase="ou=system"
userSearchMatching="(uid={0})"
userSearchSubtree=false
roleBase="ou=system"
roleName=dummyRoleName
roleSearchMatching="(uid={1})"
roleSearchSubtree=false
noCacheExceptions=".*\\..*\\.NamingException"
;
};

BrokenLDAPLoginConnectException {
org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
debug=true
Expand All @@ -126,6 +146,26 @@ BrokenLDAPLoginConnectException {
;
};

BrokenLDAPLoginConnectExceptionRegex {
org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
debug=true
initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
connectionURL="ldap://localhost:1024"
connectionUsername="uid=admin,ou=system"
connectionPassword="123"
connectionProtocol=s
authentication=simple
userBase="ou=system"
userSearchMatching="(uid={0})"
userSearchSubtree=false
roleBase="ou=system"
roleName=dummyRoleName
roleSearchMatching="(uid={1})"
roleSearchSubtree=false
noCacheExceptions="nomatch, .*"
;
};

ExpandedLDAPLogin {
org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
debug=true
Expand Down

0 comments on commit e7de2c7

Please sign in to comment.