admins.init(); admins.start(); admins.create( new User.Builder( username, LegacyCredential.INACCESSIBLE ).build() ); admins.stop(); admins.shutdown();
/** * This is a future-proofing test. If you come here because you've made changes to the serialization format, * this is your reminder to make sure to build this is in a backwards compatible way. */ @Test public void shouldReadV1SerializationFormat() throws Exception { // Given UserSerialization serialization = new UserSerialization(); byte[] salt1 = new byte[] { (byte) 0xa5, (byte) 0x43 }; byte[] hash1 = new byte[] { (byte) 0xfe, (byte) 0x00, (byte) 0x56, (byte) 0xc3, (byte) 0x7e }; byte[] salt2 = new byte[] { (byte) 0x34, (byte) 0xa4 }; byte[] hash2 = new byte[] { (byte) 0x0e, (byte) 0x1f, (byte) 0xff, (byte) 0xc2, (byte) 0x3e }; // When List<User> deserialized = serialization.deserializeRecords( UTF8.encode( "Mike:SHA-256,FE0056C37E,A543:\n" + "Steve:SHA-256,FE0056C37E,A543:nice_guy,password_change_required\n" + "Bob:SHA-256,0E1FFFC23E,34A4:password_change_required\n" ) ); // Then assertThat( deserialized, equalTo( asList( new User.Builder( "Mike", new LegacyCredential( salt1, hash1 ) ).build(), new User.Builder( "Steve", new LegacyCredential( salt1, hash1 ) ) .withRequiredPasswordChange( true ).withFlag("nice_guy").build(), new User.Builder( "Bob", new LegacyCredential( salt2, hash2 ) ) .withRequiredPasswordChange( true ) .build() ) ) ); } }
User updatedUser = existingUser.augment().withCredentials( LegacyCredential.forPassword( password ) ).withRequiredPasswordChange( requirePasswordChange ).build(); userRepository.update( existingUser, updatedUser );
admins.init(); admins.start(); admins.create( new User.Builder( username, LegacyCredential.INACCESSIBLE ).build() ); admins.stop(); admins.shutdown();
User updatedUser = existingUser.augment().withCredentials( LegacyCredential.forPassword( password ) ).withRequiredPasswordChange( requirePasswordChange ).build(); userRepository.update( existingUser, updatedUser );
@Override public void setUserPassword( String username, String password, boolean requirePasswordChange ) throws IOException, InvalidArgumentsException { User existingUser = getUser( username ); passwordPolicy.validatePassword( password ); if ( existingUser.credentials().matchesPassword( password ) ) { throw new InvalidArgumentsException( "Old password and new password cannot be the same." ); } try { User updatedUser = existingUser.augment() .withCredentials( Credential.forPassword( password ) ) .withRequiredPasswordChange( requirePasswordChange ) .build(); synchronized ( this ) { userRepository.update( existingUser, updatedUser ); } } catch ( ConcurrentModificationException e ) { // try again setUserPassword( username, password, requirePasswordChange ); } clearCacheForUser( username ); }
private void setPassword( String password ) throws Throwable { Config config = loadNeo4jConfig(); FileSystemAbstraction fileSystem = outsideWorld.fileSystem(); if ( realUsersExist( config ) ) { File authFile = CommunitySecurityModule.getUserRepositoryFile( config ); throw new CommandFailed( realUsersExistErrorMsg( fileSystem, authFile ) ); } else { File file = CommunitySecurityModule.getInitialUserRepositoryFile( config ); if ( fileSystem.fileExists( file ) ) { fileSystem.deleteFile( file ); } FileUserRepository userRepository = new FileUserRepository( fileSystem, file, NullLogProvider.getInstance() ); userRepository.start(); userRepository.create( new User.Builder( INITIAL_USER_NAME, LegacyCredential.forPassword( UTF8.encode( password ) ) ) .withRequiredPasswordChange( false ) .build() ); userRepository.shutdown(); outsideWorld.stdOutLine( "Changed password for user '" + INITIAL_USER_NAME + "'." ); } }
@Override protected User deserializeRecord( String line, int lineNumber ) throws FormatException { String[] parts = line.split( userSeparator, -1 ); if ( parts.length != 3 ) { throw new FormatException( format( "wrong number of line fields, expected 3, got %d [line %d]", parts.length, lineNumber ) ); } User.Builder b = new User.Builder() .withName( parts[0] ) .withCredentials( deserializeCredentials( parts[1], lineNumber ) ); for ( String flag : parts[2].split( ",", -1 ) ) { String trimmed = flag.trim(); if ( !trimmed.isEmpty() ) { b = b.withFlag( trimmed ); } } return b.build(); }
@Override public User newUser( String username, byte[] initialPassword, boolean requirePasswordChange ) throws IOException, InvalidArgumentsException { try { userRepository.assertValidUsername( username ); passwordPolicy.validatePassword( initialPassword ); User user = new User.Builder() .withName( username ) .withCredentials( LegacyCredential.forPassword( initialPassword ) ) .withRequiredPasswordChange( requirePasswordChange ) .build(); userRepository.create( user ); return user; } finally { // Clear password if ( initialPassword != null ) { Arrays.fill( initialPassword, (byte) 0 ); } } }
@Override public void suspendUser( String username ) throws IOException, InvalidArgumentsException { User user = getUser( username ); if ( !user.hasFlag( IS_SUSPENDED ) ) { User suspendedUser = user.augment().withFlag( IS_SUSPENDED ).build(); try { synchronized ( this ) { userRepository.update( user, suspendedUser ); } } catch ( ConcurrentModificationException e ) { // Try again suspendUser( username ); } } clearCacheForUser( username ); }
@Override public void activateUser( String username, boolean requirePasswordChange ) throws IOException, InvalidArgumentsException { User user = getUser( username ); if ( user.hasFlag( IS_SUSPENDED ) ) { User activatedUser = user.augment() .withoutFlag( IS_SUSPENDED ) .withRequiredPasswordChange( requirePasswordChange ) .build(); try { synchronized ( this ) { userRepository.update( user, activatedUser ); } } catch ( ConcurrentModificationException e ) { // Try again activateUser( username, requirePasswordChange ); } } clearCacheForUser( username ); }
@Override public User newUser( String username, String initialPassword, boolean requirePasswordChange ) throws IOException, InvalidArgumentsException { userRepository.assertValidUsername( username ); passwordPolicy.validatePassword( initialPassword ); User user = new User.Builder() .withName( username ) .withCredentials( Credential.forPassword( initialPassword ) ) .withRequiredPasswordChange( requirePasswordChange ) .build(); synchronized ( this ) { userRepository.create( user ); } return user; }
/** Use this user as a base for a new user object */ public Builder augment() { return new Builder( this ); }
public Builder withRequiredPasswordChange( boolean change ) { if ( change ) { withFlag( PASSWORD_CHANGE_REQUIRED ); } else { withoutFlag( PASSWORD_CHANGE_REQUIRED ); } return this; }
User user = new User.Builder( "jake", LegacyCredential.INACCESSIBLE ).withRequiredPasswordChange( true ).build();
private void setPassword( String password ) throws Throwable { Config config = loadNeo4jConfig(); FileSystemAbstraction fileSystem = outsideWorld.fileSystem(); if ( realUsersExist( config ) ) { File authFile = CommunitySecurityModule.getUserRepositoryFile( config ); throw new CommandFailed( realUsersExistErrorMsg( fileSystem, authFile ) ); } else { File file = CommunitySecurityModule.getInitialUserRepositoryFile( config ); if ( fileSystem.fileExists( file ) ) { fileSystem.deleteFile( file ); } FileUserRepository userRepository = new FileUserRepository( fileSystem, file, NullLogProvider.getInstance() ); userRepository.start(); userRepository.create( new User.Builder( INITIAL_USER_NAME, LegacyCredential.forPassword( UTF8.encode( password ) ) ) .withRequiredPasswordChange( false ) .build() ); userRepository.shutdown(); outsideWorld.stdOutLine( "Changed password for user '" + INITIAL_USER_NAME + "'." ); } }
@Override public User newUser( String username, byte[] initialPassword, boolean requirePasswordChange ) throws IOException, InvalidArgumentsException { try { userRepository.assertValidUsername( username ); passwordPolicy.validatePassword( initialPassword ); User user = new User.Builder() .withName( username ) .withCredentials( LegacyCredential.forPassword( initialPassword ) ) .withRequiredPasswordChange( requirePasswordChange ) .build(); userRepository.create( user ); return user; } finally { // Clear password if ( initialPassword != null ) { Arrays.fill( initialPassword, (byte) 0 ); } } }
@Override protected User deserializeRecord( String line, int lineNumber ) throws FormatException { String[] parts = line.split( userSeparator, -1 ); if ( parts.length != 3 ) { throw new FormatException( format( "wrong number of line fields, expected 3, got %d [line %d]", parts.length, lineNumber ) ); } User.Builder b = new User.Builder() .withName( parts[0] ) .withCredentials( deserializeCredentials( parts[1], lineNumber ) ); for ( String flag : parts[2].split( ",", -1 ) ) { String trimmed = flag.trim(); if ( !trimmed.isEmpty() ) { b = b.withFlag( trimmed ); } } return b.build(); }
@Test public void shouldBuildImmutableUser() { LegacyCredential abc = LegacyCredential.forPassword( "123abc" ); LegacyCredential fruit = LegacyCredential.forPassword( "fruit" ); User u1 = new User.Builder( "Steve", abc ).build(); User u2 = new User.Builder( "Steve", fruit ) .withRequiredPasswordChange( true ) .withFlag( "nice_guy" ).build(); assertThat( u1, equalTo( u1 ) ); assertThat( u1, not( equalTo( u2 ) ) ); User u1AsU2 = u1.augment().withCredentials( fruit ) .withRequiredPasswordChange( true ) .withFlag( "nice_guy" ).build(); assertThat( u1, not( equalTo( u1AsU2 ))); assertThat( u2, equalTo( u1AsU2 )); User u2AsU1 = u2.augment().withCredentials( abc ) .withRequiredPasswordChange( false ) .withoutFlag( "nice_guy" ).build(); assertThat( u2, not( equalTo( u2AsU1 ))); assertThat( u1, equalTo( u2AsU1 )); assertThat( u1, not( equalTo( u2 ) ) ); } }
@Test public void shouldLoadInitialUserIfNoneExist() throws Throwable { // Given FileUserRepository initialUserRepository = CommunitySecurityModule.getInitialUserRepository( config, NullLogProvider.getInstance(), fsRule.get() ); initialUserRepository.start(); initialUserRepository.create( new User.Builder( "neo4j", LegacyCredential.forPassword( "123" ) ) .withRequiredPasswordChange( false ) .build() ); initialUserRepository.shutdown(); // When authManager().start(); // Then final User user = users.getUserByName( "neo4j" ); assertNotNull( user ); assertTrue( user.credentials().matchesPassword( "123" ) ); assertFalse( user.passwordChangeRequired() ); }