So, till now we looked at how to configure a Neo4j server in order to obtain optimum performance. However, in a practical scenario, we also need to ensure that our database server is secure enough to handle confidential and critical data. In this section, we will look at some aspects of securing the Neo4j database server.
When a Neo4j server is started, the default behavior is to bind the host to the localhost with the connection port as 7474. Hence only local requests from the same machine are serviced. You can configure this behavior in the conf/neo4j-server.properties
file by uncommenting, adding, or modifying the following lines:
# http port (for all data, administrative, and UI access) org.neo4j.server.webserver.port=7474 #let the webserver only listen on the specified IP. Default #is localhost (only accept local connections). Uncomment to allow #any connection. #org.neo4j.server.webserver.address=0.0.0.0
You can also restrict access to the database from only the machines(s) on which the application resides. So, only requests from this machine will be serviced. You can also provide open access (a security nightmare) by changing the incoming address to 0.0.0.0
. The following setting is used for this:
org.neo4j.server.webserver.address=0.0.0.0
There is built-in support for encrypted communication with SSL over HTTPS in a Neo4j server installation. A private key and a self-signed SSL certificate is generated when the server is initiated. In production scenarios, self-signed certificates are not reliable. Hence, you can configure your own certificates and keys. You can either replace the generated key and certificate with your own, or modify the conf/neo4j-server.properties
file to change the location of the key and certificates:
# Certificate location (auto generated if the file does not exist) org.neo4j.server.webserver.https.cert.location=ssl/myapp.cert # Private key location (auto generated if the file does not exist) org.neo4j.server.webserver.https.key.location=ssl/myapp.key
You need to ensure that the key is encrypted and has the appropriate file permissions to enable read/write access for the server. There is also support for chained SSL certificates, where the certificates need to be merged in a single PEM file with the private key assuming the DER format. The option to enable/disable HTTPS support and define the port can be configured with these options:
# Support toggle for https: on/off org.neo4j.server.webserver.https.enabled=true # Port for https (for all data, administrative, and UI access) org.neo4j.server.webserver.https.port=443
Apart from restrictions at the IP level, more detailed security policies may be required for administrators. The authorization policies for the Neo4j server controls access to database aspects on the basis of user or application credentials. The security rules must first be registered with the server, making scenarios for external lookup and authentication on the basis of role possible. The detailed configuration for this is managed in the org.neo4j.server.rest.security.SecurityRule
package.
Let us look at a scenario in which a security rule for failure is being registered for restriction of access to all the external URIs. This can be configured in the conf/neo4j-server.properties
file:
org.neo4j.server.rest.security_rules=rule.CompleteRestrictionSecurityRule
The code for the CompleteRestrictionSecurityRule
class can be defined in the following manner:
publicclassCompleteRestrictionSecurityRuleimplementsSecurityRule { publicstaticfinalStringMYREALM="MyApplication"; @Override publicbooleanisAuthorized( HttpServletRequestrequest ) { returnfalse; // Forces failure always // Logic for authorization coded here } @Override publicStringforUriPath() { return"/*"; //For any incoming URI path } @Override publicStringwwwAuthenticateHeader() { returnSecurityFilter.basicAuthenticationResponse(MYREALM); } }
This rule restricts all types of access to the server from external locations. For a production scenario, you can configure the rule class to check for login credentials in order to authorize users to the application.
Sample request
POST http://localhost:7474/db/data/relationship/1 Accept:application/json; charset=UTF-8
Sample response
401:Unauthorized WWW-Authenticate:Basic realm="MyApplication"
Unlike the previous case, where all incoming requests are blocked, we can also target the restriction to some specific type of URIs with the use of wildcards. We need to register for this with a predefined wildcard URI path, with *
specifying any section of the path. For example, /users*
will block those requests that access the user root. In a similar fashion, the /users*type*
expression refers to URIs accessing the type option for users like /users/mark/type/new
.
You can use the defined CompleteRestrictionSecurityRule
security rule class with a modification to the forUriPath
method as follows:
publicStringforUriPath() { return"/secure/*"; }
This rule restricts only those requests that attempt to access the data under the /secure/
directory. So, with wildcards, you can flexibly control access to different parts of the server API.
Sample request
GET http://localhost:7474/secure/any/path/after/this/stuff Accept:application/json; charset=UTF-8
Sample response
401:Unauthorized WWW-Authenticate:Basic realm="MyApplication"
You can use multiple or a chain of wildcards in order to restrict a specific URI type or a pattern of URIs. Consider the case when the forUriPath()
method is changed to take this form:
publicStringforUriPath() { return"/protected/*/something/else/*/final/bit"; }
The type of requests that this blocks are very specific and targeted in nature. An example of the type of request restricted is as follows:
Sample request
GET http://localhost:7474/protected/any/x/y/z/path/something/else/any/subpath/final/bit/anything Accept:application/json; charset=UTF-8
Example response
401:Unauthorized WWW-Authenticate:Basic realm="MyApplication"
As a default behavior, the Neo4j server allows functionality for remote scripting, thereby allowing complete access to the underlying database instance from anywhere. This is better for development purposes. However, in production stages, allowing remote scripting is a potential high security risk, and you need to impose a sound security layer.
Apart from the numerous security configurations discussed, for critical deployments it is wise to use an additional proxy similar to Apache's mod_proxy
(http://httpd.apache.org/docs/2.2/mod/mod_proxy.html). This can provide access control to specific IPs, a range of IPs and even URI patterns. So you can essentially allow /db/data
available to external clients while /db/admin/
can be made accessible from a specific IP. The configuration would look something like this:
<Proxy *> Order Deny,Allow Deny from all Allow from 192.168.0 </Proxy>
The proxy server gives the same functionality as Neo4j's default SecurityRule feature and you can also use both together with proper non-conflicting configurations. However, admins often prefer Apache to the default Neo4j feature.