Skip to content

Commit

Permalink
Change name of method to better reflect usage
Browse files Browse the repository at this point in the history
Also cleaned up SecurityContext interface/classes
  • Loading branch information
OliviaYtterbrink authored and Lojjs committed Feb 7, 2018
1 parent 287c9d9 commit 2a6b606
Show file tree
Hide file tree
Showing 24 changed files with 179 additions and 312 deletions.
Expand Up @@ -22,8 +22,9 @@
import org.neo4j.internal.kernel.api.Token; import org.neo4j.internal.kernel.api.Token;


/** /**
* The LoginContext hold the executing authenticated user (subject). By calling {@link #freeze(Token)} the user is also authorized, and a * The LoginContext hold the executing authenticated user (subject).
* full SecurityContext is returned, which can be used to assert user permissions during query execution. * By calling {@link #authorize(Token)} the user is also authorized, and a full SecurityContext is returned,
* which can be used to assert user permissions during query execution.
*/ */
public interface LoginContext public interface LoginContext
{ {
Expand All @@ -38,7 +39,7 @@ public interface LoginContext
* @param token token lookup, used to compile property level security verification * @param token token lookup, used to compile property level security verification
* @return the security context * @return the security context
*/ */
SecurityContext freeze( Token token ); SecurityContext authorize( Token token );


LoginContext AUTH_DISABLED = new LoginContext() LoginContext AUTH_DISABLED = new LoginContext()
{ {
Expand All @@ -49,7 +50,7 @@ public AuthSubject subject()
} }


@Override @Override
public SecurityContext freeze( Token token ) public SecurityContext authorize( Token token )
{ {
return SecurityContext.AUTH_DISABLED; return SecurityContext.AUTH_DISABLED;
} }
Expand Down
Expand Up @@ -28,135 +28,96 @@
* *
* Must extend LoginContext to handle procedures creating internal transactions, periodic commit and the parallel cypher prototype. * Must extend LoginContext to handle procedures creating internal transactions, periodic commit and the parallel cypher prototype.
*/ */
public interface SecurityContext extends LoginContext public class SecurityContext implements LoginContext
{ {
protected final AuthSubject subject;
protected final AccessMode mode;

public SecurityContext( AuthSubject subject, AccessMode mode )
{
this.subject = subject;
this.mode = mode;
}

/** /**
* Get the authorization data of the user. This is immutable. * Get the authorization data of the user. This is immutable.
*/ */
AccessMode mode(); public AccessMode mode()
{
return mode;
}


/** /**
* Check whether the user is an admin. * Check whether the user is an admin.
*/ */
boolean isAdmin(); public boolean isAdmin()
{
return true;
}

@Override
public AuthSubject subject()
{
return subject;
}

@Override
public SecurityContext authorize( Token token )
{
return this;
}


/** /**
* Create a copy of this SecurityContext with the provided mode. * Create a copy of this SecurityContext with the provided mode.
*/ */
SecurityContext withMode( AccessMode mode ); public SecurityContext withMode( AccessMode mode )
{
return new SecurityContext( subject, mode );
}


default void assertCredentialsNotExpired() public void assertCredentialsNotExpired()
{ {
if ( subject().getAuthenticationResult().equals( AuthenticationResult.PASSWORD_CHANGE_REQUIRED ) ) if ( subject().getAuthenticationResult().equals( AuthenticationResult.PASSWORD_CHANGE_REQUIRED ) )
{ {
throw mode().onViolation( PERMISSION_DENIED ); throw mode().onViolation( PERMISSION_DENIED );
} }
} }


default String description() public String description()
{ {
return String.format( "user '%s' with %s", subject().username(), mode().name() ); return String.format( "user '%s' with %s", subject().username(), mode().name() );
} }


default String defaultString( String name ) protected String defaultString( String name )
{ {
return String.format( "%s{ username=%s, accessMode=%s }", name, subject().username(), mode() ); return String.format( "%s{ username=%s, accessMode=%s }", name, subject().username(), mode() );
} }


/** Allows all operations. */ /** Allows all operations. */
SecurityContext AUTH_DISABLED = new AuthDisabled( AccessMode.Static.FULL ); public static final SecurityContext AUTH_DISABLED = authDisabled( AccessMode.Static.FULL );


final class AuthDisabled implements SecurityContext private static SecurityContext authDisabled( AccessMode mode )
{ {
private final AccessMode mode; return new SecurityContext( AuthSubject.AUTH_DISABLED, mode )

private AuthDisabled( AccessMode mode )
{
this.mode = mode;
}

@Override
public AccessMode mode()
{
return mode;
}

@Override
public AuthSubject subject()
{ {
return AuthSubject.AUTH_DISABLED;
}

@Override
public boolean isAdmin()
{
return true;
}

@Override
public String toString()
{
return defaultString( "auth-disabled" );
}


@Override @Override
public String description() public SecurityContext withMode( AccessMode mode )
{ {
return "AUTH_DISABLED with " + mode.name(); return authDisabled( mode );
} }


@Override @Override
public SecurityContext freeze( Token token ) public String description()
{ {
return this; return "AUTH_DISABLED with " + mode().name();
} }


@Override @Override
public SecurityContext withMode( AccessMode mode ) public String toString()
{ {
return new AuthDisabled( mode ); return defaultString( "auth-disabled" );
} }
} };

final class Frozen implements SecurityContext
{
private final AuthSubject subject;
private final AccessMode mode;

public Frozen( AuthSubject subject, AccessMode mode )
{
this.subject = subject;
this.mode = mode;
}

@Override
public AccessMode mode()
{
return mode;
}

@Override
public AuthSubject subject()
{
return subject;
}

@Override
public boolean isAdmin()
{
return true;
}

@Override
public SecurityContext freeze( Token token )
{
return this;
}

@Override
public SecurityContext withMode( AccessMode mode )
{
return new Frozen( subject, mode );
}
} }
} }
Expand Up @@ -67,8 +67,8 @@ public AuthSubject subject()
} }


@Override @Override
public SecurityContext freeze( Token token ) public SecurityContext authorize( Token token )
{ {
return new SecurityContext.Frozen( subject(), accessMode ); return new SecurityContext( subject(), accessMode );
} }
} }
Expand Up @@ -175,7 +175,7 @@ public Supplier<ExplicitIndexTransactionState> explicitIndexTxStateSupplier()
public KernelTransaction newInstance( KernelTransaction.Type type, LoginContext loginContext, long timeout ) public KernelTransaction newInstance( KernelTransaction.Type type, LoginContext loginContext, long timeout )
{ {
assertCurrentThreadIsNotBlockingNewTransactions(); assertCurrentThreadIsNotBlockingNewTransactions();
SecurityContext securityContext = loginContext.freeze( token ); SecurityContext securityContext = loginContext.authorize( token );
try try
{ {
while ( !newTransactionsLock.readLock().tryLock( 1, TimeUnit.SECONDS ) ) while ( !newTransactionsLock.readLock().tryLock( 1, TimeUnit.SECONDS ) )
Expand Down
Expand Up @@ -107,7 +107,7 @@ storageEngine, new CanWrite(), new KernelToken( storeReadLayer ), new DefaultCur


StatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() ); StatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() );


transaction.initialize( 0, 0, statementLocks, KernelTransaction.Type.implicit, loginContext.freeze( mock( Token.class ) ), 0L, 1L ); transaction.initialize( 0, 0, statementLocks, KernelTransaction.Type.implicit, loginContext.authorize( mock( Token.class ) ), 0L, 1L );


return new Instances( transaction, storageEngine, storeReadLayer, storageStatement ); return new Instances( transaction, storageEngine, storeReadLayer, storageStatement );
} }
Expand Down
Expand Up @@ -450,7 +450,7 @@ public void shouldIncrementReuseCounterOnReuse() throws Exception
transaction.close(); transaction.close();
SimpleStatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() ); SimpleStatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() );
transaction.initialize( 1, BASE_TX_COMMIT_TIMESTAMP, statementLocks, KernelTransaction.Type.implicit, transaction.initialize( 1, BASE_TX_COMMIT_TIMESTAMP, statementLocks, KernelTransaction.Type.implicit,
loginContext().freeze( mock( Token.class ) ), 0L, 1L ); loginContext().authorize( mock( Token.class ) ), 0L, 1L );


// THEN // THEN
assertEquals( reuseCount + 1, transaction.getReuseCount() ); assertEquals( reuseCount + 1, transaction.getReuseCount() );
Expand Down Expand Up @@ -671,7 +671,7 @@ public void markForTerminationWithCorrectReuseCount() throws Exception


Locks.Client locksClient = mock( Locks.Client.class ); Locks.Client locksClient = mock( Locks.Client.class );
SimpleStatementLocks statementLocks = new SimpleStatementLocks( locksClient ); SimpleStatementLocks statementLocks = new SimpleStatementLocks( locksClient );
tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().freeze( mock( Token.class ) ), 0L, 0L ); tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().authorize( mock( Token.class ) ), 0L, 0L );


assertTrue( tx.markForTermination( reuseCount, terminationReason ) ); assertTrue( tx.markForTermination( reuseCount, terminationReason ) );


Expand All @@ -691,7 +691,7 @@ public void markForTerminationWithIncorrectReuseCount() throws Exception


Locks.Client locksClient = mock( Locks.Client.class ); Locks.Client locksClient = mock( Locks.Client.class );
SimpleStatementLocks statementLocks = new SimpleStatementLocks( locksClient ); SimpleStatementLocks statementLocks = new SimpleStatementLocks( locksClient );
tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().freeze( mock( Token.class ) ), 0L, 0L ); tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().authorize( mock( Token.class ) ), 0L, 0L );


assertFalse( tx.markForTermination( nextReuseCount, terminationReason ) ); assertFalse( tx.markForTermination( nextReuseCount, terminationReason ) );


Expand Down Expand Up @@ -758,7 +758,7 @@ private void initializeAndClose( KernelTransactionImplementation tx, int times )
for ( int i = 0; i < times; i++ ) for ( int i = 0; i < times; i++ )
{ {
SimpleStatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() ); SimpleStatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() );
tx.initialize( i + 10, i + 10, statementLocks, KernelTransaction.Type.implicit, loginContext().freeze( mock( Token.class ) ), 0L, 0L ); tx.initialize( i + 10, i + 10, statementLocks, KernelTransaction.Type.implicit, loginContext().authorize( mock( Token.class ) ), 0L, 0L );
tx.close(); tx.close();
} }
} }
Expand Down
Expand Up @@ -144,7 +144,7 @@ public KernelTransactionImplementation newTransaction( long lastTransactionIdWhe
{ {
KernelTransactionImplementation tx = newNotInitializedTransaction(); KernelTransactionImplementation tx = newNotInitializedTransaction();
StatementLocks statementLocks = new SimpleStatementLocks( locks ); StatementLocks statementLocks = new SimpleStatementLocks( locks );
SecurityContext securityContext = loginContext.freeze( mock( Token.class ) ); SecurityContext securityContext = loginContext.authorize( mock( Token.class ) );
tx.initialize( lastTransactionIdWhenStarted, BASE_TX_COMMIT_TIMESTAMP,statementLocks, Type.implicit, tx.initialize( lastTransactionIdWhenStarted, BASE_TX_COMMIT_TIMESTAMP,statementLocks, Type.implicit,
securityContext, transactionTimeout, 1L ); securityContext, transactionTimeout, 1L );
return tx; return tx;
Expand Down
Expand Up @@ -409,7 +409,7 @@ public void shouldNotLeakTransactionOnSecurityContextFreezeFailure() throws Thro
{ {
KernelTransactions kernelTransactions = newKernelTransactions(); KernelTransactions kernelTransactions = newKernelTransactions();
LoginContext loginContext = mock( LoginContext.class ); LoginContext loginContext = mock( LoginContext.class );
when( loginContext.freeze( any() ) ).thenThrow( new AuthorizationExpiredException( "Freeze failed." ) ); when( loginContext.authorize( any() ) ).thenThrow( new AuthorizationExpiredException( "Freeze failed." ) );


assertException(() -> kernelTransactions.newInstance(KernelTransaction.Type.explicit, loginContext, 0L), assertException(() -> kernelTransactions.newInstance(KernelTransaction.Type.explicit, loginContext, 0L),
AuthorizationExpiredException.class, "Freeze failed."); AuthorizationExpiredException.class, "Freeze failed.");
Expand Down
Expand Up @@ -268,7 +268,7 @@ public void failWhenCallingNonExistingProcedures() throws Throwable
{ {
// When // When
dbmsOperations().procedureCallDbms( procedureName( "dbms", "iDoNotExist" ), new Object[0], dbmsOperations().procedureCallDbms( procedureName( "dbms", "iDoNotExist" ), new Object[0],
AnonymousContext.none().freeze( mock( Token.class ) ) ); AnonymousContext.none().authorize( mock( Token.class ) ) );
fail( "This should never get here" ); fail( "This should never get here" );
} }
catch ( Exception e ) catch ( Exception e )
Expand Down
Expand Up @@ -346,7 +346,7 @@ public void accessTransactionIdAndCommitTime()
@Test @Test
public void shouldGetEmptyUsernameForAnonymousContext() public void shouldGetEmptyUsernameForAnonymousContext()
{ {
when( transaction.securityContext() ).thenReturn( AnonymousContext.read().freeze( mock( Token.class ) ) ); when( transaction.securityContext() ).thenReturn( AnonymousContext.read().authorize( mock( Token.class ) ) );


TxStateTransactionDataSnapshot transactionDataSnapshot = snapshot(); TxStateTransactionDataSnapshot transactionDataSnapshot = snapshot();
assertEquals( "", transactionDataSnapshot.username() ); assertEquals( "", transactionDataSnapshot.username() );
Expand All @@ -358,7 +358,7 @@ public void shouldAccessUsernameFromAuthSubject()
AuthSubject authSubject = mock( AuthSubject.class ); AuthSubject authSubject = mock( AuthSubject.class );
when( authSubject.username() ).thenReturn( "Christof" ); when( authSubject.username() ).thenReturn( "Christof" );
when( transaction.securityContext() ) when( transaction.securityContext() )
.thenReturn( new SecurityContext.Frozen( authSubject, AccessMode.Static.FULL ) ); .thenReturn( new SecurityContext( authSubject, AccessMode.Static.FULL ) );


TxStateTransactionDataSnapshot transactionDataSnapshot = snapshot(); TxStateTransactionDataSnapshot transactionDataSnapshot = snapshot();
assertEquals( "Christof", transactionDataSnapshot.username() ); assertEquals( "Christof", transactionDataSnapshot.username() );
Expand Down
Expand Up @@ -197,9 +197,9 @@ public AuthSubject subject()
} }


@Override @Override
public SecurityContext freeze( Token token ) public SecurityContext authorize( Token token )
{ {
return new SecurityContext.Frozen( subject, AccessMode.Static.WRITE ); return new SecurityContext( subject, AccessMode.Static.WRITE );
} }
}; };
Map<String,Object> metadata = genericMap( "username", "joe" ); Map<String,Object> metadata = genericMap( "username", "joe" );
Expand Down
Expand Up @@ -107,8 +107,8 @@ public AuthSubject subject()
} }


@Override @Override
public SecurityContext freeze( Token token ) public SecurityContext authorize( Token token )
{ {
return new SecurityContext.Frozen( authSubject, accessMode ); return new SecurityContext( authSubject, accessMode );
} }
} }
Expand Up @@ -51,7 +51,7 @@ public void shouldFailWhenDeprecatedChangePasswordWithStaticAccessModeInDbmsMode


// When // When
dbmsOperations().procedureCallDbms( procedureName( "dbms", "changePassword" ), inputArray, dbmsOperations().procedureCallDbms( procedureName( "dbms", "changePassword" ), inputArray,
AnonymousContext.none().freeze( mock( Token.class ) ) ); AnonymousContext.none().authorize( mock( Token.class ) ) );
} }


@Test @Test
Expand All @@ -67,7 +67,7 @@ public void shouldFailWhenChangePasswordWithStaticAccessModeInDbmsMode() throws


// When // When
dbmsOperations().procedureCallDbms( procedureName( "dbms", "security", "changePassword" ), inputArray, dbmsOperations().procedureCallDbms( procedureName( "dbms", "security", "changePassword" ), inputArray,
AnonymousContext.none().freeze( mock( Token.class ) ) ); AnonymousContext.none().authorize( mock( Token.class ) ) );
} }


@Override @Override
Expand Down
Expand Up @@ -54,7 +54,7 @@ public void setup() throws Throwable
manager.init(); manager.init();
manager.start(); manager.start();
manager.newUser( "johan", "bar", false ); manager.newUser( "johan", "bar", false );
context = manager.login( authToken( "johan", "bar" ) ).freeze( mock( Token.class ) ); context = manager.login( authToken( "johan", "bar" ) ).authorize( mock( Token.class ) );
} }


@After @After
Expand Down
Expand Up @@ -153,7 +153,7 @@ private void setUpMocks()
QueryRegistryOperations registryOperations = mock( QueryRegistryOperations.class ); QueryRegistryOperations registryOperations = mock( QueryRegistryOperations.class );
when( statement.queryRegistration() ).thenReturn( registryOperations ); when( statement.queryRegistration() ).thenReturn( registryOperations );
when( statementBridge.get() ).thenReturn( statement ); when( statementBridge.get() ).thenReturn( statement );
when( kernelTransaction.securityContext() ).thenReturn( loginContext.freeze( mock( Token.class ) ) ); when( kernelTransaction.securityContext() ).thenReturn( loginContext.authorize( mock( Token.class ) ) );
when( kernelTransaction.transactionType() ).thenReturn( type ); when( kernelTransaction.transactionType() ).thenReturn( type );
when( database.getGraph() ).thenReturn( databaseFacade ); when( database.getGraph() ).thenReturn( databaseFacade );
when( databaseFacade.getDependencyResolver() ).thenReturn( resolver ); when( databaseFacade.getDependencyResolver() ).thenReturn( resolver );
Expand Down

0 comments on commit 2a6b606

Please sign in to comment.