From ccb7628524afd514bacfbec4922bcb8bfa02b49d Mon Sep 17 00:00:00 2001 From: Matteo Mara Date: Wed, 1 Nov 2023 17:32:04 +0100 Subject: [PATCH] SONAR-20920 Add details about signature and encryption on the SAML Test page --- .../auth/saml/SamlAuthenticationStatus.java | 20 ++++ .../sonar/auth/saml/SamlAuthenticator.java | 2 +- .../sonar/auth/saml/SamlStatusChecker.java | 28 ++++- .../src/main/resources/samlAuthResult.html | 36 +++++- .../saml/SamlAuthStatusPageGeneratorTest.java | 32 +++++- .../auth/saml/SamlStatusCheckerTest.java | 103 ++++++++++++++++-- 6 files changed, 203 insertions(+), 18 deletions(-) diff --git a/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticationStatus.java b/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticationStatus.java index cb503d83f32..7ed5335d13d 100644 --- a/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticationStatus.java +++ b/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticationStatus.java @@ -37,6 +37,10 @@ public class SamlAuthenticationStatus { private List warnings = new ArrayList<>(); + private boolean encryptionEnabled = false; + + private boolean signatureEnabled = false; + public String getStatus() { return status; } @@ -76,4 +80,20 @@ public class SamlAuthenticationStatus { public void setWarnings(List warnings) { this.warnings = warnings; } + + public boolean isEncryptionEnabled() { + return encryptionEnabled; + } + + public void setEncryptionEnabled(boolean encryptionEnabled) { + this.encryptionEnabled = encryptionEnabled; + } + + public boolean isSignatureEnabled() { + return signatureEnabled; + } + + public void setSignatureEnabled(boolean signatureEnabled) { + this.signatureEnabled = signatureEnabled; + } } diff --git a/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticator.java b/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticator.java index 0504d35e961..f2917ebe24a 100644 --- a/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticator.java +++ b/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlAuthenticator.java @@ -224,7 +224,7 @@ public class SamlAuthenticator { public String getAuthenticationStatusPage(HttpRequest request, HttpResponse response) { try { Auth auth = initSamlAuth(request, response); - return getSamlAuthStatusHtml(request, getSamlAuthenticationStatus(auth, samlSettings)); + return getSamlAuthStatusHtml(request, getSamlAuthenticationStatus(request.getParameter("SAMLResponse"), auth, samlSettings)); } catch (IllegalStateException e) { return getSamlAuthStatusHtml(request, getSamlAuthenticationStatus(String.format("%s due to: %s", e.getMessage(), e.getCause().getMessage()))); } diff --git a/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlStatusChecker.java b/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlStatusChecker.java index ec96d2aaa0b..fe32cb6c705 100644 --- a/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlStatusChecker.java +++ b/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlStatusChecker.java @@ -20,13 +20,18 @@ package org.sonar.auth.saml; import com.onelogin.saml2.Auth; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Base64; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; import static org.sonar.auth.saml.SamlSettings.GROUP_NAME_ATTRIBUTE; import static org.sonar.auth.saml.SamlSettings.USER_EMAIL_ATTRIBUTE; @@ -35,11 +40,13 @@ import static org.sonar.auth.saml.SamlSettings.USER_NAME_ATTRIBUTE; public final class SamlStatusChecker { + private static final Pattern encryptedAssertionPattern = Pattern.compile("()); samlAuthenticationStatus.setStatus(samlAuthenticationStatus.getErrors().isEmpty() ? "success" : "error"); @@ -136,4 +146,20 @@ public final class SamlStatusChecker { .map(entry -> String.format("Mapping found for the property %s, but the field %s is empty in the SAML response.", entry.getKey(), entry.getValue())) .toList(); } + + private static boolean isSignatureEnabled(Auth auth, SamlSettings samlSettings) { + return auth.isAuthenticated() && samlSettings.isSignRequestsEnabled(); + } + + private static boolean isEncryptionEnabled(Auth auth, @Nullable String samlResponse) { + if (samlResponse != null) { + byte[] decoded = Base64.getDecoder().decode(samlResponse); + String decodedResponse = new String(decoded, StandardCharsets.UTF_8); + Matcher matcher = encryptedAssertionPattern.matcher(decodedResponse); + //We assume that the presence of an encrypted assertion means that the response is encrypted + return matcher.find() && auth.isAuthenticated(); + } + return false; + } + } diff --git a/server/sonar-auth-saml/src/main/resources/samlAuthResult.html b/server/sonar-auth-saml/src/main/resources/samlAuthResult.html index c7cf2554b3a..bff1c9ef20d 100644 --- a/server/sonar-auth-saml/src/main/resources/samlAuthResult.html +++ b/server/sonar-auth-saml/src/main/resources/samlAuthResult.html @@ -42,6 +42,7 @@ @@ -131,6 +145,21 @@ return node; } + function createEnabledLabel() { + const node = document.createElement("p"); + node.innerHTML = 'Enabled'; + node.classList.add("success-label"); + node.classList.add("label"); + return node; + } + + function createDisabledLabel() { + const node = document.createElement("p"); + node.textContent = "Disabled"; + node.classList.add("label"); + return node; + } + function createList(arr, className = "") { const list = document.createElement("ul"); @@ -184,6 +213,8 @@ const mappings = decodedStatus.mappedAttributes; const errors = decodedStatus.errors; const warnings = decodedStatus.warnings; + const signatureEnabled = decodedStatus.signatureEnabled; + const encryptionEnabled = decodedStatus.encryptionEnabled; // Switch status class const statusNode = document.querySelector("#status"); @@ -209,6 +240,9 @@ if (mappings && Object.keys(mappings).length > 0) { addSection(container, "Attribute mappings", createTable(mappings)); } + + addSection(container, "Signature of SAML requests", signatureEnabled ? createEnabledLabel() : createDisabledLabel()); + addSection(container, "Encryption of SAML assertions", encryptionEnabled ? createEnabledLabel() : createDisabledLabel()); } }); 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 2f84a89a6d7..56e867ae072 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,8 +19,12 @@ */ package org.sonar.auth.saml; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Base64; import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.junit.Test; import org.sonar.api.server.http.HttpRequest; @@ -30,22 +34,42 @@ import static org.mockito.Mockito.when; import static org.sonar.auth.saml.SamlAuthStatusPageGenerator.getSamlAuthStatusHtml; public class SamlAuthStatusPageGeneratorTest { - private static final String EMPTY_DATA_RESPONSE = "eyJ3YXJuaW5ncyI6W10sImF2YWlsYWJsZUF0dHJpYnV0ZXMiOnt9LCJlcnJvcnMiOltdLCJtYXBwZWRBdHRyaWJ1dGVzIjp7fX0="; @Test public void getSamlAuthStatusHtml_whenCalled_shouldGeneratePageWithData() { SamlAuthenticationStatus samlAuthenticationStatus = mock(SamlAuthenticationStatus.class); HttpRequest request = mock(HttpRequest.class); - when(samlAuthenticationStatus.getStatus()).thenReturn(null); + when(samlAuthenticationStatus.getStatus()).thenReturn("success"); when(samlAuthenticationStatus.getErrors()).thenReturn(new ArrayList<>()); when(samlAuthenticationStatus.getWarnings()).thenReturn(new ArrayList<>()); when(samlAuthenticationStatus.getAvailableAttributes()).thenReturn(new HashMap<>()); when(samlAuthenticationStatus.getMappedAttributes()).thenReturn(new HashMap<>()); + when(samlAuthenticationStatus.isEncryptionEnabled()).thenReturn(false); + when(samlAuthenticationStatus.isSignatureEnabled()).thenReturn(false); when(request.getContextPath()).thenReturn("context"); - String completeHtmlTemplate = getSamlAuthStatusHtml(request, samlAuthenticationStatus); + String decodedDataResponse = getDecodedDataResponse(getSamlAuthStatusHtml(request, samlAuthenticationStatus)); - assertThat(completeHtmlTemplate).contains(EMPTY_DATA_RESPONSE); + assertThat(decodedDataResponse).contains( + "\"encryptionEnabled\":false", + "\"signatureEnabled\":false", + "\"errors\":[]", + "\"warnings\":[]", + "\"status\":\"success\"", + "\"availableAttributes\":{}", + "\"mappedAttributes\":{}"); + } + + private static String getDecodedDataResponse(String completeHtmlTemplate) { + String pattern = "data-response=\"([^\"]+)\""; + Pattern regex = Pattern.compile(pattern); + Matcher matcher = regex.matcher(completeHtmlTemplate); + if (matcher.find()) { + String dataResponseValue = matcher.group(1); + byte[] decoded = Base64.getDecoder().decode(dataResponseValue); + return new String(decoded, StandardCharsets.UTF_8); + } + return ""; } } diff --git a/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlStatusCheckerTest.java b/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlStatusCheckerTest.java index 74c93afe70b..a183e25a942 100644 --- a/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlStatusCheckerTest.java +++ b/server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlStatusCheckerTest.java @@ -21,7 +21,9 @@ package org.sonar.auth.saml; import com.onelogin.saml2.Auth; import com.onelogin.saml2.settings.Saml2Settings; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Base64; import java.util.Collections; import java.util.List; import java.util.Map; @@ -47,9 +49,26 @@ import static org.sonar.auth.saml.SamlStatusChecker.getSamlAuthenticationStatus; public class SamlStatusCheckerTest { private static final String IDP_CERTIFICATE = "-----BEGIN CERTIFICATE-----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-----END CERTIFICATE-----"; - private static final String SP_CERTIFICATE = "MIICoTCCAYkCBgGBXPscaDANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlzb25hcnF1YmUwHhcNMjIwNjEzMTIxMTA5WhcNMzIwNjEzMTIxMjQ5WjAUMRIwEAYDVQQDDAlzb25hcnF1YmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSFoT371C0/klZuPgvKbGItkmTaf5CweNXL8u389d98aOXRpDQ7maTXdV/W+VcL8vUWg8yG6nn8CRwweYnGTNdn9UAdhgknvxQe3pq3EwOJyls4Fpiq6YTh+DQfiZUQizjFjDOr/GG5O2lNvTRkI4XZj/XnWjRqVZwttiA5tm1sKkvGdyOQljwn4Jja/VbITdV8GASumx66Bil/wamSsqIzm2RjsOOGSsf5VjYUPwDobpuSf+j4DLtWjem/9vIzI2wcE30uC8LBAgO3JAlIS9NQrchjS9xhMJRohOoitaSPmqsOy7D2BH0h7XX6TNgv/WYTkBY4eZPao3PsL2A6AmhAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAMBmTHUK4w+DX21tmhqdwq0WqLH5ZAkwtiocDxFXiJ4GRrUWUh3BaXsgOHB8YYnNTDfScjaU0sZMEyfC0su1zsN8B7NFckg7RcZCHuBYdgIEAmvK4YM6s6zNsiKKwt66p2MNeL+o0acrT2rYjQ1L5QDj0gpfJQAT4N7xTZfuSc2iwjotaQfvcgsO8EZlcDVrL4UuyWLbuRUlSQjxHWGYaxCW+I3enK1+8fGpF3O+k9ZQ8xt5nJsalpsZvHcPLA4IBOmjsSHqSkhg4EIAWL/sJZ1KNct4hHh5kToUTu+Q6e949VeBkWgj4O+rcGDgiN2frGiEEc0EMv8KCSENRRRrO2k="; private static final String SP_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDSFoT371C0/klZuPgvKbGItkmTaf5CweNXL8u389d98aOXRpDQ7maTXdV/W+VcL8vUWg8yG6nn8CRwweYnGTNdn9UAdhgknvxQe3pq3EwOJyls4Fpiq6YTh+DQfiZUQizjFjDOr/GG5O2lNvTRkI4XZj/XnWjRqVZwttiA5tm1sKkvGdyOQljwn4Jja/VbITdV8GASumx66Bil/wamSsqIzm2RjsOOGSsf5VjYUPwDobpuSf+j4DLtWjem/9vIzI2wcE30uC8LBAgO3JAlIS9NQrchjS9xhMJRohOoitaSPmqsOy7D2BH0h7XX6TNgv/WYTkBY4eZPao3PsL2A6AmhAgMBAAECggEBAJj11HJAR96/leBBkFGmZaBIOGGgNoOcb023evfADhGgsZ8evamhKgX5t8w2uFPaaOl/eLje82Hvslh2lH+7FW8BRDBFy2Y+ay6d+I99PdLAKKUg5C4bE5v8vm6OqpGGbPAZ5AdYit3QKEa2MKG0QgA/bhQqg3rDdDA0sIWJjtF9MLv7LI7Tm0qgiHOKsI0MEBFk+ZoibgKWYh/dnfGDRWyC3Puqe13rdSheNJYUDR/0QMkd/EJNpLWv06uk+w8w2lU4RgN6TiV76ZZUIGZAAHFgMELJysgtBTCkOQY5roPu17OmMZjKfxngeIfNyd42q3/T6DmUbbwNYfP2HRMoiMECgYEA6SVc1mZ4ykytC9M61rZwT+2zXtJKudQVa0qpTtkf0aznRmnDOuc1bL7ewKIIIp9r5HKVteO6SKgpHmrP+qmvbwZ0Pz51Zg0MetoSmT9m0599/tOU2k6OI09dvQ4Xa3ccN5Czl61Q/HkMeAIDny8MrhGVBwhallE4J4fm/OjuVK0CgYEA5q6IVgqZtfcV1azIF6uOFt6blfn142zrwq0fF39jog2f+4jXaBKw6L4aP0HvIL83UArGppYY31894bLb6YL4EjS2JNbABM2VnJpJd4oGopOE42GCZlZRpf751zOptYAN23NFSujLlfaUfMbyrqIbRFC2DCdzNTU50GT5SAXX80UCgYEAlyvQvHwJCjMZaTd3SU1WGZ1o1qzIIyHvGXh5u1Rxm0TfWPquyfys2WwRhxoI6FoyXRgnFp8oZIAU2VIstL1dsUGgEnnvKVKAqw/HS3Keu80IpziNpdeVtjN59mGysc2zkBvVNx38Cxh6Cz5TFt4s/JkN5ld2VU0oeglWrtph3qkCgYALszZ/BrKdJBcba1QKv0zJpCjIBpGOI2whx54YFwH6qi4/F8W1JZ2LcHjsVG/IfWpUyPciY+KHEdGVrPiyc04Zvkquu6WpmLPJ6ZloUrvbaxgGYF+4yRADF1ecrqYg6onJY6NUFVKeHI+TdJPCf75aTK2vGCEjxbtU8ooiOQmm8QKBgEGe9ZdrwTP9rMQ35jYtzU+dT06k1r9BE9Q8CmrXl0HwK717ZWboX4J0YoFjxZC8PDsMl3p46MJ83rKbLU728uKig1AkZo7/OedxTWvezjZ1+lDyjC2EguXbgY1ecSC2HbJh9g+v8RUuhWxuA7RYoW92xVtKj+6l4vMadVP4Myp8-----END PRIVATE KEY-----"; + public static final String ENCRYPTED_SAML_RESPONSE = """ + + Assertion Very Encrypted + + + """; + public static final String PLAIN_SAML_RESPONSE = """ + + + + """; + public static final String BASE64_ENCRYPTED_SAML_RESPONSE = new String(Base64.getEncoder().encode(ENCRYPTED_SAML_RESPONSE.getBytes()), StandardCharsets.UTF_8); + public static final String BASE64_SAML_RESPONSE = new String(Base64.getEncoder().encode(PLAIN_SAML_RESPONSE.getBytes()), StandardCharsets.UTF_8); private final MapSettings settings = new MapSettings(new PropertyDefinitions(System2.INSTANCE, SamlSettings.definitions())); @@ -66,7 +85,6 @@ public class SamlStatusCheckerTest { @Test public void authentication_status_has_errors_when_no_idp_certificate_is_provided() { - samlAuthenticationStatus = getSamlAuthenticationStatus("error message"); assertEquals("error", samlAuthenticationStatus.getStatus()); @@ -80,7 +98,7 @@ public class SamlStatusCheckerTest { getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value)); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("success", samlAuthenticationStatus.getStatus()); assertTrue(samlAuthenticationStatus.getErrors().isEmpty()); @@ -93,7 +111,7 @@ public class SamlStatusCheckerTest { when(auth.getLastErrorReason()).thenReturn("Authentication failed due to a missing parameter."); when(auth.getAttributes()).thenReturn(getEmptyAttributes()); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("error", samlAuthenticationStatus.getStatus()); assertFalse(samlAuthenticationStatus.getErrors().isEmpty()); @@ -112,7 +130,7 @@ public class SamlStatusCheckerTest { } when(auth.getAttributes()).thenReturn(getEmptyAttributes()); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("error", samlAuthenticationStatus.getStatus()); assertFalse(samlAuthenticationStatus.getErrors().isEmpty()); @@ -129,7 +147,7 @@ public class SamlStatusCheckerTest { getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value)); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("success", samlAuthenticationStatus.getStatus()); assertTrue(samlAuthenticationStatus.getErrors().isEmpty()); @@ -147,7 +165,7 @@ public class SamlStatusCheckerTest { settings.setProperty(USER_NAME_ATTRIBUTE, "wrongNameField"); getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value)); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("error", samlAuthenticationStatus.getStatus()); assertTrue(samlAuthenticationStatus.getWarnings().isEmpty()); @@ -164,7 +182,7 @@ public class SamlStatusCheckerTest { when(auth.getAttributes()).thenReturn(getEmptyAttributes()); getEmptyAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value)); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("error", samlAuthenticationStatus.getStatus()); assertTrue(samlAuthenticationStatus.getWarnings().isEmpty()); @@ -183,7 +201,7 @@ public class SamlStatusCheckerTest { settings.setProperty(GROUP_NAME_ATTRIBUTE, (String) null); getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value)); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("success", samlAuthenticationStatus.getStatus()); assertTrue(samlAuthenticationStatus.getErrors().isEmpty()); @@ -195,7 +213,7 @@ public class SamlStatusCheckerTest { setSettings(); getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value)); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("success", samlAuthenticationStatus.getStatus()); assertTrue(samlAuthenticationStatus.getErrors().isEmpty()); @@ -210,7 +228,7 @@ public class SamlStatusCheckerTest { settings.setProperty("sonar.auth.saml.sp.privateKey.secured", (String) null); getResponseAttributes().forEach((key, value) -> when(auth.getAttribute(key)).thenReturn(value)); - samlAuthenticationStatus = getSamlAuthenticationStatus(auth, new SamlSettings(settings.asConfig())); + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); assertEquals("success", samlAuthenticationStatus.getStatus()); assertTrue(samlAuthenticationStatus.getErrors().isEmpty()); @@ -222,6 +240,69 @@ public class SamlStatusCheckerTest { assertTrue(samlAuthenticationStatus.getMappedAttributes().keySet().containsAll(Set.of("User login value", "User name value", "User email value", "Groups value"))); } + @Test + public void givenSignatureEnabled_whenUserIsAuthenticated_thenSamlStatusReportsItEnabled() { + setSettings(); + settings.setProperty("sonar.auth.saml.signature.enabled", true); + when(auth.isAuthenticated()).thenReturn(true); + + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); + + assertTrue(samlAuthenticationStatus.isSignatureEnabled()); + } + + @Test + public void givenSignatureDisabled_whenUserIsAuthenticated_thenSamlStatusReportsItDisabled() { + setSettings(); + settings.setProperty("sonar.auth.saml.signature.enabled", false); + when(auth.isAuthenticated()).thenReturn(true); + + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); + + assertFalse(samlAuthenticationStatus.isSignatureEnabled()); + } + + @Test + public void givenEncryptionEnabled_whenUserIsAuthenticated_thenSamlStatusReportsItEnabled() { + setSettings(); + when(auth.isAuthenticated()).thenReturn(true); + + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_ENCRYPTED_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); + + assertTrue(samlAuthenticationStatus.isEncryptionEnabled()); + } + + @Test + public void givenEncryptionDisabled_whenUserIsAuthenticated_thenSamlStatusReportsItDisabled() { + setSettings(); + when(auth.isAuthenticated()).thenReturn(true); + + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); + + assertFalse(samlAuthenticationStatus.isEncryptionEnabled()); + } + + @Test + public void whenUserIsNotAuthenticated_thenBothSignatureAndEncryptionAreReportedDisabled() { + setSettings(); + when(auth.isAuthenticated()).thenReturn(false); + settings.setProperty("sonar.auth.saml.signature.enabled", true); + + samlAuthenticationStatus = getSamlAuthenticationStatus(BASE64_ENCRYPTED_SAML_RESPONSE, auth, new SamlSettings(settings.asConfig())); + + assertFalse(samlAuthenticationStatus.isEncryptionEnabled()); + assertFalse(samlAuthenticationStatus.isSignatureEnabled()); + } + + @Test + public void whenSamlResponseIsNull_thenEncryptionIsReportedDisabled() { + setSettings(); + + samlAuthenticationStatus = getSamlAuthenticationStatus(null, auth, new SamlSettings(settings.asConfig())); + + assertFalse(samlAuthenticationStatus.isEncryptionEnabled()); + } + private void setSettings() { settings.setProperty("sonar.auth.saml.applicationId", "MyApp"); settings.setProperty("sonar.auth.saml.providerId", "http://localhost:8080/auth/realms/sonarqube"); -- 2.39.5