diff --git a/smp-parent-pom/pom.xml b/smp-parent-pom/pom.xml index 84dbbc31682f27c4af7581a8a94b4ff3643589b8..0124d36eacc751718f5b00540cf3ca18577b3416 100644 --- a/smp-parent-pom/pom.xml +++ b/smp-parent-pom/pom.xml @@ -50,8 +50,8 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <slf4j.version>1.7.26</slf4j.version> - <spring.version>5.1.9.RELEASE</spring.version> - <spring.security.version>5.1.6.RELEASE</spring.security.version> + <spring.version>5.3.9</spring.version> + <spring.security.version>5.5.2</spring.security.version> <spring.boot.version>2.1.8.RELEASE</spring.boot.version> <!-- bdmsl.client.version>3.0.0</bdmsl.client.version --> <bdmsl.api.version>4.0.0</bdmsl.api.version> diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java index e827e0dd8d5283901dc24ce7d0d415cfa9b828a3..07b824c9e61b1eae53c8a80b46cde9fa62163aa4 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java @@ -28,15 +28,12 @@ public enum SMPPropertyEnum { SML_LOGICAL_ADDRESS("bdmsl.integration.logical.address","http://localhost:8080/smp/","Logical SMP endpoint which will be registered on SML when registering new domain", false, false , SMPPropertyTypeEnum.URL), SML_PHYSICAL_ADDRESS("bdmsl.integration.physical.address","0.0.0.0","Physical SMP endpoint which will be registered on SML when registering new domain.", false, false , SMPPropertyTypeEnum.STRING), - - HTTP_PROXY_HOST("smp.proxy.host", "", "The http proxy host", false,false, SMPPropertyTypeEnum.STRING), HTTP_NO_PROXY_HOSTS("smp.noproxy.hosts", "localhost|127.0.0.1", "list of nor proxy hosts. Ex.: localhost|127.0.0.1", false,false, SMPPropertyTypeEnum.STRING), HTTP_PROXY_PASSWORD("smp.proxy.password", "", "Base64 encrypted password for Proxy.", false, true,SMPPropertyTypeEnum.STRING), HTTP_PROXY_PORT("smp.proxy.port", "80", "The http proxy port", false, false, SMPPropertyTypeEnum.INTEGER), HTTP_PROXY_USER("smp.proxy.user", "", "The proxy user", false, false, SMPPropertyTypeEnum.STRING), - KEYSTORE_PASSWORD("smp.keystore.password","","Encrypted keystore (and keys) password ", false, true, SMPPropertyTypeEnum.STRING), KEYSTORE_FILENAME("smp.keystore.filename","smp-keystore.jks","Keystore filename ", true, false , SMPPropertyTypeEnum.FILENAME), TRUSTSTORE_PASSWORD("smp.truststore.password","","Encrypted truststore password ", false, true, SMPPropertyTypeEnum.STRING), @@ -56,7 +53,12 @@ public enum SMPPropertyEnum { SML_PROXY_PORT("bdmsl.integration.proxy.port","","Deprecated", false, false , SMPPropertyTypeEnum.INTEGER), SML_PROXY_USER("bdmsl.integration.proxy.user","","Deprecated", false, false , SMPPropertyTypeEnum.STRING), SML_PROXY_PASSWORD("bdmsl.integration.proxy.password","","Deprecated", false, false , SMPPropertyTypeEnum.STRING), - SMP_PROPERTY_REFRESH_CRON("smp.property.refresh.cronJobExpression","0 48 */1 * * *","Property refresh cron expression (def 12 minutes to each hour). Property change is refreshed at restart!", false, false , SMPPropertyTypeEnum.STRING); + SMP_PROPERTY_REFRESH_CRON("smp.property.refresh.cronJobExpression","0 48 */1 * * *","Property refresh cron expression (def 12 minutes to each hour). Property change is refreshed at restart!", false, false , SMPPropertyTypeEnum.STRING), + + UI_COOKIE_SESSION_SECURE("smp.ui.session.secure","false","Cookie is only sent to the server when a request is made with the https: scheme (except on localhost), and therefore is more resistent to man-in-the-middle attacks.", false, false , SMPPropertyTypeEnum.BOOLEAN), + UI_COOKIE_SESSION_MAX_AGE("smp.ui.session.max-age","","Number of seconds until the cookie expires. A zero or negative number will expire the cookie immediately. Empty value will not set parameter", false, false , SMPPropertyTypeEnum.INTEGER), + UI_COOKIE_SESSION_SITE("smp.ui.session.strict","None","Controls whether a cookie is sent with cross-origin requests, providing some protection against cross-site request forgery attacks. Possible values are: Strict, None, Lax", false, false , SMPPropertyTypeEnum.STRING), + UI_COOKIE_SESSION_PATH("smp.ui.session.path","","A path that must exist in the requested URL, or the browser won't send the Cookie header. Null/Empty value sets the authentication requests context by default. The forward slash (/) character is interpreted as a directory separator, and subdirectories will be matched as well: for Path=/docs, /docs, /docs/Web/, and /docs/Web/HTTP will all match", false, false , SMPPropertyTypeEnum.STRING); String property; diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java index 970c4f31cb2e7436a76653eff4a727f5541c5f80..bad6337e0afad02d534177f117bc61af0463b4fa 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java @@ -30,7 +30,6 @@ public class ConfigurationService { @Autowired private ConfigurationDao configurationDAO; - public DBConfiguration setPropertyToDatabase(SMPPropertyEnum key, String value, String description) { String finalValue = StringUtils.trimToNull(value); if (finalValue == null) { @@ -57,15 +56,15 @@ public class ConfigurationService { return res; } - public Pattern getParticipantIdentifierSchemeRexExp(){ - return (Pattern)configurationDAO.getCachedPropertyValue(PARTC_SCH_REGEXP); + public Pattern getParticipantIdentifierSchemeRexExp() { + return (Pattern) configurationDAO.getCachedPropertyValue(PARTC_SCH_REGEXP); } - public String getParticipantIdentifierSchemeRexExpPattern(){ + public String getParticipantIdentifierSchemeRexExpPattern() { return configurationDAO.getCachedProperty(PARTC_SCH_REGEXP); } - public String getParticipantIdentifierSchemeRexExpMessage(){ + public String getParticipantIdentifierSchemeRexExpMessage() { return configurationDAO.getCachedProperty(PARTC_SCH_REGEXP_MSG); } @@ -94,13 +93,12 @@ public class ConfigurationService { return (String) configurationDAO.getCachedPropertyValue(HTTP_PROXY_PASSWORD); } - public List<String> getCaseSensitiveDocumentScheme() { - return (List<String>)configurationDAO.getCachedPropertyValue(CS_DOCUMENTS); + return (List<String>) configurationDAO.getCachedPropertyValue(CS_DOCUMENTS); } public List<String> getCaseSensitiveParticipantScheme() { - return (List<String>)configurationDAO.getCachedPropertyValue(CS_PARTICIPANTS); + return (List<String>) configurationDAO.getCachedPropertyValue(CS_PARTICIPANTS); } public boolean isProxyEnabled() { @@ -132,27 +130,26 @@ public class ConfigurationService { return configurationDAO.getCachedProperty(SML_PHYSICAL_ADDRESS); } - public boolean forceCRLValidation() { Boolean value = (Boolean) configurationDAO.getCachedPropertyValue(CERTIFICATE_CRL_FORCE); // by default is not froce return value != null && value; } + public String getSMLIntegrationServerCertSubjectRegExp() { return configurationDAO.getCachedProperty(SML_TLS_SERVER_CERT_SUBJECT_REGEXP); } + public boolean smlDisableCNCheck() { Boolean value = (Boolean) configurationDAO.getCachedPropertyValue(SML_TLS_DISABLE_CN_CHECK); // by default is not froce return value != null && value; } - public File getConfigurationFolder() { return (File) configurationDAO.getCachedPropertyValue(CONFIGURATION_DIR); } - public File getTruststoreFile() { return (File) configurationDAO.getCachedPropertyValue(TRUSTSTORE_FILENAME); } @@ -169,5 +166,21 @@ public class ConfigurationService { return (String) configurationDAO.getCachedPropertyValue(KEYSTORE_PASSWORD); } + public boolean getSessionCookieSecure() { + Boolean value = (Boolean) configurationDAO.getCachedPropertyValue(UI_COOKIE_SESSION_SECURE); + return value != null && value; + } + + public Integer getSessionCookieMaxAge() { + return (Integer) configurationDAO.getCachedPropertyValue(UI_COOKIE_SESSION_MAX_AGE); + } + + public String getSessionCookieSameSite() { + return (String) configurationDAO.getCachedPropertyValue(UI_COOKIE_SESSION_SITE); + } + + public String getSessionCookiePath() { + return (String) configurationDAO.getCachedPropertyValue(UI_COOKIE_SESSION_PATH); + } } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..33b596c77c13814fdc977236f182fd9a475d27d1 --- /dev/null +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriter.java @@ -0,0 +1,108 @@ +package eu.europa.ec.edelivery.smp.utils; + +import eu.europa.ec.edelivery.smp.logging.SMPLogger; +import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpHeaders; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + + +/** + * Purpose of class is to serialize SMP cookies with the security flags + * + * @author Joze Rihtarsic + * @since 4.2 + */ +public class SMPCookieWriter { + private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SMPCookieWriter.class); + + public static final String CSRF_COOKIE_NAME = "XSRF-TOKEN"; + public static final String SESSION_COOKIE_NAME = "JSESSIONID"; + + private static final String COOKIE_PARAM_DELIMITER = "; "; + private static final String COOKIE_PARAM_SECURE = "secure"; + private static final String COOKIE_PARAM_MAX_AGE = "Max-Age"; + private static final String COOKIE_PARAM_EXPIRES = "Expires"; + + private static final String COOKIE_PARAM_PATH = "Path"; + private static final String COOKIE_PARAM_HTTP_ONLY = "HttpOnly"; + private static final String COOKIE_PARAM_SAME_SITE = "SameSite"; + + /** + * set cookie parameters https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie + */ + public void writeCookieToResponse(String cookieName, String cookieValue, boolean isSecure, Integer maxAge, String path, String sameSite, HttpServletRequest request, HttpServletResponse response) { + String cookieHeader = generateSetCookieHeader(cookieName, cookieValue, isSecure, maxAge, path, sameSite, request); + LOG.info("Set cookie [{}]",cookieHeader); + response.setHeader(HttpHeaders.SET_COOKIE, cookieHeader); + } + + /** + * Method generates set cookie header + * + * @param cookieName + * @param cookieValue + * @param isSecure + * @param maxAge + * @param path + * @param sameSite + * @param request + * @return + */ + public String generateSetCookieHeader(String cookieName, String cookieValue, boolean isSecure, Integer maxAge, String path, String sameSite, HttpServletRequest request) { + + + StringBuilder sb = new StringBuilder(); + sb.append(cookieName) + .append('=') + .append(cookieValue); + // set secure\ + if (isSecure) { + sb.append(COOKIE_PARAM_DELIMITER) + .append(COOKIE_PARAM_SECURE); + } + + sb.append(COOKIE_PARAM_DELIMITER) + .append(COOKIE_PARAM_HTTP_ONLY); + + if (maxAge != null && maxAge > -1) { + sb.append(COOKIE_PARAM_DELIMITER) + .append(COOKIE_PARAM_MAX_AGE) + .append('=') + .append(maxAge.intValue()); + + ZonedDateTime expires = (maxAge != 0) ? ZonedDateTime.now().plusSeconds(maxAge) + : Instant.EPOCH.atZone(ZoneOffset.UTC); + sb.append(COOKIE_PARAM_DELIMITER).append(COOKIE_PARAM_EXPIRES) + .append('=').append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME)); + } + + + if (StringUtils.isBlank(path)) { + path = request.getContextPath(); + path = StringUtils.isNotBlank(path) + ? path : "/"; + } + if (StringUtils.isNotBlank(path)) { + sb.append(COOKIE_PARAM_DELIMITER) + .append(COOKIE_PARAM_PATH) + .append('=') + .append(path); + } + if (StringUtils.isNotBlank(sameSite)) { + sb.append(COOKIE_PARAM_DELIMITER) + .append(COOKIE_PARAM_SAME_SITE) + .append('=') + .append(sameSite); + } + + LOG.debug("generated set cookie header [{}]", sb.toString()); + return sb.toString(); + } +} diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java index 576857da9c52dcc78a12b5e804fb4d20a5ffa742..ae2fffc2507b8b673b552ed681bd69be9e3a0eaf 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java @@ -50,8 +50,7 @@ import static eu.europa.ec.edelivery.smp.conversion.ServiceMetadataConverter.unm import static eu.europa.ec.edelivery.smp.testutil.TestConstants.*; import static eu.europa.ec.edelivery.smp.testutil.XmlTestUtils.loadDocumentAsByteArray; import static eu.europa.ec.edelivery.smp.testutil.XmlTestUtils.marshallToByteArray; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * Created by gutowpa on 15/11/2017. @@ -114,8 +113,6 @@ public class ServiceMetadataIntegrationTest extends AbstractServiceIntegrationTe @Test public void saveAndReadPositiveScenario() throws IOException, TransformerException, JAXBException { - - //given byte[] inServiceMetadataXml = loadDocumentAsByteArray(SERVICE_METADATA_XML_PATH); byte[] expectedSignedServiceMetadataXml = loadDocumentAsByteArray(SIGNED_SERVICE_METADATA_XML_PATH); @@ -131,7 +128,7 @@ public class ServiceMetadataIntegrationTest extends AbstractServiceIntegrationTe assertEquals(1, docIdsAfter.size()); assertEquals(DOC_ID.getValue().toLowerCase(), docIdsAfter.get(0).getValue()); // normalized assertEquals(DOC_ID.getScheme().toLowerCase(), docIdsAfter.get(0).getScheme()); // normalized - assertTrue(Arrays.equals(expectedSignedServiceMetadataXml, ServiceMetadataConverter.toByteArray(outServiceMetadataDoc) )); + assertArrayEquals(expectedSignedServiceMetadataXml, ServiceMetadataConverter.toByteArray(outServiceMetadataDoc)); } @Test diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriterGenerateHeaderTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriterGenerateHeaderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f65e3e6378fb478c2081199baee4224d8888f5da --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriterGenerateHeaderTest.java @@ -0,0 +1,83 @@ +package eu.europa.ec.edelivery.smp.utils; + +import org.apache.commons.lang3.StringUtils; +import org.hamcrest.Matchers; +import org.hamcrest.core.IsNot; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpSession; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.Collection; +import java.util.UUID; + +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; +import static org.hamcrest.Matchers.startsWith; +import static org.mockito.Mockito.doReturn; + +@RunWith(Parameterized.class) +public class SMPCookieWriterGenerateHeaderTest { + + // parameters + String description; + boolean isSecure; + Integer maxAge; + String path; + String sameSite; + String expectedResultContains; + String expectedResultNotContains; + + @Parameterized.Parameters(name = "{index}: {0}") + public static Collection cookieWriterTestParameters() { + return Arrays.asList(new Object[][]{ + {"Contains HttpOnly", false, 36000, "/path", "Strict", "; HttpOnly", null}, + {"Test with secure off", false, 36000, "/path", "Strict", null, "; secure"}, + {"Test with secure on", true, 36000, "/path", "Strict", "; secure", null}, + {"MaxAge given", true, 123456, "/path", "Strict", "; Max-Age=123456; Expires=", null}, + {"MaxAge not given", true, null, "/path", "Strict", null, "; Max-Age="}, + {"SameSite: off", false, 36000, "/path", null, null, "; SameSite="}, + {"SameSite: Strict", true, 36000, "/path", "Strict", "; SameSite=Strict", null}, + {"SameSite: Lax", true, 36000, "/path", "Lax", "; SameSite=Lax", null}, + {"SameSite: None", true, 36000, "/path", "None", "; SameSite=None", null}, + {"Path: Null - set request context by default", true, 36000, null, "None", "; Path=/request-context;", null}, + {"Path: user-defined-path", true, 36000, "/user-defined-path", "None", "; Path=/user-defined-path", null}, + }); + } + + public SMPCookieWriterGenerateHeaderTest(String description, boolean isSecure, Integer maxAge, String path, String sameSite,String expectedResultContains, String expectedResultNotContains) { + this.description = description; + this.isSecure = isSecure; + this.maxAge = maxAge; + this.path = path; + this.sameSite = sameSite; + this.expectedResultContains = expectedResultContains; + this.expectedResultNotContains = expectedResultNotContains; + } + + // test instance + SMPCookieWriter testInstance = new SMPCookieWriter(); + + @Test + public void generateSetCookieHeader() { + // given + String sessionID = UUID.randomUUID().toString(); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + doReturn("/request-context").when(request).getContextPath(); + + // when + String result = testInstance.generateSetCookieHeader(MockHttpSession.SESSION_COOKIE_NAME, sessionID, isSecure, maxAge, path, sameSite, request); + + // then + assertThat(result, startsWith(MockHttpSession.SESSION_COOKIE_NAME+"="+sessionID)); + if (StringUtils.isNotEmpty(expectedResultContains)) { + assertThat(result, containsString(expectedResultContains)); + } + if (StringUtils.isNotEmpty(expectedResultNotContains)) { + assertThat(result, IsNot.not(containsString(expectedResultNotContains))); + } + } +} \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriterTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e8806ea30a0536331b35212710ca103e15ccc636 --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SMPCookieWriterTest.java @@ -0,0 +1,45 @@ +package eu.europa.ec.edelivery.smp.utils; + +import org.apache.commons.lang3.StringUtils; +import org.hamcrest.core.IsNot; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mockito; +import org.springframework.http.HttpHeaders; +import org.springframework.mock.web.MockHttpSession; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.Collection; + +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + + +public class SMPCookieWriterTest { + SMPCookieWriter testInstance = spy(new SMPCookieWriter()); + + @Test + public void generateSetCookieHeaderForName() { + // given + String generatedHeader = "JSESSION=this-is-test-example; HttpOnly; Max-Age=36000; Expires=Thu, 16 Sep 2021 19:41:30 +0200; Path=/path; SameSite=Strict"; + String sessionValue="SessionValue"; + boolean isSecure=true; + Integer maxAge =null; + String path =null; + String sameSite="Lax"; + HttpServletResponse response = Mockito.mock(HttpServletResponse.class); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + doReturn("/request-context").when(request).getContextPath(); + doReturn(generatedHeader).when(testInstance).generateSetCookieHeader(SMPCookieWriter.SESSION_COOKIE_NAME,sessionValue, isSecure, maxAge, path, sameSite, request); + + // when + testInstance.writeCookieToResponse(SMPCookieWriter.SESSION_COOKIE_NAME, sessionValue, isSecure, maxAge, path, sameSite, request, response); + // then + verify(response).setHeader( eq(HttpHeaders.SET_COOKIE), eq(generatedHeader)); + } +} \ No newline at end of file diff --git a/smp-webapp/pom.xml b/smp-webapp/pom.xml index 377f0e545d80290cb83ec2c6b29f4c3fbb3facae..a2681a7d81a62f89c58375d81bbd3ce8f7ecad6b 100644 --- a/smp-webapp/pom.xml +++ b/smp-webapp/pom.xml @@ -15,7 +15,7 @@ <properties> <maven.deploy.skip>false</maven.deploy.skip> <buildtimestamp>${maven.build.timestamp}</buildtimestamp> - <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format> + <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss'Z'</maven.build.timestamp.format> <ftp.host>wltdgt02.cc.cec.eu.int</ftp.host> <ftp.port>2059</ftp.port> diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java index db303baa7c5659aa11c432882c5ab5456cb50d9b..6ee66b53a77dd6189d2fe18abff50065b247e2ae 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java @@ -20,6 +20,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.crypto.bcrypt.BCrypt; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; +import org.springframework.stereotype.Component; import java.security.cert.CertificateRevokedException; import java.text.DateFormat; @@ -33,6 +34,7 @@ import static java.util.Locale.US; @Import({SmpAppConfig.class}) +@Component public class SMPAuthenticationProvider implements AuthenticationProvider { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(AuthenticationProvider.class); diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPTaskSchedulerConfig.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPTaskSchedulerConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..d3dbe497a8e72519279fc39efde1fe60173279b0 --- /dev/null +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPTaskSchedulerConfig.java @@ -0,0 +1,28 @@ +package eu.europa.ec.edelivery.smp.config; + + +import eu.europa.ec.edelivery.smp.data.dao.ConfigurationDao; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +@EnableScheduling +@ComponentScan( + basePackages = "eu.europa.ec.edelivery.smp") +public class SMPTaskSchedulerConfig { + + final ConfigurationDao configurationDao; + + @Autowired + public SMPTaskSchedulerConfig(ConfigurationDao configurationDao) { + this.configurationDao = configurationDao; + } + + @Scheduled(cron = "${smp.property.refresh.cronJobExpression:0 48 */1 * * *}") + public void refreshProperties() { + configurationDao.refreshProperties(); + } +} diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java index f9d35066613d5c183fb418a696d5ef432404f1e8..f6e6887ff469ac5e45f11ddbc716b1b12afd5c17 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java @@ -14,6 +14,8 @@ package eu.europa.ec.edelivery.smp.config; import eu.europa.ec.edelivery.smp.error.ErrorMappingControllerAdvice; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -38,6 +40,7 @@ import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; "eu.europa.ec.edelivery.smp.ui"}) @Import({GlobalMethodSecurityConfig.class, ErrorMappingControllerAdvice.class}) public class SmpWebAppConfig implements WebMvcConfigurer { + private static final Logger LOG = LoggerFactory.getLogger(SmpWebAppConfig.class); @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java index 8a964e03cecb86fde3bb53e16d7521a82e9940fb..627db4d95d4b7b4b2c732e72c1e5bc3f6947d4af 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java @@ -15,23 +15,148 @@ package eu.europa.ec.edelivery.smp.config; import eu.europa.ec.edelivery.security.BlueCoatAuthenticationFilter; import eu.europa.ec.edelivery.security.EDeliveryX509AuthenticationFilter; +import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationProvider; +import eu.europa.ec.edelivery.smp.auth.SMPAuthority; +import eu.europa.ec.edelivery.smp.error.SpringSecurityExceptionHandler; +import eu.europa.ec.edelivery.smp.utils.SMPCookieWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.ImportResource; +import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.BeanIds; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.firewall.DefaultHttpFirewall; +import org.springframework.security.web.firewall.HttpFirewall; /** * Created by gutowpa on 12/07/2017. */ @EnableWebSecurity -@ImportResource("classpath:spring-security.xml") +@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) +//@ImportResource("classpath:spring-security.xml") @ComponentScan("eu.europa.ec.edelivery.smp.auth") -public class SpringSecurityConfig { +public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { + private static final Logger LOG = LoggerFactory.getLogger(SpringSecurityConfig.class); + SMPAuthenticationProvider smpAuthenticationProvider; + BlueCoatAuthenticationFilter blueCoatAuthenticationFilter; + EDeliveryX509AuthenticationFilter x509AuthenticationFilter; + @Value("${authentication.blueCoat.enabled:false}") + boolean clientCertEnabled; + @Value("${encodedSlashesAllowedInUrl:true}") + boolean encodedSlashesAllowedInUrl; + + /** + * Initialize beans. Use lazy initialization for filter to avoid circular dependencies + * + * @param smpAuthenticationProvider + * @param blueCoatAuthenticationFilter + * @param x509AuthenticationFilter + */ + @Autowired + public SpringSecurityConfig(SMPAuthenticationProvider smpAuthenticationProvider, + @Lazy BlueCoatAuthenticationFilter blueCoatAuthenticationFilter, + @Lazy EDeliveryX509AuthenticationFilter x509AuthenticationFilter) { + super(false); + this.smpAuthenticationProvider = smpAuthenticationProvider; + this.blueCoatAuthenticationFilter = blueCoatAuthenticationFilter; + this.x509AuthenticationFilter = x509AuthenticationFilter; + } + + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + + // prepare filters + blueCoatAuthenticationFilter.setBlueCoatEnabled(clientCertEnabled); + + httpSecurity.csrf().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS).and() + .exceptionHandling().authenticationEntryPoint(new SpringSecurityExceptionHandler()).and() + .headers().frameOptions().deny().contentTypeOptions().and().xssProtection().xssProtectionEnabled(true).and().and() + + .addFilter(blueCoatAuthenticationFilter) + .addFilter(x509AuthenticationFilter) + .httpBasic() + .and() // username + .anonymous().authorities(SMPAuthority.S_AUTHORITY_ANONYMOUS.getAuthority()).and() + .authorizeRequests().antMatchers(HttpMethod.DELETE, "/ui/rest/security/authentication").permitAll() + .antMatchers(HttpMethod.POST, "/ui/rest/security/authentication").permitAll() + .and() + .authorizeRequests() + .antMatchers(HttpMethod.DELETE).hasAnyAuthority( + SMPAuthority.S_AUTHORITY_SMP_ADMIN.getAuthority(), + SMPAuthority.S_AUTHORITY_SERVICE_GROUP.getAuthority(), + SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN.getAuthority()) + .antMatchers(HttpMethod.PUT).hasAnyAuthority( + SMPAuthority.S_AUTHORITY_SMP_ADMIN.getAuthority(), + SMPAuthority.S_AUTHORITY_SERVICE_GROUP.getAuthority(), + SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN.getAuthority()) + .antMatchers(HttpMethod.GET).permitAll().and() + .authorizeRequests().antMatchers(HttpMethod.GET, "/ui/").hasAnyAuthority( + SMPAuthority.S_AUTHORITY_SMP_ADMIN.getAuthority(), + SMPAuthority.S_AUTHORITY_SERVICE_GROUP.getAuthority(), + SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN.getAuthority()).and() + ; + + + } + + @Override + public void configure(WebSecurity web) throws Exception { + super.configure(web); + web.httpFirewall(smpHttpFirewall()); + } + + + @Bean + public HttpFirewall smpHttpFirewall() { + DefaultHttpFirewall firewall = new DefaultHttpFirewall(); + firewall.setAllowUrlEncodedSlash(encodedSlashesAllowedInUrl); + return firewall; + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) { + LOG.info("configureAuthenticationManagerBuilder, set SMP provider "); + auth.authenticationProvider(smpAuthenticationProvider); + } + + @Override + @Bean(name = {BeanIds.AUTHENTICATION_MANAGER, "smpAuthenticationManager"}) + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public BlueCoatAuthenticationFilter getClientCertAuthenticationFilter(@Qualifier("smpAuthenticationManager") AuthenticationManager authenticationManager) { + BlueCoatAuthenticationFilter blueCoatAuthenticationFilter = new BlueCoatAuthenticationFilter(); + blueCoatAuthenticationFilter.setAuthenticationManager(authenticationManager); + return blueCoatAuthenticationFilter; + } + + @Bean + public EDeliveryX509AuthenticationFilter getEDeliveryX509AuthenticationFilter(@Qualifier("smpAuthenticationManager") AuthenticationManager authenticationManager) { + EDeliveryX509AuthenticationFilter x509AuthenticationFilter = new EDeliveryX509AuthenticationFilter(); + x509AuthenticationFilter.setAuthenticationManager(authenticationManager); + return x509AuthenticationFilter; + } + + @Bean + public SMPCookieWriter getSMPCookieWriter() { + return new SMPCookieWriter(); + } } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SpringSecurityExceptionHandler.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SpringSecurityExceptionHandler.java index 7d8418e8c0acfb5220e87b22028bb3e2cadd2fb3..fb3fb8c41500f44b62f671696c79f7f2bf524356 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SpringSecurityExceptionHandler.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SpringSecurityExceptionHandler.java @@ -24,7 +24,6 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.JAXBContext; @@ -51,20 +50,20 @@ public class SpringSecurityExceptionHandler extends BasicAuthenticationEntryPoin @Override public void commence(HttpServletRequest request, HttpServletResponse response, - AuthenticationException authException) throws IOException, ServletException { + AuthenticationException authException) throws IOException { String errorMsg = authException.getMessage(); - if(authException instanceof BadCredentialsException){ + if (authException instanceof BadCredentialsException) { errorMsg += " - Provided username/password or client certificate are invalid"; } handle(response, authException, errorMsg); } @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { handle(response, accessDeniedException, accessDeniedException.getMessage()); } - private void handle(HttpServletResponse response, RuntimeException exception, String errorMsg) throws IOException, ServletException { + private void handle(HttpServletResponse response, RuntimeException exception, String errorMsg) throws IOException { ResponseEntity respEntity = buildAndWarn(exception, errorMsg); String errorBody = marshall((ErrorResponse) respEntity.getBody()); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java index 2ae1ded9b8f3c5de61e71199635b8a0f58412433..24da759ac5dfddb5c53b7c7748fefd5e5c2158ae 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java @@ -10,6 +10,8 @@ import eu.europa.ec.edelivery.smp.data.ui.LoginRO; import eu.europa.ec.edelivery.smp.data.ui.UserRO; import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; +import eu.europa.ec.edelivery.smp.services.ConfigurationService; +import eu.europa.ec.edelivery.smp.utils.SMPCookieWriter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.ConversionService; import org.springframework.http.HttpStatus; @@ -26,6 +28,10 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import static eu.europa.ec.edelivery.smp.auth.SMPAuthority.*; +import static eu.europa.ec.edelivery.smp.utils.SMPCookieWriter.CSRF_COOKIE_NAME; +import static eu.europa.ec.edelivery.smp.utils.SMPCookieWriter.SESSION_COOKIE_NAME; + /** * @author Sebastian-Ion TINCU * @since 4.0 @@ -36,15 +42,25 @@ public class AuthenticationResource { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(AuthenticationResource.class); - @Autowired protected SMPAuthenticationService authenticationService; - @Autowired protected SMPAuthorizationService authorizationService; - @Autowired private ConversionService conversionService; + private ConfigurationService configurationService; + + SMPCookieWriter smpCookieWriter; + + @Autowired + public AuthenticationResource(SMPAuthenticationService authenticationService, SMPAuthorizationService authorizationService, ConversionService conversionService, ConfigurationService configurationService, SMPCookieWriter smpCookieWriter) { + this.authenticationService = authenticationService; + this.authorizationService = authorizationService; + this.conversionService = conversionService; + this.configurationService = configurationService; + this.smpCookieWriter = smpCookieWriter; + } + @ResponseStatus(value = HttpStatus.FORBIDDEN) @ExceptionHandler({AuthenticationException.class}) public ErrorRO handleException(Exception ex) { @@ -54,8 +70,12 @@ public class AuthenticationResource { @RequestMapping(value = "authentication", method = RequestMethod.POST) @Transactional(noRollbackFor = BadCredentialsException.class) - public UserRO authenticate(@RequestBody LoginRO loginRO, HttpServletResponse response) { + public UserRO authenticate(@RequestBody LoginRO loginRO, HttpServletRequest request, HttpServletResponse response) { LOG.debug("Authenticating user [{}]", loginRO.getUsername()); + // reset session id with login + + recreatedSessionCookie(request, response); + SMPAuthenticationToken authentication = (SMPAuthenticationToken) authenticationService.authenticate(loginRO.getUsername(), loginRO.getPassword()); UserRO userRO = conversionService.convert(authentication.getUser(), UserRO.class); return authorizationService.sanitize(userRO); @@ -70,14 +90,14 @@ public class AuthenticationResource { } LOG.info("Logging out user [{}]", auth.getName()); - new CookieClearingLogoutHandler("JSESSIONID", "XSRF-TOKEN").logout(request, response, null); + new CookieClearingLogoutHandler(SESSION_COOKIE_NAME, CSRF_COOKIE_NAME).logout(request, response, null); LOG.info("Cleared cookies"); new SecurityContextLogoutHandler().logout(request, response, auth); LOG.info("Logged out"); } @RequestMapping(value = "user", method = RequestMethod.GET) - @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SMP_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SERVICE_GROUP_ADMIN}) + @Secured({S_AUTHORITY_TOKEN_SYSTEM_ADMIN, S_AUTHORITY_TOKEN_SMP_ADMIN, S_AUTHORITY_TOKEN_SERVICE_GROUP_ADMIN}) public UserRO getUser() { UserRO user = new UserRO(); @@ -88,4 +108,21 @@ public class AuthenticationResource { return user; } + /** + * set cookie parameters https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie + * + * @param request + * @param response + */ + public void recreatedSessionCookie(HttpServletRequest request, HttpServletResponse response) { + String sessionId = request.changeSessionId(); + smpCookieWriter.writeCookieToResponse(SESSION_COOKIE_NAME, + sessionId, + configurationService.getSessionCookieSecure(), configurationService.getSessionCookieMaxAge(), + configurationService.getSessionCookiePath(), + configurationService.getSessionCookieSameSite(), + request, response + ); + } + } \ No newline at end of file diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationClientCertTest.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationClientCertTest.java index 9bc1d1ce5bdfdebf479ff333b4e6685c17938ee3..ce84508031a572bdf6f46ff2542f3360ba1bf462 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationClientCertTest.java +++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationClientCertTest.java @@ -52,7 +52,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. SmpWebAppConfig.class, DatabaseConfig.class, SpringSecurityConfig.class, - SpringSecurityTestConfig.class, + SpringSecurityTestConfig.class }) @WebAppConfiguration @Sql(scripts = {"classpath:/cleanup-database.sql", @@ -123,7 +123,6 @@ public class SecurityConfigurationClientCertTest { }, - { "Issue test one", "CN=ncp.fi.ehealth.testa.eu,O=Kansanelakelaitos,C=FI:f71ee8b11cb3b787", @@ -177,7 +176,7 @@ public class SecurityConfigurationClientCertTest { @Test public void validBlueCoatHeaderAuthorizedForPutTest() throws Exception { - System.out.println("Test: "+ testName); + System.out.println("Test: " + testName); String clientCert = buildClientCert(serialNumber, certificateDn); System.out.println("Client-Cert: " + clientCert); diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java index df9a1b9af2009eba88b426ea31d79063222cdfc4..27877ddfde1c070f53e9249a78aabd1016c1a8d6 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java +++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java @@ -63,14 +63,11 @@ public class SecurityConfigurationTest { public static final String BLUE_COAT_VALID_HEADER_DB_UPPER_SN = "sno=BB66&subject=CN=common name UPPER database SN,O=org,C=BE&validfrom=Dec 6 17:41:42 2016 GMT&validto=Jul 9 23:59:00 2050 GMT&issuer=C=x,O=y,CN=z"; public static final String TEST_USERNAME_BLUE_COAT__DB_UPPER_SN = "CN=common name UPPER database SN,O=org,C=BE:000000000000bb66"; + public static final String BLUE_COAT_NOT_AUTHORIZED_HEADER = "sno=bb61&subject=C=BE,O=org,CN=common name not exists&validfrom=Dec 6 17:41:42 2016 GMT&validto=Jul 9 23:59:00 2050 GMT&issuer=C=x,O=y,CN=z"; + @Autowired private WebApplicationContext context; - /* - @PersistenceContext - private EntityManager em; - */ - MockMvc mvc; @Before @@ -151,6 +148,15 @@ public class SecurityConfigurationTest { .andExpect(content().string(TEST_USERNAME_BLUE_COAT)) .andReturn().getResponse().getContentAsString(); } + @Test + public void blueCoatHeaderNotAuthorizedForPutTest() throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.add("Client-Cert", BLUE_COAT_NOT_AUTHORIZED_HEADER); + + mvc.perform(MockMvcRequestBuilders.put(RETURN_LOGGED_USER_PATH) + .headers(headers)) + .andExpect(status().isUnauthorized()); + } @Test public void validBlueCoatHeaderAuthorizedBeforeValidBasicAuthTest() throws Exception { diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java index 7523b93aaa601b6f83131e513d202f9615cbf8ef..5400c747fabc914d4f975c61449ed2121988a710 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java +++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java @@ -125,7 +125,7 @@ public class SignatureValidatorTest { } @Test - public void validateLinarizedSignature() throws Throwable { + public void validateLinearizedSignature() throws Throwable { String serviceGroupId = "ehealth-actorid-qns::urn:brazil:ncpb"; Principal principal = new PreAuthenticatedCertificatePrincipal("C=BE, O=European Commission,OU=CEF_eDelivery.europa.eu,OU=eHealth,OU=SMP_TEST,CN=EHEALTH_SMP_EC", "C=DE, O=T-Systems International GmbH, OU=T-Systems Trust Center, ST=Nordrhein Westfalen/postalCode=57250, L=Netphen/street=Untere Industriestr. 20, CN=Shared Business CA 4", "f7:1e:e8:b1:1c:b3:b7:87"); String filePathToLoad = "/input/ServiceMetadata_linarized.xml"; @@ -181,8 +181,8 @@ public class SignatureValidatorTest { //Default signature validation Element smpSigPointer = SignatureUtil.findSignatureByParentNode(response.getDocumentElement()); SignatureUtil.validateSignature(smpSigPointer); - Assert.assertEquals(signedByCustomizedSignature, SignatureUtil.loadDocumentAsString(signedByCustomizedSignatureFilePath)); - Assert.assertEquals(SignatureUtil.marshall(response), SignatureUtil.loadDocumentAsString(defaultSignatureFilePath)); + Assert.assertEquals(SignatureUtil.loadDocumentAsString(signedByCustomizedSignatureFilePath), signedByCustomizedSignature); + Assert.assertEquals(SignatureUtil.loadDocumentAsString(defaultSignatureFilePath), SignatureUtil.marshall(response) ); } public static Document parse(String serviceMetadataXml) throws SAXException, IOException, ParserConfigurationException { diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupControllerTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupControllerTest.java index eabf3ba081ec2e5f06ca08cdd7967663278984d3..3585e368a18de25458e6e87748813c273c9093d6 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupControllerTest.java +++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupControllerTest.java @@ -203,7 +203,7 @@ public class ServiceGroupControllerTest { } @Test - public void getExistingServiceMetadatWithReverseNoProxyHost() throws Exception { + public void getExistingServiceMetadataWithReverseNoProxyHost() throws Exception { //given prepareForGet();