diff options
author | Steve Marion <unknown> | 2023-04-07 10:43:20 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-04-11 20:03:15 +0000 |
commit | e81ae5d200c7662160090e9c104873d543a374a6 (patch) | |
tree | 739b334c056b24f839aac5ac4abdad1c299e002f /server/sonar-auth-saml | |
parent | 1138e4ce11520aba6ff42121d854d3fdd71c65ef (diff) | |
download | sonarqube-e81ae5d200c7662160090e9c104873d543a374a6.tar.gz sonarqube-e81ae5d200c7662160090e9c104873d543a374a6.zip |
[SONAR-18809] replace hash by nonce for CSP headers
Diffstat (limited to 'server/sonar-auth-saml')
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> |