|
359 | 359 | import java.net.URI; |
360 | 360 | import java.net.URISyntaxException; |
361 | 361 | import java.net.URL; |
| 362 | +import java.net.http.HttpClient; |
| 363 | +import java.net.http.HttpRequest; |
| 364 | +import java.net.http.HttpResponse; |
362 | 365 | import java.nio.file.Files; |
363 | 366 | import java.nio.file.Path; |
364 | 367 | import java.nio.file.Paths; |
365 | 368 | import java.sql.SQLException; |
366 | 369 | import java.text.DecimalFormat; |
| 370 | +import java.time.Duration; |
367 | 371 | import java.util.ArrayList; |
368 | 372 | import java.util.Arrays; |
369 | 373 | import java.util.Collection; |
@@ -11960,6 +11964,13 @@ public void addNavTrail(NavTree root) |
11960 | 11964 | } |
11961 | 11965 | } |
11962 | 11966 |
|
| 11967 | + private static final URI LABKEY_ORG_REPORT_ACTION; |
| 11968 | + |
| 11969 | + static |
| 11970 | + { |
| 11971 | + LABKEY_ORG_REPORT_ACTION = URI.create("https://www.labkey.org/admin-contentSecurityPolicyReport.api"); |
| 11972 | + } |
| 11973 | + |
11963 | 11974 | @RequiresNoPermission |
11964 | 11975 | @CSRF(CSRF.Method.NONE) |
11965 | 11976 | public static class ContentSecurityPolicyReportAction extends ReadOnlyApiAction<SimpleApiJsonForm> |
@@ -11995,19 +12006,64 @@ public Object execute(SimpleApiJsonForm form, BindException errors) throws Excep |
11995 | 12006 | String urlString = cspReport.optString("document-uri", null); |
11996 | 12007 | if (urlString != null) |
11997 | 12008 | { |
11998 | | - String path = new URLHelper(urlString).deleteParameters().getPath(); |
| 12009 | + String path = new URLHelper(urlString).deleteParameters().getURIString(); |
11999 | 12010 | if (null == reports.put(path, Boolean.TRUE) || _log.isDebugEnabled()) |
12000 | 12011 | { |
12001 | | - if (isNotBlank(userAgent)) |
12002 | | - jsonObj.put("user-agent", userAgent); |
12003 | | - String labkeyVersion = request.getParameter("labkeyVersion"); |
12004 | | - if (null != labkeyVersion) |
12005 | | - jsonObj.put("labkeyVersion", labkeyVersion); |
12006 | | - String cspVersion = request.getParameter("cspVersion"); |
12007 | | - if (null != cspVersion) |
12008 | | - jsonObj.put("cspVersion", cspVersion); |
| 12012 | + // Don't modify forwarded reports; they already have user, ip, user-agent, etc. from the forwarding server. |
| 12013 | + boolean forwarded = jsonObj.optBoolean("forwarded", false); |
| 12014 | + if (!forwarded) |
| 12015 | + { |
| 12016 | + jsonObj.put("user", getUser().getEmail()); |
| 12017 | + String ipAddress = request.getHeader("X-FORWARDED-FOR"); |
| 12018 | + if (ipAddress == null) |
| 12019 | + ipAddress = request.getRemoteAddr(); |
| 12020 | + jsonObj.put("ip", ipAddress); |
| 12021 | + if (isNotBlank(userAgent)) |
| 12022 | + jsonObj.put("user-agent", userAgent); |
| 12023 | + String labkeyVersion = request.getParameter("labkeyVersion"); |
| 12024 | + if (null != labkeyVersion) |
| 12025 | + jsonObj.put("labkeyVersion", labkeyVersion); |
| 12026 | + String cspVersion = request.getParameter("cspVersion"); |
| 12027 | + if (null != cspVersion) |
| 12028 | + jsonObj.put("cspVersion", cspVersion); |
| 12029 | + } |
| 12030 | + |
12009 | 12031 | var jsonStr = jsonObj.toString(2); |
12010 | | - _log.warn("ContentSecurityPolicy warning on page: " + urlString + "\n" + jsonStr); |
| 12032 | + _log.warn("ContentSecurityPolicy warning on page: {}\n{}", urlString, jsonStr); |
| 12033 | + |
| 12034 | + if (!forwarded && OptionalFeatureService.get().isFeatureEnabled(ContentSecurityPolicyFilter.FEATURE_FLAG_FORWARD_CSP_REPORTS)) |
| 12035 | + { |
| 12036 | + jsonObj.put("forwarded", true); |
| 12037 | + |
| 12038 | + // Create an HttpClient |
| 12039 | + HttpClient client = HttpClient.newBuilder() |
| 12040 | + .connectTimeout(Duration.ofSeconds(10)) |
| 12041 | + .build(); |
| 12042 | + |
| 12043 | + // Create the POST request |
| 12044 | + HttpRequest remoteRequest = HttpRequest.newBuilder() |
| 12045 | + .uri(LABKEY_ORG_REPORT_ACTION) |
| 12046 | + .header("Content-Type", request.getContentType()) // Use whatever the browser set |
| 12047 | + .POST(HttpRequest.BodyPublishers.ofString(jsonObj.toString(2))) |
| 12048 | + .build(); |
| 12049 | + |
| 12050 | + // Send the request and get the response |
| 12051 | + HttpResponse<String> response = client.send(remoteRequest, HttpResponse.BodyHandlers.ofString()); |
| 12052 | + |
| 12053 | + if (response.statusCode() != 200) |
| 12054 | + { |
| 12055 | + _log.error("ContentSecurityPolicy report forwarding to https://www.labkey.org failed: {}\n{}", response.statusCode(), response.body()); |
| 12056 | + } |
| 12057 | + else |
| 12058 | + { |
| 12059 | + JSONObject jsonResponse = new JSONObject(response.body()); |
| 12060 | + boolean success = jsonResponse.optBoolean("success", false); |
| 12061 | + if (!success) |
| 12062 | + { |
| 12063 | + _log.error("ContentSecurityPolicy report forwarding to https://www.labkey.org failed: {}", jsonResponse); |
| 12064 | + } |
| 12065 | + } |
| 12066 | + } |
12011 | 12067 | } |
12012 | 12068 | } |
12013 | 12069 | } |
|
0 commit comments