Author: stillalex Date: Thu Mar 7 14:15:14 2019 New Revision: 1854982 URL: http://svn.apache.org/viewvc?rev=1854982&view=rev Log: OAK-8102 LoginModule error metrics
Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java (with props) jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java (with props) jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java (with props) jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java (with props) jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java (with props) jackrabbit/oak/trunk/oak-security-spi/src/test/resources/ jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml (with props) Modified: jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java jackrabbit/oak/trunk/oak-security-spi/pom.xml jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java Modified: jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java (original) +++ jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java Thu Mar 7 14:15:14 2019 @@ -246,12 +246,14 @@ public class ExternalLoginModule extends } } catch (ExternalIdentityException e) { log.error("Error while authenticating '{}' with {}", logId, idp.getName(), e); + onError(); return false; } catch (LoginException e) { log.debug("IDP {} throws login exception for '{}': {}", idp.getName(), logId, e.getMessage()); throw e; - } catch (Exception e) { - log.debug("SyncHandler {} throws sync exception for '{}'", syncHandler.getName(), logId, e); + } catch (SyncException | RepositoryException e) { + onError(); + log.error("SyncHandler {} throws sync exception for '{}'", syncHandler.getName(), logId, e); LoginException le = new LoginException("Error while syncing user."); le.initCause(e); throw le; Modified: jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java (original) +++ jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java Thu Mar 7 14:15:14 2019 @@ -488,7 +488,7 @@ public class BenchmarkRunner { // benchmarks for oak-auth-external new ExternalLoginTest(numberOfUsers.value(options), numberOfGroups.value(options), expiration.value(options), dynamicMembership.value(options), autoMembership.values(options), - report.value(options)), + report.value(options), statsProvider), new SyncAllExternalUsersTest(numberOfUsers.value(options), numberOfGroups.value(options), expiration.value(options), dynamicMembership.value(options), autoMembership.values(options)), new SyncAllUsersTest(numberOfUsers.value(options), numberOfGroups.value(options), expiration.value(options), dynamicMembership.value(options), autoMembership.values(options)), new SyncExternalUsersTest(numberOfUsers.value(options), numberOfGroups.value(options), expiration.value(options), dynamicMembership.value(options), autoMembership.values(options), batchSize.value(options)), Modified: jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java (original) +++ jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java Thu Mar 7 14:15:14 2019 @@ -16,6 +16,9 @@ */ package org.apache.jackrabbit.oak.benchmark.authentication.external; +import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL; +import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT; + import java.util.HashSet; import java.util.List; import java.util.Set; @@ -24,16 +27,17 @@ import javax.jcr.SimpleCredentials; import javax.security.auth.login.AppConfigurationEntry; import javax.security.auth.login.Configuration; -import com.google.common.collect.ImmutableMap; - import org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule; import org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl; +import org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration; import org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStats; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStatsCollector; import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule; +import org.apache.jackrabbit.oak.stats.StatisticsProvider; import org.jetbrains.annotations.NotNull; -import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT; -import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL; +import com.google.common.collect.ImmutableMap; /** * Login against the {@link ExternalLoginModule} with a randomly selected user. @@ -48,16 +52,18 @@ public class ExternalLoginTest extends A private final int numberOfUsers; private final int numberOfGroups; private final Reporter reporter; + private final LoginModuleStats lmStats; private String id; private Set<String> uniques; - public ExternalLoginTest(int numberOfUsers, int numberOfGroups, long expTime, - boolean dynamicMembership, @NotNull List<String> autoMembership, boolean report) { + public ExternalLoginTest(int numberOfUsers, int numberOfGroups, long expTime, boolean dynamicMembership, + @NotNull List<String> autoMembership, boolean report, StatisticsProvider statsProvider) { super(numberOfUsers, numberOfGroups, expTime, dynamicMembership, autoMembership); this.numberOfUsers = numberOfUsers; this.numberOfGroups = numberOfGroups; this.reporter = new Reporter(report); + this.lmStats = new LoginModuleStats(statsProvider); } @Override @@ -65,6 +71,11 @@ public class ExternalLoginTest extends A super.beforeSuite(); reporter.beforeSuite(); uniques = new HashSet<>(numberOfUsers); + AuthenticationConfiguration authenticationConfiguration = getSecurityProvider() + .getConfiguration(AuthenticationConfiguration.class); + if (authenticationConfiguration instanceof LoginModuleStatsCollector) { + ((LoginModuleStatsCollector) authenticationConfiguration).setLoginModuleMonitor(lmStats); + } } @Override Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java Thu Mar 7 14:15:14 2019 @@ -24,6 +24,8 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.SecurityProvider; import org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration; import org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStatsCollector; import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAware; import org.jetbrains.annotations.NotNull; @@ -49,7 +51,7 @@ import org.slf4j.LoggerFactory; */ @Component(service = {AuthenticationConfiguration.class, SecurityConfiguration.class}) @Designate(ocd = AuthenticationConfigurationImpl.Configuration.class) -public class AuthenticationConfigurationImpl extends ConfigurationBase implements AuthenticationConfiguration { +public class AuthenticationConfigurationImpl extends ConfigurationBase implements AuthenticationConfiguration, LoginModuleStatsCollector { @ObjectClassDefinition(name = "Apache Jackrabbit Oak AuthenticationConfiguration") @interface Configuration { @@ -71,6 +73,9 @@ public class AuthenticationConfiguration private static final Logger log = LoggerFactory.getLogger(AuthenticationConfigurationImpl.class); + // stats + private LoginModuleMonitor lmMonitor = LoginModuleMonitor.NOOP; + /** * Constructor for OSGi */ @@ -137,6 +142,12 @@ public class AuthenticationConfiguration } else { log.warn("Unable to obtain whiteboard from SecurityProvider"); } - return new LoginContextProviderImpl(appName, getParameters(), contentRepository, getSecurityProvider(), whiteboard); + return new LoginContextProviderImpl(appName, getParameters(), contentRepository, getSecurityProvider(), + whiteboard, lmMonitor); + } + + @Override + public void setLoginModuleMonitor(@NotNull LoginModuleMonitor lmMonitor) { + this.lmMonitor = lmMonitor; } } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java Thu Mar 7 14:15:14 2019 @@ -26,6 +26,7 @@ import javax.security.auth.callback.Unsu import org.apache.jackrabbit.oak.api.ContentRepository; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor; import org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback; import org.apache.jackrabbit.oak.spi.security.authentication.callback.RepositoryCallback; import org.apache.jackrabbit.oak.spi.security.authentication.callback.WhiteboardCallback; @@ -49,16 +50,19 @@ class CallbackHandlerImpl implements Cal private final ContentRepository contentRepository; private final SecurityProvider securityProvider; private final Whiteboard whiteboard; + private final LoginModuleMonitor loginModuleMonitor; CallbackHandlerImpl(Credentials credentials, String workspaceName, ContentRepository contentRepository, SecurityProvider securityProvider, - Whiteboard whiteboard) { + Whiteboard whiteboard, + LoginModuleMonitor loginModuleMonitor) { this.credentials = credentials; this.workspaceName = workspaceName; this.contentRepository = contentRepository; this.securityProvider = securityProvider; this.whiteboard = whiteboard; + this.loginModuleMonitor = loginModuleMonitor; } //----------------------------------------------------< CallbackHandler >--- @@ -76,6 +80,7 @@ class CallbackHandlerImpl implements Cal repositoryCallback.setContentRepository(contentRepository); repositoryCallback.setSecurityProvider(securityProvider); repositoryCallback.setWorkspaceName(workspaceName); + repositoryCallback.setLoginModuleMonitor(loginModuleMonitor); } else if (callback instanceof WhiteboardCallback) { ((WhiteboardCallback) callback).setWhiteboard(whiteboard); } else { Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java Thu Mar 7 14:15:14 2019 @@ -33,6 +33,7 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.authentication.JaasLoginContext; import org.apache.jackrabbit.oak.spi.security.authentication.LoginContext; import org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor; import org.apache.jackrabbit.oak.spi.security.authentication.PreAuthContext; import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; import org.jetbrains.annotations.NotNull; @@ -54,18 +55,21 @@ class LoginContextProviderImpl implement private final ContentRepository contentRepository; private final SecurityProvider securityProvider; private final Whiteboard whiteboard; + private final LoginModuleMonitor loginModuleMonitor; private Configuration configuration; LoginContextProviderImpl(String appName, ConfigurationParameters params, ContentRepository contentRepository, SecurityProvider securityProvider, - Whiteboard whiteboard) { + Whiteboard whiteboard, + LoginModuleMonitor loginModuleMonitor) { this.appName = appName; this.params = params; this.contentRepository = contentRepository; this.securityProvider = securityProvider; this.whiteboard = whiteboard; + this.loginModuleMonitor = loginModuleMonitor; } @Override @@ -99,7 +103,7 @@ class LoginContextProviderImpl implement @NotNull private CallbackHandler getCallbackHandler(Credentials credentials, String workspaceName) { - return new CallbackHandlerImpl(credentials, workspaceName, contentRepository, securityProvider, whiteboard); + return new CallbackHandlerImpl(credentials, workspaceName, contentRepository, securityProvider, whiteboard, loginModuleMonitor); } @NotNull Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java Thu Mar 7 14:15:14 2019 @@ -173,8 +173,9 @@ public final class TokenLoginModule exte updateSubject(tc, null, null); } else { // failed to create token -> fail commit() + onError(); Object logId = (userId != null) ? userId : sharedState.get(SHARED_KEY_LOGIN_NAME); - log.debug("TokenProvider failed to create a login token for user " + logId); + log.error("TokenProvider failed to create a login token for user " + logId); throw new LoginException("Failed to create login token for user " + logId); } } @@ -225,7 +226,8 @@ public final class TokenLoginModule exte callbackHandler.handle(new Callback[] {tcCallback}); provider = tcCallback.getTokenProvider(); } catch (IOException | UnsupportedCallbackException e) { - log.warn(e.getMessage()); + onError(); + log.error(e.getMessage(), e); } } return provider; Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java Thu Mar 7 14:15:14 2019 @@ -244,10 +244,10 @@ class TokenProviderImpl implements Token log.error(error, e.getMessage()); } catch (CommitFailedException | RepositoryException e) { // conflict while committing changes - log.warn(error, e.getMessage()); + log.error(error, e.getMessage()); } } else { - log.warn("Unable to get/create token store for user " + userId); + log.error("Unable to get/create token store for user {}.", userId); } return null; } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java Thu Mar 7 14:15:14 2019 @@ -214,12 +214,11 @@ public final class LoginModuleImpl exten } else { try { NameCallback callback = new NameCallback("User-ID: "); - callbackHandler.handle(new Callback[]{callback}); + callbackHandler.handle(new Callback[] { callback }); uid = callback.getName(); - } catch (UnsupportedCallbackException e) { - log.warn("Credentials- or NameCallback must be supported"); - } catch (IOException e) { - log.error("Name-Callback failed: " + e.getMessage()); + } catch (IOException | UnsupportedCallbackException e) { + onError(); + log.error(e.getMessage(), e); } } } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java Thu Mar 7 14:15:14 2019 @@ -16,6 +16,8 @@ */ package org.apache.jackrabbit.oak.security.internal; +import java.io.Closeable; +import java.util.Collections; import java.util.Dictionary; import java.util.Hashtable; import java.util.List; @@ -31,10 +33,15 @@ import org.apache.jackrabbit.oak.securit import org.apache.jackrabbit.oak.security.user.whiteboard.WhiteboardAuthorizableNodeName; import org.apache.jackrabbit.oak.security.user.whiteboard.WhiteboardUserAuthenticationFactory; import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration; +import org.apache.jackrabbit.oak.spi.security.ConfigurationBase; import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters; import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; import org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMBean; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStats; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStatsCollector; import org.apache.jackrabbit.oak.spi.security.authentication.token.CompositeTokenConfiguration; import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration; import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration; @@ -48,6 +55,9 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration; import org.apache.jackrabbit.oak.spi.security.user.UserConstants; import org.apache.jackrabbit.oak.spi.security.user.action.AuthorizableActionProvider; +import org.apache.jackrabbit.oak.spi.whiteboard.Registration; +import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; +import org.apache.jackrabbit.oak.stats.StatisticsProvider; import org.jetbrains.annotations.NotNull; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @@ -66,10 +76,14 @@ import org.osgi.service.metatype.annotat import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.io.Closer; + import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newCopyOnWriteArrayList; import static org.apache.jackrabbit.oak.spi.security.RegistrationConstants.OAK_SECURITY_NAME; +import static org.apache.jackrabbit.oak.commons.IOUtils.closeQuietly; import static org.apache.jackrabbit.oak.spi.security.ConfigurationParameters.EMPTY; +import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean; @Component(immediate=true) @Designate(ocd = SecurityProviderRegistration.Configuration.class) @@ -143,6 +157,10 @@ public class SecurityProviderRegistratio private RootProvider rootProvider; private TreeProvider treeProvider; + @Reference + private StatisticsProvider statisticsProvider = StatisticsProvider.NOOP; + private Closer closer; + //----------------------------------------------------< SCR integration >--- @Activate @@ -466,9 +484,10 @@ public class SecurityProviderRegistratio properties.put("type", "default"); + Whiteboard whiteboard = new OsgiWhiteboard(context); ServiceRegistration registration = context.registerService( SecurityProvider.class.getName(), - createSecurityProvider(context), + createSecurityProvider(whiteboard), properties ); @@ -477,6 +496,19 @@ public class SecurityProviderRegistratio this.registering = false; } + closer = Closer.create(); + if (authenticationConfiguration instanceof LoginModuleStatsCollector) { + LoginModuleStats lmMonitor = new LoginModuleStats(statisticsProvider); + ((LoginModuleStatsCollector) authenticationConfiguration).setLoginModuleMonitor(lmMonitor); + + Registration mon = whiteboard.register(LoginModuleMonitor.class, lmMonitor, Collections.emptyMap()); + closer.register((Closeable) mon::unregister); + + Registration mbean = registerMBean(whiteboard, LoginModuleMBean.class, lmMonitor, LoginModuleMBean.TYPE, + "LoginModule statistics"); + closer.register((Closeable) mbean::unregister); + } + log.info("SecurityProvider instance registered"); } @@ -509,11 +541,12 @@ public class SecurityProviderRegistratio } registration.unregister(); + closeQuietly(closer); log.info("SecurityProvider instance unregistered"); } - private SecurityProvider createSecurityProvider(@NotNull BundleContext context) { + private SecurityProvider createSecurityProvider(@NotNull Whiteboard whiteboard) { ConfigurationParameters userParams = ConfigurationParameters.of( ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_ACTION_PROVIDER, createWhiteboardAuthorizableActionProvider()), ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_NODE_NAME, createWhiteboardAuthorizableNodeName()), @@ -526,7 +559,7 @@ public class SecurityProviderRegistratio .with(authenticationConfiguration, EMPTY, privilegeConfiguration, EMPTY, userConfiguration, userParams, authorizationConfiguration, authorizationParams, principalConfiguration, EMPTY, tokenConfiguration, EMPTY) - .withWhiteboard(new OsgiWhiteboard(context)).build(); + .withWhiteboard(whiteboard).build(); } private RestrictionProvider createWhiteboardRestrictionProvider() { Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java Thu Mar 7 14:15:14 2019 @@ -24,6 +24,7 @@ import javax.security.auth.callback.Pass import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.jackrabbit.oak.AbstractSecurityTest; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor; import org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback; import org.apache.jackrabbit.oak.spi.security.authentication.callback.RepositoryCallback; import org.apache.jackrabbit.oak.spi.security.authentication.callback.WhiteboardCallback; @@ -52,7 +53,7 @@ public class CallbackHandlerImplTest ext } private CallbackHandlerImpl create(@NotNull Credentials creds) { - return new CallbackHandlerImpl(creds, root.getContentSession().getWorkspaceName(), getContentRepository(), getSecurityProvider(), whiteboard); + return new CallbackHandlerImpl(creds, root.getContentSession().getWorkspaceName(), getContentRepository(), getSecurityProvider(), whiteboard, LoginModuleMonitor.NOOP); } @Test Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java Thu Mar 7 14:15:14 2019 @@ -34,6 +34,7 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.authentication.JaasLoginContext; import org.apache.jackrabbit.oak.spi.security.authentication.LoginContext; import org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor; import org.apache.jackrabbit.oak.spi.security.authentication.PreAuthContext; import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard; import org.junit.Test; @@ -50,8 +51,12 @@ public class LoginContextProviderImplTes @Override public void before() throws Exception { super.before(); + lcProvider = newLoginContextProviderImpl(ConfigurationParameters.EMPTY); + } - lcProvider = new LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, ConfigurationParameters.EMPTY, getContentRepository(), getSecurityProvider(), new DefaultWhiteboard()); + private LoginContextProviderImpl newLoginContextProviderImpl(ConfigurationParameters params) { + return new LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, params, + getContentRepository(), getSecurityProvider(), new DefaultWhiteboard(), LoginModuleMonitor.NOOP); } @Test @@ -93,7 +98,7 @@ public class LoginContextProviderImplTes @Test public void testGetLoginContextWithInvalidProviderConfig() throws Exception { ConfigurationParameters params = ConfigurationParameters.of(AuthenticationConfiguration.PARAM_CONFIG_SPI_NAME, "invalid"); - LoginContextProvider provider = new LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, params, getContentRepository(), getSecurityProvider(), new DefaultWhiteboard()); + LoginContextProvider provider = newLoginContextProviderImpl(params); // invalid configuration falls back to default configuration LoginContext ctx = provider.getLoginContext(new SimpleCredentials(getTestUser().getID(), getTestUser().getID().toCharArray()), null); @@ -106,12 +111,12 @@ public class LoginContextProviderImplTes @Override public AppConfigurationEntry[] getAppConfigurationEntry(String applicationName) { return new AppConfigurationEntry[]{ - new AppConfigurationEntry(GuestLoginModule.class.getName(), AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap()) + new AppConfigurationEntry(GuestLoginModule.class.getName(), AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap<>()) }; } }); - LoginContextProvider provider = new LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, ConfigurationParameters.EMPTY, getContentRepository(), getSecurityProvider(), new DefaultWhiteboard()); + LoginContextProvider provider = newLoginContextProviderImpl(ConfigurationParameters.EMPTY); LoginContext ctx = provider.getLoginContext(null, null); ctx.login(); @@ -124,12 +129,12 @@ public class LoginContextProviderImplTes @Override public AppConfigurationEntry[] getAppConfigurationEntry(String applicationName) { return new AppConfigurationEntry[]{ - new AppConfigurationEntry(GuestLoginModule.class.getName(), AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap()) + new AppConfigurationEntry(GuestLoginModule.class.getName(), AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap<>()) }; } }); - LoginContextProvider provider = new LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, ConfigurationParameters.EMPTY, getContentRepository(), getSecurityProvider(), new DefaultWhiteboard()); + LoginContextProvider provider = newLoginContextProviderImpl(ConfigurationParameters.EMPTY); provider.getLoginContext(null, null); LoginContext ctx = provider.getLoginContext(null, null); Modified: jackrabbit/oak/trunk/oak-security-spi/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/pom.xml?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/pom.xml (original) +++ jackrabbit/oak/trunk/oak-security-spi/pom.xml Thu Mar 7 14:15:14 2019 @@ -171,6 +171,11 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java Thu Mar 7 14:15:14 2019 @@ -170,7 +170,7 @@ public abstract class AbstractLoginModul protected ConfigurationParameters options; private SecurityProvider securityProvider; - + private LoginModuleMonitor loginModuleMonitor; private Whiteboard whiteboard; private ContentSession systemSession; @@ -217,7 +217,8 @@ public abstract class AbstractLoginModul try { systemSession.close(); } catch (IOException e) { - log.debug(e.getMessage()); + onError(); + log.error(e.getMessage(), e); } systemSession = null; } @@ -255,10 +256,9 @@ public abstract class AbstractLoginModul } else { log.debug("Login: No supported credentials obtained from callback; trying shared state."); } - } catch (UnsupportedCallbackException e) { - log.warn(e.getMessage()); - } catch (IOException e) { - log.error(e.getMessage()); + } catch (UnsupportedCallbackException | IOException e) { + onError(); + log.error(e.getMessage(), e); } } @@ -343,8 +343,9 @@ public abstract class AbstractLoginModul try { callbackHandler.handle(new Callback[]{rcb}); securityProvider = rcb.getSecurityProvider(); - } catch (Exception e) { - log.debug("Unable to retrieve the SecurityProvider via callback", e); + } catch (IOException | UnsupportedCallbackException e) { + onError(); + log.error(e.getMessage(), e); } } return securityProvider; @@ -366,8 +367,9 @@ public abstract class AbstractLoginModul try { callbackHandler.handle(new Callback[]{cb}); whiteboard = cb.getWhiteboard(); - } catch (Exception e) { - log.debug("Unable to retrieve the Whiteboard via callback", e); + } catch (IOException | UnsupportedCallbackException e) { + onError(); + log.error(e.getMessage(), e); } } return whiteboard; @@ -401,8 +403,9 @@ public abstract class AbstractLoginModul } else { log.debug("Unable to retrieve the Root via RepositoryCallback; ContentRepository not available."); } - } catch (UnsupportedCallbackException | PrivilegedActionException | IOException e) { - log.debug(e.getMessage()); + } catch (IOException | UnsupportedCallbackException | PrivilegedActionException e) { + onError(); + log.error(e.getMessage(), e); } } return root; @@ -431,7 +434,8 @@ public abstract class AbstractLoginModul callbackHandler.handle(new Callback[]{userCallBack}); userManager = userCallBack.getUserManager(); } catch (IOException | UnsupportedCallbackException e) { - log.debug(e.getMessage()); + onError(); + log.error(e.getMessage(), e); } } @@ -461,7 +465,8 @@ public abstract class AbstractLoginModul callbackHandler.handle(new Callback[]{principalCallBack}); principalProvider = principalCallBack.getPrincipalProvider(); } catch (IOException | UnsupportedCallbackException e) { - log.debug(e.getMessage()); + onError(); + log.error(e.getMessage(), e); } } return principalProvider; @@ -507,4 +512,24 @@ public abstract class AbstractLoginModul } subject.getPublicCredentials().add(authInfo); } + + protected LoginModuleMonitor getLoginModuleMonitor() { + if (loginModuleMonitor == null && callbackHandler != null) { + RepositoryCallback rcb = new RepositoryCallback(); + try { + callbackHandler.handle(new Callback[] { rcb }); + loginModuleMonitor = rcb.getLoginModuleMonitor(); + } catch (IOException | UnsupportedCallbackException e) { + log.error(e.getMessage(), e); + } + } + return loginModuleMonitor; + } + + protected void onError() { + LoginModuleMonitor lmm = getLoginModuleMonitor(); + if (lmm != null) { + lmm.loginError(); + } + } } Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java?rev=1854982&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java (added) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java Thu Mar 7 14:15:14 2019 @@ -0,0 +1,32 @@ +/* + * 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.jackrabbit.oak.spi.security.authentication; + +import javax.management.openmbean.CompositeData; + +import org.osgi.annotation.versioning.ProviderType; + +@ProviderType +public interface LoginModuleMBean { + + String TYPE = "LoginModuleStats"; + + long getLoginErrors(); + + CompositeData getLoginErrorsHistory(); + +} Propchange: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java?rev=1854982&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java (added) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java Thu Mar 7 14:15:14 2019 @@ -0,0 +1,39 @@ +/* + * 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.jackrabbit.oak.spi.security.authentication; + +import org.osgi.annotation.versioning.ProviderType; + +@ProviderType +public interface LoginModuleMonitor { + + LoginModuleMonitor NOOP = new LoginModuleMonitor() { + + @Override + public void loginError() { + } + }; + + /** + * Event to be called in the case there is an erorr in the login chain. This + * is not covering failed logins, but actual operational errors that + * probably need to be investigated. Any triggered even should have a + * corresponding error logged to make this investigation possible. + */ + void loginError(); + +} Propchange: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java?rev=1854982&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java (added) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java Thu Mar 7 14:15:14 2019 @@ -0,0 +1,68 @@ +/* + * 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.jackrabbit.oak.spi.security.authentication; + +import javax.management.openmbean.CompositeData; + +import org.apache.jackrabbit.api.stats.TimeSeries; +import org.apache.jackrabbit.oak.stats.MeterStats; +import org.apache.jackrabbit.oak.stats.StatisticsProvider; +import org.apache.jackrabbit.oak.stats.StatsOptions; +import org.apache.jackrabbit.stats.TimeSeriesStatsUtil; + +public class LoginModuleStats implements LoginModuleMBean, LoginModuleMonitor { + + private final StatisticsProvider statisticsProvider; + + static final String LOGIN_ERRORS = "LOGIN_ERRORS"; + + private final MeterStats loginErrors; + + public LoginModuleStats(StatisticsProvider statisticsProvider) { + this.statisticsProvider = statisticsProvider; + this.loginErrors = statisticsProvider.getMeter(LOGIN_ERRORS, StatsOptions.DEFAULT); + } + + // -- LoginModuleMonitor + + @Override + public void loginError() { + loginErrors.mark(); + } + + // -- LoginModuleMBean + + @Override + public long getLoginErrors() { + return loginErrors.getCount(); + } + + @Override + public CompositeData getLoginErrorsHistory() { + return getTimeSeriesData(LOGIN_ERRORS, "Number of login errors."); + } + + // -- internal + + private CompositeData getTimeSeriesData(String name, String desc) { + return TimeSeriesStatsUtil.asCompositeData(getTimeSeries(name), desc); + } + + private TimeSeries getTimeSeries(String name) { + return statisticsProvider.getStats().getTimeSeries(name, true); + } +} Propchange: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java?rev=1854982&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java (added) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java Thu Mar 7 14:15:14 2019 @@ -0,0 +1,26 @@ +/* + * 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.jackrabbit.oak.spi.security.authentication; + +import org.osgi.annotation.versioning.ProviderType; + +@ProviderType +public interface LoginModuleStatsCollector { + + void setLoginModuleMonitor(LoginModuleMonitor lmm); + +} Propchange: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java Thu Mar 7 14:15:14 2019 @@ -20,6 +20,7 @@ import javax.security.auth.callback.Call import org.apache.jackrabbit.oak.api.ContentRepository; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; +import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor; import org.jetbrains.annotations.Nullable; /** @@ -33,6 +34,7 @@ public class RepositoryCallback implemen private ContentRepository contentRepository; private SecurityProvider securityProvider; private String workspaceName; + private LoginModuleMonitor loginModuleMonitor; @Nullable public String getWorkspaceName() { @@ -60,4 +62,13 @@ public class RepositoryCallback implemen public void setSecurityProvider(SecurityProvider securityProvider) { this.securityProvider = securityProvider; } + + public LoginModuleMonitor getLoginModuleMonitor() { + return loginModuleMonitor; + } + + @Nullable + public void setLoginModuleMonitor(LoginModuleMonitor loginModuleMonitor) { + this.loginModuleMonitor = loginModuleMonitor; + } } Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java Thu Mar 7 14:15:14 2019 @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@Version("1.0.1") +@Version("1.1.0") package org.apache.jackrabbit.oak.spi.security.authentication.callback; import org.osgi.annotation.versioning.Version; Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java Thu Mar 7 14:15:14 2019 @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@Version("1.2.1") +@Version("1.3.0") package org.apache.jackrabbit.oak.spi.security.authentication; import org.osgi.annotation.versioning.Version; Modified: jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java Thu Mar 7 14:15:14 2019 @@ -22,6 +22,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + import javax.jcr.Credentials; import javax.jcr.SimpleCredentials; import javax.security.auth.Subject; @@ -52,6 +55,8 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.principal.TestPrincipalProvider; import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard; import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; +import org.apache.jackrabbit.oak.stats.DefaultStatisticsProvider; +import org.apache.jackrabbit.oak.stats.StatisticsProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.junit.Test; @@ -72,7 +77,6 @@ public class AbstractLoginModuleTest { return lm; } - private static AbstractLoginModule initLoginModule(Class<?> supportedCredentials, CallbackHandler cbh) { AbstractLoginModule lm = new TestLoginModule(supportedCredentials); lm.initialize(new Subject(), cbh, Collections.<String, Object>emptyMap(), null); @@ -291,18 +295,30 @@ public class AbstractLoginModuleTest { assertSame(root, loginModule.getRoot()); } + private static LoginModuleStats newLoginModuleStats() { + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + StatisticsProvider sp = new DefaultStatisticsProvider(executor); + return new LoginModuleStats(sp); + } + @Test public void testGetRootIOException() { - AbstractLoginModule loginModule = initLoginModule(TestCredentials.class, new ThrowingCallbackHandler(true)); + LoginModuleStats stats = newLoginModuleStats(); + TestLoginModule lm = new TestLoginModule(TestCredentials.class, stats); + lm.initialize(new Subject(), new ThrowingCallbackHandler(true), Collections.emptyMap(), null); - assertNull(loginModule.getRoot()); + assertNull(lm.getRoot()); + assertEquals(1, stats.getLoginErrors()); } @Test public void testGetRootUnsupportedCallbackException() { - AbstractLoginModule loginModule = initLoginModule(TestCredentials.class, new ThrowingCallbackHandler(false)); + LoginModuleStats stats = newLoginModuleStats(); + TestLoginModule lm = new TestLoginModule(TestCredentials.class, stats); + lm.initialize(new Subject(), new ThrowingCallbackHandler(false), Collections.emptyMap(), null); - assertNull(loginModule.getRoot()); + assertNull(lm.getRoot()); + assertEquals(1, stats.getLoginErrors()); } @Test @@ -497,18 +513,64 @@ public class AbstractLoginModuleTest { assertSame(authInfo, fromSubject.iterator().next()); } + @Test + public void testOnError() { + LoginModuleStats stats = newLoginModuleStats(); + + CallbackHandler cbh = new CallbackHandler() { + @Override + public void handle(Callback[] callbacks) { + for (Callback cb : callbacks) { + if (cb instanceof RepositoryCallback) { + ((RepositoryCallback) cb).setLoginModuleMonitor(stats); + } + } + } + }; + + AbstractLoginModule lm = new AbstractLoginModule() { + + @Override + public boolean login() throws LoginException { + return false; + } + + @Override + public boolean commit() throws LoginException { + return false; + } + + @Override + protected Set<Class> getSupportedCredentials() { + return Collections.singleton(TestCredentials.class); + } + }; + lm.initialize(new Subject(), cbh, Collections.<String, Object>emptyMap(), null); + + assertTrue(lm.getLoginModuleMonitor() instanceof LoginModuleStats); + lm.onError(); + assertEquals(1, stats.getLoginErrors()); + } + //-------------------------------------------------------------------------- private final class TestCredentials implements Credentials {} private static final class TestLoginModule extends AbstractLoginModule { - private Class supportedCredentialsClass; + private final Class supportedCredentialsClass; + + private LoginModuleMonitor mon = LoginModuleMonitor.NOOP; private TestLoginModule(Class supportedCredentialsClass) { this.supportedCredentialsClass = supportedCredentialsClass; } + private TestLoginModule(Class supportedCredentialsClass, LoginModuleMonitor mon) { + this.supportedCredentialsClass = supportedCredentialsClass; + this.mon = mon; + } + @NotNull @Override protected Set<Class> getSupportedCredentials() { @@ -524,6 +586,11 @@ public class AbstractLoginModuleTest { public boolean commit() { return true; } + + @Override + protected LoginModuleMonitor getLoginModuleMonitor() { + return mon; + } } private final class TestCallbackHandler implements CallbackHandler { @@ -571,6 +638,7 @@ public class AbstractLoginModuleTest { rcb.setContentRepository(contentRepository); rcb.setSecurityProvider(securityProvider); rcb.setWorkspaceName(workspaceName); + rcb.setLoginModuleMonitor(LoginModuleMonitor.NOOP); } else { throw new UnsupportedCallbackException(cb); } Added: jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java?rev=1854982&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java (added) +++ jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java Thu Mar 7 14:15:14 2019 @@ -0,0 +1,42 @@ +/* + * 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.jackrabbit.oak.spi.security.authentication; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +import org.apache.jackrabbit.oak.stats.DefaultStatisticsProvider; +import org.apache.jackrabbit.oak.stats.StatisticsProvider; +import org.junit.Test; + +public class LoginModuleStatsTest { + + @Test + public void testLoginError() throws Exception { + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + StatisticsProvider sp = new DefaultStatisticsProvider(executor); + + LoginModuleStats s = new LoginModuleStats(sp); + s.loginError(); + assertEquals(1, s.getLoginErrors()); + assertNotNull(s.getLoginErrorsHistory()); + } + +} \ No newline at end of file Propchange: jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml?rev=1854982&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml (added) +++ jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml Thu Mar 7 14:15:14 2019 @@ -0,0 +1,39 @@ + <!-- + 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. + --> +<configuration> + +<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n</pattern> + </encoder> +</appender> + +<appender name="file" class="ch.qos.logback.core.FileAppender"> + <file>target/unit-tests.log</file> + <encoder> + <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n</pattern> + </encoder> +</appender> + +<root level="INFO"> + <!-- + <appender-ref ref="console"/> + --> + <appender-ref ref="file"/> +</root> + +</configuration> Propchange: jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml ------------------------------------------------------------------------------ svn:eol-style = native