Skip to content

Commit

Permalink
Add acceptance scenario for security logging
Browse files Browse the repository at this point in the history
  • Loading branch information
Mats-SX authored and fickludd committed Sep 12, 2016
1 parent 820dcd6 commit b028b12
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 30 deletions.
Expand Up @@ -19,6 +19,14 @@
*/
package org.neo4j.server.security.enterprise.auth;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.google.common.base.Charsets;
import org.junit.Rule;
import org.junit.Test;

Expand All @@ -29,9 +37,12 @@
import org.neo4j.test.rule.concurrent.ThreadingRule;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.fail;

import static org.neo4j.server.security.enterprise.auth.AuthProcedures.PERMISSION_DENIED;
import static org.neo4j.server.security.enterprise.auth.PredefinedRolesBuilder.ADMIN;
import static org.neo4j.server.security.enterprise.auth.PredefinedRolesBuilder.ARCHITECT;
Expand Down Expand Up @@ -78,6 +89,46 @@ public void loginShouldFailWithIncorrectPassword() throws Exception
neo.assertInitFailed( subject );
}

/*
* Logging scenario smoke test
*/
@Test
public void shouldLogSecurityEvents() throws Exception
{
S mats = neo.login( "mats", "neo4j" );
// for REST, login doesn't happen until the subject does something
neo.executeQuery( mats, "UNWIND [] AS i RETURN 1", Collections.emptyMap(), r -> {} );
assertEmpty( adminSubject, "CALL dbms.security.createUser('mats', 'neo4j', false)" );
// assertEmpty( adminSubject, "CALL dbms.security.createRole('role1')" );
assertEmpty( adminSubject, "CALL dbms.security.addRoleToUser('reader', 'mats')" );
mats = neo.login( "mats", "neo4j" );
assertEmpty( mats, "MATCH (n) WHERE id(n) < 0 RETURN 1" );
// assertEmpty( adminSubject, "CALL dbms.security.deleteRole('role1')" );
assertEmpty( adminSubject, "CALL dbms.security.deleteUser('mats')" );

// flush log
neo.getLocalGraph().shutdown();

// assert on log content
List<String> allLines = readFullLog();

assertThat( allLines, hasItem( containsString( "Login fail for user `mats`" ) ) );
assertThat( allLines, hasItem( containsString( "User created: `mats`" ) ) );
assertThat( allLines, hasItem( containsString( "Role `reader` added to user `mats`" ) ) );
assertThat( allLines, hasItem( containsString( "Login success for user `mats`" ) ) );
assertThat( allLines, hasItem( containsString( "User deleted: `mats`" ) ) );
}

private List<String> readFullLog() throws IOException
{
List<String> lines = new ArrayList<>();
BufferedReader bufferedReader = new BufferedReader(
neo.fileSystem().openAsReader( new File( securityLog.getAbsolutePath() ), Charsets.UTF_8 ) );
lines.add( bufferedReader.readLine() );
bufferedReader.lines().forEach( lines::add );
return lines;
}

/*
Admin creates user Henrik with password bar
Henrik logs in with correct password (gets prompted to change - change to foo)
Expand Down
Expand Up @@ -22,7 +22,10 @@
import org.junit.Rule;
import org.junit.rules.RuleChain;

import java.util.Map;

import org.neo4j.bolt.v1.transport.integration.Neo4jWithSocket;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.test.TestEnterpriseGraphDatabaseFactory;
import org.neo4j.test.TestGraphDatabaseFactory;
Expand All @@ -49,8 +52,8 @@ private TestGraphDatabaseFactory getTestGraphDatabaseFactory()
}

@Override
public NeoInteractionLevel<BoltInteraction.BoltSubject> setUpNeoServer() throws Throwable
public NeoInteractionLevel<BoltInteraction.BoltSubject> setUpNeoServer( Map<Setting<?>, String> config ) throws Throwable
{
return new BoltInteraction( server );
return new BoltInteraction( config );
}
}
Expand Up @@ -22,7 +22,10 @@
import org.junit.Rule;
import org.junit.rules.RuleChain;

import java.util.Map;

import org.neo4j.bolt.v1.transport.integration.Neo4jWithSocket;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.test.TestEnterpriseGraphDatabaseFactory;
import org.neo4j.test.TestGraphDatabaseFactory;
Expand All @@ -31,7 +34,7 @@
public class BoltAuthScenariosInteractionTest extends AuthScenariosInteractionTestBase<BoltInteraction.BoltSubject>
{
private Neo4jWithSocket server = new Neo4jWithSocket( getTestGraphDatabaseFactory(),
settings -> settings.put( GraphDatabaseSettings.auth_enabled, "true" ) );
settings -> settings.put( GraphDatabaseSettings.auth_enabled, "true" ) );

@Rule
public final RuleChain ruleChain = RuleChain.outerRule( SuppressOutput.suppressAll() ).around( server );
Expand All @@ -49,8 +52,8 @@ private TestGraphDatabaseFactory getTestGraphDatabaseFactory()
}

@Override
public NeoInteractionLevel<BoltInteraction.BoltSubject> setUpNeoServer() throws Throwable
public NeoInteractionLevel<BoltInteraction.BoltSubject> setUpNeoServer( Map<Setting<?>, String> config ) throws Throwable
{
return new BoltInteraction( server );
return new BoltInteraction( config );
}
}
Expand Up @@ -42,13 +42,18 @@
import org.neo4j.bolt.v1.transport.socket.client.TransportConnection;
import org.neo4j.function.Factory;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.helpers.HostnamePort;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.impl.coreapi.InternalTransaction;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacade;
import org.neo4j.test.TestEnterpriseGraphDatabaseFactory;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse;
Expand All @@ -69,12 +74,22 @@ public class BoltInteraction implements NeoInteractionLevel<BoltInteraction.Bolt
protected final Factory<TransportConnection> connectionFactory = SocketConnection::new;
private final Neo4jWithSocket server;
private Map<String,BoltSubject> subjects = new HashMap<>();
private FileSystemAbstraction _fileSystem;

EnterpriseAuthManager authManager;

public BoltInteraction( Neo4jWithSocket server ) throws IOException
BoltInteraction( Map<Setting<?>, String> config ) throws IOException
{
this.server = server;
TestEnterpriseGraphDatabaseFactory factory = new TestEnterpriseGraphDatabaseFactory();
factory.setFileSystem( new EphemeralFileSystemAbstraction() );
this.server = new Neo4jWithSocket(
factory,
settings -> {
settings.put( GraphDatabaseSettings.auth_enabled, "true" );
settings.putAll( config );
} );
server.restartDatabase( r -> {} );
this._fileSystem = factory.getFileSystem();
GraphDatabaseFacade db = (GraphDatabaseFacade) server.graphDatabaseService();
authManager = db.getDependencyResolver().resolveDependency( EnterpriseAuthManager.class );
}
Expand All @@ -91,6 +106,12 @@ public GraphDatabaseFacade getLocalGraph()
return (GraphDatabaseFacade) server.graphDatabaseService();
}

@Override
public FileSystemAbstraction fileSystem()
{
return _fileSystem;
}

@Override
public InternalTransaction beginLocalTransactionAsUser( BoltSubject subject, KernelTransaction.Type txType )
throws Throwable
Expand Down
Expand Up @@ -19,13 +19,16 @@
*/
package org.neo4j.server.security.enterprise.auth;

import java.util.Map;

import org.neo4j.graphdb.config.Setting;
import org.neo4j.kernel.enterprise.api.security.EnterpriseAuthSubject;

public class EmbeddedAuthScenariosInteractionTest extends AuthScenariosInteractionTestBase<EnterpriseAuthSubject>
{
@Override
protected NeoInteractionLevel<EnterpriseAuthSubject> setUpNeoServer() throws Throwable
protected NeoInteractionLevel<EnterpriseAuthSubject> setUpNeoServer( Map<Setting<?>, String> config ) throws Throwable
{
return new EmbeddedInteraction();
return new EmbeddedInteraction( config );
}
}
Expand Up @@ -21,11 +21,15 @@

import org.neo4j.kernel.enterprise.api.security.EnterpriseAuthSubject;

import java.util.Map;

import org.neo4j.graphdb.config.Setting;

public class EmbeddedBuiltInProceduresTest extends BuiltInProceduresInteractionTestBase<EnterpriseAuthSubject>
{
@Override
protected NeoInteractionLevel<EnterpriseAuthSubject> setUpNeoServer() throws Throwable
protected NeoInteractionLevel<EnterpriseAuthSubject> setUpNeoServer( Map<Setting<?>, String> config ) throws Throwable
{
return new EmbeddedInteraction();
return new EmbeddedInteraction( config );
}
}
Expand Up @@ -26,8 +26,11 @@
import org.neo4j.bolt.BoltKernelExtension;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.enterprise.api.security.EnterpriseAuthSubject;
Expand All @@ -46,21 +49,36 @@ public class EmbeddedInteraction implements NeoInteractionLevel<EnterpriseAuthSu
private GraphDatabaseFacade db;
private MultiRealmAuthManager manager;
private EnterpriseUserManager userManager;
private FileSystemAbstraction _fileSystem;

EmbeddedInteraction() throws Throwable
EmbeddedInteraction( Map<Setting<?>, String> config ) throws Throwable
{
this(new TestEnterpriseGraphDatabaseFactory().newImpermanentDatabaseBuilder());
TestEnterpriseGraphDatabaseFactory factory = new TestEnterpriseGraphDatabaseFactory();
factory.setFileSystem( new EphemeralFileSystemAbstraction() );
GraphDatabaseBuilder builder = factory.newImpermanentDatabaseBuilder();
for ( Map.Entry<Setting<?>,String> entry : config.entrySet() )
{
builder.setConfig( entry.getKey(), entry.getValue() );
}
this._fileSystem = factory.getFileSystem();

init( builder );
}

public EmbeddedInteraction( GraphDatabaseBuilder builder ) throws Throwable
{
init( builder );
}

private void init( GraphDatabaseBuilder builder ) throws Throwable
{
builder.setConfig( boltConnector( "0" ).enabled, "true" );
builder.setConfig( boltConnector( "0" ).encryption_level, OPTIONAL.name() );
builder.setConfig( BoltKernelExtension.Settings.tls_key_file, NeoInteractionLevel.tempPath( "key", ".key" ) );
builder.setConfig( BoltKernelExtension.Settings.tls_certificate_file, NeoInteractionLevel.tempPath( "cert", ".cert" ) );
builder.setConfig( BoltKernelExtension.Settings.tls_certificate_file,
NeoInteractionLevel.tempPath( "cert", ".cert" ) );
builder.setConfig( GraphDatabaseSettings.auth_enabled, "true" );
builder.setConfig( GraphDatabaseSettings.auth_manager, "enterprise-auth-manager" );

db = (GraphDatabaseFacade) builder.newGraphDatabase();
manager = db.getDependencyResolver().resolveDependency( MultiRealmAuthManager.class );
manager.init();
Expand All @@ -77,6 +95,12 @@ public EnterpriseUserManager getLocalUserManager()
@Override
public GraphDatabaseFacade getLocalGraph() { return db; }

@Override
public FileSystemAbstraction fileSystem()
{
return _fileSystem;
}

@Override
public InternalTransaction beginLocalTransactionAsUser( EnterpriseAuthSubject subject,
KernelTransaction.Type txType ) throws Throwable
Expand Down
Expand Up @@ -27,6 +27,7 @@

import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.impl.coreapi.InternalTransaction;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacade;

Expand All @@ -36,6 +37,8 @@ public interface NeoInteractionLevel<S>

GraphDatabaseFacade getLocalGraph();

FileSystemAbstraction fileSystem();

default InternalTransaction beginLocalTransactionAsUser( S subject ) throws Throwable
{
return beginLocalTransactionAsUser( subject, KernelTransaction.Type.explicit );
Expand Down
Expand Up @@ -23,20 +23,26 @@
import org.junit.Assert;
import org.junit.Before;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.neo4j.bolt.v1.transport.integration.Neo4jWithSocket;
import org.neo4j.bolt.v1.transport.integration.TransportTestUtil;
import org.neo4j.bolt.v1.transport.socket.client.SocketConnection;
import org.neo4j.bolt.v1.transport.socket.client.TransportConnection;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.helpers.HostnamePort;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.impl.proc.Procedures;
Expand All @@ -62,7 +68,6 @@
import static org.neo4j.bolt.v1.messaging.util.MessageMatchers.msgSuccess;
import static org.neo4j.bolt.v1.transport.integration.TransportTestUtil.eventuallyReceives;
import static org.neo4j.helpers.collection.MapUtil.map;
import static org.junit.Assert.assertTrue;
import static org.neo4j.procedure.Mode.READ;
import static org.neo4j.procedure.Mode.WRITE;
import static org.neo4j.server.security.enterprise.auth.PredefinedRolesBuilder.ADMIN;
Expand Down Expand Up @@ -106,11 +111,22 @@ String pwdReqErrMsg( String errMsg )
EnterpriseUserManager userManager;

protected NeoInteractionLevel<S> neo;
File securityLog;

private Map<Setting<?>,String> configure() throws IOException
{
Path homeDir = Files.createTempDirectory( "logs" );
securityLog = new File( homeDir.toFile(), "security.log" );
Map<Setting<?>,String> config = new HashMap<>( 1 );
config.put( GraphDatabaseSettings.logs_directory, homeDir.toAbsolutePath().toString() );
return config;
}

@Before
public void setUp() throws Throwable
{
neo = setUpNeoServer();
neo = setUpNeoServer( configure() );

neo.getLocalGraph().getDependencyResolver().resolveDependency( Procedures.class )
.registerProcedure( ClassWithProcedures.class );
userManager = neo.getLocalUserManager();
Expand All @@ -135,7 +151,7 @@ public void setUp() throws Throwable
executeQuery( writeSubject, "UNWIND range(0,2) AS number CREATE (:Node {number:number, name:'node'+number})" );
}

protected abstract NeoInteractionLevel<S> setUpNeoServer() throws Throwable;
protected abstract NeoInteractionLevel<S> setUpNeoServer( Map<Setting<?>, String> config ) throws Throwable;

@After
public void tearDown() throws Throwable
Expand Down
Expand Up @@ -19,9 +19,12 @@
*/
package org.neo4j.server.rest.security;

import java.util.Map;

import org.junit.Rule;

import org.neo4j.server.security.enterprise.auth.AuthProceduresInteractionTestBase;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.server.security.enterprise.auth.NeoInteractionLevel;
import org.neo4j.test.rule.SuppressOutput;

Expand All @@ -41,8 +44,8 @@ public RESTAuthProceduresInteractionTest()
}

@Override
public NeoInteractionLevel<RESTSubject> setUpNeoServer() throws Throwable
public NeoInteractionLevel<RESTSubject> setUpNeoServer( Map<Setting<?>,String> config ) throws Throwable
{
return new RESTInteraction();
return new RESTInteraction( config );
}
}

0 comments on commit b028b12

Please sign in to comment.