diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseSecurityModule.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseSecurityModule.java index 250a7f9d5c813..736f291080735 100644 --- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseSecurityModule.java +++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/EnterpriseSecurityModule.java @@ -142,7 +142,7 @@ public EnterpriseAuthAndUserManager newAuthManager( Config config, LogProvider l } // Load plugin realms if we have any - realms.addAll( createPluginRealms( config, logProvider, secureHasher ) ); + realms.addAll( createPluginRealms( config, securityLog, secureHasher ) ); // Select the active realms in the order they are configured List orderedActiveRealms = selectOrderedActiveRealms( configuredRealms, realms ); @@ -196,7 +196,7 @@ private static CacheManager createCacheManager( Config config ) return new ShiroCaffeineCache.Manager( Ticker.systemTicker(), ttl, maxCapacity ); } - private static List createPluginRealms( Config config, LogProvider logProvider, SecureHasher secureHasher ) + private static List createPluginRealms( Config config, SecurityLog securityLog, SecureHasher secureHasher ) { List realms = new ArrayList<>(); Set excludedClasses = new HashSet<>(); @@ -212,7 +212,7 @@ private static List createPluginRealms( Config config, LogProvider logPro for ( AuthPlugin plugin : authPlugins ) { PluginRealm pluginRealm = - new PluginRealm( plugin, config, logProvider, Clocks.systemClock(), secureHasher ); + new PluginRealm( plugin, config, securityLog, Clocks.systemClock(), secureHasher ); realms.add( pluginRealm ); } } @@ -229,7 +229,7 @@ private static List createPluginRealms( Config config, LogProvider logPro if ( pluginAuthorizationEnabled && plugin instanceof AuthorizationPlugin ) { // This plugin implements both interfaces, create a combined plugin - pluginRealm = new PluginRealm( plugin, (AuthorizationPlugin) plugin, config, logProvider, + pluginRealm = new PluginRealm( plugin, (AuthorizationPlugin) plugin, config, securityLog, Clocks.systemClock(), secureHasher ); // We need to make sure we do not add a duplicate when the AuthorizationPlugin service gets loaded @@ -239,7 +239,7 @@ private static List createPluginRealms( Config config, LogProvider logPro else { pluginRealm = - new PluginRealm( plugin, null, config, logProvider, Clocks.systemClock(), secureHasher ); + new PluginRealm( plugin, null, config, securityLog, Clocks.systemClock(), secureHasher ); } realms.add( pluginRealm ); } @@ -255,7 +255,7 @@ private static List createPluginRealms( Config config, LogProvider logPro if ( !excludedClasses.contains( plugin.getClass() ) ) { PluginRealm pluginRealm = - new PluginRealm( null, plugin, config, logProvider, Clocks.systemClock(), secureHasher ); + new PluginRealm( null, plugin, config, securityLog, Clocks.systemClock(), secureHasher ); realms.add( pluginRealm ); } } @@ -267,8 +267,11 @@ private static List createPluginRealms( Config config, LogProvider logPro public static RoleRepository getRoleRepository( Config config, LogProvider logProvider, FileSystemAbstraction fileSystem ) { - File authStoreDir = config.get( DatabaseManagementSystemSettings.auth_store_directory ); - File roleStoreFile = new File( authStoreDir, ROLE_STORE_FILENAME ); - return new FileRoleRepository( fileSystem, roleStoreFile, logProvider ); + return new FileRoleRepository( fileSystem, getRoleRepositoryFile( config ), logProvider ); + } + + public static File getRoleRepositoryFile( Config config ) + { + return new File( config.get( DatabaseManagementSystemSettings.auth_store_directory ), ROLE_STORE_FILENAME ); } } diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/plugin/PluginRealm.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/plugin/PluginRealm.java index c0a156a15cdff..f3b7e3663ab12 100644 --- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/plugin/PluginRealm.java +++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/auth/plugin/PluginRealm.java @@ -40,7 +40,6 @@ import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.internal.Version; import org.neo4j.logging.Log; -import org.neo4j.logging.LogProvider; import org.neo4j.server.security.enterprise.auth.PredefinedRolesBuilder; import org.neo4j.server.security.enterprise.auth.SecureHasher; import org.neo4j.server.security.enterprise.auth.ShiroAuthToken; @@ -54,6 +53,7 @@ import org.neo4j.server.security.enterprise.auth.plugin.spi.AuthorizationPlugin; import org.neo4j.server.security.enterprise.auth.plugin.spi.CustomCacheableAuthenticationInfo; import org.neo4j.server.security.enterprise.auth.plugin.spi.RealmLifecycle; +import org.neo4j.server.security.enterprise.log.SecurityLog; import static org.neo4j.server.security.enterprise.configuration.SecuritySettings.PLUGIN_REALM_NAME_PREFIX; @@ -69,12 +69,12 @@ public class PluginRealm extends AuthorizingRealm implements RealmLifecycle, Shi private RealmOperations realmOperations = new PluginRealmOperations(); - public PluginRealm( Config config, LogProvider logProvider, Clock clock, SecureHasher secureHasher ) + public PluginRealm( Config config, SecurityLog securityLog, Clock clock, SecureHasher secureHasher ) { this.config = config; this.clock = clock; this.secureHasher = secureHasher; - this.log = logProvider.getLog( getClass() ); + this.log = securityLog; setCredentialsMatcher( new CredentialsMatcher() ); @@ -88,18 +88,18 @@ public PluginRealm( Config config, LogProvider logProvider, Clock clock, SecureH } public PluginRealm( AuthenticationPlugin authenticationPlugin, AuthorizationPlugin authorizationPlugin, - Config config, LogProvider logProvider, Clock clock, SecureHasher secureHasher ) + Config config, SecurityLog securityLog, Clock clock, SecureHasher secureHasher ) { - this( config, logProvider, clock, secureHasher ); + this( config, securityLog, clock, secureHasher ); this.authenticationPlugin = authenticationPlugin; this.authorizationPlugin = authorizationPlugin; resolvePluginName(); } - public PluginRealm( AuthPlugin authPlugin, Config config, LogProvider logProvider, Clock clock, + public PluginRealm( AuthPlugin authPlugin, Config config, SecurityLog securityLog, Clock clock, SecureHasher secureHasher ) { - this( config, logProvider, clock, secureHasher ); + this( config, securityLog, clock, secureHasher ); this.authPlugin = authPlugin; resolvePluginName(); } diff --git a/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/auth/plugin/PluginRealmTest.java b/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/auth/plugin/PluginRealmTest.java new file mode 100644 index 0000000000000..e67791705e9bf --- /dev/null +++ b/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/auth/plugin/PluginRealmTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.neo4j.server.security.enterprise.auth.plugin; + +import org.junit.Test; + +import java.time.Clock; +import java.util.Collection; + +import org.neo4j.kernel.configuration.Config; +import org.neo4j.logging.AssertableLogProvider; +import org.neo4j.server.security.enterprise.auth.SecureHasher; +import org.neo4j.server.security.enterprise.auth.plugin.api.AuthToken; +import org.neo4j.server.security.enterprise.auth.plugin.api.AuthenticationException; +import org.neo4j.server.security.enterprise.auth.plugin.api.RealmOperations; +import org.neo4j.server.security.enterprise.auth.plugin.spi.AuthInfo; +import org.neo4j.server.security.enterprise.auth.plugin.spi.AuthPlugin; +import org.neo4j.server.security.enterprise.auth.plugin.spi.AuthenticationInfo; +import org.neo4j.server.security.enterprise.auth.plugin.spi.AuthenticationPlugin; +import org.neo4j.server.security.enterprise.auth.plugin.spi.AuthorizationInfo; +import org.neo4j.server.security.enterprise.auth.plugin.spi.AuthorizationPlugin; +import org.neo4j.server.security.enterprise.auth.plugin.spi.RealmLifecycle; +import org.neo4j.server.security.enterprise.log.SecurityLog; + +import static java.lang.String.format; +import static org.mockito.Mockito.mock; +import static org.neo4j.logging.AssertableLogProvider.inLog; + +public class PluginRealmTest +{ + private static final RealmOperations IGNORED = null; + + private Config config = mock( Config.class ); + private AssertableLogProvider log = new AssertableLogProvider(); + private SecurityLog securityLog = new SecurityLog( log.getLog( this.getClass() ) ); + + @Test + public void shouldLogToSecurityLogFromAuthPlugin() throws Throwable + { + PluginRealm pluginRealm = new PluginRealm( new LoggingAuthPlugin(), config, securityLog, Clock.systemUTC(), + mock( SecureHasher.class ) ); + pluginRealm.initialize( IGNORED ); + assertLogged( "LoggingAuthPlugin" ); + } + + @Test + public void shouldLogToSecurityLogFromAuthenticationPlugin() throws Throwable + { + PluginRealm pluginRealm = new PluginRealm( + new LoggingAuthenticationPlugin(), + null, + config, securityLog, Clock.systemUTC(), mock( SecureHasher.class ) ); + pluginRealm.initialize( IGNORED ); + assertLogged( "LoggingAuthenticationPlugin" ); + } + + @Test + public void shouldLogToSecurityLogFromAuthorizationPlugin() throws Throwable + { + PluginRealm pluginRealm = new PluginRealm( + null, + new LoggingAuthorizationPlugin(), + config, securityLog, Clock.systemUTC(), mock( SecureHasher.class ) ); + pluginRealm.initialize( IGNORED ); + assertLogged( "LoggingAuthorizationPlugin" ); + } + + private void assertLogged( String name ) + { + log.assertExactly( + inLog( this.getClass() ).info( format( "{plugin-%s} info line", name ) ), + inLog( this.getClass() ).warn( format( "{plugin-%s} warn line", name ) ), + inLog( this.getClass() ).error( format( "{plugin-%s} error line", name ) ) + ); + } + + private class LoggingAuthPlugin extends LoggingAdapter implements AuthPlugin + { + @Override + public String name() + { + return "LoggingAuthPlugin"; + } + + @Override + public AuthInfo authenticateAndAuthorize( AuthToken authToken ) throws AuthenticationException + { + return null; + } + } + + private class LoggingAuthenticationPlugin extends LoggingAdapter implements AuthenticationPlugin + { + @Override + public String name() + { + return "LoggingAuthenticationPlugin"; + } + + @Override + public AuthenticationInfo authenticate( AuthToken authToken ) throws AuthenticationException + { + return null; + } + } + + private class LoggingAuthorizationPlugin extends LoggingAdapter implements AuthorizationPlugin + { + @Override + public String name() + { + return "LoggingAuthorizationPlugin"; + } + + @Override + public AuthorizationInfo authorize( Collection principals ) + { + return null; + } + } + + abstract class LoggingAdapter extends RealmLifecycle.Adapter + { + @Override + public void initialize( RealmOperations realmOperations ) throws Throwable + { + RealmOperations.Log log = realmOperations.log(); + if ( log.isDebugEnabled() ) + { + log.debug( "debug line" ); + } + log.info( "info line" ); + log.warn( "warn line" ); + log.error( "error line" ); + } + } +}