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 // Given
BasicAuthManager manager = new BasicAuthManager( mock( UserRepository.class), mock( PasswordPolicy.class ), BasicAuthManager manager = new BasicAuthManager( mock( UserRepository.class), mock( PasswordPolicy.class ),
FakeClock.systemUTC() ); FakeClock.systemUTC(), mock( UserRepository.class ) );
BasicAuthSubject authSubject = mock( BasicAuthSubject.class ); BasicAuthSubject authSubject = mock( BasicAuthSubject.class );
BasicAuthentication authentication = new BasicAuthentication( manager ); BasicAuthentication authentication = new BasicAuthentication( manager );
when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.SUCCESS ); 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 AuthenticationStrategy authStrategy;
protected final UserRepository userRepository; protected final UserRepository userRepository;
protected final PasswordPolicy passwordPolicy; 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.userRepository = userRepository;
this.passwordPolicy = passwordPolicy; this.passwordPolicy = passwordPolicy;
this.authStrategy = authStrategy; 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 @Override
public void init() throws Throwable public void init() throws Throwable
{ {
userRepository.init(); userRepository.init();
initialUserRepository.init();
} }


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


if ( userRepository.numberOfUsers() == 0 ) 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 @Override
public void stop() throws Throwable public void stop() throws Throwable
{ {
userRepository.stop(); userRepository.stop();
initialUserRepository.stop();
} }


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


@Override @Override
Expand Down
Expand Up @@ -48,6 +48,12 @@ public static FileUserRepository getUserRepository( Config config, LogProvider l
return new FileUserRepository( fileSystem, getUserRepositoryFile( config ), logProvider ); 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 ) public static File getUserRepositoryFile( Config config )
{ {
return getUserRepositoryFile( config, USER_STORE_FILENAME ); 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 userRepository = getUserRepository( config, logProvider, fileSystem );
final UserRepository initialUserRepository = getInitialUserRepository( config, logProvider, fileSystem );


final PasswordPolicy passwordPolicy = new BasicPasswordPolicy(); 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.hamcrest.core.IsEqual;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;


import java.io.IOException; import java.io.IOException;
Expand All @@ -31,9 +32,13 @@
import org.neo4j.kernel.api.security.AuthenticationResult; import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException; import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException; 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.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
Expand All @@ -46,16 +51,23 @@


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

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


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


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


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


// Then // Then
final User user = users.getUserByName( "neo4j" );
assertNotNull( user ); assertNotNull( user );
assertTrue( user.credentials().matchesPassword( "neo4j" ) ); assertTrue( user.credentials().matchesPassword( "neo4j" ) );
assertTrue( user.passwordChangeRequired() ); 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 @Test
public void shouldFindAndAuthenticateUserSuccessfully() throws Throwable public void shouldFindAndAuthenticateUserSuccessfully() throws Throwable
{ {
// Given // Given
manager.start();
final User user = createUser( "jake", "abc123", false ); final User user = createUser( "jake", "abc123", false );


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


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


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


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

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


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


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


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


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

// When // When
try try
{ {
Expand Down
Expand Up @@ -72,7 +72,7 @@ public class UserServiceTest
protected void setupAuthManagerAndSubject() protected void setupAuthManagerAndSubject()
{ {
BasicAuthManager basicAuthManager = new BasicAuthManager( userRepository, passwordPolicy, BasicAuthManager basicAuthManager = new BasicAuthManager( userRepository, passwordPolicy,
mock( AuthenticationStrategy.class) ); mock( AuthenticationStrategy.class), new InMemoryUserRepository() );
authManager = basicAuthManager; authManager = basicAuthManager;
userManager = basicAuthManager.getUserManager(); userManager = basicAuthManager.getUserManager();
neo4jSubject = new BasicAuthSubject( basicAuthManager, NEO4J_USER, AuthenticationResult.SUCCESS ); 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.kernel.impl.util.JobScheduler;
import org.neo4j.logging.Log; import org.neo4j.logging.Log;
import org.neo4j.logging.LogProvider; 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.BasicPasswordPolicy;
import org.neo4j.server.security.auth.RateLimitedAuthenticationStrategy; import org.neo4j.server.security.auth.RateLimitedAuthenticationStrategy;
import org.neo4j.server.security.enterprise.auth.plugin.PluginRealm; 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( return new InternalFlatFileRealm(
getUserRepository( config, logProvider, fileSystem ), getUserRepository( config, logProvider, fileSystem ),
getRoleRepository( 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_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 ) private SecurityLog getSecurityLog( Log allegedSecurityLog )
Expand Down

0 comments on commit c909d64

Please sign in to comment.