Skip to content

Commit

Permalink
Create multi realm auth manager
Browse files Browse the repository at this point in the history
Big refactoring of enterprise auth manager
- Add a new MultiRealmAuthManager that will eventually replace
ShiroAuthManager that does not inherit BasicAuthManager
- Add LdapRealm configurable from SecuritySettings
- Add EnterpriseUserManager interface
- Let internal FileUserRealm implement EnterpriseUserManager

We still need to move some of the login logic into FileUserRealm
  • Loading branch information
henriknyman committed Jun 27, 2016
1 parent a349f27 commit 8b47da6
Show file tree
Hide file tree
Showing 20 changed files with 767 additions and 182 deletions.
Expand Up @@ -76,7 +76,7 @@ protected Consumer<Map<Setting<?>, String>> getSettingsFunction()
@Parameterized.Parameter( 1 )
public HostnamePort address;

private Connection client;
protected Connection client;

@Parameterized.Parameters
public static Collection<Object[]> transports()
Expand Down
Expand Up @@ -83,7 +83,7 @@ public void addUserToRole( @Name( "username" ) String username, @Name( "roleName
{
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
shiroSubject.getRoleManager().addUserToRole( username, roleName );
shiroSubject.getUserManager().addUserToRole( username, roleName );
}

@PerformsDBMS
Expand All @@ -96,7 +96,7 @@ public void removeUserFromRole( @Name( "username" ) String username, @Name( "rol
{
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
shiroSubject.getRoleManager().removeUserFromRole( username, roleName );
shiroSubject.getUserManager().removeUserFromRole( username, roleName );
}

@PerformsDBMS
Expand Down Expand Up @@ -141,8 +141,8 @@ public Stream<UserResult> showCurrentUser( )
throws IllegalCredentialsException, IOException
{
ShiroAuthSubject shiroSubject = ShiroAuthSubject.castOrFail( authSubject );
RoleManager roleManager = shiroSubject.getRoleManager();
return Stream.of( new UserResult( shiroSubject.name(), roleManager.getRoleNamesForUser( shiroSubject.name() ) ) );
EnterpriseUserManager userManager = shiroSubject.getUserManager();
return Stream.of( new UserResult( shiroSubject.name(), userManager.getRoleNamesForUser( shiroSubject.name() ) ) );
}

@PerformsDBMS
Expand All @@ -154,9 +154,9 @@ public Stream<UserResult> listUsers() throws IllegalCredentialsException, IOExce
{
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
RoleManager roleManager = shiroSubject.getRoleManager();
EnterpriseUserManager userManager = shiroSubject.getUserManager();
return shiroSubject.getUserManager().getAllUsernames().stream()
.map( u -> new UserResult( u, roleManager.getRoleNamesForUser( u ) ) );
.map( u -> new UserResult( u, userManager.getRoleNamesForUser( u ) ) );
}

@PerformsDBMS
Expand All @@ -168,9 +168,9 @@ public Stream<RoleResult> listRoles() throws IllegalCredentialsException, IOExce
{
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
RoleManager roleManager = shiroSubject.getRoleManager();
return roleManager.getAllRoleNames().stream()
.map( r -> new RoleResult( r, roleManager.getUsernamesForRole( r ) ) );
EnterpriseUserManager userManager = shiroSubject.getUserManager();
return userManager.getAllRoleNames().stream()
.map( r -> new RoleResult( r, userManager.getUsernamesForRole( r ) ) );
}

@PerformsDBMS
Expand All @@ -183,7 +183,7 @@ public Stream<StringResult> listRolesForUser( @Name( "username" ) String usernam
{
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
return shiroSubject.getRoleManager().getRoleNamesForUser( username ).stream().map( StringResult::new );
return shiroSubject.getUserManager().getRoleNamesForUser( username ).stream().map( StringResult::new );
}

@PerformsDBMS
Expand All @@ -196,7 +196,7 @@ public Stream<StringResult> listUsersForRole( @Name( "roleName" ) String roleNam
{
throw new AuthorizationViolationException( PERMISSION_DENIED );
}
return shiroSubject.getRoleManager().getUsernamesForRole( roleName ).stream().map( StringResult::new );
return shiroSubject.getUserManager().getUsernamesForRole( roleName ).stream().map( StringResult::new );
}

public class StringResult {
Expand Down
Expand Up @@ -20,21 +20,15 @@
package org.neo4j.server.security.enterprise.auth;

import java.time.Clock;
import java.util.Map;

import org.neo4j.kernel.api.security.AuthManager;
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;
import org.neo4j.server.security.auth.PasswordPolicy;
import org.neo4j.server.security.auth.UserRepository;

public class EnterpriseAuthManager extends ShiroAuthManager
public interface EnterpriseAuthManager extends AuthManager
{
public EnterpriseAuthManager( UserRepository userRepository, RoleRepository roleRepository,
PasswordPolicy passwordPolicy, Clock clock, boolean authEnabled )
{
super( userRepository, roleRepository, passwordPolicy, clock, authEnabled );
}

@Override
public void start() throws Throwable
{
super.start();
}
EnterpriseUserManager getUserManager();
}
Expand Up @@ -19,17 +19,23 @@
*/
package org.neo4j.server.security.enterprise.auth;

import org.apache.shiro.realm.Realm;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.neo4j.dbms.DatabaseManagementSystemSettings;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.helpers.Service;
import org.neo4j.kernel.api.security.AuthManager;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.logging.LogProvider;
import org.neo4j.server.security.auth.AuthenticationStrategy;
import org.neo4j.server.security.auth.BasicPasswordPolicy;
import org.neo4j.server.security.auth.FileUserRepository;
import org.neo4j.server.security.auth.PasswordPolicy;
import org.neo4j.server.security.auth.RateLimitedAuthenticationStrategy;
import org.neo4j.server.security.auth.UserRepository;

import static java.time.Clock.systemUTC;
Expand All @@ -50,6 +56,28 @@ public EnterpriseAuthManagerFactory()

@Override
public AuthManager newInstance( Config config, LogProvider logProvider )
{
FileUserRealm internalRealm = createInternalRealm( config, logProvider );

List<Realm> realms = new ArrayList<>( 2 );

realms.add( internalRealm );

if ( config.get( SecuritySettings.ldap_auth_enabled ) )
{
realms.add( new LdapRealm( config ) );
}

if ( config.get( SecuritySettings.external_auth_enabled ) )
{

// TODO: Load pluggable realms
}

return new MultiRealmAuthManager( internalRealm, realms );
}

private FileUserRealm createInternalRealm( Config config, LogProvider logProvider )
{
// Resolve auth store file names
File authStoreDir = config.get( DatabaseManagementSystemSettings.auth_store_directory );
Expand All @@ -71,7 +99,9 @@ public AuthManager newInstance( Config config, LogProvider logProvider )

final PasswordPolicy passwordPolicy = new BasicPasswordPolicy();

return new EnterpriseAuthManager( userRepository, roleRepository, passwordPolicy, systemUTC(),
config.get( GraphDatabaseSettings.auth_enabled ) );
AuthenticationStrategy authenticationStrategy = new RateLimitedAuthenticationStrategy( systemUTC(), 3 );

return new FileUserRealm( userRepository, roleRepository, passwordPolicy, authenticationStrategy,
true );
}
}
@@ -0,0 +1,39 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.neo4j.server.security.enterprise.auth;

import java.io.IOException;
import java.util.Set;

import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.exception.IllegalCredentialsException;
import org.neo4j.server.security.auth.UserManager;

public interface EnterpriseUserManager extends UserManager, RoleManager
{
void setPassword( AuthSubject authSubject, String username, String password ) throws IOException,
IllegalCredentialsException;

void suspendUser( String username ) throws IOException;

void activateUser( String username ) throws IOException;

Set<String> getAllUsernames();
}

0 comments on commit 8b47da6

Please sign in to comment.