Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TINKERPOP-1566 Kerberos authentication for gremlin-server #534

Merged
merged 25 commits into from
Feb 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b3cb7e9
Kerberos authenticator files added
Nov 25, 2016
36713cf
Added failing test shouldAuthenticateWithSerializeResultToString
Nov 28, 2016
d2639a7
Fixed problem with non-lowercase hostname
Dec 3, 2016
2ead423
Added Kerberos tests for client
Dec 4, 2016
202d658
Added Krb5Authenticator to reference docs
Dec 11, 2016
4544b01
Made immutable variables final
Dec 11, 2016
14dd521
Refactored and cleaned directory-kerby usage
Dec 13, 2016
972b558
Verified and documented proper usage of sasl configuration properties
Dec 13, 2016
cb75d9b
Removed unnecessary test dependency
Dec 19, 2016
68eff1d
Added audit logging wih tests and docs
Dec 22, 2016
5c735d8
KdcFixture closing
Jan 8, 2017
c364643
Fixed issue for byte[] when using serializeResultToString
Jan 8, 2017
c849295
Changelog due to TINKERPOP-1566
Jan 10, 2017
6a9c667
Some cleanup
Jan 13, 2017
a5f3e1f
Improved code comments regarding authorization after Kerberos authent…
Jan 14, 2017
0ca1b16
Added audit log integrate test for two clients
Jan 15, 2017
d81f0d7
Adapted to TINKERPOP-1600 after rebase
Jan 18, 2017
3668557
Added Kerberos authentication test with ssl
Jan 18, 2017
6400128
Restored WARN for gremlin-server log4j.properties
Jan 20, 2017
b878318
Fixed failing gremlin-server authentication integration tests
Jan 20, 2017
0e299b0
Deleted unnecessary Kerberos config file
Jan 21, 2017
4e40df9
Restored gremlin-driver behavior regarding GSSAPI mechanism
Feb 2, 2017
1bbb0b2
Merge branch 'master' into TINKERPOP-1566
Feb 2, 2017
91e510c
Fixed use of socket address for audit logging
Feb 22, 2017
3c321ca
Merge branch 'TINKERPOP-1566' of https://github.com/vtslab/incubator-…
Feb 22, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
* Added SysV and systemd init scripts.
* `GraphTraversal.valueMap(includeTokens,propertyKeys...)` now returns a `Map<Object,E>` since keys could be `T.id` or `T.label`.
* Added `skip(long)` and `skip((Scope,long)` which call the `range(low,high)` equivalents with -1 as the high.
* Added Kerberos authentication to `gremlin-server` for websockets and nio transport.
* Added audit logging of authenticated users and gremlin queries to `gremlin-server`.

TinkerPop 3.2.0 (Nine Inch Gremlins)
------------------------------------
Expand Down
90 changes: 77 additions & 13 deletions docs/src/reference/gremlin-applications.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,7 @@ The following table describes the various YAML configuration options that Gremli
|=========================================================
|Key |Description |Default
|authentication.className |The fully qualified classname of an `Authenticator` implementation to use. If this setting is not present, then authentication is effectively disabled. |`AllowAllAuthenticator`
|authentication.enableAuditLog |The available authenticators can issue audit logging messages, binding the authenticated user to his remote socket address and binding requests with a gremlin query to the remote socket address. For privacy reasons, the default value of this setting is false. The audit logging messages are logged at the INFO level via the `audit.org.apache.tinkerpop.gremlin.server` logger, which can be configured using the log4j.properties file. |false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in alphabetical order?

Copy link
Contributor Author

@vtslab vtslab Feb 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answer to this riddle (required some thought on my part): also other config items, like scriptEngines.<name>.config, are at the bottom of their section. Just because it looks more orderly in the config file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that this one was not in alphabetical order and perhaps it should be.

|authentication.config |A `Map` of configuration settings to be passes to the `Authenticator` when it is constructed. The settings available are dependent on the implementation. |_none_
|channelizer |The fully qualified classname of the `Channelizer` implementation to use. A `Channelizer` is a "channel initializer" which Gremlin Server uses to define the type of processing pipeline to use. By allowing different `Channelizer` implementations, Gremlin Server can support different communication protocols (e.g. Websockets, Java NIO, etc.). |`WebSocketChannelizer`
|graphs |A `Map` of `Graph` configuration files where the key of the `Map` becomes the name to which the `Graph` will be bound and the value is the file name of a `Graph` configuration file. |_none_
Expand Down Expand Up @@ -1139,30 +1140,51 @@ The `TraversalOpProcessor` provides a way to use <<connecting-via-remotegraph,Re
|cacheMaxSize |The maximum number of entries in the side-effect cache. |1000
|=========================================================

Security and Execution
^^^^^^^^^^^^^^^^^^^^^^
Security
^^^^^^^^

image:gremlin-server-secure.png[width=175,float=right] Gremlin Server provides for several features that aid in the
security of the graphs that it exposes. It has built in SSL support and a pluggable authentication framework using
security of the graphs that it exposes. In particular it supports SSL for transport layer security, protective measures against
malicious script execution, and authentication. SSL options are described in the configuration settings table in the
<<connecting-via-java, "Connecting via Java">> section. Script execution options are covered
<<script-execution, "at the end of this section">>. This section starts with authentication.


Gremlin Server supports a pluggable authentication framework using
link:https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer[SASL] (Simple Authentication and
Security Layer). SSL options are described in the configuration settings table above, so this section will focus on
authentication.
Security Layer). Depending on the client used to connect to Gremlin Server, different authentication
mechanisms are accessible, see the table below.

[width="70%",cols="3,5,3",options="header"]
|=========================================================
|Client |Authentication mechanism |Availability
|HTTP |BASIC |3.0.0-incubating
1.3+v|Gremlin-Java/
Gremlin-Console |PLAIN SASL (username/password) |3.0.0-incubating
|Pluggable SASL |3.0.0-incubating
|GSSAPI SASL (Kerberos) |3.3.0
|Gremlin-Python |PLAIN SASL |3.2.2
|Gremlin-Javascript |PLAIN SASL |3.3.0
|=========================================================

By default, Gremlin Server is configured to allow all requests to be processed (i.e. no authentication). To enable
authentication, Gremlin Server must be configured with an `Authenticator` implementation in its YAML file. Gremlin
Server comes packaged with an implementation called `SimpleAuthenticator`. The `SimpleAuthenticator` implements the
`PLAIN` SASL mechanism (i.e. plain text) to authenticate a request. It validates username/password pairs against a
graph database, which must be provided to it as part of the configuration.
Server comes packaged with two implementations called `SimpleAuthenticator` for plain text authentication using HTTP BASIC or
PLAIN SASL and `Krb5Authenticator` for Kerberos authentication using GSSAPI SASL.

Plain text authentication
+++++++++++++++++++++++++

The `SimpleAuthenticator` implements the "PLAIN" SASL mechanism (i.e. plain text) to authenticate a request. It also
supports handling basic authentication requests from http clients. It validates
username/password pairs against a graph database, which must be provided to it as part of the configuration.

[source,yaml]
authentication: {
className: org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator,
config: {
credentialsDb: conf/tinkergraph-credentials.properties}}

Quick Start
+++++++++++

A quick way to get started with the `SimpleAuthenticator` is to use TinkerGraph for the "credentials graph" and the
"sample" credential graph that is packaged with the server.

Expand Down Expand Up @@ -1260,9 +1282,51 @@ credentials.removeUser("daniel")
credentials.countUsers()
----

[[krb5authenticator]]
Kerberos Authentication
+++++++++++++++++++++++

The `Krb5Authenticator` implements the "GSSAPI" SASL mechanism (i.e. Kerberos) to authenticate a request from a Gremlin
client. It can be applied in an existing Kerberos environment and validates whether a
link:https://http://www.roguelynn.com/words/explain-like-im-5-kerberos/[valid authentication proof and service ticket are
offered].

[source,yaml]
authentication: {
className: org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator,
config: {
principal: gremlinserver/hostname.your.org@YOUR.REALM,
keytab: /etc/security/keytabs/gremlinserver.service.keytab}}

Krb5Authenticator needs a Kerberos service principal and a keytab that holds the secret key for that principal. The keytab
location and service name, e.g. gremlinserver, are free to be chosen, but Gremlin clients have to specify this service name
as the `protocol`. For Gremlin-Console the `protocol` is an entry in the remote.yaml file, for Gremlin-java the client builder
has a `protocol()` method.

In addition to the `protocol`, the Gremlin client needs to specify a `jaasEntry`, an entry in the
link:https://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service[JAAS] configuration file. Gremlin-Console
comes with a sample gremlin-jaas.conf file with a `GremlinConsole` jaasEntry:

[source, jaas]
GremlinConsole {
com.sun.security.auth.module.Krb5LoginModule required
doNotPrompt=true
useTicketCache=true;
};

This configuration tells Gremlin-Console to pass authentication requests from gremlin-server to the Krb5LoginModule, which is
part of the java standard library. The Krb5LoginModule does not prompt the user for a username and password but uses the ticket cache that
is normally refreshed when a user logs in to a host within the Kerberos realm.

Finally, the Gremlin client needs the location of the JAAS configuration file to be passed as a system property to the JVM. For
Gremlin-Console the easiest way to do this is to pass it to the run script via the JAVA_OPTIONS environment property:

[source, bash]
export JAVA_OPTIONS="$JAVA_OPTIONS -Djava.security.auth.login.config=conf/gremlin-jaas.conf"

[[script-execution]]
Script Execution
++++++++++++++++
Protecting Script Execution
+++++++++++++++++++++++++++

It is important to remember that Gremlin Server exposes a `ScriptEngine` instance that allows for remote execution
of arbitrary code on the server. Obviously, this situation can represent a security risk or, more minimally, provide
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ private String getHostName(final ChannelHandlerContext channelHandlerContext) {
/**
* Work out the Sasl mechanism based on the user supplied parameters.
* If we have a username and password use PLAIN otherwise GSSAPI
* ToDo: have gremlin-server provide the mechanism(s) it is configured with, so that additional mechanisms can
* be supported in the driver and confusing GSSException messages from the driver are avoided
*/
private String getMechanism() {
if ((authProps.get(AuthProperties.Property.USERNAME) != null) &&
Expand Down
6 changes: 6 additions & 0 deletions gremlin-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ limitations under the License.
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.kerby</groupId>
<artifactId>kerb-simplekdc</artifactId>
<version>1.0.0-RC2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<directory>${basedir}/target</directory>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class GremlinServer {
}

private static final String SERVER_THREAD_PREFIX = "gremlin-server-";
public static final String AUDIT_LOGGER_NAME = "audit.org.apache.tinkerpop.gremlin.server";

private static final Logger logger = LoggerFactory.getLogger(GremlinServer.class);
private final Settings settings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ public static class AuthenticationSettings {
*/
public String className = AllowAllAuthenticator.class.getName();

/**
* Enable audit logging of authenticated users and gremlin evaluation requests.
*/
public boolean enableAuditLog = false;

/**
* A {@link Map} containing {@link Authenticator} specific configurations. Consult the
* {@link Authenticator} implementation for specifics on what configurations are expected.
Expand Down
Loading