Skip to content

Commit

Permalink
Added ability to load initial user on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
fickludd committed Oct 4, 2016
1 parent 0109532 commit c909d64
Show file tree
Hide file tree
Showing 13 changed files with 328 additions and 48 deletions.
Expand Up @@ -213,7 +213,7 @@ public void shouldFailOnMalformedToken() throws Exception
{
// Given
BasicAuthManager manager = new BasicAuthManager( mock( UserRepository.class), mock( PasswordPolicy.class ),
FakeClock.systemUTC() );
FakeClock.systemUTC(), mock( UserRepository.class ) );
BasicAuthSubject authSubject = mock( BasicAuthSubject.class );
BasicAuthentication authentication = new BasicAuthentication( manager );
when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.SUCCESS );
Expand Down
Expand Up @@ -47,46 +47,70 @@ public class BasicAuthManager implements AuthManager, UserManager, UserManagerSu
protected final AuthenticationStrategy authStrategy;
protected final UserRepository userRepository;
protected final PasswordPolicy passwordPolicy;
private final UserRepository initialUserRepository;

public BasicAuthManager( UserRepository userRepository, PasswordPolicy passwordPolicy, AuthenticationStrategy authStrategy )
public BasicAuthManager( UserRepository userRepository, PasswordPolicy passwordPolicy,
AuthenticationStrategy authStrategy, UserRepository initialUserRepository )
{
this.userRepository = userRepository;
this.passwordPolicy = passwordPolicy;
this.authStrategy = authStrategy;
this.initialUserRepository = initialUserRepository;
}

public BasicAuthManager( UserRepository userRepository, PasswordPolicy passwordPolicy, Clock clock )
public BasicAuthManager( UserRepository userRepository, PasswordPolicy passwordPolicy, Clock clock,
UserRepository initialUserRepository )
{
this( userRepository, passwordPolicy, new RateLimitedAuthenticationStrategy( clock, 3 ) );
this( userRepository, passwordPolicy, new RateLimitedAuthenticationStrategy( clock, 3 ), initialUserRepository );
}

@Override
public void init() throws Throwable
{
userRepository.init();
initialUserRepository.init();
}

@Override
public void start() throws Throwable
{
userRepository.start();
initialUserRepository.start();

if ( userRepository.numberOfUsers() == 0 )
{
newUser( "neo4j", "neo4j", true );
if ( initialUserRepository.numberOfUsers() == 0 )
{
newUser( "neo4j", "neo4j", true );
}
}
for ( String username : initialUserRepository.getAllUsernames() )
{
User oldUser = userRepository.getUserByName( username );
User newUser = initialUserRepository.getUserByName( username );
if ( oldUser == null )
{
userRepository.create( newUser );
}
else
{
userRepository.update( oldUser, newUser );
}
}
}

@Override
public void stop() throws Throwable
{
userRepository.stop();
initialUserRepository.stop();
}

@Override
public void shutdown() throws Throwable
{
userRepository.shutdown();
initialUserRepository.shutdown();
}

@Override
Expand Down
Expand Up @@ -48,6 +48,12 @@ public static FileUserRepository getUserRepository( Config config, LogProvider l
return new FileUserRepository( fileSystem, getUserRepositoryFile( config ), logProvider );
}

public static FileUserRepository getInitialUserRepository( Config config, LogProvider logProvider,
FileSystemAbstraction fileSystem )
{
return new FileUserRepository( fileSystem, getInitialUserRepositoryFile( config ), logProvider );
}

public static File getUserRepositoryFile( Config config )
{
return getUserRepositoryFile( config, USER_STORE_FILENAME );
Expand Down Expand Up @@ -95,9 +101,10 @@ public AuthManager newInstance( Config config, LogProvider logProvider, Log igno
}

final UserRepository userRepository = getUserRepository( config, logProvider, fileSystem );
final UserRepository initialUserRepository = getInitialUserRepository( config, logProvider, fileSystem );

final PasswordPolicy passwordPolicy = new BasicPasswordPolicy();

return new BasicAuthManager( userRepository, passwordPolicy, Clocks.systemClock() );
return new BasicAuthManager( userRepository, passwordPolicy, Clocks.systemClock(), initialUserRepository );
}
}
Expand Up @@ -23,6 +23,7 @@
import org.hamcrest.core.IsEqual;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import java.io.IOException;
Expand All @@ -31,9 +32,13 @@
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.logging.NullLogProvider;
import org.neo4j.test.rule.fs.EphemeralFileSystemRule;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
Expand All @@ -46,16 +51,23 @@

public class BasicAuthManagerTest
{
private InMemoryUserRepository users;
@Rule
public EphemeralFileSystemRule fsRule = new EphemeralFileSystemRule();

private Config config;
private UserRepository users;
private BasicAuthManager manager;
private AuthenticationStrategy authStrategy = mock( AuthenticationStrategy.class );;
private AuthenticationStrategy authStrategy = mock( AuthenticationStrategy.class );

@Before
public void setup() throws Throwable
{
users = new InMemoryUserRepository();
manager = new BasicAuthManager( users, mock( PasswordPolicy.class ), authStrategy );
manager.start();
config = Config.defaults();
users = BasicAuthManagerFactory.getUserRepository( config, NullLogProvider.getInstance(), fsRule.get() );
UserRepository initUserRepository =
BasicAuthManagerFactory.getInitialUserRepository( config, NullLogProvider.getInstance(), fsRule.get() );
manager = new BasicAuthManager( users, mock( PasswordPolicy.class ), authStrategy, initUserRepository );
manager.init();
}

@After
Expand All @@ -65,21 +77,106 @@ public void teardown() throws Throwable
}

@Test
public void shouldCreateDefaultUserIfNoneExist()
public void shouldCreateDefaultUserIfNoneExist() throws Throwable
{
// When
final User user = users.getUserByName( "neo4j" );
manager.start();

// Then
final User user = users.getUserByName( "neo4j" );
assertNotNull( user );
assertTrue( user.credentials().matchesPassword( "neo4j" ) );
assertTrue( user.passwordChangeRequired() );
}

@Test
public void shouldLoadInitialUserIfNoneExist() throws Throwable
{
// Given
FileUserRepository initialUserRepository =
BasicAuthManagerFactory.getInitialUserRepository( config, NullLogProvider.getInstance(), fsRule.get() );
initialUserRepository.start();
initialUserRepository.create(
new User.Builder( "initUser", Credential.forPassword( "123" ))
.withRequiredPasswordChange( false )
.build()
);
initialUserRepository.shutdown();

// When
manager.start();

// Then
final User user = users.getUserByName( "initUser" );
assertNotNull( user );
assertTrue( user.credentials().matchesPassword( "123" ) );
assertFalse( user.passwordChangeRequired() );
}

@Test
public void shouldAddInitialUserIfUsersExist() throws Throwable
{
// Given
FileUserRepository initialUserRepository =
BasicAuthManagerFactory.getInitialUserRepository( config, NullLogProvider.getInstance(), fsRule.get() );
initialUserRepository.start();
initialUserRepository.create(
new User.Builder( "initUser", Credential.forPassword( "123" ))
.withRequiredPasswordChange( false )
.build()
);
initialUserRepository.shutdown();
users.start();
createUser( "oldUser", "321", false );
users.shutdown();

// When
manager.start();

// Then
final User initUser = users.getUserByName( "initUser" );
assertNotNull( initUser );
assertTrue( initUser.credentials().matchesPassword( "123" ) );
assertFalse( initUser.passwordChangeRequired() );

final User oldUser = users.getUserByName( "oldUser" );
assertNotNull( oldUser );
assertTrue( oldUser.credentials().matchesPassword( "321" ) );
assertFalse( oldUser.passwordChangeRequired() );
}

@Test
public void shouldUpdateUserIfInitialUserExist() throws Throwable
{
// Given
FileUserRepository initialUserRepository =
BasicAuthManagerFactory.getInitialUserRepository( config, NullLogProvider.getInstance(), fsRule.get() );
initialUserRepository.start();
initialUserRepository.create(
new User.Builder( "oldUser", Credential.forPassword( "newPassword" ))
.withRequiredPasswordChange( false )
.build()
);
initialUserRepository.shutdown();
users.start();
createUser( "oldUser", "oldPassword", true );
users.shutdown();

// When
manager.start();

// Then
final User oldUser = users.getUserByName( "oldUser" );
assertNotNull( oldUser );
assertTrue( oldUser.credentials().matchesPassword( "newPassword" ) );
assertFalse( oldUser.passwordChangeRequired() );
}

@Test
public void shouldFindAndAuthenticateUserSuccessfully() throws Throwable
{
// Given
manager.start();
final User user = createUser( "jake", "abc123", false );

// When
Expand All @@ -93,6 +190,7 @@ public void shouldFindAndAuthenticateUserSuccessfully() throws Throwable
public void shouldFindAndAuthenticateUserAndReturnAuthStrategyResult() throws Throwable
{
// Given
manager.start();
final User user = createUser( "jake", "abc123", true );

// When
Expand All @@ -106,6 +204,7 @@ public void shouldFindAndAuthenticateUserAndReturnAuthStrategyResult() throws Th
public void shouldFindAndAuthenticateUserAndReturnPasswordChangeIfRequired() throws Throwable
{
// Given
manager.start();
final User user = createUser( "jake", "abc123", true );

// When
Expand All @@ -119,6 +218,7 @@ public void shouldFindAndAuthenticateUserAndReturnPasswordChangeIfRequired() thr
public void shouldFailAuthenticationIfUserIsNotFound() throws Throwable
{
// Given
manager.start();
createUser( "jake", "abc123", true );

// Then
Expand All @@ -128,6 +228,9 @@ public void shouldFailAuthenticationIfUserIsNotFound() throws Throwable
@Test
public void shouldCreateUser() throws Throwable
{
// Given
manager.start();

// When
manager.newUser( "foo", "bar", true );

Expand All @@ -142,6 +245,7 @@ public void shouldCreateUser() throws Throwable
public void shouldDeleteUser() throws Throwable
{
// Given
manager.start();
manager.newUser( "jake", "abc123", true );

// When
Expand All @@ -155,6 +259,7 @@ public void shouldDeleteUser() throws Throwable
public void shouldFailToDeleteUnknownUser() throws Throwable
{
// Given
manager.start();
manager.newUser( "jake", "abc123", true );

try
Expand All @@ -180,6 +285,7 @@ public void shouldFailToDeleteUnknownUser() throws Throwable
public void shouldSetPassword() throws Throwable
{
// Given
manager.start();
manager.newUser( "jake", "abc123", true );

// When
Expand All @@ -194,6 +300,9 @@ public void shouldSetPassword() throws Throwable
@Test
public void shouldReturnNullWhenSettingPasswordForUnknownUser() throws Throwable
{
// Given
manager.start();

// When
try
{
Expand Down
Expand Up @@ -72,7 +72,7 @@ public class UserServiceTest
protected void setupAuthManagerAndSubject()
{
BasicAuthManager basicAuthManager = new BasicAuthManager( userRepository, passwordPolicy,
mock( AuthenticationStrategy.class) );
mock( AuthenticationStrategy.class), new InMemoryUserRepository() );
authManager = basicAuthManager;
userManager = basicAuthManager.getUserManager();
neo4jSubject = new BasicAuthSubject( basicAuthManager, NEO4J_USER, AuthenticationResult.SUCCESS );
Expand Down
Expand Up @@ -39,6 +39,7 @@
import org.neo4j.kernel.impl.util.JobScheduler;
import org.neo4j.logging.Log;
import org.neo4j.logging.LogProvider;
import org.neo4j.server.security.auth.BasicAuthManagerFactory;
import org.neo4j.server.security.auth.BasicPasswordPolicy;
import org.neo4j.server.security.auth.RateLimitedAuthenticationStrategy;
import org.neo4j.server.security.enterprise.auth.plugin.PluginRealm;
Expand Down Expand Up @@ -130,9 +131,13 @@ public static InternalFlatFileRealm createInternalRealm( Config config, LogProvi
return new InternalFlatFileRealm(
getUserRepository( config, logProvider, fileSystem ),
getRoleRepository( config, logProvider, fileSystem ),
new BasicPasswordPolicy(), new RateLimitedAuthenticationStrategy( Clocks.systemClock(), 3 ),
new BasicPasswordPolicy(),
new RateLimitedAuthenticationStrategy( Clocks.systemClock(), 3 ),
config.get( SecuritySettings.native_authentication_enabled ),
config.get( SecuritySettings.native_authorization_enabled ), jobScheduler );
config.get( SecuritySettings.native_authorization_enabled ),
jobScheduler,
BasicAuthManagerFactory.getInitialUserRepository( config, logProvider, fileSystem )
);
}

private SecurityLog getSecurityLog( Log allegedSecurityLog )
Expand Down

0 comments on commit c909d64

Please sign in to comment.