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 2017/01/18 11:36:38 UTC

[24/24] tinkerpop git commit: TINKERPOP-1600 Added base64 encoded string to sasl challenge

TINKERPOP-1600 Added base64 encoded string to sasl challenge


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

Branch: refs/heads/TINKERPOP-1600
Commit: 866e96efac994976e2c222f817b38c3d1abadc5b
Parents: 802ff9f
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Jan 16 15:22:07 2017 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jan 18 06:35:51 2017 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                  |  2 +-
 docs/src/dev/io/graphson.asciidoc                   |  5 ++---
 docs/src/upgrade/release-3.2.x-incubating.asciidoc  | 16 ++++++++++++++++
 .../apache/tinkerpop/gremlin/driver/Handler.java    | 15 +++++++++++++--
 .../server/handler/SaslAuthenticationHandler.java   | 14 ++++++++++++--
 5 files changed, 44 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/866e96ef/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 9471b9f..4f3f9ce 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* SASL negotiation supports both a byte array and Base64 encoded bytes as a string for authentication to Gremlin Server.
 * Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`.
 * Made error messaging more consistent during result iteration timeouts in Gremlin Server.
 * `PathRetractionStrategy` does not add a `NoOpBarrierStep` to the end of local children as its wasted computation in 99% of traversals.
@@ -580,7 +581,6 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.1.6 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* Bumped to Groovy 2.4.8.
 * Fixed bug in `IncidentToAdjacentStrategy`, it was missing some invalidating steps.
 * Returned a confirmation on session close from Gremlin Server.
 * Use non-default port for running tests on Gremlin Server.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/866e96ef/docs/src/dev/io/graphson.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/dev/io/graphson.asciidoc b/docs/src/dev/io/graphson.asciidoc
index cdc9880..fe56c27 100644
--- a/docs/src/dev/io/graphson.asciidoc
+++ b/docs/src/dev/io/graphson.asciidoc
@@ -1299,7 +1299,7 @@ ResponseMessage
 Authentication Challenge
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but no in the default provided by Gremlin Server).
+When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but not in the default provided by Gremlin Server).
 
 [source,json]
 ----
@@ -4262,14 +4262,13 @@ The following `RequestMessage` is an example of a sessionless request for a scri
 }
 ----
 
-
 ResponseMessage
 ~~~~~~~~~~~~~~~
 
 Authentication Challenge
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but no in the default provided by Gremlin Server).
+When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but not in the default provided by Gremlin Server).
 
 [source,json]
 ----

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/866e96ef/docs/src/upgrade/release-3.2.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.2.x-incubating.asciidoc b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
index 8d73baed..b478b96 100644
--- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
@@ -240,6 +240,22 @@ and defaults to `false`.
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-932[TINKERPOP-932],
 link:http://tinkerpop.apache.org/docs/current/dev/provider/#_session_opprocessor[Provider Documentation - Session OpProcessor]
 
+SASL Authentication
++++++++++++++++++++
+
+Gremlin Supports SASL based authentication. The server accepts either a byte array or Base64 encoded String as the in
+the `sasl` argument on the `RequestMessage`, however it sends back a byte array only. Some serializers or serializer
+configurations don't work well with that approach (specifically the "toString" configuration on the Gryo serializer) as
+the byte array is returned in the `ResponseMessage` result. In the case of the "toString" serializer the byte array
+gets "toString'd" and the can't be read by the client.
+
+In 3.2.4, the byte array is still returned in the `ResponseMessage` result, but is also returned in the status
+attributes under a `sasl` key as a Base64 encoded string. In this way, the client has options on how it chooses to
+process the authentication response and the change remains backward compatible. Drivers should upgrade to using the
+Base64 encoded string however as the old approach will likely be removed in the future.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1600[TINKERPOP-1600]
+
 TinkerPop 3.2.3
 ---------------
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/866e96ef/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
index 681354c..650bc2f 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
 import java.net.InetSocketAddress;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
+import java.util.Base64;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -70,6 +71,9 @@ final class Handler {
         private static final Map<String, String> SASL_PROPERTIES = new HashMap<String, String>() {{ put(Sasl.SERVER_AUTH, "true"); }};
         private static final byte[] NULL_CHALLENGE = new byte[0];
 
+        private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();
+        private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder();
+
         private final AuthProperties authProps;
 
         public GremlinSaslAuthenticationHandler(final AuthProperties authProps) {
@@ -103,9 +107,16 @@ final class Handler {
 
                     messageBuilder.addArg(Tokens.ARGS_SASL_MECHANISM, getMechanism());
                     messageBuilder.addArg(Tokens.ARGS_SASL, saslClient.get().hasInitialResponse() ?
-                                                                evaluateChallenge(subject, saslClient, NULL_CHALLENGE) : null);
+                            BASE64_ENCODER.encodeToString(evaluateChallenge(subject, saslClient, NULL_CHALLENGE)) : null);
                 } else {
-                    messageBuilder.addArg(Tokens.ARGS_SASL, evaluateChallenge(subject, saslClient, (byte[])response.getResult().getData()));
+                    // the server sends base64 encoded sasl as well as the byte array. the byte array will eventually be
+                    // phased out, but is present now for backward compatibility in 3.2.x
+                    final String base64sasl = response.getStatus().getAttributes().containsKey(Tokens.ARGS_SASL) ?
+                        response.getStatus().getAttributes().get(Tokens.ARGS_SASL).toString() :
+                        BASE64_ENCODER.encodeToString((byte[]) response.getResult().getData());
+
+                    messageBuilder.addArg(Tokens.ARGS_SASL, BASE64_ENCODER.encodeToString(
+                        evaluateChallenge(subject, saslClient, BASE64_DECODER.decode(base64sasl))));
                 }
                 channelHandlerContext.writeAndFlush(messageBuilder.create());
             } else {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/866e96ef/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
index 4bb7879..2d7edf0 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
@@ -28,6 +28,9 @@ import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.tinkerpop.gremlin.driver.Tokens;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
@@ -50,6 +53,8 @@ import org.slf4j.LoggerFactory;
 @ChannelHandler.Sharable
 public class SaslAuthenticationHandler extends ChannelInboundHandlerAdapter {
     private static final Logger logger = LoggerFactory.getLogger(SaslAuthenticationHandler.class);
+    private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder();
+    private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();
 
     private final Authenticator authenticator;
 
@@ -80,7 +85,7 @@ public class SaslAuthenticationHandler extends ChannelInboundHandlerAdapter {
                     if (saslObject instanceof byte[]) {
                         saslResponse = (byte[]) saslObject;
                     } else if(saslObject instanceof String) {
-                        saslResponse = Base64.getDecoder().decode((String) saslObject);
+                        saslResponse = BASE64_DECODER.decode((String) saslObject);
                     } else {
                         final ResponseMessage error = ResponseMessage.build(request.get())
                                 .statusMessage("Incorrect type for : " + Tokens.ARGS_SASL + " - byte[] or base64 encoded String is expected")
@@ -101,8 +106,13 @@ public class SaslAuthenticationHandler extends ChannelInboundHandlerAdapter {
                             final RequestMessage original = request.get();
                             ctx.fireChannelRead(original);
                         } else {
-                            // not done here - send back the sasl message for next challenge
+                            // not done here - send back the sasl message for next challenge. note that we send back
+                            // the base64 encoded sasl as well as the byte array. the byte array will eventually be
+                            // phased out, but is present now for backward compatibility in 3.2.x
+                            final Map<String,Object> metadata = new HashMap<>();
+                            metadata.put(Tokens.ARGS_SASL, BASE64_ENCODER.encode(saslMessage));
                             final ResponseMessage authenticate = ResponseMessage.build(requestMessage)
+                                    .statusAttributes(metadata)
                                     .code(ResponseStatusCode.AUTHENTICATE).result(saslMessage).create();
                             ctx.writeAndFlush(authenticate);
                         }