Skip to content

Commit

Permalink
Merge pull request #706 from systay/jakewins
Browse files Browse the repository at this point in the history
Consoles in webadmin can now be disabled
  • Loading branch information
systay committed Jul 14, 2012
2 parents 0302f69 + be7214b commit 745ee69
Show file tree
Hide file tree
Showing 22 changed files with 587 additions and 83 deletions.
4 changes: 4 additions & 0 deletions server/CHANGES.txt
@@ -1,3 +1,7 @@
1.8
--------------------
o Consoles in webadmin can now be disabled.

1.8.M06 (2012-07-06)
--------------------
o Fixed issue that stopped the server from starting without the UDC-jars.
Expand Down
19 changes: 19 additions & 0 deletions server/src/docs/dev/server-configuration.txt
Expand Up @@ -167,3 +167,22 @@ wrapper.java.additional.3=-Xloggc:data/log/neo4j-gc.log
This line is already present and needs uncommenting. Note also that logging is not directed to console ;
You will find the logging statements in 'data/log/ne4j-gc.log' or whatever directory you set at the option.


=== Disabling console types in Webadmin ===

You may, for security reasons, want to disable the Gremlin console and/or the Neo4j Shell in Webadmin.
Both of them allow arbitrary code execution, and so they could constitute a security risk if you do not trust all users of your Neo4j Server.

In the 'conf/neo4j-server.properties' file:

[source]
----
# To disable both Neo4j Shell and Gremlin:
org.neo4j.server.manage.console_engines=

# To enable only the Neo4j Shell:
org.neo4j.server.manage.console_engines=shell

# To enable both
org.neo4j.server.manage.console_engines=gremlin,shell
----
@@ -0,0 +1,80 @@
/**
* Copyright (c) 2002-2012 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.server.webadmin.rest;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.neo4j.server.helpers.ServerBuilder.server;

import org.junit.After;
import org.junit.Test;
import org.neo4j.server.NeoServer;
import org.neo4j.server.configuration.Configurator;
import org.neo4j.server.rest.JaxRsResponse;
import org.neo4j.server.rest.RestRequest;
import org.neo4j.test.server.ExclusiveServerTestBase;

public class ConfigureEnabledManagementConsolesTest extends ExclusiveServerTestBase {

private NeoServer server;

@After
public void stopTheServer()
{
server.stop();
}

@Test
public void shouldBeAbleToDisableGremlinConsole() throws Exception {
server = server().withProperty(Configurator.MANAGEMENT_CONSOLE_ENGINES, "shell").build();
server.start();

assertThat(exec("g","gremlin").getStatus(), is(400));
assertThat(exec("ls","shell").getStatus(), is(200));
}

@Test
public void shouldBeAbleToExplicitlySetConsolesToEnabled() throws Exception
{
server = server().withProperty(Configurator.MANAGEMENT_CONSOLE_ENGINES, "shell,gremlin").build();
server.start();

assertThat(exec("g","gremlin").getStatus(), is(200));
assertThat(exec("ls","shell").getStatus(), is(200));
}



@Test
public void gremlinAndShellConsolesShouldBeEnabledByDefault() throws Exception {
server = server().build();
server.start();

assertThat(exec("g","gremlin").getStatus(), is(200));
assertThat(exec("ls","shell").getStatus(), is(200));
}

private JaxRsResponse exec(String command, String engine)
{
return RestRequest.req().post(server.baseUri() + "db/manage/server/console", "{" +
"\"engine\":\""+engine+"\"," +
"\"command\":\""+command+"\\n\"}");
}
}
@@ -0,0 +1,111 @@
/**
* Copyright (c) 2002-2012 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.server.webadmin.rest;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;

import javax.ws.rs.core.Response;

import org.junit.Test;
import org.neo4j.server.database.Database;
import org.neo4j.server.rest.repr.OutputFormat;
import org.neo4j.server.rest.repr.formats.JsonFormat;
import org.neo4j.server.webadmin.console.ScriptSession;

public class ConsoleServiceTest
{
private final URI uri = URI.create( "http://peteriscool.com:6666/" );

@Test
public void correctRepresentation() throws URISyntaxException, UnsupportedEncodingException
{
ConsoleService consoleService = new ConsoleService( new ShellOnlyConsoleSessionFactory(), null, new OutputFormat( new JsonFormat(), uri, null ) );

Response consoleResponse = consoleService.getServiceDefinition();

assertEquals( 200, consoleResponse.getStatus() );
String response = decode( consoleResponse );
assertThat( response, containsString( "resources" ) );
assertThat( response, containsString( uri.toString() ) );
}

@Test
public void advertisesAvailableConsoleEngines() throws URISyntaxException, UnsupportedEncodingException
{
ConsoleService consoleServiceWithJustShellEngine = new ConsoleService( new ShellOnlyConsoleSessionFactory(), null, new OutputFormat( new JsonFormat(), uri, null ) );

String response = decode( consoleServiceWithJustShellEngine.getServiceDefinition());

assertThat( response, containsString( "\"engines\" : [ \"shell\" ]" ) );

ConsoleService consoleServiceWithShellAndGremlin = new ConsoleService( new GremlinAndShellConsoleSessionFactory(), null, new OutputFormat( new JsonFormat(), uri, null ) );

response = decode( consoleServiceWithShellAndGremlin.getServiceDefinition());

assertThat( response, containsString( "\"engines\" : [ \"shell\", \"gremlin\" ]" ) );
}

private String decode( final Response response ) throws UnsupportedEncodingException
{
return new String( (byte[]) response.getEntity(), "UTF-8" );
}

private static class ShellOnlyConsoleSessionFactory implements ConsoleSessionFactory
{
@Override
public ScriptSession createSession(String engineName, Database database)
{
return null;
}

@Override
public Iterable<String> supportedEngines()
{
return new ArrayList<String>(){{
add("shell");
}};
}
}

private static class GremlinAndShellConsoleSessionFactory implements ConsoleSessionFactory
{
@Override
public ScriptSession createSession(String engineName, Database database)
{
return null;
}

@Override
public Iterable<String> supportedEngines()
{
return new ArrayList<String>(){{
add("shell");
add("gremlin");
}};
}
}
}
Expand Up @@ -25,7 +25,7 @@

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;

import javax.ws.rs.core.Response;

Expand All @@ -40,7 +40,7 @@
import org.neo4j.server.webadmin.console.ScriptSession;
import org.neo4j.test.ImpermanentGraphDatabase;

public class GremlinConsoleServiceTest implements SessionFactory
public class GremlinConsoleServiceTest implements ConsoleSessionFactory
{
private ConsoleService consoleService;
private Database database;
Expand Down Expand Up @@ -76,17 +76,6 @@ public void canCreateNodesInGremlinLand() throws UnsupportedEncodingException
assertEquals( 200, evaluatedGremlinResponse.getStatus() );
assertThat( response, containsString( "v[2]" ) );
}

@Test
public void correctRepresentation() throws URISyntaxException, UnsupportedEncodingException
{
Response consoleResponse = consoleService.getServiceDefinition();

assertEquals( 200, consoleResponse.getStatus() );
String response = decode( consoleResponse );
assertThat( response, containsString( "resources" ) );
assertThat( response, containsString( uri.toString() ) );
}

@Before
public void setUp() throws Exception
Expand All @@ -106,4 +95,12 @@ public ScriptSession createSession( String engineName, Database database )
{
return new GremlinSession( database );
}

@Override
public Iterable<String> supportedEngines()
{
return new ArrayList<String>(){{
add("gremlin");
}};
}
}
Expand Up @@ -25,6 +25,7 @@

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.Response;
Expand All @@ -44,7 +45,7 @@
import org.neo4j.shell.ShellSettings;
import org.neo4j.test.TestGraphDatabaseFactory;

public class Neo4jShellConsoleSessionTest implements SessionFactory
public class Neo4jShellConsoleSessionTest implements ConsoleSessionFactory
{
private static final String LN = System.getProperty("line.separator");
private ConsoleService consoleService;
Expand Down Expand Up @@ -97,4 +98,12 @@ private List<String> decode( final Response response ) throws UnsupportedEncodin
{
return (List<String>)JsonHelper.readJson(new String( (byte[]) response.getEntity(), "UTF-8" ));
}

@Override
public Iterable<String> supportedEngines()
{
return new ArrayList<String>(){{
add("shell");
}};
}
}
Expand Up @@ -30,10 +30,10 @@ define(

class ConsoleRouter extends Router
routes :
"/console/" : "console"
"/console/:type" : "console"
"/console/" : "showConsole"
"/console/:type" : "showConsole"

consoleType : "shell"
consoleType : "http"

init : (appState) =>
@appState = appState
Expand All @@ -47,29 +47,59 @@ define(
@shellState = new Console(server:@appState.get("server"), lang:"shell")
@httpState = new HttpConsole(server:@appState.get("server"), lang:"http")

@views =
gremlin : new GremlinConsoleView
appState : @appState
consoleState : @gremlinState
lang: "gremlin"
shell : new ShellConsoleView
appState : @appState
consoleState : @shellState
lang: "shell"
http : new HttpConsoleView
appState : @appState
consoleState : @httpState
lang: "http"
# Ask the server what console engines are available
self = this
@appState.getServer().manage.console.availableEngines (engines) ->
self.onAvailableEnginesLoaded(engines)

console : (type=false) =>
showConsole : (type=false) =>
@saveLocation()

if type is false then type = @consoleType
@consoleType = type
@appState.set( mainView : @getConsoleView(type) )
@getConsoleView(type).focusOnInputField()

getConsoleView : (type) =>
@views[type]
if @views?
if @views[type]?
view = @views[type]
else
alert "Unsupported console type: '#{type}', is it disabled in the server?."
view = @views['http']

@appState.set( mainView : view )
view.focusOnInputField()
else
# Set a flag to remember to re-run this method when
# available engines has been loaded.
@renderWhenEnginesAreLoaded = true

onAvailableEnginesLoaded : (engines) ->
engines.push('http') # HTTP is always available
@views =
http : new HttpConsoleView
appState : @appState
consoleState : @httpState
lang : "http"
engines : engines

if _(engines).indexOf('gremlin') > -1
@views.gremlin = new GremlinConsoleView
appState : @appState
consoleState : @gremlinState
lang : "gremlin"
engines : engines

if _(engines).indexOf('shell') > -1
@views.shell = new ShellConsoleView
appState : @appState
consoleState : @shellState
lang : "shell"
engines : engines

# Use shell per default if it is available
@consoleType = "shell"

if @renderWhenEnginesAreLoaded?
@showConsole()

#
# Bootstrapper SPI
Expand Down

0 comments on commit 745ee69

Please sign in to comment.