From cd901b922fc4eaa6c35537adaa4a8bcb83e2464d Mon Sep 17 00:00:00 2001
From: DenisSinelnikov <142215442+DenisSinelnikov@users.noreply.github.com>
Date: Thu, 21 Nov 2024 19:52:42 +0400
Subject: [PATCH] Cb 5584 provide more information in the debug log for
auditing (#3061)
* CB-5584. Added more logs for gql and rest in RM. Added new parameter in global preferences for showing additional logs
* CB-5584. Added more logs for gql and rest in RM. Added new parameter in global preferences for showing additional logs
* CB-5584. Rename parameter
* CB-5584. Rename parameter
* CB-5584. Refactor after review
* CB-5584. Refactor after review
* CB-5584. Renamed parameter
* CB-5584. Added check variable for contains restricted variable
* CB-5584. Fixed showing wrong sessionId.
---------
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
---
.../bundles/io.cloudbeaver.server/plugin.xml | 8 ++
.../server/graphql/GraphQLEndpoint.java | 13 ++-
.../server/graphql/GraphQLLoggerUtil.java | 102 ++++++++++++++++++
3 files changed, 116 insertions(+), 7 deletions(-)
create mode 100644 server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLLoggerUtil.java
diff --git a/server/bundles/io.cloudbeaver.server/plugin.xml b/server/bundles/io.cloudbeaver.server/plugin.xml
index 73656b40b7..9259eddd80 100644
--- a/server/bundles/io.cloudbeaver.server/plugin.xml
+++ b/server/bundles/io.cloudbeaver.server/plugin.xml
@@ -75,4 +75,12 @@
+
+
+
+
+
+
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java
index 15506f79dd..d47612147b 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java
@@ -51,10 +51,7 @@
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.CompletableFuture;
public class GraphQLEndpoint extends HttpServlet {
@@ -68,7 +65,6 @@ public class GraphQLEndpoint extends HttpServlet {
private static final String HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
private static final String CORE_SCHEMA_FILE_NAME = "schema/schema.graphqls";
-
private final GraphQL graphQL;
private static final Gson gson = new GsonBuilder()
@@ -253,10 +249,13 @@ private void executeQuery(HttpServletRequest request, HttpServletResponse respon
// apiCall += " (" + variables + ")";
// }
// }
+ String sessionId = GraphQLLoggerUtil.getSessionId(request);
+ String userId = GraphQLLoggerUtil.getUserId(request);
+ String loggerMessage = GraphQLLoggerUtil.buildLoggerMessage(sessionId, userId, variables);
if (apiCall != null) {
- log.debug("API > " + apiCall);
+ log.debug("API > " + apiCall + loggerMessage);
} else if (DEBUG) {
- log.debug("API > " + query);
+ log.debug("API > " + query + loggerMessage);
}
}
ExecutionInput executionInput = contextBuilder.build();
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLLoggerUtil.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLLoggerUtil.java
new file mode 100644
index 0000000000..b42e1f28d9
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLLoggerUtil.java
@@ -0,0 +1,102 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2024 DBeaver Corp and others
+ *
+ * Licensed 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 io.cloudbeaver.server.graphql;
+
+import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.server.CBApplication;
+import io.cloudbeaver.server.CBPlatform;
+import jakarta.servlet.http.HttpServletRequest;
+import org.jkiss.utils.CommonUtils;
+
+import java.util.Map;
+import java.util.Set;
+
+public class GraphQLLoggerUtil {
+
+ public static final String LOG_API_GRAPHQL_DEBUG_PARAMETER = "log.api.graphql.debug";
+ private static final Set PROHIBITED_VARIABLES =
+ Set.of("password", "config", "parameters", "settings", "licenseText", "credentials", "username");
+
+ public static String getUserId(HttpServletRequest request) {
+ WebSession session = getWebSession(request);
+ if (session == null) {
+ return null;
+ }
+ String userId = session.getUserContext().getUserId();
+ if (userId == null && session.getUserContext().isAuthorizedInSecurityManager()) {
+ return "anonymous";
+ }
+ return userId;
+ }
+
+ public static String getSessionId(HttpServletRequest request) {
+ WebSession session = getWebSession(request);
+ if (session == null) {
+ return null;
+ }
+ return session.getUserContext().getSmSessionId();
+ }
+
+ private static WebSession getWebSession(HttpServletRequest request) {
+ if (request.getSession() == null) {
+ return null;
+ }
+ return (WebSession) CBApplication.getInstance()
+ .getSessionManager()
+ .getSession(request.getSession().getId());
+ }
+
+ public static String buildLoggerMessage(String sessionId, String userId, Map variables) {
+ StringBuilder loggerMessage = new StringBuilder(" [user: ").append(userId)
+ .append(", sessionId: ").append(sessionId).append("]");
+
+ if (CBPlatform.getInstance().getPreferenceStore().getBoolean(LOG_API_GRAPHQL_DEBUG_PARAMETER)
+ && variables != null
+ ) {
+ loggerMessage.append(" [variables] ");
+ String parsedVariables = parseVarialbes(variables);
+ if (CommonUtils.isNotEmpty(parsedVariables)) {
+ loggerMessage.append(parseVarialbes(variables));
+ }
+ }
+ return loggerMessage.toString();
+ }
+
+ private static String parseVarialbes(Map map) {
+ StringBuilder result = new StringBuilder();
+
+ for (Map.Entry entry : map.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+
+ boolean isProhibited = PROHIBITED_VARIABLES.stream()
+ .anyMatch(prohibitedKey -> key.toLowerCase().contains(prohibitedKey.toLowerCase()));
+
+ if (isProhibited) {
+ result.append(key).append(": ").append("******** ");
+ continue;
+ }
+
+ if (value instanceof Map) {
+ result.append(parseVarialbes((Map) value));
+ } else {
+ result.append(key).append(": ").append(value).append(" ");
+ }
+ }
+ return result.toString().trim();
+ }
+}