You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2015/07/17 22:38:28 UTC

[1/2] incubator-tinkerpop git commit: Write up docs for the Credentials DSL.

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/auth b9e2d43fa -> 221c7721b


Write up docs for the Credentials DSL.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/10792dcd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/10792dcd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/10792dcd

Branch: refs/heads/auth
Commit: 10792dcdc7280cc81a8c0462761e10e02e2a56e1
Parents: b9e2d43
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Jul 17 16:35:52 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Jul 17 16:35:52 2015 -0400

----------------------------------------------------------------------
 docs/preprocessor/install-plugins.groovy |  1 +
 docs/src/gremlin-applications.asciidoc   | 33 +++++++++++++++++++++++----
 2 files changed, 30 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/10792dcd/docs/preprocessor/install-plugins.groovy
----------------------------------------------------------------------
diff --git a/docs/preprocessor/install-plugins.groovy b/docs/preprocessor/install-plugins.groovy
index 4a583fa..1935072 100644
--- a/docs/preprocessor/install-plugins.groovy
+++ b/docs/preprocessor/install-plugins.groovy
@@ -40,4 +40,5 @@ installPlugin = { def artifact ->
 }
 
 :plugin use tinkerpop.sugar
+:plugin use tinkerpop.credentials
 System.err.println("done")

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/10792dcd/docs/src/gremlin-applications.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/gremlin-applications.asciidoc b/docs/src/gremlin-applications.asciidoc
index 1ec1906..0731dca 100644
--- a/docs/src/gremlin-applications.asciidoc
+++ b/docs/src/gremlin-applications.asciidoc
@@ -540,10 +540,6 @@ authentication: {
   config: {
     credentialsDb: conf/credential-graph.properties}}
 
-The "credential graph" schema is quite simple and it is up to the user to be sure that the graph given to `credentialsDb` matches that schema for the authentication process to work. The credentials graph stores users as vertices with the `label` of "user".  Each "user" vertex has two properties: `username` and `password`.  Naturally, these are both `String` values.
-
-IMPORTANT: Be sure to define an index on the `username` property, as this will be used for lookups.  If supported by the `Graph`, consider specifying a unique constraint as well.
-
 Quick Start
 +++++++++++
 
@@ -584,6 +580,35 @@ Cluster cluster = Cluster.build().credentials("stephen", "password")
 
 If connecting with Gremlin Console, which utilizes `gremlin-driver` for remote script execution, use the provided `config/remote-secure.yaml` file when defining the remote.  That file contains configuration for the username and password as well as enablement of SSL from the client side.
 
+Credentials Graph DSL
++++++++++++++++++++++
+
+The "credentials graph", which has been mentioned in previous sections, is used by Gremlin Server to hold the list of users who can authenticate to the server.  It is possible to use virtually any `Graph` instance for this task as long as it complies to a defined schema. The credentials graph stores users as vertices with the `label` of "user".  Each "user" vertex has two properties: `username` and `password`.  Naturally, these are both `String` values.  The password must not be stored in plain text and should be hashed.
+
+IMPORTANT: Be sure to define an index on the `username` property, as this will be used for lookups.  If supported by the `Graph`, consider specifying a unique constraint as well.
+
+To aid with the management of a credentials graph, Gremlin Server provides a Gremlin Console plugin which can be used to add and remove users so as to ensure that the schema is adhered to, thus ensuring compatibility with Gremlin Server.  In addition, as it is a plugin, it works naturally in the Gremlin Console as an extension of its capabilities (though one could use it programmatically, if desired).  This plugin is distributed with the Gremlin Console so it does not have to be "installed".  It does however need to be activated:
+
+[source,groovy]
+gremlin> :plugin use tinkerpop.credentials
+==>tinkerpop.credentials activated
+
+Please see the example usage as follows:
+
+[gremlin-groovy]
+----
+graph = TinkerGraph.open()
+graph.createIndex("username",Vertex.class)
+credentials = credentials(graph)
+credentials.createUser("stephen","password")
+credentials.createUser("daniel","better-password")
+credentials.createUser("marko","rainbow-dash")
+credentials.findUser("marko").properties()
+credentials.countUsers()
+credentials.removeUser("daniel")
+credentials.countUsers()
+----
+
 Serialization
 ^^^^^^^^^^^^^
 


[2/2] incubator-tinkerpop git commit: Move the Credentials DSL to gremlin-groovy.

Posted by sp...@apache.org.
Move the Credentials DSL to gremlin-groovy.

In this way, the DSL does not need to be "installed" in the console.  If it had stayed on the server the user would have had to ":install gremlin-server" which is kinda weird (especially for just one little class).  Perhaps this is the way to go for future DSLs that we might want to support - kinda fits here in a way. Plus there is the added bonus that the DSL undergoes testing in the GroovyEnvironmentSuite which means it gets validated against all the graphs out there that run that suite.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/221c7721
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/221c7721
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/221c7721

Branch: refs/heads/auth
Commit: 221c7721b9e58f7995bd7953c0f6013e46a6958d
Parents: 10792dc
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Jul 17 16:36:21 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Jul 17 16:36:21 2015 -0400

----------------------------------------------------------------------
 .../gremlin/groovy/GroovyEnvironmentSuite.java  |   2 +
 .../dsl/credential/CredentialGraphTest.java     | 110 ++++++++++++++++
 gremlin-groovy/pom.xml                          |   5 +
 .../plugin/dsl/credential/CredentialGraph.java  | 120 ++++++++++++++++++
 .../CredentialGraphGremlinPlugin.java           |  53 ++++++++
 .../dsl/credential/CredentialGraphTokens.java   |  31 +++++
 ...inkerpop.gremlin.groovy.plugin.GremlinPlugin |   3 +-
 gremlin-server/pom.xml                          |   5 -
 .../server/auth/SimpleAuthenticator.java        |   6 +-
 .../auth/groovy/plugin/CredentialGraph.java     | 124 -------------------
 .../plugin/CredentialGraphGremlinPlugin.java    |  53 --------
 .../groovy/plugin/CredentialGraphTokens.java    |  31 -----
 ...inkerpop.gremlin.groovy.plugin.GremlinPlugin |   1 -
 .../auth/groovy/plugin/CredentialGraphTest.java | 117 -----------------
 14 files changed, 326 insertions(+), 335 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyEnvironmentSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyEnvironmentSuite.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyEnvironmentSuite.java
index 2fb9e8e..a32e170 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyEnvironmentSuite.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyEnvironmentSuite.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngineSandb
 import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngineTinkerPopSandboxTest;
 import org.apache.tinkerpop.gremlin.groovy.loaders.SugarLoader;
 import org.apache.tinkerpop.gremlin.groovy.loaders.SugarLoaderTest;
+import org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.CredentialGraphTest;
 import org.apache.tinkerpop.gremlin.groovy.util.SugarTestHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -52,6 +53,7 @@ public class GroovyEnvironmentSuite extends AbstractGremlinSuite {
      * as needed to enforce tests upon implementations.
      */
     private static final Class<?>[] allTests = new Class<?>[]{
+            CredentialGraphTest.class,
             GremlinGroovyScriptEngineOverGraphTest.class,
             GremlinGroovyScriptEngineSandboxCustomTest.class,
             GremlinGroovyScriptEngineSandboxedStandardTest.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTest.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTest.java
new file mode 100644
index 0000000..93feb4b
--- /dev/null
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential;
+
+import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.hamcrest.MatcherAssert;
+import org.junit.Test;
+
+import static org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.CredentialGraph.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class CredentialGraphTest extends AbstractGremlinTest {
+
+    @Test
+    public void shouldCreateUser() {
+        final Vertex v = credentials(graph).createUser("stephen", "secret");
+        assertEquals("stephen", v.value("username"));
+        assertEquals("user", v.label());
+        assertNotEquals("secret", v.value("password"));  // hashed to something
+        assertThat(v.value("password").toString().length(), greaterThan(0));
+    }
+
+    @Test
+    public void shouldRemoveUser() {
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(1, credentials(graph).removeUser("stephen"));
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+    }
+
+    @Test
+    public void shouldNotRemoveUser() {
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(0, credentials(graph).removeUser("stephanie"));
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+    }
+
+    @Test
+    public void shouldFindUser() {
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        final Vertex stephen = credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(stephen, credentials(graph).findUser("stephen"));
+    }
+
+    @Test
+    public void shouldNotFindUser() {
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertNull(credentials(graph).findUser("stephanie"));
+    }
+
+    @Test
+    public void shouldCountUsers() {
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(3, credentials(graph).countUsers());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void shouldThrowIfFindingMultipleUsers() {
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertNull(credentials(graph).findUser("stephen"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-groovy/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-groovy/pom.xml b/gremlin-groovy/pom.xml
index 7fe90d3..69b5e0c 100644
--- a/gremlin-groovy/pom.xml
+++ b/gremlin-groovy/pom.xml
@@ -66,6 +66,11 @@ limitations under the License.
             <version>3.3.1</version>
         </dependency>
         <dependency>
+            <groupId>org.mindrot</groupId>
+            <artifactId>jbcrypt</artifactId>
+            <version>0.3m</version>
+        </dependency>
+        <dependency>
             <groupId>org.apache.tinkerpop</groupId>
             <artifactId>gremlin-test</artifactId>
             <version>${project.version}</version>

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraph.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraph.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraph.java
new file mode 100644
index 0000000..a766f46
--- /dev/null
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraph.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.mindrot.jbcrypt.BCrypt;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.drop;
+
+/**
+ * A DSL for managing a "credentials graph" used by Gremlin Server for simple authentication functions.  If the
+ * {@link Graph} is transactional, new transactions will be started for each method call.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class CredentialGraph {
+
+    private final Graph graph;
+    private final GraphTraversalSource g;
+    private final boolean supportsTransactions;
+
+    public CredentialGraph(final Graph graph) {
+        this.graph = graph;
+        g = graph.traversal();
+        supportsTransactions = graph.features().graph().supportsTransactions();
+    }
+
+    /**
+     * Finds a user by username and return {@code null} if one could not be found.
+     *
+     * @throws IllegalStateException if there is more than one user with a particular username.
+     */
+    public Vertex findUser(final String username) {
+        if (supportsTransactions) g.tx().rollback();
+        final GraphTraversal<Vertex,Vertex> t = g.V().has(CredentialGraphTokens.PROPERTY_USERNAME, username);
+        final Vertex v = t.hasNext() ? t.next() : null;
+        if (t.hasNext()) throw new IllegalStateException(String.format("Multiple users with username %s", username));
+        return v;
+    }
+
+    /**
+     * Creates a new user.
+     *
+     * @return the newly created user vertex
+     */
+    public Vertex createUser(final String username, final String password) {
+        if (findUser(username) != null) throw new IllegalStateException("User with this name already exists");
+        if (supportsTransactions) graph.tx().rollback();
+
+        try {
+            final Vertex v =  graph.addVertex(T.label, CredentialGraphTokens.VERTEX_LABEL_USER,
+                                              CredentialGraphTokens.PROPERTY_USERNAME, username,
+                                              CredentialGraphTokens.PROPERTY_PASSWORD, BCrypt.hashpw(password, BCrypt.gensalt()));
+            if (supportsTransactions) graph.tx().commit();
+            return v;
+        } catch (Exception ex) {
+            if (supportsTransactions) graph.tx().rollback();
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
+     * Removes a user by name.
+     *
+     * @return the number of users removed (which should be one or zero)
+     */
+    public long removeUser(final String username) {
+        if (supportsTransactions) graph.tx().rollback();
+        try {
+            final long count = g.V().has(CredentialGraphTokens.PROPERTY_USERNAME, username).sideEffect(drop()).count().next();
+            if (supportsTransactions) graph.tx().commit();
+            return count;
+        } catch (Exception ex) {
+            if (supportsTransactions) graph.tx().rollback();
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
+     * Get a count of the number of users in the database.
+     */
+    public long countUsers() {
+        if (supportsTransactions) graph.tx().rollback();
+        return g.V().hasLabel(CredentialGraphTokens.VERTEX_LABEL_USER).count().next();
+    }
+
+    @Override
+    public String toString() {
+        return "CredentialGraph{" +
+                "graph=" + graph +
+                '}';
+    }
+
+    /**
+     * Wrap up any {@link Graph} instance in the {@code CredentialGraph} DSL.
+     */
+    public static CredentialGraph credentials(final Graph graph) {
+        return new CredentialGraph(graph);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphGremlinPlugin.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphGremlinPlugin.java
new file mode 100644
index 0000000..9bf7880
--- /dev/null
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphGremlinPlugin.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential;
+
+import org.apache.tinkerpop.gremlin.groovy.plugin.AbstractGremlinPlugin;
+import org.apache.tinkerpop.gremlin.groovy.plugin.IllegalEnvironmentException;
+import org.apache.tinkerpop.gremlin.groovy.plugin.PluginAcceptor;
+import org.apache.tinkerpop.gremlin.groovy.plugin.PluginInitializationException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class CredentialGraphGremlinPlugin extends AbstractGremlinPlugin {
+
+    private static final Set<String> IMPORTS = new HashSet<String>() {{
+        add(IMPORT_SPACE + CredentialGraph.class.getName());
+        add(IMPORT_STATIC_SPACE + CredentialGraph.class.getName() + DOT_STAR);
+    }};
+
+    @Override
+    public String getName() {
+        return "tinkerpop.credentials";
+    }
+
+    @Override
+    public void pluginTo(final PluginAcceptor pluginAcceptor) throws PluginInitializationException, IllegalEnvironmentException {
+        pluginAcceptor.addImports(IMPORTS);
+    }
+
+    @Override
+    public void afterPluginTo(final PluginAcceptor pluginAcceptor) throws IllegalEnvironmentException, PluginInitializationException {
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTokens.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTokens.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTokens.java
new file mode 100644
index 0000000..0cb2543
--- /dev/null
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/dsl/credential/CredentialGraphTokens.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class CredentialGraphTokens {
+    public static final String PROPERTY_USERNAME = "username";
+    public static final String PROPERTY_PASSWORD = "password";
+
+    public static final String VERTEX_LABEL_USER = "user";
+
+    private CredentialGraphTokens() {}
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-groovy/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin b/gremlin-groovy/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin
index 75f65ae..79f20cd 100644
--- a/gremlin-groovy/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin
+++ b/gremlin-groovy/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin
@@ -1 +1,2 @@
-org.apache.tinkerpop.gremlin.groovy.plugin.SugarGremlinPlugin
\ No newline at end of file
+org.apache.tinkerpop.gremlin.groovy.plugin.SugarGremlinPlugin
+org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.CredentialGraphGremlinPlugin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-server/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-server/pom.xml b/gremlin-server/pom.xml
index 3ea7d08..9a9a110 100644
--- a/gremlin-server/pom.xml
+++ b/gremlin-server/pom.xml
@@ -46,11 +46,6 @@ limitations under the License.
             <artifactId>commons-collections</artifactId>
             <version>3.2.1</version>
         </dependency>
-        <dependency>
-            <groupId>org.mindrot</groupId>
-            <artifactId>jbcrypt</artifactId>
-            <version>0.3m</version>
-        </dependency>
         <!-- METRICS -->
         <dependency>
             <groupId>com.codahale.metrics</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/SimpleAuthenticator.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/SimpleAuthenticator.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/SimpleAuthenticator.java
index 17da264..123e95b 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/SimpleAuthenticator.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/SimpleAuthenticator.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server.auth;
 
-import org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraph;
+import org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.CredentialGraph;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.IoCore;
@@ -33,8 +33,8 @@ import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Map;
 
-import static org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraphTokens.PROPERTY_PASSWORD;
-import static org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraphTokens.PROPERTY_USERNAME;
+import static org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.CredentialGraphTokens.PROPERTY_PASSWORD;
+import static org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.CredentialGraphTokens.PROPERTY_USERNAME;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraph.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraph.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraph.java
deleted file mode 100644
index d5d8b65..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraph.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.server.auth.groovy.plugin;
-
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import org.mindrot.jbcrypt.BCrypt;
-
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.drop;
-import static org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraphTokens.PROPERTY_PASSWORD;
-import static org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraphTokens.PROPERTY_USERNAME;
-import static org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraphTokens.VERTEX_LABEL_USER;
-
-/**
- * A DSL for managing a "credentials graph" used by Gremlin Server for simple authentication functions.  If the
- * {@link Graph} is transactional, new transactions will be started for each method call.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class CredentialGraph {
-
-    private final Graph graph;
-    private final GraphTraversalSource g;
-    private final boolean supportsTransactions;
-
-    public CredentialGraph(final Graph graph) {
-        this.graph = graph;
-        g = graph.traversal();
-        supportsTransactions = graph.features().graph().supportsTransactions();
-    }
-
-    /**
-     * Finds a user by username and return {@code null} if one could not be found.
-     *
-     * @throws IllegalStateException if there is more than one user with a particular username.
-     */
-    public Vertex findUser(final String username) {
-        if (supportsTransactions) g.tx().rollback();
-        final GraphTraversal<Vertex,Vertex> t = g.V().has(PROPERTY_USERNAME, username);
-        final Vertex v = t.hasNext() ? t.next() : null;
-        if (t.hasNext()) throw new IllegalStateException(String.format("Multiple users with username %s", username));
-        return v;
-    }
-
-    /**
-     * Creates a new user.
-     *
-     * @return the newly created user vertex
-     */
-    public Vertex createUser(final String username, final String password) {
-        if (findUser(username) != null) throw new IllegalStateException("User with this name already exists");
-        if (supportsTransactions) graph.tx().rollback();
-
-        try {
-            final Vertex v =  graph.addVertex(T.label, VERTEX_LABEL_USER,
-                                              PROPERTY_USERNAME, username,
-                                              PROPERTY_PASSWORD, BCrypt.hashpw(password, BCrypt.gensalt()));
-            if (supportsTransactions) graph.tx().commit();
-            return v;
-        } catch (Exception ex) {
-            if (supportsTransactions) graph.tx().rollback();
-            throw new RuntimeException(ex);
-        }
-    }
-
-    /**
-     * Removes a user by name.
-     *
-     * @return the number of users removed (which should be one or zero)
-     */
-    public long removeUser(final String username) {
-        if (supportsTransactions) graph.tx().rollback();
-        try {
-            final long count = g.V().has(PROPERTY_USERNAME, username).sideEffect(drop()).count().next();
-            if (supportsTransactions) graph.tx().commit();
-            return count;
-        } catch (Exception ex) {
-            if (supportsTransactions) graph.tx().rollback();
-            throw new RuntimeException(ex);
-        }
-    }
-
-    /**
-     * Get a count of the number of users in the database.
-     */
-    public long countUsers() {
-        if (supportsTransactions) graph.tx().rollback();
-        return g.V().hasLabel(VERTEX_LABEL_USER).count().next();
-    }
-
-    @Override
-    public String toString() {
-        return "CredentialGraph{" +
-                "graph=" + graph +
-                '}';
-    }
-
-    /**
-     * Wrap up any {@link Graph} instance in the {@code CredentialGraph} DSL.
-     */
-    public static CredentialGraph credentials(final Graph graph) {
-        return new CredentialGraph(graph);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphGremlinPlugin.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphGremlinPlugin.java
deleted file mode 100644
index 2d719f0..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphGremlinPlugin.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.server.auth.groovy.plugin;
-
-import org.apache.tinkerpop.gremlin.groovy.plugin.AbstractGremlinPlugin;
-import org.apache.tinkerpop.gremlin.groovy.plugin.IllegalEnvironmentException;
-import org.apache.tinkerpop.gremlin.groovy.plugin.PluginAcceptor;
-import org.apache.tinkerpop.gremlin.groovy.plugin.PluginInitializationException;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class CredentialGraphGremlinPlugin extends AbstractGremlinPlugin {
-
-    private static final Set<String> IMPORTS = new HashSet<String>() {{
-        add(IMPORT_SPACE + CredentialGraph.class.getName());
-        add(IMPORT_STATIC_SPACE + CredentialGraph.class.getName() + DOT_STAR);
-    }};
-
-    @Override
-    public String getName() {
-        return "tinkerpop.server.credentials";
-    }
-
-    @Override
-    public void pluginTo(final PluginAcceptor pluginAcceptor) throws PluginInitializationException, IllegalEnvironmentException {
-        pluginAcceptor.addImports(IMPORTS);
-    }
-
-    @Override
-    public void afterPluginTo(final PluginAcceptor pluginAcceptor) throws IllegalEnvironmentException, PluginInitializationException {
-
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTokens.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTokens.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTokens.java
deleted file mode 100644
index 4e3aa13..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTokens.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.server.auth.groovy.plugin;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public final class CredentialGraphTokens {
-    public static final String PROPERTY_USERNAME = "username";
-    public static final String PROPERTY_PASSWORD = "password";
-
-    public static final String VERTEX_LABEL_USER = "user";
-
-    private CredentialGraphTokens() {}
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-server/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin b/gremlin-server/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin
deleted file mode 100644
index 681bac1..0000000
--- a/gremlin-server/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraphGremlinPlugin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/221c7721/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTest.java
deleted file mode 100644
index e8d5b9c..0000000
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/auth/groovy/plugin/CredentialGraphTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.server.auth.groovy.plugin;
-
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.apache.tinkerpop.gremlin.server.auth.groovy.plugin.CredentialGraph.*;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class CredentialGraphTest {
-    private TinkerGraph graph;
-
-    @Before
-    public void setup() {
-        graph = TinkerGraph.open();
-        graph.createIndex("username", Vertex.class);
-    }
-
-    @Test
-    public void shouldCreateUser() {
-        final Vertex v = credentials(graph).createUser("stephen", "secret");
-        assertEquals("stephen", v.value("username"));
-        assertEquals("user", v.label());
-        assertNotEquals("secret", v.value("password"));  // hashed to something
-        assertThat(v.value("password").toString().length(), greaterThan(0));
-    }
-
-    @Test
-    public void shouldRemoveUser() {
-        assertThat(graph.vertices().hasNext(), is(false));
-        credentials(graph).createUser("stephen", "secret");
-        assertThat(graph.vertices().hasNext(), is(true));
-
-        assertEquals(1, credentials(graph).removeUser("stephen"));
-        assertThat(graph.vertices().hasNext(), is(false));
-    }
-
-    @Test
-    public void shouldNotRemoveUser() {
-        assertThat(graph.vertices().hasNext(), is(false));
-        credentials(graph).createUser("stephen", "secret");
-        assertThat(graph.vertices().hasNext(), is(true));
-
-        assertEquals(0, credentials(graph).removeUser("stephanie"));
-        assertThat(graph.vertices().hasNext(), is(true));
-    }
-
-    @Test
-    public void shouldFindUser() {
-        assertThat(graph.vertices().hasNext(), is(false));
-        credentials(graph).createUser("marko", "secret");
-        final Vertex stephen = credentials(graph).createUser("stephen", "secret");
-        credentials(graph).createUser("daniel", "secret");
-        assertThat(graph.vertices().hasNext(), is(true));
-
-        assertEquals(stephen, credentials(graph).findUser("stephen"));
-    }
-
-    @Test
-    public void shouldNotFindUser() {
-        assertThat(graph.vertices().hasNext(), is(false));
-        credentials(graph).createUser("marko", "secret");
-        credentials(graph).createUser("stephen", "secret");
-        credentials(graph).createUser("daniel", "secret");
-        assertThat(graph.vertices().hasNext(), is(true));
-
-        assertNull(credentials(graph).findUser("stephanie"));
-    }
-
-    @Test
-    public void shouldCountUsers() {
-        assertThat(graph.vertices().hasNext(), is(false));
-        credentials(graph).createUser("marko", "secret");
-        credentials(graph).createUser("stephen", "secret");
-        credentials(graph).createUser("daniel", "secret");
-        assertThat(graph.vertices().hasNext(), is(true));
-
-        assertEquals(3, credentials(graph).countUsers());
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void shouldThrowIfFindingMultipleUsers() {
-        assertThat(graph.vertices().hasNext(), is(false));
-        credentials(graph).createUser("stephen", "secret");
-        credentials(graph).createUser("stephen", "secret");
-        assertThat(graph.vertices().hasNext(), is(true));
-
-        assertNull(credentials(graph).findUser("stephen"));
-    }
-}