From fcfeaa126e75c11cfb963f02c6f66a53bbca3109 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Thu, 26 Nov 2015 16:46:33 +0000
Subject: [PATCH] OPENDJ-2465 Add support for transactionId in current DJ access and HTTP access loggers
---
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java | 6
opendj-server-legacy/src/main/java/org/opends/server/loggers/TextAccessLogPublisher.java | 33 +++++
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/FileBasedHTTPAccessLogPublisherConfiguration.xml | 7
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java | 3
opendj-server-legacy/resource/schema/02-config.ldif | 9 +
opendj-server-legacy/src/test/java/org/opends/server/protocols/http/CollectClientConnectionsFilterTest.java | 4
opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java | 36 ++---
opendj-server-legacy/pom.xml | 4
opendj-server-legacy/src/main/java/org/opends/server/loggers/TextHTTPAccessLogPublisher.java | 4
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/GlobalConfiguration.xml | 20 +++
opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java | 45 +++++++
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPClientConnection.java | 40 ++++++
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditTransactionIdFilter.java | 86 ++++++++++++++
opendj-server-legacy/src/main/java/org/opends/server/core/CoreConfigManager.java | 8 +
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CollectClientConnectionsFilter.java | 14 +
opendj-server-legacy/src/test/java/org/opends/server/monitors/BackendMonitorTestCase.java | 2
opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPRequestInfo.java | 9 +
17 files changed, 290 insertions(+), 40 deletions(-)
diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/FileBasedHTTPAccessLogPublisherConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/FileBasedHTTPAccessLogPublisherConfiguration.xml
index 841d210..06a4184 100644
--- a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/FileBasedHTTPAccessLogPublisherConfiguration.xml
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/FileBasedHTTPAccessLogPublisherConfiguration.xml
@@ -22,7 +22,7 @@
! CDDL HEADER END
!
!
- ! Copyright 2013 ForgeRock AS
+ ! Copyright 2013-2015 ForgeRock AS
! -->
<adm:managed-object name="file-based-http-access-log-publisher"
plural-name="file-based-http-access-log-publishers"
@@ -278,7 +278,7 @@
<adm:default-behavior>
<adm:defined>
<adm:value>cs-host c-ip cs-username x-datetime cs-method cs-uri-query
- cs-version sc-status cs(User-Agent) x-connection-id x-etime</adm:value>
+ cs-version sc-status cs(User-Agent) x-connection-id x-etime x-transaction-id</adm:value>
</adm:defined>
</adm:default-behavior>
<adm:syntax>
@@ -304,7 +304,8 @@
date and time for the logged HTTP request and its ouput is
controlled by the "ds-cfg-log-record-time-format" property,
"x-etime" displays the total execution time for the logged HTTP
- request.
+ request, "x-transaction-id" displays the transaction id associated
+ to a request
</adm:synopsis>
</adm:pattern>
</adm:string>
diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/GlobalConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/GlobalConfiguration.xml
index 09f9252..185a5b8 100644
--- a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/GlobalConfiguration.xml
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/GlobalConfiguration.xml
@@ -874,4 +874,24 @@
</ldap:attribute>
</adm:profile>
</adm:property>
+ <adm:property name="trust-transaction-ids" advanced="true">
+ <adm:synopsis>
+ Indicates whether the directory server should trust the
+ transaction ids that may be received from requests, either
+ through a LDAP control or through a HTTP header.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>false</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:boolean />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:name>ds-cfg-trust-transaction-ids</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
</adm:managed-object>
diff --git a/opendj-server-legacy/pom.xml b/opendj-server-legacy/pom.xml
index 7423f80..60428a2 100644
--- a/opendj-server-legacy/pom.xml
+++ b/opendj-server-legacy/pom.xml
@@ -160,6 +160,10 @@
<groupId>org.forgerock.commons</groupId>
<artifactId>forgerock-audit-json</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.forgerock.commons</groupId>
+ <artifactId>forgerock-audit-handler-syslog</artifactId>
+ </dependency>
<!-- servlet and mail -->
<dependency>
diff --git a/opendj-server-legacy/resource/schema/02-config.ldif b/opendj-server-legacy/resource/schema/02-config.ldif
index b7e9552..0e3730b 100644
--- a/opendj-server-legacy/resource/schema/02-config.ldif
+++ b/opendj-server-legacy/resource/schema/02-config.ldif
@@ -3829,6 +3829,12 @@
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
X-ORIGIN 'OpenDJ Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.155
+ NAME 'ds-cfg-trust-transaction-ids'
+ EQUALITY booleanMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+ SINGLE-VALUE
+ X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler'
SUP top
@@ -4240,7 +4246,8 @@
ds-cfg-etime-resolution $
ds-cfg-max-allowed-client-connections $
ds-cfg-max-psearches $
- ds-cfg-max-internal-buffer-size )
+ ds-cfg-max-internal-buffer-size $
+ ds-cfg-trust-transaction-ids)
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.40
NAME 'ds-cfg-root-dn-user'
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/CoreConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/CoreConfigManager.java
index 67122ba..754f479 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/CoreConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/CoreConfigManager.java
@@ -44,6 +44,7 @@
import org.opends.server.admin.std.server.GlobalCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.AuthenticationPolicy;
+import org.opends.server.loggers.CommonAudit;
import org.opends.server.schema.SchemaUpdater;
import org.opends.server.types.*;
@@ -162,6 +163,13 @@
setMaxPersistentSearchLimit(globalConfig.getMaxPsearches());
setMaxInternalBufferSize((int) globalConfig.getMaxInternalBufferSize());
+ // For tools, common audit may not be available
+ CommonAudit commonAudit = serverContext.getCommonAudit();
+ if (commonAudit != null)
+ {
+ commonAudit.setTrustTransactionIds(globalConfig.isTrustTransactionIds());
+ }
+
// Update the "new" schema with configuration changes
SchemaUpdater schemaUpdater = serverContext.getSchemaUpdater();
SchemaBuilder schemaBuilder = schemaUpdater.getSchemaBuilder();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
index ad3bfd2..85e2902 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -1347,6 +1347,8 @@
initializeSchema();
+ commonAudit = new CommonAudit();
+
// Allow internal plugins to be registered.
pluginConfigManager.initializePluginConfigManager();
@@ -1364,7 +1366,6 @@
retentionPolicyConfigManager = new LogRetentionPolicyConfigManager(serverContext);
retentionPolicyConfigManager.initializeLogRetentionPolicyConfig();
- commonAudit = new CommonAudit();
loggerConfigManager = new LoggerConfigManager(serverContext);
loggerConfigManager.initializeLoggerConfig();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
index aa413b1..0bd29b3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
@@ -25,6 +25,8 @@
*/
package org.opends.server.loggers;
+import static java.util.Arrays.asList;
+
import static org.opends.messages.LoggerMessages.*;
import static java.util.Collections.newSetFromMap;
import static org.forgerock.audit.AuditServiceBuilder.newAuditService;
@@ -41,11 +43,13 @@
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import org.forgerock.audit.AuditException;
@@ -57,6 +61,7 @@
import org.forgerock.audit.events.EventTopicsMetaData;
import org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration.FileRetention;
import org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration.FileRotation;
+import org.forgerock.audit.filter.FilterPolicy;
import org.forgerock.audit.handlers.csv.CsvAuditEventHandler;
import org.forgerock.audit.handlers.csv.CsvAuditEventHandlerConfiguration;
import org.forgerock.audit.handlers.csv.CsvAuditEventHandlerConfiguration.CsvFormatting;
@@ -100,6 +105,8 @@
*/
public class CommonAudit
{
+ /** Transaction id used when the incoming request does not contain a transaction id. */
+ public static final String DEFAULT_TRANSACTION_ID = "0";
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
@@ -120,6 +127,7 @@
/** Audit service shared by all HTTP access publishers. */
private final AuditServiceProxy httpAccessAuditService;
+ private final AtomicBoolean trustTransactionIds = new AtomicBoolean(false);
/**
* Creates the common audit.
@@ -134,6 +142,28 @@
this.httpAccessAuditService = createAuditServiceWithoutHandlers();
}
+ /**
+ * Indicates if transactionIds received from requests should be trusted.
+ *
+ * @return {@code true} if transactionIds should be trusted, {@code false} otherwise
+ */
+ public boolean shouldTrustTransactionIds()
+ {
+ return trustTransactionIds.get();
+ }
+
+ /**
+ * Sets the indicator for transactionIds trusting.
+ *
+ * @param shouldTrust
+ * {@code true} if transactionIds should be trusted, {@code false}
+ * otherwise
+ */
+ public void setTrustTransactionIds(boolean shouldTrust)
+ {
+ trustTransactionIds.set(shouldTrust);
+ }
+
private AuditServiceProxy createAuditServiceWithoutHandlers() throws ConfigException
{
try
@@ -349,6 +379,7 @@
AuditServiceConfiguration auditConfig = new AuditServiceConfiguration();
auditConfig.setAvailableAuditEventHandlers(setup.getHandlerNames());
+ auditConfig.setFilterPolicies(getFilterPoliciesToPreventHttpHeadersLogging());
builder.withConfiguration(auditConfig);
AuditService audit = builder.build();
@@ -368,6 +399,20 @@
return proxy;
}
+ /**
+ * Build filter policies at the AuditService level to prevent logging of the headers for HTTP requests.
+ * <p>
+ * HTTP Headers may contains authentication information.
+ */
+ private Map<String, FilterPolicy> getFilterPoliciesToPreventHttpHeadersLogging()
+ {
+ Map<String, FilterPolicy> filterPolicies = new HashMap<>();
+ FilterPolicy policy = new FilterPolicy();
+ policy.setExcludeIf(asList("/http-access/http/request/headers"));
+ filterPolicies.put("field", policy);
+ return filterPolicies;
+ }
+
private void addHandlerToBuilder(PublisherConfig publisher, AuditServiceBuilder builder) throws ConfigException
{
if (publisher.isCsv())
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java
index ffa63f6..ab27fb1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAuditAccessLogPublisher.java
@@ -29,6 +29,7 @@
import static org.forgerock.json.JsonValue.json;
import static org.forgerock.json.resource.Requests.newCreateRequest;
import static org.forgerock.json.resource.ResourcePath.resourcePath;
+import static org.opends.server.loggers.CommonAudit.DEFAULT_TRANSACTION_ID;
import static org.opends.server.loggers.OpenDJAccessAuditEventBuilder.openDJAccessEvent;
import static org.opends.server.types.AuthenticationType.SASL;
@@ -66,13 +67,11 @@
import org.opends.server.core.ServerContext;
import org.opends.server.core.UnbindOperation;
import org.opends.server.types.AuthenticationInfo;
-import org.opends.server.types.Control;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Operation;
-import org.opends.server.util.ServerConstants;
import org.opends.server.util.StaticUtils;
/**
@@ -87,15 +86,14 @@
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
- /** Transaction id used when the incoming request does not contain a transaction id. */
- private static final String DEFAULT_TRANSACTION_ID = "0";
-
/** Audit service handler. */
private RequestHandler requestHandler;
/** Current configuration for this publisher. */
private T config;
+ private ServerContext serverContext;
+
@Override
public void setRequestHandler(RequestHandler handler)
{
@@ -118,6 +116,7 @@
public void initializeLogPublisher(final T cfg, ServerContext serverContext)
throws ConfigException, InitializationException
{
+ this.serverContext = serverContext;
initializeFilters(cfg);
config = cfg;
}
@@ -250,7 +249,7 @@
.client(clientConnection.getClientAddress(), clientConnection.getClientPort())
.server(clientConnection.getServerAddress(), clientConnection.getServerPort())
.request(clientConnection.getProtocol(), "CONNECT")
- .transactionId(DEFAULT_TRANSACTION_ID)
+ .transactionId(CommonAudit.DEFAULT_TRANSACTION_ID)
.response(ResponseStatus.SUCCESSFUL, String.valueOf(ResultCode.SUCCESS.intValue()), 0, TimeUnit.MILLISECONDS)
.ldapConnectionId(clientConnection.getConnectionID());
@@ -286,7 +285,7 @@
.client(clientConnection.getClientAddress(), clientConnection.getClientPort())
.server(clientConnection.getServerAddress(), clientConnection.getServerPort())
.request(clientConnection.getProtocol(),"DISCONNECT")
- .transactionId(DEFAULT_TRANSACTION_ID)
+ .transactionId(CommonAudit.DEFAULT_TRANSACTION_ID)
.response(ResponseStatus.SUCCESSFUL, String.valueOf(ResultCode.SUCCESS.intValue()), 0, TimeUnit.MILLISECONDS)
.ldapConnectionId(clientConnection.getConnectionID())
.ldapReason(disconnectReason.toString())
@@ -491,9 +490,9 @@
private String getTransactionId(Operation operation)
{
String transactionId = getTransactionIdFromControl(operation);
- if (transactionId == null)
+ if (transactionId == null || !serverContext.getCommonAudit().shouldTrustTransactionIds())
{
- // use a default value because transaction id has no usage in this case
+ // use a default value
transactionId = DEFAULT_TRANSACTION_ID;
}
return transactionId;
@@ -501,19 +500,14 @@
private String getTransactionIdFromControl(Operation operation)
{
- for (Control control : operation.getRequestControls())
+ try
{
- if (control.getOID().equals(ServerConstants.OID_TRANSACTION_ID_CONTROL))
- {
- try
- {
- return operation.getRequestControl(TransactionIdControl.DECODER).getTransactionId();
- }
- catch (DirectoryException e)
- {
- logger.error(ERR_COMMON_AUDIT_INVALID_TRANSACTION_ID.get(StaticUtils.stackTraceToSingleLineString(e)));
- }
- }
+ TransactionIdControl control = operation.getRequestControl(TransactionIdControl.DECODER);
+ return control != null ? control.getTransactionId() : null;
+ }
+ catch (DirectoryException e)
+ {
+ logger.error(ERR_COMMON_AUDIT_INVALID_TRANSACTION_ID.get(StaticUtils.stackTraceToSingleLineString(e)));
}
return null;
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPRequestInfo.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPRequestInfo.java
index 75ca8b0..42eec3c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPRequestInfo.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/HTTPRequestInfo.java
@@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
- * Copyright 2013 ForgeRock AS
+ * Copyright 2013-2015 ForgeRock AS
*/
package org.opends.server.loggers;
@@ -140,6 +140,13 @@
long getTotalProcessingTime();
/**
+ * Returns the transactionId for this request.
+ *
+ * @return the transactionId
+ */
+ String getTransactionId();
+
+ /**
* Logs the current request info in the HTTP access log.
*
* @param statusCode
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextAccessLogPublisher.java
index 054f21d..c03cd86 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextAccessLogPublisher.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextAccessLogPublisher.java
@@ -26,6 +26,7 @@
*/
package org.opends.server.loggers;
+import static org.opends.messages.LoggerMessages.ERR_COMMON_AUDIT_INVALID_TRANSACTION_ID;
import static org.opends.messages.ConfigMessages.*;
import static org.opends.server.util.StaticUtils.*;
@@ -47,8 +48,10 @@
import org.opends.server.admin.std.server.FileBasedAccessLogPublisherCfg;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ExtendedOperationHandler;
+import org.opends.server.controls.TransactionIdControl;
import org.opends.server.core.*;
import org.opends.server.types.*;
+import org.opends.server.util.StaticUtils;
import org.opends.server.util.TimeThread;
/** This class provides the implementation of the access logger used by the directory server. */
@@ -87,6 +90,7 @@
private boolean isCombinedMode;
private boolean includeControlOIDs;
private String timeStampFormat = "dd/MMM/yyyy:HH:mm:ss Z";
+ private ServerContext serverContext;
@Override
public ConfigChangeResult applyConfigurationChange(FileBasedAccessLogPublisherCfg config)
@@ -204,6 +208,7 @@
public void initializeLogPublisher(final FileBasedAccessLogPublisherCfg cfg, ServerContext serverContext)
throws ConfigException, InitializationException
{
+ this.serverContext = serverContext;
final File logFile = getLogFile(cfg);
final FileNamingPolicy fnPolicy = new TimeStampNaming(logFile);
@@ -916,6 +921,7 @@
buffer.append(" conn=").append(operation.getConnectionID());
buffer.append(" op=").append(operation.getOperationID());
buffer.append(" msgID=").append(operation.getMessageID());
+ appendTransactionId(operation, buffer);
}
private void appendModifyDNRequest(final ModifyDNOperation modifyDNOperation,
@@ -944,6 +950,33 @@
}
}
+ private void appendTransactionId(Operation operation, final StringBuilder buffer)
+ {
+ // In test context, serverContext may be null
+ if (serverContext != null && serverContext.getCommonAudit().shouldTrustTransactionIds())
+ {
+ String transactionId = getTransactionIdFromControl(operation);
+ if (transactionId != null)
+ {
+ buffer.append(" transactionId=").append(transactionId);
+ }
+ }
+ }
+
+ private String getTransactionIdFromControl(Operation operation)
+ {
+ try
+ {
+ TransactionIdControl control = operation.getRequestControl(TransactionIdControl.DECODER);
+ return control != null ? control.getTransactionId() : null;
+ }
+ catch (DirectoryException e)
+ {
+ logger.error(ERR_COMMON_AUDIT_INVALID_TRANSACTION_ID.get(StaticUtils.stackTraceToSingleLineString(e)));
+ }
+ return null;
+ }
+
private void appendRequestControls(final Operation operation, final StringBuilder buffer)
{
appendControls(buffer, " requestControls=", operation.getRequestControls());
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextHTTPAccessLogPublisher.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextHTTPAccessLogPublisher.java
index 2c37a58..42bfe33 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextHTTPAccessLogPublisher.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/TextHTTPAccessLogPublisher.java
@@ -80,12 +80,13 @@
private static final String X_CONNECTION_ID = "x-connection-id";
private static final String X_DATETIME = "x-datetime";
private static final String X_ETIME = "x-etime";
+ private static final String X_TRANSACTION_ID = "x-transaction-id";
private static final Set<String> ALL_SUPPORTED_FIELDS = new HashSet<>(
Arrays.asList(ELF_C_IP, ELF_C_PORT, ELF_CS_HOST, ELF_CS_METHOD,
ELF_CS_URI_QUERY, ELF_CS_USER_AGENT, ELF_CS_USERNAME, ELF_CS_VERSION,
ELF_S_COMPUTERNAME, ELF_S_IP, ELF_S_PORT, ELF_SC_STATUS,
- X_CONNECTION_ID, X_DATETIME, X_ETIME));
+ X_CONNECTION_ID, X_DATETIME, X_ETIME, X_TRANSACTION_ID));
/**
* Returns an instance of the text HTTP access log publisher that will print
@@ -440,6 +441,7 @@
fields.put(X_CONNECTION_ID, ri.getConnectionID());
fields.put(X_DATETIME, TimeThread.getUserDefinedTime(timeStampFormat));
fields.put(X_ETIME, ri.getTotalProcessingTime());
+ fields.put(X_TRANSACTION_ID, ri.getTransactionId());
writeLogRecord(fields, logFormatFields);
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CollectClientConnectionsFilter.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CollectClientConnectionsFilter.java
index 5ea8110..0cab816 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CollectClientConnectionsFilter.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CollectClientConnectionsFilter.java
@@ -61,6 +61,7 @@
import org.forgerock.util.promise.Promise;
import org.forgerock.util.promise.Promises;
import org.opends.server.admin.std.server.ConnectionHandlerCfg;
+import org.opends.server.core.ServerContext;
import org.opends.server.schema.SchemaConstants;
import org.opends.server.types.DisconnectReason;
import org.opends.server.util.Base64;
@@ -87,18 +88,22 @@
*/
private final HTTPAuthenticationConfig authConfig;
+ private final ServerContext serverContext;
+
/**
* Constructs a new instance of this class.
- *
+ * @param serverContext
+ * The server context.
* @param connectionHandler
* the connection handler that accepted this connection
* @param authenticationConfig
* configures how to perform the search for the username prior to
* authentication
*/
- public CollectClientConnectionsFilter(
- HTTPConnectionHandler connectionHandler, HTTPAuthenticationConfig authenticationConfig)
+ public CollectClientConnectionsFilter(ServerContext serverContext, HTTPConnectionHandler connectionHandler,
+ HTTPAuthenticationConfig authenticationConfig)
{
+ this.serverContext = serverContext;
this.connectionHandler = connectionHandler;
this.authConfig = authenticationConfig;
}
@@ -106,7 +111,8 @@
@Override
public Promise<Response, NeverThrowsException> filter(Context context, Request request, Handler next)
{
- final HTTPClientConnection clientConnection = new HTTPClientConnection(this.connectionHandler, context, request);
+ final HTTPClientConnection clientConnection =
+ new HTTPClientConnection(serverContext, this.connectionHandler, context, request);
connectionHandler.addClientConnection(clientConnection);
if (connectionHandler.keepStats())
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditTransactionIdFilter.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditTransactionIdFilter.java
new file mode 100644
index 0000000..ee7977d
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CommonAuditTransactionIdFilter.java
@@ -0,0 +1,86 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2015 ForgeRock AS
+ */
+package org.opends.server.protocols.http;
+
+import org.forgerock.http.Filter;
+import org.forgerock.http.Handler;
+import org.forgerock.http.header.MalformedHeaderException;
+import org.forgerock.http.header.TransactionIdHeader;
+import org.forgerock.http.protocol.Headers;
+import org.forgerock.http.protocol.Request;
+import org.forgerock.http.protocol.Response;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.services.TransactionId;
+import org.forgerock.services.context.Context;
+import org.forgerock.services.context.TransactionIdContext;
+import org.forgerock.util.promise.NeverThrowsException;
+import org.forgerock.util.promise.Promise;
+import org.opends.server.core.ServerContext;
+
+/**
+ * This filter is responsible for creating a {@link TransactionIdContext} in the
+ * context's chain.
+ * <p>
+ * This class is a copy of org.forgerock.http.filter.TransactionIdInboundFilter
+ * in CHF, modified to not use a system property to indicate if transaction id
+ * is trusted. Instead, it relies on DJ configuration to allow for runtime
+ * modification It would be better if TransactionIdInboundFilter class could be
+ * modified to be more generic and then usable by DJ, but it remains to be done.
+ */
+class CommonAuditTransactionIdFilter implements Filter
+{
+ private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+ private final ServerContext serverContext;
+
+ CommonAuditTransactionIdFilter(ServerContext serverContext)
+ {
+ this.serverContext = serverContext;
+ }
+
+ @Override
+ public Promise<Response, NeverThrowsException> filter(Context context, Request request, Handler next)
+ {
+ final TransactionId transactionId = serverContext.getCommonAudit().shouldTrustTransactionIds() ?
+ createTransactionId(request.getHeaders()) : new TransactionId();
+ final Context newContext = new TransactionIdContext(context, transactionId);
+ return next.handle(newContext, request);
+ }
+
+ private TransactionId createTransactionId(Headers headers)
+ {
+ try
+ {
+ TransactionIdHeader txHeader = headers.get(TransactionIdHeader.class);
+ return txHeader == null ? new TransactionId() : txHeader.getTransactionId();
+ }
+ catch (MalformedHeaderException ex)
+ {
+ logger.trace("The TransactionId header is malformed.", ex);
+ return new TransactionId();
+ }
+ }
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPClientConnection.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPClientConnection.java
index 83affaf..991d590 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPClientConnection.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPClientConnection.java
@@ -29,6 +29,7 @@
import static org.forgerock.opendj.adapter.server3x.Converters.getResponseResult;
import static org.forgerock.opendj.ldap.LdapException.newLdapException;
import static org.opends.messages.ProtocolMessages.WARN_CLIENT_DISCONNECT_IN_PROGRESS;
+import static org.opends.server.loggers.CommonAudit.DEFAULT_TRANSACTION_ID;
import static org.opends.server.loggers.AccessLogger.logDisconnect;
import java.net.InetAddress;
@@ -41,6 +42,8 @@
import java.util.concurrent.atomic.AtomicLong;
import org.forgerock.http.MutableUri;
+import org.forgerock.http.header.MalformedHeaderException;
+import org.forgerock.http.header.TransactionIdHeader;
import org.forgerock.http.protocol.Request;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
@@ -63,6 +66,7 @@
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.SearchOperation;
+import org.opends.server.core.ServerContext;
import org.opends.server.loggers.HTTPAccessLogger;
import org.opends.server.loggers.HTTPRequestInfo;
import org.opends.server.protocols.ldap.AddResponseProtocolOp;
@@ -122,7 +126,7 @@
}
}
- /** {@inheritDoc} */
+ /** Search Operation with a promise. */
private static final class SearchOperationWithPromise extends OperationWithPromise
{
@@ -243,15 +247,20 @@
/** Security-Strength Factor extracted from the request attribute. */
private final int securityStrengthFactor;
+ /** TransactionId for tracking of ForgeRock stack transactions. */
+ private final String transactionId;
+
/**
* Constructs an instance of this class.
- *
+ * @param serverContext
+ * The server context.
* @param connectionHandler
* the connection handler that accepted this connection
* @param context
* represents the context of this client connection.
*/
- public HTTPClientConnection(HTTPConnectionHandler connectionHandler, Context context, Request request)
+ public HTTPClientConnection(ServerContext serverContext, HTTPConnectionHandler connectionHandler, Context context,
+ Request request)
{
this.connectionHandler = connectionHandler;
final ClientContext clientCtx = context.asContext(ClientContext.class);
@@ -280,10 +289,27 @@
this.statTracker.updateConnect();
this.useNanoTime = DirectoryServer.getUseNanoTime();
}
-
+ this.transactionId = getTransactionId(serverContext, request);
this.connectionID = DirectoryServer.newConnectionAccepted(this);
}
+ private String getTransactionId(ServerContext serverContext, Request request)
+ {
+ if (serverContext.getCommonAudit().shouldTrustTransactionIds())
+ {
+ try
+ {
+ TransactionIdHeader txHeader = request.getHeaders().get(TransactionIdHeader.class);
+ return txHeader == null ? DEFAULT_TRANSACTION_ID : txHeader.getTransactionId().getValue();
+ }
+ catch (MalformedHeaderException e)
+ {
+ // ignore it
+ }
+ }
+ return DEFAULT_TRANSACTION_ID;
+ }
+
@Override
public String getAuthUser()
{
@@ -363,6 +389,12 @@
}
@Override
+ public String getTransactionId()
+ {
+ return transactionId;
+ }
+
+ @Override
public boolean isSecure()
{
return isSecure;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java
index 0dd19b6..f80fa63 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java
@@ -34,7 +34,6 @@
import org.forgerock.http.Handler;
import org.forgerock.http.HttpApplication;
import org.forgerock.http.HttpApplicationException;
-import org.forgerock.http.filter.TransactionIdInboundFilter;
import org.forgerock.http.handler.Handlers;
import org.forgerock.http.io.Buffer;
import org.forgerock.http.protocol.Request;
@@ -136,11 +135,12 @@
final Object jsonElems = Json.readJsonLenient(new FileReader(configFile));
final JsonValue configuration = new JsonValue(jsonElems).recordKeyAccesses();
handler = new LdapHttpHandler(configuration);
- filter = new CollectClientConnectionsFilter(connectionHandler, getAuthenticationConfig(configuration));
+ filter =
+ new CollectClientConnectionsFilter(serverContext, connectionHandler, getAuthenticationConfig(configuration));
configuration.verifyAllKeysAccessed();
- TransactionIdInboundFilter transactionIdFilter = new TransactionIdInboundFilter();
RequestHandler requestHandler = serverContext.getCommonAudit().getAuditServiceForHttpAccessLog();
+ CommonAuditTransactionIdFilter transactionIdFilter = new CommonAuditTransactionIdFilter(serverContext);
CommonAuditHttpAccessAuditFilter httpAccessFilter =
new CommonAuditHttpAccessAuditFilter(DynamicConstants.PRODUCT_NAME, requestHandler, TimeService.SYSTEM);
CommonAuditHttpAccessCheckEnabledFilter checkFilter =
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/monitors/BackendMonitorTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/monitors/BackendMonitorTestCase.java
index 3fb8b0d..1d60365 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/monitors/BackendMonitorTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/monitors/BackendMonitorTestCase.java
@@ -29,8 +29,10 @@
import org.opends.server.admin.std.server.MonitorProviderCfg;
import org.opends.server.api.MonitorProvider;
import org.opends.server.core.DirectoryServer;
+import org.testng.annotations.Test;
/** This class defines a set of tests for the {@link BackendMonitor} class. */
+@Test
public class BackendMonitorTestCase extends GenericMonitorTestCase
{
/**
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/protocols/http/CollectClientConnectionsFilterTest.java b/opendj-server-legacy/src/test/java/org/opends/server/protocols/http/CollectClientConnectionsFilterTest.java
index ad82137..7c5c758 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/protocols/http/CollectClientConnectionsFilterTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/protocols/http/CollectClientConnectionsFilterTest.java
@@ -25,6 +25,7 @@
*/
package org.opends.server.protocols.http;
+import static org.mockito.Mockito.mock;
import static org.assertj.core.api.Assertions.*;
import static org.opends.server.protocols.http.CollectClientConnectionsFilter.*;
@@ -35,6 +36,7 @@
import org.forgerock.http.protocol.Response;
import org.forgerock.json.resource.ResourceException;
import org.opends.server.DirectoryServerTestCase;
+import org.opends.server.core.ServerContext;
import org.opends.server.util.Base64;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
@@ -54,7 +56,7 @@
private void createConfigAndFilter()
{
authConfig = new HTTPAuthenticationConfig();
- filter = new CollectClientConnectionsFilter(null, authConfig);
+ filter = new CollectClientConnectionsFilter(mock(ServerContext.class), null, authConfig);
}
@DataProvider(name = "Invalid HTTP basic auth strings")
--
Gitblit v1.10.0