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/02/27 12:49:06 UTC
[03/50] [abbrv] tinkerpop git commit: Added audit logging wih tests
and docs
Added audit logging wih tests and docs
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/68eff1db
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/68eff1db
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/68eff1db
Branch: refs/heads/TINKERPOP-1612
Commit: 68eff1dbdcca69fe74ba968ff6d30c5db0feeec3
Parents: cb75d9b
Author: HadoopMarc <vt...@xs4all.nl>
Authored: Thu Dec 22 20:33:40 2016 +0100
Committer: HadoopMarc <vt...@xs4all.nl>
Committed: Wed Jan 18 20:05:40 2017 +0100
----------------------------------------------------------------------
.../src/reference/gremlin-applications.asciidoc | 1 +
.../tinkerpop/gremlin/server/GremlinServer.java | 1 +
.../tinkerpop/gremlin/server/Settings.java | 5 +
.../gremlin/server/channel/HttpChannelizer.java | 2 +-
.../gremlin/server/channel/NioChannelizer.java | 2 +-
.../server/channel/WebSocketChannelizer.java | 2 +-
.../handler/HttpBasicAuthenticationHandler.java | 19 +-
.../handler/HttpGremlinEndpointHandler.java | 5 +
.../handler/SaslAuthenticationHandler.java | 17 +-
.../server/op/AbstractEvalOpProcessor.java | 6 +
.../kerby/kerberos/kerb/server/KdcTestBase.java | 172 ----------
.../kerberos/kerb/server/LoginTestBase.java | 90 ------
.../kerberos/kerb/server/TestKdcServer.java | 61 ----
.../AbstractGremlinServerIntegrationTest.java | 1 +
.../tinkerpop/gremlin/server/AuditLogTest.java | 322 +++++++++++++++++++
.../tinkerpop/gremlin/server/AuthKrb5Test.java | 172 +++++-----
.../gremlin/server/AuthKrb5TestBase.java | 130 --------
.../tinkerpop/gremlin/server/KdcFixture.java | 152 +++++++++
.../gremlin/util/Log4jRecordingAppender.java | 20 +-
.../src/test/resources/log4j-test.properties | 2 +-
20 files changed, 634 insertions(+), 548 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 57f43e0..70e46e5 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -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
|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_
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GremlinServer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GremlinServer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GremlinServer.java
index ed0fd7c..703b7b1 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GremlinServer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GremlinServer.java
@@ -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;
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
index 97e2875..fc0560f 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
@@ -383,6 +383,11 @@ public class Settings {
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.
*/
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/HttpChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/HttpChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/HttpChannelizer.java
index 5c632e6..b509e2d 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/HttpChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/HttpChannelizer.java
@@ -68,7 +68,7 @@ public class HttpChannelizer extends AbstractChannelizer {
// not occur. It may not be a safe assumption that the handler
// is sharable so create a new handler each time.
authenticationHandler = authenticator.getClass() == AllowAllAuthenticator.class ?
- null : new HttpBasicAuthenticationHandler(authenticator);
+ null : new HttpBasicAuthenticationHandler(authenticator, settings.authentication);
if (authenticationHandler != null)
pipeline.addLast(PIPELINE_AUTHENTICATOR, authenticationHandler);
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
index d2ba520..4baad23 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
@@ -52,7 +52,7 @@ public class NioChannelizer extends AbstractChannelizer {
// configure authentication - null means don't bother to add authentication to the pipeline
if (authenticator != null)
authenticationHandler = authenticator.getClass() == AllowAllAuthenticator.class ?
- null : new SaslAuthenticationHandler(authenticator);
+ null : new SaslAuthenticationHandler(authenticator, settings.authentication);
gremlinResponseFrameEncoder = new GremlinResponseFrameEncoder();
nioGremlinResponseFrameEncoder = new NioGremlinResponseFrameEncoder();
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
index 2373819..ea59e8f 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
@@ -67,7 +67,7 @@ public class WebSocketChannelizer extends AbstractChannelizer {
// configure authentication - null means don't bother to add authentication to the pipeline
if (authenticator != null)
authenticationHandler = authenticator.getClass() == AllowAllAuthenticator.class ?
- null : new SaslAuthenticationHandler(authenticator);
+ null : new SaslAuthenticationHandler(authenticator, settings.authentication);
}
@Override
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthenticationHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthenticationHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthenticationHandler.java
index bf3b674..1beb7cf 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthenticationHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthenticationHandler.java
@@ -24,8 +24,13 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpMessage;
import io.netty.util.ReferenceCountUtil;
+import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.Settings;
+import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticationException;
import org.apache.tinkerpop.gremlin.server.auth.Authenticator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.nio.charset.Charset;
import java.util.Base64;
@@ -43,12 +48,17 @@ import static org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.Credenti
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public class HttpBasicAuthenticationHandler extends ChannelInboundHandlerAdapter {
+ private static final Logger logger = LoggerFactory.getLogger(HttpBasicAuthenticationHandler.class);
+ private static final Logger auditLogger = LoggerFactory.getLogger(GremlinServer.AUDIT_LOGGER_NAME);
private final Authenticator authenticator;
+ private final Settings.AuthenticationSettings authenticationSettings;
private final Base64.Decoder decoder = Base64.getUrlDecoder();
- public HttpBasicAuthenticationHandler(final Authenticator authenticator) {
+ public HttpBasicAuthenticationHandler(final Authenticator authenticator,
+ final Settings.AuthenticationSettings authenticationSettings) {
this.authenticator = authenticator;
+ this.authenticationSettings = authenticationSettings;
}
@Override
@@ -92,6 +102,13 @@ public class HttpBasicAuthenticationHandler extends ChannelInboundHandlerAdapter
try {
authenticator.authenticate(credentials);
ctx.fireChannelRead(request);
+
+ // User name logged with the remote socket address and authenticator classname for audit logging
+ if (authenticationSettings.enableAuditLog) {
+ String[] authClassParts = authenticator.getClass().toString().split("[.]");
+ auditLogger.info("User {} with address {} authenticated by {}", credentials.get(PROPERTY_USERNAME),
+ ctx.channel().remoteAddress().toString().substring(1), authClassParts[authClassParts.length - 1]);
+ }
} catch (AuthenticationException ae) {
sendError(ctx, msg);
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
index ad11834..2afe4b5 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
@@ -100,6 +100,7 @@ import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
@ChannelHandler.Sharable
public class HttpGremlinEndpointHandler extends ChannelInboundHandlerAdapter {
private static final Logger logger = LoggerFactory.getLogger(HttpGremlinEndpointHandler.class);
+ private static final Logger auditLogger = LoggerFactory.getLogger(GremlinServer.AUDIT_LOGGER_NAME);
private static final Charset UTF8 = Charset.forName("UTF-8");
static final Meter errorMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "errors"));
@@ -188,6 +189,10 @@ public class HttpGremlinEndpointHandler extends ChannelInboundHandlerAdapter {
try {
logger.debug("Processing request containing script [{}] and bindings of [{}] on {}",
requestArguments.getValue0(), requestArguments.getValue1(), Thread.currentThread().getName());
+ if (settings.authentication.enableAuditLog) {
+ final String address = ctx.channel().remoteAddress().toString().substring(1);
+ auditLogger.info("User with address {} requested: {}", address, requestArguments.getValue0());
+ }
final ChannelPromise promise = ctx.channel().newPromise();
final AtomicReference<Object> resultHolder = new AtomicReference<>();
promise.addListener(future -> {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/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 6cb0ddb..0878246 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
@@ -35,6 +35,8 @@ import org.apache.tinkerpop.gremlin.driver.Tokens;
import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.Settings;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticationException;
import org.apache.tinkerpop.gremlin.server.auth.Authenticator;
@@ -55,11 +57,14 @@ 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 static final Logger auditLogger = LoggerFactory.getLogger(GremlinServer.AUDIT_LOGGER_NAME);
private final Authenticator authenticator;
+ private final Settings.AuthenticationSettings authenticationSettings;
- public SaslAuthenticationHandler(final Authenticator authenticator) {
+ public SaslAuthenticationHandler(final Authenticator authenticator, final Settings.AuthenticationSettings authenticationSettings) {
this.authenticator = authenticator;
+ this.authenticationSettings = authenticationSettings;
}
@Override
@@ -93,13 +98,17 @@ public class SaslAuthenticationHandler extends ChannelInboundHandlerAdapter {
ctx.writeAndFlush(error);
return;
}
-
+
try {
final byte[] saslMessage = negotiator.get().evaluateResponse(saslResponse);
if (negotiator.get().isComplete()) {
- // todo: do something with this user
final AuthenticatedUser user = negotiator.get().getAuthenticatedUser();
-
+ // User name logged with the remote socket address and authenticator classname for audit logging
+ if (authenticationSettings.enableAuditLog) {
+ String[] authClassParts = authenticator.getClass().toString().split("[.]");
+ auditLogger.info("User {} with address {} authenticated by {}", user.getName(),
+ ctx.channel().remoteAddress().toString().substring(1), authClassParts[authClassParts.length - 1]);
+ }
// If we have got here we are authenticated so remove the handler and pass
// the original message down the pipeline for processing
ctx.pipeline().remove(this);
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index 48de830..baff5b7 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -46,6 +46,7 @@ import org.slf4j.LoggerFactory;
import javax.script.Bindings;
import javax.script.SimpleBindings;
+import java.net.SocketAddress;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
@@ -67,6 +68,7 @@ import static com.codahale.metrics.MetricRegistry.name;
*/
public abstract class AbstractEvalOpProcessor extends AbstractOpProcessor {
private static final Logger logger = LoggerFactory.getLogger(AbstractEvalOpProcessor.class);
+ private static final Logger auditLogger = LoggerFactory.getLogger(GremlinServer.AUDIT_LOGGER_NAME);
public static final Timer evalOpTimer = MetricManager.INSTANCE.getTimer(name(GremlinServer.class, "op", "eval"));
/**
@@ -243,6 +245,10 @@ public abstract class AbstractEvalOpProcessor extends AbstractOpProcessor {
final Iterator itty = IteratorUtils.asIterator(o);
logger.debug("Preparing to iterate results from - {} - in thread [{}]", msg, Thread.currentThread().getName());
+ if (settings.authentication.enableAuditLog) {
+ final String address = context.getChannelHandlerContext().channel().remoteAddress().toString().substring(1);
+ auditLogger.info("User with address {} requested: {}", address, script);
+ }
try {
handleIterator(context, itty);
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java b/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
deleted file mode 100644
index 15663cb..0000000
--- a/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
+++ /dev/null
@@ -1,172 +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.kerby.kerberos.kerb.server;
-
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.client.KrbClient;
-import org.apache.kerby.kerberos.kerb.client.KrbPkinitClient;
-import org.apache.kerby.kerberos.kerb.client.KrbTokenClient;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-
-import java.io.File;
-import java.io.IOException;
-
-/*
- * This file is based on:
- * https://github.com/apache/directory-kerby/blob/kerby-all-1.0.0-RC2/
- * kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
- * but with the following changes:
- * - added this comment
- * - made allowUdp() return false because of issues with UDP in the RC2 release, see directory-kerby on JIRA
- *
- * See also: gremlin-server/src/main/static/NOTICE
- */
-public abstract class KdcTestBase {
- private static File testDir;
-
- private final String clientPassword = "123456";
- private final String hostname = "localhost";
- private final String clientPrincipalName = "drankye";
- private final String clientPrincipal =
- clientPrincipalName + "@" + TestKdcServer.KDC_REALM;
- private final String serverPrincipalName = "test-service";
- private final String serverPrincipal =
- serverPrincipalName + "/" + hostname + "@" + TestKdcServer.KDC_REALM;
-
- private SimpleKdcServer kdcServer;
-
- @BeforeClass
- public static void createTestDir() throws IOException {
- String basedir = System.getProperty("basedir");
- if (basedir == null) {
- basedir = new File(".").getCanonicalPath();
- }
- File targetdir = new File(basedir, "target");
- testDir = new File(targetdir, "tmp");
- testDir.mkdirs();
- }
-
- @AfterClass
- public static void deleteTestDir() throws IOException {
- testDir.delete();
- }
-
- protected File getTestDir() {
- return testDir;
- }
-
- protected SimpleKdcServer getKdcServer() {
- return kdcServer;
- }
-
- protected KrbClient getKrbClient() {
- return kdcServer.getKrbClient();
- }
-
- protected KrbPkinitClient getPkinitClient() {
- return kdcServer.getPkinitClient();
- }
-
- protected KrbTokenClient getTokenClient() {
- return kdcServer.getTokenClient();
- }
-
- protected String getClientPrincipalName() {
- return clientPrincipalName;
- }
-
- protected String getClientPrincipal() {
- return clientPrincipal;
- }
-
- protected String getServerPrincipalName() {
- return serverPrincipalName;
- }
-
- protected String getClientPassword() {
- return clientPassword;
- }
-
- protected String getServerPrincipal() {
- return serverPrincipal;
- }
-
- protected String getHostname() {
- return hostname;
- }
-
- protected boolean allowUdp() {
- return false;
- } // originally: true
-
- protected boolean allowTcp() {
- return true;
- }
-
- @Before
- public void setUp() throws Exception {
- setUpKdcServer();
-
- createPrincipals();
-
- setUpClient();
- }
-
- protected void prepareKdc() throws KrbException {
- kdcServer.init();
- }
-
- protected void configKdcSeverAndClient() {
- kdcServer.setWorkDir(testDir);
- }
-
- protected void setUpKdcServer() throws Exception {
- kdcServer = new TestKdcServer(allowTcp(), allowUdp());
-
- configKdcSeverAndClient();
-
- prepareKdc();
-
- kdcServer.start();
- }
-
- protected void setUpClient() throws Exception {
- }
-
- protected void createPrincipals() throws KrbException {
- kdcServer.createPrincipals(serverPrincipal);
- kdcServer.createPrincipal(clientPrincipal, clientPassword);
- }
-
- protected void deletePrincipals() throws KrbException {
- kdcServer.getKadmin().deleteBuiltinPrincipals();
- kdcServer.deletePrincipals(serverPrincipal);
- kdcServer.deletePrincipal(clientPrincipal);
- }
-
- @After
- public void tearDown() throws Exception {
- deletePrincipals();
- kdcServer.stop();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/LoginTestBase.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/LoginTestBase.java b/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/LoginTestBase.java
deleted file mode 100644
index ed805fa..0000000
--- a/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/LoginTestBase.java
+++ /dev/null
@@ -1,90 +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.kerby.kerberos.kerb.server;
-
-import org.apache.kerby.kerberos.kerb.client.JaasKrbUtil;
-import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-import java.io.File;
-import java.security.Principal;
-import java.util.Set;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import org.junit.After;
-import org.junit.Before;
-
-/*
- * Except for this comment and the removal of the org.assertj.core.api.Assertions.assertThat import statement,
- * this file is a literal copy from:
- * https://github.com/apache/directory-kerby/blob/kerby-all-1.0.0-RC2/
- * kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/LoginTestBase.java
- *
- * See also: gremlin-server/src/main/static/NOTICE
- */
-public class LoginTestBase extends KdcTestBase {
-
- protected File ticketCacheFile;
- protected File serviceKeytabFile;
-
- @Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
-
- ticketCacheFile = new File(getTestDir(), "test-tkt.cc");
- serviceKeytabFile = new File(getTestDir(), "test-service.keytab");
- }
-
- protected Subject loginClientUsingPassword() throws LoginException {
- return JaasKrbUtil.loginUsingPassword(getClientPrincipal(),
- getClientPassword());
- }
-
- protected Subject loginClientUsingTicketCache() throws Exception {
- TgtTicket tgt = getKrbClient().requestTgt(getClientPrincipal(),
- getClientPassword());
- getKrbClient().storeTicket(tgt, ticketCacheFile);
-
- return JaasKrbUtil.loginUsingTicketCache(getClientPrincipal(),
- ticketCacheFile);
- }
-
- protected Subject loginServiceUsingKeytab() throws Exception {
- getKdcServer().exportPrincipal(getServerPrincipal(), serviceKeytabFile);
- return JaasKrbUtil.loginUsingKeytab(getServerPrincipal(),
- serviceKeytabFile);
- }
-
- protected void checkSubject(Subject subject) {
- Set<Principal> clientPrincipals = subject.getPrincipals();
- assertThat("The subject has minimally one principal", clientPrincipals.size() > 0);
- }
-
- @After
- @Override
- public void tearDown() throws Exception {
- ticketCacheFile.delete();
- serviceKeytabFile.delete();
-
- super.tearDown();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcServer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcServer.java b/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcServer.java
deleted file mode 100644
index 3addc88..0000000
--- a/gremlin-server/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcServer.java
+++ /dev/null
@@ -1,61 +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.kerby.kerberos.kerb.server;
-
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.client.KrbClient;
-import org.apache.kerby.kerberos.kerb.client.KrbConfig;
-import org.apache.kerby.kerberos.kerb.client.KrbConfigKey;
-import org.apache.kerby.util.NetworkUtil;
-
-/*
- * Except for this comment, this file is a literal copy from:
- * https://github.com/apache/directory-kerby/blob/kerby-all-1.0.0-RC2/
- * kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/TestKdcServer.java
- *
- * See also: gremlin-server/src/main/static/NOTICE
- */
-public class TestKdcServer extends SimpleKdcServer {
- public static final String KDC_REALM = "TEST.COM";
- public static final String HOSTNAME = "localhost";
-
- public TestKdcServer(boolean allowTcp, boolean allowUdp) throws KrbException {
- super();
-
- setKdcRealm(KDC_REALM);
- setKdcHost(HOSTNAME);
- setAllowTcp(allowTcp);
- setAllowUdp(allowUdp);
-
- if (allowTcp) {
- setKdcTcpPort(NetworkUtil.getServerPort());
- }
- if (allowUdp) {
- setKdcUdpPort(NetworkUtil.getServerPort());
- }
-
- KrbClient krbClnt = getKrbClient();
- KrbConfig krbConfig = krbClnt.getKrbConfig();
- krbConfig.setString(KrbConfigKey.PERMITTED_ENCTYPES,
- "aes128-cts-hmac-sha1-96 des-cbc-crc des-cbc-md5 des3-cbc-sha1");
-
- krbClnt.setTimeout(10 * 1000);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java
index 12fadb6..56a599f 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AbstractGremlinServerIntegrationTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.server;
+import org.apache.tinkerpop.gremlin.util.Log4jRecordingAppender;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuditLogTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuditLogTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuditLogTest.java
new file mode 100644
index 0000000..d8337e8
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuditLogTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LoggingEvent;
+import static org.apache.log4j.Level.INFO;
+import org.apache.tinkerpop.gremlin.driver.Client;
+import org.apache.tinkerpop.gremlin.driver.Cluster;
+import org.apache.tinkerpop.gremlin.driver.Channelizer;
+import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
+import org.apache.tinkerpop.gremlin.server.channel.NioChannelizer;
+import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
+import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
+import org.apache.tinkerpop.gremlin.server.auth.AllowAllAuthenticator;
+import org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator;
+import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
+import static org.apache.tinkerpop.gremlin.server.AuthKrb5Test.TESTCONSOLE;
+import static org.apache.tinkerpop.gremlin.server.GremlinServer.AUDIT_LOGGER_NAME;
+import org.apache.tinkerpop.gremlin.util.Log4jRecordingAppender;
+import org.slf4j.LoggerFactory;
+
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * @author Marc de Lignie
+ *
+ * Note: like other descendents of AbstractGremlinServerIntegrationTest this testsuite assumes that tests are
+ * run sequentially and thus the server variable can be reused.
+ */
+public class AuditLogTest extends AbstractGremlinServerIntegrationTest {
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AuditLogTest.class);
+ private Log4jRecordingAppender recordingAppender = null;
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final Base64.Encoder encoder = Base64.getUrlEncoder();
+
+ private static final boolean AUDIT_LOG_ENABLED = true;
+ private static final boolean AUDIT_LOG_DISABLED = false;
+
+ private KdcFixture kdcServer;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ try {
+ final String buildDir = System.getProperty("build.dir");
+ kdcServer = new KdcFixture(buildDir +
+ "/test-classes/org/apache/tinkerpop/gremlin/server/gremlin-console-jaas.conf");
+ kdcServer.setUp();
+ } catch(Exception e) {
+ logger.warn(e.getMessage());
+ }
+ super.setUp();
+ }
+
+ @Before
+ public void setupForEachTest() {
+ recordingAppender = new Log4jRecordingAppender();
+ final Logger rootLogger = Logger.getRootLogger();
+ rootLogger.addAppender(recordingAppender);
+ }
+
+ @After
+ public void teardownForEachTest() {
+ final Logger rootLogger = Logger.getRootLogger();
+ rootLogger.removeAppender(recordingAppender);
+ }
+
+ /**
+ * Configure specific Gremlin Server settings for specific tests.
+ */
+ @Override
+ public Settings overrideSettings(final Settings settings) {
+ settings.host = kdcServer.hostname;
+ final Settings.SslSettings sslConfig = new Settings.SslSettings();
+ sslConfig.enabled = false;
+ settings.ssl = sslConfig;
+ final Settings.AuthenticationSettings authSettings = new Settings.AuthenticationSettings();
+ settings.authentication = authSettings;
+ authSettings.enableAuditLog = AUDIT_LOG_ENABLED;
+ authSettings.className = Krb5Authenticator.class.getName();
+ final Map<String,Object> authConfig = new HashMap<>();
+ authSettings.config = authConfig;
+
+ final String nameOfTest = name.getMethodName();
+ switch (nameOfTest) {
+ case "shouldAuditLogWithAllowAllAuthenticator":
+ authSettings.className = AllowAllAuthenticator.class.getName();
+ break;
+ case "shouldAuditLogWithSimpleAuthenticator":
+ authSettings.className = SimpleAuthenticator.class.getName();
+ authConfig.put(SimpleAuthenticator.CONFIG_CREDENTIALS_DB, "conf/tinkergraph-credentials.properties");
+ break;
+ case "shouldNotAuditLogWhenDisabled":
+ authSettings.enableAuditLog = AUDIT_LOG_DISABLED;
+ case "shouldAuditLogWithKrb5Authenticator":
+ authConfig.put("keytab", kdcServer.serviceKeytabFile.getAbsolutePath());
+ authConfig.put("principal", kdcServer.serverPrincipal);
+ break;
+ case "shouldAuditLogWithNioTransport":
+ settings.channelizer = NioChannelizer.class.getName();
+ authConfig.put("keytab", kdcServer.serviceKeytabFile.getAbsolutePath());
+ authConfig.put("principal", kdcServer.serverPrincipal);
+ break;
+ case "shouldAuditLogWithHttpTransport":
+ settings.host = "localhost";
+ settings.channelizer = HttpChannelizer.class.getName();
+ authSettings.className = SimpleAuthenticator.class.getName();
+ authConfig.put(SimpleAuthenticator.CONFIG_CREDENTIALS_DB, "conf/tinkergraph-credentials.properties");
+ break;
+ }
+ return settings;
+ }
+
+ @Test
+ public void shouldAuditLogWithAllowAllAuthenticator() throws Exception {
+
+ final Cluster cluster = TestClientFactory.build().credentials("sdfsdf", "")
+ .addContactPoint(kdcServer.hostname).create();
+ final Client client = cluster.connect();
+
+ try {
+ assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
+ assertEquals(3, client.submit("1+2").all().get().get(0).getInt());
+ assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
+ } finally {
+ cluster.close();
+ }
+
+ // WebSocketChannelizer does not add SaslAuthenticationHandler, so no authenticated user log line available
+ assertTrue(recordingAppender.logMatchesAny(AUDIT_LOGGER_NAME, INFO, "User with address .*? requested: 1\\+1"));
+ assertTrue(recordingAppender.logMatchesAny(AUDIT_LOGGER_NAME, INFO, "User with address .*? requested: 1\\+2"));
+ assertTrue(recordingAppender.logMatchesAny(AUDIT_LOGGER_NAME, INFO, "User with address .*? requested: 1\\+3"));
+ }
+
+ @Test
+ public void shouldAuditLogWithSimpleAuthenticator() throws Exception {
+ final String username = "stephen";
+ final String password = "password";
+
+ final Cluster cluster = TestClientFactory.build().credentials(username, password)
+ .addContactPoint(kdcServer.hostname).create();
+ final Client client = cluster.connect();
+
+ try {
+ assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
+ assertEquals(3, client.submit("1+2").all().get().get(0).getInt());
+ assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
+ } finally {
+ cluster.close();
+ }
+
+ final String simpleAuthenticatorName = SimpleAuthenticator.class.getSimpleName();
+ final String authMsg = recordingAppender.getMessages().stream()
+ .filter( msg -> msg.toString().contains("by " + simpleAuthenticatorName) ).iterator().next();
+ final Matcher m = Pattern.compile(".*?([\\d.:]+).*?").matcher(authMsg);
+ m.find();
+ final String address = m.group(1);
+
+ assertTrue(recordingAppender.logContainsAny(AUDIT_LOGGER_NAME, INFO,
+ String.format("User %s with address %s authenticated by %s", username, address, simpleAuthenticatorName)));
+ assertTrue(recordingAppender.logContainsAny(AUDIT_LOGGER_NAME, INFO,
+ String.format("User with address %s requested: 1+1", address)));
+ assertTrue(recordingAppender.logContainsAny(AUDIT_LOGGER_NAME, INFO,
+ String.format("User with address %s requested: 1+2", address)));
+ assertTrue(recordingAppender.logContainsAny(AUDIT_LOGGER_NAME, INFO,
+ String.format("User with address %s requested: 1+3", address)));
+ }
+
+ @Test
+ public void shouldAuditLogWithKrb5Authenticator() throws Exception {
+ final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
+ .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+ final Client client = cluster.connect();
+ try {
+ assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
+ assertEquals(3, client.submit("1+2").all().get().get(0).getInt());
+ assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
+ } finally {
+ cluster.close();
+ }
+
+ final List<LoggingEvent> log = recordingAppender.getEvents();
+ final Stream<LoggingEvent> auditEvents = log.stream().filter(event -> event.getLoggerName().equals(AUDIT_LOGGER_NAME));
+ final LoggingEvent authEvent = auditEvents
+ .filter(event -> event.getMessage().toString().contains("Krb5Authenticator")).iterator().next();
+ final String authMsg = authEvent.getMessage().toString();
+ final Matcher m = Pattern.compile(".*?([\\d.:]+).*?").matcher(authMsg);
+ m.find();
+ final String address = m.group(1);
+ assertTrue(authEvent.getLevel() == INFO && authMsg.equals(
+ String.format("User %s with address %s authenticated by Krb5Authenticator", kdcServer.clientPrincipalName, address)));
+ assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().equals(String.format("User with address %s requested: 1+1", address))));
+ assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().equals(String.format("User with address %s requested: 1+2", address))));
+ assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().equals(String.format("User with address %s requested: 1+3", address))));
+ }
+
+ @Test
+ public void shouldNotAuditLogWhenDisabled() throws Exception {
+ final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
+ .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+ final Client client = cluster.connect();
+ try {
+ assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
+ assertEquals(3, client.submit("1+2").all().get().get(0).getInt());
+ assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
+ } finally {
+ cluster.close();
+ }
+
+ final List<LoggingEvent> log = recordingAppender.getEvents();
+ assertFalse(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().matches("User .*? with address .*? authenticated by Krb5Authenticator")));
+ assertFalse(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().matches("User with address .*? requested: 1\\+1")));
+ assertFalse(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().matches("User with address .*? requested: 1\\+2")));
+ assertFalse(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().matches("User with address .*? requested: 1\\+3")));
+ }
+
+ @Test
+ public void shouldAuditLogWithNioTransport() throws Exception {
+ // ToDo issue (outside scope of this suite): .channelizer(Channelizer.NioChannelizer.class) fails
+ final Cluster cluster = TestClientFactory.build().channelizer(Channelizer.NioChannelizer.class.getName())
+ .jaasEntry(TESTCONSOLE).protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
+ final Client client = cluster.connect();
+ try {
+ assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
+ assertEquals(3, client.submit("1+2").all().get().get(0).getInt());
+ assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
+ } finally {
+ cluster.close();
+ }
+
+ final List<LoggingEvent> log = recordingAppender.getEvents();
+ final Stream<LoggingEvent> auditEvents = log.stream().filter(event -> event.getLoggerName().equals(AUDIT_LOGGER_NAME));
+ final LoggingEvent authEvent = auditEvents
+ .filter(event -> event.getMessage().toString().contains("Krb5Authenticator")).iterator().next();
+ final String authMsg = authEvent.getMessage().toString();
+ final Matcher m = Pattern.compile(".*?([\\d.:]+).*?").matcher(authMsg);
+ m.find();
+ final String address = m.group(1);
+ assertTrue(authEvent.getLevel() == INFO && authMsg.equals(
+ String.format("User %s with address %s authenticated by Krb5Authenticator", kdcServer.clientPrincipalName, address)));
+ assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().equals(String.format("User with address %s requested: 1+1", address))));
+ assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().equals(String.format("User with address %s requested: 1+2", address))));
+ assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().equals(String.format("User with address %s requested: 1+3", address))));
+ }
+
+ @Test
+ public void shouldAuditLogWithHttpTransport() throws Exception {
+ final CloseableHttpClient httpclient = HttpClients.createDefault();
+ final HttpGet httpget = new HttpGet(TestClientFactory.createURLString("?gremlin=1-1"));
+ httpget.addHeader("Authorization", "Basic " + encoder.encodeToString("stephen:password".getBytes()));
+
+ final CloseableHttpResponse response = httpclient.execute(httpget);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals("application/json", response.getEntity().getContentType().getValue());
+ final String json = EntityUtils.toString(response.getEntity());
+ final JsonNode node = mapper.readTree(json);
+ response.close();
+ assertEquals(0, node.get("result").get("data").get(0).intValue());
+
+ final List<LoggingEvent> log = recordingAppender.getEvents();
+ final Stream<LoggingEvent> auditEvents = log.stream().filter(event -> event.getLoggerName().equals(AUDIT_LOGGER_NAME));
+ final LoggingEvent authEvent = auditEvents
+ .filter(event -> event.getMessage().toString().contains("SimpleAuthenticator")).iterator().next();
+ final String authMsg = authEvent.getMessage().toString();
+ final Matcher m = Pattern.compile(".*?([\\d.:]+).*?").matcher(authMsg);
+ m.find();
+ final String address = m.group(1);
+ assertTrue(authEvent.getLevel() == INFO && authMsg.equals(
+ String.format("User %s with address %s authenticated by SimpleAuthenticator", "stephen", address)));
+ assertTrue(log.stream().anyMatch(item -> item.getLevel() == INFO &&
+ item.getMessage().toString().equals(String.format("User with address %s requested: 1-1", address))));
+ }
+
+ //ToDo: test with two clients
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5Test.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5Test.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5Test.java
index b87c170..6d596af 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5Test.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5Test.java
@@ -19,28 +19,25 @@
package org.apache.tinkerpop.gremlin.server;
import org.apache.commons.lang.exception.ExceptionUtils;
-import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Logger;
-import org.apache.log4j.Level;
-import org.apache.log4j.spi.LoggingEvent;
import org.apache.tinkerpop.gremlin.driver.Client;
import org.apache.tinkerpop.gremlin.driver.Cluster;
+import org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator;
+import org.apache.tinkerpop.gremlin.util.Log4jRecordingAppender;
import org.ietf.jgss.GSSException;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
-import org.apache.tinkerpop.gremlin.driver.Client;
-import org.apache.tinkerpop.gremlin.driver.Cluster;
+import org.slf4j.LoggerFactory;
import java.io.File;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
import javax.security.auth.login.LoginException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import org.junit.Test;
@@ -49,14 +46,84 @@ import org.junit.Test;
*
* Todo: change back to integrate test later on
*/
-public class AuthKrb5Test extends AuthKrb5TestBase {
- // Cannot use mere slf4j because need to check log output
- private final Logger rootLogger = Logger.getRootLogger();
- private final Logger logger = Logger.getLogger(AuthKrb5Test.class);
+public class AuthKrb5Test extends AbstractGremlinServerIntegrationTest {
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AuthKrb5Test.class);
+ private Log4jRecordingAppender recordingAppender = null;
+
+ static final String TESTCONSOLE = "GremlinConsole";
+ static final String TESTCONSOLE_NOT_LOGGED_IN = "UserNotLoggedIn";
+
+ private KdcFixture kdcServer;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ setupForEachTest();
+ try {
+ final String buildDir = System.getProperty("build.dir");
+ kdcServer = new KdcFixture(buildDir +
+ "/test-classes/org/apache/tinkerpop/gremlin/server/gremlin-console-jaas.conf");
+ kdcServer.setUp();
+ } catch(Exception e) {
+ logger.warn(e.getMessage());
+ }
+ super.setUp();
+ }
+
+ public void setupForEachTest() {
+ recordingAppender = new Log4jRecordingAppender();
+ final Logger rootLogger = Logger.getRootLogger();
+ rootLogger.addAppender(recordingAppender);
+ }
- private GremlinServerAuthKrb5Integrate server;
- private static final String TESTCONSOLE = "GremlinConsole";
- private static final String TESTCONSOLE_NOT_LOGGED_IN = "UserNotLoggedIn";
+ @After
+ public void teardownForEachTest() {
+ final Logger rootLogger = Logger.getRootLogger();
+ rootLogger.removeAppender(recordingAppender);
+ }
+
+ /**
+ * Configure specific Gremlin Server settings for specific tests.
+ */
+ @Override
+ public Settings overrideSettings(final Settings settings) {
+ settings.host = kdcServer.hostname;
+ final Settings.SslSettings sslConfig = new Settings.SslSettings();
+ sslConfig.enabled = false;
+ settings.ssl = sslConfig;
+ final Settings.AuthenticationSettings authSettings = new Settings.AuthenticationSettings();
+ settings.authentication = authSettings;
+ authSettings.className = Krb5Authenticator.class.getName();
+ final Map<String,Object> authConfig = new HashMap<>();
+ authConfig.put("principal", kdcServer.serverPrincipal);
+ authConfig.put("keytab", kdcServer.serviceKeytabFile.getAbsolutePath());
+ authSettings.config = authConfig;
+
+ final String nameOfTest = name.getMethodName();
+ switch (nameOfTest) {
+ case "shouldAuthenticateWithDefaults":
+ case "shouldFailWithoutClientJaasEntry":
+ case "shouldFailWithoutClientTicketCache":
+ break;
+ case "shouldFailWithNonexistentServerPrincipal":
+ authConfig.put("principal", "no-service");
+ break;
+ case "shouldFailWithEmptyServerKeytab":
+ final File keytabFile = new File(".", "no-file");
+ authConfig.put("keytab", keytabFile);
+ break;
+ case "shouldFailWithWrongServerKeytab":
+ final String principal = "no-principal/somehost@TEST.COM";
+ try { kdcServer.createPrincipal(principal); } catch(Exception e) {
+ logger.error("Cannot create principal in overrideSettings(): " + e.getMessage());
+ };
+ authConfig.put("principal", principal);
+ break;
+ case "shouldAuthenticateWithQop":
+ break;
+ }
+ return settings;
+ }
/**
* Defaults from TestClientFactory:
@@ -89,10 +156,8 @@ public class AuthKrb5Test extends AuthKrb5TestBase {
*/
@Test
public void shouldAuthenticateWithDefaults() throws Exception {
- server = new GremlinServerAuthKrb5Integrate(getServerPrincipal(), serviceKeytabFile);
- server.setUp();
final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
- .protocol(getServerPrincipalName()).addContactPoint(getHostname()).create();
+ .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
final Client client = cluster.connect();
try {
assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
@@ -100,16 +165,13 @@ public class AuthKrb5Test extends AuthKrb5TestBase {
assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
} finally {
cluster.close();
- server.tearDown();
}
}
@Test
public void shouldFailWithoutClientJaasEntry() throws Exception {
- server = new GremlinServerAuthKrb5Integrate(getServerPrincipal(), serviceKeytabFile);
- server.setUp();
- final Cluster cluster = TestClientFactory.build().protocol(getServerPrincipalName())
- .addContactPoint(getHostname()).create();
+ final Cluster cluster = TestClientFactory.build().protocol(kdcServer.serverPrincipalName)
+ .addContactPoint(kdcServer.hostname).create();
final Client client = cluster.connect();
try {
client.submit("1+1").all().get();
@@ -119,16 +181,13 @@ public class AuthKrb5Test extends AuthKrb5TestBase {
assertEquals(GSSException.class, root.getClass());
} finally {
cluster.close();
- server.tearDown();
}
}
@Test
public void shouldFailWithoutClientTicketCache() throws Exception {
- server = new GremlinServerAuthKrb5Integrate(getServerPrincipal(), serviceKeytabFile);
- server.setUp();
final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE_NOT_LOGGED_IN)
- .protocol(getServerPrincipalName()).addContactPoint(getHostname()).create();
+ .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
final Client client = cluster.connect();
try {
client.submit("1+1").all().get();
@@ -138,80 +197,30 @@ public class AuthKrb5Test extends AuthKrb5TestBase {
assertEquals(LoginException.class, root.getClass());
} finally {
cluster.close();
- server.tearDown();
}
}
@Test
public void shouldFailWithNonexistentServerPrincipal() throws Exception {
- final TestAppender appender = new TestAppender();
- rootLogger.addAppender(appender);
- server = new GremlinServerAuthKrb5Integrate("no-service", serviceKeytabFile);
- server.setUp();
- server.tearDown();
-
- final List<LoggingEvent> log = appender.getLog();
- assertTrue(log.stream().anyMatch(item -> item.getLevel() == Level.WARN &&
- item.getMessage() == "Failed to login to kdc"));
- }
-
- class TestAppender extends AppenderSkeleton {
- private final List<LoggingEvent> log = new ArrayList<LoggingEvent>();
-
- @Override
- public boolean requiresLayout() {
- return false;
- }
-
- protected void append(final LoggingEvent loggingEvent) {
- log.add(loggingEvent);
- }
-
- @Override
- public void close() {
- }
-
- public List<LoggingEvent> getLog() {
- return new ArrayList<LoggingEvent>(log);
- }
+ assertTrue(recordingAppender.logContainsAny("WARN - Failed to login to kdc"));
}
@Test
public void shouldFailWithEmptyServerKeytab() throws Exception {
- final TestAppender appender = new TestAppender();
- rootLogger.addAppender(appender);
- final File keytabFile = new File(".", "no-file");
- server = new GremlinServerAuthKrb5Integrate(getServerPrincipal(), keytabFile);
- server.setUp();
- server.tearDown();
-
- final List<LoggingEvent> log = appender.getLog();
- for (LoggingEvent event: log) {
- System.out.println("Log: " + event.getLevel() + " " + event.getMessage());
- }
- assertTrue(log.stream().anyMatch(item -> item.getLevel() == Level.WARN &&
- item.getMessage() == "Failed to login to kdc"));
+ assertTrue(recordingAppender.logContainsAny("WARN - Failed to login to kdc"));
}
@Test
public void shouldFailWithWrongServerKeytab() throws Exception {
- final TestAppender appender = new TestAppender();
- rootLogger.addAppender(appender);
- final String principal = "no-principal/somehost@TEST.COM";
- getKdcServer().createPrincipal(principal);
- server = new GremlinServerAuthKrb5Integrate(principal, serviceKeytabFile);
- server.setUp();
- server.tearDown();
+ assertTrue(recordingAppender.logContainsAny("WARN - Failed to login to kdc"));
}
@Test
public void shouldAuthenticateWithQop() throws Exception {
- server = new GremlinServerAuthKrb5Integrate(getServerPrincipal(), serviceKeytabFile);
- server.setUp();
final String oldQop = System.getProperty("javax.security.sasl.qop", "");
System.setProperty("javax.security.sasl.qop", "auth-conf");
final Cluster cluster = TestClientFactory.build().jaasEntry(TESTCONSOLE)
- .protocol(getServerPrincipalName()).addContactPoint(getHostname()).create();
+ .protocol(kdcServer.serverPrincipalName).addContactPoint(kdcServer.hostname).create();
final Client client = cluster.connect();
try {
assertEquals(2, client.submit("1+1").all().get().get(0).getInt());
@@ -219,7 +228,6 @@ public class AuthKrb5Test extends AuthKrb5TestBase {
assertEquals(4, client.submit("1+3").all().get().get(0).getInt());
} finally {
cluster.close();
- server.tearDown();
System.setProperty("javax.security.sasl.qop", oldQop);
}
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5TestBase.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5TestBase.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5TestBase.java
deleted file mode 100644
index ccf6f9f..0000000
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/AuthKrb5TestBase.java
+++ /dev/null
@@ -1,130 +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;
-
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.server.LoginTestBase;
-import org.apache.kerby.kerberos.kerb.server.TestKdcServer;
-import org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator;
-
-import java.io.File;
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
-import java.util.*;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * @author Marc de Lignie
- */
-public class AuthKrb5TestBase extends LoginTestBase {
- private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AuthKrb5TestBase.class);
-
- private String safeHostname = null;
- private String safeServerPrincipal = null;
-
- public AuthKrb5TestBase() {
- // Hostname setting must be consistent with the way gremlin-console sets gremlin-server's hostname
- // and derives gremlin-server's principal name. Also, the hostname needs to be lowercase for use
- // in principal names.
- try {
- safeHostname = Inet4Address.getLocalHost().getCanonicalHostName().toLowerCase();
- safeServerPrincipal = getServerPrincipalName() + "/" + getHostname() + "@" + TestKdcServer.KDC_REALM;
- } catch (UnknownHostException e) {
- logger.error("Hostname not found");
- }
- }
-
- @Rule
- public TestName name = new TestName();
-
- @Override
- protected String getHostname() {
- return safeHostname;
- }
-
- @Override
- protected String getServerPrincipal() { return safeServerPrincipal; }
-
- @Override
- protected void createPrincipals() throws KrbException {
- getKdcServer().createPrincipals(getServerPrincipal());
- getKdcServer().createPrincipal(getClientPrincipal(), getClientPassword());
- }
-
- @Override
- protected void deletePrincipals() throws KrbException {
- getKdcServer().getKadmin().deleteBuiltinPrincipals();
- getKdcServer().deletePrincipals(getServerPrincipal());
- getKdcServer().deletePrincipal(getClientPrincipal());
- }
-
- protected class GremlinServerAuthKrb5Integrate extends AbstractGremlinServerIntegrationTest {
-
- final String principal;
- final File keytabFile;
-
- GremlinServerAuthKrb5Integrate(String principal, File keytabFile) {
- this.principal = principal;
- this.keytabFile = keytabFile;
- }
-
- @Override
- public Settings overrideSettings(final Settings settings) {
- settings.host = getHostname();
- logger.debug("Hostname: " + settings.host);
- final Settings.AuthenticationSettings authSettings = new Settings.AuthenticationSettings();
- authSettings.className = Krb5Authenticator.class.getName();
- final Map authConfig = new HashMap<String,Object>();
- authConfig.put("keytab", keytabFile.getAbsolutePath());
- authConfig.put("principal", principal);
- authSettings.config = authConfig;
- settings.authentication = authSettings;
- final Settings.SslSettings sslConfig = new Settings.SslSettings();
- sslConfig.enabled = false;
- settings.ssl = sslConfig;
-
-// switch (nameOfTest) {
-// case "shouldAuthenticateOverSslWithKerberosTicket":
-// case "shouldFailIfSslEnabledOnServerButNotClient":
-// final Settings.SslSettings sslConfig = new Settings.SslSettings();
-// sslConfig.enabled = true;
-// settings.ssl = sslConfig;
-// break;
-// }
- return settings;
- }
- }
-
- @Before
- @Override
- public void setUp() throws Exception {
- logger.info("Starting " + name.getMethodName());
- super.setUp();
- loginServiceUsingKeytab();
- loginClientUsingTicketCache();
- final String buildDir = System.getProperty("build.dir");
- System.setProperty("java.security.auth.login.config", buildDir +
- "/test-classes/org/apache/tinkerpop/gremlin/server/gremlin-console-jaas.conf");
- }
-}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java
new file mode 100644
index 0000000..73aa0a7
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/KdcFixture.java
@@ -0,0 +1,152 @@
+/*
+ * 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;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbClient;
+import org.apache.kerby.kerberos.kerb.client.KrbConfig;
+import org.apache.kerby.kerberos.kerb.client.KrbConfigKey;
+import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
+import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
+import org.apache.kerby.util.NetworkUtil;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.net.Inet4Address;
+
+
+/**
+ * @author Marc de Lignie
+ *
+ * This class is derived from the following classes from https://github.com/apache/directory-kerby/blob/kerby-all-1.0.0-RC2/:
+ * - org.apache.kerby.kerberos.kerb.server.TestKdcServer
+ * - org.apache.kerby.kerberos.kerb.server.KdcTestBase
+ * - org.apache.kerby.kerberos.kerb.server.LoginTestBase.java
+ *
+ * See also: gremlin-server/src/main/static/NOTICE
+ */
+public class KdcFixture {
+
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KdcFixture.class);
+
+ final String clientPassword = "123456";
+ final String clientPrincipalName = "drankye";
+ final String serverPrincipalName = "test-service";
+ final String ticketCacheFileName = "test-tkt.cc";
+ final String serviceKeytabFileName = "test-service.keytab";
+
+ final String clientPrincipal;
+ final String serverPrincipal;
+ final File testDir;
+ final File ticketCacheFile;
+ final File serviceKeytabFile;
+
+ final String hostname;
+ private SimpleKdcServer kdcServer;
+
+
+ public KdcFixture(String authConfigName) throws Exception {
+ System.setProperty("java.security.auth.login.config", authConfigName);
+ hostname = findHostname();
+ serverPrincipal = serverPrincipalName + "/" + hostname + "@" + KdcFixture.TestKdcServer.KDC_REALM;
+ clientPrincipal = clientPrincipalName + "@" + KdcFixture.TestKdcServer.KDC_REALM;
+ testDir = createTestDir();
+ ticketCacheFile = new File(testDir, ticketCacheFileName);
+ serviceKeytabFile = new File(testDir, serviceKeytabFileName);
+ }
+
+ private String findHostname() {
+ // Hostname setting must be consistent with the way gremlin-console sets gremlin-server's hostname
+ // and derives gremlin-server's principal name. Also, the hostname needs to be lowercase for use
+ // in principal names.
+ String hostname = "";
+ try {
+ hostname = Inet4Address.getLocalHost().getCanonicalHostName().toLowerCase();
+ } catch (Exception e) {
+ logger.error("Hostname not found");
+ }
+ return hostname;
+ }
+
+ private File createTestDir() {
+ String basedir = System.getProperty("basedir");
+ File targetdir = new File(basedir, "target");
+ File testDir = new File(targetdir, "tmp");
+ testDir.mkdirs();
+ return testDir;
+ }
+
+ private class TestKdcServer extends SimpleKdcServer {
+ public static final String KDC_REALM = "TEST.COM";
+ public static final String HOSTNAME = "localhost";
+
+ TestKdcServer() throws KrbException {
+ setKdcRealm(KDC_REALM);
+ setKdcHost(HOSTNAME);
+ setAllowTcp(true);
+ setAllowUdp(false); // There are still udp issues in Apache Directory-Kerby 1.0.0-RC2
+ setKdcTcpPort(NetworkUtil.getServerPort());
+
+ KrbClient krbClnt = getKrbClient();
+ KrbConfig krbConfig = krbClnt.getKrbConfig();
+ krbConfig.setString(KrbConfigKey.PERMITTED_ENCTYPES,
+ "aes128-cts-hmac-sha1-96 des-cbc-crc des-cbc-md5 des3-cbc-sha1");
+ krbClnt.setTimeout(10 * 1000);
+ }
+ }
+
+ public void setUp() throws Exception {
+ setUpKdcServer();
+ setUpPrincipals();
+ }
+
+ private void setUpKdcServer() throws Exception {
+ kdcServer = new TestKdcServer();
+ kdcServer.setWorkDir(testDir);
+ kdcServer.init();
+ kdcServer.start();
+ }
+
+ private void setUpPrincipals() throws KrbException {
+ kdcServer.createPrincipals(serverPrincipal);
+ kdcServer.exportPrincipal(serverPrincipal, serviceKeytabFile);
+
+ kdcServer.createPrincipal(clientPrincipal, clientPassword);
+ TgtTicket tgt = kdcServer.getKrbClient().requestTgt(clientPrincipal, clientPassword);
+ kdcServer.getKrbClient().storeTicket(tgt, ticketCacheFile);
+ }
+
+ public void close() throws Exception {
+ deletePrincipals();
+ kdcServer.stop();
+ ticketCacheFile.delete();
+ serviceKeytabFile.delete();
+ testDir.delete();
+ }
+
+ private void deletePrincipals() throws KrbException {
+ kdcServer.getKadmin().deleteBuiltinPrincipals();
+ kdcServer.deletePrincipals(serverPrincipal);
+ kdcServer.deletePrincipal(clientPrincipal);
+ }
+
+ public void createPrincipal(final String principal) throws KrbException {
+ kdcServer.createPrincipal(principal);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
index e44f72f..4a9ebd4 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
@@ -19,6 +19,7 @@
package org.apache.tinkerpop.gremlin.util;
import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.Level;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
@@ -32,6 +33,7 @@ import java.util.List;
*/
public class Log4jRecordingAppender extends AppenderSkeleton {
private final List<String> messages = new ArrayList<>();
+ private final List<LoggingEvent> events = new ArrayList<>();
public Log4jRecordingAppender() {
super();
@@ -41,6 +43,7 @@ public class Log4jRecordingAppender extends AppenderSkeleton {
@Override
protected void append(final LoggingEvent event) {
messages.add(layout.format(event));
+ events.add(event);
}
@Override
@@ -52,9 +55,9 @@ public class Log4jRecordingAppender extends AppenderSkeleton {
return true;
}
- public List<String> getMessages() {
- return messages;
- }
+ public List<String> getMessages() { return messages; }
+
+ public List<LoggingEvent> getEvents() { return events; }
public void clear() {
messages.clear();
@@ -63,4 +66,13 @@ public class Log4jRecordingAppender extends AppenderSkeleton {
public boolean logContainsAny(final String fragment) {
return messages.stream().anyMatch(m -> m.contains(fragment));
}
-}
\ No newline at end of file
+
+ public boolean logContainsAny(final String loggerName, final Level level, final String fragment) {
+ return events.stream().anyMatch(m -> m.getLoggerName().equals(loggerName) &&
+ m.getLevel().equals(level) && m.getMessage().toString().contains(fragment));
+ }
+ public boolean logMatchesAny(final String loggerName, final Level level, final String regex) {
+ return events.stream().anyMatch(m -> m.getLoggerName().equals(loggerName) &&
+ m.getLevel().equals(level) && m.getMessage().toString().matches(regex));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68eff1db/gremlin-server/src/test/resources/log4j-test.properties
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/resources/log4j-test.properties b/gremlin-server/src/test/resources/log4j-test.properties
index 5dec106..c806201 100644
--- a/gremlin-server/src/test/resources/log4j-test.properties
+++ b/gremlin-server/src/test/resources/log4j-test.properties
@@ -20,4 +20,4 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%p] %C - %m%n
-log4j.logger.org.apache.tinkerpop.gremlin.server.op.AbstractEvalOpProcessor=ERROR
\ No newline at end of file
+log4j.logger.org.apache.tinkerpop.gremlin.server.op.AbstractEvalOpProcessor=ERROR