aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-auth-saml
diff options
context:
space:
mode:
authorSteve Marion <unknown>2023-04-07 10:43:20 +0200
committersonartech <sonartech@sonarsource.com>2023-04-11 20:03:15 +0000
commite81ae5d200c7662160090e9c104873d543a374a6 (patch)
tree739b334c056b24f839aac5ac4abdad1c299e002f /server/sonar-auth-saml
parent1138e4ce11520aba6ff42121d854d3fdd71c65ef (diff)
downloadsonarqube-e81ae5d200c7662160090e9c104873d543a374a6.tar.gz
sonarqube-e81ae5d200c7662160090e9c104873d543a374a6.zip
[SONAR-18809] replace hash by nonce for CSP headers
Diffstat (limited to 'server/sonar-auth-saml')
-rw-r--r--server/sonar-auth-saml/src/main/resources/samlAuthResult.html2
-rw-r--r--server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlAuthStatusPageGeneratorTest.java24
-rw-r--r--server/sonar-auth-saml/src/test/resources/samlAuthResultEmpty.html216
3 files changed, 5 insertions, 237 deletions
diff --git a/server/sonar-auth-saml/src/main/resources/samlAuthResult.html b/server/sonar-auth-saml/src/main/resources/samlAuthResult.html
index a49503aa659..c7cf2554b3a 100644
--- a/server/sonar-auth-saml/src/main/resources/samlAuthResult.html
+++ b/server/sonar-auth-saml/src/main/resources/samlAuthResult.html
@@ -116,7 +116,7 @@
<div id="response" data-response="%SAML_AUTHENTICATION_STATUS%"></div>
</div>
- <script>
+ <script nonce="%NONCE%">
window.addEventListener('DOMContentLoaded', (event) => {
function createBox() {
diff --git a/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlAuthStatusPageGeneratorTest.java b/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlAuthStatusPageGeneratorTest.java
index 440279c227b..9fd398321f2 100644
--- a/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlAuthStatusPageGeneratorTest.java
+++ b/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlAuthStatusPageGeneratorTest.java
@@ -19,25 +19,21 @@
*/
package org.sonar.auth.saml;
-import com.google.common.io.Resources;
-import java.io.IOException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import org.junit.Test;
-import static org.junit.Assert.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.auth.saml.SamlAuthStatusPageGenerator.getSamlAuthStatusHtml;
public class SamlAuthStatusPageGeneratorTest {
- private static final String EMPTY_HTML_TEMPLATE_NAME = "samlAuthResultEmpty.html";
+ private static final String EMPTY_DATA_RESPONSE = "eyJ3YXJuaW5ncyI6W10sImF2YWlsYWJsZUF0dHJpYnV0ZXMiOnt9LCJlcnJvcnMiOltdLCJtYXBwZWRBdHRyaWJ1dGVzIjp7fX0=";
@Test
- public void test_full_html_generation_with_empty_values() {
+ public void getSamlAuthStatusHtml_whenCalled_shouldGeneratePageWithData() {
SamlAuthenticationStatus samlAuthenticationStatus = mock(SamlAuthenticationStatus.class);
HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);
@@ -49,19 +45,7 @@ public class SamlAuthStatusPageGeneratorTest {
when(httpServletRequest.getContextPath()).thenReturn("context");
String completeHtmlTemplate = getSamlAuthStatusHtml(httpServletRequest, samlAuthenticationStatus);
- String expectedTemplate = loadTemplateFromResources(EMPTY_HTML_TEMPLATE_NAME);
- assertEquals(expectedTemplate, completeHtmlTemplate);
-
- }
-
- private String loadTemplateFromResources(String templateName) {
- URL url = Resources.getResource(templateName);
- try {
- return Resources.toString(url, StandardCharsets.UTF_8);
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
+ assertThat(completeHtmlTemplate).contains(EMPTY_DATA_RESPONSE);
}
-
}
diff --git a/server/sonar-auth-saml/src/test/resources/samlAuthResultEmpty.html b/server/sonar-auth-saml/src/test/resources/samlAuthResultEmpty.html
deleted file mode 100644
index b592d671155..00000000000
--- a/server/sonar-auth-saml/src/test/resources/samlAuthResultEmpty.html
+++ /dev/null
@@ -1,216 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta http-equiv="content-type" content="text/html; charset=UTF-8" charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <link rel="apple-touch-icon" href="context/apple-touch-icon.png" />
- <link rel="apple-touch-icon" sizes="57x57" href="context/apple-touch-icon-57x57.png" />
- <link rel="apple-touch-icon" sizes="60x60" href="context/apple-touch-icon-60x60.png" />
- <link rel="apple-touch-icon" sizes="72x72" href="context/apple-touch-icon-72x72.png" />
- <link rel="apple-touch-icon" sizes="76x76" href="context/apple-touch-icon-76x76.png" />
- <link
- rel="apple-touch-icon"
- sizes="114x114"
- href="context/apple-touch-icon-114x114.png"
- />
- <link
- rel="apple-touch-icon"
- sizes="120x120"
- href="context/apple-touch-icon-120x120.png"
- />
- <link
- rel="apple-touch-icon"
- sizes="144x144"
- href="context/apple-touch-icon-144x144.png"
- />
- <link
- rel="apple-touch-icon"
- sizes="152x152"
- href="context/apple-touch-icon-152x152.png"
- />
- <link
- rel="apple-touch-icon"
- sizes="180x180"
- href="context/apple-touch-icon-180x180.png"
- />
- <link rel="icon" type="image/x-icon" href="context/favicon.ico" />
- <meta name="application-name" content="SonarQube" />
- <meta name="msapplication-TileColor" content="#FFFFFF" />
- <meta name="msapplication-TileImage" content="context/mstile-512x512.png" />
- <title>SAML Authentication Test</title>
-
- <style>
- body {
- background-color: #f3f3f3;
- }
-
- h1 {
- margin: 0 8px 8px;
- }
- h2 {
- margin: 0 0 8px;
- }
-
- ul {
- list-style: none;
- margin: 0 8px;
- padding: 0;
- }
-
- li + li {
- padding-top: 12px;
- margin-top: 12px;
- border-top: 1px solid rgba(150, 150, 150, 0.5);
- }
-
- table {
- border-collapse: collapse;
- }
-
- tr:nth-child(2n) {
- background-color: #e6e6e6;
- }
-
- td {
- border: 1px solid #a3a3a3;
- padding: 4px 24px 4px 8px;
- vertical-align: top;
- font-family: "Courier New", Courier, monospace;
- white-space: pre-line;
- }
-
- #content {
- padding: 16px;
- }
-
- .box {
- padding: 8px;
- margin: 8px;
- border: 1px solid #e6e6e6;
- background-color: white;
- box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.5);
- }
-
- #status {
- padding: 16px 8px;
- font-size: large;
- color: white;
- }
-
- .error {
- background-color: #d02f3a;
- }
-
- .success {
- background-color: #008a25;
- }
- </style>
- </head>
-
- <body>
- <div id="content">
- <h1>SAML Authentication Test</h1>
- <div class="box">
- <div id="status"></div>
- </div>
- <div id="response" data-response="eyJ3YXJuaW5ncyI6W10sImF2YWlsYWJsZUF0dHJpYnV0ZXMiOnt9LCJlcnJvcnMiOltdLCJtYXBwZWRBdHRyaWJ1dGVzIjp7fX0="></div>
- </div>
-
- <script>
- window.addEventListener('DOMContentLoaded', (event) => {
-
- function createBox() {
- const box = document.createElement("div");
- box.className = "box";
- return box;
- }
-
- function createSectionTitle(title) {
- const node = document.createElement("h2");
- node.textContent = title;
- return node;
- }
-
- function createList(arr, className = "") {
- const list = document.createElement("ul");
-
- arr.forEach((item) => {
- const message = document.createElement("li");
- message.className = className;
- message.textContent = item;
- list.appendChild(message);
- });
-
- return list;
- }
-
- function createTable(obj) {
- const table = document.createElement("table");
- const tbody = document.createElement("tbody");
- table.appendChild(tbody);
-
- Object.keys(obj).forEach((key) => {
- const row = document.createElement("tr");
-
- const keyNode = document.createElement("td");
- keyNode.textContent = key;
- row.appendChild(keyNode);
-
- const valueNode = document.createElement("td");
- // wrap in array, to handle single values as well
- valueNode.textContent = [].concat(obj[key]).join("\r\n");
- row.appendChild(valueNode);
-
- tbody.appendChild(row);
- });
-
- return table;
- }
-
- function addSection(container, title, contents) {
- const box = createBox();
-
- box.appendChild(createSectionTitle(title));
- box.appendChild(contents);
-
- container.appendChild(box);
- }
-
- const variables = document.querySelector("#response");
- const response = variables.dataset.response;
- const decodedStatus = JSON.parse(atob(response));
- const status = decodedStatus.status;
- const attributes = decodedStatus.availableAttributes;
- const mappings = decodedStatus.mappedAttributes;
- const errors = decodedStatus.errors;
- const warnings = decodedStatus.warnings;
-
- // Switch status class
- const statusNode = document.querySelector("#status");
- statusNode.classList.add(status);
- statusNode.textContent = status;
-
- // generate content
- const container = document.querySelector("#content");
-
- if (warnings && warnings.length > 0) {
- addSection(container, "Warnings", createList(warnings));
- }
-
- if (status === "error" && errors && errors.length > 0) {
- addSection(container, "Errors", createList(errors));
- }
-
- if (status === "success") {
- if (attributes && Object.keys(attributes).length > 0) {
- addSection(container, "Available attributes", createTable(attributes));
- }
-
- if (mappings && Object.keys(mappings).length > 0) {
- addSection(container, "Attribute mappings", createTable(mappings));
- }
- }
- });
- </script>
- </body>
-</html>